summaryrefslogtreecommitdiffstats
path: root/kioslave/smtp
diff options
context:
space:
mode:
Diffstat (limited to 'kioslave/smtp')
-rw-r--r--kioslave/smtp/CMakeLists.txt37
-rw-r--r--kioslave/smtp/Makefile.am37
-rw-r--r--kioslave/smtp/TODO11
-rw-r--r--kioslave/smtp/capabilities.cc143
-rw-r--r--kioslave/smtp/capabilities.h77
-rw-r--r--kioslave/smtp/command.cc606
-rw-r--r--kioslave/smtp/command.h283
-rw-r--r--kioslave/smtp/compliance.txt33
-rw-r--r--kioslave/smtp/interactivesmtpserver.cc127
-rw-r--r--kioslave/smtp/interactivesmtpserver.h121
-rw-r--r--kioslave/smtp/request.cc189
-rw-r--r--kioslave/smtp/request.h100
-rw-r--r--kioslave/smtp/response.cc160
-rw-r--r--kioslave/smtp/response.h125
-rw-r--r--kioslave/smtp/smtp.cc647
-rw-r--r--kioslave/smtp/smtp.h148
-rw-r--r--kioslave/smtp/smtp.protocol16
-rw-r--r--kioslave/smtp/smtps.protocol15
-rw-r--r--kioslave/smtp/test_commands.cc728
-rw-r--r--kioslave/smtp/test_headergeneration.cc86
-rw-r--r--kioslave/smtp/test_responseparser.cc107
-rw-r--r--kioslave/smtp/transactionstate.cc114
-rw-r--r--kioslave/smtp/transactionstate.h185
23 files changed, 0 insertions, 4095 deletions
diff --git a/kioslave/smtp/CMakeLists.txt b/kioslave/smtp/CMakeLists.txt
deleted file mode 100644
index af475cbc6..000000000
--- a/kioslave/smtp/CMakeLists.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-#################################################
-#
-# (C) 2010-2011 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-include_directories(
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_BINARY_DIR}
- ${TDE_INCLUDE_DIR}
- ${TQT_INCLUDE_DIRS}
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### other data ################################
-
-install( FILES smtp.protocol smtps.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
-
-
-##### kio_smtp (module) #########################
-
-set( target kio_smtp )
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES smtp.cc request.cc response.cc capabilities.cc command.cc transactionstate.cc
- LINK kio-shared ${SASL_LIBRARIES}
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
diff --git a/kioslave/smtp/Makefile.am b/kioslave/smtp/Makefile.am
deleted file mode 100644
index a3ec64a14..000000000
--- a/kioslave/smtp/Makefile.am
+++ /dev/null
@@ -1,37 +0,0 @@
-
-INCLUDES= -I$(srcdir)/../.. -I$(srcdir)/.. $(SSL_INCLUDES) $(all_includes)
-
-kde_module_LTLIBRARIES = kio_smtp.la
-
-kio_smtp_la_SOURCES = smtp.cc request.cc response.cc capabilities.cc command.cc transactionstate.cc
-kio_smtp_la_LIBADD = $(LIB_KIO) $(SASL2_LIBS)
-kio_smtp_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
-
-noinst_HEADERS = smtp.h request.h response.h capabilities.h command.h transactionstate.h
-
-kdelnk_DATA = smtp.protocol smtps.protocol
-kdelnkdir = $(kde_servicesdir)
-
-TESTS = test_headergeneration test_responseparser test_commands
-
-check_PROGRAMS = $(TESTS) interactivesmtpserver
-
-test_headergeneration_SOURCES = test_headergeneration.cc
-test_headergeneration_LDADD = $(LIB_TDECORE)
-test_headergeneration_LDFLAGS = $(all_libraries)
-
-test_responseparser_SOURCES = test_responseparser.cc
-test_responseparser_LDADD = $(LIB_TDECORE)
-test_responseparser_LDFLAGS = $(all_libraries)
-
-test_commands_SOURCES = test_commands.cc
-test_commands_LDADD = $(kio_smtp_la_LIBADD)
-test_commands_LDFLAGS = $(all_libraries)
-
-interactivesmtpserver_SOURCES = interactivesmtpserver.cc
-interactivesmtpserver_LDADD = $(LIB_QT)
-interactivesmtpserver_LDFLAGS = $(all_libraries)
-interactivesmtpserver_METASOURCES = AUTO
-
-messages:
- $(XGETTEXT) *.cc -o $(podir)/kio_smtp.pot
diff --git a/kioslave/smtp/TODO b/kioslave/smtp/TODO
deleted file mode 100644
index cad79f139..000000000
--- a/kioslave/smtp/TODO
+++ /dev/null
@@ -1,11 +0,0 @@
-1. Double check the error handling and review error message in various
- failure modes.
-2. Implement the CHUNKING extension (rfc 3030; as soon as I find an
- SMTP server that supports it).
-3. Better error message (translated standard meanings of the known
- response codes, ENHANCEDSTATUSCODES extension (rfc2034)).
-4. (KIO) MultiPutJob to support pipelining across messages.
-5. Ged rid of slave's header generation after checking who on earth
- uses that...
-
-and further refactoring to make the code pleasant to look at ;-)
diff --git a/kioslave/smtp/capabilities.cc b/kioslave/smtp/capabilities.cc
deleted file mode 100644
index 0172934dd..000000000
--- a/kioslave/smtp/capabilities.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*- c++ -*-
- capabilities.cc
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#include <config.h>
-
-#include "capabilities.h"
-
-#include "response.h"
-
-#include <tqstrlist.h>
-
-namespace KioSMTP {
-
- Capabilities Capabilities::fromResponse( const Response & ehlo ) {
- Capabilities c;
-
- // first, check whether the response was valid and indicates success:
- if ( !ehlo.isOk()
- || ehlo.code() / 10 != 25 // ### restrict to 250 only?
- || ehlo.lines().empty() )
- return c;
-
- QCStringList l = ehlo.lines();
-
- for ( QCStringList::const_iterator it = ++l.begin() ; it != l.end() ; ++it )
- c.add( *it );
-
- return c;
- }
-
- void Capabilities::add( const TQString & cap, bool replace ) {
- TQStringList tokens = TQStringList::split( ' ', cap.upper() );
- if ( tokens.empty() )
- return;
- TQString name = tokens.front(); tokens.pop_front();
- add( name, tokens, replace );
- }
-
- void Capabilities::add( const TQString & name, const TQStringList & args, bool replace ) {
- if ( replace )
- mCapabilities[name] = args;
- else
- mCapabilities[name] += args;
- }
-
- TQString Capabilities::asMetaDataString() const {
- TQString result;
- for ( TQMap<TQString,TQStringList>::const_iterator it = mCapabilities.begin() ; it != mCapabilities.end() ; ++it ) {
- result += it.key();
- if ( !it.data().empty() )
- result += ' ' + it.data().join( " " );
- result += '\n';
- }
- return result;
- }
-
- TQString Capabilities::authMethodMetaData() const {
- TQStringList sl = saslMethodsQSL();
- TQString result;
- for ( TQStringList::const_iterator it = sl.begin() ; it != sl.end() ; ++it )
- result += "SASL/" + *it + '\n';
- return result;
- }
-
- TQStrIList Capabilities::saslMethods() const {
- TQStrIList result( true ); // deep copies to be safe
- TQStringList sl = saslMethodsQSL();
- for ( TQStringList::const_iterator it = sl.begin() ; it != sl.end() ; ++it )
- result.append( (*it).latin1() );
- return result;
- }
-
- TQString Capabilities::createSpecialResponse( bool tls ) const {
- TQStringList result;
- if ( tls )
- result.push_back( "STARTTLS" );
- result += saslMethodsQSL();
- if ( have( "PIPELINING" ) )
- result.push_back( "PIPELINING" );
- if ( have( "8BITMIME" ) )
- result.push_back( "8BITMIME" );
- if ( have( "SIZE" ) ) {
- bool ok = false;
- unsigned int size = mCapabilities["SIZE"].front().toUInt( &ok );
- if ( ok && !size )
- result.push_back( "SIZE=*" ); // any size
- else if ( ok )
- result.push_back( "SIZE=" + TQString::number( size ) ); // fixed max
- else
- result.push_back( "SIZE" ); // indetermined
- }
- return result.join( " " );
- }
-
- TQStringList Capabilities::saslMethodsQSL() const {
- TQStringList result;
- for ( TQMap<TQString,TQStringList>::const_iterator it = mCapabilities.begin() ; it != mCapabilities.end() ; ++it ) {
- if ( it.key() == "AUTH" )
- result += it.data();
- else if ( it.key().startsWith( "AUTH=" ) ) {
- result.push_back( it.key().mid( tqstrlen("AUTH=") ) );
- result += it.data();
- }
- }
- result.sort();
- TQStringList::iterator it = result.begin();
- for (TQStringList::iterator ot = it++; it != result.end(); ot = it++)
- if (*ot == *it) result.remove(ot);
- return result;
- }
-
-
-
-} // namespace KioSMTP
-
diff --git a/kioslave/smtp/capabilities.h b/kioslave/smtp/capabilities.h
deleted file mode 100644
index 9f9464104..000000000
--- a/kioslave/smtp/capabilities.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- c++ -*-
- capabilities.h
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#ifndef __KIOSMTP_CAPABILITIES_H__
-#define __KIOSMTP_CAPABILITIES_H__
-
-#include <tqmap.h>
-#include <tqcstring.h>
-#include <tqstring.h>
-#include <tqstringlist.h>
-
-class TQStrIList;
-
-namespace KioSMTP {
-
- class Response;
-
- class Capabilities {
- public:
- Capabilities() {}
-
- static Capabilities fromResponse( const Response & response );
-
- void add( const TQString & cap, bool replace=false );
- void add( const TQString & name, const TQStringList & args, bool replace=false );
- void clear() { mCapabilities.clear(); }
-
- bool have( const TQString & cap ) const {
- return mCapabilities.find( cap.upper() ) != mCapabilities.end();
- }
- bool have( const TQCString & cap ) const { return have( TQString( cap.data() ) ); }
- bool have( const char * cap ) const { return have( TQString::fromLatin1( cap ) ); }
-
- TQString asMetaDataString() const;
-
- TQString authMethodMetaData() const;
- TQStrIList saslMethods() const;
-
- TQString createSpecialResponse( bool tls ) const;
-
- TQStringList saslMethodsQSL() const;
- private:
-
- TQMap<TQString,TQStringList> mCapabilities;
- };
-
-} // namespace KioSMTP
-
-#endif // __KIOSMTP_CAPABILITIES_H__
diff --git a/kioslave/smtp/command.cc b/kioslave/smtp/command.cc
deleted file mode 100644
index 2971c291a..000000000
--- a/kioslave/smtp/command.cc
+++ /dev/null
@@ -1,606 +0,0 @@
-/* -*- c++ -*-
- command.cc
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#include <config.h>
-
-#include "command.h"
-
-#include "smtp.h"
-#include "response.h"
-#include "transactionstate.h"
-
-#include <kidna.h>
-#include <klocale.h>
-#include <kdebug.h>
-#include <kmdcodec.h>
-#include <kio/slavebase.h> // for test_commands, where SMTPProtocol is not derived from TCPSlaveBase
-
-#include <assert.h>
-
-namespace KioSMTP {
-
-#ifdef HAVE_LIBSASL2
-static sasl_callback_t callbacks[] = {
- { SASL_CB_ECHOPROMPT, NULL, NULL },
- { SASL_CB_NOECHOPROMPT, NULL, NULL },
- { SASL_CB_GETREALM, NULL, NULL },
- { SASL_CB_USER, NULL, NULL },
- { SASL_CB_AUTHNAME, NULL, NULL },
- { SASL_CB_PASS, NULL, NULL },
- { SASL_CB_CANON_USER, NULL, NULL },
- { SASL_CB_LIST_END, NULL, NULL }
-};
-#endif
-
- //
- // Command (base class)
- //
-
- Command::Command( SMTPProtocol * smtp, int flags )
- : mSMTP( smtp ),
- mComplete( false ), mNeedResponse( false ), mFlags( flags )
- {
- assert( smtp );
- }
-
- Command::~Command() {}
-
- bool Command::processResponse( const Response & r, TransactionState * ) {
- mComplete = true;
- mNeedResponse = false;
- return r.isOk();
- }
-
- void Command::ungetCommandLine( const TQCString &, TransactionState * ) {
- mComplete = false;
- }
-
- Command * Command::createSimpleCommand( int which, SMTPProtocol * smtp ) {
- switch ( which ) {
- case STARTTLS: return new StartTLSCommand( smtp );
- case DATA: return new DataCommand( smtp );
- case NOOP: return new NoopCommand( smtp );
- case RSET: return new RsetCommand( smtp );
- case QUIT: return new QuitCommand( smtp );
- default: return 0;
- }
- }
-
- //
- // relay methods:
- //
-
- void Command::parseFeatures( const Response & r ) {
- mSMTP->parseFeatures( r );
- }
-
- int Command::startTLS() {
- return mSMTP->startTLS();
- }
-
- bool Command::usingSSL() const {
- return mSMTP->usingSSL();
- }
-
- bool Command::usingTLS() const {
- return mSMTP->usingTLS();
- }
-
- bool Command::haveCapability( const char * cap ) const {
- return mSMTP->haveCapability( cap );
- }
-
- //
- // EHLO / HELO
- //
-
- TQCString EHLOCommand::nextCommandLine( TransactionState * ) {
- mNeedResponse = true;
- mComplete = mEHLONotSupported;
- const char * cmd = mEHLONotSupported ? "HELO " : "EHLO " ;
- return cmd + KIDNA::toAsciiCString( mHostname ) + "\r\n";
- }
-
- bool EHLOCommand::processResponse( const Response & r, TransactionState * ) {
- mNeedResponse = false;
- // "command not {recognized,implemented}" response:
- if ( r.code() == 500 || r.code() == 502 ) {
- if ( mEHLONotSupported ) { // HELO failed...
- mSMTP->error( TDEIO::ERR_INTERNAL_SERVER,
- i18n("The server rejected both EHLO and HELO commands "
- "as unknown or unimplemented.\n"
- "Please contact the server's system administrator.") );
- return false;
- }
- mEHLONotSupported = true; // EHLO failed, but that's ok.
- return true;
- }
- mComplete = true;
- if ( r.code() / 10 == 25 ) { // 25x: success
- parseFeatures( r );
- return true;
- }
- mSMTP->error( TDEIO::ERR_UNKNOWN,
- i18n("Unexpected server response to %1 command.\n%2")
- .arg( mEHLONotSupported ? "HELO" : "EHLO" )
- .arg( r.errorMessage() ) );
- return false;
- }
-
- //
- // STARTTLS - rfc 3207
- //
-
- TQCString StartTLSCommand::nextCommandLine( TransactionState * ) {
- mComplete = true;
- mNeedResponse = true;
- return "STARTTLS\r\n";
- }
-
- bool StartTLSCommand::processResponse( const Response & r, TransactionState * ) {
- mNeedResponse = false;
- if ( r.code() != 220 ) {
- mSMTP->error( r.errorCode(),
- i18n("Your SMTP server does not support TLS. "
- "Disable TLS, if you want to connect "
- "without encryption.") );
- return false;
- }
-
- int tlsrc = startTLS();
-
- if ( tlsrc == 1 )
- return true;
-
- if ( tlsrc != -3 )
- //kdDebug(7112) << "TLS negotiation failed!" << endl;
- mSMTP->messageBox(TDEIO::SlaveBase::Information,
- i18n("Your SMTP server claims to "
- "support TLS, but negotiation "
- "was unsuccessful.\nYou can "
- "disable TLS in KDE using the "
- "crypto settings module."),
- i18n("Connection Failed"));
- return false;
- }
-
-
-#define SASLERROR mSMTP->error(TDEIO::ERR_COULD_NOT_AUTHENTICATE, \
- i18n("An error occured during authentication: %1").arg \
- ( TQString::fromUtf8( sasl_errdetail( conn ) )));
-
- //
- // AUTH - rfc 2554
- //
- AuthCommand::AuthCommand( SMTPProtocol * smtp,
- const char *mechanisms,
- const TQString &aFQDN,
- TDEIO::AuthInfo &ai )
- : Command( smtp, CloseConnectionOnError|OnlyLastInPipeline ),
- mAi( &ai ),
- mFirstTime( true )
- {
-#ifdef HAVE_LIBSASL2
- int result;
- mMechusing = 0;
- conn = 0;
- client_interact = 0;
- mOut = 0; mOutlen = 0;
- mOneStep = false;
-
- result = sasl_client_new( "smtp", aFQDN.latin1(),
- 0, 0, callbacks, 0, &conn );
- if ( result != SASL_OK ) {
- SASLERROR
- return;
- }
- do {
- result = sasl_client_start(conn, mechanisms,
- &client_interact, &mOut, &mOutlen, &mMechusing);
-
- if (result == SASL_INTERACT)
- if ( !saslInteract( client_interact ) ) {
- return;
- };
- } while ( result == SASL_INTERACT );
- if ( result != SASL_CONTINUE && result != SASL_OK ) {
- SASLERROR
- return;
- }
- if ( result == SASL_OK ) mOneStep = true;
- kdDebug(7112) << "Mechanism: " << mMechusing << " one step: " << mOneStep << endl;
-#else
- mSMTP->error(TDEIO::ERR_COULD_NOT_AUTHENTICATE,
- i18n("Authentication support is not compiled into kio_smtp."));
-#endif
- }
-
- AuthCommand::~AuthCommand()
- {
-#ifdef HAVE_LIBSASL2
- if ( conn ) {
- kdDebug(7112) << "dispose sasl connection" << endl;
- sasl_dispose( &conn );
- conn = 0;
- }
-#endif
- }
-
- bool AuthCommand::saslInteract( void *in )
- {
-#ifdef HAVE_LIBSASL2
- kdDebug(7112) << "saslInteract: " << endl;
- sasl_interact_t *interact = ( sasl_interact_t * ) in;
-
- //some mechanisms do not require username && pass, so don't need a popup
- //window for getting this info
- for ( ; interact->id != SASL_CB_LIST_END; interact++ ) {
- if ( interact->id == SASL_CB_AUTHNAME ||
- interact->id == SASL_CB_PASS ) {
-
- if ( mAi->username.isEmpty() || mAi->password.isEmpty()) {
- if (!mSMTP->openPassDlg(*mAi)) {
- mSMTP->error(TDEIO::ERR_ABORTED, i18n("No authentication details supplied."));
- return false;
- }
- }
- break;
- }
- }
-
- interact = ( sasl_interact_t * ) in;
- while( interact->id != SASL_CB_LIST_END ) {
- switch( interact->id ) {
- case SASL_CB_USER:
- case SASL_CB_AUTHNAME:
- kdDebug(7112) << "SASL_CB_[USER|AUTHNAME]: " << mAi->username << endl;
- interact->result = strdup( mAi->username.utf8() );
- interact->len = strlen( (const char *) interact->result );
- break;
- case SASL_CB_PASS:
- kdDebug(7112) << "SASL_CB_PASS: [HIDDEN]" << endl;
- interact->result = strdup( mAi->password.utf8() );
- interact->len = strlen( (const char *) interact->result );
- break;
- default:
- interact->result = NULL; interact->len = 0;
- break;
- }
- interact++;
- }
- return true;
-#else
- return false;
-#endif
- }
-
- bool AuthCommand::doNotExecute( const TransactionState * ) const {
- return !mMechusing;
- }
-
- void AuthCommand::ungetCommandLine( const TQCString & s, TransactionState * ) {
- mUngetSASLResponse = s;
- mComplete = false;
- }
-
- TQCString AuthCommand::nextCommandLine( TransactionState * ) {
- mNeedResponse = true;
- TQCString cmd;
-#ifdef HAVE_LIBSASL2
- TQByteArray tmp, challenge;
- if ( !mUngetSASLResponse.isNull() ) {
- // implement un-ungetCommandLine
- cmd = mUngetSASLResponse;
- mUngetSASLResponse = 0;
- } else if ( mFirstTime ) {
- TQString firstCommand = "AUTH " + TQString::fromLatin1( mMechusing );
-
- tmp.setRawData( mOut, mOutlen );
- KCodecs::base64Encode( tmp, challenge );
- tmp.resetRawData( mOut, mOutlen );
- if ( !challenge.isEmpty() ) {
- firstCommand += " ";
- firstCommand += TQString::fromLatin1( challenge.data(), challenge.size() );
- }
- cmd = firstCommand.latin1();
-
- if ( mOneStep ) mComplete = true;
- } else {
-// kdDebug(7112) << "SS: '" << mLastChallenge << "'" << endl;
- tmp.setRawData( mLastChallenge.data(), mLastChallenge.length() );
- KCodecs::base64Decode( tmp, challenge );
- tmp.resetRawData( mLastChallenge.data(), mLastChallenge.length() );
- int result;
- do {
- result = sasl_client_step(conn, challenge.isEmpty() ? 0 : challenge.data(),
- challenge.size(),
- &client_interact,
- &mOut, &mOutlen);
- if (result == SASL_INTERACT)
- if ( !saslInteract( client_interact ) ) {
- return "";
- };
- } while ( result == SASL_INTERACT );
- if ( result != SASL_CONTINUE && result != SASL_OK ) {
- kdDebug(7112) << "sasl_client_step failed with: " << result << endl;
- SASLERROR
- return "";
- }
- tmp.setRawData( mOut, mOutlen );
- cmd = KCodecs::base64Encode( tmp );
- tmp.resetRawData( mOut, mOutlen );
-
-// kdDebug(7112) << "CC: '" << cmd << "'" << endl;
- mComplete = ( result == SASL_OK );
- }
-#endif //HAVE_LIBSASL2
- cmd += "\r\n";
- return cmd;
- }
-
- bool AuthCommand::processResponse( const Response & r, TransactionState * ) {
- if ( !r.isOk() ) {
- if ( mFirstTime )
- if ( haveCapability( "AUTH" ) )
- mSMTP->error( TDEIO::ERR_COULD_NOT_LOGIN,
- i18n("Your SMTP server does not support %1.\nChoose a different authentication method.\n%2")
- .arg( mMechusing ).arg( r.errorMessage() ) );
- else
- mSMTP->error( TDEIO::ERR_COULD_NOT_LOGIN,
- i18n("Your SMTP server does not support authentication.\n"
- " %2").arg( r.errorMessage() ) );
- else
- mSMTP->error( TDEIO::ERR_COULD_NOT_LOGIN,
- i18n("Authentication failed.\n"
- "Most likely the password is wrong.\n"
- "%1").arg( r.errorMessage() ) );
- return false;
- }
- mFirstTime = false;
- mLastChallenge = r.lines().front(); // ### better join all lines with \n?
- mNeedResponse = false;
- return true;
- }
-
- //
- // MAIL FROM:
- //
-
- TQCString MailFromCommand::nextCommandLine( TransactionState * ) {
- mComplete = true;
- mNeedResponse = true;
- TQCString cmdLine = "MAIL FROM:<" + mAddr + '>';
- if ( m8Bit && haveCapability("8BITMIME") )
- cmdLine += " BODY=8BITMIME";
- if ( mSize && haveCapability("SIZE") )
- cmdLine += " SIZE=" + TQCString().setNum( mSize );
- return cmdLine + "\r\n";
- }
-
- bool MailFromCommand::processResponse( const Response & r, TransactionState * ts ) {
- assert( ts );
- mNeedResponse = false;
-
- if ( r.code() == 250 )
- return true;
-
- ts->setMailFromFailed( mAddr, r );
- return false;
- }
-
- //
- // RCPT TO:
- //
-
- TQCString RcptToCommand::nextCommandLine( TransactionState * ) {
- mComplete = true;
- mNeedResponse = true;
- return "RCPT TO:<" + mAddr + ">\r\n";
- }
-
- bool RcptToCommand::processResponse( const Response & r, TransactionState * ts ) {
- assert( ts );
- mNeedResponse = false;
-
- if ( r.code() == 250 ) {
- ts->setRecipientAccepted();
- return true;
- }
-
- ts->addRejectedRecipient( mAddr, r.errorMessage() );
- return false;
- }
-
- //
- // DATA (only initial processing!)
- //
-
- TQCString DataCommand::nextCommandLine( TransactionState * ts ) {
- assert( ts );
- mComplete = true;
- mNeedResponse = true;
- ts->setDataCommandIssued( true );
- return "DATA\r\n";
- }
-
- void DataCommand::ungetCommandLine( const TQCString &, TransactionState * ts ) {
- assert( ts );
- mComplete = false;
- ts->setDataCommandIssued( false );
- }
-
- bool DataCommand::processResponse( const Response & r, TransactionState * ts ) {
- assert( ts );
- mNeedResponse = false;
-
- if ( r.code() == 354 ) {
- ts->setDataCommandSucceeded( true, r );
- return true;
- }
-
- ts->setDataCommandSucceeded( false, r );
- return false;
- }
-
- //
- // DATA (data transfer)
- //
- void TransferCommand::ungetCommandLine( const TQCString & cmd, TransactionState * ) {
- if ( cmd.isEmpty() )
- return; // don't change state when we can't detect the unget in
- // the next nextCommandLine !!
- mWasComplete = mComplete;
- mComplete = false;
- mNeedResponse = false;
- mUngetBuffer = cmd;
- }
-
- bool TransferCommand::doNotExecute( const TransactionState * ts ) const {
- assert( ts );
- return ts->failed();
- }
-
- TQCString TransferCommand::nextCommandLine( TransactionState * ts ) {
- assert( ts ); // let's rely on it ( at least for the moment )
- assert( !isComplete() );
- assert( !ts->failed() );
-
- static const TQCString dotCRLF = ".\r\n";
- static const TQCString CRLFdotCRLF = "\r\n.\r\n";
-
- if ( !mUngetBuffer.isEmpty() ) {
- const TQCString ret = mUngetBuffer;
- mUngetBuffer = 0;
- if ( mWasComplete ) {
- mComplete = true;
- mNeedResponse = true;
- }
- return ret; // don't prepare(), it's slave-generated or already prepare()d
- }
-
- // normal processing:
-
- kdDebug(7112) << "requesting data" << endl;
- mSMTP->dataReq();
- TQByteArray ba;
- int result = mSMTP->readData( ba );
- kdDebug(7112) << "got " << result << " bytes" << endl;
- if ( result > 0 )
- return prepare( ba );
- else if ( result < 0 ) {
- ts->setFailedFatally( TDEIO::ERR_INTERNAL,
- i18n("Could not read data from application.") );
- mComplete = true;
- mNeedResponse = true;
- return 0;
- }
- mComplete = true;
- mNeedResponse = true;
- return mLastChar == '\n' ? dotCRLF : CRLFdotCRLF ;
- }
-
- bool TransferCommand::processResponse( const Response & r, TransactionState * ts ) {
- mNeedResponse = false;
- assert( ts );
- ts->setComplete();
- if ( !r.isOk() ) {
- ts->setFailed();
- mSMTP->error( r.errorCode(),
- i18n("The message content was not accepted.\n"
- "%1").arg( r.errorMessage() ) );
- return false;
- }
- return true;
- }
-
- static TQCString dotstuff_lf2crlf( const TQByteArray & ba, char & last ) {
- TQCString result( ba.size() * 2 + 1 ); // worst case: repeated "[.]\n"
- const char * s = ba.data();
- const char * const send = ba.data() + ba.size();
- char * d = result.data();
-
- while ( s < send ) {
- const char ch = *s++;
- if ( ch == '\n' && last != '\r' )
- *d++ = '\r'; // lf2crlf
- else if ( ch == '.' && last == '\n' )
- *d++ = '.'; // dotstuff
- last = *d++ = ch;
- }
-
- result.truncate( d - result.data() );
- return result;
- }
-
- TQCString TransferCommand::prepare( const TQByteArray & ba ) {
- if ( ba.isEmpty() )
- return 0;
- if ( mSMTP->metaData("lf2crlf+dotstuff") == "slave" ) {
- kdDebug(7112) << "performing dotstuffing and LF->CRLF transformation" << endl;
- return dotstuff_lf2crlf( ba, mLastChar );
- } else {
- mLastChar = ba[ ba.size() - 1 ];
- return TQCString( ba.data(), ba.size() + 1 );
- }
- }
-
- //
- // NOOP
- //
-
- TQCString NoopCommand::nextCommandLine( TransactionState * ) {
- mComplete = true;
- mNeedResponse = true;
- return "NOOP\r\n";
- }
-
- //
- // RSET
- //
-
- TQCString RsetCommand::nextCommandLine( TransactionState * ) {
- mComplete = true;
- mNeedResponse = true;
- return "RSET\r\n";
- }
-
- //
- // QUIT
- //
-
- TQCString QuitCommand::nextCommandLine( TransactionState * ) {
- mComplete = true;
- mNeedResponse = true;
- return "QUIT\r\n";
- }
-
-} // namespace KioSMTP
-
diff --git a/kioslave/smtp/command.h b/kioslave/smtp/command.h
deleted file mode 100644
index ed3e1fb66..000000000
--- a/kioslave/smtp/command.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/* -*- c++ -*-
- command.h
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#ifndef __KIOSMTP_COMMAND_H__
-#define __KIOSMTP_COMMAND_H__
-
-
-#include <tqstring.h>
-#include <tqcstring.h>
-
-#ifdef HAVE_LIBSASL2
-extern "C" {
-#include <sasl/sasl.h>
-}
-#endif
-
-#include <kio/authinfo.h>
-
-class SMTPProtocol;
-class TQStrIList;
-
-namespace KioSMTP {
-
- class Response;
- class TransactionState;
-
- /**
- * @short Represents an SMTP command
- *
- * Semantics: A command consists of a series of "command lines"
- * (though that's stretching it a bit for @ref TransferJob and @ref
- * AuthCommand) and responses. There's typically one response for
- * one command line and the command is completed.
- *
- * However, some commands consist of a dialog (command line,
- * response, command line, response,...) where each successive
- * command line is dependant on the previously received response
- * (and thus those commands are not pipelinable). That's why each
- * command signals completion by having it's @ref #isComplete()
- * method return true @em after the last command line to be sent,
- * but @em before the last response to receive. @ref AuthCommand is
- * the principal representative of this kind of command. Because
- * @ref EHLOCommand automatically falls back to HELO in case EHLO
- * isn't supported, it is also of this kind. If completion is
- * signalled before the first command line is issued, it is not to
- * be executed at all.
- *
- * Other commands need to send multiple "command lines" before
- * receiving a single (final) response. @ref TransferCommand is the
- * only representative of this kind of "command". That's why each
- * command signals whether it now expects a response before being
- * able to issue the next command line (if any) by having it's @ref
- * #needsResponse() method return true.
- *
- * Commands whose @ref #nextCommandLine() does not support being
- * called multiple times in a row without changing command state,
- * must reimplement @ref #ungetCommandLine().
- **/
- class Command {
- public:
- enum Flags {
- OnlyLastInPipeline = 1,
- OnlyFirstInPipeline = 2,
- CloseConnectionOnError = 4
- };
-
- Command( SMTPProtocol * smtp, int flags=0 );
- virtual ~Command();
-
- enum Type {
- STARTTLS, DATA, NOOP, RSET, QUIT
- };
-
- static Command * createSimpleCommand( int which, SMTPProtocol * smtp );
-
- virtual TQCString nextCommandLine( TransactionState * ts=0 ) = 0;
- /* Reimplement this if your @ref #nextCommandLine() implementation
- changes state other than @ref mComplete. The default
- implementation just resets @ref mComplete to false. */
- virtual void ungetCommandLine( const TQCString & cmdLine, TransactionState * ts=0 );
- /* Reimplement this if your command need more sophisicated
- response processing than just checking for @ref
- Response::isOk(). The default implementation sets @ref
- mComplete to true, @ref mNeedResponse to false and returns
- whether the response isOk(). */
- virtual bool processResponse( const Response & response, TransactionState * ts=0 );
-
- virtual bool doNotExecute( const TransactionState * ) const { return false; }
-
- bool isComplete() const { return mComplete; }
- /** @return whether the command expects a response now. Some
- commands (most notably AUTH) may consist of a series of
- commands and associated responses until they are
- complete. Others (most notably @ref TransferCommand usually
- send multiple "command lines" before expecting a response. */
- bool needsResponse() const { return mNeedResponse; }
- /** @return whether an error in executing this command is so fatal
- that closing the connection is the only option */
- bool closeConnectionOnError() const {
- return mFlags & CloseConnectionOnError;
- }
- bool mustBeLastInPipeline() const {
- return mFlags & OnlyLastInPipeline;
- }
- bool mustBeFirstInPipeline() const {
- return mFlags & OnlyFirstInPipeline;
- }
-
- protected:
- SMTPProtocol * mSMTP;
- bool mComplete;
- bool mNeedResponse;
- const int mFlags;
-
- protected:
- // only relay methods to enable access to slave-protected methods
- // for subclasses of Command:
- void parseFeatures( const Response & r );
- int startTLS();
- bool usingSSL() const;
- bool usingTLS() const;
- bool haveCapability( const char * cap ) const;
- };
-
- class EHLOCommand : public Command {
- public:
- EHLOCommand( SMTPProtocol * smtp, const TQString & hostname )
- : Command( smtp, CloseConnectionOnError|OnlyLastInPipeline ),
- mEHLONotSupported( false ),
- mHostname( hostname.stripWhiteSpace() ) {}
-
- TQCString nextCommandLine( TransactionState * );
- bool processResponse( const Response & response, TransactionState * );
- private:
- bool mEHLONotSupported;
- TQString mHostname;
- };
-
- class StartTLSCommand : public Command {
- public:
- StartTLSCommand( SMTPProtocol * smtp )
- : Command( smtp, CloseConnectionOnError|OnlyLastInPipeline ) {}
-
- TQCString nextCommandLine( TransactionState * );
- bool processResponse( const Response & response, TransactionState * );
- };
-
- class AuthCommand : public Command {
- public:
- AuthCommand( SMTPProtocol * smtp, const char *mechanisms,
- const TQString &aFQDN, TDEIO::AuthInfo &ai );
- ~AuthCommand();
- bool doNotExecute( const TransactionState * ts ) const;
- TQCString nextCommandLine( TransactionState * );
- void ungetCommandLine( const TQCString & cmdLine, TransactionState * );
- bool processResponse( const Response & response, TransactionState * );
- private:
- bool saslInteract( void *in );
-
-#ifdef HAVE_LIBSASL2
- sasl_conn_t *conn;
- sasl_interact_t *client_interact;
-#endif
- const char *mOut, *mMechusing;
- uint mOutlen;
- bool mOneStep;
-
- TDEIO::AuthInfo *mAi;
- TQCString mLastChallenge;
- TQCString mUngetSASLResponse;
- bool mFirstTime;
- };
-
- class MailFromCommand : public Command {
- public:
- MailFromCommand( SMTPProtocol * smtp, const TQCString & addr,
- bool eightBit=false, unsigned int size=0 )
- : Command( smtp ), mAddr( addr ), m8Bit( eightBit ), mSize( size ) {}
-
- TQCString nextCommandLine( TransactionState * );
- bool processResponse( const Response & response, TransactionState * );
- private:
- TQCString mAddr;
- bool m8Bit;
- unsigned int mSize;
- };
-
- class RcptToCommand : public Command {
- public:
- RcptToCommand( SMTPProtocol * smtp, const TQCString & addr )
- : Command( smtp ), mAddr( addr ) {}
-
- TQCString nextCommandLine( TransactionState * );
- bool processResponse( const Response & response, TransactionState * );
- private:
- TQCString mAddr;
- };
-
- /** Handles only the initial intermediate response and compltetes at
- the point where the mail contents need to be sent */
- class DataCommand : public Command {
- public:
- DataCommand( SMTPProtocol * smtp )
- : Command( smtp, OnlyLastInPipeline ) {}
-
- TQCString nextCommandLine( TransactionState * );
- void ungetCommandLine( const TQCString & cmd, TransactionState * ts );
- bool processResponse( const Response & response, TransactionState * );
- };
-
- /** Handles the data transfer following a successful DATA command */
- class TransferCommand : public Command {
- public:
- TransferCommand( SMTPProtocol * smtp, const TQCString & initialBuffer )
- : Command( smtp, OnlyFirstInPipeline ),
- mUngetBuffer( initialBuffer ), mLastChar( '\n' ), mWasComplete( false ) {}
-
- bool doNotExecute( const TransactionState * ts ) const;
- TQCString nextCommandLine( TransactionState * );
- void ungetCommandLine( const TQCString & cmd, TransactionState * ts );
- bool processResponse( const Response & response, TransactionState * );
- private:
- TQCString prepare( const TQByteArray & ba );
- TQCString mUngetBuffer;
- char mLastChar;
- bool mWasComplete; // ... before ungetting
- };
-
- class NoopCommand : public Command {
- public:
- NoopCommand( SMTPProtocol * smtp )
- : Command( smtp, OnlyLastInPipeline ) {}
-
- TQCString nextCommandLine( TransactionState * );
- };
-
- class RsetCommand : public Command {
- public:
- RsetCommand( SMTPProtocol * smtp )
- : Command( smtp, CloseConnectionOnError ) {}
-
- TQCString nextCommandLine( TransactionState * );
- };
-
- class QuitCommand : public Command {
- public:
- QuitCommand( SMTPProtocol * smtp )
- : Command( smtp, CloseConnectionOnError|OnlyLastInPipeline ) {}
-
- TQCString nextCommandLine( TransactionState * );
- };
-
-} // namespace KioSMTP
-
-#endif // __KIOSMTP_COMMAND_H__
diff --git a/kioslave/smtp/compliance.txt b/kioslave/smtp/compliance.txt
deleted file mode 100644
index b6b9874c8..000000000
--- a/kioslave/smtp/compliance.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-The SMTP kioslave currently conforms to the following SMTP-related RFCs:
-
-Base Spec:
-2821 Simple Mail Transfer Protocol. J. Klensin, Ed.. April 2001.
- (Format: TXT=192504 bytes) (Obsoletes RFC0821, RFC0974, RFC1869)
- (Status: PROPOSED STANDARD)
-
-Encryption/Auth:
-3207 SMTP Service Extension for Secure SMTP over Transport Layer
- Security. P. Hoffman. February 2002. (Format: TXT=18679 bytes)
- (Obsoletes RFC2487) (Status: PROPOSED STANDARD)
-
-2554 SMTP Service Extension for Authentication. J. Myers. March 1999.
- (Format: TXT=20534 bytes) (Status: PROPOSED STANDARD)
-(with all SASL mechanisms supported by KDESasl)
-
-General:
-1652 SMTP Service Extension for 8bit-MIMEtransport. J. Klensin, N.
- Freed, M. Rose, E. Stefferud, D. Crocker. July 1994. (Format:
- TXT=11842 bytes) (Obsoletes RFC1426) (Status: DRAFT STANDARD)
-
-1870 SMTP Service Extension for Message Size Declaration. J. Klensin,
- N. Freed, K. Moore. November 1995. (Format: TXT=18226 bytes)
- (Obsoletes RFC1653) (Also STD0010) (Status: STANDARD)
-
-2920 SMTP Service Extension for Command Pipelining. N. Freed.
- September 2000. (Format: TXT=17065 bytes) (Obsoletes RFC2197) (Also
- STD0060) (Status: STANDARD)
-
-Known shortcomings:
-- Doesn't enforce the CRLF lineending convention on user-supplied data.
-- Due to the lack of a Mulit_Put_ in the KIO infrastructure, pipelining
- across messages isn't supported.
diff --git a/kioslave/smtp/interactivesmtpserver.cc b/kioslave/smtp/interactivesmtpserver.cc
deleted file mode 100644
index 54c0b58be..000000000
--- a/kioslave/smtp/interactivesmtpserver.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -*- c++ -*-
- interactivesmtpserver.cc
-
- Code based on the serverSocket example by Jesper Pedersen.
-
- This file is part of the testsuite of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2004 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#include <config.h>
-
-#include <tqserversocket.h>
-#include <tqsocket.h>
-#include <tqwidget.h>
-#include <tqapplication.h>
-#include <tqhostaddress.h>
-#include <tqtextedit.h>
-#include <tqlineedit.h>
-#include <tqlabel.h>
-#include <tqstring.h>
-#include <tqlayout.h>
-#include <tqpushbutton.h>
-
-#include <cassert>
-
-#include "interactivesmtpserver.h"
-
-static const TQHostAddress localhost( 0x7f000001 ); // 127.0.0.1
-
-InteractiveSMTPServerWindow::~InteractiveSMTPServerWindow() {
- if ( mSocket ) {
- mSocket->close();
- if ( mSocket->state() == TQSocket::Closing )
- connect( mSocket, TQT_SIGNAL(delayedCloseFinished()),
- mSocket, TQT_SLOT(deleteLater()) );
- else
- mSocket->deleteLater();
- mSocket = 0;
- }
-}
-
-void InteractiveSMTPServerWindow::slotSendResponse()
-{
- const TQString line = mLineEdit->text();
- mLineEdit->clear();
- TQTextStream s( mSocket );
- s << line + "\r\n";
- slotDisplayServer( line );
-}
-
-InteractiveSMTPServer::InteractiveSMTPServer( TQObject* parent )
- : TQServerSocket( localhost, 2525, 1, parent )
-{
-}
-
-int main( int argc, char * argv[] ) {
- TQApplication app( argc, argv );
-
- InteractiveSMTPServer server;
-
- tqDebug( "Server should now listen on localhost:2525" );
- tqDebug( "Hit CTRL-C to quit." );
- return app.exec();
-};
-
-
-InteractiveSMTPServerWindow::InteractiveSMTPServerWindow( TQSocket * socket, TQWidget * parent, const char * name, WFlags f )
- : TQWidget( parent, name, f ), mSocket( socket )
-{
- TQPushButton * but;
- assert( socket );
-
- TQVBoxLayout * vlay = new TQVBoxLayout( this, 6 );
-
- mTextEdit = new TQTextEdit( this );
- mTextEdit->setTextFormat( TQTextEdit::LogText );
- vlay->addWidget( mTextEdit, 1 );
-
- TQHBoxLayout * hlay = new TQHBoxLayout( vlay );
-
- mLineEdit = new TQLineEdit( this );
- but = new TQPushButton( "&Send", this );
- hlay->addWidget( new TQLabel( mLineEdit, "&Response:", this ) );
- hlay->addWidget( mLineEdit, 1 );
- hlay->addWidget( but );
-
- connect( mLineEdit, TQT_SIGNAL(returnPressed()), TQT_SLOT(slotSendResponse()) );
- connect( but, TQT_SIGNAL(clicked()), TQT_SLOT(slotSendResponse()) );
-
- but = new TQPushButton( "&Close Connection", this );
- vlay->addWidget( but );
-
- connect( but, TQT_SIGNAL(clicked()), TQT_SLOT(slotConnectionClosed()) );
-
- connect( socket, TQT_SIGNAL(connectionClosed()), TQT_SLOT(slotConnectionClosed()) );
- connect( socket, TQT_SIGNAL(error(int)), TQT_SLOT(slotError(int)) );
- connect( socket, TQT_SIGNAL(readyRead()), TQT_SLOT(slotReadyRead()) );
-
- mLineEdit->setText( "220 hi there" );
- mLineEdit->setFocus();
-}
-
-#include "interactivesmtpserver.moc"
diff --git a/kioslave/smtp/interactivesmtpserver.h b/kioslave/smtp/interactivesmtpserver.h
deleted file mode 100644
index 39a07f6a9..000000000
--- a/kioslave/smtp/interactivesmtpserver.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef INTERACTIVESMTPSERVER_H
-#define INTERACTIVESMTPSERVER_H
-
-/* -*- c++ -*-
- interactivesmtpserver.h
-
- Code based on the serverSocket example by Jesper Pedersen.
-
- This file is part of the testsuite of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2004 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#include <tqwidget.h>
-
-
-static TQString err2str( int err ) {
- switch ( err ) {
- case TQSocket::ErrConnectionRefused: return "Connection refused";
- case TQSocket::ErrHostNotFound: return "Host not found";
- case TQSocket::ErrSocketRead: return "Failed to read from socket";
- default: return "Unknown error";
- }
-}
-
-
-static TQString escape( TQString s ) {
- return s
- .replace( '&', "&amp;" )
- .replace( '>', "&gt;" )
- .replace( '<', "&lt;" )
- .replace( '"', "&quot;" )
- ;
-}
-
-
-static TQString trim( const TQString & s ) {
- if ( s.endsWith( "\r\n" ) )
- return s.left( s.length() - 2 );
- if ( s.endsWith( "\r" ) || s.endsWith( "\n" ) )
- return s.left( s.length() - 1 );
- return s;
-}
-
-
-class InteractiveSMTPServerWindow : public TQWidget {
- Q_OBJECT
-public:
- InteractiveSMTPServerWindow( TQSocket * socket, TQWidget * parent=0, const char * name=0, WFlags f=0 );
- ~InteractiveSMTPServerWindow();
-
-public slots:
- void slotSendResponse();
- void slotDisplayClient( const TQString & s ) {
- mTextEdit->append( "C:" + escape(s) );
- }
- void slotDisplayServer( const TQString & s ) {
- mTextEdit->append( "S:" + escape(s) );
- }
- void slotDisplayMeta( const TQString & s ) {
- mTextEdit->append( "<font color=\"red\">" + escape(s) + "</font>" );
- }
- void slotReadyRead() {
- while ( mSocket->canReadLine() )
- slotDisplayClient( trim( mSocket->readLine() ) );
- }
- void slotError( int err ) {
- slotDisplayMeta( TQString( "E: %1 (%2)" ).arg( err2str( err ) ).arg( err ) );
- }
- void slotConnectionClosed() {
- slotDisplayMeta( "Connection closed by peer" );
- }
- void slotCloseConnection() {
- mSocket->close();
- }
-private:
- TQSocket * mSocket;
- TQTextEdit * mTextEdit;
- TQLineEdit * mLineEdit;
-};
-
-class InteractiveSMTPServer : public TQServerSocket {
- Q_OBJECT
-public:
- InteractiveSMTPServer( TQObject * parent=0 );
- ~InteractiveSMTPServer() {}
-
- /*! \reimp */
- void newConnection( int fd ) {
- TQSocket * socket = new TQSocket();
- socket->setSocket( fd );
- InteractiveSMTPServerWindow * w = new InteractiveSMTPServerWindow( socket );
- w->show();
- }
-};
-
-
-#endif
diff --git a/kioslave/smtp/request.cc b/kioslave/smtp/request.cc
deleted file mode 100644
index 84a1663f8..000000000
--- a/kioslave/smtp/request.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-/* -*- c++ -*-
- request.cc
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#include <config.h>
-
-#include "request.h"
-
-#include <kurl.h>
-#include <kidna.h>
-#include <kmdcodec.h>
-#include <kdebug.h>
-
-#include <assert.h>
-
-namespace KioSMTP {
-
- Request Request::fromURL( const KURL & url ) {
- Request request;
-
- const TQStringList query = TQStringList::split( '&', url.query().mid(1) );
-#ifndef NDEBUG
- kdDebug(7112) << "Parsing request from query:\n" + query.join("\n" ) << endl;
-#endif
- for ( TQStringList::const_iterator it = query.begin() ; it != query.end() ; ++it ) {
- int equalsPos = (*it).find( '=' );
- if ( equalsPos <= 0 )
- continue;
-
- const TQString key = (*it).left( equalsPos ).lower();
- const TQString value = KURL::decode_string( (*it).mid( equalsPos + 1 ) );
-
- if ( key == "to" )
- request.addTo( value );
- else if ( key == "cc" )
- request.addCc( value );
- else if ( key == "bcc" )
- request.addBcc( value );
- else if ( key == "headers" ) {
- request.setEmitHeaders( value == "0" );
- request.setEmitHeaders( false ); // ### ???
- }
- else if ( key == "subject" )
- request.setSubject( value );
- else if ( key == "from" )
- request.setFromAddress( value );
- else if ( key == "profile" )
- request.setProfileName( value );
- else if ( key == "hostname" )
- request.setHeloHostname( value );
- else if ( key == "body" )
- request.set8BitBody( value.upper() == "8BIT" );
- else if ( key == "size" )
- request.setSize( value.toUInt() );
- else
- kdWarning(7112) << "while parsing query: unknown query item \""
- << key << "\" with value \"" << value << "\"" << endl;
- }
-
- return request;
- }
-
- TQCString Request::heloHostnameCString() const {
- return KIDNA::toAsciiCString( heloHostname() );
- }
-
- static bool isUsAscii( const TQString & s ) {
- for ( uint i = 0 ; i < s.length() ; ++i )
- if ( s[i].unicode() > 127 ) return false;
- return true;
- }
-
-
-
- static inline bool isSpecial( char ch ) {
- static const TQCString specials = "()<>[]:;@\\,.\"";
- return specials.find( ch ) >= 0;
- }
-
-
-
- static inline bool needsQuoting( char ch ) {
- return ch == '\\' || ch == '"' || ch == '\n' ;
- }
-
-
-
- static inline TQCString rfc2047Encode( const TQString & s ) {
- TQCString r = KCodecs::base64Encode( s.stripWhiteSpace().utf8(), false );
- return "=?utf-8?b?" + r + "?=" ; // use base64 since that always gives a valid encoded-word
- }
-
-
-
- static TQCString quote( const TQString & s ) {
- assert( isUsAscii( s ) );
-
- TQCString r( s.length() * 2 );
- bool needsQuotes = false;
-
- unsigned int j = 0;
- for ( unsigned int i = 0 ; i < s.length() ; ++i ) {
- char ch = s[i].latin1();
- if ( isSpecial( ch ) ) {
- if ( needsQuoting( ch ) )
- r[j++] = '\\';
- needsQuotes = true;
- }
- r[j++] = ch;
- }
- r.truncate( j );
-
- if ( needsQuotes )
- return '"' + r + '"';
- else
- return r;
- }
-
-
-
- static TQCString formatFromAddress( const TQString & fromRealName, const TQString & fromAddress ) {
- if ( fromRealName.isEmpty() )
- return fromAddress.latin1(); // no real name: return "[email protected]"
-
- // return "Joe User <[email protected]>", "\"User, Joe\" <[email protected]>"
- // or "=?utf-8?q?Joe_User?= <[email protected]>", depending on real name's nature.
- TQCString r = isUsAscii( fromRealName ) ? quote( fromRealName ) : rfc2047Encode( fromRealName );
- return r + " <" + fromAddress.latin1() + '>';
- }
-
-
-
- static TQCString formatSubject( TQString s ) {
- if ( isUsAscii( s ) )
- return TQString(s.remove( '\n' )).latin1(); // don't break header folding,
- // so remove any line break
- // that happen to be around
- else
- return rfc2047Encode( s );
- }
-
-
-
- TQCString Request::headerFields( const TQString & fromRealName ) const {
- if ( !emitHeaders() )
- return 0;
-
- assert( hasFromAddress() ); // should have been checked for by
- // caller (MAIL FROM comes before DATA)
-
- TQCString result = "From: " + formatFromAddress( fromRealName, fromAddress() ) + "\r\n";
-
- if ( !subject().isEmpty() )
- result += "Subject: " + formatSubject( subject() ) + "\r\n";
- if ( !to().empty() )
- result += TQCString( "To: " ) + to().join( ",\r\n\t" /* line folding */ ).latin1() + "\r\n";
- if ( !cc().empty() )
- result += TQCString( "Cc: " ) + cc().join( ",\r\n\t" /* line folding */ ).latin1() + "\r\n";
- return result;
- }
-
-} // namespace KioSMTP
diff --git a/kioslave/smtp/request.h b/kioslave/smtp/request.h
deleted file mode 100644
index e1b3acda8..000000000
--- a/kioslave/smtp/request.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- c++ -*-
- request.h
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#ifndef __KIOSMTP_REQUEST_H__
-#define __KIOSMTP_REQUEST_H__
-
-#include <tqstring.h>
-#include <tqstringlist.h>
-
-class KURL;
-
-namespace KioSMTP {
-
- class Request {
- public:
- Request()
- : mSubject( "missing subject" ), mEmitHeaders( true ),
- m8Bit( false ), mSize( 0 ) {}
-
- static Request fromURL( const KURL & url );
-
- TQString profileName() const { return mProfileName; }
- void setProfileName( const TQString & profileName ) { mProfileName = profileName; }
- bool hasProfile() const { return !profileName().isNull(); }
-
- TQString subject() const { return mSubject; }
- void setSubject( const TQString & subject ) { mSubject = subject; }
-
- TQString fromAddress() const { return mFromAddress; }
- void setFromAddress( const TQString & fromAddress ) { mFromAddress = fromAddress; }
- bool hasFromAddress() const { return !mFromAddress.isEmpty(); }
-
- TQStringList recipients() const { return to() + cc() + bcc() ; }
- bool hasRecipients() const { return !to().empty() || !cc().empty() || !bcc().empty() ; }
-
- TQStringList to() const { return mTo; }
- TQStringList cc() const { return mCc; }
- TQStringList bcc() const { return mBcc; }
- void addTo( const TQString & to ) { mTo.push_back( to ); }
- void addCc( const TQString & cc ) { mCc.push_back( cc ); }
- void addBcc( const TQString & bcc ) { mBcc.push_back( bcc ); }
-
- TQString heloHostname() const { return mHeloHostname; }
- TQCString heloHostnameCString() const;
- void setHeloHostname( const TQString & hostname ) { mHeloHostname = hostname; }
-
- bool emitHeaders() const { return mEmitHeaders; }
- void setEmitHeaders( bool emitHeaders ) { mEmitHeaders = emitHeaders; }
-
- bool is8BitBody() const { return m8Bit; }
- void set8BitBody( bool a8Bit ) { m8Bit = a8Bit; }
-
- unsigned int size() const { return mSize; }
- void setSize( unsigned int size ) { mSize = size; }
-
- /** If @ref #emitHeaders() is true, returns the rfc2822
- serialization of the header fields "To", "Cc", "Subject" and
- "From", as determined by the respective settings. If @ref
- #emitHeaders() is false, returns a null string. */
- TQCString headerFields( const TQString & fromRealName=TQString::null ) const;
-
- private:
- TQStringList mTo, mCc, mBcc;
- TQString mProfileName, mSubject, mFromAddress, mHeloHostname;
- bool mEmitHeaders;
- bool m8Bit;
- unsigned int mSize;
- };
-
-} // namespace KioSMTP
-
-#endif // __KIOSMTP_REQUEST_H__
diff --git a/kioslave/smtp/response.cc b/kioslave/smtp/response.cc
deleted file mode 100644
index 0ddce0e5a..000000000
--- a/kioslave/smtp/response.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-/* -*- c++ -*-
- response.cc
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#include <config.h>
-
-#include "response.h"
-
-#include <klocale.h>
-#include <kio/global.h>
-
-#include <tqstring.h>
-
-namespace KioSMTP {
-
- void Response::parseLine( const char * line, int len ) {
-
- if ( !isWellFormed() ) return; // don't bother
-
- if ( isComplete() )
- // if the response is already complete, there can't be another line
- mValid = false;
-
- if ( len > 1 && line[len-1] == '\n' && line[len-2] == '\r' )
- len -= 2;
-
- if ( len < 3 ) {
- // can't be valid - too short
- mValid = false;
- mWellFormed = false;
- return;
- }
-
- bool ok = false;
- unsigned int code = TQCString( line, 3+1 ).toUInt( &ok );
- if ( !ok || code < 100 || code > 559 ) {
- // not a number or number out of range
- mValid = false;
- if ( !ok || code < 100 )
- mWellFormed = false;
- return;
- }
- if ( mCode && code != mCode ) {
- // different codes in one response are not allowed.
- mValid = false;
- return;
- }
- mCode = code;
-
- if ( len == 3 || line[3] == ' ' )
- mSawLastLine = true;
- else if ( line[3] != '-' ) {
- // code must be followed by either SP or hyphen (len == 3 is
- // also accepted since broken servers exist); all else is
- // invalid
- mValid = false;
- mWellFormed = false;
- return;
- }
-
- mLines.push_back( len > 4 ? TQCString( line+4, len-4+1 ).stripWhiteSpace() : TQCString() );
- }
-
-
- // hackishly fixing QCStringList flaws...
- static TQCString join( char sep, const QCStringList & list ) {
- if ( list.empty() )
- return TQCString();
- TQCString result = list.front();
- for ( QCStringList::const_iterator it = ++list.begin() ; it != list.end() ; ++it )
- result += sep + *it;
- return result;
- }
-
- TQString Response::errorMessage() const {
- TQString msg;
- if ( lines().count() > 1 )
- msg = i18n("The server responded:\n%1")
- .arg( static_cast<const char *>(join( '\n', lines()) ) );
- else
- msg = i18n("The server responded: \"%1\"")
- .arg( static_cast<const char *>(lines().front()) );
- if ( first() == 4 )
- msg += '\n' + i18n("This is a temporary failure. "
- "You may try again later.");
- return msg;
- }
-
- int Response::errorCode() const {
- switch ( code() ) {
- case 421: // Service not available, closing transmission channel
- case 454: // TLS not available due to temporary reason
- // Temporary authentication failure
- case 554: // Transaction failed / No SMTP service here / No valid recipients
- return TDEIO::ERR_SERVICE_NOT_AVAILABLE;
-
- case 451: // Requested action aborted: local error in processing
- return TDEIO::ERR_INTERNAL_SERVER;
-
- case 452: // Requested action not taken: insufficient system storage
- case 552: // Requested mail action aborted: exceeded storage allocation
- return TDEIO::ERR_DISK_FULL;
-
- case 500: // Syntax error, command unrecognized
- case 501: // Syntax error in parameters or arguments
- case 502: // Command not implemented
- case 503: // Bad sequence of commands
- case 504: // Command parameter not implemented
- return TDEIO::ERR_INTERNAL;
-
- case 450: // Requested mail action not taken: mailbox unavailable
- case 550: // Requested action not taken: mailbox unavailable
- case 551: // User not local; please try <forward-path>
- case 553: // Requested action not taken: mailbox name not allowed
- return TDEIO::ERR_DOES_NOT_EXIST;
-
- case 530: // {STARTTLS,Authentication} required
- case 538: // Encryption required for requested authentication mechanism
- case 534: // Authentication mechanism is too weak
- return TDEIO::ERR_UPGRADE_REQUIRED;
-
- case 432: // A password transition is needed
- return TDEIO::ERR_COULD_NOT_AUTHENTICATE;
-
- default:
- if ( isPositive() )
- return 0;
- else
- return TDEIO::ERR_UNKNOWN;
- }
- }
-
-} // namespace KioSMTP
diff --git a/kioslave/smtp/response.h b/kioslave/smtp/response.h
deleted file mode 100644
index 2fd48ebf3..000000000
--- a/kioslave/smtp/response.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* -*- c++ -*-
- response.h
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#ifndef __KIOSMTP_RESPONSE_H__
-#define __KIOSMTP_RESPONSE_H__
-
-#include <tqcstring.h>
-#include <tqvaluelist.h>
-typedef TQValueList<TQCString> QCStringList;
-
-class TQString;
-
-namespace KioSMTP {
-
- class Response {
- public:
- Response()
- : mCode(0),
- mValid(true),
- mSawLastLine(false),
- mWellFormed(true) {}
-
- void parseLine( const char * line ) {
- parseLine( line, tqstrlen( line ) );
- }
- void parseLine( const char * line, int len );
-
- /** Return an internationalized error message according to the
- response's code. */
- TQString errorMessage() const;
- /** Translate the SMTP error code into a KIO one */
- int errorCode() const;
-
- enum Reply {
- UnknownReply = -1,
- PositivePreliminary = 1,
- PositiveCompletion = 2,
- PositiveIntermediate = 3,
- TransientNegative = 4,
- PermanentNegative = 5
- };
-
- enum Category {
- UnknownCategory = -1,
- SyntaxError = 0,
- Information = 1,
- Connections = 2,
- MailSystem = 5
- };
-
- unsigned int code() const { return mCode; }
- unsigned int first() const { return code() / 100 ; }
- unsigned int second() const { return ( code() % 100 ) / 10 ; }
- unsigned int third() const { return code() % 10 ; }
-
- bool isPositive() const { return first() <= 3 && first() >= 1 ; }
- bool isNegative() const { return first() == 4 || first() == 5 ; }
- bool isUnknown() const { return !isPositive() && !isNegative() ; }
-
- QCStringList lines() const { return mLines; }
-
- bool isValid() const { return mValid; }
- bool isComplete() const { return mSawLastLine; }
-
- /** Shortcut method.
- @return true iff the response is valid, complete and positive */
- bool isOk() const { return isValid() && isComplete() && isPositive() ; }
- /** Indicates whether the response was well-formed, meaning it
- obeyed the syntax of smtp responses. That the response
- nevertheless is not valid may be caused by e.g. different
- response codes in a multilie response. A non-well-formed
- response is never valid. */
- bool isWellFormed() const { return mWellFormed; }
-
- void clear() { *this = Response(); }
-
-#ifdef KIOSMTP_COMPARATORS
- bool operator==( const Response & other ) const {
- return mCode == other.mCode &&
- mValid == other.mValid &&
- mSawLastLine == other.mSawLastLine &&
- mWellFormed == other.mWellFormed &&
- mLines == other.mLines;
- }
-#endif
-
- private:
- unsigned int mCode;
- QCStringList mLines;
- bool mValid;
- bool mSawLastLine;
- bool mWellFormed;
- };
-
-} // namespace KioSMTP
-
-#endif // __KIOSMTP_RESPONSE_H__
diff --git a/kioslave/smtp/smtp.cc b/kioslave/smtp/smtp.cc
deleted file mode 100644
index b1effa415..000000000
--- a/kioslave/smtp/smtp.cc
+++ /dev/null
@@ -1,647 +0,0 @@
-/*
- * Copyright (c) 2000, 2001 Alex Zepeda <[email protected]>
- * Copyright (c) 2001 Michael H�ckel <[email protected]>
- * Copyright (c) 2002 Aaron J. Seigo <[email protected]>
- * Copyright (c) 2003 Marc Mutz <[email protected]>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <config.h>
-
-#ifdef HAVE_LIBSASL2
-extern "C" {
-#include <sasl/sasl.h>
-}
-#endif
-
-#include "smtp.h"
-#include "request.h"
-#include "response.h"
-#include "transactionstate.h"
-#include "command.h"
-using KioSMTP::Capabilities;
-using KioSMTP::Command;
-using KioSMTP::EHLOCommand;
-using KioSMTP::AuthCommand;
-using KioSMTP::MailFromCommand;
-using KioSMTP::RcptToCommand;
-using KioSMTP::DataCommand;
-using KioSMTP::TransferCommand;
-using KioSMTP::Request;
-using KioSMTP::Response;
-using KioSMTP::TransactionState;
-
-#include <kemailsettings.h>
-#include <ksock.h>
-#include <kdebug.h>
-#include <kinstance.h>
-#include <kio/connection.h>
-#include <kio/slaveinterface.h>
-#include <klocale.h>
-
-#include <tqstring.h>
-#include <tqstringlist.h>
-#include <tqcstring.h>
-
-#include <memory>
-using std::auto_ptr;
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <assert.h>
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#include <netdb.h>
-
-#ifndef NI_NAMEREQD
-// FIXME for KDE 3.3: fake defintion
-// API design flaw in KExtendedSocket::resolve
-# define NI_NAMEREQD 0
-#endif
-
-
-extern "C" {
- KDE_EXPORT int kdemain(int argc, char **argv);
-}
-
-int kdemain(int argc, char **argv)
-{
- TDEInstance instance("kio_smtp");
-
- if (argc != 4) {
- fprintf(stderr,
- "Usage: kio_smtp protocol domain-socket1 domain-socket2\n");
- exit(-1);
- }
-
-#ifdef HAVE_LIBSASL2
- if ( sasl_client_init( NULL ) != SASL_OK ) {
- fprintf(stderr, "SASL library initialization failed!\n");
- exit(-1);
- }
-#endif
- SMTPProtocol slave( argv[2], argv[3], tqstricmp( argv[1], "smtps" ) == 0 );
- slave.dispatchLoop();
-#ifdef HAVE_LIBSASL2
- sasl_done();
-#endif
- return 0;
-}
-
-SMTPProtocol::SMTPProtocol(const TQCString & pool, const TQCString & app,
- bool useSSL)
-: TCPSlaveBase(useSSL ? 465 : 25,
- useSSL ? "smtps" : "smtp",
- pool, app, useSSL),
- m_iOldPort(0),
- m_opened(false)
-{
- //kdDebug(7112) << "SMTPProtocol::SMTPProtocol" << endl;
- mPendingCommandQueue.setAutoDelete( true );
- mSentCommandQueue.setAutoDelete( true );
-}
-
-unsigned int SMTPProtocol::sendBufferSize() const {
- // ### how much is eaten by SSL/TLS overhead?
- const int fd = fileno( fp );
- int value = -1;
- kde_socklen_t len = sizeof(value);
- if ( fd < 0 || ::getsockopt( fd, SOL_SOCKET, SO_SNDBUF, (char*)&value, &len ) )
- value = 1024; // let's be conservative
- kdDebug(7112) << "send buffer size seems to be " << value << " octets." << endl;
- return value > 0 ? value : 1024 ;
-}
-
-SMTPProtocol::~SMTPProtocol() {
- //kdDebug(7112) << "SMTPProtocol::~SMTPProtocol" << endl;
- smtp_close();
-}
-
-void SMTPProtocol::openConnection() {
- if ( smtp_open() )
- connected();
- else
- closeConnection();
-}
-
-void SMTPProtocol::closeConnection() {
- smtp_close();
-}
-
-void SMTPProtocol::special( const TQByteArray & aData ) {
- TQDataStream s( aData, IO_ReadOnly );
- int what;
- s >> what;
- if ( what == 'c' ) {
- infoMessage( createSpecialResponse() );
-#ifndef NDEBUG
- kdDebug(7112) << "special('c') returns \"" << createSpecialResponse() << "\"" << endl;
-#endif
- } else if ( what == 'N' ) {
- if ( !execute( Command::NOOP ) )
- return;
- } else {
- error( TDEIO::ERR_INTERNAL,
- i18n("The application sent an invalid request.") );
- return;
- }
- finished();
-}
-
-
-// Usage: smtp://smtphost:port/[email protected]&subject=blah
-// If smtphost is the name of a profile, it'll use the information
-// provided by that profile. If it's not a profile name, it'll use it as
-// nature intended.
-// One can also specify in the query:
-// headers=0 (turns off header generation)
-// to=emailaddress
-// cc=emailaddress
-// bcc=emailaddress
-// subject=text
-// profile=text (this will override the "host" setting)
-// hostname=text (used in the HELO)
-// body={7bit,8bit} (default: 7bit; 8bit activates the use of the 8BITMIME SMTP extension)
-void SMTPProtocol::put(const KURL & url, int /*permissions */ ,
- bool /*overwrite */ , bool /*resume */ )
-{
- Request request = Request::fromURL( url ); // parse settings from URL's query
-
- KEMailSettings mset;
- KURL open_url = url;
- if ( !request.hasProfile() ) {
- //kdDebug(7112) << "kio_smtp: Profile is null" << endl;
- bool hasProfile = mset.profiles().contains( open_url.host() );
- if ( hasProfile ) {
- mset.setProfile(open_url.host());
- open_url.setHost(mset.getSetting(KEMailSettings::OutServer));
- m_sUser = mset.getSetting(KEMailSettings::OutServerLogin);
- m_sPass = mset.getSetting(KEMailSettings::OutServerPass);
-
- if (m_sUser.isEmpty())
- m_sUser = TQString::null;
- if (m_sPass.isEmpty())
- m_sPass = TQString::null;
- open_url.setUser(m_sUser);
- open_url.setPass(m_sPass);
- m_sServer = open_url.host();
- m_iPort = open_url.port();
- }
- else {
- mset.setProfile(mset.defaultProfileName());
- }
- }
- else {
- mset.setProfile( request.profileName() );
- }
-
- // Check KEMailSettings to see if we've specified an E-Mail address
- // if that worked, check to see if we've specified a real name
- // and then format accordingly (either: [email protected] or
- // Real Name <[email protected]>)
- if ( !request.hasFromAddress() ) {
- const TQString from = mset.getSetting( KEMailSettings::EmailAddress );
- if ( !from.isNull() )
- request.setFromAddress( from );
- else if ( request.emitHeaders() ) {
- error(TDEIO::ERR_NO_CONTENT, i18n("The sender address is missing."));
- return;
- }
- }
-
- if ( !smtp_open( request.heloHostname() ) )
- {
- error(TDEIO::ERR_SERVICE_NOT_AVAILABLE,
- i18n("SMTPProtocol::smtp_open failed (%1)") // ### better error message?
- .arg(open_url.path()));
- return;
- }
-
- if ( request.is8BitBody()
- && !haveCapability("8BITMIME") && metaData("8bitmime") != "on" ) {
- error( TDEIO::ERR_SERVICE_NOT_AVAILABLE,
- i18n("Your server does not support sending of 8-bit messages.\n"
- "Please use base64 or quoted-printable encoding.") );
- return;
- }
-
- queueCommand( new MailFromCommand( this, request.fromAddress().latin1(),
- request.is8BitBody(), request.size() ) );
-
- // Loop through our To and CC recipients, and send the proper
- // SMTP commands, for the benefit of the server.
- TQStringList recipients = request.recipients();
- for ( TQStringList::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it )
- queueCommand( new RcptToCommand( this, (*it).latin1() ) );
-
- queueCommand( Command::DATA );
- queueCommand( new TransferCommand( this, request.headerFields( mset.getSetting( KEMailSettings::RealName ) ) ) );
-
- TransactionState ts;
- if ( !executeQueuedCommands( &ts ) ) {
- if ( ts.errorCode() )
- error( ts.errorCode(), ts.errorMessage() );
- } else
- finished();
-}
-
-
-void SMTPProtocol::setHost(const TQString & host, int port,
- const TQString & user, const TQString & pass)
-{
- m_sServer = host;
- m_iPort = port;
- m_sUser = user;
- m_sPass = pass;
-}
-
-bool SMTPProtocol::sendCommandLine( const TQCString & cmdline ) {
- //kdDebug( cmdline.length() < 4096, 7112) << "C: " << cmdline.data();
- //kdDebug( cmdline.length() >= 4096, 7112) << "C: <" << cmdline.length() << " bytes>" << endl;
- kdDebug( 7112) << "C: <" << cmdline.length() << " bytes>" << endl;
- ssize_t cmdline_len = cmdline.length();
- if ( write( cmdline.data(), cmdline_len ) != cmdline_len ) {
- error( TDEIO::ERR_COULD_NOT_WRITE, m_sServer );
- return false;
- }
- return true;
-}
-
-Response SMTPProtocol::getResponse( bool * ok ) {
-
- if ( ok )
- *ok = false;
-
- Response response;
- char buf[2048];
-
- int recv_len = 0;
- do {
- // wait for data...
- if ( !waitForResponse( 600 ) ) {
- error( TDEIO::ERR_SERVER_TIMEOUT, m_sServer );
- return response;
- }
-
- // ...read data...
- recv_len = readLine( buf, sizeof(buf) - 1 );
- if ( recv_len < 1 && !isConnectionValid() ) {
- error( TDEIO::ERR_CONNECTION_BROKEN, m_sServer );
- return response;
- }
-
- kdDebug(7112) << "S: " << TQCString( buf, recv_len + 1 ).data();
- // ...and parse lines...
- response.parseLine( buf, recv_len );
-
- // ...until the response is complete or the parser is so confused
- // that it doesn't think a RSET would help anymore:
- } while ( !response.isComplete() && response.isWellFormed() );
-
- if ( !response.isValid() ) {
- error( TDEIO::ERR_NO_CONTENT, i18n("Invalid SMTP response (%1) received.").arg(response.code()) );
- return response;
- }
-
- if ( ok )
- *ok = true;
-
- return response;
-}
-
-bool SMTPProtocol::executeQueuedCommands( TransactionState * ts ) {
- assert( ts );
-
- kdDebug( canPipelineCommands(), 7112 ) << "using pipelining" << endl;
-
- while( !mPendingCommandQueue.isEmpty() ) {
- TQCString cmdline = collectPipelineCommands( ts );
- if ( ts->failedFatally() ) {
- smtp_close( false ); // _hard_ shutdown
- return false;
- }
- if ( ts->failed() )
- break;
- if ( cmdline.isEmpty() )
- continue;
- if ( !sendCommandLine( cmdline ) ||
- !batchProcessResponses( ts ) ||
- ts->failedFatally() ) {
- smtp_close( false ); // _hard_ shutdown
- return false;
- }
- }
-
- if ( ts->failed() ) {
- if ( !execute( Command::RSET ) )
- smtp_close( false );
- return false;
- }
- return true;
-}
-
-TQCString SMTPProtocol::collectPipelineCommands( TransactionState * ts ) {
- assert( ts );
-
- TQCString cmdLine;
- unsigned int cmdLine_len = 0;
-
- while ( mPendingCommandQueue.head() ) {
-
- Command * cmd = mPendingCommandQueue.head();
-
- if ( cmd->doNotExecute( ts ) ) {
- delete mPendingCommandQueue.dequeue();
- if ( cmdLine_len )
- break;
- else
- continue;
- }
-
- if ( cmdLine_len && cmd->mustBeFirstInPipeline() )
- break;
-
- if ( cmdLine_len && !canPipelineCommands() )
- break;
-
- while ( !cmd->isComplete() && !cmd->needsResponse() ) {
- const TQCString currentCmdLine = cmd->nextCommandLine( ts );
- if ( ts->failedFatally() )
- return cmdLine;
- const unsigned int currentCmdLine_len = currentCmdLine.length();
-
- if ( cmdLine_len && cmdLine_len + currentCmdLine_len > sendBufferSize() ) {
- // must all fit into the send buffer, else connection deadlocks,
- // but we need to have at least _one_ command to send
- cmd->ungetCommandLine( currentCmdLine, ts );
- return cmdLine;
- }
- cmdLine_len += currentCmdLine_len;
- cmdLine += currentCmdLine;
- }
-
- mSentCommandQueue.enqueue( mPendingCommandQueue.dequeue() );
-
- if ( cmd->mustBeLastInPipeline() )
- break;
- }
-
- return cmdLine;
-}
-
-bool SMTPProtocol::batchProcessResponses( TransactionState * ts ) {
- assert( ts );
-
- while ( !mSentCommandQueue.isEmpty() ) {
-
- Command * cmd = mSentCommandQueue.head();
- assert( cmd->isComplete() );
-
- bool ok = false;
- Response r = getResponse( &ok );
- if ( !ok )
- return false;
- cmd->processResponse( r, ts );
- if ( ts->failedFatally() )
- return false;
-
- mSentCommandQueue.remove();
- }
-
- return true;
-}
-
-void SMTPProtocol::queueCommand( int type ) {
- queueCommand( Command::createSimpleCommand( type, this ) );
-}
-
-bool SMTPProtocol::execute( int type, TransactionState * ts ) {
- auto_ptr<Command> cmd( Command::createSimpleCommand( type, this ) );
- kdFatal( !cmd.get(), 7112 ) << "Command::createSimpleCommand( " << type << " ) returned null!" << endl;
- return execute( cmd.get(), ts );
-}
-
-// ### fold into pipelining engine? How? (execute() is often called
-// ### when command queues are _not_ empty!)
-bool SMTPProtocol::execute( Command * cmd, TransactionState * ts )
-{
- kdFatal( !cmd, 7112 ) << "SMTPProtocol::execute() called with no command to run!" << endl;
-
- if (!cmd)
- return false;
-
- if ( cmd->doNotExecute( ts ) )
- return true;
-
- do {
- while ( !cmd->isComplete() && !cmd->needsResponse() ) {
- const TQCString cmdLine = cmd->nextCommandLine( ts );
- if ( ts && ts->failedFatally() ) {
- smtp_close( false );
- return false;
- }
- if ( cmdLine.isEmpty() )
- continue;
- if ( !sendCommandLine( cmdLine ) ) {
- smtp_close( false );
- return false;
- }
- }
-
- bool ok = false;
- Response r = getResponse( &ok );
- if ( !ok ) {
- smtp_close( false );
- return false;
- }
- if ( !cmd->processResponse( r, ts ) ) {
- if ( ts && ts->failedFatally() ||
- cmd->closeConnectionOnError() ||
- !execute( Command::RSET ) )
- smtp_close( false );
- return false;
- }
- } while ( !cmd->isComplete() );
-
- return true;
-}
-
-bool SMTPProtocol::smtp_open(const TQString& fakeHostname)
-{
- if (m_opened &&
- m_iOldPort == port(m_iPort) &&
- m_sOldServer == m_sServer &&
- m_sOldUser == m_sUser &&
- (fakeHostname.isNull() || m_hostname == fakeHostname))
- return true;
-
- smtp_close();
- if (!connectToHost(m_sServer, m_iPort))
- return false; // connectToHost has already send an error message.
- m_opened = true;
-
- bool ok = false;
- Response greeting = getResponse( &ok );
- if ( !ok || !greeting.isOk() )
- {
- if ( ok )
- error( TDEIO::ERR_COULD_NOT_LOGIN,
- i18n("The server did not accept the connection.\n"
- "%1").arg( greeting.errorMessage() ) );
- smtp_close();
- return false;
- }
-
- if (!fakeHostname.isNull())
- {
- m_hostname = fakeHostname;
- }
- else
- {
- TQString tmpPort;
- TDESocketAddress* addr = KExtendedSocket::localAddress(m_iSock);
- // perform name lookup. NI_NAMEREQD means: don't return a numeric
- // value (we need to know when we get have the IP address, so we
- // can enclose it in sqaure brackets (domain-literal). Failure to
- // do so is normally harmless with IPv4, but fails for IPv6:
- if (KExtendedSocket::resolve(addr, m_hostname, tmpPort, NI_NAMEREQD) != 0)
- // FQDN resolution failed
- // use the IP address as domain-literal
- m_hostname = '[' + addr->nodeName() + ']';
- delete addr;
-
- if(m_hostname.isEmpty())
- {
- m_hostname = "localhost.invalid";
- }
- }
-
- EHLOCommand ehloCmdPreTLS( this, m_hostname );
- if ( !execute( &ehloCmdPreTLS ) ) {
- smtp_close();
- return false;
- }
-
- if ( ( haveCapability("STARTTLS") && canUseTLS() && metaData("tls") != "off" )
- || metaData("tls") == "on" ) {
- // For now we're gonna force it on.
-
- if ( execute( Command::STARTTLS ) ) {
-
- // re-issue EHLO to refresh the capability list (could be have
- // been faked before TLS was enabled):
- EHLOCommand ehloCmdPostTLS( this, m_hostname );
- if ( !execute( &ehloCmdPostTLS ) ) {
- smtp_close();
- return false;
- }
- }
- }
- // Now we try and login
- if (!authenticate()) {
- smtp_close();
- return false;
- }
-
- m_iOldPort = m_iPort;
- m_sOldServer = m_sServer;
- m_sOldUser = m_sUser;
- m_sOldPass = m_sPass;
-
- return true;
-}
-
-bool SMTPProtocol::authenticate()
-{
- // return with success if the server doesn't support SMTP-AUTH or an user
- // name is not specified and metadata doesn't tell us to force it.
- if ( (m_sUser.isEmpty() || !haveCapability( "AUTH" )) &&
- metaData( "sasl" ).isEmpty() ) return true;
-
- TDEIO::AuthInfo authInfo;
- authInfo.username = m_sUser;
- authInfo.password = m_sPass;
- authInfo.prompt = i18n("Username and password for your SMTP account:");
-
- TQStringList strList;
-
- if (!metaData("sasl").isEmpty())
- strList.append(metaData("sasl").latin1());
- else
- strList = mCapabilities.saslMethodsQSL();
-
- AuthCommand authCmd( this, strList.join(" ").latin1(), m_sServer, authInfo );
- bool ret = execute( &authCmd );
- m_sUser = authInfo.username;
- m_sPass = authInfo.password;
- return ret;
-}
-
-void SMTPProtocol::parseFeatures( const Response & ehloResponse ) {
- mCapabilities = Capabilities::fromResponse( ehloResponse );
-
- TQString category = usingTLS() ? "TLS" : usingSSL() ? "SSL" : "PLAIN" ;
- setMetaData( category + " AUTH METHODS", mCapabilities.authMethodMetaData() );
- setMetaData( category + " CAPABILITIES", mCapabilities.asMetaDataString() );
-#ifndef NDEBUG
- kdDebug(7112) << "parseFeatures() " << category << " AUTH METHODS:"
- << '\n' + mCapabilities.authMethodMetaData() << endl
- << "parseFeatures() " << category << " CAPABILITIES:"
- << '\n' + mCapabilities.asMetaDataString() << endl;
-#endif
-}
-
-void SMTPProtocol::smtp_close( bool nice ) {
- if (!m_opened) // We're already closed
- return;
-
- if ( nice )
- execute( Command::QUIT );
- kdDebug( 7112 ) << "closing connection" << endl;
- closeDescriptor();
- m_sOldServer = TQString::null;
- m_sOldUser = TQString::null;
- m_sOldPass = TQString::null;
-
- mCapabilities.clear();
- mPendingCommandQueue.clear();
- mSentCommandQueue.clear();
-
- m_opened = false;
-}
-
-void SMTPProtocol::stat(const KURL & url)
-{
- TQString path = url.path();
- error(TDEIO::ERR_DOES_NOT_EXIST, url.path());
-}
-
diff --git a/kioslave/smtp/smtp.h b/kioslave/smtp/smtp.h
deleted file mode 100644
index eef1aab42..000000000
--- a/kioslave/smtp/smtp.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* -*- c++ -*-
- * Copyright (c) 2000, 2001 Alex Zepeda <[email protected]>
- * Copyright (c) 2001 Michael H�ckel <[email protected]>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#ifndef _SMTP_H
-#define _SMTP_H
-
-#include <kio/tcpslavebase.h>
-
-#include "capabilities.h"
-
-#include <tqstring.h>
-#include <tqptrqueue.h>
-
-class KURL;
-class TQCString;
-template <typename T> class TQMemArray;
-#ifdef USE_QT3
-typedef TQMemArray<char> TQByteArray;
-#endif // USE_QT3
-
-namespace KioSMTP {
- class Response;
- class TransactionState;
- class Command;
-}
-
-class SMTPProtocol : public TDEIO::TCPSlaveBase {
- friend class KioSMTP::Command;
-public:
- SMTPProtocol(const TQCString & pool, const TQCString & app, bool useSSL);
- virtual ~ SMTPProtocol();
-
- virtual void setHost(const TQString & host, int port,
- const TQString & user, const TQString & pass);
-
- virtual void special(const TQByteArray & aData);
- virtual void put(const KURL & url, int permissions, bool overwrite,
- bool resume);
- virtual void stat(const KURL & url);
- virtual void openConnection();
- virtual void closeConnection();
-
-protected:
-
- bool smtp_open(const TQString& fakeHostname = TQString::null);
-
- /** Closes the connection. If @p nice is true (default), then QUIT
- is sent and it's reponse waited for. */
- void smtp_close( bool nice=true );
-
- /** Execute command @p cmd */
- bool execute( KioSMTP::Command * cmd, KioSMTP::TransactionState * ts=0 );
- /** Execute a command of type @p type */
- bool execute( int type, KioSMTP::TransactionState * ts=0 );
- /** Execute the queued commands. If something goes horribly wrong
- (sending command oline fails, getting response fails or some
- command raises the failedFatally() flag in @p ts, shuts down the
- connection with <code>smtp_close( false )</code>. If The
- transaction fails gracefully (<code>ts->failed()</code> is
- true), issues a RSET command.
-
- @return true if transaction succeeded, false otherwise.
- **/
- bool executeQueuedCommands( KioSMTP::TransactionState * ts );
-
- /** Parse a single response from the server. Single- vs. multiline
- responses are correctly detected.
-
- @param ok if not 0, returns whether response parsing was
- successful. Don't confuse this with negative responses
- (e.g. 5xx), which you can check for using
- @ref Response::isNegative()
- @return the @ref Response object representing the server response.
- **/
- KioSMTP::Response getResponse( bool * ok );
-
- bool authenticate();
- void parseFeatures( const KioSMTP::Response & ehloResponse );
-
- bool sendCommandLine( const TQCString & cmd );
- TQCString collectPipelineCommands( KioSMTP::TransactionState * ts );
- bool batchProcessResponses( KioSMTP::TransactionState * ts );
-
- /** This is a pure convenience wrapper around
- @ref KioSMTP::Capabilities::have() */
- bool haveCapability( const char * cap ) const {
- return mCapabilities.have( cap );
- }
-
- /** @return true is pipelining is available and allowed by metadata */
- bool canPipelineCommands() const {
- return haveCapability("PIPELINING") && metaData("pipelining") != "off" ;
- }
-
- /** Wrapper around getsockopt(..., SO_SNDBUF,...) */
- unsigned int sendBufferSize() const;
-
- /** This is a pure convenience wrapper around
- @ref KioSMTP::Capabilities::createSpecialResponse */
- TQString createSpecialResponse() const {
- return mCapabilities.createSpecialResponse( usingTLS() || haveCapability( "STARTTLS" ) );
- }
-
- void queueCommand( KioSMTP::Command * command ) {
- mPendingCommandQueue.enqueue( command );
- }
- void queueCommand( int type );
-
- unsigned short m_iOldPort;
- bool m_opened;
- TQString m_sServer, m_sOldServer;
- TQString m_sUser, m_sOldUser;
- TQString m_sPass, m_sOldPass;
- TQString m_hostname;
-
- KioSMTP::Capabilities mCapabilities;
-
- typedef TQPtrQueue<KioSMTP::Command> CommandQueue;
- CommandQueue mPendingCommandQueue;
- CommandQueue mSentCommandQueue;
-};
-
-#endif // _SMTP_H
diff --git a/kioslave/smtp/smtp.protocol b/kioslave/smtp/smtp.protocol
deleted file mode 100644
index e01be9c7f..000000000
--- a/kioslave/smtp/smtp.protocol
+++ /dev/null
@@ -1,16 +0,0 @@
-[Protocol]
-exec=kio_smtp
-protocol=smtp
-Capabilities=SASL
-input=none
-output=filesystem
-listing=Name,Type,Size
-reading=false
-writing=true
-deleting=false
-source=true
-makedir=false
-linking=false
-moving=false
-DocPath=kioslave/smtp.html
-Icon=folder_outbox
diff --git a/kioslave/smtp/smtps.protocol b/kioslave/smtp/smtps.protocol
deleted file mode 100644
index 2087845f2..000000000
--- a/kioslave/smtp/smtps.protocol
+++ /dev/null
@@ -1,15 +0,0 @@
-[Protocol]
-exec=kio_smtp
-protocol=smtps
-Capabilities=SASL
-input=none
-output=filesystem
-listing=Name,Type,Size
-reading=false
-writing=true
-deleting=false
-source=true
-makedir=false
-linking=false
-moving=false
-Icon=folder_outbox
diff --git a/kioslave/smtp/test_commands.cc b/kioslave/smtp/test_commands.cc
deleted file mode 100644
index 458b386b8..000000000
--- a/kioslave/smtp/test_commands.cc
+++ /dev/null
@@ -1,728 +0,0 @@
-#include <kio/global.h>
-#include <kdebug.h>
-
-#include <tqstring.h>
-#include <tqcstring.h>
-#include <tqstringlist.h>
-
-//#include <iostream>
-//using std::cout;
-//using std::endl;
-
-namespace KioSMTP {
- class Response;
-};
-
-// fake
-class SMTPProtocol {
-public:
- SMTPProtocol() { clear(); }
-
- //
- // public members to control the API emulation below:
- //
- int startTLSReturnCode;
- bool usesSSL;
- bool usesTLS;
- int lastErrorCode;
- TQString lastErrorMessage;
- int lastMessageBoxCode;
- TQString lastMessageBoxText;
- TQByteArray nextData;
- int nextDataReturnCode;
- TQStringList caps;
- TDEIO::MetaData metadata;
-
- void clear() {
- startTLSReturnCode = 1;
- usesSSL = usesTLS = false;
- lastErrorCode = lastMessageBoxCode = 0;
- lastErrorMessage = lastMessageBoxText = TQString::null;
- nextData.resize( 0 );
- nextDataReturnCode = -1;
- caps.clear();
- metadata.clear();
- }
-
- //
- // emulated API:
- //
- void parseFeatures( const KioSMTP::Response & ) { /* noop */ }
- int startTLS() {
- if ( startTLSReturnCode == 1 )
- usesTLS = true;
- return startTLSReturnCode;
- }
- bool usingSSL() const { return usesSSL; }
- bool usingTLS() const { return usesTLS; }
- bool haveCapability( const char * cap ) const { return caps.contains( cap ); }
- void error( int id, const TQString & msg ) {
- lastErrorCode = id;
- lastErrorMessage = msg;
- }
- void messageBox( int id, const TQString & msg, const TQString & ) {
- lastMessageBoxCode = id;
- lastMessageBoxText = msg;
- }
- void dataReq() { /* noop */ }
- int readData( TQByteArray & ba ) { ba = nextData; return nextDataReturnCode; }
- TQString metaData( const TQString & key ) const { return metadata[key]; }
-
-};
-
-#define _SMTP_H
-
-#define KIOSMTP_COMPARATORS // for TransactionState::operator==
-#include "command.h"
-#include "response.h"
-#include "transactionstate.h"
-
-#include <assert.h>
-
-using namespace KioSMTP;
-
-static const char * foobarbaz = ".Foo bar baz";
-static const unsigned int foobarbaz_len = tqstrlen( foobarbaz );
-
-static const char * foobarbaz_dotstuffed = "..Foo bar baz";
-static const unsigned int foobarbaz_dotstuffed_len = tqstrlen( foobarbaz_dotstuffed );
-
-static const char * foobarbaz_lf = ".Foo bar baz\n";
-static const unsigned int foobarbaz_lf_len = tqstrlen( foobarbaz_lf );
-
-static const char * foobarbaz_crlf = "..Foo bar baz\r\n";
-static const unsigned int foobarbaz_crlf_len = tqstrlen( foobarbaz_crlf );
-
-static void checkSuccessfulTransferCommand( bool, bool, bool, bool, bool );
-
-int main( int, char** ) {
-
- // FIXME: Port this to new API.
-#if 0
- SMTPProtocol smtp;
- Response r;
- TransactionState ts, ts2;
-
- //
- // EHLO / HELO
- //
-
- smtp.clear();
- EHLOCommand ehlo( &smtp, "mail.example.com" );
- // flags
- assert( ehlo.closeConnectionOnError() );
- assert( ehlo.mustBeLastInPipeline() );
- assert( !ehlo.mustBeFirstInPipeline() );
-
- // initial state
- assert( !ehlo.isComplete() );
- assert( !ehlo.doNotExecute( 0 ) );
- assert( !ehlo.needsResponse() );
-
- // dynamics 1: EHLO succeeds
- assert( ehlo.nextCommandLine( 0 ) == "EHLO mail.example.com\r\n" );
- assert( !ehlo.isComplete() ); // EHLO may fail and we then try HELO
- assert( ehlo.needsResponse() );
- r.clear();
- r.parseLine( "250-mail.example.net\r\n" );
- r.parseLine( "250-PIPELINING\r\n" );
- r.parseLine( "250 8BITMIME\r\n" );
- assert( ehlo.processResponse( r, 0 ) == true );
- assert( ehlo.isComplete() );
- assert( !ehlo.needsResponse() );
- assert( smtp.lastErrorCode == 0 );
- assert( smtp.lastErrorMessage.isNull() );
-
- // dynamics 2: EHLO fails with "unknown command"
- smtp.clear();
- EHLOCommand ehlo2( &smtp, "mail.example.com" );
- ehlo2.nextCommandLine( 0 );
- r.clear();
- r.parseLine( "500 unknown command\r\n" );
- assert( ehlo2.processResponse( r, 0 ) == true );
- assert( !ehlo2.isComplete() );
- assert( !ehlo2.needsResponse() );
- assert( ehlo2.nextCommandLine( 0 ) == "HELO mail.example.com\r\n" );
- assert( ehlo2.isComplete() );
- assert( ehlo2.needsResponse() );
- r.clear();
- r.parseLine( "250 mail.example.net\r\n" );
- assert( ehlo2.processResponse( r, 0 ) == true );
- assert( !ehlo2.needsResponse() );
- assert( smtp.lastErrorCode == 0 );
- assert( smtp.lastErrorMessage.isNull() );
-
- // dynamics 3: EHLO fails with unknown response code
- smtp.clear();
- EHLOCommand ehlo3( &smtp, "mail.example.com" );
- ehlo3.nextCommandLine( 0 );
- r.clear();
- r.parseLine( "545 you don't know me\r\n" );
- assert( ehlo3.processResponse( r, 0 ) == false );
- assert( ehlo3.isComplete() );
- assert( !ehlo3.needsResponse() );
- assert( smtp.lastErrorCode == TDEIO::ERR_UNKNOWN );
-
- // dynamics 4: EHLO _and_ HELO fail with "command unknown"
- smtp.clear();
- EHLOCommand ehlo4( &smtp, "mail.example.com" );
- ehlo4.nextCommandLine( 0 );
- r.clear();
- r.parseLine( "500 unknown command\r\n" );
- ehlo4.processResponse( r, 0 );
- ehlo4.nextCommandLine( 0 );
- r.clear();
- r.parseLine( "500 unknown command\r\n" );
- assert( ehlo4.processResponse( r, 0 ) == false );
- assert( ehlo4.isComplete() );
- assert( !ehlo4.needsResponse() );
- assert( smtp.lastErrorCode == TDEIO::ERR_INTERNAL_SERVER );
-
- //
- // STARTTLS
- //
-
- smtp.clear();
- StartTLSCommand tls( &smtp );
- // flags
- assert( tls.closeConnectionOnError() );
- assert( tls.mustBeLastInPipeline() );
- assert( !tls.mustBeFirstInPipeline() );
-
- // initial state
- assert( !tls.isComplete() );
- assert( !tls.doNotExecute( 0 ) );
- assert( !tls.needsResponse() );
-
- // dynamics 1: ok from server, TLS negotiation successful
- ts.clear();
- ts2 = ts;
- assert( tls.nextCommandLine( &ts ) == "STARTTLS\r\n" );
- assert( ts == ts2 );
- assert( tls.isComplete() );
- assert( tls.needsResponse() );
- r.clear();
- r.parseLine( "220 Go ahead" );
- smtp.startTLSReturnCode = 1;
- assert( tls.processResponse( r, &ts ) == true );
- assert( !tls.needsResponse() );
- assert( smtp.lastErrorCode == 0 );
-
- // dynamics 2: NAK from server
- smtp.clear();
- StartTLSCommand tls2( &smtp );
- ts.clear();
- tls2.nextCommandLine( &ts );
- r.clear();
- r.parseLine( "454 TLS temporarily disabled" );
- smtp.startTLSReturnCode = 1;
- assert( tls2.processResponse( r, &ts ) == false );
- assert( !tls2.needsResponse() );
- assert( smtp.lastErrorCode == TDEIO::ERR_SERVICE_NOT_AVAILABLE );
-
- // dynamics 3: ok from server, TLS negotiation unsuccessful
- smtp.clear();
- StartTLSCommand tls3( &smtp );
- ts.clear();
- tls3.nextCommandLine( &ts );
- r.clear();
- r.parseLine( "220 Go ahead" );
- smtp.startTLSReturnCode = -1;
- assert( tls.processResponse( r, &ts ) == false );
- assert( !tls.needsResponse() );
-
- //
- // AUTH
- //
-
- smtp.clear();
- TQStrIList mechs;
- mechs.append( "PLAIN" );
- smtp.metadata["sasl"] = "PLAIN";
- AuthCommand auth( &smtp, mechs, "user", "pass" );
- // flags
- assert( auth.closeConnectionOnError() );
- assert( auth.mustBeLastInPipeline() );
- assert( !auth.mustBeFirstInPipeline() );
-
- // initial state
- assert( !auth.isComplete() );
- assert( !auth.doNotExecute( 0 ) );
- assert( !auth.needsResponse() );
-
- // dynamics 1: TLS, so AUTH should include initial-response:
- smtp.usesTLS = true;
- ts.clear();
- ts2 = ts;
- assert( auth.nextCommandLine( &ts ) == "AUTH PLAIN dXNlcgB1c2VyAHBhc3M=\r\n" );
- assert( auth.isComplete() );
- assert( auth.needsResponse() );
- assert( ts == ts2 );
- r.clear();
- r.parseLine( "250 OK" );
-
- // dynamics 2: No TLS, so AUTH should not include initial-response:
- smtp.clear();
- smtp.metadata["sasl"] = "PLAIN";
- smtp.usesTLS = false;
- AuthCommand auth2( &smtp, mechs, "user", "pass" );
- ts.clear();
- assert( auth2.nextCommandLine( &ts ) == "AUTH PLAIN\r\n" );
- assert( !auth2.isComplete() );
- assert( auth2.needsResponse() );
- r.clear();
- r.parseLine( "334 Go on" );
- assert( auth2.processResponse( r, &ts ) == true );
- assert( auth2.nextCommandLine( &ts ) == "dXNlcgB1c2VyAHBhc3M=\r\n" );
- assert( auth2.isComplete() );
- assert( auth2.needsResponse() );
-
- // dynamics 3: LOGIN
- smtp.clear();
- smtp.metadata["sasl"] = "LOGIN";
- mechs.clear();
- mechs.append( "LOGIN" );
- AuthCommand auth3( &smtp, mechs, "user", "pass" );
- ts.clear();
- ts2 = ts;
- assert( auth3.nextCommandLine( &ts ) == "AUTH LOGIN\r\n" );
- assert( !auth3.isComplete() );
- assert( auth3.needsResponse() );
- r.clear();
- r.parseLine( "334 VXNlcm5hbWU6" );
- assert( auth3.processResponse( r, &ts ) == true );
- assert( !auth3.needsResponse() );
- assert( auth3.nextCommandLine( &ts ) == "dXNlcg==\r\n" );
- assert( !auth3.isComplete() );
- assert( auth3.needsResponse() );
- r.clear();
- r.parseLine( "334 go on" );
- assert( auth3.processResponse( r, &ts ) == true );
- assert( !auth3.needsResponse() );
- assert( auth3.nextCommandLine( &ts ) == "cGFzcw==\r\n" );
- assert( auth3.isComplete() );
- assert( auth3.needsResponse() );
- r.clear();
- r.parseLine( "250 OK" );
- assert( auth3.processResponse( r, &ts ) == true );
- assert( !auth3.needsResponse() );
- assert( !smtp.lastErrorCode );
- assert( ts == ts2 );
-
- //
- // MAIL FROM:
- //
-
- smtp.clear();
- MailFromCommand mail( &smtp, "[email protected]" );
- // flags
- assert( !mail.closeConnectionOnError() );
- assert( !mail.mustBeLastInPipeline() );
- assert( !mail.mustBeFirstInPipeline() );
-
- // initial state
- assert( !mail.isComplete() );
- assert( !mail.doNotExecute( 0 ) );
- assert( !mail.needsResponse() );
-
- // dynamics: success, no size, no 8bit
- ts.clear();
- ts2 = ts;
- assert( mail.nextCommandLine( &ts ) == "MAIL FROM:<[email protected]>\r\n" );
- assert( ts2 == ts );
- assert( mail.isComplete() );
- assert( mail.needsResponse() );
- r.clear();
- r.parseLine( "250 Ok" );
- assert( mail.processResponse( r, &ts ) == true );
- assert( !mail.needsResponse() );
- assert( ts == ts2 );
- assert( smtp.lastErrorCode == 0 );
-
- // dynamics: success, size, 8bit, but no SIZE, 8BITMIME caps
- smtp.clear();
- MailFromCommand mail2( &smtp, "[email protected]", true, 500 );
- ts.clear();
- ts2 = ts;
- assert( mail2.nextCommandLine( &ts ) == "MAIL FROM:<[email protected]>\r\n" );
- assert( ts == ts2 );
-
- // dynamics: success, size, 8bit, SIZE, 8BITMIME caps
- smtp.clear();
- MailFromCommand mail3( &smtp, "[email protected]", true, 500 );
- ts.clear();
- ts2 = ts;
- smtp.caps << "SIZE" << "8BITMIME" ;
- assert( mail3.nextCommandLine( &ts ) == "MAIL FROM:<[email protected]> BODY=8BITMIME SIZE=500\r\n" );
- assert( ts == ts2 );
-
- // dynamics: failure
- smtp.clear();
- MailFromCommand mail4( &smtp, "[email protected]" );
- ts.clear();
- mail4.nextCommandLine( &ts );
- r.clear();
- r.parseLine( "503 Bad sequence of commands" );
- assert( mail4.processResponse( r, &ts ) == false );
- assert( mail4.isComplete() );
- assert( !mail4.needsResponse() );
- assert( ts.failed() );
- assert( !ts.failedFatally() );
- assert( smtp.lastErrorCode == 0 );
-
- //
- // RCPT TO:
- //
-
- smtp.clear();
- RcptToCommand rcpt( &smtp, "[email protected]" );
- // flags
- assert( !rcpt.closeConnectionOnError() );
- assert( !rcpt.mustBeLastInPipeline() );
- assert( !rcpt.mustBeFirstInPipeline() );
-
- // initial state
- assert( !rcpt.isComplete() );
- assert( !rcpt.doNotExecute( 0 ) );
- assert( !rcpt.needsResponse() );
-
- // dynamics: success
- ts.clear();
- ts2 = ts;
- assert( rcpt.nextCommandLine( &ts ) == "RCPT TO:<[email protected]>\r\n" );
- assert( ts == ts2 );
- assert( rcpt.isComplete() );
- assert( rcpt.needsResponse() );
- r.clear();
- r.parseLine( "250 Ok" );
- assert( rcpt.processResponse( r, &ts ) == true );
- assert( !rcpt.needsResponse() );
- assert( ts.atLeastOneRecipientWasAccepted() );
- assert( !ts.haveRejectedRecipients() );
- assert( !ts.failed() );
- assert( !ts.failedFatally() );
- assert( smtp.lastErrorCode == 0 );
-
- // dynamics: failure
- smtp.clear();
- RcptToCommand rcpt2( &smtp, "[email protected]" );
- ts.clear();
- rcpt2.nextCommandLine( &ts );
- r.clear();
- r.parseLine( "530 5.7.1 Relaying not allowed!" );
- assert( rcpt2.processResponse( r, &ts ) == false );
- assert( rcpt2.isComplete() );
- assert( !rcpt2.needsResponse() );
- assert( !ts.atLeastOneRecipientWasAccepted() );
- assert( ts.haveRejectedRecipients() );
- assert( ts.rejectedRecipients().count() == 1 );
- assert( ts.rejectedRecipients().front().recipient == "[email protected]" );
- assert( ts.failed() );
- assert( !ts.failedFatally() );
- assert( smtp.lastErrorCode == 0 );
-
- // dynamics: success and failure combined
- smtp.clear();
- RcptToCommand rcpt3( &smtp, "[email protected]" );
- RcptToCommand rcpt4( &smtp, "[email protected]" );
- RcptToCommand rcpt5( &smtp, "[email protected]" );
- ts.clear();
- rcpt3.nextCommandLine( &ts );
- r.clear();
- r.parseLine( "530 5.7.1 Relaying not allowed!" );
- rcpt3.processResponse( r, &ts );
-
- rcpt4.nextCommandLine( &ts );
- r.clear();
- r.parseLine( "250 Ok" );
- rcpt4.processResponse( r, &ts );
-
- rcpt5.nextCommandLine( &ts );
- r.clear();
- r.parseLine( "250 Ok" );
- assert( ts.failed() );
- assert( !ts.failedFatally() );
- assert( ts.haveRejectedRecipients() );
- assert( ts.atLeastOneRecipientWasAccepted() );
- assert( smtp.lastErrorCode == 0 );
-
- //
- // DATA (init)
- //
-
- smtp.clear();
- DataCommand data( &smtp );
- // flags
- assert( !data.closeConnectionOnError() );
- assert( data.mustBeLastInPipeline() );
- assert( !data.mustBeFirstInPipeline() );
-
- // initial state
- assert( !data.isComplete() );
- assert( !data.doNotExecute( 0 ) );
- assert( !data.needsResponse() );
-
- // dynamics: success
- ts.clear();
- assert( data.nextCommandLine( &ts ) == "DATA\r\n" );
- assert( data.isComplete() );
- assert( data.needsResponse() );
- assert( ts.dataCommandIssued() );
- assert( !ts.dataCommandSucceeded() );
- r.clear();
- r.parseLine( "354 Send data, end in <CR><LF>.<CR><LF>" );
- assert( data.processResponse( r, &ts ) == true );
- assert( !data.needsResponse() );
- assert( ts.dataCommandSucceeded() );
- assert( ts.dataResponse() == r );
- assert( smtp.lastErrorCode == 0 );
-
- // dynamics: failure
- smtp.clear();
- DataCommand data2( &smtp );
- ts.clear();
- data2.nextCommandLine( &ts );
- r.clear();
- r.parseLine( "551 No valid recipients" );
- assert( data2.processResponse( r, &ts ) == false );
- assert( !data2.needsResponse() );
- assert( !ts.dataCommandSucceeded() );
- assert( ts.dataResponse() == r );
- assert( smtp.lastErrorCode == 0 );
-
- //
- // DATA (transfer)
- //
-
- TransferCommand xfer( &smtp, 0 );
- // flags
- assert( !xfer.closeConnectionOnError() );
- assert( !xfer.mustBeLastInPipeline() );
- assert( xfer.mustBeFirstInPipeline() );
-
- // initial state
- assert( !xfer.isComplete() );
- assert( !xfer.needsResponse() );
-
- // dynamics 1: DATA command failed
- ts.clear();
- r.clear();
- r.parseLine( "551 no valid recipients" );
- ts.setDataCommandIssued( true );
- ts.setDataCommandSucceeded( false, r );
- assert( xfer.doNotExecute( &ts ) );
-
- // dynamics 2: some recipients rejected, but not all
- smtp.clear();
- TransferCommand xfer2( &smtp, 0 );
- ts.clear();
- ts.setRecipientAccepted();
- ts.addRejectedRecipient( "[email protected]", "No relaying allowed" );
- ts.setDataCommandIssued( true );
- r.clear();
- r.parseLine( "354 go on" );
- ts.setDataCommandSucceeded( true, r );
- // ### will change with allow-partial-delivery option:
- assert( xfer.doNotExecute( &ts ) );
-
- // successful dynamics with all combinations of:
- enum {
- EndInLF = 1,
- PerformDotStuff = 2,
- UngetLast = 4,
- Preloading = 8,
- Error = 16,
- EndOfOptions = 32
- };
- for ( unsigned int i = 0 ; i < EndOfOptions ; ++i )
- checkSuccessfulTransferCommand( i & Error, i & Preloading, i & UngetLast,
- i & PerformDotStuff, i & EndInLF );
-
- //
- // NOOP
- //
-
- smtp.clear();
- NoopCommand noop( &smtp );
- // flags
- assert( !noop.closeConnectionOnError() );
- assert( noop.mustBeLastInPipeline() );
- assert( !noop.mustBeFirstInPipeline() );
-
- // initial state
- assert( !noop.isComplete() );
- assert( !noop.doNotExecute( &ts ) );
- assert( !noop.needsResponse() );
-
- // dynamics: success (failure is tested with RSET)
- assert( noop.nextCommandLine( 0 ) == "NOOP\r\n" );
- assert( noop.isComplete() );
- assert( noop.needsResponse() );
- r.clear();
- r.parseLine( "250 Ok" );
- assert( noop.processResponse( r, 0 ) == true );
- assert( noop.isComplete() );
- assert( !noop.needsResponse() );
- assert( smtp.lastErrorCode == 0 );
- assert( smtp.lastErrorMessage.isNull() );
-
- //
- // RSET
- //
-
- smtp.clear();
- RsetCommand rset( &smtp );
- // flags
- assert( rset.closeConnectionOnError() );
- assert( !rset.mustBeLastInPipeline() );
- assert( !rset.mustBeFirstInPipeline() );
-
- // initial state
- assert( !rset.isComplete() );
- assert( !rset.doNotExecute( &ts ) );
- assert( !rset.needsResponse() );
-
- // dynamics: failure (success is tested with NOOP/QUIT)
- assert( rset.nextCommandLine( 0 ) == "RSET\r\n" );
- assert( rset.isComplete() );
- assert( rset.needsResponse() );
- r.clear();
- r.parseLine( "502 command not implemented" );
- assert( rset.processResponse( r, 0 ) == false );
- assert( rset.isComplete() );
- assert( !rset.needsResponse() );
- assert( smtp.lastErrorCode == 0 ); // an RSET failure isn't worth it, is it?
- assert( smtp.lastErrorMessage.isNull() );
-
- //
- // QUIT
- //
-
- smtp.clear();
- QuitCommand quit( &smtp );
- // flags
- assert( quit.closeConnectionOnError() );
- assert( quit.mustBeLastInPipeline() );
- assert( !quit.mustBeFirstInPipeline() );
-
- // initial state
- assert( !quit.isComplete() );
- assert( !quit.doNotExecute( 0 ) );
- assert( !quit.needsResponse() );
-
- // dynamics 1: success
- assert( quit.nextCommandLine( 0 ) == "QUIT\r\n" );
- assert( quit.isComplete() );
- assert( quit.needsResponse() );
- r.clear();
- r.parseLine( "221 Goodbye" );
- assert( quit.processResponse( r, 0 ) == true );
- assert( quit.isComplete() );
- assert( !quit.needsResponse() );
- assert( smtp.lastErrorCode == 0 );
- assert( smtp.lastErrorMessage.isNull() );
-
- // dynamics 2: success
- smtp.clear();
- QuitCommand quit2( &smtp );
- quit2.nextCommandLine( 0 );
- r.clear();
- r.parseLine( "500 unknown command" );
- assert( quit2.processResponse( r, 0 ) == false );
- assert( quit2.isComplete() );
- assert( !quit2.needsResponse() );
- assert( smtp.lastErrorCode == 0 ); // an QUIT failure isn't worth it, is it?
- assert( smtp.lastErrorMessage.isNull() );
-#endif
-
- return 0;
-}
-
-void checkSuccessfulTransferCommand( bool error, bool preload, bool ungetLast,
- bool slaveDotStuff, bool mailEndsInNewline ) {
- kdDebug() << " ===== checkTransferCommand( "
- << error << ", "
- << preload << ", "
- << ungetLast << ", "
- << slaveDotStuff << ", "
- << mailEndsInNewline << " ) =====" << endl;
-
- SMTPProtocol smtp;
- if ( slaveDotStuff )
- smtp.metadata["lf2crlf+dotstuff"] = "slave";
-
- Response r;
-
- const char * s_pre = slaveDotStuff ?
- mailEndsInNewline ? foobarbaz_lf : foobarbaz
- :
- mailEndsInNewline ? foobarbaz_crlf : foobarbaz_dotstuffed ;
- const unsigned int s_pre_len = tqstrlen( s_pre );
-
- const char * s_post = mailEndsInNewline ? foobarbaz_crlf : foobarbaz_dotstuffed ;
- //const unsigned int s_post_len = tqstrlen( s_post );
-
- TransferCommand xfer( &smtp, preload ? s_post : 0 );
-
- TransactionState ts;
- ts.setRecipientAccepted();
- ts.setDataCommandIssued( true );
- r.clear();
- r.parseLine( "354 ok" );
- ts.setDataCommandSucceeded( true, r );
- assert( !xfer.doNotExecute( &ts ) );
- if ( preload ) {
- assert( xfer.nextCommandLine( &ts ) == s_post );
- assert( !xfer.isComplete() );
- assert( !xfer.needsResponse() );
- assert( !ts.failed() );
- assert( smtp.lastErrorCode == 0 );
- }
- smtp.nextData.duplicate( s_pre, s_pre_len );
- smtp.nextDataReturnCode = s_pre_len;
- assert( xfer.nextCommandLine( &ts ) == s_post );
- assert( !xfer.isComplete() );
- assert( !xfer.needsResponse() );
- assert( !ts.failed() );
- assert( smtp.lastErrorCode == 0 );
- smtp.nextData.resize( 0 );
- smtp.nextDataReturnCode = 0;
- if ( ungetLast ) {
- xfer.ungetCommandLine( xfer.nextCommandLine( &ts ), &ts );
- assert( !xfer.isComplete() );
- assert( !xfer.needsResponse() );
- assert( !ts.complete() );
- smtp.nextDataReturnCode = -1; // double read -> error
- }
- if ( mailEndsInNewline )
- assert( xfer.nextCommandLine( &ts ) == ".\r\n" );
- else
- assert( xfer.nextCommandLine( &ts ) == "\r\n.\r\n" );
- assert( xfer.isComplete() );
- assert( xfer.needsResponse() );
- assert( !ts.complete() );
- assert( !ts.failed() );
- assert( smtp.lastErrorCode == 0 );
- r.clear();
- if ( error ) {
- r.parseLine( "552 Exceeded storage allocation" );
- assert( xfer.processResponse( r, &ts ) == false );
- assert( !xfer.needsResponse() );
- assert( ts.complete() );
- assert( ts.failed() );
- assert( smtp.lastErrorCode == TDEIO::ERR_DISK_FULL );
- } else {
- r.parseLine( "250 Message accepted" );
- assert( xfer.processResponse( r, &ts ) == true );
- assert( !xfer.needsResponse() );
- assert( ts.complete() );
- assert( !ts.failed() );
- assert( smtp.lastErrorCode == 0 );
- }
-};
-
-#define NDEBUG
-
-#include "command.cc"
-#include "response.cc"
-#include "transactionstate.cc"
diff --git a/kioslave/smtp/test_headergeneration.cc b/kioslave/smtp/test_headergeneration.cc
deleted file mode 100644
index 83d999c4a..000000000
--- a/kioslave/smtp/test_headergeneration.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "request.h"
-
-//#include <iostream>
-
-//using std::cout;
-//using std::endl;
-
-int main( int , char ** ) {
- static TQCString expected =
- "From: [email protected]\r\n"
- "Subject: missing subject\r\n"
- "To: [email protected],\r\n"
- "Cc: [email protected]\r\n"
- "\n"
- "From: Marc Mutz <[email protected]>\r\n"
- "Subject: missing subject\r\n"
- "To: [email protected],\r\n"
- "Cc: [email protected]\r\n"
- "\n"
- "From: \"Mutz, Marc\" <[email protected]>\r\n"
- "Subject: missing subject\r\n"
- "To: [email protected],\r\n"
- "Cc: [email protected]\r\n"
- "\n"
- "From: =?utf-8?b?TWFyYyBNw7Z0eg==?= <[email protected]>\r\n"
- "Subject: missing subject\r\n"
- "To: [email protected],\r\n"
- "Cc: [email protected]\r\n"
- "\n"
- "From: [email protected]\r\n"
- "Subject: =?utf-8?b?QmzDtmRlcyBTdWJqZWN0?=\r\n"
- "To: [email protected],\r\n"
- "Cc: [email protected]\r\n"
- "\n"
- "From: Marc Mutz <[email protected]>\r\n"
- "Subject: =?utf-8?b?QmzDtmRlcyBTdWJqZWN0?=\r\n"
- "To: [email protected],\r\n"
- "Cc: [email protected]\r\n"
- "\n"
- "From: \"Mutz, Marc\" <[email protected]>\r\n"
- "Subject: =?utf-8?b?QmzDtmRlcyBTdWJqZWN0?=\r\n"
- "To: [email protected],\r\n"
- "Cc: [email protected]\r\n"
- "\n"
- "From: =?utf-8?b?TWFyYyBNw7Z0eg==?= <[email protected]>\r\n"
- "Subject: =?utf-8?b?QmzDtmRlcyBTdWJqZWN0?=\r\n"
- "To: [email protected],\r\n"
- "Cc: [email protected]\r\n"
- "\n";
-
- KioSMTP::Request request;
- TQCString result;
-
- request.setEmitHeaders( true );
- request.setFromAddress( "[email protected]" );
- request.addTo( "[email protected]" );
- request.addTo( "[email protected]" );
- request.addCc( "[email protected]" );
-
- result += request.headerFields() + '\n';
- result += request.headerFields( "Marc Mutz" ) + '\n';
- result += request.headerFields( "Mutz, Marc" ) + '\n';
- result += request.headerFields( "Marc M�tz" ) + '\n';
-
- request.setSubject( "Bl�des Subject" );
-
- result += request.headerFields() + '\n';
- result += request.headerFields( "Marc Mutz" ) + '\n';
- result += request.headerFields( "Mutz, Marc" ) + '\n';
- result += request.headerFields( "Marc M�tz" ) + '\n';
-
- //cout << "Result:\n" << result.data() << endl;
-
- return result == expected ? 0 : 1 ;
-}
-
-#include "request.cc"
-
diff --git a/kioslave/smtp/test_responseparser.cc b/kioslave/smtp/test_responseparser.cc
deleted file mode 100644
index e251aa291..000000000
--- a/kioslave/smtp/test_responseparser.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-#include "response.h"
-#include <assert.h>
-
-static const TQCString singleLineResponseCRLF = "250 OK\r\n";
-static const TQCString singleLineResponse = "250 OK";
-
-static const TQCString multiLineResponse[] = {
- "250-ktown.kde.org\r\n",
- "250-STARTTLS\r\n",
- "250-AUTH PLAIN DIGEST-MD5\r\n",
- "250 PIPELINING\r\n"
-};
-static const unsigned int numMultiLineLines = sizeof multiLineResponse / sizeof *multiLineResponse ;
-
-int main ( int, char** ) {
-
- KioSMTP::Response r;
- assert( r.isValid() );
- assert( r.lines().empty() );
- assert( r.isWellFormed() );
- assert( r.code() == 0 );
- assert( r.isUnknown() );
- assert( !r.isComplete() );
- assert( !r.isOk() );
- r.parseLine( singleLineResponseCRLF.data(),
- singleLineResponseCRLF.length() );
- assert( r.isWellFormed() );
- assert( r.isComplete() );
- assert( r.isValid() );
- assert( r.isPositive() );
- assert( r.isOk() );
- assert( r.code() == 250 );
- assert( r.errorCode() == 0 );
- assert( r.first() == 2 );
- assert( r.second() == 5 );
- assert( r.third() == 0 );
- assert( r.lines().count() == 1 );
- assert( r.lines().front() == "OK" );
- r.parseLine( singleLineResponse.data(),
- singleLineResponse.length() );
- assert( !r.isValid() );
- r.clear();
- assert( r.isValid() );
- assert( r.lines().empty() );
-
- r.parseLine( singleLineResponse.data(),
- singleLineResponse.length() );
- assert( r.isWellFormed() );
- assert( r.isComplete() );
- assert( r.isValid() );
- assert( r.isPositive() );
- assert( r.isOk() );
- assert( r.code() == 250 );
- assert( r.first() == 2 );
- assert( r.second() == 5 );
- assert( r.third() == 0 );
- assert( r.lines().count() == 1 );
- assert( r.lines().front() == "OK" );
- r.parseLine( singleLineResponse.data(),
- singleLineResponse.length() );
- assert( !r.isValid() );
- r.clear();
- assert( r.isValid() );
-
- for ( unsigned int i = 0 ; i < numMultiLineLines ; ++i ) {
- r.parseLine( multiLineResponse[i].data(),
- multiLineResponse[i].length() );
- assert( r.isWellFormed() );
- if ( i < numMultiLineLines-1 )
- assert( !r.isComplete() );
- else
- assert( r.isComplete() );
- assert( r.isValid() );
- assert( r.isPositive() );
- assert( r.code() == 250 );
- assert( r.first() == 2 );
- assert( r.second() == 5 );
- assert( r.third() == 0 );
- assert( r.lines().count() == i + 1 );
- }
- assert( r.lines().back() == "PIPELINING" );
-
- r.clear();
- r.parseLine( "230", 3 );
- assert( r.isValid() );
- assert( r.isWellFormed() ); // even though it isn't ;-)
- assert( r.code() == 230 );
- assert( r.lines().count() == 1 );
- assert( r.lines().front().isNull() );
-
- r.clear();
- r.parseLine( "230\r\n", 5 );
- assert( r.isValid() );
- assert( r.isWellFormed() ); // even though it isn't ;-)
- assert( r.code() == 230 );
- assert( r.lines().count() == 1 );
- assert( r.lines().front().isNull() );
-
- r.clear();
- r.parseLine( " 23 ok", 6 );
- assert( !r.isValid() );
- assert( !r.isWellFormed() );
-
- return 0;
-}
-
-#include "response.cc"
diff --git a/kioslave/smtp/transactionstate.cc b/kioslave/smtp/transactionstate.cc
deleted file mode 100644
index b34b45227..000000000
--- a/kioslave/smtp/transactionstate.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-/* -*- c++ -*-
- transactionstate.cc
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#include <config.h>
-
-#include "transactionstate.h"
-
-#include <kio/global.h>
-#include <klocale.h>
-
-#include <tqstringlist.h>
-
-namespace KioSMTP {
-
- void TransactionState::setFailedFatally( int code, const TQString & msg ) {
- mFailed = mFailedFatally = true;
- mErrorCode = code;
- mErrorMessage = msg;
- }
-
- void TransactionState::setMailFromFailed( const TQString & addr, const Response & r ) {
- setFailed();
- mErrorCode = TDEIO::ERR_NO_CONTENT;
- if ( addr.isEmpty() )
- mErrorMessage = i18n("The server did not accept a blank sender address.\n"
- "%1").arg( r.errorMessage() );
- else
- mErrorMessage = i18n("The server did not accept the sender address \"%1\".\n"
- "%2").arg( addr ).arg( r.errorMessage() );
- }
-
- void TransactionState::addRejectedRecipient( const RecipientRejection & r ) {
- mRejectedRecipients.push_back( r );
- if ( mRcptToDenyIsFailure )
- setFailed();
- }
-
- void TransactionState::setDataCommandSucceeded( bool succeeded, const Response & r ) {
- mDataCommandSucceeded = succeeded;
- mDataResponse = r;
- if ( !succeeded )
- setFailed();
- else if ( failed() )
- // can happen with pipelining: the server accepts the DATA, but
- // we don't want to send the data, so force a connection
- // shutdown:
- setFailedFatally();
- }
-
- int TransactionState::errorCode() const {
- if ( !failed() )
- return 0;
- if ( mErrorCode )
- return mErrorCode;
- if ( haveRejectedRecipients() || !dataCommandSucceeded() )
- return TDEIO::ERR_NO_CONTENT;
- // ### what else?
- return TDEIO::ERR_INTERNAL;
- }
-
- TQString TransactionState::errorMessage() const {
- if ( !failed() )
- return TQString::null;
-
- if ( !mErrorMessage.isEmpty() )
- return mErrorMessage;
-
- if ( haveRejectedRecipients() ) {
- TQString msg = i18n("Message sending failed since the following recipients were rejected by the server:\n"
- "%1");
- TQStringList recip;
- for ( RejectedRecipientList::const_iterator it = mRejectedRecipients.begin() ;
- it != mRejectedRecipients.end() ; ++it )
- recip.push_back( (*it).recipient + " (" + (*it).reason + ')' );
- return msg.arg( recip.join("\n") );
- }
-
- if ( !dataCommandSucceeded() )
- return i18n("The attempt to start sending the message content failed.\n"
- "%1").arg( mDataResponse.errorMessage() );
-
- // ### what else?
- return i18n("Unhandled error condition. Please send a bug report.");
- }
-
-}
diff --git a/kioslave/smtp/transactionstate.h b/kioslave/smtp/transactionstate.h
deleted file mode 100644
index d2f9ef797..000000000
--- a/kioslave/smtp/transactionstate.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* -*- c++ -*-
- transactionstate.h
-
- This file is part of kio_smtp, the KDE SMTP kioslave.
- Copyright (c) 2003 Marc Mutz <[email protected]>
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#ifndef __KIOSMTP_TRANSACTIONSTATE_H__
-#define __KIOSMTP_TRANSACTIONSTATE_H__
-
-#include "response.h"
-
-#include <tqstring.h>
-#include <tqvaluelist.h>
-
-namespace KioSMTP {
-
- /**
- @short A class modelling an SMTP transaction's state
-
- This class models SMTP transaction state, ie. the collective
- result of the MAIL FROM:, RCPT TO: and DATA commands. This is
- needed since e.g. a single failed RCPT TO: command does not
- neccessarily fail the whole transaction (servers are free to
- accept delivery for some recipients, but not for others).
-
- The class can operate in two modes, which differ in the way
- failed recipients are handled. If @p rcptToDenyIsFailure is true
- (the default), then any failing RCPT TO: will cause the
- transaction to fail. Since at the point of RCPT TO: failure
- detection, the DATA command may have already been sent
- (pipelining), the only way to cancel the transaction is to take
- down the connection hard (ie. without proper quit).
-
- Since that is not very nice behaviour, a second mode that is more
- to the spirit of SMTP is provided that can cope with partially
- failed RCPT TO: commands.
- */
- class TransactionState {
- public:
- struct RecipientRejection {
- RecipientRejection( const TQString & who=TQString::null,
- const TQString & why=TQString::null )
- : recipient( who ), reason( why ) {}
- TQString recipient;
- TQString reason;
-#ifdef KIOSMTP_COMPARATORS
- bool operator==( const RecipientRejection & other ) const {
- return recipient == other.recipient && reason == other.reason;
- }
-#endif
- };
- typedef TQValueList<RecipientRejection> RejectedRecipientList;
-
- TransactionState( bool rcptToDenyIsFailure=true )
- : mErrorCode( 0 ),
- mRcptToDenyIsFailure( rcptToDenyIsFailure ),
- mAtLeastOneRecipientWasAccepted( false ),
- mDataCommandIssued( false ),
- mDataCommandSucceeded( false ),
- mFailed( false ),
- mFailedFatally( false ),
- mComplete( false ) {}
-
- /** @return whether the transaction failed (e.g. the server
- rejected all recipients. Graceful failure is handled after
- transaction ends. */
- bool failed() const { return mFailed || mFailedFatally; }
- void setFailed() { mFailed = true; }
-
- /** @return whether the failure was so grave that an immediate
- untidy connection shutdown is in order (ie. @ref
- smtp_close(false)). Fatal failure is handled immediately */
- bool failedFatally() const { return mFailedFatally; }
- void setFailedFatally( int code=0, const TQString & msg=TQString::null );
-
- /** @return whether the transaction was completed successfully */
- bool complete() const { return mComplete; }
- void setComplete() { mComplete = true; }
-
- /** @return an appropriate KIO error code in case the transaction
- failed, or 0 otherwise */
- int errorCode() const;
- /** @return an appropriate error message in case the transaction
- failed or TQString::null otherwise */
- TQString errorMessage() const;
-
- void setMailFromFailed( const TQString & addr, const Response & r );
-
- bool dataCommandIssued() const { return mDataCommandIssued; }
- void setDataCommandIssued( bool issued ) { mDataCommandIssued = issued; }
-
- bool dataCommandSucceeded() const {
- return mDataCommandIssued && mDataCommandSucceeded;
- }
- void setDataCommandSucceeded( bool succeeded, const Response & r );
-
- Response dataResponse() const {
- return mDataResponse;
- }
-
- bool atLeastOneRecipientWasAccepted() const {
- return mAtLeastOneRecipientWasAccepted;
- }
- void setRecipientAccepted() {
- mAtLeastOneRecipientWasAccepted = true;
- }
-
- bool haveRejectedRecipients() const {
- return !mRejectedRecipients.empty();
- }
- RejectedRecipientList rejectedRecipients() const {
- return mRejectedRecipients;
- }
- void addRejectedRecipient( const RecipientRejection & r );
- void addRejectedRecipient( const TQString & who, const TQString & why ) {
- addRejectedRecipient( RecipientRejection( who, why ) );
- }
-
- void clear() {
- mRejectedRecipients.clear();
- mDataResponse.clear();
- mAtLeastOneRecipientWasAccepted
- = mDataCommandIssued
- = mDataCommandSucceeded
- = mFailed = mFailedFatally
- = mComplete = false;
- }
-
-#ifdef KIOSMTP_COMPARATORS
- bool operator==( const TransactionState & other ) const {
- return
- mAtLeastOneRecipientWasAccepted == other.mAtLeastOneRecipientWasAccepted &&
- mDataCommandIssued == other.mDataCommandIssued &&
- mDataCommandSucceeded == other.mDataCommandSucceeded &&
- mFailed == other.mFailed &&
- mFailedFatally == other.mFailedFatally &&
- mComplete == other.mComplete &&
- mDataResponse.code() == other.mDataResponse.code() &&
- mRejectedRecipients == other.mRejectedRecipients;
- }
-#endif
-
-
- private:
- RejectedRecipientList mRejectedRecipients;
- Response mDataResponse;
- TQString mErrorMessage;
- int mErrorCode;
- bool mRcptToDenyIsFailure;
- bool mAtLeastOneRecipientWasAccepted;
- bool mDataCommandIssued;
- bool mDataCommandSucceeded;
- bool mFailed;
- bool mFailedFatally;
- bool mComplete;
- };
-
-} // namespace KioSMTP
-
-#endif // __KIOSMTP_TRANSACTIONSTATE_H__