kio Library API Documentation

smtp.cpp

00001 /* $Id: smtp.cpp,v 1.8 2003/09/10 00:12:17 wheeler Exp $ */ 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@host.ext"; 00020 recipientAddress = "user@host.ext"; 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.nowhere.org"; 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"
KDE Logo
This file is part of the documentation for kio Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 16 17:22:33 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003