2 * This file is part of KMail.
3 * Copyright (c) 2009 Constantin Berzan <exit3219@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "akonadisender.h"
22 #include <KMessageBox>
26 #include <KConfigGroup>
28 #include "messagehelper.h"
29 #include "messagecomposersettings.h"
31 #include <kmime/kmime_message.h>
32 #include <boost/shared_ptr.hpp>
34 #include <progressmanager.h>
36 #include <mailtransport/dispatcherinterface.h>
37 #include <mailtransport/messagequeuejob.h>
38 #include <mailtransport/transport.h>
39 #include <mailtransport/transportmanager.h>
40 #include <messagecore/stringutil.h>
42 using namespace KMime
;
43 using namespace KMime::Types
;
45 using namespace MailTransport
;
48 static QStringList
addrSpecListToStringList( const AddrSpecList
&l
, bool allowEmpty
= false )
51 for ( AddrSpecList::const_iterator it
= l
.begin(), end
= l
.end() ; it
!= end
; ++it
) {
52 const QString s
= (*it
).asString();
53 if ( allowEmpty
|| !s
.isEmpty() )
54 result
.push_back( s
);
60 static void extractSenderToCCAndBcc( const KMime::Message::Ptr
&aMsg
, QString
&sender
, QStringList
&to
, QStringList
&cc
, QStringList
&bcc
)
62 sender
= aMsg
->sender()->asUnicodeString();
63 if( aMsg
->headerByType("X-KMail-Recipients") ) {
64 // extended BCC handling to prevent TOs and CCs from seeing
65 // BBC information by looking at source of an OpenPGP encrypted mail
66 to
= addrSpecListToStringList( MessageHelper::extractAddrSpecs( aMsg
, "X-KMail-Recipients" ) );
67 aMsg
->removeHeader( "X-KMail-Recipients" );
69 to
= addrSpecListToStringList( MessageHelper::extractAddrSpecs( aMsg
, "To" ) );
70 cc
= addrSpecListToStringList( MessageHelper::extractAddrSpecs( aMsg
, "Cc" ) );
71 bcc
= addrSpecListToStringList( MessageHelper::extractAddrSpecs( aMsg
, "Bcc" ) );
77 AkonadiSender::AkonadiSender()
82 bool AkonadiSender::doSend( const KMime::Message::Ptr
&aMsg
, short sendNow
)
85 sendNow
= MessageComposer::MessageComposerSettings::self()->sendImmediate(); // -1 == use default setting
88 sendOrQueueMessage( aMsg
, MessageSender::SendLater
);
90 sendOrQueueMessage( aMsg
, MessageSender::SendImmediate
);
95 bool AkonadiSender::doSendQueued( const QString
&customTransport
)
97 kDebug() << "Sending queued message with custom transport:" << customTransport
;
98 mCustomTransport
= customTransport
;
100 DispatcherInterface
*dispatcher
= new DispatcherInterface();
101 if( mCustomTransport
.isEmpty() ) {
102 dispatcher
->dispatchManually();
104 dispatcher
->dispatchManualTransport( TransportManager::self()->transportByName( mCustomTransport
)->id() );
110 void AkonadiSender::sendOrQueueMessage( const KMime::Message::Ptr
&message
, MessageSender::SendMethod method
)
113 kDebug() << "KMime::Message: \n[\n" << message
->encodedContent().left( 1000 ) << "\n]\n";
115 MessageQueueJob
*qjob
= new MessageQueueJob( this );
116 if ( message
->headerByType( "X-KMail-Fcc" ) ) {
117 qjob
->sentBehaviourAttribute().setSentBehaviour(
118 SentBehaviourAttribute::MoveToCollection
);
119 const int sentCollectionId
= message
->headerByType( "X-KMail-Fcc" )->asUnicodeString().toInt();
120 qjob
->sentBehaviourAttribute().setMoveToCollection(
121 Akonadi::Collection( sentCollectionId
) );
123 qjob
->sentBehaviourAttribute().setSentBehaviour(
124 MailTransport::SentBehaviourAttribute::MoveToDefaultSentCollection
);
126 qjob
->setMessage( message
);
129 QString transportName
= mCustomTransport
;
130 kDebug() << "Custom transportName:" << mCustomTransport
;
131 if( transportName
.isEmpty() ) {
132 transportName
= message
->headerByType( "X-KMail-Transport" ) ? message
->headerByType( "X-KMail-Transport" )->asUnicodeString() : QString();
133 kDebug() << "TransportName from headers:" << transportName
;
135 if( transportName
.isEmpty() ) {
136 transportName
= TransportManager::self()->defaultTransportName();
137 kDebug() << "Default transport" << TransportManager::self()->defaultTransportName();
139 Transport
*transport
= TransportManager::self()->transportByName( transportName
);
140 Q_ASSERT( transport
);
141 kDebug() << "Using transport (" << transportName
<< "," << transport
->id() << ")";
142 qjob
->transportAttribute().setTransportId( transport
->id() );
144 // if we want to manually queue it for sending later, then do it
145 if( method
== MessageSender::SendLater
)
146 qjob
->dispatchModeAttribute().setDispatchMode( MailTransport::DispatchModeAttribute::Manual
);
149 QStringList to
, cc
, bcc
;
151 extractSenderToCCAndBcc( message
, from
, to
, cc
, bcc
);
152 qjob
->addressAttribute().setFrom( from
);
153 qjob
->addressAttribute().setTo( to
);
154 qjob
->addressAttribute().setCc( cc
);
155 qjob
->addressAttribute().setBcc( bcc
);
157 MessageCore::StringUtil::removePrivateHeaderFields( message
);
159 // Queue the message.
160 connect( qjob
, SIGNAL(result(KJob
*)), this, SLOT(queueJobResult(KJob
*)) );
161 mPendingJobs
.insert( qjob
);
163 kDebug() << "QueueJob started.";
165 // TODO potential problem:
166 // The MDA finishes sending a message before I queue the next one, and
167 // thinking it is finished, the progress item deletes itself.
168 // Turn the MDA offline until everything is queued?
171 void AkonadiSender::queueJobResult( KJob
*job
)
173 Q_ASSERT( mPendingJobs
.contains( job
) );
174 mPendingJobs
.remove( job
);
177 kDebug() << "QueueJob failed with error" << job
->errorString();
179 kDebug() << "QueueJob success.";
183 #include "akonadisender.moc"