/**************************************************************************** ** ** This file is a modified version of part of an example program for TQt. ** This file may be used, distributed and modified without limitation. ** ** Don Sanders ** *****************************************************************************/ #include "smtp.h" #include #include #include #include #include #include Smtp::Smtp( const TQString &from, const TQStringList &to, const TQString &aMessage, const TQString &server, unsigned short int port ) { skipReadResponse = false; mSocket = new TQSocket( this ); connect ( mSocket, TQ_SIGNAL( readyRead() ), this, TQ_SLOT( readyRead() ) ); connect ( mSocket, TQ_SIGNAL( connected() ), this, TQ_SLOT( connected() ) ); connect ( mSocket, TQ_SIGNAL( error(int) ), this, TQ_SLOT( socketError(int) ) ); message = aMessage; this->from = from; rcpt = to; state = smtpInit; command = ""; emit status( i18n( "Connecting to %1" ).arg( server ) ); mSocket->connectToHost( server, port ); t = new TQTextStream( mSocket ); t->setEncoding(TQTextStream::Latin1); } Smtp::~Smtp() { if (t) delete t; if (mSocket) delete mSocket; } void Smtp::send( const TQString &from, const TQStringList &to, const TQString &aMessage ) { skipReadResponse = true; message = aMessage; this->from = from; rcpt = to; state = smtpMail; command = ""; readyRead(); } void Smtp::quit() { skipReadResponse = true; state = smtpQuit; command = ""; readyRead(); } void Smtp::connected() { emit status( i18n( "Connected to %1" ).arg( mSocket->peerName() ) ); } void Smtp::socketError(int errorCode) { command = "CONNECT"; switch ( errorCode ) { case TQSocket::ErrConnectionRefused: responseLine = i18n( "Connection refused." ); break; case TQSocket::ErrHostNotFound: responseLine = i18n( "Host Not Found." ); break; case TQSocket::ErrSocketRead: responseLine = i18n( "Error reading socket." ); break; default: responseLine = i18n( "Internal error, unrecognized error." ); } TQTimer::singleShot( 0, this, TQ_SLOT(emitError()) ); } void Smtp::emitError() { error( command, responseLine ); } void Smtp::readyRead() { if (!skipReadResponse) { // SMTP is line-oriented if ( !mSocket->canReadLine() ) return; do { responseLine = mSocket->readLine(); response += responseLine; } while( mSocket->canReadLine() && responseLine[3] != ' ' ); } skipReadResponse = false; if ( state == smtpInit && responseLine[0] == '2' ) { // banner was okay, let's go on command = "HELO there"; *t << "HELO there\r\n"; state = smtpMail; } else if ( state == smtpMail && responseLine[0] == '2' ) { // HELO response was okay (well, it has to be) command = "MAIL"; *t << "MAIL FROM: <" << from << ">\r\n"; state = smtpRcpt; } else if ( state == smtpRcpt && responseLine[0] == '2' && (rcpt.begin() != rcpt.end())) { command = "RCPT"; *t << "RCPT TO: <" << *(rcpt.begin()) << ">\r\n"; rcpt.remove( rcpt.begin() ); if (rcpt.begin() == rcpt.end()) state = smtpData; } else if ( state == smtpData && responseLine[0] == '2' ) { command = "DATA"; *t << "DATA\r\n"; state = smtpBody; } else if ( state == smtpBody && responseLine[0] == '3' ) { command = "DATA"; TQString seperator = ""; if (message[message.length() - 1] != '\n') seperator = "\r\n"; *t << message << seperator << ".\r\n"; state = smtpSuccess; } else if ( state == smtpSuccess && responseLine[0] == '2' ) { TQTimer::singleShot( 0, this, TQ_SIGNAL(success()) ); } else if ( state == smtpQuit && responseLine[0] == '2' ) { command = "QUIT"; *t << "QUIT\r\n"; // here, we just close. state = smtpClose; emit status( i18n( "Message sent" ) ); } else if ( state == smtpClose ) { // we ignore it } else { // error occurred TQTimer::singleShot( 0, this, TQ_SLOT(emitError()) ); state = smtpClose; } response = ""; if ( state == smtpClose ) { delete t; t = 0; delete mSocket; mSocket = 0; TQTimer::singleShot( 0, this, TQ_SLOT(deleteMe()) ); } } void Smtp::deleteMe() { delete this; } #include "smtp.moc"