[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kmail-devel
Subject:    PATCH: Non-blocking sending
From:       Don Sanders <sanders () kde ! org>
Date:       2001-04-01 1:17:36
[Download RAW message or body]

Here is an updated non-blocking sending patch. If I don't find any problems 
soon I plan to commit it to cvs (at long last).

On Monday 19 March 2001 13:45, Don Sanders wrote:
> Try the non-blocking smtp patch.
>
> Outstanding issues:
>
> I'm having trouble preventing lines that start with a dot "." from being
> mangled.

Fixed.

> Cancelling the sending of a mail doesn't take effect immediately.

Fixed.

> I noticed a problem when queueing mails. Changing the smtp server caused
> the smtp server in the preferences to be changed.

Fixed.

> I haven't tested sendmail since I started making changes.

Still got to do that.

> The flow of execution is getting too complicated, could make debugging
> difficult.

Still true unfortunately. I tried to simplify things.

> Would be nice to support pop before sending for authentication.

I guess that Makefile.am change included in the patch might be a little stale.

BFN,
Don.

["non-blocking-sending2.diff" (text/x-c++)]

Index: kmsender.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmsender.cpp,v
retrieving revision 1.83
diff -u -b -r1.83 kmsender.cpp
--- kmsender.cpp	2000/11/01 11:31:09	1.83
+++ kmsender.cpp	2001/04/01 01:10:05
@@ -1,11 +1,9 @@
 // kmsender.cpp
 
 
-#ifndef KRN
 #include "kmfoldermgr.h"
 #include "kmglobal.h"
 #include "kmfolder.h"
-#endif
 
 #include "kmsender.h"
 #include "kmmessage.h"
@@ -13,6 +11,7 @@
 #include "kmiostatusdlg.h"
 #include "kbusyptr.h"
 #include "kmaccount.h"
+#include "smtp.h"
 
 #include <kdebug.h>
 #include <kconfig.h>
@@ -22,10 +21,6 @@
 #include <qregexp.h>
 #include <qdialog.h>
 
-#ifdef KRN
-#include <kapp.h>
-#endif
-
 #include <assert.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -45,32 +40,27 @@
 
 #define SENDER_GROUP "sending mail"
 
-/** uncomment the following line for SMTP debug output */
-//#define SMTP_DEBUG_OUTPUT
-
-#define MSG_BLOCK_SIZE 1024
-
 //-----------------------------------------------------------------------------
 KMSender::KMSender()
 {
+  kdDebug() << "KMSender::KMSender()" << endl;
   mSendDlg = NULL;
   mSendProc = NULL;
   mMsgSendProc = NULL;
   mSendProcStarted = FALSE;
   mSendInProgress = FALSE;
   mCurrentMsg = NULL;
+  labelDialog = 0;
   readConfig();
   quitOnDone = false;
-  labelDialog = new QDialog(0);
-  label = new QLabel(labelDialog);
-  labelDialog->setCaption("KMail");
-  labelDialog->setIcon(kapp->miniIcon());
+  mSendAborted = false;
 }
 
 
 //-----------------------------------------------------------------------------
 KMSender::~KMSender()
 {
+  kdDebug() << "KMSender::~KMSender()" << endl;
   writeConfig(FALSE);
   if (mSendProc) delete mSendProc;
   if (labelDialog) delete labelDialog;
@@ -80,6 +70,7 @@
 void
 KMSender::setStatusMsg(const QString &msg)
 {
+   if (labelDialog)
    label->setText( msg );
    emit statusMsg( msg);
 }
@@ -87,6 +78,8 @@
 //-----------------------------------------------------------------------------
 void KMSender::readConfig(void)
 {
+  kdDebug() << "KMSender::readConfig" << endl;
+
   QString str;
   KConfig* config = kapp->config();
 
@@ -109,6 +102,8 @@
 //-----------------------------------------------------------------------------
 void KMSender::writeConfig(bool aWithSync)
 {
+  kdDebug() << "KMSender::writeConfig" << endl;
+
   KConfig* config = kapp->config();
   config->setGroup(SENDER_GROUP);
 
@@ -150,7 +145,6 @@
 //-----------------------------------------------------------------------------
 bool KMSender::send(KMMessage* aMsg, short sendNow)
 {
-#ifndef KRN
   int rc;
 
   //assert(aMsg != NULL);
@@ -206,9 +200,6 @@
   kernel->outboxFolder()->close();
 
   return rc;
-#else
-  return true;
-#endif
 }
 
 
@@ -223,7 +214,6 @@
 //-----------------------------------------------------------------------------
 bool KMSender::sendQueued(void)
 {
-#ifndef KRN
   if (!settingsOk()) return FALSE;
 
   if (mSendInProgress)
@@ -242,25 +232,22 @@
 
   // create a sender
   if (mSendProc) delete mSendProc;
-  if (mMethod == smMail) mSendProc = new KMSendSendmail(this);
-  else if (mMethod == smSMTP) mSendProc = new KMSendSMTP(this);
+  if (mMethod == smMail) mSendProc = new KMSendSendmail(this,mMailer);
+  else if (mMethod == smSMTP) mSendProc = new KMSendSMTP(this,mSmtpHost,mSmtpPort);
   else mSendProc = NULL;
   assert(mSendProc != NULL);
   connect(mSendProc,SIGNAL(idle()),SLOT(slotIdle()));
+  connect(mSendProc,SIGNAL(started(bool)),this,SLOT(sendProcStarted(bool)));
 
   // start sending the messages
   doSendMsg();
   return TRUE;
-#else
-  return TRUE;
-#endif
 }
 
 
 //-----------------------------------------------------------------------------
 void KMSender::doSendMsg()
 {
-#ifndef KRN
   assert(mSendProc != NULL);
   bool someSent = mCurrentMsg;
 
@@ -276,10 +263,8 @@
   // Would be more efficient to only do this when the mail transport
   // (server or port) has changed
   if (mMsgSendProc) {
-    mMsgSendProc->finish();
-    delete mMsgSendProc;
+    mMsgSendProc->finish(true);
     mMsgSendProc = 0;
-    restoreTransportSettings();
     mSendProcStarted = FALSE;
   }
 
@@ -299,10 +284,16 @@
   {
     kernel->serverReady (false); //sven - stop IPC
 
-    label->setText(i18n("Initiating sender process..."));
+    if (!labelDialog) {
+      labelDialog = new QDialog(0, "sendinglabel", false, WDestructiveClose );
+      label = new QLabel(labelDialog);
+      labelDialog->setCaption("KMail");
+      labelDialog->setIcon(kapp->miniIcon());
+      connect(labelDialog,SIGNAL(destroyed()),this,SLOT(slotAbortSend()));
     label->resize(400, label->sizeHint().height());
+      label->setText(i18n("Initiating sender process..."));
     labelDialog->show();
-    kapp->processEvents(50); // Not sure this is safe -sanders
+    }
 
     // Run the precommand if there is one
     setStatusMsg(i18n(QString("Executing precommand ") + mPrecommand));
@@ -319,36 +310,53 @@
   QString msgTransport = mCurrentMsg->headerField("X-KMail-Transport");
   if (!msgTransport.isEmpty()  && (msgTransport != mMethodStr)) {
     if (mSendProcStarted && mSendProc) {
-      mSendProc->finish();
+      mSendProc->finish(false);
       mSendProcStarted = FALSE;
     }
 
-    saveTransportSettings();
-
-    mMsgSendProc = parseTransportFromString(mCurrentMsg->headerField("X-KMail-Transport"));
-    mMethodStr = transportString();
+    mMsgSendProc = createSendProcFromString(mCurrentMsg->headerField("X-KMail-Transport"));
+    mMethodStr = msgTransport;
 
-    if (!mMsgSendProc || !mMsgSendProc->start()) {
-      if (mMsgSendProc) {
-	mMsgSendProc->finish();
-	delete mMsgSendProc;
+    if (!mMsgSendProc)
+      msgSendProcStarted(false);
+    else {
+	connect(mMsgSendProc,SIGNAL(idle()),SLOT(slotIdle()));
+	connect(mMsgSendProc,SIGNAL(started(bool)),this,SLOT(msgSendProcStarted(bool)));
+	mMsgSendProc->start();
       }
+  }
+  else if (!mSendProcStarted)
+    mSendProc->start();
       else
+    doSendMsgAux();
+}
+
+void KMSender::msgSendProcStarted(bool success)
+{
+  if (!success) {
+    if (mMsgSendProc)
+       mMsgSendProc->finish(true);
+    else
 	setStatusMsg(i18n("Unrecognised transport protocol, could not send message."));
       mMsgSendProc = 0;
       mSendProcStarted = false;
-      restoreTransportSettings();
       cleanup();
       return;
-    }
-    connect(mMsgSendProc,SIGNAL(idle()),SLOT(slotIdle()));
   }
-  else if (!mSendProcStarted)
-    if (!mSendProc->start())
-    {
+  doSendMsgAux();
+}
+
+void KMSender::sendProcStarted(bool success)
+{
+  if (!success) {
       cleanup();
       return;
     }
+  doSendMsgAux();
+}
+
+void KMSender::doSendMsgAux()
+{
   mSendProcStarted = TRUE;
   mSendInProgress = TRUE;
 
@@ -381,17 +389,15 @@
   }
   // Do *not* add code here, after send(). It can happen that this method
   // is called recursively if send() emits the idle signal directly.
-#endif
 }
 
 
 //-----------------------------------------------------------------------------
 void KMSender::cleanup(void)
 {
-#ifndef KRN
   assert(mSendProc!=NULL);
 
-  if (mSendProcStarted) mSendProc->finish();
+  if (mSendProcStarted) mSendProc->finish(false);
   mSendProcStarted = FALSE;
   mSendInProgress = FALSE;
   kernel->sentFolder()->close();
@@ -402,13 +408,17 @@
   else kernel->outboxFolder()->compact();
 
   kernel->serverReady (true); // sven - enable ipc
-  labelDialog->hide();
+  mSendAborted = false;
+  if (labelDialog) {
+      disconnect(labelDialog,SIGNAL(destroyed()),this,SLOT(slotAbortSend()));
+      delete labelDialog;
+      labelDialog = 0;
+      //      labelDialog->hide();
+  }
   if (quitOnDone)
   {
-    kdDebug() << "Done sending messages." << endl;
     kapp->quit();
   }
-#endif
 }
 
 
@@ -419,10 +429,22 @@
 }
 
 //-----------------------------------------------------------------------------
+void KMSender::slotAbortSend()
+{
+    labelDialog = 0;
+    mSendAborted = true;
+    if (mMsgSendProc)
+	mMsgSendProc->abort();
+    else
+	mSendProc->abort();
+}
+
+//-----------------------------------------------------------------------------
 void KMSender::slotIdle()
 {
   assert(mSendProc != NULL);
-  //assert(!mSendProc->sending());
+
+  if (!mSendAborted) {
   if (mMsgSendProc) {
     if (mMsgSendProc->sendOk()) {
       doSendMsg();
@@ -433,25 +455,30 @@
     doSendMsg();
     return;
   }
+  }
 
 
   // sending of message failed
   QString msg;
+  QString errString;
+  if (mMsgSendProc)
+      errString = mMsgSendProc->message();
+  else
+      errString = mSendProc->message();
+  
   msg = i18n("Sending failed:\n%1\n"
         "The message will stay in the 'outbox' folder and will be resent.\n"
         "Please remove it from there if you do not want the message to\n"
 		"be resent.\n\n"
 	"The following transport protocol was used:\n  %2")
-    .arg(mSendProc->message())
+    .arg(errString)
     .arg(mMethodStr);
   KMessageBox::information(0,msg);
 
   if (mMsgSendProc) {
-    mMsgSendProc->finish();
-    delete mMsgSendProc;
+    mMsgSendProc->finish(true);
     mMsgSendProc = 0;
     mSendProcStarted = false;
-    restoreTransportSettings();
   }
   cleanup();
 }
@@ -499,30 +526,9 @@
 
 
 //-----------------------------------------------------------------------------
-void KMSender::saveTransportSettings(void)
+KMSendProc* KMSender::createSendProcFromString(QString transport)
 {
-  mOldMethod = mMethod;
-  mOldMailer = mMailer;
-  mOldSmtpHost = mSmtpHost;
-  mOldSmtpPort = mSmtpPort;
-}
-
-
-//-----------------------------------------------------------------------------
-void KMSender::restoreTransportSettings(void)
-{
-  mMethod = mOldMethod;
-  mMailer = mOldMailer;
-  mSmtpHost = mOldSmtpHost;
-  mSmtpPort = mOldSmtpPort;
-}
-
-
-//-----------------------------------------------------------------------------
-KMSendProc* KMSender::parseTransportFromString(QString transport)
-{
   if (transport.left(7) == "smtp://") { // to i18n or not to i18n?
-    mMethod = smSMTP;
     QString serverport = transport.mid(7);
     QString server = serverport;
     QString port = "25";
@@ -531,16 +537,14 @@
       server = serverport.left(colon);
       port = serverport.mid(colon + 1);
     }
-    mSmtpHost = server;
-    mSmtpPort = port.toInt();
-    return new KMSendSMTP(this);
+    return new KMSendSMTP(this,server,port.toInt());
   }
   else if (transport.left(7) == "file://") {
-    mMethod = smMail;
-    mMailer = transport.mid(7);
-    return new KMSendSendmail(this);
+    return new KMSendSendmail(this,transport.mid(7));
   }
-  else return 0;
+  else {
+    return 0;
+  }
 }
 
 //-----------------------------------------------------------------------------
@@ -563,6 +567,7 @@
   initMetaObject();
   mSender = aSender;
   preSendInit();
+  mMsg = i18n("operation aborted by user.");
 }
 
 //-----------------------------------------------------------------------------
@@ -582,14 +587,16 @@
 }
 
 //-----------------------------------------------------------------------------
-bool KMSendProc::start(void)
+void KMSendProc::start(void)
 {
-  return TRUE;
+  emit started(true);
 }
 
 //-----------------------------------------------------------------------------
-bool KMSendProc::finish(void)
+bool KMSendProc::finish(bool destructive)
 {
+    if (destructive)
+	delete this;
   return TRUE;
 }
 
@@ -610,11 +617,11 @@
     {
       if (toCRLF) str += '\r';
       str += c;
-      if (noSingleDot && aStr[pos+1]=='.' && aStr[pos+2]=='\n')
+
+      if (noSingleDot && aStr[pos+1]=='.')
       {
 	pos++;
-	str += '.';
-        str += ' ';
+	str += "..";
       }
     }
     else str += c;
@@ -627,7 +634,6 @@
 void KMSendProc::statusMsg(const QString& aMsg)
 {
   if (mSender) mSender->setStatusMsg(aMsg);
-  kapp->processEvents(50); // Not sure this is safe -sanders
 }
 
 //-----------------------------------------------------------------------------
@@ -667,8 +673,8 @@
 
 //=============================================================================
 //=============================================================================
-KMSendSendmail::KMSendSendmail(KMSender* aSender):
-  KMSendSendmailInherited(aSender)
+KMSendSendmail::KMSendSendmail(KMSender* aSender, QString mailer):
+  KMSendSendmailInherited(aSender), mMailer(mailer)
 {
   initMetaObject();
   mMailerProc = NULL;
@@ -681,9 +687,9 @@
 }
 
 //-----------------------------------------------------------------------------
-bool KMSendSendmail::start(void)
+void KMSendSendmail::start(void)
 {
-  if (mSender->mailer().isEmpty())
+  if (mMailer.isEmpty())
   {
     QString str = i18n("Please specify a mailer program\n"
 				    "in the settings.");
@@ -696,7 +702,7 @@
     .arg(str + "\n")
     .arg("sendmail://");
     KMessageBox::information(0,msg);
-    return FALSE;
+    emit started(false);
   }
 
   if (!mMailerProc)
@@ -710,24 +716,37 @@
     connect(mMailerProc,SIGNAL(receivedStderr(KProcess*,char*,int)),
 	    this, SLOT(receivedStderr(KProcess*, char*, int)));
   }
-  return TRUE;
+  emit started(true);
 }
 
 //-----------------------------------------------------------------------------
-bool KMSendSendmail::finish(void)
+bool KMSendSendmail::finish(bool destructive)
 {
   if (mMailerProc) delete mMailerProc;
   mMailerProc = NULL;
+  if (destructive)
+      delete this;
   return TRUE;
 }
 
 //-----------------------------------------------------------------------------
+void KMSendSendmail::abort()
+{
+  if (mMailerProc) delete mMailerProc;
+  mMailerProc = NULL;
+  mSendOk = false;
+  mMsgStr = 0;
+  idle();
+}
+
+
+//-----------------------------------------------------------------------------
 bool KMSendSendmail::send(KMMessage* aMsg)
 {
   QString bccStr;
 
   mMailerProc->clearArguments();
-  *mMailerProc << mSender->mailer();
+  *mMailerProc << mMailer;
   addRecipients(aMsg->headerAddrField("To"));
   if (!aMsg->cc().isEmpty()) addRecipients(aMsg->headerAddrField("Cc"));
 
@@ -744,7 +763,7 @@
   if (!mMailerProc->start(KProcess::NotifyOnExit,KProcess::All))
   {
     KMessageBox::information(0,i18n("Failed to execute mailer program") +
-				    mSender->mailer());
+				    mMailer);
     return FALSE;
   }
   mMsgPos  = mMsgStr.data();
@@ -810,11 +829,11 @@
 
 //=============================================================================
 //=============================================================================
-KMSendSMTP::KMSendSMTP(KMSender* aSender):
-  KMSendSMTPInherited(aSender)
+KMSendSMTP::KMSendSMTP(KMSender* aSender, QString smtpHost, 
+		       unsigned short int smtpPort ):
+    KMSendSMTPInherited(aSender), mSmtpHost(smtpHost), mSmtpPort(smtpPort)
 {
-  mClient = NULL;
-  mOldHandler = 0;
+  smtp = 0;
 }
 
 //-----------------------------------------------------------------------------
@@ -823,63 +842,34 @@
 }
 
 //-----------------------------------------------------------------------------
-bool KMSendSMTP::start(void)
+void KMSendSMTP::start(void)
 {
-  int replyCode;
-
-  mOldHandler = signal(SIGALRM, SIG_IGN);
-  mClient = new DwSmtpClient;
-  assert(mClient != NULL);
-
   statusMsg(i18n("connecting to server"));
-  mClient->Open(mSender->smtpHost(), mSender->smtpPort()); // Open connection
-  if(!mClient->IsOpen()) // Check if connection succeded
-  {
-    QString str;
-    QString msg;
-    str = i18n("Cannot open SMTP connection to\n"
-			       "host %1 for sending:\n%2")
-		.arg(mSender->smtpHost())
-		.arg((const char*)mClient->Response().c_str());
-    msg = i18n("Sending failed:\n%1\n"
-	"The message will stay in the 'outbox' folder and will be resent.\n"
-        "Please remove it from there if you do not want the message to\n"
-		"be resent.\n\n"
-	"The following transport protocol was used:\n  %2")
-    .arg(str)
-    .arg(QString("smtp://%1:%2").arg(mSender->smtpHost()).arg(mSender->smtpPort()));
-
-  KMessageBox::information(0,msg);
-    return FALSE;
-  }
-  kapp->processEvents(50); // not sure this is safe -sanders
+  emit started(true);
+}
 
-  smtpInCmd("HELO");
-  replyCode = mClient->Helo(); // Send HELO command
-  smtpDebug("HELO");
-  if (replyCode != 250) return smtpFailed("HELO", replyCode);
+//-----------------------------------------------------------------------------
+bool KMSendSMTP::finish(bool destructive)
+{
+  if (smtp)
+    smtp->quit();
+  smtp = 0;
+  if (destructive)
+      delete this;
   return TRUE;
 }
 
 //-----------------------------------------------------------------------------
-bool KMSendSMTP::finish(void)
+void KMSendSMTP::abort()
 {
-  if (mClient->ReplyCode() != 0)
-  {
-    int replyCode = mClient->Quit(); // Send QUIT command
-    smtpDebug("QUIT");
-    if(replyCode != 221)
-      return smtpFailed("QUIT", replyCode);
-  }
-
-  if (mClient->Close() != 0)
-    KMessageBox::information(0,i18n("Cannot close SMTP connection."));
-
-  signal(SIGALRM, mOldHandler);
-  delete mClient;
-  mClient = NULL;
-
-  return TRUE;
+  disconnect( smtp, SIGNAL(error(const QString&, const QString&)),
+	      this, SLOT(smtpFailed(const QString&, const QString& )) );
+  disconnect( smtp, SIGNAL(success()),
+	      this, SIGNAL(idle()) );
+  if (smtp)
+    smtp->quit();
+  smtp = 0;
+  idle();
 }
 
 
@@ -887,7 +877,6 @@
 bool KMSendSMTP::send(KMMessage *msg)
 {
   mSendOk = smtpSend(msg);
-  emit idle();
   return mSendOk;
 }
 
@@ -896,17 +885,12 @@
 bool KMSendSMTP::smtpSend(KMMessage* aMsg)
 {
   QString str, msgStr, bccStr;
-  int replyCode;
   KMIdentity ident( i18n( "Default" ));
   ident.readConfig();
 
   assert(aMsg != NULL);
+  recipients.clear();
 
-  smtpInCmd("MAIL");
-  replyCode = mClient->Mail(ident.emailAddr());
-  smtpDebug("MAIL");
-  if(replyCode != 250) return smtpFailed("MAIL", replyCode);
-
   if (!addRecipients(aMsg->headerAddrField("To"))) return FALSE;
 
   if (!aMsg->cc().isEmpty())
@@ -919,23 +903,21 @@
     aMsg->removeHeaderField("Bcc");
   }
 
-  kapp->processEvents(50); // not sure this is safe -sanders
+  msgStr = prepareStr(aMsg->asString(), TRUE );
+  if (!smtp) {
+      smtp = new Smtp( ident.emailAddr(), recipients,
+		       msgStr,
+		       mSmtpHost,
+		       mSmtpPort );
+      connect( smtp, SIGNAL(error(const QString&, const QString&)),
+	       this, SLOT(smtpFailed(const QString&, const QString& )) );
+      connect( smtp, SIGNAL(success()),
+	       this, SIGNAL(idle()) );
+  } else {
+      smtp->send( ident.emailAddr(), recipients, msgStr );
+  }
 
-  smtpInCmd("DATA");
-  replyCode = mClient->Data(); // Send DATA command
-  smtpDebug("DATA");
-  if(replyCode != 354)
-    return smtpFailed("DATA", replyCode);
-
-  statusMsg(i18n("transmitting message"));
-  msgStr = prepareStr(aMsg->asString(), TRUE, FALSE);
-  replyCode = mClient->SendData((const char*)msgStr);
   if (!bccStr.isEmpty()) aMsg->setBcc(bccStr);
-
-  smtpDebug("<body>");
-  if(replyCode != 250 && replyCode != 251)
-    return smtpFailed("<body>", replyCode);
-
   return TRUE;
 }
 
@@ -943,39 +925,26 @@
 //-----------------------------------------------------------------------------
 bool KMSendSMTP::addOneRecipient(const QString aRcpt)
 {
-  int replyCode;
   if (aRcpt.isEmpty()) return TRUE;
 
-  smtpInCmd("RCPT");
-  replyCode = mClient->Rcpt(aRcpt);
-  smtpDebug("RCPT");
-
-  if(replyCode != 250 && replyCode != 251)
-    return smtpFailed("RCPT", replyCode);
+  recipients.append( aRcpt );
   return TRUE;
 }
 
 
 //-----------------------------------------------------------------------------
-bool KMSendSMTP::smtpFailed(const char* inCommand,
-			  int replyCode)
+void KMSendSMTP::smtpFailed(const QString &command,
+			    const QString &response)
 {
-  QString str;
-  QString errorStr = mClient->Response().c_str();
-
-  if (replyCode==0 && (!errorStr || !*errorStr))
-    errorStr = i18n("network error");
-
-  str = i18n("a SMTP error occured.\n"
+  failed( i18n("a SMTP error occured.\n"
 			     "Command: %1\n"
-			     "Response: %2\n"
-			     "Return code: %3")
-		.arg(inCommand)
-		.arg(!errorStr.isEmpty() ? errorStr : i18n("(nothing)"))
-		.arg(replyCode);
-  mMsg = str;
-
-  return FALSE;
+	     "Response: %2")
+	  .arg(command)
+	  .arg(response) );
+  if (smtp)
+      delete smtp;
+  smtp = 0;
+  idle();
 }
 
 
@@ -985,17 +954,6 @@
   QString str;
   str = i18n("Sending SMTP command: %1").arg(inCommand);
   statusMsg(str);
-}
-
-
-//-----------------------------------------------------------------------------
-void KMSendSMTP::smtpDebug(const char* /*inCommand*/)
-{
-#ifdef SMTP_DEBUG_OUTPUT
-  const char* errorStr = mClient->Response().c_str();
-  int replyCode = mClient->ReplyCode();
-  kdDebug() << "SMTP '" << inCommand << "': rc=" << replyCode << ", msg='" << errorStr << "'" << endl;
-#endif
 }
 
 
Index: kmsender.h
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmsender.h,v
retrieving revision 1.27
diff -u -b -r1.27 kmsender.h
--- kmsender.h	2000/11/01 11:31:09	1.27
+++ kmsender.h	2001/04/01 01:10:05
@@ -8,6 +8,7 @@
 #include <mimelib/string.h>
 #include <mimelib/utility.h>
 #include <qstring.h>
+#include <qstringlist.h>
 #include <qobject.h>
 #include <qlabel.h>
 
@@ -21,6 +22,7 @@
 class KMSendProc;
 class QStrList;
 class QDialog;
+class Smtp;
 
 class KMSender: public QObject
 {
@@ -105,10 +107,20 @@
 protected slots:
   virtual void slotIdle();
 
+  /** abort sending of the current message */
+  virtual void slotAbortSend();
+
+  /** initialization sequence has finised */
+  virtual void msgSendProcStarted(bool success);
+  virtual void sendProcStarted(bool success);
+
 protected:
   /** handle sending of messages */
   virtual void doSendMsg();
 
+  /** second part of handling sending of messages */
+  virtual void doSendMsgAux();
+
   /** cleanup after sending */
   virtual void cleanup(void);
 
@@ -117,25 +129,19 @@
       Returns TRUE if everything is Ok. */
   virtual bool settingsOk(void) const;
 
-  /** Save mMethod, mMail, mSmtpHost, and mSmtpPort */
-  virtual void saveTransportSettings(void);
-
-  /** Restore saved mMethod, mMail, mSmtpHost, and mSmtpPort */
-  virtual void restoreTransportSettings(void);
-
   /** Parse protocol '://' (host port? | mailer) string and 
       set transport settings */
-  virtual KMSendProc* parseTransportFromString(QString transport); 
+  virtual KMSendProc* createSendProcFromString(QString transport);
 
 private:
-  Method mMethod, mOldMethod;
+  Method mMethod;
   bool mSendImmediate, mSendQuotedPrintable;
-  QString mMailer, mOldMailer;
-  QString mSmtpHost, mOldSmtpHost;
-  unsigned short int mSmtpPort, mOldSmtpPort;
+  QString mMailer;
+  QString mSmtpHost;
+  unsigned short int mSmtpPort;
   QString mPrecommand;
 
-  bool mSentOk;
+  bool mSentOk, mSendAborted;
   QString mErrorMsg;
   KMIOStatusDlg* mSendDlg;
   KMSendProc *mSendProc, *mMsgSendProc;
@@ -159,7 +165,7 @@
   KMSendProc(KMSender*);
 
   /** Initialize sending of one or more messages. */
-  virtual bool start(void);
+  virtual void start(void);
 
   /** Initializes variables directly before send() is called. */
   virtual void preSendInit(void);
@@ -168,8 +174,11 @@
   virtual bool send(KMMessage* msg) = 0;
 
   /** Cleanup after sending messages. */
-  virtual bool finish(void);
+  virtual bool finish(bool destructive);
 
+  /** Abort sending the current message. Sets mSending to false */
+  virtual void abort() = 0;
+
   /** Returns TRUE if send was successful, and FALSE otherwise.
       Returns FALSE if sending is still in progress. */
   bool sendOk(void) const { return mSendOk; }
@@ -184,6 +193,10 @@
   /** Emitted when the current message is sent or an error occured. */
   void idle();
 
+  /** Emitted when the initialization sequence has finished */
+  void started(bool);
+
+
 protected:
   /** Called to signal a transmission error. The sender then
     calls finish() and terminates sending of messages. 
@@ -223,11 +236,12 @@
 {
   Q_OBJECT
 public:
-  KMSendSendmail(KMSender*);
+  KMSendSendmail(KMSender*,QString);
   virtual ~KMSendSendmail();
-  virtual bool start(void);
+  virtual void start(void);
   virtual bool send(KMMessage* msg);
-  virtual bool finish(void);
+  virtual bool finish(bool destructive);
+  virtual void abort();
 
 protected slots:
   void receivedStderr(KProcess*,char*,int);
@@ -241,28 +255,34 @@
   char* mMsgPos;
   int mMsgRest;
   KProcess* mMailerProc;
+  QString mMailer;
 };
 
 //-----------------------------------------------------------------------------
 #define KMSendSMTPInherited KMSendProc
 class KMSendSMTP: public KMSendProc
 {
+  Q_OBJECT
 public:
-  KMSendSMTP(KMSender*);
+  KMSendSMTP(KMSender*,QString,unsigned short int);
   virtual ~KMSendSMTP();
-  virtual bool start(void);
+  virtual void start(void);
   virtual bool send(KMMessage* msg);
-  virtual bool finish(void);
+  virtual bool finish(bool destructive);
+  virtual void abort();
+
+public slots:
+  virtual void smtpFailed(const QString&, const QString &);
 
 protected:
   virtual bool smtpSend(KMMessage* msg);
-  virtual bool smtpFailed(const char* inCommand, int replyCode);
-  virtual void smtpDebug(const char* inCommand);
   virtual void smtpInCmd(const char* inCommand);
   virtual bool addOneRecipient(const QString aRecipient);
   
-  void (*mOldHandler)(int);
-  DwSmtpClient* mClient;
+  Smtp *smtp;
+  QStringList recipients;
+  QString mSmtpHost;
+  unsigned short int mSmtpPort;
 };
 
 #endif /*kmsender_h*/
Index: Makefile.am
===================================================================
RCS file: /home/kde/kdenetwork/kmail/Makefile.am,v
retrieving revision 1.102
diff -u -b -r1.102 Makefile.am
--- Makefile.am	2001/01/25 21:46:28	1.102
+++ Makefile.am	2001/04/01 01:10:05
@@ -28,7 +28,8 @@
 		kmacctexppop.cpp configuredialog.cpp colorlistbox.cpp \
                 kmkernel.cpp kmailIface.skel kmailIface.stub main.cpp \
 		accountdialog.cpp kmfldsearch.cpp addtoaddressbook.cpp \
-		kmdisplayvcard.cpp vcard.cpp md5.c
+		kmdisplayvcard.cpp vcard.cpp md5.c \
+		smtp.cpp smtp.h
 
 
 include_HEADERS = kmailIface.h

["smtp.h" (text/x-c++)]

/****************************************************************************
**
** This file is a modified version of part of an example program for Qt.
** This file may be used, distributed and modified without limitation.
**
** Don Sanders <sanders@kde.org>
**
*****************************************************************************/

#ifndef SMTP_H
#define SMTP_H

#include <qobject.h>
#include <qstring.h>
#include <qstringlist.h>

class QSocket;
class QTextStream;

class Smtp : public QObject
{
    Q_OBJECT

public:
    Smtp( const QString &, const QStringList &, const QString &, const QString &,
          unsigned short int );
    ~Smtp();
    void send( const QString &, const QStringList &, const QString & );
    void quit();


signals:
    void success();
    void status( const QString & );
    void error( const QString &command, const QString &response );

private slots:
    void readyRead();
    void connected();
    void deleteMe();
    void socketError(int err);
    void emitError();

private:
    enum State {
	Init,
	Mail,
	Rcpt,
	Data,
	Body,
	Success,
	Quit,
	Close
    };

    QString message;
    QString from;
    QStringList rcpt;
    QSocket *socket;
    QTextStream * t;
    int state;
    QString response, responseLine;
    bool skipReadResponse;
    QString command;
};

#endif

["smtp.cpp" (text/x-c)]

/****************************************************************************
**
** This file is a modified version of part of an example program for Qt.
** This file may be used, distributed and modified without limitation.
**
** Don Sanders <sanders@kde.org>
**
*****************************************************************************/

#include "smtp.h"

#include <qtextstream.h>
#include <qsocket.h>
#include <qtimer.h>
#include <kapp.h>
#include <kmessagebox.h>
#include <klocale.h>

Smtp::Smtp( const QString &from, const QStringList &to,
	    const QString &aMessage,
	    const QString &server,
	    unsigned short int port )
{
    skipReadResponse = false;
    socket = new QSocket( this );
    connect ( socket, SIGNAL( readyRead() ),
	      this, SLOT( readyRead() ) );
    connect ( socket, SIGNAL( connected() ),
	      this, SLOT( connected() ) );
    connect ( socket, SIGNAL( error(int) ),
	      this, SLOT( socketError(int) ) );

    message = aMessage;
    
    this->from = from;
    rcpt = to;

    state = Init;
    command = "";

    emit status( i18n( "Connecting to %1" ).arg( server ) );

    socket->connectToHost( server, port );
    t = new QTextStream( socket );
}


Smtp::~Smtp()
{
    if (t)
	delete t;
    if (socket)
	delete socket;
}


void Smtp::send( const QString &from, const QStringList &to,
	    const QString &aMessage )
{
    skipReadResponse = true;
    message = aMessage;
    this->from = from;
    rcpt = to;

    state = Mail;
    command = "";
    readyRead();
}


void Smtp::quit()
{
    skipReadResponse = true;
    state = Quit;
    command = "";
    readyRead();	
}


void Smtp::connected()
{
    emit status( i18n( "Connected to %1" ).arg( socket->peerName() ) );
}

void Smtp::socketError(int errorCode)
{
    command = "CONNECT";
    responseLine;
    switch ( errorCode ) {
        case QSocket::ErrConnectionRefused:
	    responseLine = i18n( "Connection refused." );
	    break;
        case QSocket::ErrHostNotFound:
	    responseLine = i18n( "Host Not Found." );
	    break;
        case QSocket::ErrSocketRead:
	    responseLine = i18n( "Error reading socket." );
	    break;
        default:
	    responseLine = i18n( "Internal error, unrecognized error." );
    }
    QTimer::singleShot( 0, this, SLOT(emitError()) );
}

void Smtp::emitError() {
    error( command, responseLine );
}

void Smtp::readyRead()
{
    if (!skipReadResponse) {
	// SMTP is line-oriented
	if ( !socket->canReadLine() )
	    return;

	do {
	    responseLine = socket->readLine();
	    response += responseLine;
	} while( socket->canReadLine() && responseLine[3] != ' ' );
	responseLine.truncate( 3 );
    }
    skipReadResponse = false;
	
    if ( state == Init && responseLine[0] == '2' ) {
	// banner was okay, let's go on
	command = "HELO there";
	*t << "HELO there\r\n";
	state = Mail;
    } else if ( state == Mail && responseLine[0] == '2' ) {
	// HELO response was okay (well, it has to be)
	command = "MAIL";
	*t << "MAIL FROM: <" << from << ">\r\n";
	state = Rcpt;
    } else if ( state == Rcpt && responseLine[0] == '2' && (rcpt.begin() != rcpt.end())) {
	command = "RCPT";
	*t << "RCPT TO: <" << *(rcpt.begin()) << ">\r\n";
	rcpt.remove( rcpt.begin() );
	if (rcpt.begin() == rcpt.end())
	    state = Data;
    } else if ( state == Data && responseLine[0] == '2' ) {
	command = "DATA";
	*t << "DATA\r\n";
	state = Body;
    } else if ( state == Body && responseLine[0] == '3' ) {
	command = "DATA";
	QString seperator = "";
	if (message[message.length() - 1] != '\n')
	    seperator = "\n";
	*t << message << seperator << ".\r\n";
	state = Success;
    } else if ( state == Success && responseLine[0] == '2' ) {
	QTimer::singleShot( 0, this, SIGNAL(success()) );
    } else if ( state == Quit && responseLine[0] == '2' ) {
	command = "QUIT";
	*t << "QUIT\r\n";
	// here, we just close.
	state = Close;
	emit status( tr( "Message sent" ) );
    } else if ( state == Close ) {
	// we ignore it
    } else {
	state = Close;
    }

    response = "";

    if ( state == Close ) {
	delete t;
	t = 0;
	delete socket;
	socket = 0;
	QTimer::singleShot( 0, this, SLOT(deleteMe()) );
    }
}


void Smtp::deleteMe()
{
    delete this;
}


_______________________________________________
Kmail Developers mailing list
Kmail@master.kde.org
http://master.kde.org/mailman/listinfo/kmail


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic