24 #include "transport.h"
26 #include "precommandjob.h"
27 #include "smtp/smtpsession.h"
33 #include <KLocalizedString>
36 #include <KIO/Scheduler>
37 #include <KPasswordDialog>
39 using namespace MailTransport;
44 SlavePool() : ref( 0 ) {}
46 QHash<int, KIO::Slave*> slaves;
48 void removeSlave( KIO::Slave *slave,
bool disconnect =
false )
50 kDebug() <<
"Removing slave" << slave <<
"from pool";
51 const int slaveKey = slaves.key( slave );
53 slaves.remove( slaveKey );
55 KIO::Scheduler::disconnectSlave( slave );
61 K_GLOBAL_STATIC( SlavePool, s_slavePool )
70 SmtpJobPrivate(
SmtpJob *parent ) : q( parent ) {}
74 #ifndef MAILTRANSPORT_INPROCESS_SMTP
78 q->setError( KJob::UserDefinedError );
88 Idle, Precommand, Smtp
94 :
TransportJob( transport, parent ), d( new SmtpJobPrivate( this ) )
96 d->currentState = SmtpJobPrivate::Idle;
99 if ( !s_slavePool.isDestroyed() ) {
102 KIO::Scheduler::connect( SIGNAL(slaveError(KIO::Slave*,
int,QString)),
103 this, SLOT(slaveError(KIO::Slave*,
int,QString)) );
108 if ( !s_slavePool.isDestroyed() ) {
110 if ( s_slavePool->ref == 0 ) {
111 kDebug() <<
"clearing SMTP slave pool" << s_slavePool->slaves.count();
112 foreach ( KIO::Slave *slave, s_slavePool->slaves ) {
114 KIO::Scheduler::disconnectSlave( slave );
117 s_slavePool->slaves.clear();
125 if ( s_slavePool.isDestroyed() ) {
129 if ( ( !s_slavePool->slaves.isEmpty() &&
130 s_slavePool->slaves.contains(
transport()->
id() ) ) ||
132 d->currentState = SmtpJobPrivate::Smtp;
135 d->currentState = SmtpJobPrivate::Precommand;
142 void SmtpJob::startSmtpJob()
144 if ( s_slavePool.isDestroyed() ) {
149 destination.setProtocol( (
transport()->encryption() == Transport::EnumEncryption::SSL ) ?
150 SMTPS_PROTOCOL : SMTP_PROTOCOL );
151 destination.setHost(
transport()->host().trimmed() );
152 destination.setPort(
transport()->port() );
154 destination.addQueryItem( QLatin1String(
"headers" ), QLatin1String(
"0" ) );
155 destination.addQueryItem( QLatin1String(
"from" ),
sender() );
157 foreach (
const QString &str,
to() ) {
158 destination.addQueryItem( QLatin1String(
"to" ), str );
160 foreach (
const QString &str,
cc() ) {
161 destination.addQueryItem( QLatin1String(
"cc" ), str );
163 foreach (
const QString &str,
bcc() ) {
164 destination.addQueryItem( QLatin1String(
"bcc" ), str );
168 destination.addQueryItem( QLatin1String(
"hostname" ),
transport()->localHostname() );
171 if (
transport()->requiresAuthentication() ) {
174 if ( ( user.isEmpty() || passwd.isEmpty() ) &&
175 transport()->authenticationType() != Transport::EnumAuthenticationType::GSSAPI ) {
177 QPointer<KPasswordDialog> dlg =
180 KPasswordDialog::ShowUsernameLine |
181 KPasswordDialog::ShowKeepPassword );
182 dlg->setPrompt( i18n(
"You need to supply a username and a password "
183 "to use this SMTP server." ) );
184 dlg->setKeepPassword(
transport()->storePassword() );
185 dlg->addCommentLine( QString(),
transport()->name() );
186 dlg->setUsername( user );
187 dlg->setPassword( passwd );
191 transport()->setUserName( dlg->username() );
193 transport()->setStorePassword( dlg->keepPassword() );
200 setError( KilledJobError );
205 destination.setUser(
transport()->userName() );
206 destination.setPass(
transport()->password() );
210 if ( !
data().isEmpty() ) {
213 destination.addQueryItem( QLatin1String(
"size" ),
214 QString::number( qRound(
data().length() * 1.05 ) ) );
217 destination.setPath( QLatin1String(
"/send" ) );
219 #ifndef MAILTRANSPORT_INPROCESS_SMTP
220 d->slave = s_slavePool->slaves.value(
transport()->
id() );
222 KIO::MetaData slaveConfig;
223 slaveConfig.insert( QLatin1String(
"tls" ),
224 (
transport()->encryption() == Transport::EnumEncryption::TLS ) ?
225 QLatin1String(
"on" ) : QLatin1String(
"off" ) );
226 if (
transport()->requiresAuthentication() ) {
227 slaveConfig.insert( QLatin1String(
"sasl" ),
transport()->authenticationTypeString() );
229 d->slave = KIO::Scheduler::getConnectedSlave( destination, slaveConfig );
230 kDebug() <<
"Created new SMTP slave" << d->slave;
231 s_slavePool->slaves.insert(
transport()->
id(), d->slave );
233 kDebug() <<
"Re-using existing slave" << d->slave;
236 KIO::TransferJob *job = KIO::put( destination, -1, KIO::HideProgressInfo );
237 if ( !d->slave || !job ) {
238 setError( UserDefinedError );
239 setErrorText( i18n(
"Unable to create SMTP job." ) );
244 job->addMetaData( QLatin1String(
"lf2crlf+dotstuff" ), QLatin1String(
"slave" ) );
245 connect( job, SIGNAL(dataReq(KIO::Job*,QByteArray&)),
246 SLOT(dataRequest(KIO::Job*,QByteArray&)) );
249 KIO::Scheduler::assignJobToSlave( d->slave, job );
255 if (
transport()->requiresAuthentication() ) {
261 setTotalAmount( KJob::Bytes,
data().length() );
264 bool SmtpJob::doKill()
266 if ( s_slavePool.isDestroyed() ) {
270 if ( !hasSubjobs() ) {
273 if ( d->currentState == SmtpJobPrivate::Precommand ) {
274 return subjobs().first()->kill();
275 }
else if ( d->currentState == SmtpJobPrivate::Smtp ) {
276 KIO::SimpleJob *job =
static_cast<KIO::SimpleJob*
>( subjobs().first() );
278 KIO::Scheduler::cancelJob( job );
279 s_slavePool->removeSlave( d->slave );
285 void SmtpJob::slotResult( KJob *job )
287 if ( s_slavePool.isDestroyed() ) {
312 int errorCode = error();
314 errorCode = job->error();
317 if ( errorCode && d->currentState == SmtpJobPrivate::Smtp ) {
318 s_slavePool->removeSlave( d->slave, errorCode != KIO::ERR_SLAVE_DIED );
319 TransportJob::slotResult( job );
323 TransportJob::slotResult( job );
324 if ( !error() && d->currentState == SmtpJobPrivate::Precommand ) {
325 d->currentState = SmtpJobPrivate::Smtp;
334 void SmtpJob::dataRequest( KIO::Job *job, QByteArray &data )
336 if ( s_slavePool.isDestroyed() ) {
342 if (
buffer()->atEnd() ) {
345 Q_ASSERT(
buffer()->isOpen() );
346 data =
buffer()->read( 32 * 1024 );
348 setProcessedAmount( KJob::Bytes,
buffer()->pos() );
351 void SmtpJob::slaveError( KIO::Slave *slave,
int errorCode,
const QString &errorMsg )
353 if ( s_slavePool.isDestroyed() ) {
357 s_slavePool->removeSlave( slave, errorCode != KIO::ERR_SLAVE_DIED );
358 if ( d->slave == slave && !d->finished ) {
359 setError( errorCode );
360 setErrorText( KIO::buildErrorString( errorCode, errorMsg ) );
365 #include "moc_smtpjob.cpp"
QStringList bcc() const
Returns the "Bcc" receiver(s) of the mail.
void setPassword(const QString &passwd)
Sets the password of this transport.
QString password()
Returns the password of this transport.
Connection to an SMTP server.
Mail transport job for SMTP.
virtual void start()
Executes the precommand.
void setSaslMethod(const QString &method)
Sets the SASL method used for authentication.
Job to execute a command.
void setUseTLS(bool useTLS)
Enable TLS encryption.
QStringList cc() const
Returns the "Cc" receiver(s) of the mail.
SmtpJob(Transport *transport, QObject *parent=0)
Creates a SmtpJob.
QString sender() const
Returns the sender of the mail.
Abstract base class for all mail transport jobs.
QByteArray data() const
Returns the data of the mail.
virtual void doStart()
Do the actual work, implement in your subclass.
QString errorMessage() const
Returns the error nmeesage, if any.
Internal file containing constant definitions etc.
Represents the settings of a specific mail transport.
QStringList to() const
Returns the "To" receiver(s) of the mail.
void sendMessage(const KUrl &destination, QIODevice *data)
Send a message.
virtual ~SmtpJob()
Deletes this job.
Transport * transport() const
Returns the Transport object containing the mail transport settings.
QBuffer * buffer()
Returns a QBuffer opened on the message data.