• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIO

smtp.cpp

Go to the documentation of this file.
00001 /*
00002    Copyright (c) 2000 Bernd Johannes Wuebben <wuebben@math.cornell.edu>
00003    Copyright (c) 2000 Stephan Kulow <coolo@kde.org>
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2, or (at your option)
00008    any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 
00020 #include "smtp.h"
00021 
00022 #include <sys/utsname.h>
00023 #include <unistd.h>
00024 #include <stdio.h>
00025 
00026 #include <kdebug.h>
00027 
00028 SMTP::SMTP(char *serverhost, unsigned short int port, int timeout)
00029 {
00030     struct utsname uts;
00031 
00032     serverHost = serverhost;
00033     hostPort = port;
00034     timeOut = timeout * 1000;
00035 
00036     senderAddress = "user@example.net";
00037     recipientAddress = "user@example.net";
00038     messageSubject = "(no subject)";
00039     messageBody = "empty";
00040     messageHeader = "";
00041 
00042     connected = false;
00043     finished = false;
00044 
00045     sock = 0L;
00046     state = Init;
00047     serverState = None;
00048 
00049     uname(&uts);
00050     domainName = uts.nodename;
00051 
00052 
00053     if(domainName.isEmpty())
00054         domainName = "somemachine.example.net";
00055 
00056     kDebug() << "SMTP object created";
00057 
00058     connect(&connectTimer, SIGNAL(timeout()), this, SLOT(connectTimerTick()));
00059     connect(&timeOutTimer, SIGNAL(timeout()), this, SLOT(connectTimedOut()));
00060     connect(&interactTimer, SIGNAL(timeout()), this, SLOT(interactTimedOut()));
00061 
00062     // some sendmail will give 'duplicate helo' error, quick fix for now
00063     connect(this, SIGNAL(messageSent()), SLOT(closeConnection()));
00064 }
00065 
00066 SMTP::~SMTP()
00067 {
00068     if(sock){
00069         delete sock;
00070         sock = 0L;
00071     }
00072     connectTimer.stop();
00073     timeOutTimer.stop();
00074 }
00075 
00076 void SMTP::setServerHost(const QString& serverhost)
00077 {
00078     serverHost = serverhost;
00079 }
00080 
00081 void SMTP::setPort(unsigned short int port)
00082 {
00083     hostPort = port;
00084 }
00085 
00086 void SMTP::setTimeOut(int timeout)
00087 {
00088     timeOut = timeout;
00089 }
00090 
00091 void SMTP::setSenderAddress(const QString& sender)
00092 {
00093     senderAddress = sender;
00094     int index = senderAddress.indexOf('<');
00095     if (index == -1)
00096         return;
00097     senderAddress = senderAddress.mid(index + 1);
00098     index =  senderAddress.indexOf('>');
00099     if (index != -1)
00100         senderAddress = senderAddress.left(index);
00101     senderAddress = senderAddress.simplified();
00102     while (1) {
00103         index =  senderAddress.indexOf(' ');
00104         if (index != -1)
00105             senderAddress = senderAddress.mid(index + 1); // take one side
00106         else
00107             break;
00108     }
00109     index = senderAddress.indexOf('@');
00110     if (index == -1)
00111         senderAddress.append("@localhost"); // won't go through without a local mail system
00112 
00113 }
00114 
00115 void SMTP::setRecipientAddress(const QString& recipient)
00116 {
00117     recipientAddress = recipient;
00118 }
00119 
00120 void SMTP::setMessageSubject(const QString& subject)
00121 {
00122     messageSubject = subject;
00123 }
00124 
00125 void SMTP::setMessageBody(const QString& message)
00126 {
00127     messageBody = message;
00128 }
00129 
00130 void SMTP::setMessageHeader(const QString &header)
00131 {
00132     messageHeader = header;
00133 }
00134 
00135 void SMTP::openConnection(void)
00136 {
00137     kDebug() << "started connect timer";
00138     connectTimer.setSingleShot(true);
00139     connectTimer.start(100);
00140 }
00141 
00142 void SMTP::closeConnection(void)
00143 {
00144     socketClosed();
00145 }
00146 
00147 void SMTP::sendMessage(void)
00148 {
00149     if(!connected)
00150         connectTimerTick();
00151     if(state == Finished && connected){
00152         kDebug() << "state was == Finished\n";
00153         finished = false;
00154         state = In;
00155         writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
00156         sock->write(writeString.toAscii().constData(), writeString.length());
00157     }
00158     if(connected){
00159         kDebug() << "enabling read on sock...\n";
00160         interactTimer.setSingleShot(true);
00161         interactTimer.start(timeOut);
00162     }
00163 }
00164 
00165 void SMTP::connectTimerTick(void)
00166 {
00167     connectTimer.stop();
00168 //    timeOutTimer.start(timeOut, true);
00169 
00170     kDebug() << "connectTimerTick called...";
00171 
00172     if(sock){
00173         delete sock;
00174         sock = 0L;
00175     }
00176 
00177     kDebug() << "connecting to " << serverHost << ":" << hostPort << " ..... ";
00178     sock = KSocketFactory::connectToHost("smtp", serverHost, hostPort, this);
00179 
00180     connected = true;
00181     finished = false;
00182     state = Init;
00183     serverState = None;
00184 
00185     connect(sock, SIGNAL(readyRead()), this, SLOT(socketReadyToRead()));
00186     connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this,
00187             SLOT(socketError(QAbstractSocket::SocketError)));
00188     connect(sock, SIGNAL(disconnected()), this, SLOT(socketClosed()));
00189     timeOutTimer.stop();
00190     kDebug() << "connected";
00191 }
00192 
00193 void SMTP::connectTimedOut(void)
00194 {
00195     timeOutTimer.stop();
00196 
00197     kDebug() << "socket connection timed out";
00198     socketClosed();
00199     emit error(ConnectTimeout);
00200 }
00201 
00202 void SMTP::interactTimedOut(void)
00203 {
00204     interactTimer.stop();
00205 
00206     kDebug() << "time out waiting for server interaction";
00207     socketClosed();
00208     emit error(InteractTimeout);
00209 }
00210 
00211 void SMTP::socketReadyToRead()
00212 {
00213     int n, nl;
00214 
00215     kDebug() << "socketRead() called...";
00216     interactTimer.stop();
00217 
00218     if (!sock)
00219         return;
00220 
00221     n = sock->read(readBuffer, SMTP_READ_BUFFER_SIZE-1);
00222     if (n < 0)
00223     return;
00224     readBuffer[n] = 0;
00225     lineBuffer += readBuffer;
00226     nl = lineBuffer.indexOf('\n');
00227     if(nl == -1)
00228         return;
00229     lastLine = lineBuffer.left(nl);
00230     lineBuffer = lineBuffer.right(lineBuffer.length() - nl - 1);
00231     processLine(&lastLine);
00232     if(connected) {
00233         interactTimer.setSingleShot(true);
00234         interactTimer.start(timeOut);
00235     }
00236 }
00237 
00238 void SMTP::socketError(QAbstractSocket::SocketError socketError)
00239 {
00240     kDebug() << socketError << sock->errorString();
00241     Q_UNUSED(socketError);
00242     emit error(ConnectError);
00243     socketClosed();
00244 }
00245 
00246 void SMTP::socketClosed()
00247 {
00248     timeOutTimer.stop();
00249     kDebug() << "connection terminated";
00250     connected = false;
00251     if (sock)
00252         sock->deleteLater();
00253     sock = 0;
00254     emit connectionClosed();
00255 }
00256 
00257 void SMTP::processLine(QString *line)
00258 {
00259     int i, stat;
00260     QString tmpstr;
00261 
00262     i = line->indexOf(' ');
00263     tmpstr = line->left(i);
00264     if(i > 3)
00265         kDebug() << "warning: SMTP status code longer than 3 digits: " << tmpstr;
00266     stat = tmpstr.toInt();
00267     serverState = (SMTPServerStatus)stat;
00268     lastState = state;
00269 
00270     kDebug() << "smtp state: [" << stat << "][" << *line << "]";
00271 
00272     switch(stat){
00273     case Greet:     //220
00274         state = In;
00275         writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
00276         kDebug() << "out: " << writeString;
00277         sock->write(writeString.toAscii().constData(), writeString.length());
00278         break;
00279     case Goodbye:   //221
00280         state = Quit;
00281         break;
00282     case Successful://250
00283         switch(state){
00284         case In:
00285             state = Ready;
00286             writeString = QString::fromLatin1("mail from: %1\r\n").arg(senderAddress);
00287             kDebug() << "out: " << writeString;
00288             sock->write(writeString.toAscii().constData(), writeString.length());
00289             break;
00290         case Ready:
00291             state = SentFrom;
00292             writeString = QString::fromLatin1("rcpt to: %1\r\n").arg(recipientAddress);
00293              kDebug() << "out: " << writeString;
00294             sock->write(writeString.toAscii().constData(), writeString.length());
00295             break;
00296         case SentFrom:
00297             state = SentTo;
00298             writeString = QLatin1String("data\r\n");
00299              kDebug() << "out: " << writeString;
00300             sock->write(writeString.toAscii().constData(), writeString.length());
00301             break;
00302         case Data:
00303             state = Finished;
00304             finished = true;
00305             emit messageSent();
00306             break;
00307         default:
00308             state = CError;
00309             kDebug() << "smtp error (state error): [" << lastState << "]:[" << stat << "][" << *line << "]";
00310             socketClosed();
00311             emit error(Command);
00312             break;
00313         }
00314         break;
00315     case ReadyData: //354
00316         state = Data;
00317         writeString = QString::fromLatin1("Subject: %1\r\n").arg(messageSubject);
00318         writeString += messageHeader;
00319         writeString += "\r\n";
00320         writeString += messageBody;
00321         writeString += QLatin1String(".\r\n");
00322         kDebug() << "out: " << writeString;
00323         sock->write(writeString.toAscii().constData(), writeString.length());
00324         break;
00325     case Error:     //501
00326         state = CError;
00327         kDebug() << "smtp error (command error): [" << lastState << "]:[" << stat << "][" << *line << "]\n";
00328         socketClosed();
00329         emit error(Command);
00330         break;
00331     case Unknown:   //550
00332         state = CError;
00333         kDebug() << "smtp error (unknown user): [" << lastState << "]:[" << stat << "][" << *line << "]";
00334         socketClosed();
00335         emit error(UnknownUser);
00336         break;
00337     default:
00338         state = CError;
00339         kDebug() << "unknown response: [" << lastState << "]:[" << stat << "][" << *line << "]";
00340         socketClosed();
00341         emit error(UnknownResponse);
00342     }
00343 }
00344 
00345 #include "smtp.moc"

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal