diff --git a/mailtransport/TODO b/mailtransport/TODO index b08dd9eaa..e2b12e33e 100644 --- a/mailtransport/TODO +++ b/mailtransport/TODO @@ -1,32 +1,35 @@ Mail Transport TODO ~~~~~~~~~~~~~~~~~~~ Migration --------- - password migration within kwallet (for kmail and knode), requires KWallet to be fixed first TransportManager ---------------- - load passwords if another instance opens the wallet - load passwords if application opens wallet - add D-Bus interface for sending mails - test to see if there is always a default transport, by adding / deleting accounts +- it would be nice to make showNewTransportDialog, + promptCreateTransportIfNoneExists, and configureTransport visible on D-Bus, + but how to handle QWidget *parent? Transport --------- - password is not reloaded from wallet on remote change TransportJob ------------ - use QByteArray for addresses instead of QString SMTPJob ------- - get rid of kmail specific stuff in start() Precommand ---------- - test conversion from kprocess to qprocess (TA) diff --git a/mailtransport/TODO.cberzan b/mailtransport/TODO.cberzan deleted file mode 100644 index 4c0d501c7..000000000 --- a/mailtransport/TODO.cberzan +++ /dev/null @@ -1,12 +0,0 @@ -* all CamelCase... -* smtpsettings.ui has hidden widgets... test those... and why can't I set/see the 'visible' property in designer? -* why is identitylistview in kmail instead of kpimidentities? -* figure out what needs to be exported and what not (add .hs to CMakeLists afterwards) -* include KLocale or KLocalizedString?? -* SMTPJob (and probably others) give empty errorString when killed - -Bugs: -* modify -> change password -> ok. password is saved in wallet and seen ok on restart, but clicking modify again shows old password -* Type=Akonadi and Type=Sendmail appear in the config file, but no Type=SMTP (probably because SMTP == 0 == default) -* cancel doesn't work in transportmgr, apparently - diff --git a/mailtransport/addtransportdialog.cpp b/mailtransport/addtransportdialog.cpp index a79b1f0ef..69e1f50a0 100644 --- a/mailtransport/addtransportdialog.cpp +++ b/mailtransport/addtransportdialog.cpp @@ -1,144 +1,147 @@ /* Copyright (c) 2009 Constantin Berzan - Based on code from Kopete (addaccountwizard) - This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "addtransportdialog.h" #include "transport.h" #include "transportconfigwidget.h" #include "transportmanager.h" #include "transporttype.h" #include "ui_addtransportdialog.h" -#include -#include #include #include #include using namespace MailTransport; /** @internal */ class AddTransportDialog::Private { public: Private( AddTransportDialog *qq ) : q( qq ) { } + /** + Returns the currently selected type in the type selection widget, or + an invalid type if none is selected. + */ TransportType selectedType() const; - // slots - void typeListClicked(); + /** + Enables the OK button if a type is selected. + */ + void typeListClicked(); // slot AddTransportDialog *const q; Ui::AddTransportDialog ui; }; TransportType AddTransportDialog::Private::selectedType() const { QList sel = ui.typeListView->selectedItems(); if( !sel.empty() ) { return sel.first()->data( 0, Qt::UserRole ).value(); } return TransportType(); } void AddTransportDialog::Private::typeListClicked() { // Make sure a type is selected before allowing the user to continue. q->enableButtonOk( selectedType().isValid() ); } AddTransportDialog::AddTransportDialog( QWidget *parent ) : KDialog( parent ) , d( new Private( this ) ) { // Setup UI. { QWidget *widget = new QWidget( this ); d->ui.setupUi( widget ); setMainWidget( widget ); setCaption( i18n( "Create Outgoing Account" ) ); setButtons( Ok|Cancel ); enableButtonOk( false ); setButtonText( Ok, i18nc( "create and configure a mail transport", "Create and Configure" ) ); } // Populate type list. foreach( const TransportType &type, TransportManager::self()->types() ) { QTreeWidgetItem *treeItem = new QTreeWidgetItem( d->ui.typeListView ); treeItem->setText( 0, type.name() ); treeItem->setText( 1, type.description() ); treeItem->setData( 0, Qt::UserRole, QVariant::fromValue( type ) ); // the transport type } d->ui.typeListView->resizeColumnToContents( 0 ); updateGeometry(); d->ui.typeListView->setFocus(); // Connect user input. connect( d->ui.typeListView, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(typeListClicked()) ); connect( d->ui.typeListView, SIGNAL(itemSelectionChanged()), this, SLOT(typeListClicked()) ); } AddTransportDialog::~AddTransportDialog() { + delete d; } void AddTransportDialog::accept() { if( !d->selectedType().isValid() ) { return; } // Create a new transport and configure it. Transport *transport = TransportManager::self()->createTransport(); transport->setTransportType( d->selectedType() ); if( d->selectedType().type() == Transport::EnumType::Akonadi ) { // Create a resource instance if Akonadi-type transport. using namespace Akonadi; AgentInstanceCreateJob *cjob = new AgentInstanceCreateJob( d->selectedType().agentType() ); if( !cjob->exec() ) { kWarning() << "Failed to create agent instance of type" << d->selectedType().agentType().identifier(); return; } transport->setHost( cjob->instance().identifier() ); } transport->setName( d->ui.name->text() ); transport->forceUniqueName(); if( TransportManager::self()->configureTransport( transport, this ) ) { // The user clicked OK and the transport settings were saved. TransportManager::self()->addTransport( transport ); if( d->ui.setDefault->isChecked() ) { TransportManager::self()->setDefaultTransport( transport->id() ); } KDialog::accept(); } } #include "addtransportdialog.moc" diff --git a/mailtransport/addtransportdialog.h b/mailtransport/addtransportdialog.h index f21c87bf0..14f5cd07a 100644 --- a/mailtransport/addtransportdialog.h +++ b/mailtransport/addtransportdialog.h @@ -1,57 +1,67 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_ADDTRANSPORTDIALOG_H #define MAILTRANSPORT_ADDTRANSPORTDIALOG_H -#include - #include namespace MailTransport { /** + @internal + A dialog for creating a new transport. It asks the user for the transport type and name, and then proceeds to configure the new transport. + + To create a new transport from applications, use + TransportManager::showNewTransportDialog(). + + @author Constantin Berzan + @since 4.4 */ class AddTransportDialog : public KDialog { Q_OBJECT -public: - explicit AddTransportDialog( QWidget *parent = 0 ); - virtual ~AddTransportDialog(); + public: + /** + Creates a new AddTransportDialog. + */ + explicit AddTransportDialog( QWidget *parent = 0 ); - /* reimpl */ - virtual void accept(); + /** + Destroys the AddTransportDialog. + */ + virtual ~AddTransportDialog(); -private: - class Private; - Private *const d; + /* reimpl */ + virtual void accept(); - Q_PRIVATE_SLOT( d, void typeListClicked() ) - -}; + private: + class Private; + Private *const d; + Q_PRIVATE_SLOT( d, void typeListClicked() ) -} - +}; -#endif +} // namespace MailTransport +#endif // MAILTRANSPORT_ADDTRANSPORTDIALOG_H diff --git a/mailtransport/akonadijob.cpp b/mailtransport/akonadijob.cpp index d47721d09..b61d49650 100644 --- a/mailtransport/akonadijob.cpp +++ b/mailtransport/akonadijob.cpp @@ -1,110 +1,111 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "akonadijob.h" #include "transport.h" #include #include #include #include #include using namespace Akonadi; using namespace MailTransport; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class AkonadiJobPrivate { public: Item::Id itemId; QDBusInterface *iface; }; AkonadiJob::AkonadiJob( Transport *transport, QObject *parent ) : TransportJob( transport, parent ), d( new AkonadiJobPrivate ) { d->itemId = -1; d->iface = 0; } AkonadiJob::~ AkonadiJob() { delete d; } Akonadi::Item::Id AkonadiJob::itemId() const { return d->itemId; } void AkonadiJob::setItemId( Akonadi::Item::Id id ) { d->itemId = id; } void AkonadiJob::doStart() { if( !d->itemId < 0 ) { // TODO should this check be performed here or somewhere on a higher level? setError( UserDefinedError ); setErrorText( i18n( "Asked to send invalid item with id %1.", d->itemId ) ); emitResult(); return; } d->iface = new QDBusInterface( QLatin1String( "org.freedesktop.Akonadi.Resource." ) + transport()->host(), QLatin1String( "/" ), QLatin1String( "org.freedesktop.Akonadi.Resource.Transport" ), QDBusConnection::sessionBus(), this ); if( !d->iface->isValid() ) { setError( UserDefinedError ); setErrorText( i18n( "Failed to get D-Bus interface of resource %1.", transport()->host() ) ); emitResult(); return; } - connect( d->iface, SIGNAL( transportResult( bool, const QString & ) ), - this, SLOT( resourceResult( bool, const QString & ) ) ); + connect( d->iface, SIGNAL(transportResult(qlonglong,bool,QString)), + this, SLOT(resourceResult(qlonglong,bool,QString)) ); // What TODO about timeouts? It is quite possible that the result D-Bus signal // will get lost, and then what? QDBusReply reply = d->iface->call( QLatin1String( "send" ), d->itemId ); if( !reply.isValid() ) { setError( UserDefinedError ); setErrorText( i18n( "Invalid D-Bus reply from resource %1.", transport()->host() ) ); emitResult(); return; } } -void AkonadiJob::resourceResult( bool success, const QString &message ) +void AkonadiJob::resourceResult( qlonglong itemId, bool success, const QString &message ) { + Q_ASSERT( itemId == d->itemId ); if( !success ) { setError( UserDefinedError ); setErrorText( message ); } emitResult(); } #include "akonadijob.moc" diff --git a/mailtransport/akonadijob.h b/mailtransport/akonadijob.h index 9c29b9c0f..9751320a8 100644 --- a/mailtransport/akonadijob.h +++ b/mailtransport/akonadijob.h @@ -1,77 +1,84 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_AKONADIJOB_H #define MAILTRANSPORT_AKONADIJOB_H #include #include class AkonadiJobPrivate; namespace MailTransport { /** - Mail transport job for an Akonadi resource. - - TODO docu... apps need to call setItem if it's an Akonadi job... + Mail transport job for an Akonadi-based transport. + Unlike SmtpJob and SendmailJob, you also need to call setItemId() before + starting this job. In other words, the item you want to send has to be + created in advance. + + TODO API: + * Should we provide setItem or let the job assemble the item out of data()? + * What to do about from, to, cc, bcc? Should there be some kind of standard + attribute containing these? Currently data(), from(), to() etc. are + completely ignored. */ class MAILTRANSPORT_EXPORT AkonadiJob : public TransportJob { Q_OBJECT public: /** Creates an AkonadiJob. - @param transport The transport settings. + @param transport The transport object to use. @param parent The parent object. */ explicit AkonadiJob( Transport *transport, QObject *parent = 0 ); /** Destroys this job. */ virtual ~AkonadiJob(); - // TODO have these here or in TransportJob? They are useless in {SMTP,Sendmail}Job... /** The id of the item to send. */ Akonadi::Item::Id itemId() const; /** Set the id of the item to send. @param itemId id of the item to send */ void setItemId( Akonadi::Item::Id id ); protected: + /** reimpl */ virtual void doStart(); private Q_SLOTS: - void resourceResult( bool success, const QString &message ); + void resourceResult( qlonglong itemId, bool success, const QString &message ); private: AkonadiJobPrivate *const d; }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_AKONADIJOB_H diff --git a/mailtransport/configmodule.cpp b/mailtransport/configmodule.cpp index 0db3b9fac..b73fa98f3 100644 --- a/mailtransport/configmodule.cpp +++ b/mailtransport/configmodule.cpp @@ -1,40 +1,41 @@ /* Copyright (c) 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "configmodule.h" #include "transportmanagementwidget.h" -#include -#include -#include +#include + +#include +#include using namespace MailTransport; K_PLUGIN_FACTORY( MailTransportConfigFactory, registerPlugin(); ) K_EXPORT_PLUGIN( MailTransportConfigFactory( "mailtransport", "libmailtransport" ) ) ConfigModule::ConfigModule( QWidget * parent, const QVariantList & args ) : KCModule( MailTransportConfigFactory::componentData(), parent, args ) { setButtons( 0 ); QVBoxLayout *l = new QVBoxLayout( this ); l->setMargin( 0 ); TransportManagementWidget *tmw = new TransportManagementWidget( this ); l->addWidget( tmw ); } diff --git a/mailtransport/configmodule.h b/mailtransport/configmodule.h index 6994d37bd..8a678bbfc 100644 --- a/mailtransport/configmodule.h +++ b/mailtransport/configmodule.h @@ -1,39 +1,39 @@ /* Copyright (c) 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_CONFIGMODULE_H #define MAILTRANSPORT_CONFIGMODULE_H -#include +#include namespace MailTransport { /** KCModule for transport management. */ class ConfigModule : public KCModule { public: explicit ConfigModule( QWidget *parent = 0, const QVariantList &args = QVariantList() ); }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_CONFIGMODULE_H diff --git a/mailtransport/legacydecrypt.cpp b/mailtransport/legacydecrypt.cpp index 3cf6c8284..9da525774 100644 --- a/mailtransport/legacydecrypt.cpp +++ b/mailtransport/legacydecrypt.cpp @@ -1,47 +1,47 @@ /* Copyright (c) 2007 Volker Krause KNode code: Copyright (c) 1999-2005 the KNode authors. // krazy:exclude=copyright This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "legacydecrypt.h" -#include +#include using namespace MailTransport; QString Legacy::decryptKMail( const QString &data ) { return KStringHandler::obscure( data ); } QString Legacy::decryptKNode( const QString &data ) { uint i, val, len = data.length(); QString result; for ( i = 0; i < len; ++i ) { val = data[i].toLatin1(); val -= ' '; val = ( 255 - ' ' ) - val; result += QLatin1Char( (char)( val + ' ' ) ); } return result; } diff --git a/mailtransport/legacydecrypt.h b/mailtransport/legacydecrypt.h index 209a3e9c1..a7ded7296 100644 --- a/mailtransport/legacydecrypt.h +++ b/mailtransport/legacydecrypt.h @@ -1,49 +1,49 @@ /* Copyright (c) 2007 Volker Krause KNode code: Copyright (c) 1999-2005 the KNode authors. // krazy:exclude=copyright This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_LEGACYDECRYPT_H #define MAILTRANSPORT_LEGACYDECRYPT_H -#include +#include namespace MailTransport { /** Methods to read passwords from config files still using legacy encryption. */ class Legacy { public: /** Read data encrypted using KMail's legacy encryption. */ static QString decryptKMail( const QString &data ); /** Read data encrypted using KNode's legacy encryption. */ static QString decryptKNode( const QString &data ); }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_LEGACYDECRYPT_H diff --git a/mailtransport/mailtransport_defs.h b/mailtransport/mailtransport_defs.h index 3245e1ece..a4125bb5d 100644 --- a/mailtransport/mailtransport_defs.h +++ b/mailtransport/mailtransport_defs.h @@ -1,57 +1,57 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_MAILTRANSPORT_DEFS_H #define MAILTRANSPORT_MAILTRANSPORT_DEFS_H /** @file mailtransport_defs.h Internal file containing constant definitions etc. */ #define WALLET_FOLDER QLatin1String("mailtransports") #define KMAIL_WALLET_FOLDER QLatin1String("kmail") #define DBUS_SERVICE_NAME QLatin1String("org.kde.pim.TransportManager") #define DBUS_INTERFACE_NAME QLatin1String("org.kde.pim.TransportManager") #define DBUS_OBJECT_PATH QLatin1String("/TransportManager") #define DBUS_CHANGE_SIGNAL QLatin1String("changesCommitted") #define SMTP_PROTOCOL QLatin1String("smtp") #define SMTPS_PROTOCOL QLatin1String("smtps") #define SMTP_PORT 25 #define SMTPS_PORT 465 -/* Because ServerTest is also capable of testing IMAP, - * some addition defines. */ +// Because ServerTest is also capable of testing IMAP, +// some additional defines: #define IMAP_PROTOCOL QLatin1String("imap") #define IMAPS_PROTOCOL QLatin1String("imaps") #define POP_PROTOCOL QLatin1String("pop") #define POPS_PROTOCOL QLatin1String("pops") #define IMAP_PORT 143 #define IMAPS_PORT 993 #define POP_PORT 110 #define POPS_PORT 995 #endif diff --git a/mailtransport/precommandjob.cpp b/mailtransport/precommandjob.cpp index cef89c10d..9c75dfb54 100644 --- a/mailtransport/precommandjob.cpp +++ b/mailtransport/precommandjob.cpp @@ -1,100 +1,100 @@ /* Copyright (c) 2007 Volker Krause Based on KMail code by: Copyright (c) 1996-1998 Stefan Taferner Copyright (c) 2000-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "precommandjob.h" -#include -#include +#include +#include #include using namespace MailTransport; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class PreCommandJobPrivate { public: KProcess *process; QString precommand; }; PrecommandJob::PrecommandJob( const QString &precommand, QObject *parent ) : KJob( parent ), d( new PreCommandJobPrivate ) { d->precommand = precommand; d->process = new KProcess( this ); connect( d->process, SIGNAL(started()), SLOT(slotStarted()) ); connect( d->process, SIGNAL(error(QProcess::ProcessError error)), SLOT(slotError(QProcess::ProcessError error))); connect( d->process, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(slotFinished(int, QProcess::ExitStatus)) ); } PrecommandJob::~ PrecommandJob() { delete d; } void PrecommandJob::start() { d->process->setShellCommand( d->precommand ); d->process->start(); } void PrecommandJob::slotStarted() { emit infoMessage( this, i18n( "Executing precommand" ), i18n( "Executing precommand '%1'.", d->precommand ) ); } void PrecommandJob::slotError( QProcess::ProcessError error ) { setError( UserDefinedError ); setErrorText( i18n( "Could not execute precommand '%1'.", d->precommand ) ); kDebug() << "Execution precommand has failed:" << error; emitResult(); } bool PrecommandJob::doKill() { delete d->process; d->process = 0; return true; } void PrecommandJob::slotFinished( int exitCode, QProcess::ExitStatus exitStatus ) { if ( exitStatus == QProcess::CrashExit ) { setError( UserDefinedError ); setErrorText( i18n( "The precommand crashed." ) ); } else if ( exitCode != 0 ) { setError( UserDefinedError ); setErrorText( i18n( "The precommand exited with code %1.", d->process->exitStatus() ) ); } emitResult(); } #include "precommandjob.moc" diff --git a/mailtransport/precommandjob.h b/mailtransport/precommandjob.h index 440cb9ffc..2ed02d5e4 100644 --- a/mailtransport/precommandjob.h +++ b/mailtransport/precommandjob.h @@ -1,74 +1,74 @@ /* Copyright (c) 2007 Volker Krause Based on KMail code by: Copyright (c) 1996-1998 Stefan Taferner Copyright (c) 2000-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_PRECOMMANDJOB_H #define MAILTRANSPORT_PRECOMMANDJOB_H -#include +#include -#include +#include class PreCommandJobPrivate; namespace MailTransport { /** Job to execute commands before connecting to an account. */ class PrecommandJob : public KJob { Q_OBJECT public: /** Creates a new precommand job. @param precommand The command to run. @param parent The parent object. */ explicit PrecommandJob( const QString &precommand, QObject *parent = 0 ); /** Destroys this job. */ virtual ~PrecommandJob(); /** Executes the precommand. */ virtual void start(); protected: virtual bool doKill(); private slots: void slotFinished( int, QProcess::ExitStatus ); void slotStarted(); void slotError( QProcess::ProcessError error ); private: PreCommandJobPrivate *const d; }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_PRECOMMANDJOB_H diff --git a/mailtransport/sendmailconfigwidget.h b/mailtransport/sendmailconfigwidget.h index 8327aa8c5..62667515c 100644 --- a/mailtransport/sendmailconfigwidget.h +++ b/mailtransport/sendmailconfigwidget.h @@ -1,64 +1,64 @@ /* Copyright (c) 2009 Constantin Berzan Based on MailTransport code by: Copyright (c) 2006 - 2007 Volker Krause Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_SENDMAILCONFIGWIDGET_H #define MAILTRANSPORT_SENDMAILCONFIGWIDGET_H #include "transportconfigwidget.h" namespace MailTransport { class Transport; /** @internal */ class SendmailConfigWidgetPrivate; /** @internal Configuration widget for a Sendmail transport. */ class SendmailConfigWidget : public TransportConfigWidget { Q_OBJECT public: explicit SendmailConfigWidget( Transport *transport, QWidget *parent = 0 ); //virtual ~SendmailConfigWidget(); protected: SendmailConfigWidget( SendmailConfigWidgetPrivate &dd, Transport *transport, QWidget *parent ); private: Q_DECLARE_PRIVATE( SendmailConfigWidget ) void init(); }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_SENDMAILCONFIGWIDGET_H diff --git a/mailtransport/sendmailjob.cpp b/mailtransport/sendmailjob.cpp index d0551d416..5257bf821 100644 --- a/mailtransport/sendmailjob.cpp +++ b/mailtransport/sendmailjob.cpp @@ -1,110 +1,110 @@ /* Copyright (c) 2007 Volker Krause Copyright (c) 2007 KovoKs Based on KMail code by: Copyright (c) 1996-1998 Stefan Taferner This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sendmailjob.h" #include "transport.h" -#include +#include #include #include using namespace MailTransport; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class SendMailJobPrivate { public: QProcess *process; QString lastError; }; SendmailJob::SendmailJob( Transport *transport, QObject *parent ) : TransportJob( transport, parent ), d( new SendMailJobPrivate ) { d->process = new QProcess( this ); connect( d->process, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(sendmailExited(int, QProcess::ExitStatus)) ); connect( d->process, SIGNAL(error(QProcess::ProcessError)), SLOT(receivedError()) ); connect( d->process, SIGNAL(readyReadStandardError()), SLOT(receivedStdErr()) ); } SendmailJob::~ SendmailJob() { delete d; } void SendmailJob::doStart() { QStringList arguments; arguments << QLatin1String( "-i" ) << QLatin1String( "-f" ) << sender() << to() << cc() << bcc(); d->process->start( transport()->host(), arguments ); if ( !d->process->waitForStarted() ) { setError( UserDefinedError ); setErrorText( i18n( "Failed to execute mailer program %1", transport()->host() ) ); emitResult(); } else { d->process->write( buffer()->readAll() ); d->process->closeWriteChannel(); } } void SendmailJob::sendmailExited( int exitCode, QProcess::ExitStatus exitStatus ) { if ( exitStatus != 0 || exitCode != 0 ) { setError( UserDefinedError ); if ( d->lastError.isEmpty() ) { setErrorText( i18n( "Sendmail exited abnormally." ) ); } else { setErrorText( i18n( "Sendmail exited abnormally: %1", d->lastError ) ); } } emitResult(); } void SendmailJob::receivedError() { d->lastError += d->process->errorString(); } void SendmailJob::receivedStdErr() { d->lastError += QLatin1String( d->process->readAllStandardError() ); } bool SendmailJob::doKill() { delete d->process; d->process = 0; return true; } #include "sendmailjob.moc" diff --git a/mailtransport/sendmailjob.h b/mailtransport/sendmailjob.h index 261e681fe..7826403a9 100644 --- a/mailtransport/sendmailjob.h +++ b/mailtransport/sendmailjob.h @@ -1,68 +1,69 @@ /* Copyright (c) 2007 Volker Krause Copyright (c) 2007 KovoKs Based on KMail code by: Copyright (c) 1996-1998 Stefan Taferner This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_SENDMAILJOB_H #define MAILTRANSPORT_SENDMAILJOB_H #include #include + class SendMailJobPrivate; namespace MailTransport { /** Mail transport job for sendmail. */ class MAILTRANSPORT_EXPORT SendmailJob : public TransportJob { Q_OBJECT public: /** Creates a SendmailJob. @param transport The transport settings. @param parent The parent object. */ explicit SendmailJob( Transport *transport, QObject *parent = 0 ); /** Destroys this job. */ virtual ~SendmailJob(); protected: virtual void doStart(); virtual bool doKill(); private Q_SLOTS: void sendmailExited( int, QProcess::ExitStatus ); void receivedError(); void receivedStdErr(); private: SendMailJobPrivate *const d; }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_SENDMAILJOB_H diff --git a/mailtransport/servertest.cpp b/mailtransport/servertest.cpp index 9ee3e9be8..6361ec2c5 100644 --- a/mailtransport/servertest.cpp +++ b/mailtransport/servertest.cpp @@ -1,599 +1,599 @@ /* Copyright (c) 2006 - 2007 Volker Krause Copyright (C) 2007 KovoKs Copyright (c) 2008 Thomas McGuire This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // Own #include "servertest.h" #include "socket.h" #include #include // Qt #include #include #include // KDE -#include -#include +#include +#include using namespace MailTransport; namespace MailTransport { class ServerTestPrivate { public: ServerTestPrivate( ServerTest *test ); ServerTest *const q; QString server; QString fakeHostname; QString testProtocol; MailTransport::Socket *normalSocket; MailTransport::Socket *secureSocket; QSet< int > connectionResults; QHash< int, QList > authenticationResults; QSet< ServerTest::Capability > capabilityResults; QHash< int, uint > customPorts; QTimer *normalSocketTimer; QTimer *secureSocketTimer; QTimer *progressTimer; QProgressBar *testProgress; bool secureSocketFinished; bool normalSocketFinished; bool tlsFinished; bool popSupportsTLS; int normalStage; int secureStage; int encryptionMode; void finalResult(); void handleSMTPIMAPResponse( int type, const QString &text ); void sendInitialCapabilityQuery( MailTransport::Socket *socket ); bool handlePopConversation( MailTransport::Socket *socket, int type, int stage, const QString &response, bool *shouldStartTLS ); QList< int > parseAuthenticationList( const QStringList &authentications ); // slots void slotNormalPossible(); void slotNormalNotPossible(); void slotSslPossible(); void slotSslNotPossible(); void slotTlsDone(); void slotReadNormal( const QString &text ); void slotReadSecure( const QString &text ); void slotUpdateProgress(); }; } ServerTestPrivate::ServerTestPrivate( ServerTest *test ) : q( test ), testProgress( 0 ), secureSocketFinished( false ), normalSocketFinished( false ), tlsFinished( false ) { } void ServerTestPrivate::finalResult() { if ( !secureSocketFinished || !normalSocketFinished || !tlsFinished ) { return; } kDebug() << "Modes:" << connectionResults; kDebug() << "Capabilities:" << capabilityResults; kDebug() << "Normal:" << q->normalProtocols(); kDebug() << "SSL:" << q->secureProtocols(); kDebug() << "TLS:" << q->tlsProtocols(); if ( testProgress ) { testProgress->hide(); } progressTimer->stop(); secureSocketFinished = false; normalSocketFinished = false; tlsFinished = false ; emit q->finished( connectionResults.toList() ); } QList< int > ServerTestPrivate::parseAuthenticationList( const QStringList &authentications ) { QList< int > result; for ( QStringList::ConstIterator it = authentications.begin(); it != authentications.end(); ++it ) { QString current = (*it).toUpper(); if ( current == QLatin1String( "LOGIN" ) ) { result << Transport::EnumAuthenticationType::LOGIN; } else if ( current == QLatin1String( "PLAIN" ) ) { result << Transport::EnumAuthenticationType::PLAIN; } else if ( current == QLatin1String( "CRAM-MD5" ) ) { result << Transport::EnumAuthenticationType::CRAM_MD5; } else if ( current == QLatin1String( "DIGEST-MD5" ) ) { result << Transport::EnumAuthenticationType::DIGEST_MD5; } else if ( current == QLatin1String( "NTLM" ) ) { result << Transport::EnumAuthenticationType::NTLM; } else if ( current == QLatin1String( "GSSAPI" ) ) { result << Transport::EnumAuthenticationType::GSSAPI; } else if ( current == QLatin1String( "ANONYMOUS" ) ) { result << Transport::EnumAuthenticationType::ANONYMOUS; } // APOP is handled by handlePopConversation() } kDebug() << authentications << result; // LOGIN doesn't offer anything over PLAIN, requires more server // roundtrips and is not an official SASL mechanism, but a MS-ism, // so only enable it if PLAIN isn't available: if ( result.contains( Transport::EnumAuthenticationType::PLAIN ) ) { result.removeAll( Transport::EnumAuthenticationType::LOGIN ); } return result; } void ServerTestPrivate::handleSMTPIMAPResponse( int type, const QString &text ) { if ( !text.contains( QLatin1String( "AUTH" ), Qt::CaseInsensitive ) ) { kDebug() << "No authentication possible"; return; } QStringList protocols; protocols << QLatin1String( "LOGIN" ) << QLatin1String( "PLAIN" ) << QLatin1String( "CRAM-MD5" ) << QLatin1String( "DIGEST-MD5" ) << QLatin1String( "NTLM" ) << QLatin1String( "GSSAPI" ) << QLatin1String( "ANONYMOUS" ); QStringList results; for ( int i = 0; i < protocols.count(); ++i ) { if ( text.contains( protocols.at( i ), Qt::CaseInsensitive ) ) { results.append( protocols.at( i ) ); } } authenticationResults[type] = parseAuthenticationList( results ); kDebug() << "For type" << type << ", we have:" << authenticationResults[type]; } void ServerTestPrivate::slotNormalPossible() { normalSocketTimer->stop(); connectionResults << Transport::EnumEncryption::None; } void ServerTestPrivate::sendInitialCapabilityQuery( MailTransport::Socket *socket ) { kDebug(); if ( testProtocol == IMAP_PROTOCOL ) { socket->write( QLatin1String( "1 CAPABILITY" ) ); } else if ( testProtocol == SMTP_PROTOCOL ) { // Detect the hostname which we send with the EHLO command. // If there is a fake one set, use that, otherwise use the // local host name (and make sure it contains a domain, so the // server thinks it is valid). QString hostname; if ( !fakeHostname.isNull() ) { hostname = fakeHostname; } else { hostname = QHostInfo::localHostName(); if( hostname.isEmpty() ) { hostname = QLatin1String( "localhost.invalid" ); } else if ( !hostname.contains( QChar::fromAscii( '.' ) ) ) { hostname += QLatin1String( ".localnet" ); } } kDebug() << "Hostname for EHLO is" << hostname; socket->write( QLatin1String( "EHLO " ) + hostname ); } } void ServerTestPrivate::slotTlsDone() { kDebug(); // The server will not send a response after starting TLS. Therefore, we have to manually // call slotReadNormal(), because this is not triggered by a data received signal this time. slotReadNormal( QString() ); } bool ServerTestPrivate::handlePopConversation( MailTransport::Socket *socket, int type, int stage, const QString &response, bool *shouldStartTLS ) { Q_ASSERT( shouldStartTLS != 0 ); // Initial Greeting if ( stage == 0 ) { //Regexp taken from POP3 ioslave QString responseWithoutCRLF = response; responseWithoutCRLF.chop( 2 ); QRegExp re( QLatin1String( "<[A-Za-z0-9\\.\\-_]+@[A-Za-z0-9\\.\\-_]+>$" ), Qt::CaseInsensitive ); if ( responseWithoutCRLF.indexOf( re ) != -1 ) { authenticationResults[type] << Transport::EnumAuthenticationType::APOP; } //Each server is supposed to support clear text login authenticationResults[type] << Transport::EnumAuthenticationType::CLEAR; // If we are in TLS stage, the server does not send the initial greeting. // Assume that the APOP availability is the same as with an unsecured connection. if ( type == Transport::EnumEncryption::TLS && authenticationResults[Transport::EnumEncryption::None]. contains( Transport::EnumAuthenticationType::APOP ) ) { authenticationResults[Transport::EnumEncryption::TLS] << Transport::EnumAuthenticationType::APOP; } socket->write( QLatin1String( "CAPA" ) ); return true; } // CAPA result else if( stage == 1 ) { // Example: // CAPA // +OK // TOP // USER // SASL LOGIN CRAM-MD5 // UIDL // RESP-CODES // . if ( response.contains( QLatin1String( "TOP" ) ) ) { capabilityResults += ServerTest::Top; } if ( response.contains( QLatin1String( "PIPELINING" ) ) ) { capabilityResults += ServerTest::Pipelining; } if ( response.contains( QLatin1String( "UIDL" ) ) ) { capabilityResults += ServerTest::UIDL; } if ( response.contains( QLatin1String( "STLS" ) ) ) { connectionResults << Transport::EnumEncryption::TLS; popSupportsTLS = true; } socket->write( QLatin1String( "AUTH" ) ); return true; } // AUTH response else if( stage == 2 ) { // Example: // C: AUTH // S: +OK List of supported authentication methods follows // S: LOGIN // S: CRAM-MD5 // S:. QString formattedReply = response; // Get rid of trailling ".CRLF" formattedReply.chop( 3 ); // Get rid of the first +OK line formattedReply = formattedReply.right( formattedReply.size() - formattedReply.indexOf( QLatin1Char( '\n' ) ) - 1 ); formattedReply = formattedReply.replace( QLatin1Char( ' ' ), QLatin1Char( '-' ) ). replace( QLatin1String( "\r\n" ), QLatin1String( " " ) ); authenticationResults[type] += parseAuthenticationList( formattedReply.split( QLatin1Char( ' ' ) ) ); } *shouldStartTLS = popSupportsTLS; return false; } // slotReadNormal() handles normal (no) encryption and TLS encryption. // At first, the communication is not encrypted, but if the server supports // the STARTTLS/STLS keyword, the same authentication query is done again // with TLS. void ServerTestPrivate::slotReadNormal( const QString &text ) { Q_ASSERT( encryptionMode != Transport::EnumEncryption::SSL ); static const int tlsHandshakeStage = 42; kDebug() << "Stage" << normalStage + 1 << ", Mode" << encryptionMode; // If we are in stage 42, we just do the handshake for TLS encryption and // then reset the stage to -1, so that all authentication modes and // capabilities are queried again for TLS encryption (some servers have // different authentication methods in normal and in TLS mode). if ( normalStage == tlsHandshakeStage ) { Q_ASSERT( encryptionMode == Transport::EnumEncryption::TLS ); normalStage = -1; normalSocket->startTLS(); return; } bool shouldStartTLS = false; normalStage++; // Handle the whole POP converstation separatly, it is very different from // IMAP and SMTP if ( testProtocol == POP_PROTOCOL ) { if ( handlePopConversation( normalSocket, encryptionMode, normalStage, text, &shouldStartTLS ) ) { return; } } else { // Handle the SMTP/IMAP conversation here. We just send the EHLO command in // sendInitialCapabilityQuery. if ( normalStage == 0 ) { sendInitialCapabilityQuery( normalSocket ); return; } if ( text.contains( QLatin1String( "STARTTLS" ), Qt::CaseInsensitive ) ) { connectionResults << Transport::EnumEncryption::TLS; shouldStartTLS = true; } handleSMTPIMAPResponse( encryptionMode, text ); } // If we reach here, the normal authentication/capabilities query is completed. // Now do the same for TLS. normalSocketFinished = true; // If the server announced that STARTTLS/STLS is available, we'll add TLS to the // connection result, do the command and set the stage to 42 to start the handshake. if ( shouldStartTLS && encryptionMode == Transport::EnumEncryption::None ) { kDebug() << "Trying TLS..."; connectionResults << Transport::EnumEncryption::TLS; if ( testProtocol == POP_PROTOCOL ) { normalSocket->write( QLatin1String( "STLS" ) ); } else if ( testProtocol == IMAP_PROTOCOL ) { normalSocket->write( QLatin1String( "2 STARTTLS" ) ); } else { normalSocket->write( QLatin1String( "STARTTLS" ) ); } encryptionMode = Transport::EnumEncryption::TLS; normalStage = tlsHandshakeStage; return; } // If we reach here, either the TLS authentication/capabilities query is finished // or the server does not support the STARTTLS/STLS command. tlsFinished = true; finalResult(); } void ServerTestPrivate::slotReadSecure( const QString &text ) { secureStage++; if ( testProtocol == POP_PROTOCOL ) { bool dummy; if ( handlePopConversation( secureSocket, Transport::EnumEncryption::SSL, secureStage, text, &dummy ) ) { return; } } else { if ( secureStage == 0 ) { sendInitialCapabilityQuery( secureSocket ); return; } handleSMTPIMAPResponse( Transport::EnumEncryption::SSL, text ); } secureSocketFinished = true; finalResult(); } void ServerTestPrivate::slotNormalNotPossible() { normalSocketFinished = true; tlsFinished = true; finalResult(); } void ServerTestPrivate::slotSslPossible() { secureSocketTimer->stop(); connectionResults << Transport::EnumEncryption::SSL; } void ServerTestPrivate::slotSslNotPossible() { secureSocketFinished = true; finalResult(); } void ServerTestPrivate::slotUpdateProgress() { if ( testProgress ) { testProgress->setValue( testProgress->value() + 1 ); } } //---------------------- end private class -----------------------// ServerTest::ServerTest( QWidget *parent ) : QWidget( parent ), d( new ServerTestPrivate( this ) ) { d->normalSocketTimer = new QTimer( this ); d->normalSocketTimer->setSingleShot( true ); connect( d->normalSocketTimer, SIGNAL( timeout() ), SLOT( slotNormalNotPossible() ) ); d->secureSocketTimer = new QTimer( this ); d->secureSocketTimer->setSingleShot( true ); connect( d->secureSocketTimer, SIGNAL( timeout() ), SLOT( slotSslNotPossible() ) ); d->progressTimer = new QTimer( this ); connect( d->progressTimer, SIGNAL( timeout() ), SLOT( slotUpdateProgress() ) ); } ServerTest::~ServerTest() { delete d; } void ServerTest::start() { kDebug() << d; d->connectionResults.clear(); d->authenticationResults.clear(); d->capabilityResults.clear(); d->popSupportsTLS = false; d->normalStage = -1; d->secureStage = -1; d->encryptionMode = Transport::EnumEncryption::None; if ( d->testProgress ) { d->testProgress->setMaximum( 20 ); d->testProgress->setValue( 0 ); d->testProgress->setTextVisible( true ); d->testProgress->show(); d->progressTimer->start( 1000 ); } d->normalSocket = new MailTransport::Socket( this ); d->secureSocket = new MailTransport::Socket( this ); d->normalSocket->setObjectName( QLatin1String( "normal" ) ); d->normalSocket->setServer( d->server ); d->normalSocket->setProtocol( d->testProtocol ); if ( d->testProtocol == IMAP_PROTOCOL ) { d->normalSocket->setPort( IMAP_PORT ); d->secureSocket->setPort( IMAPS_PORT ); } else if ( d->testProtocol == SMTP_PROTOCOL ) { d->normalSocket->setPort( SMTP_PORT ); d->secureSocket->setPort( SMTPS_PORT ); } else if ( d->testProtocol == POP_PROTOCOL ) { d->normalSocket->setPort( POP_PORT ); d->secureSocket->setPort( POPS_PORT ); } if ( d->customPorts.contains( Transport::EnumEncryption::None ) ) { d->normalSocket->setPort( d->customPorts.value( Transport::EnumEncryption::None ) ); } if ( d->customPorts.contains( Transport::EnumEncryption::SSL ) ) { d->secureSocket->setPort( d->customPorts.value( Transport::EnumEncryption::SSL ) ); } connect( d->normalSocket, SIGNAL(connected()), SLOT(slotNormalPossible()) ); connect( d->normalSocket, SIGNAL(failed()), SLOT(slotNormalNotPossible()) ); connect( d->normalSocket, SIGNAL(data(const QString&)), SLOT(slotReadNormal(const QString&)) ); connect( d->normalSocket, SIGNAL(tlsDone()), SLOT(slotTlsDone())); d->normalSocket->reconnect(); d->normalSocketTimer->start( 10000 ); d->secureSocket->setObjectName( QLatin1String( "secure" ) ); d->secureSocket->setServer( d->server ); d->secureSocket->setProtocol( d->testProtocol + QLatin1Char( 's' ) ); d->secureSocket->setSecure( true ); connect( d->secureSocket, SIGNAL(connected()), SLOT(slotSslPossible()) ); connect( d->secureSocket, SIGNAL(failed()), SLOT(slotSslNotPossible()) ); connect( d->secureSocket, SIGNAL(data(const QString&) ), SLOT(slotReadSecure(const QString&)) ); d->secureSocket->reconnect(); d->secureSocketTimer->start( 10000 ); } void ServerTest::setFakeHostname( const QString &fakeHostname ) { d->fakeHostname = fakeHostname; } QString ServerTest::fakeHostname() { return d->fakeHostname; } void ServerTest::setServer( const QString &server ) { d->server = server; } void ServerTest::setPort( Transport::EnumEncryption::type encryptionMode, uint port ) { Q_ASSERT( encryptionMode == Transport::EnumEncryption::None || encryptionMode == Transport::EnumEncryption::SSL ); d->customPorts.insert( encryptionMode, port ); } void ServerTest::setProgressBar( QProgressBar *pb ) { d->testProgress = pb; } void ServerTest::setProtocol( const QString &protocol ) { d->testProtocol = protocol; } QString ServerTest::protocol() { return d->testProtocol; } QString ServerTest::server() { return d->server; } int ServerTest::port( Transport::EnumEncryption::type encryptionMode ) { Q_ASSERT( encryptionMode == Transport::EnumEncryption::None || encryptionMode == Transport::EnumEncryption::SSL ); if ( d->customPorts.contains( encryptionMode ) ) { return d->customPorts.value( static_cast( encryptionMode ) ); } else { return -1; } } QProgressBar *ServerTest::progressBar() { return d->testProgress; } QList< int > ServerTest::normalProtocols() { return d->authenticationResults[TransportBase::EnumEncryption::None]; } QList< int > ServerTest::tlsProtocols() { return d->authenticationResults[TransportBase::EnumEncryption::TLS]; } QList< int > ServerTest::secureProtocols() { return d->authenticationResults[Transport::EnumEncryption::SSL]; } QList< ServerTest::Capability > ServerTest::capabilities() const { return d->capabilityResults.toList(); } #include "servertest.moc" diff --git a/mailtransport/servertest.h b/mailtransport/servertest.h index 99ef116ec..664d8660b 100644 --- a/mailtransport/servertest.h +++ b/mailtransport/servertest.h @@ -1,214 +1,214 @@ /* Copyright (C) 2007 KovoKs Copyright (c) 2008 Thomas McGuire This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_SERVERTEST_H #define MAILTRANSPORT_SERVERTEST_H #include #include #include #include class QProgressBar; namespace MailTransport { class ServerTestPrivate; /** * @class ServerTest * This class can be used to test certain server to see if they support stuff. * @author Tom Albers */ class MAILTRANSPORT_EXPORT ServerTest : public QWidget { Q_OBJECT Q_PROPERTY( QString server READ server WRITE setServer ) Q_PROPERTY( QString protocol READ protocol WRITE setProtocol ) Q_PROPERTY( QProgressBar *progressBar READ progressBar WRITE setProgressBar ) public: /** * This enumeration has the special capabilities a server might * support. This covers only capabilities not related to authentication. * @since 4.1 */ enum Capability { Pipelining, ///< POP3 only. The server supports pipeplining of commands Top, ///< POP3 only. The server supports fetching only the headers UIDL ///< POP3 only. The server has support for unique identifiers }; /** * Constructor * @param parent Parent Widget */ ServerTest( QWidget *parent = 0 ); /** * Destructor */ ~ServerTest(); /** * Set the server to test. */ void setServer( const QString &server ); /** * Get the server to test. */ QString server(); /** * Set a custom port to use. * * Each encryption mode (no encryption or SSL) has a different port. * TLS uses the same port as no encryption, because TLS is invoked during * a normal session. * * If this function is never called, the default port is used, which is: * (normal first, then SSL) * SMTP: 25, 465 * POP: 110, 995 * IMAP: 143, 993 * * @param encryptionMode the port will only be used in this encryption mode. * Valid values for this are only 'None' and 'SSL'. * @param port the port to use * * @since 4.1 */ void setPort( Transport::EnumEncryption::type encryptionMode, uint port ); /** * @param encryptionMode the port of this encryption mode is returned. * Can only be 'None' and 'SSL' * * @return the port set by @ref setPort or -1 if @ref setPort() was never * called for this encryption mode. * * @since 4.1 */ int port( Transport::EnumEncryption::type encryptionMode ); /** * Sets a fake hostname for the test. This is currently only used when * testing a SMTP server; there, the command for testing the capabilities * (called EHLO) needs to have the hostname of the client included. * The user can however choose to send a fake hostname instead of the * local hostname to work around various problems. This fake hostname needs * to be set here. * * @param fakeHostname the fake hostname to send */ void setFakeHostname( const QString &fakeHostname ); /** * @return the fake hostname, as set before with @ref setFakeHostname */ QString fakeHostname(); /** * Makes @p pb the progressbar to use. This class will call show() * and hide() and will count down. It does not take ownership of * the progressbar. */ void setProgressBar( QProgressBar *pb ); /** * returns the used progressBar */ QProgressBar *progressBar(); /** * Set @p protocol the protocol to test, currently supported are * "smtp", "pop" and "imap". */ void setProtocol( const QString &protocol ); /** * returns the protocol */ QString protocol(); /** * Starts the test. Will emit finished() when done. */ void start(); /** * Get the protocols for the normal connections.. Call this only * after the finished() signals has been sent. * @return an enum of the type Transport::EnumAuthenticationType */ QList< int > normalProtocols(); /** * Get the protocols for the TLS connections. Call this only * after the finished() signals has been sent. * @return an enum of the type Transport::EnumAuthenticationType * @since 4.1 */ QList< int > tlsProtocols(); /** * Get the protocols for the SSL connections. Call this only * after the finished() signals has been sent. * @return an enum of the type Transport::EnumAuthenticationType */ QList< int > secureProtocols(); /** * Get the special capabilities of the server. * Call this only after the finished() signals has been sent. * * @return the list of special capabilities of the server. * @since 4.1 */ QList< Capability > capabilities() const; Q_SIGNALS: /** * This will be emitted when the test is done. It will contain * the values from the enum EnumEncryption which are possible. */ void finished( QList< int > ); private: Q_DECLARE_PRIVATE( ServerTest ) ServerTestPrivate *const d; Q_PRIVATE_SLOT( d, void slotNormalPossible() ) Q_PRIVATE_SLOT( d, void slotTlsDone() ) Q_PRIVATE_SLOT( d, void slotSslPossible() ) Q_PRIVATE_SLOT( d, void slotReadNormal( const QString &text ) ) Q_PRIVATE_SLOT( d, void slotReadSecure( const QString &text ) ) Q_PRIVATE_SLOT( d, void slotNormalNotPossible() ) Q_PRIVATE_SLOT( d, void slotSslNotPossible() ) Q_PRIVATE_SLOT( d, void slotUpdateProgress() ) }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_SERVERTEST_H diff --git a/mailtransport/smtpconfigwidget.h b/mailtransport/smtpconfigwidget.h index 4bce4d51b..2d0f0cc13 100644 --- a/mailtransport/smtpconfigwidget.h +++ b/mailtransport/smtpconfigwidget.h @@ -1,77 +1,77 @@ /* Copyright (c) 2009 Constantin Berzan Based on MailTransport code by: Copyright (c) 2006 - 2007 Volker Krause Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_SMTPCONFIGWIDGET_H #define MAILTRANSPORT_SMTPCONFIGWIDGET_H #include "transportconfigwidget.h" namespace MailTransport { class Transport; /** @internal */ class SMTPConfigWidgetPrivate; /** @internal Configuration widget for a SMTP transport. */ class SMTPConfigWidget : public TransportConfigWidget { Q_OBJECT public: explicit SMTPConfigWidget( Transport *transport, QWidget *parent = 0 ); //virtual ~SMTPConfigWidget(); public Q_SLOTS: /** reimpl */ virtual void apply(); protected: // TODO probably not needed since no one will inherit from us SMTPConfigWidget( SMTPConfigWidgetPrivate &dd, Transport *transport, QWidget *parent ); private Q_SLOTS: void checkSmtpCapabilities(); void passwordsLoaded(); void slotFinished( QList results ); void hostNameChanged( const QString &text ); void encryptionChanged( int enc ); void ensureValidAuthSelection(); private: Q_DECLARE_PRIVATE( SMTPConfigWidget ) void init(); }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_SMTPCONFIGWIDGET_H diff --git a/mailtransport/smtpjob.cpp b/mailtransport/smtpjob.cpp index 8c8204be8..b5f979edb 100644 --- a/mailtransport/smtpjob.cpp +++ b/mailtransport/smtpjob.cpp @@ -1,333 +1,333 @@ /* Copyright (c) 2007 Volker Krause Based on KMail code by: Copyright (c) 1996-1998 Stefan Taferner This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "smtpjob.h" #include "transport.h" #include "mailtransport_defs.h" #include "precommandjob.h" -#include -#include -#include -#include -#include - #include #include +#include +#include +#include +#include +#include + using namespace MailTransport; class SlavePool { public: SlavePool() : ref( 0 ) {} int ref; QHash slaves; void removeSlave( KIO::Slave *slave, bool disconnect = false ) { kDebug() << "Removing slave" << slave << "from pool"; const int slaveKey = slaves.key( slave ); if ( slaveKey > 0 ) { slaves.remove( slaveKey ); if ( disconnect ) { KIO::Scheduler::disconnectSlave( slave ); } } } }; K_GLOBAL_STATIC( SlavePool, s_slavePool ) /** * Private class that helps to provide binary compatibility between releases. * @internal */ class SmtpJobPrivate { public: KIO::Slave *slave; enum State { Idle, Precommand, Smtp } currentState; bool finished; }; SmtpJob::SmtpJob( Transport *transport, QObject *parent ) : TransportJob( transport, parent ), d( new SmtpJobPrivate ) { d->currentState = SmtpJobPrivate::Idle; d->slave = 0; d->finished = false; if ( !s_slavePool.isDestroyed() ) { s_slavePool->ref++; } KIO::Scheduler::connect( SIGNAL(slaveError(KIO::Slave*,int,QString)), this, SLOT(slaveError(KIO::Slave*,int,QString)) ); } SmtpJob::~SmtpJob() { if ( !s_slavePool.isDestroyed() ) { s_slavePool->ref--; if ( s_slavePool->ref == 0 ) { kDebug() << "clearing SMTP slave pool" << s_slavePool->slaves.count(); foreach ( KIO::Slave *slave, s_slavePool->slaves ) { if ( slave ) { KIO::Scheduler::disconnectSlave( slave ); } } s_slavePool->slaves.clear(); } } delete d; } void SmtpJob::doStart() { if ( s_slavePool.isDestroyed() ) { return; } if ( s_slavePool->slaves.contains( transport()->id() ) || transport()->precommand().isEmpty() ) { d->currentState = SmtpJobPrivate::Smtp; startSmtpJob(); } else { d->currentState = SmtpJobPrivate::Precommand; PrecommandJob *job = new PrecommandJob( transport()->precommand(), this ); addSubjob( job ); job->start(); } } void SmtpJob::startSmtpJob() { if ( s_slavePool.isDestroyed() ) { return; } KUrl destination; destination.setProtocol( ( transport()->encryption() == Transport::EnumEncryption::SSL ) ? SMTPS_PROTOCOL : SMTP_PROTOCOL ); destination.setHost( transport()->host().trimmed() ); destination.setPort( transport()->port() ); destination.addQueryItem( QLatin1String( "headers" ), QLatin1String( "0" ) ); destination.addQueryItem( QLatin1String( "from" ), sender() ); foreach ( const QString &str, to() ) { destination.addQueryItem( QLatin1String( "to" ), str ); } foreach ( const QString &str, cc() ) { destination.addQueryItem( QLatin1String( "cc" ), str ); } foreach ( const QString &str, bcc() ) { destination.addQueryItem( QLatin1String( "bcc" ), str ); } if ( transport()->specifyHostname() ) { destination.addQueryItem( QLatin1String( "hostname" ), transport()->localHostname() ); } #ifdef __GNUC__ #warning Argh! #endif // if ( !kmkernel->msgSender()->sendQuotedPrintable() ) // query += "&body=8bit"; if ( transport()->requiresAuthentication() ) { if( ( transport()->userName().isEmpty() || transport()->password().isEmpty() ) && transport()->authenticationType() != Transport::EnumAuthenticationType::GSSAPI ) { QString user = transport()->userName(); QString passwd = transport()->password(); int result; #ifdef __GNUC__ #warning yet another KMail specific thing #endif // KCursorSaver idle( KBusyPtr::idle() ); bool keep = transport()->storePassword(); result = KIO::PasswordDialog::getNameAndPassword( user, passwd, &keep, i18n( "You need to supply a username and a password to use this SMTP server." ), false, QString(), transport()->name(), QString() ); if ( result != QDialog::Accepted ) { setError( KilledJobError ); emitResult(); return; } transport()->setUserName( user ); transport()->setPassword( passwd ); transport()->setStorePassword( keep ); transport()->writeConfig(); } destination.setUser( transport()->userName() ); destination.setPass( transport()->password() ); } // dotstuffing is now done by the slave (see setting of metadata) if ( !data().isEmpty() ) { // allow +5% for subsequent LF->CRLF and dotstuffing (an average // over 2G-lines gives an average line length of 42-43): destination.addQueryItem( QLatin1String( "size" ), QString::number( qRound( data().length() * 1.05 ) ) ); } destination.setPath( QLatin1String( "/send" ) ); d->slave = s_slavePool->slaves.value( transport()->id() ); if ( !d->slave ) { KIO::MetaData slaveConfig; slaveConfig.insert( QLatin1String( "tls" ), ( transport()->encryption() == Transport::EnumEncryption::TLS ) ? QLatin1String( "on" ) : QLatin1String( "off" ) ); if ( transport()->requiresAuthentication() ) { slaveConfig.insert( QLatin1String( "sasl" ), transport()->authenticationTypeString() ); } d->slave = KIO::Scheduler::getConnectedSlave( destination, slaveConfig ); kDebug() << "Created new SMTP slave" << d->slave; s_slavePool->slaves.insert( transport()->id(), d->slave ); } else { kDebug() << "Re-using existing slave" << d->slave; } KIO::TransferJob *job = KIO::put( destination, -1, KIO::HideProgressInfo ); if ( !d->slave || !job ) { setError( UserDefinedError ); setErrorText( i18n( "Unable to create SMTP job." ) ); emitResult(); return; } job->addMetaData( QLatin1String( "lf2crlf+dotstuff" ), QLatin1String( "slave" ) ); connect( job, SIGNAL(dataReq(KIO::Job*,QByteArray&)), SLOT(dataRequest(KIO::Job*,QByteArray&)) ); addSubjob( job ); KIO::Scheduler::assignJobToSlave( d->slave, job ); setTotalAmount( KJob::Bytes, data().length() ); } bool SmtpJob::doKill() { if ( s_slavePool.isDestroyed() ) { return false; } if ( !hasSubjobs() ) { return true; } if ( d->currentState == SmtpJobPrivate::Precommand ) { return subjobs().first()->kill(); } else if ( d->currentState == SmtpJobPrivate::Smtp ) { KIO::SimpleJob *job = static_cast( subjobs().first() ); clearSubjobs(); KIO::Scheduler::cancelJob( job ); s_slavePool->removeSlave( d->slave ); return true; } return false; } void SmtpJob::slotResult( KJob *job ) { if ( s_slavePool.isDestroyed() ) { return; } // The job has finished, so we don't care about any further errors. Set // d->finished to true, so slaveError() knows about this and doesn't call // emitResult() anymore. // Sometimes, the SMTP slave emits more than one error // // The first error causes slotResult() to be called, but not slaveError(), since // the scheduler doesn't emit errors for connected slaves. // // The second error then causes slaveError() to be called (as the slave is no // longer connected), which does emitResult() a second time, which is invalid // (and triggers an assert in KMail). d->finished = true; // Normally, calling TransportJob::slotResult() whould set the proper error code // for error() via KComposite::slotResult(). However, we can't call that here, // since that also emits the result signal. // In KMail, when there are multiple mails in the outbox, KMail tries to send // the next mail when it gets the result signal, which then would reuse the // old broken slave from the slave pool if there was an error. // To prevent that, we call TransportJob::slotResult() only after removing the // slave from the pool and calculate the error code ourselves. int errorCode = error(); if ( !errorCode ) { errorCode = job->error(); } if ( errorCode && d->currentState == SmtpJobPrivate::Smtp ) { s_slavePool->removeSlave( d->slave, errorCode != KIO::ERR_SLAVE_DIED ); TransportJob::slotResult( job ); return; } TransportJob::slotResult( job ); if ( !error() && d->currentState == SmtpJobPrivate::Precommand ) { d->currentState = SmtpJobPrivate::Smtp; startSmtpJob(); return; } if ( !error() ) { emitResult(); } } void SmtpJob::dataRequest( KIO::Job *job, QByteArray &data ) { if ( s_slavePool.isDestroyed() ) { return; } Q_ASSERT( job ); if ( buffer()->atEnd() ) { data.clear(); } else { Q_ASSERT( buffer()->isOpen() ); data = buffer()->read( 32 * 1024 ); } setProcessedAmount( KJob::Bytes, buffer()->pos() ); } void SmtpJob::slaveError( KIO::Slave *slave, int errorCode, const QString &errorMsg ) { if ( s_slavePool.isDestroyed() ) { return; } s_slavePool->removeSlave( slave, errorCode != KIO::ERR_SLAVE_DIED ); if ( d->slave == slave && !d->finished ) { setError( errorCode ); setErrorText( KIO::buildErrorString( errorCode, errorMsg ) ); emitResult(); } } #include "smtpjob.moc" diff --git a/mailtransport/smtpjob.h b/mailtransport/smtpjob.h index c2b3e758d..0bd9e369f 100644 --- a/mailtransport/smtpjob.h +++ b/mailtransport/smtpjob.h @@ -1,83 +1,83 @@ /* Copyright (c) 2007 Volker Krause Based on KMail code by: Copyright (c) 1996-1998 Stefan Taferner This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_SMTPJOB_H #define MAILTRANSPORT_SMTPJOB_H #include namespace KIO { -class Job; -class Slave; + class Job; + class Slave; } class SmtpJobPrivate; namespace MailTransport { /** Mail transport job for SMTP. Internally, all jobs for a specific transport are queued to use the same KIO::Slave. This avoids multiple simultaneous connections to the server, which is not always allowed. Also, re-using an already existing connection avoids the login overhead and can improve performance. Precommands are automatically executed, once per opening a connection to the server (not necessarily once per message). */ class MAILTRANSPORT_EXPORT SmtpJob : public TransportJob { Q_OBJECT public: /** Creates a SmtpJob. @param transport The transport settings. @param parent The parent object. */ explicit SmtpJob( Transport *transport, QObject *parent = 0 ); /** Deletes this job. */ virtual ~SmtpJob(); protected: virtual void doStart(); virtual bool doKill(); protected Q_SLOTS: virtual void slotResult( KJob *job ); void slaveError( KIO::Slave *slave, int errorCode, const QString &errorMsg ); private: void startSmtpJob(); private Q_SLOTS: void dataRequest( KIO::Job *job, QByteArray &data ); private: SmtpJobPrivate *const d; }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_SMTPJOB_H diff --git a/mailtransport/socket.cpp b/mailtransport/socket.cpp index 0bfa84d2c..f42dacb7e 100644 --- a/mailtransport/socket.cpp +++ b/mailtransport/socket.cpp @@ -1,228 +1,228 @@ /* Copyright (C) 2006-2007 KovoKs This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // Uncomment the next line for full comm debug // #define comm_debug // Own #include "socket.h" // Qt #include #include #include // KDE -#include +#include +#include #include -#include using namespace MailTransport; namespace MailTransport { class SocketPrivate { public: SocketPrivate( Socket *s ); Socket *const q; QSslSocket *socket; QString server; QString protocol; int port; bool secure; // slots void slotConnected(); void slotStateChanged( QAbstractSocket::SocketState state ); void slotModeChanged( QSslSocket::SslMode state ); void slotSocketRead(); void slotSslErrors( const QList &errors ); private: QString m_msg; }; } SocketPrivate::SocketPrivate( Socket *s ) : q( s ) { } void SocketPrivate::slotConnected() { kDebug() ; if ( !secure ) { kDebug() << "normal connect"; emit q->connected(); } else { kDebug() << "encrypted connect"; socket->startClientEncryption(); } } void SocketPrivate::slotStateChanged( QAbstractSocket::SocketState state ) { #ifdef comm_debug kDebug() << "State is now:" << ( int ) state; #endif if ( state == QAbstractSocket::UnconnectedState ) { emit q->failed(); } } void SocketPrivate::slotModeChanged( QSslSocket::SslMode state ) { #ifdef comm_debug kDebug() << "Mode is now:" << state; #endif if ( state == QSslSocket::SslClientMode ) { emit q->tlsDone(); } } void SocketPrivate::slotSocketRead() { kDebug(); if ( !socket ) { return; } m_msg += QLatin1String( socket->readAll() ); if ( !m_msg.endsWith( QLatin1Char( '\n' ) ) ) { return; } #ifdef comm_debug kDebug() << socket->isEncrypted() << m_msg.trimmed(); #endif emit q->data( m_msg ); m_msg.clear(); } void SocketPrivate::slotSslErrors( const QList & ) { kDebug(); /* We can safely ignore the errors, we are only interested in the capabilities. We're not sending auth info. */ socket->ignoreSslErrors(); emit q->connected(); } // ------------------ end private ---------------------------// Socket::Socket( QObject *parent ) : QObject( parent ), d( new SocketPrivate( this ) ) { d->socket = 0; d->port = 0; d->secure = false; kDebug(); } Socket::~Socket() { kDebug(); delete d; } void Socket::reconnect() { kDebug() << "Connecting to:" << d->server << ":" << d->port; #ifdef comm_debug // kDebug() << d->protocol; #endif if ( d->socket ) { return; } d->socket = static_cast( KSocketFactory::connectToHost( d->protocol, d->server, d->port, this ) ); d->socket->setProtocol( QSsl::AnyProtocol ); connect( d->socket, SIGNAL( stateChanged( QAbstractSocket::SocketState ) ), SLOT( slotStateChanged( QAbstractSocket::SocketState ) ) ); connect( d->socket, SIGNAL( modeChanged( QSslSocket::SslMode ) ), SLOT( slotModeChanged( QSslSocket::SslMode ) ) ); connect( d->socket, SIGNAL( connected() ), SLOT( slotConnected() ) ); connect( d->socket, SIGNAL( readyRead() ), SLOT( slotSocketRead() ) ); connect( d->socket, SIGNAL( encrypted() ), SIGNAL( connected() ) ); connect( d->socket, SIGNAL( sslErrors( const QList & ) ), SLOT( slotSslErrors( const QList& ) ) ); } void Socket::write( const QString &text ) { // kDebug(); // Eat things in the queue when there is no connection. We need // to get a connection first don't we... if ( !d->socket || !available() ) { return; } QByteArray cs = ( text + QLatin1String( "\r\n" ) ).toLatin1(); #ifdef comm_debug kDebug() << "C :" << cs; #endif d->socket->write( cs.data(), cs.size() ); } bool Socket::available() { // kDebug(); bool ok = d->socket && d->socket->state() == QAbstractSocket::ConnectedState; return ok; } void Socket::startTLS() { kDebug() << objectName(); d->socket->setProtocol( QSsl::TlsV1 ); d->socket->startClientEncryption(); } void Socket::setProtocol( const QString &proto ) { d->protocol = proto; } void Socket::setServer( const QString &server ) { d->server = server; } void Socket::setPort( int port ) { d->port = port; } void Socket::setSecure( bool what ) { d->secure = what; } #include "socket.moc" diff --git a/mailtransport/socket.h b/mailtransport/socket.h index f6b16dcd5..4ef03bbd7 100644 --- a/mailtransport/socket.h +++ b/mailtransport/socket.h @@ -1,131 +1,131 @@ /* Copyright (C) 2006-2007 KovoKs This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_SOCKET_H #define MAILTRANSPORT_SOCKET_H #include -#include +#include namespace MailTransport { class SocketPrivate; /** * @class Socket * Responsible for communicating with the server, it's designed to work * with the ServerTest class. * @author Tom Albers */ class MAILTRANSPORT_EXPORT Socket : public QObject { Q_OBJECT public: /** * Contructor, it will not auto connect. Call reconnect() to connect to * the parameters given. * @param parent the parent */ explicit Socket( QObject *parent ); /** * Destructor */ ~Socket(); /** * Existing connection will be closed and a new connection will be * made */ virtual void reconnect(); /** * Write @p text to the socket */ virtual void write( const QString &text ); /** * @return true when the connection is live and kicking */ virtual bool available(); /** * set the protocol to use */ void setProtocol( const QString &proto ); /** * set the server to use */ void setServer( const QString &server ); /** * set the port to use. If not specified, it will use the default * belonging to the protocol. */ void setPort( int port ); /** * this will be a secure connection */ void setSecure( bool what ); /** * If you want to start TLS encryption, call this. For example after the starttls command. */ void startTLS(); private: Q_DECLARE_PRIVATE( Socket ) SocketPrivate *const d; Q_PRIVATE_SLOT( d, void slotConnected() ) Q_PRIVATE_SLOT( d, void slotStateChanged( QAbstractSocket::SocketState state ) ) Q_PRIVATE_SLOT( d, void slotModeChanged( QSslSocket::SslMode state ) ) Q_PRIVATE_SLOT( d, void slotSocketRead() ) Q_PRIVATE_SLOT( d, void slotSslErrors( const QList &errors ) ) Q_SIGNALS: /** * emits the incoming data */ void data( const QString & ); /** * emitted when there is a connection (ready to send something). */ void connected(); /** * emitted when not connected. */ void failed(); /** * emitted when startShake() is completed. */ void tlsDone(); }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_SOCKET_H diff --git a/mailtransport/tests/transportmgr.cpp b/mailtransport/tests/transportmgr.cpp index 211a916ea..afe9ddf0b 100644 --- a/mailtransport/tests/transportmgr.cpp +++ b/mailtransport/tests/transportmgr.cpp @@ -1,146 +1,148 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportmgr.h" #include #include #include #include #include #include #include #include #include #include using namespace MailTransport; TransportMgr::TransportMgr() : mCurrentJob( 0 ) { new TransportManagementWidget( this ); mComboBox = new TransportComboBox( this ); mComboBox->setEditable( true ); QPushButton *b = new QPushButton( "&Edit", this ); connect( b, SIGNAL(clicked(bool)), SLOT(editBtnClicked()) ); b = new QPushButton( "&Remove all transports", this ); connect( b, SIGNAL(clicked(bool)), SLOT(removeAllBtnClicked()) ); mSenderEdit = new KLineEdit( this ); mSenderEdit->setClickMessage( "Sender" ); mToEdit = new KLineEdit( this ); mToEdit->setClickMessage( "To" ); mCcEdit = new KLineEdit( this ); mCcEdit->setClickMessage( "Cc" ); mBccEdit = new KLineEdit( this ); mBccEdit->setClickMessage( "Bcc" ); mMailEdit = new KTextEdit( this ); mMailEdit->setAcceptRichText( false ); mMailEdit->setLineWrapMode( QTextEdit::NoWrap ); b = new QPushButton( "&Send", this ); connect( b, SIGNAL(clicked(bool)), SLOT(sendBtnClicked()) ); b = new QPushButton( "&Cancel", this ); connect( b, SIGNAL(clicked(bool)), SLOT(cancelBtnClicked()) ); } void TransportMgr::removeAllBtnClicked() { MailTransport::TransportManager *manager = MailTransport::TransportManager::self(); QList transports = manager->transports(); for ( int i=0; i < transports.count(); i++ ) { MailTransport::Transport *transport = transports.at( i ); kDebug() << transport->host(); manager->removeTransport( transport->id() ); } } void TransportMgr::editBtnClicked() { + // NOTE: Using deprecated TransportConfigDialog here for testing purposes. + // The TransportManagementWidget uses the non-deprecated method instead. TransportConfigDialog *t = new TransportConfigDialog( TransportManager::self()->transportById( mComboBox->currentTransportId() ), this ); t->exec(); delete t; } void TransportMgr::sendBtnClicked() { TransportJob *job; job = TransportManager::self()->createTransportJob( mComboBox->currentTransportId() ); if ( !job ) { kDebug() << "Invalid transport!"; return; } job->setSender( mSenderEdit->text() ); job->setTo( mToEdit->text().isEmpty() ? QStringList() : mToEdit->text().split( ',' ) ); job->setCc( mCcEdit->text().isEmpty() ? QStringList() : mCcEdit->text().split( ',' ) ); job->setBcc( mBccEdit->text().isEmpty() ? QStringList() : mBccEdit->text().split( ',' ) ); job->setData( mMailEdit->document()->toPlainText().toLatin1() ); connect( job, SIGNAL(result(KJob*)), SLOT(jobResult(KJob*)) ); connect( job, SIGNAL(percent(KJob*,unsigned long)), SLOT(jobPercent(KJob*,unsigned long)) ); connect( job, SIGNAL(infoMessage(KJob*,QString,QString)), SLOT(jobInfoMessage(KJob*,QString,QString)) ); mCurrentJob = job; TransportManager::self()->schedule( job ); } void TransportMgr::cancelBtnClicked() { if ( mCurrentJob ) { kDebug() << "kill success:" << mCurrentJob->kill(); } mCurrentJob = 0; } int main( int argc, char **argv ) { KCmdLineArgs::init( argc, argv, "transportmgr", 0, ki18n( "transportmgr" ), "0", ki18n( "Mail Transport Manager Demo" ) ); KApplication app; TransportMgr *t = new TransportMgr(); t->show(); app.exec(); delete t; } void TransportMgr::jobResult( KJob *job ) { kDebug() << job->error() << job->errorText(); mCurrentJob = 0; } void TransportMgr::jobPercent( KJob *job, unsigned long percent ) { Q_UNUSED( job ); kDebug() << percent << "%"; } void TransportMgr::jobInfoMessage( KJob *job, const QString &info, const QString &info2 ) { Q_UNUSED( job ); kDebug() << info; kDebug() << info2; } #include "transportmgr.moc" diff --git a/mailtransport/transport.cpp b/mailtransport/transport.cpp index cd457240e..33e56534e 100644 --- a/mailtransport/transport.cpp +++ b/mailtransport/transport.cpp @@ -1,338 +1,338 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transport.h" #include "legacydecrypt.h" #include "mailtransport_defs.h" #include "transportmanager.h" #include "transporttype_p.h" -#include -#include -#include -#include -#include -#include - #include +#include +#include +#include +#include +#include +#include + #include #include using namespace MailTransport; using namespace KWallet; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class TransportPrivate { public: TransportType transportType; QString password; bool passwordLoaded; bool passwordDirty; bool storePasswordInFile; bool needsWalletMigration; QString oldName; }; Transport::Transport( const QString &cfgGroup ) : TransportBase( cfgGroup ), d( new TransportPrivate ) { kDebug() << cfgGroup; d->passwordLoaded = false; d->passwordDirty = false; d->storePasswordInFile = false; d->needsWalletMigration = false; readConfig(); } Transport::~Transport() { delete d; } bool Transport::isValid() const { return ( id() > 0 ) && !host().isEmpty() && port() <= 65536; } QString Transport::password() { if ( !d->passwordLoaded && requiresAuthentication() && storePassword() && d->password.isEmpty() ) { TransportManager::self()->loadPasswords(); d->password = TransportManager::self()->transportById( id(), false )->password(); } return d->password; } void Transport::setPassword( const QString &passwd ) { d->passwordLoaded = true; if ( d->password == passwd ) { return; } d->passwordDirty = true; d->password = passwd; } void Transport::forceUniqueName() { QStringList existingNames; foreach ( Transport *t, TransportManager::self()->transports() ) { if ( t->id() != id() ) { existingNames << t->name(); } } int suffix = 1; QString origName = name(); while ( existingNames.contains( name() ) ) { setName( i18nc( "%1: name; %2: number appended to it to make " "it unique among a list of names", "%1 #%2", origName, suffix ) ); ++suffix; } } void Transport::updatePasswordState() { Transport *original = TransportManager::self()->transportById( id(), false ); if ( original == this ) { kWarning() << "Tried to update password state of non-cloned transport."; return; } if ( original ) { d->password = original->d->password; d->passwordLoaded = original->d->passwordLoaded; d->passwordDirty = original->d->passwordDirty; } else { kWarning() << "Transport with this ID not managed by transport manager."; } } bool Transport::isComplete() const { return !requiresAuthentication() || !storePassword() || d->passwordLoaded; } QString Transport::authenticationTypeString() const { switch ( authenticationType() ) { case EnumAuthenticationType::LOGIN: return QLatin1String( "LOGIN" ); case EnumAuthenticationType::PLAIN: return QLatin1String( "PLAIN" ); case EnumAuthenticationType::CRAM_MD5: return QLatin1String( "CRAM-MD5" ); case EnumAuthenticationType::DIGEST_MD5: return QLatin1String( "DIGEST-MD5" ); case EnumAuthenticationType::NTLM: return QLatin1String( "NTLM" ); case EnumAuthenticationType::GSSAPI: return QLatin1String( "GSSAPI" ); } Q_ASSERT( false ); return QString(); } void Transport::usrReadConfig() { TransportBase::usrReadConfig(); setHost( host().trimmed() ); if ( d->oldName.isEmpty() ) { d->oldName = name(); } // Set TransportType. { using namespace Akonadi; d->transportType = TransportType(); d->transportType.d->mType = type(); kDebug() << "type" << type(); if( type() == EnumType::Akonadi ) { const AgentInstance instance = AgentManager::self()->instance( host() ); if( !instance.isValid() ) { kWarning() << "Akonadi transport with invalid resource instance."; } d->transportType.d->mAgentType = instance.type(); kDebug() << "agent type" << instance.type().name() << "id" << instance.type().identifier(); } // Now we have the type and possibly agentType. Get the name, description // etc. from TransportManager. const TransportType::List &types = TransportManager::self()->types(); int index = types.indexOf( d->transportType ); if( index != -1 ) { d->transportType = types[ index ]; } else { kWarning() << "Type unknown to manager."; d->transportType.d->mName = i18n( "Unknown" ); } } // we have everything we need if ( !storePassword() || d->passwordLoaded ) { return; } // try to find a password in the config file otherwise KConfigGroup group( config(), currentGroup() ); if ( group.hasKey( "password" ) ) { d->password = KStringHandler::obscure( group.readEntry( "password" ) ); } else if ( group.hasKey( "password-kmail" ) ) { d->password = Legacy::decryptKMail( group.readEntry( "password-kmail" ) ); } else if ( group.hasKey( "password-knode" ) ) { d->password = Legacy::decryptKNode( group.readEntry( "password-knode" ) ); } if ( !d->password.isEmpty() ) { d->passwordLoaded = true; if ( Wallet::isEnabled() ) { d->needsWalletMigration = true; } else { d->storePasswordInFile = true; } } else { // read password if wallet is open, defer otherwise if ( Wallet::isOpen( Wallet::NetworkWallet() ) ) { // Don't read the password right away because this can lead // to reentrancy problems in KDBusServiceStarter when an application // run in Kontact creates the transports (due to a QEventLoop in the // synchronous KWallet openWallet call). QTimer::singleShot( 0, this, SLOT(readPassword()) ); } } } void Transport::usrWriteConfig() { if ( requiresAuthentication() && storePassword() && d->passwordDirty ) { Wallet *wallet = TransportManager::self()->wallet(); if ( !wallet || wallet->writePassword( QString::number( id() ), d->password ) != 0 ) { // wallet saving failed, ask if we should store in the config file instead if ( d->storePasswordInFile || KMessageBox::warningYesNo( 0, i18n( "KWallet is not available. It is strongly recommended to use " "KWallet for managing your passwords.\n" "However, the password can be stored in the configuration " "file instead. The password is stored in an obfuscated format, " "but should not be considered secure from decryption efforts " "if access to the configuration file is obtained.\n" "Do you want to store the password for server '%1' in the " "configuration file?", name() ), i18n( "KWallet Not Available" ), KGuiItem( i18n( "Store Password" ) ), KGuiItem( i18n( "Do Not Store Password" ) ) ) == KMessageBox::Yes ) { // write to config file KConfigGroup group( config(), currentGroup() ); group.writeEntry( "password", KStringHandler::obscure( d->password ) ); d->storePasswordInFile = true; } } d->passwordDirty = false; } TransportBase::usrWriteConfig(); TransportManager::self()->emitChangesCommitted(); if ( name() != d->oldName ) { emit TransportManager::self()->transportRenamed( id(), d->oldName, name() ); d->oldName = name(); } } void Transport::readPassword() { // no need to load a password if the account doesn't require auth if ( !requiresAuthentication() ) { return; } d->passwordLoaded = true; // check whether there is a chance to find our password at all if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER ) || Wallet::keyDoesNotExist( Wallet::NetworkWallet(), WALLET_FOLDER, QString::number( id() ) ) ) { // try migrating password from kmail if ( Wallet::folderDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER ) || Wallet::keyDoesNotExist( Wallet::NetworkWallet(), KMAIL_WALLET_FOLDER, QString::fromLatin1( "transport-%1" ).arg( id() ) ) ) { return; } kDebug() << "migrating password from kmail wallet"; KWallet::Wallet *wallet = TransportManager::self()->wallet(); if ( wallet ) { wallet->setFolder( KMAIL_WALLET_FOLDER ); wallet->readPassword( QString::fromLatin1( "transport-%1" ).arg( id() ), d->password ); wallet->removeEntry( QString::fromLatin1( "transport-%1" ).arg( id() ) ); wallet->setFolder( WALLET_FOLDER ); d->passwordDirty = true; writeConfig(); } return; } // finally try to open the wallet and read the password KWallet::Wallet *wallet = TransportManager::self()->wallet(); if ( wallet ) { wallet->readPassword( QString::number( id() ), d->password ); } } bool Transport::needsWalletMigration() const { return d->needsWalletMigration; } void Transport::migrateToWallet() { kDebug() << "migrating" << id() << "to wallet"; d->needsWalletMigration = false; KConfigGroup group( config(), currentGroup() ); group.deleteEntry( "password" ); d->passwordDirty = true; d->storePasswordInFile = false; writeConfig(); } Transport *Transport::clone() const { QString id = currentGroup().mid( 10 ); return new Transport( id ); } TransportType Transport::transportType() const { if( !d->transportType.isValid() ) { kWarning() << "Invalid transport type."; } return d->transportType; } void Transport::setTransportType( const TransportType &type ) { Q_ASSERT( type.isValid() ); d->transportType = type; setType( type.type() ); } #include "transport.moc" diff --git a/mailtransport/transport.h b/mailtransport/transport.h index 41e62849d..9f2b7d7c2 100644 --- a/mailtransport/transport.h +++ b/mailtransport/transport.h @@ -1,154 +1,157 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORT_H #define MAILTRANSPORT_TRANSPORT_H #include #include #include class TransportPrivate; namespace MailTransport { class TransportType; /** Represents the settings of a specific mail transport. To create a new empty Transport object, use TransportManager::createTransport(). */ // TODO KDE5: Do something about the kcfg-generated TransportBase. // Currently it has the config stuff as private members, which means it is // utterly inextensible. Also the sendmail and akonadi-type transports use // the "host" setting for keeping the location of the sendmail executable and // the resource id, respectively. This is a hack; they should have separate // config options... (cberzan) class MAILTRANSPORT_EXPORT Transport : public TransportBase { Q_OBJECT friend class TransportManager; public: /** Destructor */ virtual ~Transport(); typedef QList List; /** Returns true if this transport is valid, ie. has all necessary data set. */ bool isValid() const; /** Returns the password of this transport. */ QString password(); /** Sets the password of this transport. @param passwd The new password. */ void setPassword( const QString &passwd ); /** Makes sure the transport has a unique name. Adds #1, #2, #3 etc. if necessary. + @since 4.4 */ void forceUniqueName(); /** This function synchronizes the password of this transport with the password of the transport with the same ID that is managed by the transport manager. This is only useful for cloned transports, since their passwords don't automatically get updated when calling TransportManager::loadPasswordsAsync() or TransportManager::loadPasswords(). @sa clone() @since 4.2 */ void updatePasswordState(); /** Returns true if all settings have been loaded. This is the way to find out if the password has already been loaded from the wallet. */ bool isComplete() const; /** Returns a string representation of the authentication type. */ QString authenticationTypeString() const; /** Returns a deep copy of this Transport object which will no longer be automatically updated. Use this if you need to store a Transport object over a longer time. However it is recommended to store transport identifiers instead if possible. @sa updatePasswordState() */ Transport *clone() const; /** Returns the type of this transport. @see TransportType. + @since 4.4 */ TransportType transportType() const; /** Sets the type of this transport. @see TransportType. + @since 4.4 */ void setTransportType( const TransportType &type ); protected: /** Creates a Transport object. Should only be used by TransportManager. @param cfgGroup The KConfig group to read its data from. */ Transport( const QString &cfgGroup ); virtual void usrReadConfig(); virtual void usrWriteConfig(); /** Returns true if the password was not stored in the wallet. */ bool needsWalletMigration() const; /** Try to migrate the password from the config file to the wallet. */ void migrateToWallet(); private Q_SLOTS: void readPassword(); private: TransportPrivate *const d; }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_TRANSPORT_H diff --git a/mailtransport/transportcombobox.cpp b/mailtransport/transportcombobox.cpp index f1a310f98..28a72a8a8 100644 --- a/mailtransport/transportcombobox.cpp +++ b/mailtransport/transportcombobox.cpp @@ -1,98 +1,96 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportcombobox.h" #include "transport.h" #include "transportmanager.h" -#include -#include - -#include +#include +#include using namespace MailTransport; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class TransportComboBoxPrivate { public: QList transports; }; TransportComboBox::TransportComboBox( QWidget *parent ) : KComboBox( parent ), d( new TransportComboBoxPrivate ) { fillComboBox(); connect( TransportManager::self(), SIGNAL(transportsChanged()), SLOT(fillComboBox()) ); } TransportComboBox::~TransportComboBox() { delete d; } int TransportComboBox::currentTransportId() const { if ( currentIndex() >= 0 && currentIndex() < d->transports.count() ) { return d->transports.at( currentIndex() ); } return -1; } void TransportComboBox::setCurrentTransport( int transportId ) { int i = d->transports.indexOf( transportId ); if ( i >= 0 && i < count() ) { setCurrentIndex( i ); } } TransportBase::EnumType::type TransportComboBox::transportType() const { int transtype = TransportManager::self()->transportById( currentTransportId() )->type(); return static_cast( transtype ); } void TransportComboBox::fillComboBox() { int oldTransport = currentTransportId(); clear(); d->transports.clear(); int defaultId = 0; if ( !TransportManager::self()->isEmpty() ) { QStringList listNames = TransportManager::self()->transportNames(); QList listIds = TransportManager::self()->transportIds(); addItems( listNames ); d->transports << listIds; defaultId = TransportManager::self()->defaultTransportId(); } if ( oldTransport != -1 ) { setCurrentTransport( oldTransport ); } else { setCurrentTransport( defaultId ); } } #include "transportcombobox.moc" diff --git a/mailtransport/transportcombobox.h b/mailtransport/transportcombobox.h index 6e6c0e865..562f2aa27 100644 --- a/mailtransport/transportcombobox.h +++ b/mailtransport/transportcombobox.h @@ -1,72 +1,74 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTCOMBOBOX_H #define MAILTRANSPORT_TRANSPORTCOMBOBOX_H -#include #include -#include +#include + +#include class TransportComboBoxPrivate; namespace MailTransport { /** A combo-box for selecting a mail transport. + It is updated automatically when transports are added, changed, or removed. */ class MAILTRANSPORT_EXPORT TransportComboBox : public KComboBox { Q_OBJECT public: /** Creates a new mail transport selection combo box. @param parent The paren widget. */ TransportComboBox( QWidget *parent = 0 ); ~TransportComboBox(); /** Returns identifier of the currently selected mail transport. */ int currentTransportId() const; /** Selects the given transport. @param transportId The transport identifier. */ void setCurrentTransport( int transportId ); /** Returns the type of the selected transport. */ TransportBase::EnumType::type transportType() const; private Q_SLOTS: void fillComboBox(); private: TransportComboBoxPrivate *const d; }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_TRANSPORTCOMBOBOX_H diff --git a/mailtransport/transportconfigdialog.h b/mailtransport/transportconfigdialog.h index 85963e7d2..440163d97 100644 --- a/mailtransport/transportconfigdialog.h +++ b/mailtransport/transportconfigdialog.h @@ -1,79 +1,79 @@ /* Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2009 Constantin Berzan Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTCONFIGDIALOG_H #define MAILTRANSPORT_TRANSPORTCONFIGDIALOG_H #include #include namespace MailTransport { class Transport; /** Configuration dialog for a mail transport. @deprecated Use TransportManager::configureTransport() instead. */ -// KDE5: this class should not be exported. +// TODO KDE5: this class should not be exported. // FIXME how to avoid deprecated warning from its own moc? class MAILTRANSPORT_EXPORT_DEPRECATED TransportConfigDialog : public KDialog { Q_OBJECT public: /** Creates a new mail transport configuration dialog for the given Transport object. The config dialog does not delete @p transport, you have to delete it yourself. Note that this class only works for transports that are handled directly by MailTransport, i.e. SMTP and Sendmail. This class cannot be used to configure an Akonadi transport. @param transport The Transport object to configure. This must be a deep copy of a Transport object or a newly created one, which hasn't been added to the TransportManager yet. @param parent The parent widget. */ explicit TransportConfigDialog( Transport *transport, QWidget *parent = 0 ); /** Destroys the dialog. */ virtual ~TransportConfigDialog(); private: class Private; Private *const d; Q_PRIVATE_SLOT( d, void okClicked() ) }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_TRANSPORTCONFIGDIALOG_H diff --git a/mailtransport/transportconfigwidget.cpp b/mailtransport/transportconfigwidget.cpp index 640b159e6..adf8cc49e 100644 --- a/mailtransport/transportconfigwidget.cpp +++ b/mailtransport/transportconfigwidget.cpp @@ -1,85 +1,83 @@ /* Copyright (c) 2009 Constantin Berzan Based on MailTransport code by: Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2007 KovoKs Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportconfigwidget.h" #include "transportconfigwidget_p.h" #include "transport.h" #include "transportmanager.h" #include #include -#include using namespace MailTransport; TransportConfigWidget::TransportConfigWidget( Transport *transport, QWidget *parent ) : QWidget( parent ) , d_ptr( new TransportConfigWidgetPrivate ) { init( transport ); } TransportConfigWidget::TransportConfigWidget( TransportConfigWidgetPrivate &dd, Transport *transport, QWidget *parent ) : QWidget( parent ) , d_ptr( &dd ) { init( transport ); } TransportConfigWidget::~ TransportConfigWidget() { delete d_ptr; } void TransportConfigWidget::init( Transport *transport ) { Q_D( TransportConfigWidget ); kDebug() << "this" << this << "d" << d; Q_ASSERT( transport ); d->transport = transport; d->manager = new KConfigDialogManager( this, transport ); - //d->manager->updateWidgets(); // no use; ui is set up in subclasses. + //d->manager->updateWidgets(); // no-op; ui is set up in subclasses. } KConfigDialogManager *TransportConfigWidget::configManager() const { Q_D( const TransportConfigWidget ); Q_ASSERT( d->manager ); return d->manager; } void TransportConfigWidget::apply() { Q_D( TransportConfigWidget ); d->manager->updateSettings(); d->transport->forceUniqueName(); d->transport->writeConfig(); kDebug() << "Config written."; } - #include "transportconfigwidget.moc" diff --git a/mailtransport/transportconfigwidget.h b/mailtransport/transportconfigwidget.h index 907494f1f..fc6b4f54f 100644 --- a/mailtransport/transportconfigwidget.h +++ b/mailtransport/transportconfigwidget.h @@ -1,93 +1,107 @@ /* Copyright (c) 2009 Constantin Berzan Based on MailTransport code by: Copyright (c) 2006 - 2007 Volker Krause Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTCONFIGWIDGET_H #define MAILTRANSPORT_TRANSPORTCONFIGWIDGET_H #include class KConfigDialogManager; namespace MailTransport { class Transport; class TransportConfigWidgetPrivate; /** @internal - Abstract configuration widget for a mail transport. - There is a derived class for each transport, such as SMTPConfigWidget etc. + + Abstract configuration widget for a mail transport. It makes sure that + the configured transport has a unique name, and takes care of writing its + settings to the config file. If it is a new transport, the caller must + still call TransportManager::addTransport() to register the transport. + + Concrete configuration is done in subclasses SMTPConfigWidget and + SendmailConfigWidget. Akonadi-type transports are not configured by + MailTransport directly, instead the configure() method of their agent + instance is called. + + To configure a transport from applications, use + TransportManager::configureTransport(). You still need to call + TransportManager::addTransport() if this is a new transport, not registered + with TransportManager. + + @author Constantin Berzan + @since 4.4 */ class TransportConfigWidget : public QWidget { Q_OBJECT public: /** Creates a new mail transport configuration widget for the given Transport object. - @param transport The Transport object to configure. This must be a deep - copy of a Transport object or a newly created one, which hasn't been - added to the TransportManager yet. + @param transport The Transport object to configure. @param parent The parent widget. */ explicit TransportConfigWidget( Transport *transport, QWidget *parent = 0 ); /** Destroys the widget. */ virtual ~TransportConfigWidget(); /** @internal Get the KConfigDialogManager for this widget. */ KConfigDialogManager *configManager() const; public Q_SLOTS: /** Saves the transport's settings. The base implementation writes the settings to the config file and makes sure the transport has a unique name. Reimplement in derived classes to save your custom settings, and call the base implementation. */ // TODO: do we also want to check for invalid settings? virtual void apply(); protected: TransportConfigWidgetPrivate *const d_ptr; TransportConfigWidget( TransportConfigWidgetPrivate &dd, Transport *transport, QWidget *parent ); private: Q_DECLARE_PRIVATE( TransportConfigWidget ) void init( Transport *transport ); }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_TRANSPORTCONFIGWIDGET_H diff --git a/mailtransport/transportconfigwidget_p.h b/mailtransport/transportconfigwidget_p.h index 32618c9fd..1e61ba505 100644 --- a/mailtransport/transportconfigwidget_p.h +++ b/mailtransport/transportconfigwidget_p.h @@ -1,44 +1,46 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTCONFIGWIDGET_P_H #define MAILTRANSPORT_TRANSPORTCONFIGWIDGET_P_H #include "transport.h" #include -namespace MailTransport -{ +namespace MailTransport { +/** + @internal +*/ class TransportConfigWidgetPrivate { public: Transport *transport; KConfigDialogManager *manager; virtual ~TransportConfigWidgetPrivate() { } }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_TRANSPORTCONFIGWIDGET_P_H diff --git a/mailtransport/transportjob.cpp b/mailtransport/transportjob.cpp index 63361499c..4967778cf 100644 --- a/mailtransport/transportjob.cpp +++ b/mailtransport/transportjob.cpp @@ -1,130 +1,130 @@ /* Copyright (c) 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportjob.h" #include "transport.h" -#include - #include +#include + using namespace MailTransport; class MailTransport::TransportJob::Private { public: Transport *transport; QString sender; QStringList to; QStringList cc; QStringList bcc; QByteArray data; QBuffer *buffer; }; TransportJob::TransportJob( Transport *transport, QObject *parent ) : KCompositeJob( parent ), d( new Private ) { d->transport = transport; d->buffer = 0; } TransportJob::~ TransportJob() { delete d->transport; delete d; } void TransportJob::setSender( const QString &sender ) { d->sender = sender; } void TransportJob::setTo( const QStringList &to ) { d->to = to; } void TransportJob::setCc( const QStringList &cc ) { d->cc = cc; } void TransportJob::setBcc( const QStringList &bcc ) { d->bcc = bcc; } void TransportJob::setData( const QByteArray &data ) { d->data = data; } Transport *TransportJob::transport() const { return d->transport; } QString TransportJob::sender() const { return d->sender; } QStringList TransportJob::to() const { return d->to; } QStringList TransportJob::cc() const { return d->cc; } QStringList TransportJob::bcc() const { return d->bcc; } QByteArray TransportJob::data() const { return d->data; } QBuffer *TransportJob::buffer() { if ( !d->buffer ) { d->buffer = new QBuffer( this ); d->buffer->setData( d->data ); d->buffer->open( QIODevice::ReadOnly ); Q_ASSERT( d->buffer->isOpen() ); } return d->buffer; } void TransportJob::start() { if ( !transport()->isValid() ) { setError( UserDefinedError ); setErrorText( i18n( "The mail transport \"%1\" is not correctly configured.", transport()->name() ) ); emitResult(); return; } doStart(); } diff --git a/mailtransport/transportjob.h b/mailtransport/transportjob.h index 8310919ec..164dd88e2 100644 --- a/mailtransport/transportjob.h +++ b/mailtransport/transportjob.h @@ -1,138 +1,140 @@ /* Copyright (c) 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTJOB_H #define MAILTRANSPORT_TRANSPORTJOB_H #include -#include + #include +#include + class QBuffer; namespace MailTransport { class Transport; /** Abstract base class for all mail transport jobs. This is a job that is supposed to send exactly one mail. */ class MAILTRANSPORT_EXPORT TransportJob : public KCompositeJob { friend class TransportManager; public: /** Deletes this transport job. */ virtual ~TransportJob(); /** Sets the sender of the mail. */ void setSender( const QString &sender ); /** Sets the "To" receiver(s) of the mail. */ void setTo( const QStringList &to ); /** Sets the "Cc" receiver(s) of the mail. */ void setCc( const QStringList &cc ); /** Sets the "Bcc" receiver(s) of the mail. */ void setBcc( const QStringList &bcc ); /** Sets the content of the mail. */ void setData( const QByteArray &data ); /** Starts this job. It is recommended to not call this method directly but use TransportManager::schedule() to execute the job instead. @see TransportManager::schedule() */ virtual void start(); /** Returns the Transport object containing the mail transport settings. */ Transport *transport() const; protected: /** Creates a new mail transport job. @param transport The transport configuration. This must be a deep copy of a Transport object, the job takes the ownership of this object. @param parent The parent object. @see TransportManager::createTransportJob() */ explicit TransportJob( Transport *transport, QObject *parent = 0 ); /** Returns the sender of the mail. */ QString sender() const; /** Returns the "To" receiver(s) of the mail. */ QStringList to() const; /** Returns the "Cc" receiver(s) of the mail. */ QStringList cc() const; /** Returns the "Bcc" receiver(s) of the mail. */ QStringList bcc() const; /** Returns the data of the mail. */ QByteArray data() const; /** Returns a QBuffer opened on the message data. This is useful for processing the data in smaller chunks. */ QBuffer *buffer(); /** Do the actual work, implement in your subclass. */ virtual void doStart() = 0; private: class Private; Private *const d; }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_TRANSPORTJOB_H diff --git a/mailtransport/transportlistview.cpp b/mailtransport/transportlistview.cpp index d9568999c..0956f6547 100644 --- a/mailtransport/transportlistview.cpp +++ b/mailtransport/transportlistview.cpp @@ -1,116 +1,114 @@ /* Copyright (c) 2009 Constantin Berzan Based on KMail code by: Copyright (c) 2002 Marc Mutz 2007 Mathias Soeken This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportlistview.h" #include "transport.h" #include "transportmanager.h" #include "transporttype.h" #include #include #include #include - using namespace MailTransport; TransportListView::TransportListView( QWidget *parent ) : QTreeWidget( parent ) { setHeaderLabels( QStringList() << i18nc( "@title:column email transport name", "Name" ) << i18nc( "@title:column email transport type", "Type" ) ); setRootIsDecorated( false ); header()->setMovable( false ); setAllColumnsShowFocus( true ); setAlternatingRowColors( true ); setSortingEnabled( true ); sortByColumn( 0, Qt::AscendingOrder ); setSelectionMode( SingleSelection ); fillTransportList(); connect( TransportManager::self(), SIGNAL(transportsChanged()), this, SLOT(fillTransportList()) ); } void TransportListView::editItem( QTreeWidgetItem *item, int column ) { // TODO: is there a nicer way to make only the 'name' column editable? if ( column == 0 && item ) { Qt::ItemFlags oldFlags = item->flags(); item->setFlags( oldFlags | Qt::ItemIsEditable ); QTreeWidget::editItem( item, 0 ); item->setFlags( oldFlags ); } } void TransportListView::commitData( QWidget *editor ) { if( selectedItems().size() < 1 ) { // transport was deleted by someone else??? kDebug() << "No selected item."; return; } QTreeWidgetItem *item = selectedItems()[0]; QLineEdit *edit = dynamic_cast( editor ); // krazy:exclude=qclasses Q_ASSERT( edit ); // original code had if int id = item->data( 0, Qt::UserRole ).toInt(); Transport *t = TransportManager::self()->transportById( id ); if( !t ) { kWarning() << "Transport" << id << "not known by manager."; return; } kDebug() << "Renaming transport" << id << "to" << edit->text(); t->setName( edit->text() ); t->forceUniqueName(); t->writeConfig(); } void TransportListView::fillTransportList() { // try to preserve the selection int selected = -1; if ( currentItem() ) { selected = currentItem()->data( 0, Qt::UserRole ).toInt(); } clear(); foreach ( Transport *t, TransportManager::self()->transports() ) { QTreeWidgetItem *item = new QTreeWidgetItem( this ); item->setData( 0, Qt::UserRole, t->id() ); item->setText( 0, t->name() ); QString type = t->transportType().name(); if ( TransportManager::self()->defaultTransportId() == t->id() ) { type += i18nc( "@label the default mail transport", " (Default)" ); } item->setText( 1, type ); if ( t->id() == selected ) { setCurrentItem( item ); } } } - #include "transportlistview.moc" diff --git a/mailtransport/transportlistview.h b/mailtransport/transportlistview.h index 4061fa4a1..1ffd9571a 100644 --- a/mailtransport/transportlistview.h +++ b/mailtransport/transportlistview.h @@ -1,56 +1,52 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTLISTVIEW_H #define MAILTRANSPORT_TRANSPORTLISTVIEW_H - #include -namespace MailTransport -{ +namespace MailTransport { /** @internal A QTreeWidget for transports. */ class TransportListView : public QTreeWidget { Q_OBJECT public: TransportListView( QWidget *parent = 0 ); //virtual ~TransportListView() {} // overloaded from QTreeWidget void editItem( QTreeWidgetItem *item, int column = 0 ); protected slots: virtual void commitData( QWidget *editor ); private slots: - void fillTransportList(); // TODO rename? + void fillTransportList(); }; +} // namespace MailTransport -} - - -#endif +#endif // MAILTRANSPORT_TRANSPORTLISTVIEW_H diff --git a/mailtransport/transportmanagementwidget.cpp b/mailtransport/transportmanagementwidget.cpp index 3260008c9..9e0e06876 100644 --- a/mailtransport/transportmanagementwidget.cpp +++ b/mailtransport/transportmanagementwidget.cpp @@ -1,131 +1,125 @@ /* Copyright (c) 2006 - 2007 Volker Krause Based on KMail code by: Copyright (C) 2001-2003 Marc Mutz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportmanagementwidget.h" -#include "addtransportdialog.h" #include "ui_transportmanagementwidget.h" #include "transportmanager.h" #include "transport.h" -#include "transportconfigdialog.h" - -#include using namespace MailTransport; class TransportManagementWidget::Private { public: Ui::TransportManagementWidget ui; }; TransportManagementWidget::TransportManagementWidget( QWidget *parent ) : QWidget( parent ), d( new Private ) { KGlobal::locale()->insertCatalog( QString::fromLatin1( "libmailtransport" ) ); d->ui.setupUi( this ); updateButtonState(); connect( d->ui.transportList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(updateButtonState()) ); connect( d->ui.transportList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), SLOT(editClicked()) ); connect( d->ui.addButton, SIGNAL(clicked()), SLOT(addClicked()) ); connect( d->ui.editButton, SIGNAL(clicked()), SLOT(editClicked()) ); connect( d->ui.renameButton, SIGNAL(clicked()), SLOT(renameClicked()) ); connect( d->ui.removeButton, SIGNAL(clicked()), SLOT(removeClicked()) ); connect( d->ui.defaultButton, SIGNAL(clicked()), SLOT(defaultClicked()) ); } TransportManagementWidget::~TransportManagementWidget() { delete d; } void TransportManagementWidget::updateButtonState() { // TODO figure out current item vs. selected item (in almost every function) if ( !d->ui.transportList->currentItem() ) { d->ui.editButton->setEnabled( false ); d->ui.renameButton->setEnabled( false ); d->ui.removeButton->setEnabled( false ); d->ui.defaultButton->setEnabled( false ); } else { d->ui.editButton->setEnabled( true ); d->ui.renameButton->setEnabled( true ); d->ui.removeButton->setEnabled( true ); if ( d->ui.transportList->currentItem()->data( 0, Qt::UserRole ) == TransportManager::self()->defaultTransportId() ) { d->ui.defaultButton->setEnabled( false ); } else { d->ui.defaultButton->setEnabled( true ); } } } void TransportManagementWidget::addClicked() { - QPointer dialog = new AddTransportDialog( this ); - dialog->exec(); - delete dialog; + TransportManager::self()->showNewTransportDialog( this ); } void TransportManagementWidget::editClicked() { if( !d->ui.transportList->currentItem() ) { return; } int currentId = d->ui.transportList->currentItem()->data( 0, Qt::UserRole ).toInt(); Transport *transport = TransportManager::self()->transportById( currentId ); TransportManager::self()->configureTransport( transport, this ); } void TransportManagementWidget::renameClicked() { if( !d->ui.transportList->currentItem() ) { return; } d->ui.transportList->editItem( d->ui.transportList->currentItem(), 0 ); } void TransportManagementWidget::removeClicked() { if( !d->ui.transportList->currentItem() ) { return; } TransportManager::self()->removeTransport( d->ui.transportList->currentItem()->data( 0, Qt::UserRole ).toInt() ); } void TransportManagementWidget::defaultClicked() { if( !d->ui.transportList->currentItem() ) { return; } TransportManager::self()->setDefaultTransport( d->ui.transportList->currentItem()->data( 0, Qt::UserRole ).toInt() ); } #include "transportmanagementwidget.moc" diff --git a/mailtransport/transportmanagementwidget.h b/mailtransport/transportmanagementwidget.h index 864d13044..81b49ac64 100644 --- a/mailtransport/transportmanagementwidget.h +++ b/mailtransport/transportmanagementwidget.h @@ -1,65 +1,66 @@ /* Copyright (c) 2006 - 2007 Volker Krause Based on KMail code by: Copyright (C) 2001-2003 Marc Mutz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTMANAGEMENTWIDGET_H #define MAILTRANSPORT_TRANSPORTMANAGEMENTWIDGET_H #include + #include namespace MailTransport { /** A widget to manage mail transports. */ class MAILTRANSPORT_EXPORT TransportManagementWidget : public QWidget { Q_OBJECT public: /** Creates a new TransportManagementWidget. @param parent The parent widget. */ TransportManagementWidget( QWidget *parent = 0 ); /** Destroys the widget. */ virtual ~TransportManagementWidget(); private Q_SLOTS: void updateButtonState(); void addClicked(); void editClicked(); void renameClicked(); void removeClicked(); void defaultClicked(); private: class Private; Private * const d; }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_TRANSPORTMANAGEMENTWIDGET_H diff --git a/mailtransport/transportmanager.cpp b/mailtransport/transportmanager.cpp index 981cfd9c2..f64e85a6e 100644 --- a/mailtransport/transportmanager.cpp +++ b/mailtransport/transportmanager.cpp @@ -1,765 +1,769 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transportmanager.h" #include "addtransportdialog.h" #include "akonadijob.h" #include "mailtransport_defs.h" +#include "sendmailconfigwidget.h" +#include "sendmailjob.h" +#include "smtpconfigwidget.h" +#include "smtpjob.h" #include "transport.h" #include "transportconfigwidget.h" #include "transportjob.h" #include "transporttype.h" #include "transporttype_p.h" #include "transportconfigdialog.h" -#include "sendmailconfigwidget.h" -#include "sendmailjob.h" -#include "smtpconfigwidget.h" -#include "smtpjob.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include using namespace MailTransport; using namespace KWallet; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class TransportManager::Private { public: Private() {} ~Private() { delete config; qDeleteAll( transports ); } KConfig *config; QList transports; TransportType::List types; bool myOwnChange; bool appliedChange; KWallet::Wallet *wallet; bool walletOpenFailed; bool walletAsyncOpen; int defaultTransportId; bool isMainInstance; QList walletQueue; }; class StaticTransportManager : public TransportManager { public: StaticTransportManager() : TransportManager() {} }; StaticTransportManager *sSelf = 0; static void destroyStaticTransportManager() { delete sSelf; } TransportManager::TransportManager() : QObject(), d( new Private ) { KGlobal::locale()->insertCatalog( QLatin1String( "libmailtransport" ) ); qAddPostRoutine( destroyStaticTransportManager ); d->myOwnChange = false; d->appliedChange = false; d->wallet = 0; d->walletOpenFailed = false; d->walletAsyncOpen = false; d->defaultTransportId = -1; d->config = new KConfig( QLatin1String( "mailtransports" ) ); QDBusConnection::sessionBus().registerObject( DBUS_OBJECT_PATH, this, QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSignals ); QDBusConnection::sessionBus().connect( QString(), QString(), DBUS_INTERFACE_NAME, DBUS_CHANGE_SIGNAL, this, SLOT(slotTransportsChanged()) ); d->isMainInstance = QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); connect( QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), SLOT(dbusServiceOwnerChanged(QString,QString,QString)) ); fillTypes(); } TransportManager::~TransportManager() { qRemovePostRoutine( destroyStaticTransportManager ); delete d; } TransportManager *TransportManager::self() { if ( !sSelf ) { sSelf = new StaticTransportManager; sSelf->readConfig(); } return sSelf; } Transport *TransportManager::transportById( int id, bool def ) const { foreach ( Transport *t, d->transports ) { if ( t->id() == id ) { return t; } } if ( def || ( id == 0 && d->defaultTransportId != id ) ) { return transportById( d->defaultTransportId, false ); } return 0; } Transport *TransportManager::transportByName( const QString &name, bool def ) const { foreach ( Transport *t, d->transports ) { if ( t->name() == name ) { return t; } } if ( def ) { return transportById( 0, false ); } return 0; } QList< Transport * > TransportManager::transports() const { return d->transports; } const TransportType::List &TransportManager::types() const { return d->types; } Transport *TransportManager::createTransport() const { int id = createId(); Transport *t = new Transport( QString::number( id ) ); t->setId( id ); return t; } void TransportManager::addTransport( Transport *transport ) { if ( d->transports.contains( transport ) ) { kDebug() << "Already have this transport."; return; } kDebug() << "Added transport" << transport; d->transports.append( transport ); validateDefault(); emitChangesCommitted(); } void TransportManager::schedule( TransportJob *job ) { connect( job, SIGNAL(result(KJob*)), SLOT(jobResult(KJob*)) ); // check if the job is waiting for the wallet if ( !job->transport()->isComplete() ) { kDebug() << "job waits for wallet:" << job; d->walletQueue << job; loadPasswordsAsync(); return; } job->start(); } void TransportManager::createDefaultTransport() { KEMailSettings kes; Transport *t = createTransport(); t->setName( i18n( "Default Transport" ) ); t->setHost( kes.getSetting( KEMailSettings::OutServer ) ); if ( t->isValid() ) { t->writeConfig(); addTransport( t ); } else { kWarning() << "KEMailSettings does not contain a valid transport."; } } +bool TransportManager::showNewTransportDialog( QWidget *parent ) +{ + QPointer dialog = new AddTransportDialog( parent ); + bool accepted = ( dialog->exec() == QDialog::Accepted ); + delete dialog; + return accepted; +} + bool TransportManager::promptCreateTransportIfNoneExists( QWidget *parent ) { if ( !isEmpty() ) return true; const int response = KMessageBox::messageBox( parent, KMessageBox::WarningContinueCancel, i18n("You must create an outgoing account before sending."), i18n("Create Account Now?"), KGuiItem( i18n("Create Account Now") ) ); if ( response == KMessageBox::Continue ) { - QPointer dialog = new AddTransportDialog( parent ); - dialog->exec(); - delete dialog; - return !isEmpty(); // The user has created and configured a transport. + return showNewTransportDialog( parent ); } return false; } bool TransportManager::configureTransport( Transport *transport, QWidget *parent ) { if( transport->type() == Transport::EnumType::Akonadi ) { using namespace Akonadi; AgentInstance instance = AgentManager::self()->instance( transport->host() ); if( !instance.isValid() ) { kWarning() << "Invalid resource instance" << transport->host(); } instance.configure( parent ); // Async... transport->writeConfig(); return true; // No way to know here if the user cancelled or not. } QPointer dialog = new KDialog( parent ); TransportConfigWidget *configWidget = 0; switch( transport->type() ) { case Transport::EnumType::SMTP: { configWidget = new SMTPConfigWidget( transport, dialog ); break; } case Transport::EnumType::Sendmail: { configWidget = new SendmailConfigWidget( transport, dialog ); break; } default: { Q_ASSERT( false ); delete dialog; return false; } } dialog->setMainWidget( configWidget ); dialog->setCaption( i18n( "Configure account" ) ); dialog->setButtons( KDialog::Ok | KDialog::Cancel ); bool okClicked = ( dialog->exec() == QDialog::Accepted ); if( okClicked ) { configWidget->apply(); // calls transport->writeConfig() } delete dialog; return okClicked; } TransportJob *TransportManager::createTransportJob( int transportId ) { Transport *t = transportById( transportId, false ); if ( !t ) { return 0; } t = t->clone(); // Jobs delete their transports. switch ( t->type() ) { case Transport::EnumType::SMTP: return new SmtpJob( t, this ); case Transport::EnumType::Sendmail: return new SendmailJob( t, this ); case Transport::EnumType::Akonadi: return new AkonadiJob( t, this ); } Q_ASSERT( false ); return 0; } TransportJob *TransportManager::createTransportJob( const QString &transport ) { bool ok = false; Transport *t = 0; int transportId = transport.toInt( &ok ); if ( ok ) { t = transportById( transportId ); } if ( !t ) { t = transportByName( transport, false ); } if ( t ) { return createTransportJob( t->id() ); } return 0; } bool TransportManager::isEmpty() const { return d->transports.isEmpty(); } QList TransportManager::transportIds() const { QList rv; foreach ( Transport *t, d->transports ) { rv << t->id(); } return rv; } QStringList TransportManager::transportNames() const { QStringList rv; foreach ( Transport *t, d->transports ) { rv << t->name(); } return rv; } QString TransportManager::defaultTransportName() const { Transport *t = transportById( d->defaultTransportId, false ); if ( t ) { return t->name(); } return QString(); } int TransportManager::defaultTransportId() const { return d->defaultTransportId; } void TransportManager::setDefaultTransport( int id ) { if ( id == d->defaultTransportId || !transportById( id, false ) ) { return; } d->defaultTransportId = id; writeConfig(); } void TransportManager::removeTransport( int id ) { Transport *t = transportById( id, false ); if ( !t ) { return; } emit transportRemoved( t->id(), t->name() ); // Kill the resource, if Akonadi-type transport. if( t->type() == Transport::EnumType::Akonadi ) { using namespace Akonadi; const AgentInstance instance = AgentManager::self()->instance( t->host() ); if( !instance.isValid() ) { kWarning() << "Could not find resource instance."; } AgentManager::self()->removeInstance( instance ); } d->transports.removeAll( t ); validateDefault(); QString group = t->currentGroup(); delete t; d->config->deleteGroup( group ); writeConfig(); } void TransportManager::readConfig() { QList oldTransports = d->transports; d->transports.clear(); QRegExp re( QLatin1String( "^Transport (.+)$" ) ); QStringList groups = d->config->groupList().filter( re ); foreach ( const QString &s, groups ) { re.indexIn( s ); Transport *t = 0; // see if we happen to have that one already foreach ( Transport *old, oldTransports ) { if ( old->currentGroup() == QLatin1String( "Transport " ) + re.cap( 1 ) ) { kDebug() << "reloading existing transport:" << s; t = old; t->readConfig(); oldTransports.removeAll( old ); break; } } if ( !t ) { t = new Transport( re.cap( 1 ) ); } if ( t->id() <= 0 ) { t->setId( createId() ); t->writeConfig(); } d->transports.append( t ); } qDeleteAll( oldTransports ); oldTransports.clear(); // read default transport KConfigGroup group( d->config, "General" ); d->defaultTransportId = group.readEntry( "default-transport", 0 ); if ( d->defaultTransportId == 0 ) { // migrated default transport contains the name instead QString name = group.readEntry( "default-transport", QString() ); if ( !name.isEmpty() ) { Transport *t = transportByName( name, false ); if ( t ) { d->defaultTransportId = t->id(); writeConfig(); } } } validateDefault(); migrateToWallet(); } void TransportManager::writeConfig() { KConfigGroup group( d->config, "General" ); group.writeEntry( "default-transport", d->defaultTransportId ); d->config->sync(); emitChangesCommitted(); } void TransportManager::fillTypes() { Q_ASSERT( d->types.isEmpty() ); // SMTP. { TransportType type; type.d->mType = Transport::EnumType::SMTP; type.d->mName = i18nc( "@option SMTP transport", "SMTP" ); type.d->mDescription = i18n( "An SMTP server on the internet" ); d->types << type; } // Sendmail. { TransportType type; type.d->mType = Transport::EnumType::Sendmail; type.d->mName = i18nc( "@option sendmail transport", "Sendmail" ); type.d->mDescription = i18n( "A local sendmail installation" ); d->types << type; } // All Akonadi resources with MailTransport capability. { using namespace Akonadi; foreach( const AgentType &atype, AgentManager::self()->types() ) { // TODO probably the string "MailTransport" should be #defined somewhere // and used like that in the resources (?) if( atype.capabilities().contains( QLatin1String( "MailTransport" ) ) ) { TransportType type; type.d->mType = Transport::EnumType::Akonadi; type.d->mAgentType = atype; type.d->mName = atype.name(); type.d->mDescription = atype.description(); d->types << type; kDebug() << "Found Akonadi type" << atype.name(); } } // Watch for appearing and disappearing types. connect( AgentManager::self(), SIGNAL(typeAdded(Akonadi::AgentType)), this, SLOT(agentTypeAdded(Akonadi::AgentType)) ); connect( AgentManager::self(), SIGNAL(typeRemoved(Akonadi::AgentType)), this, SLOT(agentTypeRemoved(Akonadi::AgentType)) ); } kDebug() << "Have SMTP, Sendmail, and" << d->types.count() - 2 << "Akonadi types."; } void TransportManager::emitChangesCommitted() { d->myOwnChange = true; // prevent us from reading our changes again d->appliedChange = false; // but we have to read them at least once emit transportsChanged(); emit changesCommitted(); } void TransportManager::slotTransportsChanged() { if ( d->myOwnChange && d->appliedChange ) { d->myOwnChange = false; d->appliedChange = false; return; } kDebug(); d->config->reparseConfiguration(); // FIXME: this deletes existing transport objects! readConfig(); d->appliedChange = true; // to prevent recursion emit transportsChanged(); } int TransportManager::createId() const { QList usedIds; foreach ( Transport *t, d->transports ) { usedIds << t->id(); } usedIds << 0; // 0 is default for unknown int newId; do { newId = KRandom::random(); } while ( usedIds.contains( newId ) ); - kDebug() << "id" << newId; return newId; } KWallet::Wallet * TransportManager::wallet() { if ( d->wallet && d->wallet->isOpen() ) { return d->wallet; } if ( !Wallet::isEnabled() || d->walletOpenFailed ) { return 0; } WId window = 0; if ( qApp->activeWindow() ) { window = qApp->activeWindow()->winId(); } else if ( !QApplication::topLevelWidgets().isEmpty() ) { window = qApp->topLevelWidgets().first()->winId(); } delete d->wallet; d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window ); if ( !d->wallet ) { d->walletOpenFailed = true; return 0; } prepareWallet(); return d->wallet; } void TransportManager::prepareWallet() { if ( !d->wallet ) { return; } if ( !d->wallet->hasFolder( WALLET_FOLDER ) ) { d->wallet->createFolder( WALLET_FOLDER ); } d->wallet->setFolder( WALLET_FOLDER ); } void TransportManager::loadPasswords() { foreach ( Transport *t, d->transports ) { t->readPassword(); } // flush the wallet queue foreach ( TransportJob *job, d->walletQueue ) { job->start(); } d->walletQueue.clear(); emit passwordsChanged(); } void TransportManager::loadPasswordsAsync() { kDebug(); // check if there is anything to do at all bool found = false; foreach ( Transport *t, d->transports ) { if ( !t->isComplete() ) { found = true; break; } } if ( !found ) { return; } // async wallet opening if ( !d->wallet && !d->walletOpenFailed ) { WId window = 0; if ( qApp->activeWindow() ) { window = qApp->activeWindow()->winId(); } else if ( !QApplication::topLevelWidgets().isEmpty() ) { window = qApp->topLevelWidgets().first()->winId(); } d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window, Wallet::Asynchronous ); if ( d->wallet ) { connect( d->wallet, SIGNAL(walletOpened(bool)), SLOT(slotWalletOpened(bool)) ); d->walletAsyncOpen = true; } else { d->walletOpenFailed = true; loadPasswords(); } return; } if ( d->wallet && !d->walletAsyncOpen ) { loadPasswords(); } } void TransportManager::slotWalletOpened( bool success ) { kDebug(); d->walletAsyncOpen = false; if ( !success ) { d->walletOpenFailed = true; delete d->wallet; d->wallet = 0; } else { prepareWallet(); } loadPasswords(); } void TransportManager::validateDefault() { if ( !transportById( d->defaultTransportId, false ) ) { if ( isEmpty() ) { d->defaultTransportId = -1; } else { d->defaultTransportId = d->transports.first()->id(); writeConfig(); } } } void TransportManager::migrateToWallet() { // check if we tried this already static bool firstRun = true; if ( !firstRun ) { return; } firstRun = false; // check if we are the main instance if ( !d->isMainInstance ) { return; } // check if migration is needed QStringList names; foreach ( Transport *t, d->transports ) { if ( t->needsWalletMigration() ) { names << t->name(); } } if ( names.isEmpty() ) { return; } // ask user if he wants to migrate int result = KMessageBox::questionYesNoList( 0, i18n( "The following mail transports store their passwords in an " "unencrypted configuration file.\nFor security reasons, " "please consider migrating these passwords to KWallet, the " "KDE Wallet management tool,\nwhich stores sensitive data " "for you in a strongly encrypted file.\n" "Do you want to migrate your passwords to KWallet?" ), names, i18n( "Question" ), KGuiItem( i18n( "Migrate" ) ), KGuiItem( i18n( "Keep" ) ), QString::fromAscii( "WalletMigrate" ) ); if ( result != KMessageBox::Yes ) { return; } // perform migration foreach ( Transport *t, d->transports ) { if ( t->needsWalletMigration() ) { t->migrateToWallet(); } } } void TransportManager::dbusServiceOwnerChanged( const QString &service, const QString &oldOwner, const QString &newOwner ) { Q_UNUSED( oldOwner ); if ( service == DBUS_SERVICE_NAME && newOwner.isEmpty() ) { QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); } } void TransportManager::agentTypeAdded( const Akonadi::AgentType &atype ) { using namespace Akonadi; if( atype.capabilities().contains( QLatin1String( "MailTransport" ) ) ) { TransportType type; type.d->mType = Transport::EnumType::Akonadi; type.d->mAgentType = atype; type.d->mName = atype.name(); type.d->mDescription = atype.description(); d->types << type; kDebug() << "Added new Akonadi type" << atype.name(); } } void TransportManager::agentTypeRemoved( const Akonadi::AgentType &atype ) { using namespace Akonadi; foreach( const TransportType &type, d->types ) { if( type.type() == Transport::EnumType::Akonadi && type.agentType() == atype ) { d->types.removeAll( type ); kDebug() << "Removed Akonadi type" << atype.name(); } } } void TransportManager::jobResult( KJob *job ) { d->walletQueue.removeAll( static_cast( job ) ); } #include "transportmanager.moc" diff --git a/mailtransport/transportmanager.h b/mailtransport/transportmanager.h index eae93917b..ba1ac1fc3 100644 --- a/mailtransport/transportmanager.h +++ b/mailtransport/transportmanager.h @@ -1,285 +1,299 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTMANAGER_H #define MAILTRANSPORT_TRANSPORTMANAGER_H #include #include #include #include #include class KJob; namespace KWallet { class Wallet; } namespace MailTransport { class Transport; class TransportConfigWidget; class TransportJob; /** - Takes care of loading and storing mail transport settings and - creating of transport jobs. + @short Central transport management interface. + + This class manages the creation, configuration, and removal of mail + transports, as well as the loading and storing of mail transport settings, + and creation of transport jobs. */ class MAILTRANSPORT_EXPORT TransportManager : public QObject { Q_OBJECT Q_CLASSINFO( "D-Bus Interface", "org.kde.pim.TransportManager" ) friend class Transport; friend class Private; public: class Private; /** Destructor. */ virtual ~TransportManager(); /** Returns the TransportManager instance. */ static TransportManager *self(); /** Tries to load passwords asynchronously from KWallet if needed. The passwordsChanged() signal is emitted once the passwords have been loaded. Nothing happens if the passwords were already available. */ void loadPasswordsAsync(); /** Returns the Transport object with the given id. @param id The identifier of the Transport. @param def if set to true, the default transport will be returned if the specified Transport object could not be found, 0 otherwise. @returns A Transport object for immediate use. It might become invalid as soon as the event loop is entered again due to remote changes. If you need to store a Transport object, store the transport identifier instead. */ Transport *transportById( int id, bool def = true ) const; /** Returns the transport object with the given name. @param name The transport name. @param def if set to true, the default transport will be returned if the specified Transport object could not be found, 0 otherwise. @returns A Transport object for immediate use, see transportById() for limitations. */ Transport *transportByName( const QString &name, bool def = true ) const; /** Returns a list of all available transports. Note: The Transport objects become invalid as soon as a change occur, so they are only suitable for immediate use. */ QListtransports() const; /** Returns a list of all available transport types. */ const TransportType::List &types() const; /** Creates a new, empty Transport object. The object is owned by the caller. If you want to add the Transport permanently (eg. after configuring it) call addTransport(). */ Transport *createTransport() const; /** Adds the given transport. The object ownership is transferred to TransportMananger, ie. you must not delete @p transport. @param transport The Transport object to add. */ void addTransport( Transport *transport ); /** Creates a mail transport job for the given transport identifier. Returns 0 if the specified transport is invalid. @param transportId The transport identifier. */ TransportJob *createTransportJob( int transportId ); /** Creates a mail transport job for the given transport identifer, or transport name. Returns 0 if the specified transport is invalid. @param transport A string defining a mail transport. */ TransportJob *createTransportJob( const QString &transport ); /** Executes the given transport job. This is the preferred way to start transport jobs. It takes care of asynchronously loading passwords from KWallet if necessary. @param job The completely configured transport job to execute. */ void schedule( TransportJob *job ); /** Tries to create a transport based on KEMailSettings. If the data in KEMailSettings is incomplete, no transport is created. */ void createDefaultTransport(); + /** + Shows a dialog for creating and configuring a new transport. + @param parent Parent widget of the dialog. + @return True if a new transport has been created and configured. + @since 4.4 + */ + bool showNewTransportDialog( QWidget *parent ); + /** If no transport exists, asks the user to create and configure one. Returns true if a transport exists or the user created one. Otherwise returns false. @param parent Parent widget of the dialog. @since 4.4 */ bool promptCreateTransportIfNoneExists( QWidget *parent ); /** Open a configuration dialog for an existing transport. @param transport The transport to configure. It can be a new transport, or one already managed by TransportManager. @param parent The parent widget for the dialog. @return True if the user clicked Ok, false if the user cancelled. @since 4.4 */ bool configureTransport( Transport *transport, QWidget *parent ); public Q_SLOTS: /** Returns true if there are no mail transports at all. */ Q_SCRIPTABLE bool isEmpty() const; /** Returns a list of transport identifiers. */ Q_SCRIPTABLE QList transportIds() const; /** Returns a list of transport names. */ Q_SCRIPTABLE QStringList transportNames() const; /** Returns the default transport name. */ Q_SCRIPTABLE QString defaultTransportName() const; /** Returns the default transport identifier. Invalid if there are no transports at all. */ Q_SCRIPTABLE int defaultTransportId() const; /** Sets the default transport. The change will be in effect immediately. @param id The identifier of the new default transport. */ Q_SCRIPTABLE void setDefaultTransport( int id ); /** Deletes the specified transport. @param id The identifier of the mail transport to remove. */ Q_SCRIPTABLE void removeTransport( int id ); Q_SIGNALS: /** Emitted when transport settings have changed (by this or any other TransportManager instance). */ Q_SCRIPTABLE void transportsChanged(); /** Internal signal to synchronize all TransportManager instances. This signal is emitted by the instance writing the changes. You probably want to use transportsChanged() instead. */ Q_SCRIPTABLE void changesCommitted(); /** Emitted when passwords have been loaded from the wallet. If you made a deep copy of a transport, you should call updatePasswordState() for the cloned transport to ensure its password is updated as well. */ void passwordsChanged(); /** Emitted when a transport is deleted. @param id The identifier of the deleted transport. @param name The name of the deleted transport. */ void transportRemoved( int id, const QString &name ); /** Emitted when a transport has been renamed. @param id The identifier of the renamed transport. @param oldName The old name. @param newName The new name. */ void transportRenamed( int id, const QString &oldName, const QString &newName ); protected: /** Returns a pointer to an open wallet if available, 0 otherwise. The wallet is opened synchronously if necessary. */ KWallet::Wallet *wallet(); /** Loads all passwords synchronously. */ void loadPasswords(); + /** + Singleton class, the only instance resides in the static object sSelf. + */ TransportManager(); private: void readConfig(); void writeConfig(); void fillTypes(); void emitChangesCommitted(); int createId() const; void prepareWallet(); void validateDefault(); void migrateToWallet(); private Q_SLOTS: void slotTransportsChanged(); void slotWalletOpened( bool success ); void dbusServiceOwnerChanged( const QString &service, const QString &oldOwner, const QString &newOwner ); void agentTypeAdded( const Akonadi::AgentType &atype ); void agentTypeRemoved( const Akonadi::AgentType &atype ); void jobResult( KJob *job ); private: Private *const d; }; -} +} // namespace MailTransport -#endif +#endif // MAILTRANSPORT_TRANSPORTMANAGER_H diff --git a/mailtransport/transporttype.cpp b/mailtransport/transporttype.cpp index 3446f9b1c..f62cd6062 100644 --- a/mailtransport/transporttype.cpp +++ b/mailtransport/transporttype.cpp @@ -1,82 +1,90 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "transporttype.h" #include "transporttype_p.h" #include "transport.h" #include using namespace MailTransport; TransportType::TransportType() : d( new Private ) { } TransportType::TransportType( const TransportType &other ) : d( other.d ) { } TransportType::~TransportType() { } +TransportType& TransportType::operator=( const TransportType &other ) +{ + if( this != &other ) { + d = other.d; + } + return *this; +} + bool TransportType::operator==( const TransportType &other ) const { if( d->mType == Transport::EnumType::Akonadi && other.d->mType == Transport::EnumType::Akonadi ) { return ( d->mAgentType == other.d->mAgentType ); } return ( d->mType == other.d->mType ); } bool TransportType::isValid() const { using namespace Akonadi; if( d->mType == Transport::EnumType::Akonadi ) { return d->mAgentType.isValid() && AgentManager::self()->types().contains( d->mAgentType ); } else { return d->mType >= 0; } } int TransportType::type() const { return d->mType; } QString TransportType::name() const { return d->mName; } QString TransportType::description() const { return d->mDescription; } Akonadi::AgentType TransportType::agentType() const { Q_ASSERT( d->mType == Transport::EnumType::Akonadi ); return d->mAgentType; } diff --git a/mailtransport/transporttype.h b/mailtransport/transporttype.h index d8548b8c9..76b90218f 100644 --- a/mailtransport/transporttype.h +++ b/mailtransport/transporttype.h @@ -1,74 +1,128 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTTYPE_H #define MAILTRANSPORT_TRANSPORTTYPE_H #include "mailtransport_export.h" #include "transport.h" #include #include namespace MailTransport { class AddTransportDialog; class TransportManager; /** - A representation of a transport type. + @short A representation of a transport type. - TODO docu look at Akonadi::AgentType + Represents an available transport type. SMTP and Sendmail are available, + as well as a number of Akonadi-based types. Each Akonadi-based type + corresponds to an Akonadi resource type that supports sending messages. + + This class provides information about the type, such as name and + description. Additionally, for Akonadi types, it provides the corresponding + Akonadi AgentType. + + All available transport types can be retrieved via TransportManager::types(). + + @author Constantin Berzan + @since 4.4 */ class MAILTRANSPORT_EXPORT TransportType { friend class AddTransportDialog; friend class Transport; friend class TransportManager; public: + /** + Describes a list of transport types. + */ typedef QList List; + /** + Constructs a new TransportType. + */ TransportType(); + + /** + Creates a copy of the @p other TransportType. + */ TransportType( const TransportType &other ); + + /** + Destroys the TransportType. + */ ~TransportType(); + + /** + @internal + */ + TransportType& operator=( const TransportType &other ); + + /** + @internal + Compares two transport types. + */ bool operator==( const TransportType &other ) const; + /** + Returns whether the transport type is valid. + */ bool isValid() const; + /** + @internal + Returns the numeric type of the transport. This corresponds to + Transport::EnumType::type. + */ // TODO should this be Transport::EnumType::type instead of int? int type() const; + + /** + Returns the i18n'ed name of the transport type. + */ QString name() const; + + /** + Returns a description of the transport type. + */ QString description() const; - /// only valid if this is an Akonadi transport + /** + Returns the corresponding Akonadi::AgentType that this transport type + represents. Only valid if type() is Transport::EnumType::Akonadi. + */ Akonadi::AgentType agentType() const; private: class Private; QSharedDataPointer d; }; -} +} // namespace MailTransport Q_DECLARE_METATYPE( MailTransport::TransportType ) -#endif +#endif // MAILTRANSPORT_TRANSPORTTYPE_H diff --git a/mailtransport/transporttype_p.h b/mailtransport/transporttype_p.h index 82620c023..407d191ca 100644 --- a/mailtransport/transporttype_p.h +++ b/mailtransport/transporttype_p.h @@ -1,59 +1,58 @@ /* Copyright (c) 2009 Constantin Berzan This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAILTRANSPORT_TRANSPORTTYPE_P_H #define MAILTRANSPORT_TRANSPORTTYPE_P_H #include #include #include -namespace MailTransport -{ +namespace MailTransport { /** @internal */ class TransportType::Private : public QSharedData { public: Private() { mType = -1; } Private( const Private &other ) : QSharedData( other ) { mType = other.mType; mName = other.mName; mDescription = other.mDescription; mAgentType = other.mAgentType; } int mType; QString mName; QString mDescription; Akonadi::AgentType mAgentType; }; -} +} // namespace MailTransport -#endif +#endif //MAILTRANSPORT_TRANSPORTTYPE_P_H