5#define REALLY_WANT_KMSENDER
8#undef REALLY_WANT_KMSENDER
10#include <kmime_header_parsing.h>
11using namespace KMime::Types;
13#include <tdeio/passdlg.h>
14#include <tdeio/scheduler.h>
15#include <tdeapplication.h>
16#include <tdemessagebox.h>
27#include "globalsettings.h"
28#include "kmfiltermgr.h"
30#include "kcursorsaver.h"
31#include <libkpimidentities/identity.h>
32#include <libkpimidentities/identitymanager.h>
33#include "progressmanager.h"
35#include "kmtransport.h"
36#include "kmfolderindex.h"
37#include "kmfoldermgr.h"
41#include "kmcommands.h"
42#include <mimelib/mediatyp.h>
43#include <mimelib/enum.h>
44#include <mimelib/param.h>
46#define SENDER_GROUP "sending mail"
50 : mOutboxFolder( 0 ), mSentFolder( 0 )
54 mSendProcStarted =
false;
55 mSendInProgress =
false;
57 mTransportInfo =
new KMTransportInfo();
75 delete mTransportInfo;
79void KMSender::setStatusMsg(
const TQString &msg)
82 mProgressItem->setStatus(msg);
86void KMSender::readConfig(
void)
89 TDEConfigGroup config(KMKernel::config(), SENDER_GROUP);
91 mSendImmediate = config.readBoolEntry(
"Immediate",
true);
92 mSendQuotedPrintable = config.readBoolEntry(
"Quoted-Printable",
true);
97void KMSender::writeConfig(
bool aWithSync)
99 TDEConfigGroup config(KMKernel::config(), SENDER_GROUP);
101 config.writeEntry(
"Immediate", mSendImmediate);
102 config.writeEntry(
"Quoted-Printable", mSendQuotedPrintable);
104 if (aWithSync) config.sync();
109bool KMSender::settingsOk()
const
111 if (KMTransportInfo::availableTransports().isEmpty())
113 KMessageBox::information(0,i18n(
"Please create an account for sending and try again."));
119static void handleRedirections(
KMMessage * m ) {
120 const TQString from = m->
headerField(
"X-KMail-Redirect-From");
121 const TQString msgId = m->
msgId();
122 if( from.isEmpty() || msgId.isEmpty() )
127bool KMSender::doSend(
KMMessage* aMsg,
short sendNow)
132 if (!settingsOk())
return false;
134 if (aMsg->
to().isEmpty())
156 aMsg->setTo(
"Undisclosed.Recipients: ;");
159 handleRedirections( aMsg );
161 if (sendNow==-1) sendNow = mSendImmediate;
163 KMFolder *
const outbox = kmkernel->outboxFolder();
168 if (
const int err = outbox->
addMsg(aMsg) ) {
170 KMessageBox::information(0,i18n(
"Cannot add message to outbox folder"));
185 const int idx = outbox->
count() - 1;
191 if ( !sendNow || mSendInProgress )
199void KMSender::outboxMsgAdded(
int idx)
202 KMMsgBase* msg = kmkernel->outboxFolder()->getMsgBase(idx);
205 mTotalBytes += msg->msgSize();
210bool KMSender::doSendQueued(
const TQString &customTransport )
212 if (!settingsOk())
return false;
220 mOutboxFolder = kmkernel->outboxFolder();
221 mOutboxFolder->open(
"dosendoutbox");
222 mTotalMessages = mOutboxFolder->count();
223 if (mTotalMessages == 0) {
225 mOutboxFolder->close(
"dosendoutbox");
230 for(
int i = 0 ; i<mTotalMessages ; ++i )
231 mTotalBytes += mOutboxFolder->getMsgBase(i)->msgSize();
233 connect( mOutboxFolder, TQ_SIGNAL(msgAdded(
int)),
234 this, TQ_SLOT(outboxMsgAdded(
int)) );
237 mSentFolder = kmkernel->sentFolder();
238 mSentFolder->open(
"dosendsent");
239 kmkernel->filterMgr()->ref();
242 mCustomTransport = customTransport;
248void KMSender::emitProgressInfo(
int currentFileProgress )
250 int percent = (mTotalBytes) ? ( 100 * (mSentBytes+currentFileProgress) / mTotalBytes ) : 0;
251 if (percent > 100) percent = 100;
252 mProgressItem->setProgress(percent);
255static bool messageIsDispositionNotificationReport(
KMMessage *msg )
257 if ( msg->type() == DwMime::kTypeMessage &&
258 msg->subtype() == DwMime::kSubtypeDispositionNotification )
261 if ( msg->type() != DwMime::kTypeMultipart ||
262 msg->subtype() != DwMime::kSubtypeReport )
266 DwParameter *param = ct.FirstParameter();
268 if ( !tqstricmp( param->Attribute().c_str(),
"report-type")
269 && !tqstricmp( param->Value().c_str(),
"disposition-notification" ) )
272 param = param->Next();
278void KMSender::doSendMsg()
283 const bool someSent = mCurrentMsg;
286 mSentBytes += mCurrentMsg->msgSize();
290 KMFolder *sentFolder = 0, *imapSentFolder = 0;
291 if (mCurrentMsg && kmkernel->filterMgr())
293 mCurrentMsg->setTransferInProgress(
false );
294 if( mCurrentMsg->hasUnencryptedMsg() ) {
295 kdDebug(5006) <<
"KMSender::doSendMsg() post-processing: replace mCurrentMsg body by unencryptedMsg data" << endl;
297 mCurrentMsg->deleteBodyParts();
299 KMMessage & newMsg( *mCurrentMsg->unencryptedMsg() );
300 mCurrentMsg->dwContentType() = newMsg.dwContentType();
301 mCurrentMsg->setContentTransferEncodingStr( newMsg.contentTransferEncodingStr() );
302 TQCString newDispo = newMsg.headerField(
"Content-Disposition").latin1();
303 if( newDispo.isEmpty() )
304 mCurrentMsg->removeHeaderField(
"Content-Disposition" );
306 mCurrentMsg->setHeaderField(
"Content-Disposition", newDispo );
308 mCurrentMsg->setBody( newMsg.body() );
310 KMMessagePart msgPart;
311 for(
int i = 0; i < newMsg.numBodyParts(); ++i ) {
312 newMsg.bodyPart( i, &msgPart );
313 mCurrentMsg->addBodyPart( &msgPart );
316 mCurrentMsg->setStatus(KMMsgStatusSent);
317 mCurrentMsg->setStatus(KMMsgStatusRead);
318 mCurrentMsg->updateAttachmentState();
319 mCurrentMsg->updateInvitationState();
321 const KPIM::Identity &
id = kmkernel->identityManager()
322 ->identityForUoidOrDefault( mCurrentMsg->headerField(
"X-KMail-Identity" ).stripWhiteSpace().toUInt() );
323 if ( !mCurrentMsg->fcc().isEmpty() )
325 sentFolder = kmkernel->folderMgr()->findIdString( mCurrentMsg->fcc() );
326 if ( sentFolder == 0 )
329 kmkernel->dimapFolderMgr()->findIdString( mCurrentMsg->fcc() );
330 if ( sentFolder == 0 )
332 kmkernel->imapFolderMgr()->findIdString( mCurrentMsg->fcc() );
336 if ( ( sentFolder == 0 || sentFolder->
isReadOnly() )
337 && ( imapSentFolder == 0 || imapSentFolder->isReadOnly() )
338 && !
id.fcc().isEmpty() )
340 sentFolder = kmkernel->folderMgr()->findIdString(
id.fcc() );
341 if ( sentFolder == 0 )
343 sentFolder = kmkernel->dimapFolderMgr()->findIdString(
id.fcc() );
344 if ( sentFolder == 0 )
345 imapSentFolder = kmkernel->imapFolderMgr()->findIdString(
id.fcc() );
348 && ( imapSentFolder->noContent() || imapSentFolder->isReadOnly() ) )
351 if ( sentFolder == 0 || sentFolder->
isReadOnly() )
352 sentFolder = kmkernel->sentFolder();
355 if (
const int err = sentFolder->
open(
"sentFolder") ) {
365 if ( mCurrentMsg->parent() ) mCurrentMsg->parent()->quiet(
true );
366 const int processResult = kmkernel->filterMgr()->process(mCurrentMsg,KMFilterMgr::Outbound);
367 if ( mCurrentMsg->parent() ) mCurrentMsg->parent()->quiet(
false );
370 switch (processResult) {
372 perror(
"Critical error: Unable to process sent mail (out of space?)");
373 KMessageBox::information(0, i18n(
"Critical error: "
374 "Unable to process sent mail (out of space?)"
375 "Moving failing message to \"sent-mail\" folder."));
377 sentFolder->
moveMsg(mCurrentMsg);
378 sentFolder->
close(
"sentFolder");
383 if ( sentFolder && sentFolder->
moveMsg(mCurrentMsg) != 0 )
385 KMessageBox::error(0, i18n(
"Moving the sent message \"%1\" from the "
386 "\"outbox\" to the \"sent-mail\" folder failed.\n"
387 "Possible reasons are lack of disk space or write permission. "
388 "Please try to fix the problem and move the message manually.")
389 .arg(mCurrentMsg->subject()));
393 if (imapSentFolder) {
395 KMCommand *command =
new KMMoveCommand( imapSentFolder, mCurrentMsg );
396 command->keepFolderOpen( sentFolder );
402 setStatusByLink( mCurrentMsg );
403 if (mCurrentMsg->parent() && !imapSentFolder) {
406 assert( mCurrentMsg->parent()->find( mCurrentMsg )
407 == mCurrentMsg->parent()->count() - 1 );
409 mCurrentMsg->parent()->unGetMsg( mCurrentMsg->parent()->count() -1 );
416 mCurrentMsg = mOutboxFolder->getMsg(mFailedMessages);
417 if ( mCurrentMsg && !mCurrentMsg->transferInProgress() &&
418 mCurrentMsg->sender().isEmpty() ) {
422 const KPIM::Identity &
id = kmkernel->identityManager()
423 ->identityForUoidOrDefault( mCurrentMsg->headerField(
"X-KMail-Identity" ).stripWhiteSpace().toUInt() );
424 if ( !
id.primaryEmailAddress().isEmpty() ) {
425 mCurrentMsg->setFrom(
id.fullEmailAddr() );
427 else if ( !kmkernel->identityManager()->defaultIdentity().primaryEmailAddress().isEmpty() ) {
428 mCurrentMsg->setFrom( kmkernel->identityManager()->defaultIdentity().fullEmailAddr() );
431 KMessageBox::sorry( 0, i18n(
"It's not possible to send messages "
432 "without specifying a sender address.\n"
433 "Please set the email address of "
434 "identity '%1' in the Identities "
435 "section of the configuration dialog "
436 "and then try again." )
437 .arg(
id.identityName() ) );
438 mOutboxFolder->unGetMsg( mFailedMessages );
442 if (!mCurrentMsg || mCurrentMsg->transferInProgress())
445 if (mCurrentMsg && mCurrentMsg->transferInProgress())
448 if ( sentFolder != 0 )
449 sentFolder->
close(
"sentFolder");
451 if ( mSentMessages == mTotalMessages ) {
452 setStatusMsg(i18n(
"%n queued message successfully sent.",
453 "%n queued messages successfully sent.",
456 setStatusMsg(i18n(
"%1 of %2 queued messages successfully sent.")
457 .arg(mSentMessages).arg( mTotalMessages ));
463 mCurrentMsg->setTransferInProgress(
true );
466 if (!mSendInProgress)
468 Q_ASSERT( !mProgressItem );
469 mProgressItem = KPIM::ProgressManager::createProgressItem(
471 i18n(
"Sending messages" ),
472 i18n(
"Initiating sender process..."),
474 connect( mProgressItem, TQ_SIGNAL(progressItemCanceled(KPIM::ProgressItem*)),
475 this, TQ_SLOT( slotAbortSend() ) );
477 mSendInProgress =
true;
480 TQString msgTransport = mCustomTransport;
481 if ( msgTransport.isEmpty() ) {
482 msgTransport = mCurrentMsg->headerField(
"X-KMail-Transport");
484 if ( msgTransport.isEmpty() ) {
485 msgTransport = GlobalSettings::self()->defaultTransport();
487 if ( msgTransport.isEmpty() ) {
488 const TQStringList sl = KMTransportInfo::availableTransports();
489 if (!sl.empty()) msgTransport = sl.front();
492 if (!mSendProc || msgTransport != mMethodStr) {
493 if (mSendProcStarted && mSendProc) {
495 mSendProcStarted =
false;
498 mSendProc = createSendProcFromString(msgTransport);
499 mMethodStr = msgTransport;
501 if( mTransportInfo->encryption ==
"TLS" || mTransportInfo->encryption ==
"SSL" ) {
502 mProgressItem->setUsesCrypto(
true );
503 }
else if ( !mCustomTransport.isEmpty() ) {
504 int result = KMessageBox::warningContinueCancel( 0,
505 i18n(
"You have chosen to send all queued email using an unencrypted transport, do you want to continue? "),
506 i18n(
"Security Warning" ),
507 i18n(
"Send Unencrypted" ),
508 "useCustomTransportWithoutAsking",
false);
510 if( result == KMessageBox::Cancel ) {
511 mProgressItem->cancel();
512 mProgressItem->setComplete();
520 sendProcStarted(
false);
522 connect(mSendProc, TQ_SIGNAL(idle()), TQ_SLOT(slotIdle()));
523 connect(mSendProc, TQ_SIGNAL(started(
bool)), TQ_SLOT(sendProcStarted(
bool)));
526 if ( !mTransportInfo->precommand.isEmpty() ) {
527 runPrecommand( mTransportInfo->precommand );
534 else if (!mSendProcStarted)
540bool KMSender::runPrecommand(
const TQString & cmd ) {
541 setStatusMsg( i18n(
"Executing precommand %1").arg( cmd ) );
542 mPrecommand =
new KMPrecommand( cmd );
543 connect( mPrecommand, TQ_SIGNAL(finished(
bool)),
544 TQ_SLOT(slotPrecommandFinished(
bool)) );
545 if ( !mPrecommand->start() ) {
546 delete mPrecommand; mPrecommand = 0;
553void KMSender::sendProcStarted(
bool success)
559 setStatusMsg(i18n(
"Unrecognized transport protocol. Unable to send message."));
561 mSendProcStarted =
false;
569static TQStringList addrSpecListToStringList(
const AddrSpecList & l,
bool allowEmpty=
false ) {
571 for ( AddrSpecList::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it ) {
572 const TQString s = (*it).asString();
573 if ( allowEmpty || !s.isEmpty() )
574 result.push_back( s );
579static void extractSenderToCCAndBcc(
KMMessage * aMsg, TQString * sender, TQStringList * to, TQStringList * cc, TQStringList * bcc ) {
580 if ( sender ) *sender = aMsg->
sender();
581 if( !aMsg->
headerField(
"X-KMail-Recipients").isEmpty() ) {
584 if ( to ) *to = addrSpecListToStringList( aMsg->extractAddrSpecs(
"X-KMail-Recipients" ) );
587 if ( to ) *to = addrSpecListToStringList( aMsg->extractAddrSpecs(
"To" ) );
588 if ( cc ) *cc = addrSpecListToStringList( aMsg->extractAddrSpecs(
"Cc" ) );
589 if ( bcc ) *bcc = addrSpecListToStringList( aMsg->extractAddrSpecs(
"Bcc" ) );
594void KMSender::doSendMsgAux()
596 mSendProcStarted =
true;
600 setStatusMsg(i18n(
"%3: subject of message",
"Sending message %1 of %2: %3")
601 .arg(mSentMessages+mFailedMessages+1).arg(mTotalMessages)
602 .arg(mCurrentMsg->subject()));
603 TQStringList to, cc, bcc;
605 extractSenderToCCAndBcc( mCurrentMsg, &sender, &to, &cc, &bcc );
608 if ( messageIsDispositionNotificationReport( mCurrentMsg ) && GlobalSettings::self()->sendMDNsWithEmptySender() )
611 const TQByteArray message = mCurrentMsg->asSendableString();
612 if ( sender.isEmpty() || !mSendProc->send( sender, to, cc, bcc, message ) ) {
614 mCurrentMsg->setTransferInProgress(
false );
616 mOutboxFolder->unGetMsg( mFailedMessages );
619 setStatusMsg(i18n(
"Failed to send (some) queued messages."));
628void KMSender::cleanup(
void)
630 kdDebug(5006) << k_funcinfo << endl;
631 if (mSendProc && mSendProcStarted) mSendProc->finish();
633 mSendProcStarted =
false;
634 if (mSendInProgress) tdeApp->deref();
635 mSendInProgress =
false;
638 mCurrentMsg->setTransferInProgress(
false );
642 mSentFolder->close(
"dosendsent");
645 if ( mOutboxFolder ) {
646 disconnect( mOutboxFolder, TQ_SIGNAL(msgAdded(
int)),
647 this, TQ_SLOT(outboxMsgAdded(
int)) );
648 mOutboxFolder->close(
"dosendoutbox");
649 if ( mOutboxFolder->count(
true ) == 0 ) {
650 mOutboxFolder->expunge();
652 else if ( mOutboxFolder->needsCompacting() ) {
653 mOutboxFolder->compact( KMFolder::CompactSilentlyNow );
658 mSendAborted =
false;
663 mProgressItem->setComplete();
665 kmkernel->filterMgr()->deref();
670void KMSender::slotAbortSend()
675 if (mSendProc) mSendProc->abort();
679void KMSender::slotIdle()
681 assert(mSendProc != 0);
686 errString = mSendProc->lastErrorMessage();
693 mOutboxFolder->unGetMsg( mFailedMessages );
696 msg = i18n(
"Sending aborted:\n%1\n"
697 "The message will stay in the 'outbox' folder until you either "
698 "fix the problem (e.g. a broken address) or remove the message "
699 "from the 'outbox' folder.\n"
700 "The following transport protocol was used:\n %2")
703 if (!errString.isEmpty()) KMessageBox::error(0,msg);
704 setStatusMsg( i18n(
"Sending aborted." ) );
706 if (!mSendProc->sendOk()) {
708 mCurrentMsg->setTransferInProgress(
false );
710 mOutboxFolder->unGetMsg( mFailedMessages );
714 TQMapIterator <TQString,TQString> pc;
715 if ( (pc = mPasswdCache.find( mMethodStr )) != mPasswdCache.end() ) {
716 mPasswdCache.erase(pc);
719 if (!errString.isEmpty()) {
720 int res = KMessageBox::Yes;
721 if (mSentMessages+mFailedMessages != mTotalMessages) {
722 msg = i18n(
"<p>Sending failed:</p>"
724 "<p>The message will stay in the 'outbox' folder until you either "
725 "fix the problem (e.g. a broken address) or remove the message "
726 "from the 'outbox' folder.</p>"
727 "<p>The following transport protocol was used: %2</p>"
728 "<p>Do you want me to continue sending the remaining messages?</p>")
731 res = KMessageBox::warningYesNo( 0 , msg ,
732 i18n(
"Continue Sending" ), i18n(
"&Continue Sending" ),
733 i18n(
"&Abort Sending") );
735 msg = i18n(
"Sending failed:\n%1\n"
736 "The message will stay in the 'outbox' folder until you either "
737 "fix the problem (e.g. a broken address) or remove the message "
738 "from the 'outbox' folder.\n"
739 "The following transport protocol was used:\n %2")
742 KMessageBox::error(0,msg);
744 if (res == KMessageBox::Yes) {
749 setStatusMsg( i18n(
"Sending aborted." ) );
760 mSendProcStarted =
false;
767void KMSender::slotPrecommandFinished(
bool normalExit)
771 if (normalExit) mSendProc->start();
777void KMSender::setSendImmediate(
bool aSendImmediate)
779 mSendImmediate = aSendImmediate;
784void KMSender::setSendQuotedPrintable(
bool aSendQuotedPrintable)
786 mSendQuotedPrintable = aSendQuotedPrintable;
791KMSendProc* KMSender::createSendProcFromString(
const TQString & transport )
793 mTransportInfo->type = TQString();
794 int nr = KMTransportInfo::findTransport(transport);
797 mTransportInfo->readConfig(nr);
799 if (transport.startsWith(
"smtp://"))
801 mTransportInfo->type =
"smtp";
802 mTransportInfo->auth =
false;
803 mTransportInfo->encryption =
"NONE";
804 TQString serverport = transport.mid(7);
805 int colon = serverport.find(
':');
807 mTransportInfo->host = serverport.left(colon);
808 mTransportInfo->port = serverport.mid(colon + 1);
810 mTransportInfo->host = serverport;
811 mTransportInfo->port =
"25";
814 if (transport.startsWith(
"smtps://"))
816 mTransportInfo->type =
"smtps";
817 mTransportInfo->auth =
false;
818 mTransportInfo->encryption =
"ssl";
819 TQString serverport = transport.mid(7);
820 int colon = serverport.find(
':');
822 mTransportInfo->host = serverport.left(colon);
823 mTransportInfo->port = serverport.mid(colon + 1);
825 mTransportInfo->host = serverport;
826 mTransportInfo->port =
"465";
829 else if (transport.startsWith(
"file://"))
831 mTransportInfo->type =
"sendmail";
832 mTransportInfo->host = transport.mid(7);
836 while (mTransportInfo->host.endsWith(
"/")) {
837 mTransportInfo->host.truncate(mTransportInfo->host.length()-1);
841 if (mTransportInfo->type ==
"sendmail")
842 return new KMSendSendmail(
this);
843 if (mTransportInfo->type ==
"smtp" || mTransportInfo->type ==
"smtps")
844 return new KMSendSMTP(
this);
850void KMSender::setStatusByLink(
const KMMessage *aMsg)
856 aMsg->
getLink(n, &msn, &status);
864 if (folder && index != -1) {
866 if ( status == KMMsgStatusDeleted ) {
868 KMDeleteMsgCommand *cmd =
869 new KMDeleteMsgCommand( folder, folder->
getMsg( index ) );
875 kdWarning(5006) << k_funcinfo <<
"Cannot update linked message, it could not be found!" << endl;
882KMSendProc::KMSendProc( KMSender * sender )
892void KMSendProc::reset()
896 mLastErrorMessage = TQString();
900void KMSendProc::failed(
const TQString &aMsg)
904 mLastErrorMessage = aMsg;
908void KMSendProc::statusMsg(
const TQString& aMsg)
910 if (mSender) mSender->setStatusMsg(aMsg);
915KMSendSendmail::KMSendSendmail( KMSender * sender )
916 : KMSendProc( sender ),
925KMSendSendmail::~KMSendSendmail() {
926 delete mMailerProc; mMailerProc = 0;
929bool KMSendSendmail::doStart() {
931 if (mSender->transportInfo()->host.isEmpty())
933 const TQString str = i18n(
"Please specify a mailer program in the settings.");
934 const TQString msg = i18n(
"Sending failed:\n%1\n"
935 "The message will stay in the 'outbox' folder and will be resent.\n"
936 "Please remove it from there if you do not want the message to "
938 "The following transport protocol was used:\n %2")
941 KMessageBox::information(0,msg);
947 mMailerProc =
new TDEProcess;
948 assert(mMailerProc != 0);
949 connect(mMailerProc,TQ_SIGNAL(processExited(TDEProcess*)),
950 this, TQ_SLOT(sendmailExited(TDEProcess*)));
951 connect(mMailerProc,TQ_SIGNAL(wroteStdin(TDEProcess*)),
952 this, TQ_SLOT(wroteStdin(TDEProcess*)));
953 connect(mMailerProc,TQ_SIGNAL(receivedStderr(TDEProcess*,
char*,
int)),
954 this, TQ_SLOT(receivedStderr(TDEProcess*,
char*,
int)));
959void KMSendSendmail::doFinish() {
964void KMSendSendmail::abort()
973bool KMSendSendmail::doSend(
const TQString & sender,
const TQStringList & to,
const TQStringList & cc,
const TQStringList & bcc,
const TQByteArray & message ) {
974 mMailerProc->clearArguments();
975 *mMailerProc << mSender->transportInfo()->host
976 <<
"-i" <<
"-f" << sender
981 if ( !mMailerProc->start( TDEProcess::NotifyOnExit, TDEProcess::All ) ) {
982 KMessageBox::information( 0, i18n(
"Failed to execute mailer program %1")
983 .arg( mSender->transportInfo()->host ) );
986 mMsgPos = mMsgStr.data();
987 mMsgRest = mMsgStr.size();
988 wroteStdin( mMailerProc );
994void KMSendSendmail::wroteStdin(TDEProcess *proc)
1003 len = (mMsgRest>1024 ? 1024 : mMsgRest);
1007 mMailerProc->closeStdin();
1013 mMailerProc->writeStdin(str,len);
1020void KMSendSendmail::receivedStderr(TDEProcess *proc,
char *buffer,
int buflen)
1024 mLastErrorMessage.replace(mLastErrorMessage.length(), buflen, buffer);
1028void KMSendSendmail::sendmailExited(TDEProcess *proc)
1031 mSendOk = (proc->normalExit() && proc->exitStatus()==0);
1032 if (!mSendOk) failed(i18n(
"Sendmail exited abnormally."));
1042KMSendSMTP::KMSendSMTP(KMSender *sender)
1043 : KMSendProc(sender),
1048 TDEIO::Scheduler::connect(TQ_SIGNAL(slaveError(TDEIO::Slave *,
int,
1049 const TQString &)),
this, TQ_SLOT(slaveError(TDEIO::Slave *,
int,
1050 const TQString &)));
1053KMSendSMTP::~KMSendSMTP()
1055 if (mJob) mJob->kill();
1058bool KMSendSMTP::doSend(
const TQString & sender,
const TQStringList & to,
const TQStringList & cc,
const TQStringList & bcc,
const TQByteArray & message ) {
1059 TQString query =
"headers=0&from=";
1060 query += KURL::encode_string( sender );
1062 TQStringList::ConstIterator it;
1064 for ( it = to.begin(); it != to.end(); ++it )
1065 query +=
"&to=" + KURL::encode_string(*it);
1066 for ( it = cc.begin(); it != cc.end(); ++it )
1067 query +=
"&cc=" + KURL::encode_string(*it);
1068 for ( it = bcc.begin(); it != bcc.end(); ++it )
1069 query +=
"&bcc=" + KURL::encode_string(*it);
1071 KMTransportInfo * ti = mSender->transportInfo();
1073 if ( ti->specifyHostname )
1074 query +=
"&hostname=" + KURL::encode_string( ti->localHostname );
1076 if ( !kmkernel->msgSender()->sendQuotedPrintable() )
1077 query +=
"&body=8bit";
1081 destination.setProtocol((ti->encryption ==
"SSL") ? SMTPS_PROTOCOL : SMTP_PROTOCOL);
1082 destination.setHost(ti->host);
1083 destination.setPort(ti->port.toUShort());
1087 TQMapIterator<TQString,TQString> tpc = mSender->mPasswdCache.find( ti->name );
1088 TQString tpwd = ( tpc != mSender->mPasswdCache.end() )?(*tpc):TQString();
1090 if ( ti->passwd().isEmpty() )
1091 ti->setPasswd( tpwd );
1093 if( (ti->user.isEmpty() || ti->passwd().isEmpty()) &&
1094 ti->authType !=
"GSSAPI" )
1100 TQString passwd = ti->passwd();
1101 result = TDEIO::PasswordDialog::getNameAndPassword(ti->user, passwd,
1102 &b, i18n(
"You need to supply a username and a password to use this "
1103 "SMTP server."),
false, TQString(), ti->name, TQString());
1105 if ( result != TQDialog::Accepted )
1110 if (
int id = KMTransportInfo::findTransport(ti->name)) {
1111 ti->setPasswd( passwd );
1112 ti->writeConfig(
id);
1115 mSender->mPasswdCache[ti->name] = passwd;
1118 destination.setUser(ti->user);
1119 destination.setPass(ti->passwd());
1122 if (!mSlave || !mInProcess)
1124 TDEIO::MetaData slaveConfig;
1125 slaveConfig.insert(
"tls", (ti->encryption ==
"TLS") ?
"on" :
"off");
1126 if (ti->auth) slaveConfig.insert(
"sasl", ti->authType);
1127 mSlave = TDEIO::Scheduler::getConnectedSlave(destination, slaveConfig);
1138 mMessageLength = mMessage.size();
1141 if ( mMessageLength )
1144 query +=
"&size=" + TQString::number( tqRound( mMessageLength * 1.05 ) );
1146 destination.setPath(
"/send");
1147 destination.setQuery( query );
1149 mJob = TDEIO::put( destination, -1,
false,
false,
false );
1154 mJob->addMetaData(
"lf2crlf+dotstuff",
"slave" );
1155 TDEIO::Scheduler::assignJobToSlave(mSlave, mJob);
1156 connect(mJob, TQ_SIGNAL(result(TDEIO::Job *)),
this, TQ_SLOT(result(TDEIO::Job *)));
1157 connect(mJob, TQ_SIGNAL(dataReq(TDEIO::Job *, TQByteArray &)),
1158 this, TQ_SLOT(dataReq(TDEIO::Job *, TQByteArray &)));
1164void KMSendSMTP::cleanup() {
1174 TDEIO::Scheduler::disconnectSlave(mSlave);
1181void KMSendSMTP::abort() {
1186void KMSendSMTP::doFinish() {
1190void KMSendSMTP::dataReq(TDEIO::Job *, TQByteArray &array)
1193 const int chunkSize = TQMIN( mMessageLength - mMessageOffset, 32*1024 );
1194 if ( chunkSize > 0 ) {
1195 array.duplicate(mMessage.data() + mMessageOffset, chunkSize);
1196 mMessageOffset += chunkSize;
1202 mSender->emitProgressInfo( mMessageOffset );
1205void KMSendSMTP::result(TDEIO::Job *_job)
1213 if (_job->error() == TDEIO::ERR_SLAVE_DIED) mSlave = 0;
1214 failed(_job->errorString());
1221void KMSendSMTP::slaveError(TDEIO::Slave *aSlave,
int error,
const TQString &errorMsg)
1223 if (aSlave == mSlave)
1225 if (error == TDEIO::ERR_SLAVE_DIED) mSlave = 0;
1228 failed(TDEIO::buildErrorString(error, errorMsg));
1233#include "kmsender.moc"
1234#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.
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.
KMMessage * unencryptedMsg() const
Returns an unencrypted copy of this message or 0 if none exists.
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.