• Skip to content
  • Skip to link menu
KDE 4.1 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 #if 0
00181     // socket can't fail here
00182     if (!sock->connect()) {
00183         timeOutTimer.stop();
00184         kDebug() << "connection failed!";
00185         socketClosed();
00186         emit error(ConnectError);
00187         connected = false;
00188         return;
00189     }
00190 #endif
00191     connected = true;
00192     finished = false;
00193     state = Init;
00194     serverState = None;
00195 
00196     connect(sock, SIGNAL(readyRead()), this, SLOT(socketReadyToRead()));
00197     connect(sock, SIGNAL(error()), this, SLOT(socketClosed()));
00198     connect(sock, SIGNAL(disconnected()), this, SLOT(socketClosed()));
00199     timeOutTimer.stop();
00200     kDebug() << "connected";
00201 }
00202 
00203 void SMTP::connectTimedOut(void)
00204 {
00205     timeOutTimer.stop();
00206 
00207     kDebug() << "socket connection timed out";
00208     socketClosed();
00209     emit error(ConnectTimeout);
00210 }
00211 
00212 void SMTP::interactTimedOut(void)
00213 {
00214     interactTimer.stop();
00215 
00216     kDebug() << "time out waiting for server interaction";
00217     socketClosed();
00218     emit error(InteractTimeout);
00219 }
00220 
00221 void SMTP::socketReadyToRead()
00222 {
00223     int n, nl;
00224 
00225     kDebug() << "socketRead() called...";
00226     interactTimer.stop();
00227 
00228     if (!sock)
00229         return;
00230 
00231     n = sock->read(readBuffer, SMTP_READ_BUFFER_SIZE-1);
00232     if (n < 0)
00233     return;
00234     readBuffer[n] = 0;
00235     lineBuffer += readBuffer;
00236     nl = lineBuffer.indexOf('\n');
00237     if(nl == -1)
00238         return;
00239     lastLine = lineBuffer.left(nl);
00240     lineBuffer = lineBuffer.right(lineBuffer.length() - nl - 1);
00241     processLine(&lastLine);
00242     if(connected) {
00243         interactTimer.setSingleShot(true);
00244         interactTimer.start(timeOut);
00245     }
00246 }
00247 
00248 void SMTP::socketClosed()
00249 {
00250     timeOutTimer.stop();
00251     kDebug() << "connection terminated";
00252     connected = false;
00253     delete sock;
00254     sock = 0L;
00255     emit connectionClosed();
00256 }
00257 
00258 void SMTP::processLine(QString *line)
00259 {
00260     int i, stat;
00261     QString tmpstr;
00262 
00263     i = line->indexOf(' ');
00264     tmpstr = line->left(i);
00265     if(i > 3)
00266         kDebug() << "warning: SMTP status code longer then 3 digits: " << tmpstr;
00267     stat = tmpstr.toInt();
00268     serverState = (SMTPServerStatus)stat;
00269     lastState = state;
00270 
00271     kDebug() << "smtp state: [" << stat << "][" << *line << "]";
00272 
00273     switch(stat){
00274     case Greet:     //220
00275         state = In;
00276         writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
00277         kDebug() << "out: " << writeString;
00278         sock->write(writeString.toAscii().constData(), writeString.length());
00279         break;
00280     case Goodbye:   //221
00281         state = Quit;
00282         break;
00283     case Successful://250
00284         switch(state){
00285         case In:
00286             state = Ready;
00287             writeString = QString::fromLatin1("mail from: %1\r\n").arg(senderAddress);
00288             kDebug() << "out: " << writeString;
00289             sock->write(writeString.toAscii().constData(), writeString.length());
00290             break;
00291         case Ready:
00292             state = SentFrom;
00293             writeString = QString::fromLatin1("rcpt to: %1\r\n").arg(recipientAddress);
00294              kDebug() << "out: " << writeString;
00295             sock->write(writeString.toAscii().constData(), writeString.length());
00296             break;
00297         case SentFrom:
00298             state = SentTo;
00299             writeString = QLatin1String("data\r\n");
00300              kDebug() << "out: " << writeString;
00301             sock->write(writeString.toAscii().constData(), writeString.length());
00302             break;
00303         case Data:
00304             state = Finished;
00305             finished = true;
00306             emit messageSent();
00307             break;
00308         default:
00309             state = CError;
00310             kDebug() << "smtp error (state error): [" << lastState << "]:[" << stat << "][" << *line << "]";
00311             socketClosed();
00312             emit error(Command);
00313             break;
00314         }
00315         break;
00316     case ReadyData: //354
00317         state = Data;
00318         writeString = QString::fromLatin1("Subject: %1\r\n").arg(messageSubject);
00319         writeString += messageHeader;
00320         writeString += "\r\n";
00321         writeString += messageBody;
00322         writeString += QLatin1String(".\r\n");
00323         kDebug() << "out: " << writeString;
00324         sock->write(writeString.toAscii().constData(), writeString.length());
00325         break;
00326     case Error:     //501
00327         state = CError;
00328         kDebug() << "smtp error (command error): [" << lastState << "]:[" << stat << "][" << *line << "]\n";
00329         socketClosed();
00330         emit error(Command);
00331         break;
00332     case Unknown:   //550
00333         state = CError;
00334         kDebug() << "smtp error (unknown user): [" << lastState << "]:[" << stat << "][" << *line << "]";
00335         socketClosed();
00336         emit error(UnknownUser);
00337         break;
00338     default:
00339         state = CError;
00340         kDebug() << "unknown response: [" << lastState << "]:[" << stat << "][" << *line << "]";
00341         socketClosed();
00342         emit error(UnknownResponse);
00343     }
00344 }
00345 
00346 #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
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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