|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** 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 <sanders@kde.org>
|
|
|
|
**
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
#include "smtp.h"
|
|
|
|
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
#include <tqsocket.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
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, TQT_SIGNAL( readyRead() ),
|
|
|
|
this, TQT_SLOT( readyRead() ) );
|
|
|
|
connect ( mSocket, TQT_SIGNAL( connected() ),
|
|
|
|
this, TQT_SLOT( connected() ) );
|
|
|
|
connect ( mSocket, TQT_SIGNAL( error(int) ),
|
|
|
|
this, TQT_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, TQT_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, TQT_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, TQT_SLOT(emitError()) );
|
|
|
|
state = smtpClose;
|
|
|
|
}
|
|
|
|
|
|
|
|
response = "";
|
|
|
|
|
|
|
|
if ( state == smtpClose ) {
|
|
|
|
delete t;
|
|
|
|
t = 0;
|
|
|
|
delete mSocket;
|
|
|
|
mSocket = 0;
|
|
|
|
TQTimer::singleShot( 0, this, TQT_SLOT(deleteMe()) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Smtp::deleteMe()
|
|
|
|
{
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "smtp.moc"
|