Bug 136360 - request for SMTP authentication support
Summary: request for SMTP authentication support
Status: RESOLVED FIXED
Alias: None
Product: mailody
Classification: Miscellaneous
Component: general (show other bugs)
Version: unspecified
Platform: Ubuntu Linux
: NOR wishlist
Target Milestone: ---
Assignee: Tom Albers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-10-26 23:42 UTC by Danni Matzk
Modified: 2006-11-25 19:21 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Danni Matzk 2006-10-26 23:42:27 UTC
Version:            (using KDE KDE 3.5.5)
Installed from:    Ubuntu Packages
OS:                Linux

There is currently no support for SMTP authentication for sending emails. Since some servers require SMTP authentication, this would be a useful feature.
Comment 1 Tom Albers 2006-11-25 01:29:23 UTC
SVN commit 607540 by toma:

Rewritten the smtp part. Should behave a lot better + preparations for auth on smtp.
BUG:137698
CCBUG:136360


 M  +0 -1      TODO  
 M  +3 -2      src/Makefile.am  
 M  +13 -153   src/composer.cpp  
 M  +3 -20     src/composer.h  
 M  +1 -0      src/imap.cpp  
 M  +1 -1      src/imap.h  
 A             src/smtp.cpp   [License: GPL (v2+)]
 A             src/smtp.h   [License: GPL (v2+)]
 M  +21 -23    src/socketsafe.cpp  
 M  +6 -0      src/socketsafe.h  


--- trunk/playground/pim/mailody/TODO #607539:607540
@@ -38,5 +38,4 @@
 Known Bugs:
   when not correctly logged in, no message. it just waits. Put a timer on that?
   copy an existing message and paste it in a new message, links are still blue
-  smtp broken
 
--- trunk/playground/pim/mailody/src/Makefile.am #607539:607540
@@ -2,7 +2,7 @@
 INCLUDES =  -I$(top_srcdir) -I$(top_srcdir)/libkmime $(all_includes)
 
 # these are the headers for your project
-noinst_HEADERS = mainwindow.h db.h imap.h messagedata.h \
+noinst_HEADERS = mainwindow.h db.h imap.h smtp.h messagedata.h \
                  headerlistview.h mailboxlistview.h messageview.h \
                  setup.h setupaccount.h sidebar.h colorquotes.h \
                  socketsafe.h composer.h filebrowser.h global.h \
@@ -24,7 +24,8 @@
 bin_PROGRAMS =  mailody 
 
 # the application source, library search path, and link libraries
-mailody_SOURCES = main.cpp mainwindow.cpp imap.cpp db.cpp messagedata.cpp \
+mailody_SOURCES = main.cpp mainwindow.cpp imap.cpp smtp.cpp db.cpp m\
+              messagedata.cpp \
               headerlistview.cpp mailboxlistview.cpp messageview.cpp \
               setup.cpp setupaccount.cpp sidebar.cpp colorquotes.cpp \
 			  socketsafe.cpp composer.cpp filebrowser.cpp global.cpp \
--- trunk/playground/pim/mailody/src/composer.cpp #607539:607540
@@ -45,11 +45,11 @@
 #include "sidebar.h"
 #include "imap.h"
 #include "global.h"
-#include "socketsafe.h"
 #include "filebrowser.h"
 #include "datalistview.h"
 #include "addresslineedit.h"
 #include "composer.h"
+#include "smtp.h"
 
 namespace Mailody {
 
@@ -58,7 +58,6 @@
   : KMainWindow(0),
     m_lastState(To),
     m_smtp(0),
-    m_currentCommand(Connecting),
     m_close(false),
     m_dirty(false)
 {
@@ -729,7 +728,7 @@
 
     if (totalSize > 2000000)
     {
-        int i = KMessageBox::warningContinueCancel(this, 
+        int i = KMessageBox::warningContinueCancel(this,
                     i18n("The size of the attachments is %1, are you "
                          "sure you want to send it?")
                            .arg( KIO::convertSize(KIO::filesize_t(totalSize))),
@@ -748,47 +747,19 @@
 
     // Sending it!!! Yeah!
 
+    Imap* t = Imap::instance();
+    t->saveMessage(m_mailbox, m->encodedContent( true ));
+
     if (m_smtp)
         delete m_smtp;
 
-    m_currentCommand = Connecting;
-
-    QString server = smtp_server.section(":",0,0);
-    int port = smtp_server.section(":",1,1).toInt();
-    switch(safe)
-    {
-        case 0:
-            if (port == 0)
-                port = 25;
-            m_smtp = new SocketSafe(this, server, port, SocketSafe::NONE);
-            break;
-        case 1:
-            if (port == 0)
-                port = 465;
-            m_smtp = new SocketSafe(this, server, port, SocketSafe::SSL);
-            break;
-        case 2:
-            if (port == 0)
-                port = 25;
-            m_smtp = new SocketSafe(this, server, port, SocketSafe::TLS);
-            break;
-    }
-
-
-    connect(m_smtp, SIGNAL(data(const QString&)),
-            SLOT(slotRead(const QString&)));
-    connect(m_smtp, SIGNAL(connected()), SLOT(slotConnected()));
-    m_smtp->reconnect();
+    m_smtp = new SMTP(this, "SMTP");
     connect(m_smtp, SIGNAL(error(const QString&)),
             SLOT(slotError(const QString&)));
-    connect(m_smtp, SIGNAL(readyfortls()),
-            SLOT(slotTLS()));
+    connect(m_smtp, SIGNAL(done()),SLOT(slotDone()));
 
-}
+    m_smtp->send(m_tos, m->encodedContent());
 
-void Composer::slotTLS()
-{
-    m_smtp->write("starttls");
 }
 
 void Composer::slotSetDirty()
@@ -796,128 +767,17 @@
     m_dirty = true;
 }
 
-void Composer::slotError(const QString& error)
+void Composer::slotDone()
 {
-    //kdDebug()<< "slotError " <<  error << endl;
-    // There is a 10% chance for a crash remaining here
-    // on a timeout error
-    // Thiago guarded for that for KDE 3.5.6 - comitted on 2006-10-29
-    if (m_smtp)
-    {
-        m_smtp->deleteLater();
-        m_smtp = 0;
-    }
-
-    KMessageBox::information(this, error);
+    m_close = true;
+    close();
 }
 
-void Composer::slotRead(const QString& dataIn)
+void Composer::slotError(const QString& error)
 {
-    // kdDebug() << "Received: " << dataIn.stripWhiteSpace()
-    //     << " for the command " << m_currentCommand << endl;
-
-    static QString lastEmail;
-
-    if (!m_smtp)
-        return;
-
-    if (m_currentCommand == Connecting)
-    {
-        m_currentCommand = Helo;
-        m_smtp->write("helo localhost");
-    }
-    else if (m_currentCommand == Helo)
-    {
-        m_currentCommand = From;
-        m_smtp->write("MAIL FROM:" + m->from()->email());
-    }
-    else if (m_currentCommand == From || !m_tos.isEmpty())
-    {
-        // Please remember, this can be the response to hte Helo or to
-        // a previous RCPT command....
-        if (!dataIn.startsWith("250"))
-        {
-            if (dataIn.startsWith("501"))
-                showError(i18n("One of the emailaddress was refused by the "
-                        "server. The refused address is: " + lastEmail));
-            else
-                showError( dataIn );
-            return;
-        }
-
-        m_currentCommand = Rcpt;
-        QString to = m_tos.first();
-        m_tos.pop_front();
-
-        //only send the actual emailaddress, not the name.
-        KMime::Headers::AddressField Address;
-        Address.fromUnicodeString( to,"UTF-8");
-        lastEmail = Address.email();
-
-        m_smtp->write("RCPT TO:" + lastEmail);
-    }
-    else if (m_currentCommand == Rcpt )
-    {
-        if (!dataIn.startsWith("250"))
-        {
-            if (dataIn.startsWith("501"))
-                showError(i18n("One of the emailaddress was refused by the "
-                    "server. The refused address is: " + lastEmail));
-            else
-                showError( dataIn );
-            return;
-        }
-        m_currentCommand = Data;
-        m_smtp->write("DATA");
-    }
-    else if (m_currentCommand == Data)
-    {
-        if (!dataIn.startsWith("250") && !dataIn.startsWith("354"))
-        {
-            showError( dataIn );
-            return;
-        }
-        m_currentCommand = Quit;
-        m_smtp->write(m->encodedContent());
-        m_smtp->write("\r\n.");
-    }
-    else if (m_currentCommand == Quit)
-    {
-        if (!dataIn.startsWith("250") && !dataIn.startsWith("354"))
-        {
-            showError( dataIn );
-            return;
-        }
-        m_currentCommand = Done;
-        m_smtp->aboutToClose();     // prevent disconnect message.
-        m_smtp->write("QUIT");
-    }
-    else if (m_currentCommand == Done)
-    {
-        // Time to store the message:
-        Imap* t = Imap::instance();
-        t->saveMessage(m_mailbox, m->encodedContent( true ));
-        m_close = true;
-        close();
-    }
+    KMessageBox::information(this, error);
 }
 
-void Composer::showError(const QString& error)
-{
-    //kdDebug()<< "showError " <<  error << endl;
-    m_currentCommand = NotDone;
-    m_smtp->aboutToClose();
-    m_smtp->write("QUIT");
-    m_smtp = 0;
-    KMessageBox::error(this, i18n("The message can not be send, de server "
-            "answered:\n\n"+error));
 }
 
-void Composer::slotConnected()
-{
-    kdDebug() << "Connected! " << endl;
-}
-
-}
-
 #include "composer.moc"
--- trunk/playground/pim/mailody/src/composer.h #607539:607540
@@ -53,7 +53,7 @@
 
 class AddressLineEdit;
 class DataListView;
-class SocketSafe;
+class SMTP;
 
 /**
  * @class Composer
@@ -117,17 +117,6 @@
 
     private:
 
-        enum Commands{
-            None=0,
-            Connecting,
-            Helo,
-            From,
-            Rcpt,
-            Data,
-            Quit,
-            Done,
-            NotDone
-        };
 
         AddressLineEdit                 *m_edit;
         DataListView                    *m_lv;
@@ -141,8 +130,7 @@
         QSplitter*                      m_vhsplitter;
         KLineEdit*                      m_subject;
         KTextEdit*                      m_text;
-        SocketSafe*                     m_smtp;
-        Commands                        m_currentCommand;
+        SMTP*                           m_smtp;
         KMime::Message*                 m;
         QStringList                     m_tos;
         QPushButton*                    m_add;
@@ -177,13 +165,8 @@
                                         const QPoint &point);
         void slotContextMenuAddressList(KListView*, QListViewItem* lvi,
                                         const QPoint &point);
-
-
-
         void slotSend();
-        void slotConnected();
-        void slotTLS();
-        void slotRead(const QString&);
+        void slotDone();
         void slotError(const QString& error);
         void slotSetDirty();
 };
--- trunk/playground/pim/mailody/src/imap.cpp #607539:607540
@@ -751,6 +751,7 @@
 
     connect(m_imap, SIGNAL(data(const QString&)),
             SLOT(slotRead(const QString&)));
+    connect(m_imap, SIGNAL(TLSCompleted()), SLOT(slotLogin()));
     connect(m_imap, SIGNAL(connected()), SLOT(slotLogin()));
     connect(m_imap, SIGNAL(error(const QString&)),
             SLOT(slotError(const QString&)));
--- trunk/playground/pim/mailody/src/imap.h #607539:607540
@@ -79,7 +79,7 @@
     /**
      * Contructor
      */
-      Imap( QWidget* parent,  const char* name );
+    explicit Imap( QWidget* parent,  const char* name );
 
     /**
      * Destructor
--- trunk/playground/pim/mailody/src/socketsafe.cpp #607539:607540
@@ -326,7 +326,7 @@
                     << "), but accepted previously... " << endl;
     }
 
-    emit connected();
+    emit TLSCompleted();
     m_ready = true;
 }
 
@@ -362,25 +362,32 @@
         // The bits received are not crypted. This can happen when
         // we don't want tls or ssl or when the connection is ready for tls.
 
-        if (m_safe == TLS)
-        {
-            QString msg = m_socket->readLine();
+        static QString received;
+        uint available = m_socket->bytesAvailable();
+        QByteArray buffer(available);
+        m_socket->readBlock(buffer.data(), buffer.size());
+        QCString cs;
+        cs.resize(buffer.size()+1);
+        memcpy(cs.data(), buffer.data(), buffer.size());
+        QString msg = cs.data();
+
 #ifdef comm_debug
-            kdDebug() << "S(0): " << QString(msg).stripWhiteSpace() << endl;
+        kdDebug() << "S(0): " << msg.stripWhiteSpace() << endl;
 #endif
+        if (m_safe == TLS)
+        {
 
             // handle the tls case.
+            // TODO move intelligence to imap/smtp
             if (msg.find("a02 OK") != -1 ||
-                msg.find("220 Ready to start TLS") != -1)
+                msg.find("220 ") < msg.find("TLS") && msg.find("220 ") != -1)
             {
                 // Request accepted.
                 kdDebug() << "Accepted, starting TLS handshake..." << endl;
                 m_ssl->startClient(m_server);
                 m_crypted=true;
             }
-            else if (msg.find("a02 ") != -1 || msg.find("error",0,false) != -1 ||
-                     msg.find("500") != -1 || msg.find("503") != -1 ||
-                     msg.find("501") != -1 || msg.find("502") != -1)
+            else if (msg.find("a02 ") != -1)
             {
                 // request returned, but not ok.
                 KMessageBox::information(0,i18n("TLS was refused:\n\n")+msg);
@@ -388,26 +395,17 @@
             else
             {
                 // request tls.
-                kdDebug() << "Connected, starting request for TLS" << endl;
+                kdDebug() << "Connected, emitting req. to deal with TLS" << endl;
                 emit readyfortls();
+                emit data(msg);
             }
         }
         else
         {
+            received.append(msg);
+
             // we don't need any encryption, so gather stuff and emit it.
-            static QString received;
-            uint available = m_socket->bytesAvailable();
-            QByteArray buffer(available);
-            m_socket->readBlock(buffer.data(), buffer.size());
-            QCString cs;
-            cs.resize(buffer.size()+1);
-            memcpy(cs.data(), buffer.data(), buffer.size());
-            QString t = cs.data();
-            received.append(t);
-#ifdef comm_debug
-            kdDebug() << "S(0): " << t.stripWhiteSpace() << endl;
-#endif
-            QStringList splitted = QStringList::split("\n",t);
+            QStringList splitted = QStringList::split("\n",msg);
             if (!m_gather || splitted.grep(QRegExp("^a02")).count() != 0)
             {
                 emit data(received);
--- trunk/playground/pim/mailody/src/socketsafe.h #607539:607540
@@ -122,7 +122,13 @@
          */
         void connected();
 
+
         /**
+         * emitted when TLS is done
+         */
+        void TLSCompleted();
+
+        /**
          * emitted when the dns request is ok (pretty useless, but still).
          */
         void hostFound();
Comment 2 Tom Albers 2006-11-25 19:21:36 UTC
SVN commit 607785 by toma:

Support for Authentication for SMTP.
BUG: 136360


 M  +131 -58   setupaccount.cpp  
 M  +53 -21    smtp.cpp  
 M  +6 -0      smtp.h