00001 #include "smtpwrapper.h"
00002 #include "mailwrapper.h"
00003 #include "abstractmail.h"
00004 #include "logindialog.h"
00005 #include "mailtypes.h"
00006 #include "sendmailprogress.h"
00007
00008 #include <opie2/odebug.h>
00009 #include <qt.h>
00010
00011 #include <qpe/config.h>
00012 #include <qpe/qcopenvelope_qws.h>
00013
00014 #include <libetpan/libetpan.h>
00015
00016
00017 using namespace Opie::Core;
00018 progressMailSend*SMTPwrapper::sendProgress = 0;
00019
00020 SMTPwrapper::SMTPwrapper(SMTPaccount * aSmtp )
00021 : Generatemail()
00022 {
00023 m_SmtpAccount = aSmtp;
00024 Config cfg( "mail" );
00025 cfg.setGroup( "Status" );
00026 m_queuedMail = cfg.readNumEntry( "outgoing", 0 );
00027 emit queuedMails( m_queuedMail );
00028 connect( this, SIGNAL( queuedMails(int) ), this, SLOT( emitQCop(int) ) );
00029 m_smtp = 0;
00030 }
00031
00032 SMTPwrapper::~SMTPwrapper()
00033 {
00034 disc_server();
00035 }
00036
00037 void SMTPwrapper::emitQCop( int queued ) {
00038 QCopEnvelope env( "QPE/Pim", "outgoingMails(int)" );
00039 env << queued;
00040 }
00041
00042 QString SMTPwrapper::mailsmtpError( int errnum ) {
00043 switch ( errnum ) {
00044 case MAILSMTP_NO_ERROR:
00045 return tr( "No error" );
00046 case MAILSMTP_ERROR_UNEXPECTED_CODE:
00047 return tr( "Unexpected error code" );
00048 case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE:
00049 return tr( "Service not available" );
00050 case MAILSMTP_ERROR_STREAM:
00051 return tr( "Stream error" );
00052 case MAILSMTP_ERROR_HOSTNAME:
00053 return tr( "gethostname() failed" );
00054 case MAILSMTP_ERROR_NOT_IMPLEMENTED:
00055 return tr( "Not implemented" );
00056 case MAILSMTP_ERROR_ACTION_NOT_TAKEN:
00057 return tr( "Error, action not taken" );
00058 case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION:
00059 return tr( "Data exceeds storage allocation" );
00060 case MAILSMTP_ERROR_IN_PROCESSING:
00061 return tr( "Error in processing" );
00062 case MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED:
00063 return tr( "Starttls not supported" );
00064
00065
00066 case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE:
00067 return tr( "Mailbox unavailable" );
00068 case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED:
00069 return tr( "Mailbox name not allowed" );
00070 case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND:
00071 return tr( "Bad command sequence" );
00072 case MAILSMTP_ERROR_USER_NOT_LOCAL:
00073 return tr( "User not local" );
00074 case MAILSMTP_ERROR_TRANSACTION_FAILED:
00075 return tr( "Transaction failed" );
00076 case MAILSMTP_ERROR_MEMORY:
00077 return tr( "Memory error" );
00078 case MAILSMTP_ERROR_CONNECTION_REFUSED:
00079 return tr( "Connection refused" );
00080 default:
00081 return tr( "Unknown error code" );
00082 }
00083 }
00084
00085
00086 void SMTPwrapper::progress( size_t current, size_t maximum ) {
00087 if (SMTPwrapper::sendProgress) {
00088 SMTPwrapper::sendProgress->setSingleMail(current, maximum );
00089 qApp->processEvents();
00090 }
00091 }
00092
00093 void SMTPwrapper::storeMail(const char*mail, size_t length, const QString&box) {
00094 if (!mail)
00095 return;
00096 QString localfolders = AbstractMail::defaultLocalfolder();
00097 AbstractMail*wrap = AbstractMail::getWrapper(localfolders);
00098 wrap->createMbox(box);
00099 wrap->storeMessage(mail,length,box);
00100 delete wrap;
00101 }
00102
00103 void SMTPwrapper::smtpSend( mailmime *mail,bool later) {
00104 clist *rcpts = 0;
00105 char *from, *data;
00106 size_t size;
00107
00108 from = data = 0;
00109
00110 mailmessage * msg = 0;
00111 msg = mime_message_init(mail);
00112 mime_message_set_tmpdir(msg,getenv( "HOME" ));
00113 int r = mailmessage_fetch(msg,&data,&size);
00114 mime_message_detach_mime(msg);
00115 mailmessage_free(msg);
00116 if (r != MAIL_NO_ERROR || !data) {
00117 if (data)
00118 free(data);
00119 odebug << "Error fetching mime..." << oendl;
00120 return;
00121 }
00122 msg = 0;
00123 if (later) {
00124 storeMail(data,size,"Outgoing");
00125 if (data)
00126 free( data );
00127 Config cfg( "mail" );
00128 cfg.setGroup( "Status" );
00129 cfg.writeEntry( "outgoing", ++m_queuedMail );
00130 emit queuedMails( m_queuedMail );
00131 return;
00132 }
00133 from = getFrom( mail );
00134 rcpts = createRcptList( mail->mm_data.mm_message.mm_fields );
00135 smtpSend(from,rcpts,data,size);
00136 if (data) {
00137 free(data);
00138 }
00139 if (from) {
00140 free(from);
00141 }
00142 if (rcpts)
00143 smtp_address_list_free( rcpts );
00144 }
00145
00146 void SMTPwrapper::storeFailedMail(const char*data,unsigned int size, const char*failuremessage)
00147 {
00148 if (data) {
00149 storeMail(data,size,"Sendfailed");
00150 }
00151 if (failuremessage) {
00152 QMessageBox::critical(0,tr("Error sending mail"),
00153 tr("<center>%1</center>").arg(failuremessage));
00154 }
00155 }
00156
00157 int SMTPwrapper::start_smtp_tls()
00158 {
00159 if (!m_smtp) {
00160 return MAILSMTP_ERROR_IN_PROCESSING;
00161 }
00162 int err = mailesmtp_starttls(m_smtp);
00163 if (err != MAILSMTP_NO_ERROR) return err;
00164 mailstream_low * low;
00165 mailstream_low * new_low;
00166 low = mailstream_get_low(m_smtp->stream);
00167 if (!low) {
00168 return MAILSMTP_ERROR_IN_PROCESSING;
00169 }
00170 int fd = mailstream_low_get_fd(low);
00171 if (fd > -1 && (new_low = mailstream_low_ssl_open(fd))!=0) {
00172 mailstream_low_free(low);
00173 mailstream_set_low(m_smtp->stream, new_low);
00174 } else {
00175 return MAILSMTP_ERROR_IN_PROCESSING;
00176 }
00177 return err;
00178 }
00179
00180 void SMTPwrapper::connect_server()
00181 {
00182 const char *server, *user, *pass;
00183 bool ssl;
00184 uint16_t port;
00185 ssl = false;
00186 bool try_tls = true;
00187 bool force_tls=false;
00188 server = user = pass = 0;
00189 QString failuretext = "";
00190
00191 if (m_smtp || !m_SmtpAccount) {
00192 return;
00193 }
00194 server = m_SmtpAccount->getServer().latin1();
00195 if ( m_SmtpAccount->ConnectionType() == 2 ) {
00196 ssl = true;
00197 try_tls = false;
00198 } else if (m_SmtpAccount->ConnectionType() == 1) {
00199 force_tls = true;
00200 }
00201 int result = 1;
00202 port = m_SmtpAccount->getPort().toUInt();
00203
00204 m_smtp = mailsmtp_new( 20, &progress );
00205 if ( m_smtp == NULL ) {
00206
00207
00208 return;
00209 }
00210
00211 int err = MAILSMTP_NO_ERROR;
00212 odebug << "Servername " << server << " at port " << port << "" << oendl;
00213 if ( ssl ) {
00214 odebug << "SSL session" << oendl;
00215 err = mailsmtp_ssl_connect( m_smtp, server, port );
00216 } else {
00217 odebug << "No SSL session" << oendl;
00218 err = mailsmtp_socket_connect( m_smtp, server, port );
00219 }
00220 if ( err != MAILSMTP_NO_ERROR ) {
00221 odebug << "Error init connection" << oendl;
00222 failuretext = tr("Error init SMTP connection: %1").arg(mailsmtpError(err));
00223 result = 0;
00224 }
00225
00226
00227 if (result) {
00228 err = mailsmtp_init( m_smtp );
00229 if (err != MAILSMTP_NO_ERROR) {
00230 result = 0;
00231 failuretext = tr("Error init SMTP connection: %1").arg(mailsmtpError(err));
00232 }
00233 }
00234
00235 if (try_tls) {
00236 err = start_smtp_tls();
00237 if (err != MAILSMTP_NO_ERROR) {
00238 try_tls = false;
00239 } else {
00240 err = mailesmtp_ehlo(m_smtp);
00241 }
00242 }
00243
00244 if (!try_tls && force_tls) {
00245 result = 0;
00246 failuretext = tr("Error init SMTP tls: %1").arg(mailsmtpError(err));
00247 }
00248
00249 if (result==1 && m_SmtpAccount->getLogin() ) {
00250 odebug << "smtp with auth" << oendl;
00251 if ( m_SmtpAccount->getUser().isEmpty() || m_SmtpAccount->getPassword().isEmpty() ) {
00252
00253 LoginDialog login( m_SmtpAccount->getUser(),
00254 m_SmtpAccount->getPassword(), NULL, 0, true );
00255 login.show();
00256 if ( QDialog::Accepted == login.exec() ) {
00257
00258 user = login.getUser().latin1();
00259 pass = login.getPassword().latin1();
00260 } else {
00261 result = 0;
00262 failuretext=tr("Login aborted - storing mail to localfolder");
00263 }
00264 } else {
00265 user = m_SmtpAccount->getUser().latin1();
00266 pass = m_SmtpAccount->getPassword().latin1();
00267 }
00268 odebug << "session->auth: " << m_smtp->auth << "" << oendl;
00269 if (result) {
00270 err = mailsmtp_auth( m_smtp, (char*)user, (char*)pass );
00271 if ( err == MAILSMTP_NO_ERROR ) {
00272 odebug << "auth ok" << oendl;
00273 } else {
00274 failuretext = tr("Authentification failed");
00275 result = 0;
00276 }
00277 }
00278 }
00279 }
00280
00281 void SMTPwrapper::disc_server()
00282 {
00283 if (m_smtp) {
00284 mailsmtp_quit( m_smtp );
00285 mailsmtp_free( m_smtp );
00286 m_smtp = 0;
00287 }
00288 }
00289
00290 int SMTPwrapper::smtpSend(char*from,clist*rcpts,const char*data,size_t size )
00291 {
00292 int err,result;
00293 QString failuretext = "";
00294
00295 connect_server();
00296
00297 result = 1;
00298 if (m_smtp) {
00299 err = mailsmtp_send( m_smtp, from, rcpts, data, size );
00300 if ( err != MAILSMTP_NO_ERROR ) {
00301 failuretext=tr("Error sending mail: %1").arg(mailsmtpError(err));
00302 result = 0;
00303 }
00304 } else {
00305 result = 0;
00306 }
00307
00308 if (!result) {
00309 storeFailedMail(data,size,failuretext);
00310 } else {
00311 odebug << "Mail sent." << oendl;
00312 storeMail(data,size,"Sent");
00313 }
00314 return result;
00315 }
00316
00317 void SMTPwrapper::sendMail(const Opie::Core::OSmartPointer<Mail>&mail,bool later )
00318 {
00319 mailmime * mimeMail;
00320
00321 mimeMail = createMimeMail(mail );
00322 if ( mimeMail == NULL ) {
00323 odebug << "sendMail: error creating mime mail" << oendl;
00324 } else {
00325 sendProgress = new progressMailSend();
00326 sendProgress->show();
00327 sendProgress->setMaxMails(1);
00328 smtpSend( mimeMail,later);
00329 odebug << "Clean up done" << oendl;
00330 sendProgress->hide();
00331 delete sendProgress;
00332 sendProgress = 0;
00333 mailmime_free( mimeMail );
00334 }
00335 }
00336
00337 int SMTPwrapper::sendQueuedMail(AbstractMail*wrap,const RecMailP&which) {
00338 size_t curTok = 0;
00339 mailimf_fields *fields = 0;
00340 mailimf_field*ffrom = 0;
00341 clist *rcpts = 0;
00342 char*from = 0;
00343 int res = 0;
00344
00345 encodedString * data = wrap->fetchRawBody(which);
00346 if (!data)
00347 return 0;
00348 int err = mailimf_fields_parse( data->Content(), data->Length(), &curTok, &fields );
00349 if (err != MAILIMF_NO_ERROR) {
00350 delete data;
00351 delete wrap;
00352 return 0;
00353 }
00354
00355 rcpts = createRcptList( fields );
00356 ffrom = getField(fields, MAILIMF_FIELD_FROM );
00357 from = getFrom(ffrom);
00358
00359 if (rcpts && from) {
00360 res = smtpSend(from,rcpts,data->Content(),data->Length());
00361 }
00362 if (fields) {
00363 mailimf_fields_free(fields);
00364 fields = 0;
00365 }
00366 if (data) {
00367 delete data;
00368 }
00369 if (from) {
00370 free(from);
00371 }
00372 if (rcpts) {
00373 smtp_address_list_free( rcpts );
00374 }
00375 return res;
00376 }
00377
00378
00379 bool SMTPwrapper::flushOutbox() {
00380 bool returnValue = true;
00381
00382 odebug << "Sending the queue" << oendl;
00383 if (!m_SmtpAccount) {
00384 odebug << "No smtp account given" << oendl;
00385 return false;
00386 }
00387
00388 bool reset_user_value = false;
00389 QString localfolders = AbstractMail::defaultLocalfolder();
00390 AbstractMail*wrap = AbstractMail::getWrapper(localfolders);
00391 if (!wrap) {
00392 odebug << "memory error" << oendl;
00393 return false;
00394 }
00395 QString oldPw, oldUser;
00396 QValueList<RecMailP> mailsToSend;
00397 QValueList<RecMailP> mailsToRemove;
00398 QString mbox("Outgoing");
00399 wrap->listMessages(mbox,mailsToSend);
00400 if (mailsToSend.count()==0) {
00401 delete wrap;
00402 odebug << "No mails to send" << oendl;
00403 return false;
00404 }
00405
00406 oldPw = m_SmtpAccount->getPassword();
00407 oldUser = m_SmtpAccount->getUser();
00408 if (m_SmtpAccount->getLogin() && (m_SmtpAccount->getUser().isEmpty() || m_SmtpAccount->getPassword().isEmpty()) ) {
00409
00410 QString user,pass;
00411 LoginDialog login( m_SmtpAccount->getUser(), m_SmtpAccount->getPassword(), NULL, 0, true );
00412 login.show();
00413 if ( QDialog::Accepted == login.exec() ) {
00414
00415 user = login.getUser().latin1();
00416 pass = login.getPassword().latin1();
00417 reset_user_value = true;
00418 m_SmtpAccount->setUser(user);
00419 m_SmtpAccount->setPassword(pass);
00420 } else {
00421 return true;
00422 }
00423 }
00424
00425
00426 sendProgress = new progressMailSend();
00427 sendProgress->show();
00428 sendProgress->setMaxMails(mailsToSend.count());
00429
00430 while (mailsToSend.count()>0) {
00431 if (sendQueuedMail(wrap, (*mailsToSend.begin()))==0) {
00432 QMessageBox::critical(0,tr("Error sending mail"),
00433 tr("Error sending queued mail - breaking"));
00434 returnValue = false;
00435 break;
00436 }
00437 mailsToRemove.append((*mailsToSend.begin()));
00438 mailsToSend.remove(mailsToSend.begin());
00439 sendProgress->setCurrentMails(mailsToRemove.count());
00440 }
00441 if (reset_user_value) {
00442 m_SmtpAccount->setUser(oldUser);
00443 m_SmtpAccount->setPassword(oldPw);
00444 }
00445 Config cfg( "mail" );
00446 cfg.setGroup( "Status" );
00447 m_queuedMail = 0;
00448 cfg.writeEntry( "outgoing", m_queuedMail );
00449 emit queuedMails( m_queuedMail );
00450 sendProgress->hide();
00451 delete sendProgress;
00452 sendProgress = 0;
00453 wrap->deleteMails(mbox,mailsToRemove);
00454 delete wrap;
00455 return returnValue;
00456 }