00001 #warning "TODO: XXX This class needs to be rewritten. XXX"
00002
00003 #include <qsocket.h>
00004 #include <qtimer.h>
00005 #include <qfile.h>
00006 #include <qdatetime.h>
00007 #include <qdir.h>
00008 #include <qregexp.h>
00009
00010 #include <qpe/mimetype.h>
00011 #include <qpe/config.h>
00012
00013 #include <stdlib.h>
00014
00015 #include "smtphandler.h"
00016 #include "miscfunctions.h"
00017
00018 SmtpHandler::SmtpHandler(const QString &header, const QString &message, Account &account, const QString &to)
00019 : QObject(), _header(header), _message(message), _account(account), _to(to)
00020 {
00021 _header.replace(QRegExp("\\n"), "\r\n");
00022 _message.replace(QRegExp("\\n"), "\r\n");
00023 _message.replace(QRegExp("\\r\\n\\.\\r\\n"), "\r\n..\r\n");
00024
00025
00026 _state = Helo;
00027
00028 _socket = new QSocket(this);
00029 connect(_socket, SIGNAL(hostFound()), this, SLOT(hostFound()));
00030 connect(_socket, SIGNAL(connected()), this, SLOT(connected()));
00031 connect(_socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
00032 connect(_socket, SIGNAL(error(int)), this, SLOT(errorHandling(int)));
00033
00034 _socket->connectToHost(account.smtpServer(), account.smtpPort().toUInt());
00035 emit status(tr("Looking up host..."));
00036 }
00037
00038 void SmtpHandler::errorHandling(int err)
00039 {
00040 if (err == QSocket::ErrConnectionRefused) {
00041 emit error(tr("The server refused the connection."));
00042 } else if (err == QSocket::ErrHostNotFound) {
00043 emit error(tr("Host lookup failed."));
00044 } else if (err == QSocket::ErrSocketRead) {
00045 emit error(tr("The read from the socket failed for an unknown reason."));
00046 } else {
00047 emit error(tr("The sending failed for an unknown reason."));
00048 }
00049 stop();
00050 }
00051
00052 void SmtpHandler::hostFound()
00053 {
00054 emit status(tr("Host found."));
00055 }
00056
00057 void SmtpHandler::connected()
00058 {
00059 emit status(tr("Connected to %1").arg(_socket->peerName()));
00060 }
00061
00062 void SmtpHandler::readyRead()
00063 {
00064 if (!_socket->canReadLine()) return;
00065 if (_state == Close) stop();
00066
00067 QString response = _socket->readLine();
00068 QString temp = response;
00069 temp.truncate(3);
00070 int responseCode = temp.toInt();
00071
00072 #ifndef QT_NO_DEBUG
00073 qDebug(tr("SMTP > %3").arg(response.stripWhiteSpace()));
00074 #endif
00075
00076 response.replace(0, 4, "");
00077 response.stripWhiteSpace();
00078
00079 if (_state == Ehlo && responseCode == 220) {
00080 QString hostname = getenv("HOSTNAME");
00081 if (hostname.stripWhiteSpace().isEmpty())
00082 hostname = "opiemail";
00083
00084 emit status(tr("SMTP> EHLO *"));
00085 sendToSocket(QString("EHLO %1\r\n").arg(hostname));
00086 _state = Auth;
00087 } else if (_state == Auth && responseCode == 250) {
00088 QStringList capabilities;
00089 while (_socket->canReadLine()) {
00090 QString line = _socket->readLine().stripWhiteSpace();
00091 capabilities.append(line);
00092 }
00093
00094
00095 if (!capabilities.grep(QRegExp("^250-AUTH=LOGIN.*CRAM-MD5.*$")).isEmpty()) {
00096
00097 _state = Mail;
00098 } else {
00099 emit status(tr("SMTP> AUTH CRAM-MD5"));
00100 sendToSocket("AUTH CRAM-MD5\r\n");
00101 _state = ReadAuth;
00102 }
00103 } else if (_state == ReadAuth && responseCode == 334) {
00104 QString msgId = MiscFunctions::decodeBase64(response);
00105
00106 QString authString;
00107 authString = _account.user() + " " +
00108 MiscFunctions::smtpAuthCramMd5(msgId, _account.pass());
00109 authString = MiscFunctions::encodeBase64(authString);
00110
00111 emit status(tr("SMTP> Authenticating"));
00112 sendToSocket(authString + "\r\n");
00113
00114 _state = Mail;
00115 } else if (_state == Helo && responseCode == 220) {
00116 QString hostname = getenv("HOSTNAME");
00117 if (hostname.stripWhiteSpace().isEmpty())
00118 hostname = "opiemail";
00119
00120 emit status(tr("SMTP> HELO *"));
00121 sendToSocket(QString("HELO %1\r\n").arg(hostname));
00122 _state = Mail;
00123 } else if (_state == Mail && responseCode == 250) {
00124 emit status(tr("SMTP> MAIL FROM: *"));
00125 sendToSocket("MAIL FROM: <" + _account.email() + ">\r\n");
00126 _state = Rcpt;
00127 } else if (_state == Rcpt && responseCode == 250) {
00128 emit status(tr("SMTP> RCPT TO: *"));
00129 sendToSocket("RCPT TO: <" + _to + ">\r\n");
00130 _state = Data;
00131 } else if (_state == Data && responseCode == 250) {
00132 emit status(tr("SMTP> DATA"));
00133 sendToSocket("DATA\r\n");
00134 _state = Body;
00135 } else if (_state == Body && responseCode == 354) {
00136 emit status(tr("SMTP> Sending data..."));
00137 sendToSocket(_header + "\r\n" + _message + "\r\n.\r\n", false);
00138 _state = Quit;
00139 } else if (_state == Quit) {
00140 emit status(tr("SMTP> QUIT (Done)"));
00141 sendToSocket("QUIT\r\n");
00142 _state = Close;
00143 } else if (_state == Close) {
00144
00145 } else {
00146 emit error(tr("The server returned an error. This is the message:<br>%1").arg(response));
00147 stop();
00148 }
00149 }
00150
00151 void SmtpHandler::sendToSocket(const QString &text, bool log)
00152 {
00153 _socket->writeBlock(text.latin1(), text.length());
00154
00155 if (log) {
00156 #ifndef QT_NO_DEBUG
00157 qDebug(tr("SMTP < %3").arg(text.stripWhiteSpace()));
00158 #endif
00159 }
00160 }
00161
00162 void SmtpHandler::stop()
00163 {
00164 emit finished();
00165 QTimer::singleShot(0, this, SLOT(deleteMe()));
00166 }
00167
00168 void SmtpHandler::deleteMe()
00169 {
00170 delete this;
00171 }
00172