• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • 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     delete sock;
00069     sock = 0L;
00070     connectTimer.stop();
00071     timeOutTimer.stop();
00072 }
00073 
00074 void SMTP::setServerHost(const QString& serverhost)
00075 {
00076     serverHost = serverhost;
00077 }
00078 
00079 void SMTP::setPort(unsigned short int port)
00080 {
00081     hostPort = port;
00082 }
00083 
00084 void SMTP::setTimeOut(int timeout)
00085 {
00086     timeOut = timeout;
00087 }
00088 
00089 void SMTP::setSenderAddress(const QString& sender)
00090 {
00091     senderAddress = sender;
00092     int index = senderAddress.indexOf('<');
00093     if (index == -1)
00094         return;
00095     senderAddress = senderAddress.mid(index + 1);
00096     index =  senderAddress.indexOf('>');
00097     if (index != -1)
00098         senderAddress = senderAddress.left(index);
00099     senderAddress = senderAddress.simplified();
00100     while (1) {
00101         index =  senderAddress.indexOf(' ');
00102         if (index != -1)
00103             senderAddress = senderAddress.mid(index + 1); // take one side
00104         else
00105             break;
00106     }
00107     index = senderAddress.indexOf('@');
00108     if (index == -1)
00109         senderAddress.append("@localhost"); // won't go through without a local mail system
00110 
00111 }
00112 
00113 void SMTP::setRecipientAddress(const QString& recipient)
00114 {
00115     recipientAddress = recipient;
00116 }
00117 
00118 void SMTP::setMessageSubject(const QString& subject)
00119 {
00120     messageSubject = subject;
00121 }
00122 
00123 void SMTP::setMessageBody(const QString& message)
00124 {
00125     messageBody = message;
00126 }
00127 
00128 void SMTP::setMessageHeader(const QString &header)
00129 {
00130     messageHeader = header;
00131 }
00132 
00133 void SMTP::openConnection(void)
00134 {
00135     kDebug() << "started connect timer";
00136     connectTimer.setSingleShot(true);
00137     connectTimer.start(100);
00138 }
00139 
00140 void SMTP::closeConnection(void)
00141 {
00142     socketClosed();
00143 }
00144 
00145 void SMTP::sendMessage(void)
00146 {
00147     if(!connected)
00148         connectTimerTick();
00149     if(state == Finished && connected){
00150         kDebug() << "state was == Finished\n";
00151         finished = false;
00152         state = In;
00153         writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
00154         sock->write(writeString.toAscii().constData(), writeString.length());
00155     }
00156     if(connected){
00157         kDebug() << "enabling read on sock...\n";
00158         interactTimer.setSingleShot(true);
00159         interactTimer.start(timeOut);
00160     }
00161 }
00162 
00163 void SMTP::connectTimerTick(void)
00164 {
00165     connectTimer.stop();
00166 //    timeOutTimer.start(timeOut, true);
00167 
00168     kDebug() << "connectTimerTick called...";
00169 
00170     delete sock;
00171     sock = 0L;
00172 
00173     kDebug() << "connecting to " << serverHost << ":" << hostPort << " ..... ";
00174     sock = KSocketFactory::connectToHost("smtp", serverHost, hostPort, this);
00175 
00176     connected = true;
00177     finished = false;
00178     state = Init;
00179     serverState = None;
00180 
00181     connect(sock, SIGNAL(readyRead()), this, SLOT(socketReadyToRead()));
00182     connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this,
00183             SLOT(socketError(QAbstractSocket::SocketError)));
00184     connect(sock, SIGNAL(disconnected()), this, SLOT(socketClosed()));
00185     timeOutTimer.stop();
00186     kDebug() << "connected";
00187 }
00188 
00189 void SMTP::connectTimedOut(void)
00190 {
00191     timeOutTimer.stop();
00192 
00193     kDebug() << "socket connection timed out";
00194     socketClosed();
00195     emit error(ConnectTimeout);
00196 }
00197 
00198 void SMTP::interactTimedOut(void)
00199 {
00200     interactTimer.stop();
00201 
00202     kDebug() << "time out waiting for server interaction";
00203     socketClosed();
00204     emit error(InteractTimeout);
00205 }
00206 
00207 void SMTP::socketReadyToRead()
00208 {
00209     int n, nl;
00210 
00211     kDebug() << "socketRead() called...";
00212     interactTimer.stop();
00213 
00214     if (!sock)
00215         return;
00216 
00217     n = sock->read(readBuffer, SMTP_READ_BUFFER_SIZE-1);
00218     if (n < 0)
00219     return;
00220     readBuffer[n] = 0;
00221     lineBuffer += readBuffer;
00222     nl = lineBuffer.indexOf('\n');
00223     if(nl == -1)
00224         return;
00225     lastLine = lineBuffer.left(nl);
00226     lineBuffer = lineBuffer.right(lineBuffer.length() - nl - 1);
00227     processLine(&lastLine);
00228     if(connected) {
00229         interactTimer.setSingleShot(true);
00230         interactTimer.start(timeOut);
00231     }
00232 }
00233 
00234 void SMTP::socketError(QAbstractSocket::SocketError socketError)
00235 {
00236     kDebug() << socketError << sock->errorString();
00237     Q_UNUSED(socketError);
00238     emit error(ConnectError);
00239     socketClosed();
00240 }
00241 
00242 void SMTP::socketClosed()
00243 {
00244     timeOutTimer.stop();
00245     kDebug() << "connection terminated";
00246     connected = false;
00247     if (sock)
00248         sock->deleteLater();
00249     sock = 0;
00250     emit connectionClosed();
00251 }
00252 
00253 void SMTP::processLine(QString *line)
00254 {
00255     int i, stat;
00256     QString tmpstr;
00257 
00258     i = line->indexOf(' ');
00259     tmpstr = line->left(i);
00260     if(i > 3)
00261         kDebug() << "warning: SMTP status code longer than 3 digits: " << tmpstr;
00262     stat = tmpstr.toInt();
00263     serverState = (SMTPServerStatus)stat;
00264     lastState = state;
00265 
00266     kDebug() << "smtp state: [" << stat << "][" << *line << "]";
00267 
00268     switch(stat){
00269     case Greet:     //220
00270         state = In;
00271         writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
00272         kDebug() << "out: " << writeString;
00273         sock->write(writeString.toAscii().constData(), writeString.length());
00274         break;
00275     case Goodbye:   //221
00276         state = Quit;
00277         break;
00278     case Successful://250
00279         switch(state){
00280         case In:
00281             state = Ready;
00282             writeString = QString::fromLatin1("mail from: %1\r\n").arg(senderAddress);
00283             kDebug() << "out: " << writeString;
00284             sock->write(writeString.toAscii().constData(), writeString.length());
00285             break;
00286         case Ready:
00287             state = SentFrom;
00288             writeString = QString::fromLatin1("rcpt to: %1\r\n").arg(recipientAddress);
00289              kDebug() << "out: " << writeString;
00290             sock->write(writeString.toAscii().constData(), writeString.length());
00291             break;
00292         case SentFrom:
00293             state = SentTo;
00294             writeString = QLatin1String("data\r\n");
00295              kDebug() << "out: " << writeString;
00296             sock->write(writeString.toAscii().constData(), writeString.length());
00297             break;
00298         case Data:
00299             state = Finished;
00300             finished = true;
00301             emit messageSent();
00302             break;
00303         default:
00304             state = CError;
00305             kDebug() << "smtp error (state error): [" << lastState << "]:[" << stat << "][" << *line << "]";
00306             socketClosed();
00307             emit error(Command);
00308             break;
00309         }
00310         break;
00311     case ReadyData: //354
00312         state = Data;
00313         writeString = QString::fromLatin1("Subject: %1\r\n").arg(messageSubject);
00314         writeString += messageHeader;
00315         writeString += "\r\n";
00316         writeString += messageBody;
00317         writeString += QLatin1String(".\r\n");
00318         kDebug() << "out: " << writeString;
00319         sock->write(writeString.toAscii().constData(), writeString.length());
00320         break;
00321     case Error:     //501
00322         state = CError;
00323         kDebug() << "smtp error (command error): [" << lastState << "]:[" << stat << "][" << *line << "]\n";
00324         socketClosed();
00325         emit error(Command);
00326         break;
00327     case Unknown:   //550
00328         state = CError;
00329         kDebug() << "smtp error (unknown user): [" << lastState << "]:[" << stat << "][" << *line << "]";
00330         socketClosed();
00331         emit error(UnknownUser);
00332         break;
00333     default:
00334         state = CError;
00335         kDebug() << "unknown response: [" << lastState << "]:[" << stat << "][" << *line << "]";
00336         socketClosed();
00337         emit error(UnknownResponse);
00338     }
00339 }
00340 
00341 #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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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