5 #define REALLY_WANT_KMSENDER
7 #include "kmsender_p.h"
8 #undef REALLY_WANT_KMSENDER
10 #include <kmime_header_parsing.h>
11 using namespace KMime::Types;
13 #include <tdeio/passdlg.h>
14 #include <tdeio/scheduler.h>
15 #include <tdeapplication.h>
16 #include <tdemessagebox.h>
17 #include <tdeversion.h>
18 #include <tdelocale.h>
20 #include <tdeconfig.h>
25 #include <sys/types.h>
28 #include "globalsettings.h"
29 #include "kmfiltermgr.h"
31 #include "kcursorsaver.h"
32 #include <libkpimidentities/identity.h>
33 #include <libkpimidentities/identitymanager.h>
34 #include "progressmanager.h"
35 #include "kmaccount.h"
36 #include "kmtransport.h"
37 #include "kmfolderindex.h"
38 #include "kmfoldermgr.h"
39 #include "kmmsgdict.h"
40 #include "kmmsgpart.h"
41 #include "protocols.h"
42 #include "kmcommands.h"
43 #include <mimelib/mediatyp.h>
44 #include <mimelib/enum.h>
45 #include <mimelib/param.h>
47 #define SENDER_GROUP "sending mail"
51 : mOutboxFolder( 0 ), mSentFolder( 0 )
55 mSendProcStarted =
false;
56 mSendInProgress =
false;
58 mTransportInfo =
new KMTransportInfo();
76 delete mTransportInfo;
80 void KMSender::setStatusMsg(
const TQString &msg)
83 mProgressItem->setStatus(msg);
87 void KMSender::readConfig(
void)
90 TDEConfigGroup config(KMKernel::config(), SENDER_GROUP);
92 mSendImmediate = config.readBoolEntry(
"Immediate",
true);
93 mSendQuotedPrintable = config.readBoolEntry(
"Quoted-Printable",
true);
98 void KMSender::writeConfig(
bool aWithSync)
100 TDEConfigGroup config(KMKernel::config(), SENDER_GROUP);
102 config.writeEntry(
"Immediate", mSendImmediate);
103 config.writeEntry(
"Quoted-Printable", mSendQuotedPrintable);
105 if (aWithSync) config.sync();
110 bool KMSender::settingsOk()
const
112 if (KMTransportInfo::availableTransports().isEmpty())
114 KMessageBox::information(0,i18n(
"Please create an account for sending and try again."));
120 static void handleRedirections(
KMMessage * m ) {
121 const TQString from = m->
headerField(
"X-KMail-Redirect-From");
122 const TQString msgId = m->
msgId();
123 if( from.isEmpty() || msgId.isEmpty() )
128 bool KMSender::doSend(
KMMessage* aMsg,
short sendNow)
133 if (!settingsOk())
return false;
135 if (aMsg->
to().isEmpty())
157 aMsg->setTo(
"Undisclosed.Recipients: ;");
160 handleRedirections( aMsg );
162 if (sendNow==-1) sendNow = mSendImmediate;
164 KMFolder *
const outbox = kmkernel->outboxFolder();
169 if (
const int err = outbox->
addMsg(aMsg) ) {
171 KMessageBox::information(0,i18n(
"Cannot add message to outbox folder"));
186 const int idx = outbox->
count() - 1;
192 if ( !sendNow || mSendInProgress )
200 void KMSender::outboxMsgAdded(
int idx)
203 KMMsgBase* msg = kmkernel->outboxFolder()->getMsgBase(idx);
206 mTotalBytes += msg->msgSize();
211 bool KMSender::doSendQueued(
const TQString &customTransport )
213 if (!settingsOk())
return false;
221 mOutboxFolder = kmkernel->outboxFolder();
222 mOutboxFolder->open(
"dosendoutbox");
223 mTotalMessages = mOutboxFolder->count();
224 if (mTotalMessages == 0) {
226 mOutboxFolder->close(
"dosendoutbox");
231 for(
int i = 0 ; i<mTotalMessages ; ++i )
232 mTotalBytes += mOutboxFolder->getMsgBase(i)->msgSize();
234 connect( mOutboxFolder, TQT_SIGNAL(msgAdded(
int)),
235 this, TQT_SLOT(outboxMsgAdded(
int)) );
238 mSentFolder = kmkernel->sentFolder();
239 mSentFolder->open(
"dosendsent");
240 kmkernel->filterMgr()->ref();
243 mCustomTransport = customTransport;
249 void KMSender::emitProgressInfo(
int currentFileProgress )
251 int percent = (mTotalBytes) ? ( 100 * (mSentBytes+currentFileProgress) / mTotalBytes ) : 0;
252 if (percent > 100) percent = 100;
253 mProgressItem->setProgress(percent);
256 static bool messageIsDispositionNotificationReport(
KMMessage *msg )
258 if ( msg->type() == DwMime::kTypeMessage &&
259 msg->subtype() == DwMime::kSubtypeDispositionNotification )
262 if ( msg->type() != DwMime::kTypeMultipart ||
263 msg->subtype() != DwMime::kSubtypeReport )
267 DwParameter *param = ct.FirstParameter();
269 if ( !tqstricmp( param->Attribute().c_str(),
"report-type")
270 && !tqstricmp( param->Value().c_str(),
"disposition-notification" ) )
273 param = param->Next();
279 void KMSender::doSendMsg()
284 const bool someSent = mCurrentMsg;
287 mSentBytes += mCurrentMsg->msgSize();
291 KMFolder *sentFolder = 0, *imapSentFolder = 0;
292 if (mCurrentMsg && kmkernel->filterMgr())
294 mCurrentMsg->setTransferInProgress(
false );
295 if( mCurrentMsg->hasUnencryptedMsg() ) {
296 kdDebug(5006) <<
"KMSender::doSendMsg() post-processing: replace mCurrentMsg body by unencryptedMsg data" << endl;
298 mCurrentMsg->deleteBodyParts();
300 KMMessage & newMsg( *mCurrentMsg->unencryptedMsg() );
302 mCurrentMsg->setContentTransferEncodingStr( newMsg.contentTransferEncodingStr() );
303 TQCString newDispo = newMsg.headerField(
"Content-Disposition").latin1();
304 if( newDispo.isEmpty() )
305 mCurrentMsg->removeHeaderField(
"Content-Disposition" );
307 mCurrentMsg->setHeaderField(
"Content-Disposition", newDispo );
309 mCurrentMsg->setBody( newMsg.body() );
311 KMMessagePart msgPart;
312 for(
int i = 0; i < newMsg.numBodyParts(); ++i ) {
313 newMsg.bodyPart( i, &msgPart );
314 mCurrentMsg->addBodyPart( &msgPart );
317 mCurrentMsg->setStatus(KMMsgStatusSent);
318 mCurrentMsg->setStatus(KMMsgStatusRead);
319 mCurrentMsg->updateAttachmentState();
320 mCurrentMsg->updateInvitationState();
322 const KPIM::Identity &
id = kmkernel->identityManager()
323 ->identityForUoidOrDefault( mCurrentMsg->headerField(
"X-KMail-Identity" ).stripWhiteSpace().toUInt() );
324 if ( !mCurrentMsg->fcc().isEmpty() )
326 sentFolder = kmkernel->folderMgr()->findIdString( mCurrentMsg->fcc() );
327 if ( sentFolder == 0 )
330 kmkernel->dimapFolderMgr()->findIdString( mCurrentMsg->fcc() );
331 if ( sentFolder == 0 )
333 kmkernel->imapFolderMgr()->findIdString( mCurrentMsg->fcc() );
337 if ( ( sentFolder == 0 || sentFolder->
isReadOnly() )
338 && ( imapSentFolder == 0 || imapSentFolder->isReadOnly() )
339 && !
id.fcc().isEmpty() )
341 sentFolder = kmkernel->folderMgr()->findIdString(
id.fcc() );
342 if ( sentFolder == 0 )
344 sentFolder = kmkernel->dimapFolderMgr()->findIdString(
id.fcc() );
345 if ( sentFolder == 0 )
346 imapSentFolder = kmkernel->imapFolderMgr()->findIdString(
id.fcc() );
349 && ( imapSentFolder->noContent() || imapSentFolder->isReadOnly() ) )
352 if ( sentFolder == 0 || sentFolder->
isReadOnly() )
353 sentFolder = kmkernel->sentFolder();
356 if (
const int err = sentFolder->
open(
"sentFolder") ) {
366 if ( mCurrentMsg->parent() ) mCurrentMsg->parent()->quiet(
true );
367 const int processResult = kmkernel->filterMgr()->process(mCurrentMsg,KMFilterMgr::Outbound);
368 if ( mCurrentMsg->parent() ) mCurrentMsg->parent()->quiet(
false );
371 switch (processResult) {
373 perror(
"Critical error: Unable to process sent mail (out of space?)");
374 KMessageBox::information(0, i18n(
"Critical error: "
375 "Unable to process sent mail (out of space?)"
376 "Moving failing message to \"sent-mail\" folder."));
378 sentFolder->
moveMsg(mCurrentMsg);
379 sentFolder->
close(
"sentFolder");
384 if ( sentFolder && sentFolder->
moveMsg(mCurrentMsg) != 0 )
386 KMessageBox::error(0, i18n(
"Moving the sent message \"%1\" from the "
387 "\"outbox\" to the \"sent-mail\" folder failed.\n"
388 "Possible reasons are lack of disk space or write permission. "
389 "Please try to fix the problem and move the message manually.")
390 .arg(mCurrentMsg->subject()));
394 if (imapSentFolder) {
396 KMCommand *command =
new KMMoveCommand( imapSentFolder, mCurrentMsg );
397 command->keepFolderOpen( sentFolder );
403 setStatusByLink( mCurrentMsg );
404 if (mCurrentMsg->parent() && !imapSentFolder) {
407 assert( mCurrentMsg->parent()->find( mCurrentMsg )
408 == mCurrentMsg->parent()->count() - 1 );
410 mCurrentMsg->parent()->unGetMsg( mCurrentMsg->parent()->count() -1 );
417 mCurrentMsg = mOutboxFolder->getMsg(mFailedMessages);
418 if ( mCurrentMsg && !mCurrentMsg->transferInProgress() &&
419 mCurrentMsg->sender().isEmpty() ) {
423 const KPIM::Identity &
id = kmkernel->identityManager()
424 ->identityForUoidOrDefault( mCurrentMsg->headerField(
"X-KMail-Identity" ).stripWhiteSpace().toUInt() );
425 if ( !
id.primaryEmailAddress().isEmpty() ) {
426 mCurrentMsg->setFrom(
id.fullEmailAddr() );
428 else if ( !kmkernel->identityManager()->defaultIdentity().primaryEmailAddress().isEmpty() ) {
429 mCurrentMsg->setFrom( kmkernel->identityManager()->defaultIdentity().fullEmailAddr() );
432 KMessageBox::sorry( 0, i18n(
"It's not possible to send messages "
433 "without specifying a sender address.\n"
434 "Please set the email address of "
435 "identity '%1' in the Identities "
436 "section of the configuration dialog "
437 "and then try again." )
438 .arg(
id.identityName() ) );
439 mOutboxFolder->unGetMsg( mFailedMessages );
443 if (!mCurrentMsg || mCurrentMsg->transferInProgress())
446 if (mCurrentMsg && mCurrentMsg->transferInProgress())
449 if ( sentFolder != 0 )
450 sentFolder->
close(
"sentFolder");
452 if ( mSentMessages == mTotalMessages ) {
453 setStatusMsg(i18n(
"%n queued message successfully sent.",
454 "%n queued messages successfully sent.",
457 setStatusMsg(i18n(
"%1 of %2 queued messages successfully sent.")
458 .arg(mSentMessages).arg( mTotalMessages ));
464 mCurrentMsg->setTransferInProgress(
true );
467 if (!mSendInProgress)
469 Q_ASSERT( !mProgressItem );
470 mProgressItem = KPIM::ProgressManager::createProgressItem(
472 i18n(
"Sending messages" ),
473 i18n(
"Initiating sender process..."),
475 connect( mProgressItem, TQT_SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
476 this, TQT_SLOT( slotAbortSend() ) );
478 mSendInProgress =
true;
481 TQString msgTransport = mCustomTransport;
482 if ( msgTransport.isEmpty() ) {
483 msgTransport = mCurrentMsg->headerField(
"X-KMail-Transport");
485 if ( msgTransport.isEmpty() ) {
486 const TQStringList sl = KMTransportInfo::availableTransports();
487 if (!sl.empty()) msgTransport = sl.front();
490 if (!mSendProc || msgTransport != mMethodStr) {
491 if (mSendProcStarted && mSendProc) {
493 mSendProcStarted =
false;
496 mSendProc = createSendProcFromString(msgTransport);
497 mMethodStr = msgTransport;
499 if( mTransportInfo->encryption ==
"TLS" || mTransportInfo->encryption ==
"SSL" ) {
500 mProgressItem->setUsesCrypto(
true );
501 }
else if ( !mCustomTransport.isEmpty() ) {
502 int result = KMessageBox::warningContinueCancel( 0,
503 i18n(
"You have chosen to send all queued email using an unencrypted transport, do you want to continue? "),
504 i18n(
"Security Warning" ),
505 i18n(
"Send Unencrypted" ),
506 "useCustomTransportWithoutAsking",
false);
508 if( result == KMessageBox::Cancel ) {
509 mProgressItem->cancel();
510 mProgressItem->setComplete();
518 sendProcStarted(
false);
520 connect(mSendProc, TQT_SIGNAL(idle()), TQT_SLOT(slotIdle()));
521 connect(mSendProc, TQT_SIGNAL(started(
bool)), TQT_SLOT(sendProcStarted(
bool)));
524 if ( !mTransportInfo->precommand.isEmpty() ) {
525 runPrecommand( mTransportInfo->precommand );
532 else if (!mSendProcStarted)
538 bool KMSender::runPrecommand(
const TQString & cmd ) {
539 setStatusMsg( i18n(
"Executing precommand %1").arg( cmd ) );
540 mPrecommand =
new KMPrecommand( cmd );
541 connect( mPrecommand, TQT_SIGNAL(finished(
bool)),
542 TQT_SLOT(slotPrecommandFinished(
bool)) );
543 if ( !mPrecommand->start() ) {
544 delete mPrecommand; mPrecommand = 0;
551 void KMSender::sendProcStarted(
bool success)
557 setStatusMsg(i18n(
"Unrecognized transport protocol. Unable to send message."));
559 mSendProcStarted =
false;
567 static TQStringList addrSpecListToStringList(
const AddrSpecList & l,
bool allowEmpty=
false ) {
569 for ( AddrSpecList::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it ) {
570 const TQString s = (*it).asString();
571 if ( allowEmpty || !s.isEmpty() )
572 result.push_back( s );
577 static void extractSenderToCCAndBcc(
KMMessage * aMsg, TQString * sender, TQStringList * to, TQStringList * cc, TQStringList * bcc ) {
578 if ( sender ) *sender = aMsg->
sender();
579 if( !aMsg->
headerField(
"X-KMail-Recipients").isEmpty() ) {
582 if ( to ) *to = addrSpecListToStringList( aMsg->extractAddrSpecs(
"X-KMail-Recipients" ) );
585 if ( to ) *to = addrSpecListToStringList( aMsg->extractAddrSpecs(
"To" ) );
586 if ( cc ) *cc = addrSpecListToStringList( aMsg->extractAddrSpecs(
"Cc" ) );
587 if ( bcc ) *bcc = addrSpecListToStringList( aMsg->extractAddrSpecs(
"Bcc" ) );
592 void KMSender::doSendMsgAux()
594 mSendProcStarted =
true;
598 setStatusMsg(i18n(
"%3: subject of message",
"Sending message %1 of %2: %3")
599 .arg(mSentMessages+mFailedMessages+1).arg(mTotalMessages)
600 .arg(mCurrentMsg->subject()));
601 TQStringList to, cc, bcc;
603 extractSenderToCCAndBcc( mCurrentMsg, &sender, &to, &cc, &bcc );
606 if ( messageIsDispositionNotificationReport( mCurrentMsg ) && GlobalSettings::self()->sendMDNsWithEmptySender() )
609 const TQByteArray message = mCurrentMsg->asSendableString();
610 if ( sender.isEmpty() || !mSendProc->send( sender, to, cc, bcc, message ) ) {
612 mCurrentMsg->setTransferInProgress(
false );
614 mOutboxFolder->unGetMsg( mFailedMessages );
617 setStatusMsg(i18n(
"Failed to send (some) queued messages."));
626 void KMSender::cleanup(
void)
628 kdDebug(5006) << k_funcinfo << endl;
629 if (mSendProc && mSendProcStarted) mSendProc->finish();
631 mSendProcStarted =
false;
632 if (mSendInProgress) kapp->deref();
633 mSendInProgress =
false;
636 mCurrentMsg->setTransferInProgress(
false );
640 mSentFolder->close(
"dosendsent");
643 if ( mOutboxFolder ) {
644 disconnect( mOutboxFolder, TQT_SIGNAL(msgAdded(
int)),
645 this, TQT_SLOT(outboxMsgAdded(
int)) );
646 mOutboxFolder->close(
"dosendoutbox");
647 if ( mOutboxFolder->count(
true ) == 0 ) {
648 mOutboxFolder->expunge();
650 else if ( mOutboxFolder->needsCompacting() ) {
651 mOutboxFolder->compact( KMFolder::CompactSilentlyNow );
656 mSendAborted =
false;
661 mProgressItem->setComplete();
663 kmkernel->filterMgr()->deref();
668 void KMSender::slotAbortSend()
673 if (mSendProc) mSendProc->abort();
677 void KMSender::slotIdle()
679 assert(mSendProc != 0);
684 errString = mSendProc->lastErrorMessage();
691 mOutboxFolder->unGetMsg( mFailedMessages );
694 msg = i18n(
"Sending aborted:\n%1\n"
695 "The message will stay in the 'outbox' folder until you either "
696 "fix the problem (e.g. a broken address) or remove the message "
697 "from the 'outbox' folder.\n"
698 "The following transport protocol was used:\n %2")
701 if (!errString.isEmpty()) KMessageBox::error(0,msg);
702 setStatusMsg( i18n(
"Sending aborted." ) );
704 if (!mSendProc->sendOk()) {
706 mCurrentMsg->setTransferInProgress(
false );
708 mOutboxFolder->unGetMsg( mFailedMessages );
712 TQMapIterator <TQString,TQString> pc;
713 if ( (pc = mPasswdCache.find( mMethodStr )) != mPasswdCache.end() ) {
714 mPasswdCache.erase(pc);
717 if (!errString.isEmpty()) {
718 int res = KMessageBox::Yes;
719 if (mSentMessages+mFailedMessages != mTotalMessages) {
720 msg = i18n(
"<p>Sending failed:</p>"
722 "<p>The message will stay in the 'outbox' folder until you either "
723 "fix the problem (e.g. a broken address) or remove the message "
724 "from the 'outbox' folder.</p>"
725 "<p>The following transport protocol was used: %2</p>"
726 "<p>Do you want me to continue sending the remaining messages?</p>")
729 res = KMessageBox::warningYesNo( 0 , msg ,
730 i18n(
"Continue Sending" ), i18n(
"&Continue Sending" ),
731 i18n(
"&Abort Sending") );
733 msg = i18n(
"Sending failed:\n%1\n"
734 "The message will stay in the 'outbox' folder until you either "
735 "fix the problem (e.g. a broken address) or remove the message "
736 "from the 'outbox' folder.\n"
737 "The following transport protocol was used:\n %2")
740 KMessageBox::error(0,msg);
742 if (res == KMessageBox::Yes) {
747 setStatusMsg( i18n(
"Sending aborted." ) );
758 mSendProcStarted =
false;
765 void KMSender::slotPrecommandFinished(
bool normalExit)
769 if (normalExit) mSendProc->start();
775 void KMSender::setSendImmediate(
bool aSendImmediate)
777 mSendImmediate = aSendImmediate;
782 void KMSender::setSendQuotedPrintable(
bool aSendQuotedPrintable)
784 mSendQuotedPrintable = aSendQuotedPrintable;
789 KMSendProc* KMSender::createSendProcFromString(
const TQString & transport )
791 mTransportInfo->type = TQString();
792 int nr = KMTransportInfo::findTransport(transport);
795 mTransportInfo->readConfig(nr);
797 if (transport.startsWith(
"smtp://"))
799 mTransportInfo->type =
"smtp";
800 mTransportInfo->auth =
false;
801 mTransportInfo->encryption =
"NONE";
802 TQString serverport = transport.mid(7);
803 int colon = serverport.find(
':');
805 mTransportInfo->host = serverport.left(colon);
806 mTransportInfo->port = serverport.mid(colon + 1);
808 mTransportInfo->host = serverport;
809 mTransportInfo->port =
"25";
812 if (transport.startsWith(
"smtps://"))
814 mTransportInfo->type =
"smtps";
815 mTransportInfo->auth =
false;
816 mTransportInfo->encryption =
"ssl";
817 TQString serverport = transport.mid(7);
818 int colon = serverport.find(
':');
820 mTransportInfo->host = serverport.left(colon);
821 mTransportInfo->port = serverport.mid(colon + 1);
823 mTransportInfo->host = serverport;
824 mTransportInfo->port =
"465";
827 else if (transport.startsWith(
"file://"))
829 mTransportInfo->type =
"sendmail";
830 mTransportInfo->host = transport.mid(7);
834 while (mTransportInfo->host.endsWith(
"/")) {
835 mTransportInfo->host.truncate(mTransportInfo->host.length()-1);
839 if (mTransportInfo->type ==
"sendmail")
840 return new KMSendSendmail(
this);
841 if (mTransportInfo->type ==
"smtp" || mTransportInfo->type ==
"smtps")
842 return new KMSendSMTP(
this);
848 void KMSender::setStatusByLink(
const KMMessage *aMsg)
854 aMsg->
getLink(n, &msn, &status);
862 if (folder && index != -1) {
864 if ( status == KMMsgStatusDeleted ) {
866 KMDeleteMsgCommand *cmd =
867 new KMDeleteMsgCommand( folder, folder->
getMsg( index ) );
873 kdWarning(5006) << k_funcinfo <<
"Cannot update linked message, it could not be found!" << endl;
880 KMSendProc::KMSendProc( KMSender * sender )
890 void KMSendProc::reset()
894 mLastErrorMessage = TQString();
898 void KMSendProc::failed(
const TQString &aMsg)
902 mLastErrorMessage = aMsg;
906 void KMSendProc::statusMsg(
const TQString& aMsg)
908 if (mSender) mSender->setStatusMsg(aMsg);
913 KMSendSendmail::KMSendSendmail( KMSender * sender )
914 : KMSendProc( sender ),
923 KMSendSendmail::~KMSendSendmail() {
924 delete mMailerProc; mMailerProc = 0;
927 bool KMSendSendmail::doStart() {
929 if (mSender->transportInfo()->host.isEmpty())
931 const TQString str = i18n(
"Please specify a mailer program in the settings.");
932 const TQString msg = i18n(
"Sending failed:\n%1\n"
933 "The message will stay in the 'outbox' folder and will be resent.\n"
934 "Please remove it from there if you do not want the message to "
936 "The following transport protocol was used:\n %2")
939 KMessageBox::information(0,msg);
945 mMailerProc =
new TDEProcess;
946 assert(mMailerProc != 0);
947 connect(mMailerProc,TQT_SIGNAL(processExited(TDEProcess*)),
948 this, TQT_SLOT(sendmailExited(TDEProcess*)));
949 connect(mMailerProc,TQT_SIGNAL(wroteStdin(TDEProcess*)),
950 this, TQT_SLOT(wroteStdin(TDEProcess*)));
951 connect(mMailerProc,TQT_SIGNAL(receivedStderr(TDEProcess*,
char*,
int)),
952 this, TQT_SLOT(receivedStderr(TDEProcess*,
char*,
int)));
957 void KMSendSendmail::doFinish() {
962 void KMSendSendmail::abort()
971 bool KMSendSendmail::doSend(
const TQString & sender,
const TQStringList & to,
const TQStringList & cc,
const TQStringList & bcc,
const TQByteArray & message ) {
972 mMailerProc->clearArguments();
973 *mMailerProc << mSender->transportInfo()->host
974 <<
"-i" <<
"-f" << sender
979 if ( !mMailerProc->start( TDEProcess::NotifyOnExit, TDEProcess::All ) ) {
980 KMessageBox::information( 0, i18n(
"Failed to execute mailer program %1")
981 .arg( mSender->transportInfo()->host ) );
984 mMsgPos = mMsgStr.data();
985 mMsgRest = mMsgStr.size();
986 wroteStdin( mMailerProc );
992 void KMSendSendmail::wroteStdin(TDEProcess *proc)
1001 len = (mMsgRest>1024 ? 1024 : mMsgRest);
1005 mMailerProc->closeStdin();
1011 mMailerProc->writeStdin(str,len);
1018 void KMSendSendmail::receivedStderr(TDEProcess *proc,
char *buffer,
int buflen)
1022 mLastErrorMessage.replace(mLastErrorMessage.length(), buflen, buffer);
1026 void KMSendSendmail::sendmailExited(TDEProcess *proc)
1029 mSendOk = (proc->normalExit() && proc->exitStatus()==0);
1030 if (!mSendOk) failed(i18n(
"Sendmail exited abnormally."));
1040 KMSendSMTP::KMSendSMTP(KMSender *sender)
1041 : KMSendProc(sender),
1046 TDEIO::Scheduler::connect(TQT_SIGNAL(slaveError(TDEIO::Slave *,
int,
1047 const TQString &)),
this, TQT_SLOT(slaveError(TDEIO::Slave *,
int,
1048 const TQString &)));
1051 KMSendSMTP::~KMSendSMTP()
1053 if (mJob) mJob->kill();
1056 bool KMSendSMTP::doSend(
const TQString & sender,
const TQStringList & to,
const TQStringList & cc,
const TQStringList & bcc,
const TQByteArray & message ) {
1057 TQString query =
"headers=0&from=";
1058 query += KURL::encode_string( sender );
1060 TQStringList::ConstIterator it;
1062 for ( it = to.begin(); it != to.end(); ++it )
1063 query +=
"&to=" + KURL::encode_string(*it);
1064 for ( it = cc.begin(); it != cc.end(); ++it )
1065 query +=
"&cc=" + KURL::encode_string(*it);
1066 for ( it = bcc.begin(); it != bcc.end(); ++it )
1067 query +=
"&bcc=" + KURL::encode_string(*it);
1069 KMTransportInfo * ti = mSender->transportInfo();
1071 if ( ti->specifyHostname )
1072 query +=
"&hostname=" + KURL::encode_string( ti->localHostname );
1074 if ( !kmkernel->msgSender()->sendQuotedPrintable() )
1075 query +=
"&body=8bit";
1079 destination.setProtocol((ti->encryption ==
"SSL") ? SMTPS_PROTOCOL : SMTP_PROTOCOL);
1080 destination.setHost(ti->host);
1081 destination.setPort(ti->port.toUShort());
1085 TQMapIterator<TQString,TQString> tpc = mSender->mPasswdCache.find( ti->name );
1086 TQString tpwd = ( tpc != mSender->mPasswdCache.end() )?(*tpc):TQString();
1088 if ( ti->passwd().isEmpty() )
1089 ti->setPasswd( tpwd );
1091 if( (ti->user.isEmpty() || ti->passwd().isEmpty()) &&
1092 ti->authType !=
"GSSAPI" )
1098 TQString passwd = ti->passwd();
1099 result = TDEIO::PasswordDialog::getNameAndPassword(ti->user, passwd,
1100 &b, i18n(
"You need to supply a username and a password to use this "
1101 "SMTP server."),
false, TQString(), ti->name, TQString());
1103 if ( result != TQDialog::Accepted )
1108 if (
int id = KMTransportInfo::findTransport(ti->name)) {
1109 ti->setPasswd( passwd );
1110 ti->writeConfig(
id);
1113 mSender->mPasswdCache[ti->name] = passwd;
1116 destination.setUser(ti->user);
1117 destination.setPass(ti->passwd());
1120 if (!mSlave || !mInProcess)
1122 TDEIO::MetaData slaveConfig;
1123 slaveConfig.insert(
"tls", (ti->encryption ==
"TLS") ?
"on" :
"off");
1124 if (ti->auth) slaveConfig.insert(
"sasl", ti->authType);
1125 mSlave = TDEIO::Scheduler::getConnectedSlave(destination, slaveConfig);
1136 mMessageLength = mMessage.size();
1139 if ( mMessageLength )
1142 query +=
"&size=" + TQString::number( tqRound( mMessageLength * 1.05 ) );
1144 destination.setPath(
"/send");
1145 destination.setQuery( query );
1147 mJob = TDEIO::put( destination, -1,
false,
false,
false );
1152 mJob->addMetaData(
"lf2crlf+dotstuff",
"slave" );
1153 TDEIO::Scheduler::assignJobToSlave(mSlave, mJob);
1154 connect(mJob, TQT_SIGNAL(result(TDEIO::Job *)),
this, TQT_SLOT(result(TDEIO::Job *)));
1155 connect(mJob, TQT_SIGNAL(dataReq(TDEIO::Job *, TQByteArray &)),
1156 this, TQT_SLOT(dataReq(TDEIO::Job *, TQByteArray &)));
1162 void KMSendSMTP::cleanup() {
1172 TDEIO::Scheduler::disconnectSlave(mSlave);
1179 void KMSendSMTP::abort() {
1184 void KMSendSMTP::doFinish() {
1188 void KMSendSMTP::dataReq(TDEIO::Job *, TQByteArray &array)
1191 const int chunkSize = TQMIN( mMessageLength - mMessageOffset, 32*1024 );
1192 if ( chunkSize > 0 ) {
1193 array.duplicate(mMessage.data() + mMessageOffset, chunkSize);
1194 mMessageOffset += chunkSize;
1200 mSender->emitProgressInfo( mMessageOffset );
1203 void KMSendSMTP::result(TDEIO::Job *_job)
1211 if (_job->error() == TDEIO::ERR_SLAVE_DIED) mSlave = 0;
1212 failed(_job->errorString());
1219 void KMSendSMTP::slaveError(TDEIO::Slave *aSlave,
int error,
const TQString &errorMsg)
1221 if (aSlave == mSlave)
1223 if (error == TDEIO::ERR_SLAVE_DIED) mSlave = 0;
1226 failed(TDEIO::buildErrorString(error, errorMsg));
1231 #include "kmsender.moc"
1232 #include "kmsender_p.moc"