# kio Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# smtp.cpp

    00001 /* $Id: smtp.cpp 328808 2004-07-13 17:37:05Z staikos $ */
    00002
    00003 #include <sys/utsname.h>
    00004 #include <unistd.h>
    00005 #include <stdio.h>
    00006
    00007 #include <kdebug.h>
    00008
    00009 #include "smtp.h"
    00010
    00011 SMTP::SMTP(char *serverhost, unsigned short int port, int timeout)
    00012 {
    00013     struct utsname uts;
    00014
    00015     serverHost = serverhost;
    00016     hostPort = port;
    00017     timeOut = timeout * 1000;
    00018
    00019     senderAddress = "user@example.net";
    00020     recipientAddress = "user@example.net";
    00021     messageSubject = "(no subject)";
    00022     messageBody = "empty";
    00023     messageHeader = "";
    00024
    00025     connected = false;
    00026     finished = false;
    00027
    00028     sock = 0L;
    00029     state = INIT;
    00030     serverState = NONE;
    00031
    00032     uname(&uts);
    00033     domainName = uts.nodename;
    00034
    00035
    00036     if(domainName.isEmpty())
    00037         domainName = "somemachine.example.net";
    00038
    00039     kdDebug() << "SMTP object created" << endl;
    00040
    00041     connect(&connectTimer, SIGNAL(timeout()), this, SLOT(connectTimerTick()));
    00042     connect(&timeOutTimer, SIGNAL(timeout()), this, SLOT(connectTimedOut()));
    00043     connect(&interactTimer, SIGNAL(timeout()), this, SLOT(interactTimedOut()));
    00044
    00045     // some sendmail will give 'duplicate helo' error, quick fix for now
    00046     connect(this, SIGNAL(messageSent()), SLOT(closeConnection()));
    00047 }
    00048
    00049 SMTP::~SMTP()
    00050 {
    00051     if(sock){
    00052         delete sock;
    00053         sock = 0L;
    00054     }
    00055     connectTimer.stop();
    00056     timeOutTimer.stop();
    00057 }
    00058
    00059 void SMTP::setServerHost(const QString& serverhost)
    00060 {
    00061     serverHost = serverhost;
    00062 }
    00063
    00064 void SMTP::setPort(unsigned short int port)
    00065 {
    00066     hostPort = port;
    00067 }
    00068
    00069 void SMTP::setTimeOut(int timeout)
    00070 {
    00071     timeOut = timeout;
    00072 }
    00073
    00074 void SMTP::setSenderAddress(const QString& sender)
    00075 {
    00076     senderAddress = sender;
    00077     int index = senderAddress.find('<');
    00078     if (index == -1)
    00079         return;
    00080     senderAddress = senderAddress.mid(index + 1);
    00081     index =  senderAddress.find('>');
    00082     if (index != -1)
    00083         senderAddress = senderAddress.left(index);
    00084     senderAddress = senderAddress.simplifyWhiteSpace();
    00085     while (1) {
    00086         index =  senderAddress.find(' ');
    00087         if (index != -1)
    00088             senderAddress = senderAddress.mid(index + 1); // take one side
    00089         else
    00090             break;
    00091     }
    00092     index = senderAddress.find('@');
    00093     if (index == -1)
    00094         senderAddress.append("@localhost"); // won't go through without a local mail system
    00095
    00096 }
    00097
    00098 void SMTP::setRecipientAddress(const QString& recipient)
    00099 {
    00100     recipientAddress = recipient;
    00101 }
    00102
    00103 void SMTP::setMessageSubject(const QString& subject)
    00104 {
    00105     messageSubject = subject;
    00106 }
    00107
    00108 void SMTP::setMessageBody(const QString& message)
    00109 {
    00110     messageBody = message;
    00111 }
    00112
    00113 void SMTP::setMessageHeader(const QString &header)
    00114 {
    00115     messageHeader = header;
    00116 }
    00117
    00118 void SMTP::openConnection(void)
    00119 {
    00120     kdDebug() << "started connect timer" << endl;
    00121     connectTimer.start(100, true);
    00122 }
    00123
    00124 void SMTP::closeConnection(void)
    00125 {
    00126     socketClose(sock);
    00127 }
    00128
    00129 void SMTP::sendMessage(void)
    00130 {
    00131     if(!connected)
    00132         connectTimerTick();
    00133     if(state == FINISHED && connected){
    00134         kdDebug() << "state was == FINISHED\n" << endl;
    00135         finished = false;
    00136         state = IN;
    00137         writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
    00138         write(sock->socket(), writeString.ascii(), writeString.length());
    00139     }
    00140     if(connected){
    00141         kdDebug() << "enabling read on sock...\n" << endl;
    00142         interactTimer.start(timeOut, true);
    00143         sock->enableRead(true);
    00144     }
    00145 }
    00146 #include <stdio.h>
    00147
    00148 void SMTP::connectTimerTick(void)
    00149 {
    00150     connectTimer.stop();
    00151 //    timeOutTimer.start(timeOut, true);
    00152
    00153     kdDebug() << "connectTimerTick called..." << endl;
    00154
    00155     if(sock){
    00156         delete sock;
    00157         sock = 0L;
    00158     }
    00159
    00160     kdDebug() << "connecting to " << serverHost << ":" << hostPort << " ..... " << endl;
    00161     sock = new KSocket(serverHost.ascii(), hostPort);
    00162
    00163     if(sock == 0L || sock->socket() < 0) {
    00164         timeOutTimer.stop();
    00165         kdDebug() << "connection failed!" << endl;
    00166         socketClose(sock);
    00167         emit error(CONNECTERROR);
    00168         connected = false;
    00169         return;
    00170     }
    00171     connected = true;
    00172     finished = false;
    00173     state = INIT;
    00174     serverState = NONE;
    00175
    00176     connect(sock, SIGNAL(readEvent(KSocket *)), this, SLOT(socketRead(KSocket *)));
    00177     connect(sock, SIGNAL(closeEvent(KSocket *)), this, SLOT(socketClose(KSocket *)));
    00178     //    sock->enableRead(true);
    00179     timeOutTimer.stop();
    00180     kdDebug() << "connected" << endl;
    00181 }
    00182
    00183 void SMTP::connectTimedOut(void)
    00184 {
    00185     timeOutTimer.stop();
    00186
    00187     if(sock)
    00188     sock->enableRead(false);
    00189     kdDebug() << "socket connection timed out" << endl;
    00190     socketClose(sock);
    00191     emit error(CONNECTTIMEOUT);
    00192 }
    00193
    00194 void SMTP::interactTimedOut(void)
    00195 {
    00196     interactTimer.stop();
    00197
    00198     if(sock)
    00199         sock->enableRead(false);
    00200     kdDebug() << "time out waiting for server interaction" << endl;
    00201     socketClose(sock);
    00202     emit error(INTERACTTIMEOUT);
    00203 }
    00204
    00205 void SMTP::socketRead(KSocket *socket)
    00206 {
    00207     int n, nl;
    00208
    00209     kdDebug() << "socketRead() called..." << endl;
    00210     interactTimer.stop();
    00211
    00212     if(socket == 0L || socket->socket() < 0)
    00213         return;
    00214     n = read(socket->socket(), readBuffer, SMTP_READ_BUFFER_SIZE-1 );
    00215     readBuffer[n] = '\0';
    00216     lineBuffer += readBuffer;
    00217     nl = lineBuffer.find('\n');
    00218     if(nl == -1)
    00219         return;
    00220     lastLine = lineBuffer.left(nl);
    00221     lineBuffer = lineBuffer.right(lineBuffer.length() - nl - 1);
    00222     processLine(&lastLine);
    00223     if(connected)
    00224         interactTimer.start(timeOut, true);
    00225 }
    00226
    00227 void SMTP::socketClose(KSocket *socket)
    00228 {
    00229     timeOutTimer.stop();
    00230     disconnect(sock, SIGNAL(readEvent(KSocket *)), this, SLOT(socketRead(KSocket *)));
    00231     disconnect(sock, SIGNAL(closeEvent(KSocket *)), this, SLOT(socketClose(KSocket *)));
    00232     socket->enableRead(false);
    00233     kdDebug() << "connection terminated" << endl;
    00234     connected = false;
    00235     if(socket){
    00236         delete socket;
    00237         socket = 0L;
    00238         sock = 0L;
    00239     }
    00240     emit connectionClosed();
    00241 }
    00242
    00243 void SMTP::processLine(QString *line)
    00244 {
    00245     int i, stat;
    00246     QString tmpstr;
    00247
    00248     i = line->find(' ');
    00249     tmpstr = line->left(i);
    00250     if(i > 3)
    00251         kdDebug() << "warning: SMTP status code longer then 3 digits: " << tmpstr << endl;
    00252     stat = tmpstr.toInt();
    00253     serverState = (SMTPServerStatus)stat;
    00254     lastState = state;
    00255
    00256     kdDebug() << "smtp state: [" << stat << "][" << *line << "]" << endl;
    00257
    00258     switch(stat){
    00259     case GREET:     //220
    00260         state = IN;
    00261         writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
    00262         kdDebug() << "out: " << writeString << endl;
    00263     write(sock->socket(), writeString.ascii(), writeString.length());
    00264         break;
    00265     case GOODBYE:   //221
    00266         state = QUIT;
    00267         break;
    00268     case SUCCESSFUL://250
    00269         switch(state){
    00270         case IN:
    00271             state = READY;
    00272             writeString = QString::fromLatin1("mail from: %1\r\n").arg(senderAddress);
    00273             kdDebug() << "out: " << writeString << endl;
    00274             write(sock->socket(), writeString.ascii(), writeString.length());
    00275             break;
    00276         case READY:
    00277             state = SENTFROM;
    00278             writeString = QString::fromLatin1("rcpt to: %1\r\n").arg(recipientAddress);
    00279              kdDebug() << "out: " << writeString << endl;
    00280             write(sock->socket(), writeString.ascii(), writeString.length());
    00281             break;
    00282         case SENTFROM:
    00283             state = SENTTO;
    00284             writeString = QString::fromLatin1("data\r\n");
    00285              kdDebug() << "out: " << writeString << endl;
    00286             write(sock->socket(), writeString.ascii(), writeString.length());
    00287             break;
    00288         case DATA:
    00289             state = FINISHED;
    00290             finished = true;
    00291             sock->enableRead(false);
    00292             emit messageSent();
    00293             break;
    00294         default:
    00295             state = CERROR;
    00296             kdDebug() << "smtp error (state error): [" << lastState << "]:[" << stat << "][" << *line << "]" << endl;
    00297             socketClose(sock);
    00298             emit error(COMMAND);
    00299             break;
    00300         }
    00301         break;
    00302     case READYDATA: //354
    00303         state = DATA;
    00304         writeString = QString::fromLatin1("Subject: %1\r\n").arg(messageSubject);
    00305         writeString += messageHeader;
    00306         writeString += "\r\n";
    00307         writeString += messageBody;
    00308         writeString += QString::fromLatin1(".\r\n");
    00309         kdDebug() << "out: " << writeString;
    00310         write(sock->socket(), writeString.ascii(), writeString.length());
    00311         break;
    00312     case ERROR:     //501
    00313         state = CERROR;
    00314         kdDebug() << "smtp error (command error): [" << lastState << "]:[" << stat << "][" << *line << "]\n" << endl;
    00315         socketClose(sock);
    00316         emit error(COMMAND);
    00317         break;
    00318     case UNKNOWN:   //550
    00319         state = CERROR;
    00320         kdDebug() << "smtp error (unknown user): [" << lastState << "]:[" << stat << "][" << *line << "]" << endl;
    00321         socketClose(sock);
    00322         emit error(UNKNOWNUSER);
    00323         break;
    00324     default:
    00325         state = CERROR;
    00326         kdDebug() << "unknown response: [" << lastState << "]:[" << stat << "][" << *line << "]" << endl;
    00327         socketClose(sock);
    00328         emit error(UNKNOWNRESPONSE);
    00329     }
    00330 }
    00331
    00332 #include "smtp.moc"

This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:24:08 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003