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, TQ_SIGNAL(msgAdded(
int)),
235 this, TQ_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() );
301 mCurrentMsg->dwContentType() = newMsg.dwContentType();
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, TQ_SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
476 this, TQ_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 msgTransport = GlobalSettings::self()->defaultTransport();
488 if ( msgTransport.isEmpty() ) {
489 const TQStringList sl = KMTransportInfo::availableTransports();
490 if (!sl.empty()) msgTransport = sl.front();
493 if (!mSendProc || msgTransport != mMethodStr) {
494 if (mSendProcStarted && mSendProc) {
496 mSendProcStarted =
false;
499 mSendProc = createSendProcFromString(msgTransport);
500 mMethodStr = msgTransport;
502 if( mTransportInfo->encryption ==
"TLS" || mTransportInfo->encryption ==
"SSL" ) {
503 mProgressItem->setUsesCrypto(
true );
504 }
else if ( !mCustomTransport.isEmpty() ) {
505 int result = KMessageBox::warningContinueCancel( 0,
506 i18n(
"You have chosen to send all queued email using an unencrypted transport, do you want to continue? "),
507 i18n(
"Security Warning" ),
508 i18n(
"Send Unencrypted" ),
509 "useCustomTransportWithoutAsking",
false);
511 if( result == KMessageBox::Cancel ) {
512 mProgressItem->cancel();
513 mProgressItem->setComplete();
521 sendProcStarted(
false);
523 connect(mSendProc, TQ_SIGNAL(idle()), TQ_SLOT(slotIdle()));
524 connect(mSendProc, TQ_SIGNAL(started(
bool)), TQ_SLOT(sendProcStarted(
bool)));
527 if ( !mTransportInfo->precommand.isEmpty() ) {
528 runPrecommand( mTransportInfo->precommand );
535 else if (!mSendProcStarted)
541 bool KMSender::runPrecommand(
const TQString & cmd ) {
542 setStatusMsg( i18n(
"Executing precommand %1").arg( cmd ) );
543 mPrecommand =
new KMPrecommand( cmd );
544 connect( mPrecommand, TQ_SIGNAL(finished(
bool)),
545 TQ_SLOT(slotPrecommandFinished(
bool)) );
546 if ( !mPrecommand->start() ) {
547 delete mPrecommand; mPrecommand = 0;
554 void KMSender::sendProcStarted(
bool success)
560 setStatusMsg(i18n(
"Unrecognized transport protocol. Unable to send message."));
562 mSendProcStarted =
false;
570 static TQStringList addrSpecListToStringList(
const AddrSpecList & l,
bool allowEmpty=
false ) {
572 for ( AddrSpecList::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it ) {
573 const TQString s = (*it).asString();
574 if ( allowEmpty || !s.isEmpty() )
575 result.push_back( s );
580 static void extractSenderToCCAndBcc(
KMMessage * aMsg, TQString * sender, TQStringList * to, TQStringList * cc, TQStringList * bcc ) {
581 if ( sender ) *sender = aMsg->
sender();
582 if( !aMsg->
headerField(
"X-KMail-Recipients").isEmpty() ) {
585 if ( to ) *to = addrSpecListToStringList( aMsg->extractAddrSpecs(
"X-KMail-Recipients" ) );
588 if ( to ) *to = addrSpecListToStringList( aMsg->extractAddrSpecs(
"To" ) );
589 if ( cc ) *cc = addrSpecListToStringList( aMsg->extractAddrSpecs(
"Cc" ) );
590 if ( bcc ) *bcc = addrSpecListToStringList( aMsg->extractAddrSpecs(
"Bcc" ) );
595 void KMSender::doSendMsgAux()
597 mSendProcStarted =
true;
601 setStatusMsg(i18n(
"%3: subject of message",
"Sending message %1 of %2: %3")
602 .arg(mSentMessages+mFailedMessages+1).arg(mTotalMessages)
603 .arg(mCurrentMsg->subject()));
604 TQStringList to, cc, bcc;
606 extractSenderToCCAndBcc( mCurrentMsg, &sender, &to, &cc, &bcc );
609 if ( messageIsDispositionNotificationReport( mCurrentMsg ) && GlobalSettings::self()->sendMDNsWithEmptySender() )
612 const TQByteArray message = mCurrentMsg->asSendableString();
613 if ( sender.isEmpty() || !mSendProc->send( sender, to, cc, bcc, message ) ) {
615 mCurrentMsg->setTransferInProgress(
false );
617 mOutboxFolder->unGetMsg( mFailedMessages );
620 setStatusMsg(i18n(
"Failed to send (some) queued messages."));
629 void KMSender::cleanup(
void)
631 kdDebug(5006) << k_funcinfo << endl;
632 if (mSendProc && mSendProcStarted) mSendProc->finish();
634 mSendProcStarted =
false;
635 if (mSendInProgress) kapp->deref();
636 mSendInProgress =
false;
639 mCurrentMsg->setTransferInProgress(
false );
643 mSentFolder->close(
"dosendsent");
646 if ( mOutboxFolder ) {
647 disconnect( mOutboxFolder, TQ_SIGNAL(msgAdded(
int)),
648 this, TQ_SLOT(outboxMsgAdded(
int)) );
649 mOutboxFolder->close(
"dosendoutbox");
650 if ( mOutboxFolder->count(
true ) == 0 ) {
651 mOutboxFolder->expunge();
653 else if ( mOutboxFolder->needsCompacting() ) {
654 mOutboxFolder->compact( KMFolder::CompactSilentlyNow );
659 mSendAborted =
false;
664 mProgressItem->setComplete();
666 kmkernel->filterMgr()->deref();
671 void KMSender::slotAbortSend()
676 if (mSendProc) mSendProc->abort();
680 void KMSender::slotIdle()
682 assert(mSendProc != 0);
687 errString = mSendProc->lastErrorMessage();
694 mOutboxFolder->unGetMsg( mFailedMessages );
697 msg = i18n(
"Sending aborted:\n%1\n"
698 "The message will stay in the 'outbox' folder until you either "
699 "fix the problem (e.g. a broken address) or remove the message "
700 "from the 'outbox' folder.\n"
701 "The following transport protocol was used:\n %2")
704 if (!errString.isEmpty()) KMessageBox::error(0,msg);
705 setStatusMsg( i18n(
"Sending aborted." ) );
707 if (!mSendProc->sendOk()) {
709 mCurrentMsg->setTransferInProgress(
false );
711 mOutboxFolder->unGetMsg( mFailedMessages );
715 TQMapIterator <TQString,TQString> pc;
716 if ( (pc = mPasswdCache.find( mMethodStr )) != mPasswdCache.end() ) {
717 mPasswdCache.erase(pc);
720 if (!errString.isEmpty()) {
721 int res = KMessageBox::Yes;
722 if (mSentMessages+mFailedMessages != mTotalMessages) {
723 msg = i18n(
"<p>Sending failed:</p>"
725 "<p>The message will stay in the 'outbox' folder until you either "
726 "fix the problem (e.g. a broken address) or remove the message "
727 "from the 'outbox' folder.</p>"
728 "<p>The following transport protocol was used: %2</p>"
729 "<p>Do you want me to continue sending the remaining messages?</p>")
732 res = KMessageBox::warningYesNo( 0 , msg ,
733 i18n(
"Continue Sending" ), i18n(
"&Continue Sending" ),
734 i18n(
"&Abort Sending") );
736 msg = i18n(
"Sending failed:\n%1\n"
737 "The message will stay in the 'outbox' folder until you either "
738 "fix the problem (e.g. a broken address) or remove the message "
739 "from the 'outbox' folder.\n"
740 "The following transport protocol was used:\n %2")
743 KMessageBox::error(0,msg);
745 if (res == KMessageBox::Yes) {
750 setStatusMsg( i18n(
"Sending aborted." ) );
761 mSendProcStarted =
false;
768 void KMSender::slotPrecommandFinished(
bool normalExit)
772 if (normalExit) mSendProc->start();
778 void KMSender::setSendImmediate(
bool aSendImmediate)
780 mSendImmediate = aSendImmediate;
785 void KMSender::setSendQuotedPrintable(
bool aSendQuotedPrintable)
787 mSendQuotedPrintable = aSendQuotedPrintable;
792 KMSendProc* KMSender::createSendProcFromString(
const TQString & transport )
794 mTransportInfo->type = TQString();
795 int nr = KMTransportInfo::findTransport(transport);
798 mTransportInfo->readConfig(nr);
800 if (transport.startsWith(
"smtp://"))
802 mTransportInfo->type =
"smtp";
803 mTransportInfo->auth =
false;
804 mTransportInfo->encryption =
"NONE";
805 TQString serverport = transport.mid(7);
806 int colon = serverport.find(
':');
808 mTransportInfo->host = serverport.left(colon);
809 mTransportInfo->port = serverport.mid(colon + 1);
811 mTransportInfo->host = serverport;
812 mTransportInfo->port =
"25";
815 if (transport.startsWith(
"smtps://"))
817 mTransportInfo->type =
"smtps";
818 mTransportInfo->auth =
false;
819 mTransportInfo->encryption =
"ssl";
820 TQString serverport = transport.mid(7);
821 int colon = serverport.find(
':');
823 mTransportInfo->host = serverport.left(colon);
824 mTransportInfo->port = serverport.mid(colon + 1);
826 mTransportInfo->host = serverport;
827 mTransportInfo->port =
"465";
830 else if (transport.startsWith(
"file://"))
832 mTransportInfo->type =
"sendmail";
833 mTransportInfo->host = transport.mid(7);
837 while (mTransportInfo->host.endsWith(
"/")) {
838 mTransportInfo->host.truncate(mTransportInfo->host.length()-1);
842 if (mTransportInfo->type ==
"sendmail")
843 return new KMSendSendmail(
this);
844 if (mTransportInfo->type ==
"smtp" || mTransportInfo->type ==
"smtps")
845 return new KMSendSMTP(
this);
851 void KMSender::setStatusByLink(
const KMMessage *aMsg)
857 aMsg->
getLink(n, &msn, &status);
865 if (folder && index != -1) {
867 if ( status == KMMsgStatusDeleted ) {
869 KMDeleteMsgCommand *cmd =
870 new KMDeleteMsgCommand( folder, folder->
getMsg( index ) );
876 kdWarning(5006) << k_funcinfo <<
"Cannot update linked message, it could not be found!" << endl;
883 KMSendProc::KMSendProc( KMSender * sender )
893 void KMSendProc::reset()
897 mLastErrorMessage = TQString();
901 void KMSendProc::failed(
const TQString &aMsg)
905 mLastErrorMessage = aMsg;
909 void KMSendProc::statusMsg(
const TQString& aMsg)
911 if (mSender) mSender->setStatusMsg(aMsg);
916 KMSendSendmail::KMSendSendmail( KMSender * sender )
917 : KMSendProc( sender ),
926 KMSendSendmail::~KMSendSendmail() {
927 delete mMailerProc; mMailerProc = 0;
930 bool KMSendSendmail::doStart() {
932 if (mSender->transportInfo()->host.isEmpty())
934 const TQString str = i18n(
"Please specify a mailer program in the settings.");
935 const TQString msg = i18n(
"Sending failed:\n%1\n"
936 "The message will stay in the 'outbox' folder and will be resent.\n"
937 "Please remove it from there if you do not want the message to "
939 "The following transport protocol was used:\n %2")
942 KMessageBox::information(0,msg);
948 mMailerProc =
new TDEProcess;
949 assert(mMailerProc != 0);
950 connect(mMailerProc,TQ_SIGNAL(processExited(TDEProcess*)),
951 this, TQ_SLOT(sendmailExited(TDEProcess*)));
952 connect(mMailerProc,TQ_SIGNAL(wroteStdin(TDEProcess*)),
953 this, TQ_SLOT(wroteStdin(TDEProcess*)));
954 connect(mMailerProc,TQ_SIGNAL(receivedStderr(TDEProcess*,
char*,
int)),
955 this, TQ_SLOT(receivedStderr(TDEProcess*,
char*,
int)));
960 void KMSendSendmail::doFinish() {
965 void KMSendSendmail::abort()
974 bool KMSendSendmail::doSend(
const TQString & sender,
const TQStringList & to,
const TQStringList & cc,
const TQStringList & bcc,
const TQByteArray & message ) {
975 mMailerProc->clearArguments();
976 *mMailerProc << mSender->transportInfo()->host
977 <<
"-i" <<
"-f" << sender
982 if ( !mMailerProc->start( TDEProcess::NotifyOnExit, TDEProcess::All ) ) {
983 KMessageBox::information( 0, i18n(
"Failed to execute mailer program %1")
984 .arg( mSender->transportInfo()->host ) );
987 mMsgPos = mMsgStr.data();
988 mMsgRest = mMsgStr.size();
989 wroteStdin( mMailerProc );
995 void KMSendSendmail::wroteStdin(TDEProcess *proc)
1004 len = (mMsgRest>1024 ? 1024 : mMsgRest);
1008 mMailerProc->closeStdin();
1014 mMailerProc->writeStdin(str,len);
1021 void KMSendSendmail::receivedStderr(TDEProcess *proc,
char *buffer,
int buflen)
1025 mLastErrorMessage.replace(mLastErrorMessage.length(), buflen, buffer);
1029 void KMSendSendmail::sendmailExited(TDEProcess *proc)
1032 mSendOk = (proc->normalExit() && proc->exitStatus()==0);
1033 if (!mSendOk) failed(i18n(
"Sendmail exited abnormally."));
1043 KMSendSMTP::KMSendSMTP(KMSender *sender)
1044 : KMSendProc(sender),
1049 TDEIO::Scheduler::connect(TQ_SIGNAL(slaveError(TDEIO::Slave *,
int,
1050 const TQString &)),
this, TQ_SLOT(slaveError(TDEIO::Slave *,
int,
1051 const TQString &)));
1054 KMSendSMTP::~KMSendSMTP()
1056 if (mJob) mJob->kill();
1059 bool KMSendSMTP::doSend(
const TQString & sender,
const TQStringList & to,
const TQStringList & cc,
const TQStringList & bcc,
const TQByteArray & message ) {
1060 TQString query =
"headers=0&from=";
1061 query += KURL::encode_string( sender );
1063 TQStringList::ConstIterator it;
1065 for ( it = to.begin(); it != to.end(); ++it )
1066 query +=
"&to=" + KURL::encode_string(*it);
1067 for ( it = cc.begin(); it != cc.end(); ++it )
1068 query +=
"&cc=" + KURL::encode_string(*it);
1069 for ( it = bcc.begin(); it != bcc.end(); ++it )
1070 query +=
"&bcc=" + KURL::encode_string(*it);
1072 KMTransportInfo * ti = mSender->transportInfo();
1074 if ( ti->specifyHostname )
1075 query +=
"&hostname=" + KURL::encode_string( ti->localHostname );
1077 if ( !kmkernel->msgSender()->sendQuotedPrintable() )
1078 query +=
"&body=8bit";
1082 destination.setProtocol((ti->encryption ==
"SSL") ? SMTPS_PROTOCOL : SMTP_PROTOCOL);
1083 destination.setHost(ti->host);
1084 destination.setPort(ti->port.toUShort());
1088 TQMapIterator<TQString,TQString> tpc = mSender->mPasswdCache.find( ti->name );
1089 TQString tpwd = ( tpc != mSender->mPasswdCache.end() )?(*tpc):TQString();
1091 if ( ti->passwd().isEmpty() )
1092 ti->setPasswd( tpwd );
1094 if( (ti->user.isEmpty() || ti->passwd().isEmpty()) &&
1095 ti->authType !=
"GSSAPI" )
1101 TQString passwd = ti->passwd();
1102 result = TDEIO::PasswordDialog::getNameAndPassword(ti->user, passwd,
1103 &b, i18n(
"You need to supply a username and a password to use this "
1104 "SMTP server."),
false, TQString(), ti->name, TQString());
1106 if ( result != TQDialog::Accepted )
1111 if (
int id = KMTransportInfo::findTransport(ti->name)) {
1112 ti->setPasswd( passwd );
1113 ti->writeConfig(
id);
1116 mSender->mPasswdCache[ti->name] = passwd;
1119 destination.setUser(ti->user);
1120 destination.setPass(ti->passwd());
1123 if (!mSlave || !mInProcess)
1125 TDEIO::MetaData slaveConfig;
1126 slaveConfig.insert(
"tls", (ti->encryption ==
"TLS") ?
"on" :
"off");
1127 if (ti->auth) slaveConfig.insert(
"sasl", ti->authType);
1128 mSlave = TDEIO::Scheduler::getConnectedSlave(destination, slaveConfig);
1139 mMessageLength = mMessage.size();
1142 if ( mMessageLength )
1145 query +=
"&size=" + TQString::number( tqRound( mMessageLength * 1.05 ) );
1147 destination.setPath(
"/send");
1148 destination.setQuery( query );
1150 mJob = TDEIO::put( destination, -1,
false,
false,
false );
1155 mJob->addMetaData(
"lf2crlf+dotstuff",
"slave" );
1156 TDEIO::Scheduler::assignJobToSlave(mSlave, mJob);
1157 connect(mJob, TQ_SIGNAL(result(TDEIO::Job *)),
this, TQ_SLOT(result(TDEIO::Job *)));
1158 connect(mJob, TQ_SIGNAL(dataReq(TDEIO::Job *, TQByteArray &)),
1159 this, TQ_SLOT(dataReq(TDEIO::Job *, TQByteArray &)));
1165 void KMSendSMTP::cleanup() {
1175 TDEIO::Scheduler::disconnectSlave(mSlave);
1182 void KMSendSMTP::abort() {
1187 void KMSendSMTP::doFinish() {
1191 void KMSendSMTP::dataReq(TDEIO::Job *, TQByteArray &array)
1194 const int chunkSize = TQMIN( mMessageLength - mMessageOffset, 32*1024 );
1195 if ( chunkSize > 0 ) {
1196 array.duplicate(mMessage.data() + mMessageOffset, chunkSize);
1197 mMessageOffset += chunkSize;
1203 mSender->emitProgressInfo( mMessageOffset );
1206 void KMSendSMTP::result(TDEIO::Job *_job)
1214 if (_job->error() == TDEIO::ERR_SLAVE_DIED) mSlave = 0;
1215 failed(_job->errorString());
1222 void KMSendSMTP::slaveError(TDEIO::Slave *aSlave,
int error,
const TQString &errorMsg)
1224 if (aSlave == mSlave)
1226 if (error == TDEIO::ERR_SLAVE_DIED) mSlave = 0;
1229 failed(TDEIO::buildErrorString(error, errorMsg));
1234 #include "kmsender.moc"
1235 #include "kmsender_p.moc"
sets a cursor and makes sure it's restored on destruction Create a KCursorSaver object when you want ...
RAII for KMFolder::open() / close().
int moveMsg(KMMessage *msg, int *index_return=0)
Detaches the given message from it's current folder and adds it to this folder.
KMMsgInfo * unGetMsg(int idx)
Replace KMMessage with KMMsgInfo and delete KMMessage
int addMsg(KMMessage *msg, int *index_return=0)
Add the given message to the folder.
void close(const char *owner, bool force=false)
Close folder.
KMMessage * getMsg(int idx)
Read message at given index.
void setStatus(int idx, KMMsgStatus status, bool toggle=false)
Set the status of the message at index idx to status.
int count(bool cache=false) const
Number of messages in this folder.
int open(const char *owner)
Open folder for access.
bool isReadOnly() const
Is the folder read-only?
static TQString generateMessageId(const TQString &addr)
Generates the Message-Id.
void setTransferInProgress(bool value, bool force=false)
Set that the message shall not be deleted because it is still required.
TQString msgId() const
Get or set the 'Message-Id' header field.
KMMessage * unencryptedMsg() const
Returns an unencrypted copy of this message or 0 if none exists.
void setStatus(const KMMsgStatus status, int idx=-1)
Set status and mark dirty.
void setUnencryptedMsg(KMMessage *unencrypted)
Specifies an unencrypted copy of this message to be stored in a separate member variable to allow sav...
DwMediaType & dwContentType()
Return reference to Content-Type header for direct manipulation.
TQString to() const
Get or set the 'To' header field.
void removeHeaderField(const TQCString &name)
Remove header field with given name.
TQString headerField(const TQCString &name) const
Returns the value of a header field with the given name.
void getLink(int n, ulong *retMsgSerNum, KMMsgStatus *reStatus) const
Returns the information for the Nth link into retMsg and reStatus.
void getLocation(unsigned long key, KMFolder **retFolder, int *retIndex) const
Returns the folder the message represented by the serial number key is in and the index in that folde...
static const KMMsgDict * instance()
Access the globally unique MessageDict.