24 #include "transport.h"
26 #include "precommandjob.h"
27 #include "smtp/smtpsession.h"
33 #include <KLocalizedString>
37 #include <KIO/Scheduler>
38 #include <KPasswordDialog>
40 using namespace MailTransport;
45 SlavePool() : ref( 0 ) {}
47 QHash<int, KIO::Slave*> slaves;
49 void removeSlave( KIO::Slave *slave,
bool disconnect =
false )
51 kDebug() <<
"Removing slave" << slave <<
"from pool";
52 const int slaveKey = slaves.key( slave );
54 slaves.remove( slaveKey );
56 KIO::Scheduler::disconnectSlave( slave );
62 K_GLOBAL_STATIC( SlavePool, s_slavePool )
71 SmtpJobPrivate(
SmtpJob *parent ) : q( parent ) {}
75 #ifndef MAILTRANSPORT_INPROCESS_SMTP
79 q->setError( KJob::UserDefinedError );
89 Idle, Precommand, Smtp
95 :
TransportJob( transport, parent ), d( new SmtpJobPrivate( this ) )
97 d->currentState = SmtpJobPrivate::Idle;
100 if ( !s_slavePool.isDestroyed() ) {
103 KIO::Scheduler::connect( SIGNAL(slaveError(KIO::Slave*,
int,QString)),
104 this, SLOT(slaveError(KIO::Slave*,
int,QString)) );
109 if ( !s_slavePool.isDestroyed() ) {
111 if ( s_slavePool->ref == 0 ) {
112 kDebug() <<
"clearing SMTP slave pool" << s_slavePool->slaves.count();
113 foreach ( KIO::Slave *slave, s_slavePool->slaves ) {
115 KIO::Scheduler::disconnectSlave( slave );
118 s_slavePool->slaves.clear();
126 if ( s_slavePool.isDestroyed() ) {
130 if ( ( !s_slavePool->slaves.isEmpty() &&
131 s_slavePool->slaves.contains(
transport()->
id() ) ) ||
133 d->currentState = SmtpJobPrivate::Smtp;
136 d->currentState = SmtpJobPrivate::Precommand;
143 void SmtpJob::startSmtpJob()
145 if ( s_slavePool.isDestroyed() ) {
150 destination.setProtocol( (
transport()->encryption() == Transport::EnumEncryption::SSL ) ?
151 SMTPS_PROTOCOL : SMTP_PROTOCOL );
152 destination.setHost(
transport()->host().trimmed() );
153 destination.setPort(
transport()->port() );
155 destination.addQueryItem( QLatin1String(
"headers" ), QLatin1String(
"0" ) );
156 destination.addQueryItem( QLatin1String(
"from" ),
sender() );
158 foreach (
const QString &str,
to() ) {
159 destination.addQueryItem( QLatin1String(
"to" ), str );
161 foreach (
const QString &str,
cc() ) {
162 destination.addQueryItem( QLatin1String(
"cc" ), str );
164 foreach (
const QString &str,
bcc() ) {
165 destination.addQueryItem( QLatin1String(
"bcc" ), str );
169 destination.addQueryItem( QLatin1String(
"hostname" ),
transport()->localHostname() );
172 if (
transport()->requiresAuthentication() ) {
175 if ( ( user.isEmpty() || passwd.isEmpty() ) &&
176 transport()->authenticationType() != Transport::EnumAuthenticationType::GSSAPI ) {
178 QPointer<KPasswordDialog> dlg =
181 KPasswordDialog::ShowUsernameLine |
182 KPasswordDialog::ShowKeepPassword );
183 dlg->setPrompt( i18n(
"You need to supply a username and a password "
184 "to use this SMTP server." ) );
185 dlg->setKeepPassword(
transport()->storePassword() );
186 dlg->addCommentLine( QString(),
transport()->name() );
187 dlg->setUsername( user );
188 dlg->setPassword( passwd );
192 transport()->setUserName( dlg->username() );
194 transport()->setStorePassword( dlg->keepPassword() );
201 setError( KilledJobError );
206 destination.setUser(
transport()->userName() );
207 destination.setPass(
transport()->password() );
211 if ( !
data().isEmpty() ) {
214 destination.addQueryItem( QLatin1String(
"size" ),
215 QString::number( qRound(
data().length() * 1.05 ) ) );
218 destination.setPath( QLatin1String(
"/send" ) );
220 #ifndef MAILTRANSPORT_INPROCESS_SMTP
221 d->slave = s_slavePool->slaves.value(
transport()->
id() );
223 KIO::MetaData slaveConfig;
224 slaveConfig.insert( QLatin1String(
"tls" ),
225 (
transport()->encryption() == Transport::EnumEncryption::TLS ) ?
226 QLatin1String(
"on" ) : QLatin1String(
"off" ) );
227 if (
transport()->requiresAuthentication() ) {
228 slaveConfig.insert( QLatin1String(
"sasl" ),
transport()->authenticationTypeString() );
230 d->slave = KIO::Scheduler::getConnectedSlave( destination, slaveConfig );
231 kDebug() <<
"Created new SMTP slave" << d->slave;
232 s_slavePool->slaves.insert(
transport()->
id(), d->slave );
234 kDebug() <<
"Re-using existing slave" << d->slave;
237 KIO::TransferJob *job = KIO::put( destination, -1, KIO::HideProgressInfo );
238 if ( !d->slave || !job ) {
239 setError( UserDefinedError );
240 setErrorText( i18n(
"Unable to create SMTP job." ) );
245 job->addMetaData( QLatin1String(
"lf2crlf+dotstuff" ), QLatin1String(
"slave" ) );
246 connect( job, SIGNAL(dataReq(KIO::Job*,QByteArray&)),
247 SLOT(dataRequest(KIO::Job*,QByteArray&)) );
250 KIO::Scheduler::assignJobToSlave( d->slave, job );
256 if (
transport()->requiresAuthentication() ) {
262 setTotalAmount( KJob::Bytes,
data().length() );
265 bool SmtpJob::doKill()
267 if ( s_slavePool.isDestroyed() ) {
271 if ( !hasSubjobs() ) {
274 if ( d->currentState == SmtpJobPrivate::Precommand ) {
275 return subjobs().first()->kill();
276 }
else if ( d->currentState == SmtpJobPrivate::Smtp ) {
277 KIO::SimpleJob *job =
static_cast<KIO::SimpleJob*
>( subjobs().first() );
279 KIO::Scheduler::cancelJob( job );
280 s_slavePool->removeSlave( d->slave );
286 void SmtpJob::slotResult( KJob *job )
288 if ( s_slavePool.isDestroyed() ) {
313 int errorCode = error();
315 errorCode = job->error();
318 if ( errorCode && d->currentState == SmtpJobPrivate::Smtp ) {
319 s_slavePool->removeSlave( d->slave, errorCode != KIO::ERR_SLAVE_DIED );
320 TransportJob::slotResult( job );
324 TransportJob::slotResult( job );
325 if ( !error() && d->currentState == SmtpJobPrivate::Precommand ) {
326 d->currentState = SmtpJobPrivate::Smtp;
335 void SmtpJob::dataRequest( KIO::Job *job, QByteArray &data )
337 if ( s_slavePool.isDestroyed() ) {
343 if (
buffer()->atEnd() ) {
346 Q_ASSERT(
buffer()->isOpen() );
347 data =
buffer()->read( 32 * 1024 );
349 setProcessedAmount( KJob::Bytes,
buffer()->pos() );
352 void SmtpJob::slaveError( KIO::Slave *slave,
int errorCode,
const QString &errorMsg )
354 if ( s_slavePool.isDestroyed() ) {
358 s_slavePool->removeSlave( slave, errorCode != KIO::ERR_SLAVE_DIED );
359 if ( d->slave == slave && !d->finished ) {
360 setError( errorCode );
361 setErrorText( KIO::buildErrorString( errorCode, errorMsg ) );
366 #include "moc_smtpjob.cpp"