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"