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

kio

smtp.cpp

Go to the documentation of this file.
00001 /* $Id: smtp.cpp 532141 2006-04-21 10:38:02Z cartman $ */
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 
00216     if(n < 0)
00217         return;
00218 
00219     readBuffer[n] = '\0';
00220     lineBuffer += readBuffer;
00221     nl = lineBuffer.find('\n');
00222     if(nl == -1)
00223         return;
00224     lastLine = lineBuffer.left(nl);
00225     lineBuffer = lineBuffer.right(lineBuffer.length() - nl - 1);
00226     processLine(&lastLine);
00227     if(connected)
00228         interactTimer.start(timeOut, true);
00229 }
00230 
00231 void SMTP::socketClose(KSocket *socket)
00232 {
00233     timeOutTimer.stop();
00234     disconnect(sock, SIGNAL(readEvent(KSocket *)), this, SLOT(socketRead(KSocket *)));
00235     disconnect(sock, SIGNAL(closeEvent(KSocket *)), this, SLOT(socketClose(KSocket *)));
00236     socket->enableRead(false);
00237     kdDebug() << "connection terminated" << endl;
00238     connected = false;
00239     if(socket){
00240         delete socket;
00241         socket = 0L;
00242         sock = 0L;
00243     }
00244     emit connectionClosed();
00245 }
00246 
00247 void SMTP::processLine(QString *line)
00248 {
00249     int i, stat;
00250     QString tmpstr;
00251 
00252     i = line->find(' ');
00253     tmpstr = line->left(i);
00254     if(i > 3)
00255         kdDebug() << "warning: SMTP status code longer then 3 digits: " << tmpstr << endl;
00256     stat = tmpstr.toInt();
00257     serverState = (SMTPServerStatus)stat;
00258     lastState = state;
00259 
00260     kdDebug() << "smtp state: [" << stat << "][" << *line << "]" << endl;
00261 
00262     switch(stat){
00263     case GREET:     //220
00264         state = IN;
00265         writeString = QString::fromLatin1("helo %1\r\n").arg(domainName);
00266         kdDebug() << "out: " << writeString << endl;
00267     write(sock->socket(), writeString.ascii(), writeString.length());
00268         break;
00269     case GOODBYE:   //221
00270         state = QUIT;
00271         break;
00272     case SUCCESSFUL://250
00273         switch(state){
00274         case IN:
00275             state = READY;
00276             writeString = QString::fromLatin1("mail from: %1\r\n").arg(senderAddress);
00277             kdDebug() << "out: " << writeString << endl;
00278             write(sock->socket(), writeString.ascii(), writeString.length());
00279             break;
00280         case READY:
00281             state = SENTFROM;
00282             writeString = QString::fromLatin1("rcpt to: %1\r\n").arg(recipientAddress);
00283              kdDebug() << "out: " << writeString << endl;
00284             write(sock->socket(), writeString.ascii(), writeString.length());
00285             break;
00286         case SENTFROM:
00287             state = SENTTO;
00288             writeString = QString::fromLatin1("data\r\n");
00289              kdDebug() << "out: " << writeString << endl;
00290             write(sock->socket(), writeString.ascii(), writeString.length());
00291             break;
00292         case DATA:
00293             state = FINISHED;
00294             finished = true;
00295             sock->enableRead(false);
00296             emit messageSent();
00297             break;
00298         default:
00299             state = CERROR;
00300             kdDebug() << "smtp error (state error): [" << lastState << "]:[" << stat << "][" << *line << "]" << endl;
00301             socketClose(sock);
00302             emit error(COMMAND);
00303             break;
00304         }
00305         break;
00306     case READYDATA: //354
00307         state = DATA;
00308         writeString = QString::fromLatin1("Subject: %1\r\n").arg(messageSubject);
00309         writeString += messageHeader;
00310         writeString += "\r\n";
00311         writeString += messageBody;
00312         writeString += QString::fromLatin1(".\r\n");
00313         kdDebug() << "out: " << writeString;
00314         write(sock->socket(), writeString.ascii(), writeString.length());
00315         break;
00316     case ERROR:     //501
00317         state = CERROR;
00318         kdDebug() << "smtp error (command error): [" << lastState << "]:[" << stat << "][" << *line << "]\n" << endl;
00319         socketClose(sock);
00320         emit error(COMMAND);
00321         break;
00322     case UNKNOWN:   //550
00323         state = CERROR;
00324         kdDebug() << "smtp error (unknown user): [" << lastState << "]:[" << stat << "][" << *line << "]" << endl;
00325         socketClose(sock);
00326         emit error(UNKNOWNUSER);
00327         break;
00328     default:
00329         state = CERROR;
00330         kdDebug() << "unknown response: [" << lastState << "]:[" << stat << "][" << *line << "]" << endl;
00331         socketClose(sock);
00332         emit error(UNKNOWNRESPONSE);
00333     }
00334 }
00335 
00336 #include "smtp.moc"

kio

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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