-rw-r--r-- | noncore/net/mail/libmailwrapper/smtpwrapper.cpp | 55 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/smtpwrapper.h | 13 |
2 files changed, 60 insertions, 8 deletions
diff --git a/noncore/net/mail/libmailwrapper/smtpwrapper.cpp b/noncore/net/mail/libmailwrapper/smtpwrapper.cpp index e8db9ca..3ab6b77 100644 --- a/noncore/net/mail/libmailwrapper/smtpwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/smtpwrapper.cpp @@ -30,64 +30,66 @@ SMTPwrapper::SMTPwrapper( Settings *s ) Config cfg( "mail" ); cfg.setGroup( "Status" ); m_queuedMail = cfg.readNumEntry( "outgoing", 0 ); emit queuedMails( m_queuedMail ); connect( this, SIGNAL( queuedMails( int ) ), this, SLOT( emitQCop( int ) ) ); } void SMTPwrapper::emitQCop( int queued ) { QCopEnvelope env( "QPE/Pim", "outgoingMails(int)" ); env << queued; } QString SMTPwrapper::mailsmtpError( int errnum ) { switch ( errnum ) { case MAILSMTP_NO_ERROR: return tr( "No error" ); case MAILSMTP_ERROR_UNEXPECTED_CODE: return tr( "Unexpected error code" ); case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: return tr( "Service not available" ); case MAILSMTP_ERROR_STREAM: return tr( "Stream error" ); case MAILSMTP_ERROR_HOSTNAME: return tr( "gethostname() failed" ); case MAILSMTP_ERROR_NOT_IMPLEMENTED: return tr( "Not implemented" ); case MAILSMTP_ERROR_ACTION_NOT_TAKEN: return tr( "Error, action not taken" ); case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: return tr( "Data exceeds storage allocation" ); case MAILSMTP_ERROR_IN_PROCESSING: return tr( "Error in processing" ); + case MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED: + return tr( "Starttls not supported" ); // case MAILSMTP_ERROR_INSUFFISANT_SYSTEM_STORAGE: // return tr( "Insufficient system storage" ); case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: return tr( "Mailbox unavailable" ); case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: return tr( "Mailbox name not allowed" ); case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: return tr( "Bad command sequence" ); case MAILSMTP_ERROR_USER_NOT_LOCAL: return tr( "User not local" ); case MAILSMTP_ERROR_TRANSACTION_FAILED: return tr( "Transaction failed" ); case MAILSMTP_ERROR_MEMORY: return tr( "Memory error" ); case MAILSMTP_ERROR_CONNECTION_REFUSED: return tr( "Connection refused" ); default: return tr( "Unknown error code" ); } } mailimf_mailbox *SMTPwrapper::newMailbox(const QString&name, const QString&mail ) { return mailimf_mailbox_new( strdup( name.latin1() ), strdup( mail.latin1() ) ); } mailimf_address_list *SMTPwrapper::parseAddresses(const QString&addr ) { mailimf_address_list *addresses; if ( addr.isEmpty() ) return NULL; @@ -536,115 +538,158 @@ void SMTPwrapper::smtpSend( mailmime *mail,bool later, SMTPaccount *smtp ) { if (data) free( data ); Config cfg( "mail" ); cfg.setGroup( "Status" ); cfg.writeEntry( "outgoing", ++m_queuedMail ); emit queuedMails( m_queuedMail ); return; } from = getFrom( mail ); rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); smtpSend(from,rcpts,data,size,smtp); if (data) { free(data); } if (from) { free(from); } if (rcpts) smtp_address_list_free( rcpts ); } void SMTPwrapper::storeFailedMail(const char*data,unsigned int size, const char*failuremessage) { if (data) { storeMail(data,size,"Sendfailed"); } if (failuremessage) { QMessageBox::critical(0,tr("Error sending mail"), tr("<center>%1</center>").arg(failuremessage)); } } +int SMTPwrapper::start_smtp_tls(mailsmtp *session) +{ + if (!session) { + return MAILSMTP_ERROR_IN_PROCESSING; + } + int err = mailesmtp_starttls(session); + if (err != MAILSMTP_NO_ERROR) return err; + mailstream_low * low; + mailstream_low * new_low; + low = mailstream_get_low(session->stream); + if (!low) { + return MAILSMTP_ERROR_IN_PROCESSING; + } + int fd = mailstream_low_get_fd(low); + if (fd > -1 && (new_low = mailstream_low_ssl_open(fd))!=0) { + mailstream_low_free(low); + mailstream_set_low(session->stream, new_low); + } else { + return MAILSMTP_ERROR_IN_PROCESSING; + } + return err; +} + int SMTPwrapper::smtpSend(char*from,clist*rcpts,const char*data,size_t size, SMTPaccount *smtp ) { const char *server, *user, *pass; bool ssl; uint16_t port; mailsmtp *session; int err,result; QString failuretext = ""; result = 1; server = user = pass = 0; server = smtp->getServer().latin1(); // FIXME: currently only TLS and Plain work. ssl = false; + bool try_tls = true; + bool force_tls=false; if ( smtp->ConnectionType() == 2 ) { ssl = true; + try_tls = false; + } else if (smtp->ConnectionType() == 1) { + force_tls = true; } port = smtp->getPort().toUInt(); session = mailsmtp_new( 20, &progress ); if ( session == NULL ) { /* no failure message cause this happens when problems with memory - than we we can not display any messagebox */ return 0; } qDebug( "Servername %s at port %i", server, port ); if ( ssl ) { qDebug( "SSL session" ); err = mailsmtp_ssl_connect( session, server, port ); } else { qDebug( "No SSL session" ); err = mailsmtp_socket_connect( session, server, port ); } if ( err != MAILSMTP_NO_ERROR ) { qDebug("Error init connection"); failuretext = tr("Error init SMTP connection: %1").arg(mailsmtpError(err)); result = 0; } + /* switch to tls after init 'cause there it will send the ehlo */ if (result) { err = mailsmtp_init( session ); if (err != MAILSMTP_NO_ERROR) { result = 0; failuretext = tr("Error init SMTP connection: %1").arg(mailsmtpError(err)); } } + if (try_tls) { + err = start_smtp_tls(session); + if (err != MAILSMTP_NO_ERROR) { + try_tls = false; + } else { + err = mailesmtp_ehlo(session); + } + } + + if (!try_tls && force_tls) { + result = 0; + failuretext = tr("Error init SMTP tls: %1").arg(mailsmtpError(err)); + } + if (result==1 && smtp->getLogin() ) { qDebug("smtp with auth"); if ( smtp->getUser().isEmpty() || smtp->getPassword().isEmpty() ) { // get'em LoginDialog login( smtp->getUser(), smtp->getPassword(), NULL, 0, true ); login.show(); if ( QDialog::Accepted == login.exec() ) { // ok user = login.getUser().latin1(); pass = login.getPassword().latin1(); } else { result = 0; failuretext=tr("Login aborted - storing mail to localfolder"); } } else { user = smtp->getUser().latin1(); pass = smtp->getPassword().latin1(); } qDebug( "session->auth: %i", session->auth); if (result) { err = mailsmtp_auth( session, (char*)user, (char*)pass ); if ( err == MAILSMTP_NO_ERROR ) { qDebug("auth ok"); } else { failuretext = tr("Authentification failed"); result = 0; } } } if (result) { err = mailsmtp_send( session, from, rcpts, data, size ); @@ -708,104 +753,108 @@ int SMTPwrapper::sendQueuedMail(AbstractMail*wrap,SMTPaccount*smtp,RecMail*which delete data; delete wrap; return 0; } rcpts = createRcptList( fields ); ffrom = getField(fields, MAILIMF_FIELD_FROM ); from = getFrom(ffrom); if (rcpts && from) { res = smtpSend(from,rcpts,data->Content(),data->Length(),smtp ); } if (fields) { mailimf_fields_free(fields); fields = 0; } if (data) { delete data; } if (from) { free(from); } if (rcpts) { smtp_address_list_free( rcpts ); } return res; } /* this is a special fun */ bool SMTPwrapper::flushOutbox(SMTPaccount*smtp) { bool returnValue = true; - if (!smtp) + qDebug("Sending the queue"); + if (!smtp) { + qDebug("No smtp account given"); return false; + } bool reset_user_value = false; QString localfolders = AbstractMail::defaultLocalfolder(); AbstractMail*wrap = AbstractMail::getWrapper(localfolders); if (!wrap) { qDebug("memory error"); return false; } QString oldPw, oldUser; QList<RecMail> mailsToSend; QList<RecMail> mailsToRemove; QString mbox("Outgoing"); wrap->listMessages(mbox,mailsToSend); if (mailsToSend.count()==0) { delete wrap; + qDebug("No mails to send"); return false; } - + oldPw = smtp->getPassword(); oldUser = smtp->getUser(); if (smtp->getLogin() && (smtp->getUser().isEmpty() || smtp->getPassword().isEmpty()) ) { // get'em QString user,pass; LoginDialog login( smtp->getUser(), smtp->getPassword(), NULL, 0, true ); login.show(); if ( QDialog::Accepted == login.exec() ) { // ok user = login.getUser().latin1(); pass = login.getPassword().latin1(); reset_user_value = true; smtp->setUser(user); smtp->setPassword(pass); } else { return true; } } - + mailsToSend.setAutoDelete(false); sendProgress = new progressMailSend(); sendProgress->show(); sendProgress->setMaxMails(mailsToSend.count()); while (mailsToSend.count()>0) { if (sendQueuedMail(wrap,smtp,mailsToSend.at(0))==0) { QMessageBox::critical(0,tr("Error sending mail"), tr("Error sending queued mail - breaking")); returnValue = false; break; } mailsToRemove.append(mailsToSend.at(0)); mailsToSend.removeFirst(); sendProgress->setCurrentMails(mailsToRemove.count()); } if (reset_user_value) { smtp->setUser(oldUser); smtp->setPassword(oldPw); } Config cfg( "mail" ); cfg.setGroup( "Status" ); m_queuedMail = 0; cfg.writeEntry( "outgoing", m_queuedMail ); emit queuedMails( m_queuedMail ); sendProgress->hide(); delete sendProgress; sendProgress = 0; wrap->deleteMails(mbox,mailsToRemove); mailsToSend.setAutoDelete(true); delete wrap; return returnValue; diff --git a/noncore/net/mail/libmailwrapper/smtpwrapper.h b/noncore/net/mail/libmailwrapper/smtpwrapper.h index 89826d9..75e4891 100644 --- a/noncore/net/mail/libmailwrapper/smtpwrapper.h +++ b/noncore/net/mail/libmailwrapper/smtpwrapper.h @@ -1,73 +1,76 @@ #ifndef SMTPwrapper_H #define SMTPwrapper_H #include <qpe/applnk.h> #include <qbitarray.h> #include <qdatetime.h> #include <libetpan/clist.h> #include "settings.h" class Mail; class AbstractMail; class RecMail; class Attachment; struct mailimf_fields; struct mailimf_field; struct mailimf_mailbox; struct mailmime; struct mailimf_address_list; class progressMailSend; +struct mailsmtp; class SMTPwrapper : public QObject { Q_OBJECT public: - SMTPwrapper( Settings *s ); + SMTPwrapper( Settings *s ); virtual ~SMTPwrapper(){} void sendMail(const Mail& mail,SMTPaccount*smtp,bool later=false ); bool flushOutbox(SMTPaccount*smtp); static progressMailSend*sendProgress; signals: - void queuedMails( int ); + void queuedMails( int ); protected: mailimf_mailbox *newMailbox(const QString&name,const QString&mail ); mailimf_fields *createImfFields(const Mail &mail ); mailmime *createMimeMail(const Mail&mail ); - + mailimf_address_list *parseAddresses(const QString&addr ); void addFileParts( mailmime *message,const QList<Attachment>&files ); mailmime *buildTxtPart(const QString&str ); mailmime *buildFilePart(const QString&filename,const QString&mimetype,const QString&content); void smtpSend( mailmime *mail,bool later, SMTPaccount *smtp ); clist *createRcptList( mailimf_fields *fields ); - + static void storeMail(const char*mail, size_t length, const QString&box); static QString mailsmtpError( int err ); static void progress( size_t current, size_t maximum ); static void addRcpts( clist *list, mailimf_address_list *addr_list ); static char *getFrom( mailmime *mail ); static char *getFrom( mailimf_field *ffrom); static mailimf_field *getField( mailimf_fields *fields, int type ); + static int start_smtp_tls(mailsmtp *session); + int smtpSend(char*from,clist*rcpts,const char*data,size_t size, SMTPaccount *smtp ); void storeMail(mailmime*mail, const QString&box); Settings *settings; - + int sendQueuedMail(AbstractMail*wrap,SMTPaccount*smtp,RecMail*which); void storeFailedMail(const char*data,unsigned int size, const char*failuremessage); int m_queuedMail; static const char* USER_AGENT; protected slots: void emitQCop( int queued ); }; #endif |