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> 
   17#include <tdeversion.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" 
   36#include "kmtransport.h" 
   37#include "kmfolderindex.h" 
   38#include "kmfoldermgr.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;
 
   80void KMSender::setStatusMsg(
const TQString &msg)
 
   83    mProgressItem->setStatus(msg);
 
   87void KMSender::readConfig(
void)
 
   90  TDEConfigGroup config(KMKernel::config(), SENDER_GROUP);
 
   92  mSendImmediate = config.readBoolEntry(
"Immediate", 
true);
 
   93  mSendQuotedPrintable = config.readBoolEntry(
"Quoted-Printable", 
true);
 
   98void 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();
 
  110bool KMSender::settingsOk()
 const 
  112  if (KMTransportInfo::availableTransports().isEmpty())
 
  114    KMessageBox::information(0,i18n(
"Please create an account for sending and try again."));
 
  120static 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() )
 
  128bool 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 )
 
  200void KMSender::outboxMsgAdded(
int idx)
 
  203    KMMsgBase* msg = kmkernel->outboxFolder()->getMsgBase(idx);
 
  206        mTotalBytes += msg->msgSize();
 
  211bool 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;
 
  249void KMSender::emitProgressInfo( 
int currentFileProgress )
 
  251  int percent = (mTotalBytes) ? ( 100 * (mSentBytes+currentFileProgress) / mTotalBytes ) : 0;
 
  252  if (percent > 100) percent = 100;
 
  253  mProgressItem->setProgress(percent);
 
  256static 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();
 
  279void 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)
 
  541bool 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;
 
  554void KMSender::sendProcStarted(
bool success)
 
  560      setStatusMsg(i18n(
"Unrecognized transport protocol. Unable to send message."));
 
  562    mSendProcStarted = 
false;
 
  570static 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 );
 
  580static 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" ) );
 
  595void 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."));
 
  629void KMSender::cleanup(
void)
 
  631  kdDebug(5006) << k_funcinfo << endl;
 
  632  if (mSendProc && mSendProcStarted) mSendProc->finish();
 
  634  mSendProcStarted = 
false;
 
  635  if (mSendInProgress) tdeApp->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();
 
  671void KMSender::slotAbortSend()
 
  676  if (mSendProc) mSendProc->abort();
 
  680void 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;
 
  768void KMSender::slotPrecommandFinished(
bool normalExit)
 
  772  if (normalExit) mSendProc->start();
 
  778void KMSender::setSendImmediate(
bool aSendImmediate)
 
  780  mSendImmediate = aSendImmediate;
 
  785void KMSender::setSendQuotedPrintable(
bool aSendQuotedPrintable)
 
  787  mSendQuotedPrintable = aSendQuotedPrintable;
 
  792KMSendProc* 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);
 
  851void 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;
 
  883KMSendProc::KMSendProc( KMSender * sender )
 
  893void KMSendProc::reset()
 
  897  mLastErrorMessage = TQString();
 
  901void KMSendProc::failed(
const TQString &aMsg)
 
  905  mLastErrorMessage = aMsg;
 
  909void KMSendProc::statusMsg(
const TQString& aMsg)
 
  911  if (mSender) mSender->setStatusMsg(aMsg);
 
  916KMSendSendmail::KMSendSendmail( KMSender * sender )
 
  917  : KMSendProc( sender ),
 
  926KMSendSendmail::~KMSendSendmail() {
 
  927  delete mMailerProc; mMailerProc = 0;
 
  930bool 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)));
 
  960void KMSendSendmail::doFinish() {
 
  965void KMSendSendmail::abort()
 
  974bool 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 );
 
  995void KMSendSendmail::wroteStdin(TDEProcess *proc)
 
 1004  len = (mMsgRest>1024 ? 1024 : mMsgRest);
 
 1008    mMailerProc->closeStdin();
 
 1014    mMailerProc->writeStdin(str,len);
 
 1021void KMSendSendmail::receivedStderr(TDEProcess *proc, 
char *buffer, 
int buflen)
 
 1025  mLastErrorMessage.replace(mLastErrorMessage.length(), buflen, buffer);
 
 1029void KMSendSendmail::sendmailExited(TDEProcess *proc)
 
 1032  mSendOk = (proc->normalExit() && proc->exitStatus()==0);
 
 1033  if (!mSendOk) failed(i18n(
"Sendmail exited abnormally."));
 
 1043KMSendSMTP::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 &)));
 
 1054KMSendSMTP::~KMSendSMTP()
 
 1056  if (mJob) mJob->kill();
 
 1059bool 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 &)));
 
 1165void KMSendSMTP::cleanup() {
 
 1175    TDEIO::Scheduler::disconnectSlave(mSlave);
 
 1182void KMSendSMTP::abort() {
 
 1187void KMSendSMTP::doFinish() {
 
 1191void 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 );
 
 1206void KMSendSMTP::result(TDEIO::Job *_job)
 
 1214    if (_job->error() == TDEIO::ERR_SLAVE_DIED) mSlave = 0;
 
 1215    failed(_job->errorString());
 
 1222void 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.
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.