-rw-r--r-- | noncore/net/mail/libmailwrapper/mailwrapper.cpp | 1 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mboxwrapper.cpp | 66 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mboxwrapper.h | 3 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/smtpwrapper.cpp | 333 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/smtpwrapper.h | 18 | ||||
-rw-r--r-- | noncore/net/mail/mailwrapper.cpp | 1 | ||||
-rw-r--r-- | noncore/net/mail/mboxwrapper.cpp | 66 | ||||
-rw-r--r-- | noncore/net/mail/mboxwrapper.h | 3 | ||||
-rw-r--r-- | noncore/net/mail/opiemail.cpp | 19 | ||||
-rw-r--r-- | noncore/net/mail/smtpwrapper.cpp | 333 | ||||
-rw-r--r-- | noncore/net/mail/smtpwrapper.h | 18 |
11 files changed, 585 insertions, 276 deletions
diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.cpp b/noncore/net/mail/libmailwrapper/mailwrapper.cpp index c5d4265..f8efd09 100644 --- a/noncore/net/mail/libmailwrapper/mailwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/mailwrapper.cpp @@ -1,75 +1,74 @@ #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <qdir.h> #include "mailwrapper.h" #include "logindialog.h" -//#include "mail.h" #include "defines.h" Attachment::Attachment( DocLnk lnk ) { doc = lnk; size = QFileInfo( doc.file() ).size(); } Folder::Folder(const QString&tmp_name, const QString&sep ) { name = tmp_name; nameDisplay = name; separator = sep; } const QString& Folder::Separator()const { return separator; } IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const QString&prefix ) : Folder( name,sep ),m_MaySelect(select) { // Decode IMAP foldername nameDisplay = IMAPFolder::decodeFolderName( name ); qDebug( "folder " + name + " - displayed as " + nameDisplay ); if (prefix.length()>0) { if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) { nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length()); } } } static unsigned char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; /** * Decodes base64 encoded parts of the imapfolder name * Code taken from kde cvs: kdebase/kioslave/imap4/rfcdecoder.cc */ QString IMAPFolder::decodeFolderName( const QString &name ) { unsigned char c, i, bitcount; unsigned long ucs4, utf16, bitbuf; unsigned char base64[256], utf8[6]; unsigned long srcPtr = 0; QCString dst; QCString src = name.ascii(); /* initialize modified base64 decoding table */ memset(base64, UNDEFINED, sizeof(base64)); for (i = 0; i < sizeof(base64chars); ++i) { base64[(int)base64chars[i]] = i; } /* loop until end of string */ while (srcPtr < src.length ()) { c = src[srcPtr++]; /* deal with literal characters and &- */ if (c != '&' || src[srcPtr] == '-') { /* encode literally */ dst += c; /* skip over the '-' if this is an &- sequence */ diff --git a/noncore/net/mail/libmailwrapper/mboxwrapper.cpp b/noncore/net/mail/libmailwrapper/mboxwrapper.cpp index 8117cef..293ae1b 100644 --- a/noncore/net/mail/libmailwrapper/mboxwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/mboxwrapper.cpp @@ -156,64 +156,130 @@ RecBody MBOXwrapper::fetchBody( const RecMail &mail ) QString p = MBOXPath+"/"; p+=mail.getMbox(); mailmessage * msg; char*data=0; size_t size; int r = mbox_mailstorage_init(storage,strdup(p.latin1()),0,0,0); mailfolder*folder; folder = mailfolder_new( storage,strdup(p.latin1()),NULL); r = mailfolder_connect(folder); if (r != MAIL_NO_ERROR) { qDebug("Error initializing mbox"); mailfolder_free(folder); mailstorage_free(storage); return body; } r = mailsession_get_message(folder->fld_session, mail.getNumber(), &msg); if (r != MAIL_NO_ERROR) { qDebug("Error fetching mail %i",mail.getNumber()); mailfolder_free(folder); mailstorage_free(storage); return body; } r = mailmessage_fetch(msg,&data,&size); if (r != MAIL_NO_ERROR) { qDebug("Error fetching mail %i",mail.getNumber()); mailfolder_free(folder); mailstorage_free(storage); mailmessage_free(msg); return body; } body = parseMail(msg); mailmessage_fetch_result_free(msg,data); mailfolder_free(folder); mailstorage_free(storage); return body; } void MBOXwrapper::mbox_progress( size_t current, size_t maximum ) { qDebug("MBOX %i von %i",current,maximum); } void MBOXwrapper::createFolder(const QString&) { } void MBOXwrapper::storeMessage(const char*msg,size_t length, const QString&folder) { QString p = MBOXPath+"/"; p+=folder; mailmbox_folder*f = 0; int r = mailmbox_init(p.latin1(),0,1,0,&f); if (r != MAIL_NO_ERROR) { qDebug("Error init folder"); return; } r = mailmbox_append_message(f,msg,length); if (r != MAIL_NO_ERROR) { qDebug("Error writing message folder"); } mailmbox_done(f); } + +void MBOXwrapper::fetchRawBody(const RecMail&mail,char**target,size_t*length) +{ + RecBody body; + mailstorage*storage = mailstorage_new(NULL); + QString p = MBOXPath+"/"; + p+=mail.getMbox(); + mailmessage * msg; + char*data=0; + size_t size; + + int r = mbox_mailstorage_init(storage,strdup(p.latin1()),0,0,0); + mailfolder*folder; + folder = mailfolder_new( storage,strdup(p.latin1()),NULL); + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + qDebug("Error initializing mbox"); + mailfolder_free(folder); + mailstorage_free(storage); + return; + } + r = mailsession_get_message(folder->fld_session, mail.getNumber(), &msg); + if (r != MAIL_NO_ERROR) { + qDebug("Error fetching mail %i",mail.getNumber()); + mailfolder_free(folder); + mailstorage_free(storage); + return; + } + r = mailmessage_fetch(msg,&data,&size); + if (r != MAIL_NO_ERROR) { + qDebug("Error fetching mail %i",mail.getNumber()); + mailfolder_free(folder); + mailstorage_free(storage); + mailmessage_free(msg); + return; + } + *target = data; + *length = size; + mailfolder_free(folder); + mailstorage_free(storage); + mailmessage_free(msg); +} + +void MBOXwrapper::deleteMails(const QString & mailbox,QList<RecMail> &target) +{ + QString p = MBOXPath+"/"; + p+=mailbox; + mailmbox_folder*f = 0; + int r = mailmbox_init(p.latin1(),0,1,0,&f); + if (r != MAIL_NO_ERROR) { + qDebug("Error init folder"); + return; + } + for (unsigned int i=0; i < target.count();++i) { + r = mailmbox_delete_msg(f,target.at(i)->getNumber()); + if (r!=MAILMBOX_NO_ERROR) { + qDebug("error delete mail"); + } + } + r = mailmbox_expunge(f); + if (r != MAILMBOX_NO_ERROR) { + qDebug("error expunge mailbox"); + } + mailmbox_done(f); +} + diff --git a/noncore/net/mail/libmailwrapper/mboxwrapper.h b/noncore/net/mail/libmailwrapper/mboxwrapper.h index 1bbaf79..f64ad52 100644 --- a/noncore/net/mail/libmailwrapper/mboxwrapper.h +++ b/noncore/net/mail/libmailwrapper/mboxwrapper.h @@ -1,32 +1,35 @@ #ifndef __MBOX_WRAPPER_H #define __MBOX_WRAPPER_H #include "genericwrapper.h" #include <qstring.h> class RecMail; class RecBody; class MBOXwrapper : public Genericwrapper { Q_OBJECT public: MBOXwrapper(const QString & dir); virtual ~MBOXwrapper(); virtual void listMessages(const QString & mailbox, QList<RecMail> &target ); virtual QList<Folder>* listFolders(); virtual void deleteMail(const RecMail&mail); virtual void answeredMail(const RecMail&mail); virtual void createFolder(const QString&aFolder); virtual void storeMessage(const char*msg,size_t length, const QString&folder); virtual RecBody fetchBody( const RecMail &mail ); static void mbox_progress( size_t current, size_t maximum ); + virtual void fetchRawBody(const RecMail&mail,char**target,size_t*length); + virtual void deleteMails(const QString & mailbox,QList<RecMail> &target); + protected: QString MBOXPath; }; #endif diff --git a/noncore/net/mail/libmailwrapper/smtpwrapper.cpp b/noncore/net/mail/libmailwrapper/smtpwrapper.cpp index a6a46ba..b81a87f 100644 --- a/noncore/net/mail/libmailwrapper/smtpwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/smtpwrapper.cpp @@ -1,84 +1,80 @@ #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <qdir.h> +#include <qt.h> #include <libetpan/libetpan.h> -#if 0 -#include <libetpan/mailimf.h> -#include <libetpan/mailsmtp.h> -#include <libetpan/mailstorage.h> -#include <libetpan/maildriver.h> -#endif #include "smtpwrapper.h" #include "mailwrapper.h" #include "mboxwrapper.h" #include "logindialog.h" +#include "mailtypes.h" #include "defines.h" SMTPwrapper::SMTPwrapper( Settings *s ) : QObject() { settings = s; } 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_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; addresses = mailimf_address_list_new_empty(); @@ -147,499 +143,572 @@ err_free_fields: mailimf_fields_free( fields ); err_free_reply: mailimf_address_list_free( reply ); mailimf_address_list_free( bcc ); mailimf_address_list_free( cc ); mailimf_address_list_free( to ); err_free_from: mailimf_mailbox_list_free( from ); err_free_fromBox: mailimf_mailbox_free( fromBox ); err_free_sender: mailimf_mailbox_free( sender ); err_free: free( subject ); qDebug( "createImfFields - error" ); return NULL; // Error :( } mailmime *SMTPwrapper::buildTxtPart(const QString&str ) { mailmime *txtPart; mailmime_fields *fields; mailmime_content *content; mailmime_parameter *param; char *txt = strdup( str.latin1() ); int err; param = mailmime_parameter_new( strdup( "charset" ), strdup( "iso-8859-1" ) ); if ( param == NULL ) goto err_free; content = mailmime_content_new_with_str( "text/plain" ); if ( content == NULL ) goto err_free_param; err = clist_append( content->ct_parameters, param ); if ( err != MAILIMF_NO_ERROR ) goto err_free_content; fields = mailmime_fields_new_encoding( MAILMIME_MECHANISM_8BIT ); if ( fields == NULL ) goto err_free_content; txtPart = mailmime_new_empty( content, fields ); if ( txtPart == NULL ) goto err_free_fields; err = mailmime_set_body_text( txtPart, txt, strlen( txt ) ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; return txtPart; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_fields: mailmime_fields_free( fields ); err_free_content: mailmime_content_free( content ); err_free_param: mailmime_parameter_free( param ); err_free: free( txt ); qDebug( "buildTxtPart - error" ); return NULL; // Error :( } -mailmime *SMTPwrapper::buildFilePart(const QString&filename,const QString&mimetype ) +mailmime *SMTPwrapper::buildFilePart(const QString&filename,const QString&mimetype,const QString&TextContent ) { - mailmime * filePart; - mailmime_fields * fields; - mailmime_content * content; - mailmime_parameter * param = NULL; + mailmime * filePart = 0; + mailmime_fields * fields = 0; + mailmime_content * content = 0; + mailmime_parameter * param = 0; + char*name = 0; + char*file = 0; int err; int pos = filename.findRev( '/' ); - QString tmp = filename.right( filename.length() - ( pos + 1 ) ); - char *name = strdup( tmp.latin1() ); // just filename - char *file = strdup( filename.latin1() ); // full name with path + + if (filename.length()>0) { + QString tmp = filename.right( filename.length() - ( pos + 1 ) ); + name = strdup( tmp.latin1() ); // just filename + file = strdup( filename.latin1() ); // full name with path + } char *mime = strdup( mimetype.latin1() ); // mimetype -e.g. text/plain - fields = mailmime_fields_new_filename( - MAILMIME_DISPOSITION_TYPE_ATTACHMENT, name, - MAILMIME_MECHANISM_BASE64 ); - if ( fields == NULL ) goto err_free; - - content = mailmime_content_new_with_str( mime ); - if ( content == NULL ) goto err_free_fields; - - if ( mimetype.compare( "text/plain" ) == 0 ) { + int disptype = MAILMIME_DISPOSITION_TYPE_ATTACHMENT; + int mechanism = MAILMIME_MECHANISM_BASE64; + + if ( mimetype.startsWith( "text/" ) ) { param = mailmime_parameter_new( strdup( "charset" ), - strdup( "iso-8859-1" ) ); - if ( param == NULL ) goto err_free_content; - - err = clist_append( content->ct_parameters, param ); - if ( err != MAILIMF_NO_ERROR ) goto err_free_param; + strdup( "iso-8859-1" ) ); + disptype = MAILMIME_DISPOSITION_TYPE_INLINE; + mechanism = MAILMIME_MECHANISM_QUOTED_PRINTABLE; } - filePart = mailmime_new_empty( content, fields ); - if ( filePart == NULL ) goto err_free_param; - - err = mailmime_set_body_file( filePart, file ); - if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart; + fields = mailmime_fields_new_filename( + disptype, name, + mechanism ); + content = mailmime_content_new_with_str( mime ); + if (content!=0 && fields != 0) { + if (param) { + clist_append(content->ct_parameters,param); + param = 0; + } + if (filename.length()>0) { + QFileInfo f(filename); + param = mailmime_parameter_new(strdup("name"),strdup(f.fileName().latin1())); + clist_append(content->ct_parameters,param); + param = 0; + } + filePart = mailmime_new_empty( content, fields ); + } + if (filePart) { + if (filename.length()>0) { + err = mailmime_set_body_file( filePart, file ); + } else { + err = mailmime_set_body_text(filePart,strdup(TextContent.ascii()),TextContent.length()); + } + if (err != MAILIMF_NO_ERROR) { + qDebug("Error setting body with file %s",file); + mailmime_free( filePart ); + filePart = 0; + } + } + if (!filePart) { + if ( param != NULL ) { + mailmime_parameter_free( param ); + } + if (content) { + mailmime_content_free( content ); + } else { + if (mime) { + free( mime ); + } + } + if (fields) { + mailmime_fields_free( fields ); + } else { + if (name) { + free( name ); + } + if (file) { + free( file ); + } + } + } return filePart; // Success :) -err_free_filePart: - mailmime_free( filePart ); -err_free_param: - if ( param != NULL ) mailmime_parameter_free( param ); -err_free_content: - mailmime_content_free( content ); -err_free_fields: - mailmime_fields_free( fields ); -err_free: - free( name ); - free( mime ); - free( file ); - qDebug( "buildFilePart - error" ); - - return NULL; // Error :( } void SMTPwrapper::addFileParts( mailmime *message,const QList<Attachment>&files ) { const Attachment *it; - /* work around for the brainfucked qlist which can not act with const values */ - for ( it = ((QList<Attachment>)files).first(); it; it = ((QList<Attachment>)files).next() ) { + unsigned int count = files.count(); + qDebug("List contains %i values",count); + for ( unsigned int i = 0; i < count; ++i ) { qDebug( "Adding file" ); mailmime *filePart; int err; + it = ((QList<Attachment>)files).at(i); - filePart = buildFilePart( it->getFileName(), it->getMimeType() ); - if ( filePart == NULL ) goto err_free; - + filePart = buildFilePart( it->getFileName(), it->getMimeType(),"" ); + if ( filePart == NULL ) { + qDebug( "addFileParts: error adding file:" ); + qDebug( it->getFileName() ); + continue; + } err = mailmime_smart_add_part( message, filePart ); - if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart; - - continue; // Success :) - - err_free_filePart: - mailmime_free( filePart ); - err_free: - qDebug( "addFileParts: error adding file:" ); - qDebug( it->getFileName() ); + if ( err != MAILIMF_NO_ERROR ) { + mailmime_free( filePart ); + qDebug("error smart add"); + } } } mailmime *SMTPwrapper::createMimeMail(const Mail &mail ) { mailmime *message, *txtPart; mailimf_fields *fields; int err; fields = createImfFields( mail ); if ( fields == NULL ) goto err_free; message = mailmime_new_message_data( NULL ); if ( message == NULL ) goto err_free_fields; mailmime_set_imf_fields( message, fields ); - txtPart = buildTxtPart( mail.getMessage() ); + if (mail.getAttachments().count()==0) { + txtPart = buildTxtPart( mail.getMessage() ); + } else { + txtPart = buildFilePart("","text/plain",mail.getMessage()); + } if ( txtPart == NULL ) goto err_free_message; err = mailmime_smart_add_part( message, txtPart ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; addFileParts( message, mail.getAttachments() ); return message; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_message: mailmime_free( message ); err_free_fields: mailimf_fields_free( fields ); err_free: qDebug( "createMimeMail: error" ); return NULL; // Error :( } mailimf_field *SMTPwrapper::getField( mailimf_fields *fields, int type ) { mailimf_field *field; clistiter *it; it = clist_begin( fields->fld_list ); while ( it ) { field = (mailimf_field *) it->data; if ( field->fld_type == type ) { return field; } it = it->next; } return NULL; } void SMTPwrapper::addRcpts( clist *list, mailimf_address_list *addr_list ) { clistiter *it, *it2; for ( it = clist_begin( addr_list->ad_list ); it; it = it->next ) { mailimf_address *addr; addr = (mailimf_address *) it->data; if ( addr->ad_type == MAILIMF_ADDRESS_MAILBOX ) { esmtp_address_list_add( list, addr->ad_data.ad_mailbox->mb_addr_spec, 0, NULL ); } else if ( addr->ad_type == MAILIMF_ADDRESS_GROUP ) { clist *l = addr->ad_data.ad_group->grp_mb_list->mb_list; for ( it2 = clist_begin( l ); it2; it2 = it2->next ) { mailimf_mailbox *mbox; mbox = (mailimf_mailbox *) it2->data; esmtp_address_list_add( list, mbox->mb_addr_spec, 0, NULL ); } } } } clist *SMTPwrapper::createRcptList( mailimf_fields *fields ) { clist *rcptList; mailimf_field *field; rcptList = esmtp_address_list_new(); field = getField( fields, MAILIMF_FIELD_TO ); if ( field && (field->fld_type == MAILIMF_FIELD_TO) && field->fld_data.fld_to->to_addr_list ) { addRcpts( rcptList, field->fld_data.fld_to->to_addr_list ); } field = getField( fields, MAILIMF_FIELD_CC ); if ( field && (field->fld_type == MAILIMF_FIELD_CC) && field->fld_data.fld_cc->cc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_cc->cc_addr_list ); } field = getField( fields, MAILIMF_FIELD_BCC ); if ( field && (field->fld_type == MAILIMF_FIELD_BCC) && field->fld_data.fld_bcc->bcc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_bcc->bcc_addr_list ); } return rcptList; } -char *SMTPwrapper::getFrom( mailmime *mail ) +char *SMTPwrapper::getFrom( mailimf_field *ffrom) { char *from = NULL; - - mailimf_field *ffrom; - ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM ); if ( ffrom && (ffrom->fld_type == MAILIMF_FIELD_FROM) && ffrom->fld_data.fld_from->frm_mb_list && ffrom->fld_data.fld_from->frm_mb_list->mb_list ) { clist *cl = ffrom->fld_data.fld_from->frm_mb_list->mb_list; clistiter *it; for ( it = clist_begin( cl ); it; it = it->next ) { mailimf_mailbox *mb = (mailimf_mailbox *) it->data; from = strdup( mb->mb_addr_spec ); } } return from; } -SMTPaccount *SMTPwrapper::getAccount(const QString&from ) +char *SMTPwrapper::getFrom( mailmime *mail ) +{ + mailimf_field *ffrom = 0; + ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM ); + return getFrom(ffrom); +} + +SMTPaccount *SMTPwrapper::getAccount(const QString&name ) { SMTPaccount *smtp; QList<Account> list = settings->getAccounts(); Account *it; for ( it = list.first(); it; it = list.next() ) { if ( it->getType().compare( "SMTP" ) == 0 ) { smtp = static_cast<SMTPaccount *>(it); - if ( smtp->getMail().compare( from ) == 0 ) { + if ( smtp->getName()== name ) { qDebug( "SMTPaccount found for" ); - qDebug( from ); + qDebug( name ); return smtp; } } } return NULL; } QString SMTPwrapper::getTmpFile() { int num = 0; QString unique; QDir dir( "/tmp" ); - QStringList::Iterator it; QStringList list = dir.entryList( "opiemail-tmp-*" ); + do { unique.setNum( num++ ); } while ( list.contains( "opiemail-tmp-" + unique ) > 0 ); return "/tmp/opiemail-tmp-" + unique; } void SMTPwrapper::writeToFile(const QString&file, mailmime *mail ) { FILE *f; int err, col = 0; f = fopen( file.latin1(), "w" ); if ( f == NULL ) { qDebug( "writeToFile: error opening file" ); return; } err = mailmime_write( f, &col, mail ); if ( err != MAILIMF_NO_ERROR ) { fclose( f ); qDebug( "writeToFile: error writing mailmime" ); return; } fclose( f ); } void SMTPwrapper::readFromFile(const QString&file, char **data, size_t *size ) { QFile msg_cache(file); QString msg = ""; msg_cache.open(IO_ReadOnly); char*message = new char[4096]; memset(message,0,4096); while (msg_cache.readBlock(message,4095)>0) { msg+=message; memset(message,0,4096); } delete message; *data = (char*)malloc(msg.length()+1*sizeof(char)); memset(*data,0,msg.length()+1); memcpy(*data,msg.ascii(),msg.length()); *size=msg.length(); - -#if 0 - char *buf; - struct stat st; - int fd, count = 0, total = 0; - - fd = open( file.latin1(), O_RDONLY, 0 ); - if ( fd == -1 ) return; - - if ( fstat( fd, &st ) != 0 ) goto err_close; - if ( !st.st_size ) goto err_close; - - buf = (char *) malloc( st.st_size ); - if ( !buf ) goto err_close; - - while ( ( total < st.st_size ) && ( count >= 0 ) ) { - count = read( fd, buf + total, st.st_size - total ); - total += count; - } - if ( count < 0 ) goto err_free; - - *data = buf; - *size = st.st_size; - - close( fd ); - - return; // Success :) - -err_free: - free( buf ); -err_close: - close( fd ); -#endif } void SMTPwrapper::progress( size_t current, size_t maximum ) { - qDebug( "Current: %i of %i", current, maximum ); +// qDebug( "Current: %i of %i", current, maximum ); } void SMTPwrapper::storeMail(char*mail, size_t length, const QString&box) { if (!mail) return; QString localfolders = (QString) getenv( "HOME" ) + QString("/Applications/opiemail/localmail/"); MBOXwrapper*wrap = new MBOXwrapper(localfolders); wrap->storeMessage(mail,length,box); delete wrap; } -void SMTPwrapper::smtpSend( mailmime *mail,bool later ) +void SMTPwrapper::smtpSend( mailmime *mail,bool later, SMTPaccount *smtp ) { - mailsmtp *session; - clist *rcpts; - char *from, *data, *server, *user = NULL, *pass = NULL; + clist *rcpts = 0; + char *from, *data; size_t size; - int err; - bool ssl; - uint16_t port; - - from = getFrom( mail ); - SMTPaccount *smtp = getAccount( from ); if ( smtp == NULL ) { - free(from); return; } - rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); - + from = data = 0; + QString file = getTmpFile(); writeToFile( file, mail ); - readFromFile( file, &data, &size ); QFile f( file ); f.remove(); - storeMail(data,size,(later?"Outgoing":"Sent")); - if (later) { - smtp_address_list_free( rcpts ); + storeMail(data,size,"Outgoing"); if (data) free( data ); - if (from) free(from); return; } + from = getFrom( mail ); + rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); + smtpSend(from,rcpts,data,size,smtp); +} + +int SMTPwrapper::smtpSend(char*from,clist*rcpts,char*data,size_t size, SMTPaccount *smtp ) +{ + char *server, *user, *pass; + bool ssl; + uint16_t port; + mailsmtp *session; + int err,result; + + result = 1; + server = user = pass = 0; server = strdup( smtp->getServer().latin1() ); ssl = smtp->getSSL(); port = smtp->getPort().toUInt(); session = mailsmtp_new( 20, &progress ); if ( session == NULL ) goto free_mem; 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 ) goto free_mem_session; + if ( err != MAILSMTP_NO_ERROR ) {result = 0;goto free_mem_session;} err = mailsmtp_init( session ); - if ( err != MAILSMTP_NO_ERROR ) goto free_con_session; + if ( err != MAILSMTP_NO_ERROR ) {result = 0; goto free_con_session;} qDebug( "INIT OK" ); if ( smtp->getLogin() ) { 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 = strdup( login.getUser().latin1() ); pass = strdup( login.getPassword().latin1() ); } else { - goto free_con_session; + result = 0; goto free_con_session; } } else { user = strdup( smtp->getUser().latin1() ); pass = strdup( smtp->getPassword().latin1() ); } qDebug( "session->auth: %i", session->auth); err = mailsmtp_auth( session, user, pass ); if ( err == MAILSMTP_NO_ERROR ) qDebug("auth ok"); qDebug( "Done auth!" ); } err = mailsmtp_send( session, from, rcpts, data, size ); - if ( err != MAILSMTP_NO_ERROR ) goto free_con_session; + if ( err != MAILSMTP_NO_ERROR ) {result = 0; goto free_con_session;} qDebug( "Mail sent." ); + storeMail(data,size,"Sent"); free_con_session: mailsmtp_quit( session ); free_mem_session: mailsmtp_free( session ); free_mem: - smtp_address_list_free( rcpts ); + if (rcpts) smtp_address_list_free( rcpts ); if (data) free( data ); - if (from) free(from); if (server) free( server ); + if (from) free( from ); if ( smtp->getLogin() ) { free( user ); free( pass ); } - free( from ); + return result; } void SMTPwrapper::sendMail(const Mail&mail,bool later ) { mailmime * mimeMail; - + + SMTPaccount *smtp = getAccount(mail.getName()); + mimeMail = createMimeMail(mail ); if ( mimeMail == NULL ) { qDebug( "sendMail: error creating mime mail" ); } else { - smtpSend( mimeMail,later ); + smtpSend( mimeMail,later,smtp); mailmime_free( mimeMail ); + qDebug("Clean up done"); + } +} + +int SMTPwrapper::sendQueuedMail(MBOXwrapper*wrap,SMTPaccount*smtp,RecMail*which) +{ + char*data = 0; + size_t length = 0; + size_t curTok = 0; + mailimf_fields *fields = 0; + mailimf_field*ffrom = 0; + clist *rcpts = 0; + char*from = 0; + + wrap->fetchRawBody(*which,&data,&length); + if (!data) return 0; + int err = mailimf_fields_parse( data, length, &curTok, &fields ); + if (err != MAILIMF_NO_ERROR) { + free(data); + delete wrap; + return 0; + } + + rcpts = createRcptList( fields ); + ffrom = getField(fields, MAILIMF_FIELD_FROM ); + from = getFrom(ffrom); + qDebug("Size: %i vs. %i",length,strlen(data)); + if (rcpts && from) { + return smtpSend(from,rcpts,data,strlen(data),smtp ); } + return 0; +} + +/* this is a special fun */ +void SMTPwrapper::flushOutbox(SMTPaccount*smtp) +{ + if (!smtp) return; + QString localfolders = (QString) getenv( "HOME" ) + QString("/Applications/opiemail/localmail/"); + MBOXwrapper*wrap = new MBOXwrapper(localfolders); + if (!wrap) { + qDebug("memory error"); + return; + } + QList<RecMail> mailsToSend; + QList<RecMail> mailsToRemove; + QString mbox("Outgoing"); + wrap->listMessages(mbox,mailsToSend); + if (mailsToSend.count()==0) { + delete wrap; + return; + } + mailsToSend.setAutoDelete(false); + 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")); + break; + } + mailsToRemove.append(mailsToSend.at(0)); + mailsToSend.removeFirst(); + } + wrap->deleteMails(mbox,mailsToRemove); + mailsToSend.setAutoDelete(true); + delete wrap; } diff --git a/noncore/net/mail/libmailwrapper/smtpwrapper.h b/noncore/net/mail/libmailwrapper/smtpwrapper.h index 41e9a8c..c0dcc11 100644 --- a/noncore/net/mail/libmailwrapper/smtpwrapper.h +++ b/noncore/net/mail/libmailwrapper/smtpwrapper.h @@ -1,55 +1,63 @@ #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 MBOXwrapper; +class RecMail; class Attachment; struct mailimf_fields; struct mailimf_field; struct mailimf_mailbox; struct mailmime; struct mailimf_address_list; class SMTPwrapper : public QObject { Q_OBJECT public: SMTPwrapper( Settings *s ); virtual ~SMTPwrapper(){} void sendMail(const Mail& mail,bool later=false ); + void flushOutbox(SMTPaccount*smtp); 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 ); - void smtpSend( mailmime *mail,bool later ); - mailimf_field *getField( mailimf_fields *fields, int type ); + mailmime *buildFilePart(const QString&filename,const QString&mimetype,const QString&content); + void smtpSend( mailmime *mail,bool later, SMTPaccount *smtp ); clist *createRcptList( mailimf_fields *fields ); - char *getFrom( mailmime *mail ); SMTPaccount *getAccount(const QString&from ); void writeToFile(const QString&file, mailmime *mail ); void readFromFile(const QString&file, char **data, size_t *size ); - void storeMail(char*mail, size_t length, const QString&box); + static void storeMail(char*mail, size_t length, const QString&box); static QString mailsmtpError( int err ); static QString getTmpFile(); 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 smtpSend(char*from,clist*rcpts,char*data,size_t size, SMTPaccount *smtp ); + void storeMail(mailmime*mail, const QString&box); Settings *settings; + + int sendQueuedMail(MBOXwrapper*wrap,SMTPaccount*smtp,RecMail*which); }; #endif diff --git a/noncore/net/mail/mailwrapper.cpp b/noncore/net/mail/mailwrapper.cpp index c5d4265..f8efd09 100644 --- a/noncore/net/mail/mailwrapper.cpp +++ b/noncore/net/mail/mailwrapper.cpp @@ -1,75 +1,74 @@ #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <qdir.h> #include "mailwrapper.h" #include "logindialog.h" -//#include "mail.h" #include "defines.h" Attachment::Attachment( DocLnk lnk ) { doc = lnk; size = QFileInfo( doc.file() ).size(); } Folder::Folder(const QString&tmp_name, const QString&sep ) { name = tmp_name; nameDisplay = name; separator = sep; } const QString& Folder::Separator()const { return separator; } IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const QString&prefix ) : Folder( name,sep ),m_MaySelect(select) { // Decode IMAP foldername nameDisplay = IMAPFolder::decodeFolderName( name ); qDebug( "folder " + name + " - displayed as " + nameDisplay ); if (prefix.length()>0) { if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) { nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length()); } } } static unsigned char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; /** * Decodes base64 encoded parts of the imapfolder name * Code taken from kde cvs: kdebase/kioslave/imap4/rfcdecoder.cc */ QString IMAPFolder::decodeFolderName( const QString &name ) { unsigned char c, i, bitcount; unsigned long ucs4, utf16, bitbuf; unsigned char base64[256], utf8[6]; unsigned long srcPtr = 0; QCString dst; QCString src = name.ascii(); /* initialize modified base64 decoding table */ memset(base64, UNDEFINED, sizeof(base64)); for (i = 0; i < sizeof(base64chars); ++i) { base64[(int)base64chars[i]] = i; } /* loop until end of string */ while (srcPtr < src.length ()) { c = src[srcPtr++]; /* deal with literal characters and &- */ if (c != '&' || src[srcPtr] == '-') { /* encode literally */ dst += c; /* skip over the '-' if this is an &- sequence */ diff --git a/noncore/net/mail/mboxwrapper.cpp b/noncore/net/mail/mboxwrapper.cpp index 8117cef..293ae1b 100644 --- a/noncore/net/mail/mboxwrapper.cpp +++ b/noncore/net/mail/mboxwrapper.cpp @@ -156,64 +156,130 @@ RecBody MBOXwrapper::fetchBody( const RecMail &mail ) QString p = MBOXPath+"/"; p+=mail.getMbox(); mailmessage * msg; char*data=0; size_t size; int r = mbox_mailstorage_init(storage,strdup(p.latin1()),0,0,0); mailfolder*folder; folder = mailfolder_new( storage,strdup(p.latin1()),NULL); r = mailfolder_connect(folder); if (r != MAIL_NO_ERROR) { qDebug("Error initializing mbox"); mailfolder_free(folder); mailstorage_free(storage); return body; } r = mailsession_get_message(folder->fld_session, mail.getNumber(), &msg); if (r != MAIL_NO_ERROR) { qDebug("Error fetching mail %i",mail.getNumber()); mailfolder_free(folder); mailstorage_free(storage); return body; } r = mailmessage_fetch(msg,&data,&size); if (r != MAIL_NO_ERROR) { qDebug("Error fetching mail %i",mail.getNumber()); mailfolder_free(folder); mailstorage_free(storage); mailmessage_free(msg); return body; } body = parseMail(msg); mailmessage_fetch_result_free(msg,data); mailfolder_free(folder); mailstorage_free(storage); return body; } void MBOXwrapper::mbox_progress( size_t current, size_t maximum ) { qDebug("MBOX %i von %i",current,maximum); } void MBOXwrapper::createFolder(const QString&) { } void MBOXwrapper::storeMessage(const char*msg,size_t length, const QString&folder) { QString p = MBOXPath+"/"; p+=folder; mailmbox_folder*f = 0; int r = mailmbox_init(p.latin1(),0,1,0,&f); if (r != MAIL_NO_ERROR) { qDebug("Error init folder"); return; } r = mailmbox_append_message(f,msg,length); if (r != MAIL_NO_ERROR) { qDebug("Error writing message folder"); } mailmbox_done(f); } + +void MBOXwrapper::fetchRawBody(const RecMail&mail,char**target,size_t*length) +{ + RecBody body; + mailstorage*storage = mailstorage_new(NULL); + QString p = MBOXPath+"/"; + p+=mail.getMbox(); + mailmessage * msg; + char*data=0; + size_t size; + + int r = mbox_mailstorage_init(storage,strdup(p.latin1()),0,0,0); + mailfolder*folder; + folder = mailfolder_new( storage,strdup(p.latin1()),NULL); + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + qDebug("Error initializing mbox"); + mailfolder_free(folder); + mailstorage_free(storage); + return; + } + r = mailsession_get_message(folder->fld_session, mail.getNumber(), &msg); + if (r != MAIL_NO_ERROR) { + qDebug("Error fetching mail %i",mail.getNumber()); + mailfolder_free(folder); + mailstorage_free(storage); + return; + } + r = mailmessage_fetch(msg,&data,&size); + if (r != MAIL_NO_ERROR) { + qDebug("Error fetching mail %i",mail.getNumber()); + mailfolder_free(folder); + mailstorage_free(storage); + mailmessage_free(msg); + return; + } + *target = data; + *length = size; + mailfolder_free(folder); + mailstorage_free(storage); + mailmessage_free(msg); +} + +void MBOXwrapper::deleteMails(const QString & mailbox,QList<RecMail> &target) +{ + QString p = MBOXPath+"/"; + p+=mailbox; + mailmbox_folder*f = 0; + int r = mailmbox_init(p.latin1(),0,1,0,&f); + if (r != MAIL_NO_ERROR) { + qDebug("Error init folder"); + return; + } + for (unsigned int i=0; i < target.count();++i) { + r = mailmbox_delete_msg(f,target.at(i)->getNumber()); + if (r!=MAILMBOX_NO_ERROR) { + qDebug("error delete mail"); + } + } + r = mailmbox_expunge(f); + if (r != MAILMBOX_NO_ERROR) { + qDebug("error expunge mailbox"); + } + mailmbox_done(f); +} + diff --git a/noncore/net/mail/mboxwrapper.h b/noncore/net/mail/mboxwrapper.h index 1bbaf79..f64ad52 100644 --- a/noncore/net/mail/mboxwrapper.h +++ b/noncore/net/mail/mboxwrapper.h @@ -1,32 +1,35 @@ #ifndef __MBOX_WRAPPER_H #define __MBOX_WRAPPER_H #include "genericwrapper.h" #include <qstring.h> class RecMail; class RecBody; class MBOXwrapper : public Genericwrapper { Q_OBJECT public: MBOXwrapper(const QString & dir); virtual ~MBOXwrapper(); virtual void listMessages(const QString & mailbox, QList<RecMail> &target ); virtual QList<Folder>* listFolders(); virtual void deleteMail(const RecMail&mail); virtual void answeredMail(const RecMail&mail); virtual void createFolder(const QString&aFolder); virtual void storeMessage(const char*msg,size_t length, const QString&folder); virtual RecBody fetchBody( const RecMail &mail ); static void mbox_progress( size_t current, size_t maximum ); + virtual void fetchRawBody(const RecMail&mail,char**target,size_t*length); + virtual void deleteMails(const QString & mailbox,QList<RecMail> &target); + protected: QString MBOXPath; }; #endif diff --git a/noncore/net/mail/opiemail.cpp b/noncore/net/mail/opiemail.cpp index 7ab4e0d..9257866 100644 --- a/noncore/net/mail/opiemail.cpp +++ b/noncore/net/mail/opiemail.cpp @@ -1,55 +1,74 @@ +#include <qmessagebox.h> #include "opiemail.h" #include "editaccounts.h" #include "composemail.h" +#include "smtpwrapper.h" OpieMail::OpieMail( QWidget *parent, const char *name, WFlags flags ) : MainWindow( parent, name, flags ) { settings = new Settings(); folderView->populate( settings->getAccounts() ); connect( composeMail, SIGNAL( activated() ), SLOT( slotComposeMail() ) ); connect( sendQueued, SIGNAL( activated() ), SLOT( slotSendQueued() ) ); // connect( searchMails, SIGNAL( activated() ), SLOT( slotSearchMails() ) ); connect( editSettings, SIGNAL( activated() ), SLOT( slotEditSettings() ) ); connect( editAccounts, SIGNAL( activated() ), SLOT( slotEditAccounts() ) ); } void OpieMail::slotComposeMail() { qDebug( "Compose Mail" ); ComposeMail compose( settings, this, 0 , true ); compose.showMaximized(); compose.slotAdjustColumns(); compose.exec(); } void OpieMail::slotSendQueued() { qDebug( "Send Queued" ); + SMTPaccount *smtp = 0; + + QList<Account> list = settings->getAccounts(); + Account *it; +// if (list.count()==1) { + for ( it = list.first(); it; it = list.next() ) { + if ( it->getType().compare( "SMTP" ) == 0 ) { + smtp = static_cast<SMTPaccount *>(it); + break; + } + } +// } + if (smtp) { + SMTPwrapper * wrap = new SMTPwrapper(settings); + wrap->flushOutbox(smtp); + QMessageBox::information(0,tr("Info"),tr("Mail queue flushed")); + } } void OpieMail::slotSearchMails() { qDebug( "Search Mails" ); } void OpieMail::slotEditSettings() { qDebug( "Edit Settings" ); } void OpieMail::slotEditAccounts() { qDebug( "Edit Accounts" ); EditAccounts eaDialog( settings, this, 0, true ); eaDialog.showMaximized(); eaDialog.slotAdjustColumns(); eaDialog.exec(); if ( settings ) delete settings; settings = new Settings(); folderView->populate( settings->getAccounts() ); } diff --git a/noncore/net/mail/smtpwrapper.cpp b/noncore/net/mail/smtpwrapper.cpp index a6a46ba..b81a87f 100644 --- a/noncore/net/mail/smtpwrapper.cpp +++ b/noncore/net/mail/smtpwrapper.cpp @@ -1,84 +1,80 @@ #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <qdir.h> +#include <qt.h> #include <libetpan/libetpan.h> -#if 0 -#include <libetpan/mailimf.h> -#include <libetpan/mailsmtp.h> -#include <libetpan/mailstorage.h> -#include <libetpan/maildriver.h> -#endif #include "smtpwrapper.h" #include "mailwrapper.h" #include "mboxwrapper.h" #include "logindialog.h" +#include "mailtypes.h" #include "defines.h" SMTPwrapper::SMTPwrapper( Settings *s ) : QObject() { settings = s; } 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_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; addresses = mailimf_address_list_new_empty(); @@ -147,499 +143,572 @@ err_free_fields: mailimf_fields_free( fields ); err_free_reply: mailimf_address_list_free( reply ); mailimf_address_list_free( bcc ); mailimf_address_list_free( cc ); mailimf_address_list_free( to ); err_free_from: mailimf_mailbox_list_free( from ); err_free_fromBox: mailimf_mailbox_free( fromBox ); err_free_sender: mailimf_mailbox_free( sender ); err_free: free( subject ); qDebug( "createImfFields - error" ); return NULL; // Error :( } mailmime *SMTPwrapper::buildTxtPart(const QString&str ) { mailmime *txtPart; mailmime_fields *fields; mailmime_content *content; mailmime_parameter *param; char *txt = strdup( str.latin1() ); int err; param = mailmime_parameter_new( strdup( "charset" ), strdup( "iso-8859-1" ) ); if ( param == NULL ) goto err_free; content = mailmime_content_new_with_str( "text/plain" ); if ( content == NULL ) goto err_free_param; err = clist_append( content->ct_parameters, param ); if ( err != MAILIMF_NO_ERROR ) goto err_free_content; fields = mailmime_fields_new_encoding( MAILMIME_MECHANISM_8BIT ); if ( fields == NULL ) goto err_free_content; txtPart = mailmime_new_empty( content, fields ); if ( txtPart == NULL ) goto err_free_fields; err = mailmime_set_body_text( txtPart, txt, strlen( txt ) ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; return txtPart; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_fields: mailmime_fields_free( fields ); err_free_content: mailmime_content_free( content ); err_free_param: mailmime_parameter_free( param ); err_free: free( txt ); qDebug( "buildTxtPart - error" ); return NULL; // Error :( } -mailmime *SMTPwrapper::buildFilePart(const QString&filename,const QString&mimetype ) +mailmime *SMTPwrapper::buildFilePart(const QString&filename,const QString&mimetype,const QString&TextContent ) { - mailmime * filePart; - mailmime_fields * fields; - mailmime_content * content; - mailmime_parameter * param = NULL; + mailmime * filePart = 0; + mailmime_fields * fields = 0; + mailmime_content * content = 0; + mailmime_parameter * param = 0; + char*name = 0; + char*file = 0; int err; int pos = filename.findRev( '/' ); - QString tmp = filename.right( filename.length() - ( pos + 1 ) ); - char *name = strdup( tmp.latin1() ); // just filename - char *file = strdup( filename.latin1() ); // full name with path + + if (filename.length()>0) { + QString tmp = filename.right( filename.length() - ( pos + 1 ) ); + name = strdup( tmp.latin1() ); // just filename + file = strdup( filename.latin1() ); // full name with path + } char *mime = strdup( mimetype.latin1() ); // mimetype -e.g. text/plain - fields = mailmime_fields_new_filename( - MAILMIME_DISPOSITION_TYPE_ATTACHMENT, name, - MAILMIME_MECHANISM_BASE64 ); - if ( fields == NULL ) goto err_free; - - content = mailmime_content_new_with_str( mime ); - if ( content == NULL ) goto err_free_fields; - - if ( mimetype.compare( "text/plain" ) == 0 ) { + int disptype = MAILMIME_DISPOSITION_TYPE_ATTACHMENT; + int mechanism = MAILMIME_MECHANISM_BASE64; + + if ( mimetype.startsWith( "text/" ) ) { param = mailmime_parameter_new( strdup( "charset" ), - strdup( "iso-8859-1" ) ); - if ( param == NULL ) goto err_free_content; - - err = clist_append( content->ct_parameters, param ); - if ( err != MAILIMF_NO_ERROR ) goto err_free_param; + strdup( "iso-8859-1" ) ); + disptype = MAILMIME_DISPOSITION_TYPE_INLINE; + mechanism = MAILMIME_MECHANISM_QUOTED_PRINTABLE; } - filePart = mailmime_new_empty( content, fields ); - if ( filePart == NULL ) goto err_free_param; - - err = mailmime_set_body_file( filePart, file ); - if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart; + fields = mailmime_fields_new_filename( + disptype, name, + mechanism ); + content = mailmime_content_new_with_str( mime ); + if (content!=0 && fields != 0) { + if (param) { + clist_append(content->ct_parameters,param); + param = 0; + } + if (filename.length()>0) { + QFileInfo f(filename); + param = mailmime_parameter_new(strdup("name"),strdup(f.fileName().latin1())); + clist_append(content->ct_parameters,param); + param = 0; + } + filePart = mailmime_new_empty( content, fields ); + } + if (filePart) { + if (filename.length()>0) { + err = mailmime_set_body_file( filePart, file ); + } else { + err = mailmime_set_body_text(filePart,strdup(TextContent.ascii()),TextContent.length()); + } + if (err != MAILIMF_NO_ERROR) { + qDebug("Error setting body with file %s",file); + mailmime_free( filePart ); + filePart = 0; + } + } + if (!filePart) { + if ( param != NULL ) { + mailmime_parameter_free( param ); + } + if (content) { + mailmime_content_free( content ); + } else { + if (mime) { + free( mime ); + } + } + if (fields) { + mailmime_fields_free( fields ); + } else { + if (name) { + free( name ); + } + if (file) { + free( file ); + } + } + } return filePart; // Success :) -err_free_filePart: - mailmime_free( filePart ); -err_free_param: - if ( param != NULL ) mailmime_parameter_free( param ); -err_free_content: - mailmime_content_free( content ); -err_free_fields: - mailmime_fields_free( fields ); -err_free: - free( name ); - free( mime ); - free( file ); - qDebug( "buildFilePart - error" ); - - return NULL; // Error :( } void SMTPwrapper::addFileParts( mailmime *message,const QList<Attachment>&files ) { const Attachment *it; - /* work around for the brainfucked qlist which can not act with const values */ - for ( it = ((QList<Attachment>)files).first(); it; it = ((QList<Attachment>)files).next() ) { + unsigned int count = files.count(); + qDebug("List contains %i values",count); + for ( unsigned int i = 0; i < count; ++i ) { qDebug( "Adding file" ); mailmime *filePart; int err; + it = ((QList<Attachment>)files).at(i); - filePart = buildFilePart( it->getFileName(), it->getMimeType() ); - if ( filePart == NULL ) goto err_free; - + filePart = buildFilePart( it->getFileName(), it->getMimeType(),"" ); + if ( filePart == NULL ) { + qDebug( "addFileParts: error adding file:" ); + qDebug( it->getFileName() ); + continue; + } err = mailmime_smart_add_part( message, filePart ); - if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart; - - continue; // Success :) - - err_free_filePart: - mailmime_free( filePart ); - err_free: - qDebug( "addFileParts: error adding file:" ); - qDebug( it->getFileName() ); + if ( err != MAILIMF_NO_ERROR ) { + mailmime_free( filePart ); + qDebug("error smart add"); + } } } mailmime *SMTPwrapper::createMimeMail(const Mail &mail ) { mailmime *message, *txtPart; mailimf_fields *fields; int err; fields = createImfFields( mail ); if ( fields == NULL ) goto err_free; message = mailmime_new_message_data( NULL ); if ( message == NULL ) goto err_free_fields; mailmime_set_imf_fields( message, fields ); - txtPart = buildTxtPart( mail.getMessage() ); + if (mail.getAttachments().count()==0) { + txtPart = buildTxtPart( mail.getMessage() ); + } else { + txtPart = buildFilePart("","text/plain",mail.getMessage()); + } if ( txtPart == NULL ) goto err_free_message; err = mailmime_smart_add_part( message, txtPart ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; addFileParts( message, mail.getAttachments() ); return message; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_message: mailmime_free( message ); err_free_fields: mailimf_fields_free( fields ); err_free: qDebug( "createMimeMail: error" ); return NULL; // Error :( } mailimf_field *SMTPwrapper::getField( mailimf_fields *fields, int type ) { mailimf_field *field; clistiter *it; it = clist_begin( fields->fld_list ); while ( it ) { field = (mailimf_field *) it->data; if ( field->fld_type == type ) { return field; } it = it->next; } return NULL; } void SMTPwrapper::addRcpts( clist *list, mailimf_address_list *addr_list ) { clistiter *it, *it2; for ( it = clist_begin( addr_list->ad_list ); it; it = it->next ) { mailimf_address *addr; addr = (mailimf_address *) it->data; if ( addr->ad_type == MAILIMF_ADDRESS_MAILBOX ) { esmtp_address_list_add( list, addr->ad_data.ad_mailbox->mb_addr_spec, 0, NULL ); } else if ( addr->ad_type == MAILIMF_ADDRESS_GROUP ) { clist *l = addr->ad_data.ad_group->grp_mb_list->mb_list; for ( it2 = clist_begin( l ); it2; it2 = it2->next ) { mailimf_mailbox *mbox; mbox = (mailimf_mailbox *) it2->data; esmtp_address_list_add( list, mbox->mb_addr_spec, 0, NULL ); } } } } clist *SMTPwrapper::createRcptList( mailimf_fields *fields ) { clist *rcptList; mailimf_field *field; rcptList = esmtp_address_list_new(); field = getField( fields, MAILIMF_FIELD_TO ); if ( field && (field->fld_type == MAILIMF_FIELD_TO) && field->fld_data.fld_to->to_addr_list ) { addRcpts( rcptList, field->fld_data.fld_to->to_addr_list ); } field = getField( fields, MAILIMF_FIELD_CC ); if ( field && (field->fld_type == MAILIMF_FIELD_CC) && field->fld_data.fld_cc->cc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_cc->cc_addr_list ); } field = getField( fields, MAILIMF_FIELD_BCC ); if ( field && (field->fld_type == MAILIMF_FIELD_BCC) && field->fld_data.fld_bcc->bcc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_bcc->bcc_addr_list ); } return rcptList; } -char *SMTPwrapper::getFrom( mailmime *mail ) +char *SMTPwrapper::getFrom( mailimf_field *ffrom) { char *from = NULL; - - mailimf_field *ffrom; - ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM ); if ( ffrom && (ffrom->fld_type == MAILIMF_FIELD_FROM) && ffrom->fld_data.fld_from->frm_mb_list && ffrom->fld_data.fld_from->frm_mb_list->mb_list ) { clist *cl = ffrom->fld_data.fld_from->frm_mb_list->mb_list; clistiter *it; for ( it = clist_begin( cl ); it; it = it->next ) { mailimf_mailbox *mb = (mailimf_mailbox *) it->data; from = strdup( mb->mb_addr_spec ); } } return from; } -SMTPaccount *SMTPwrapper::getAccount(const QString&from ) +char *SMTPwrapper::getFrom( mailmime *mail ) +{ + mailimf_field *ffrom = 0; + ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM ); + return getFrom(ffrom); +} + +SMTPaccount *SMTPwrapper::getAccount(const QString&name ) { SMTPaccount *smtp; QList<Account> list = settings->getAccounts(); Account *it; for ( it = list.first(); it; it = list.next() ) { if ( it->getType().compare( "SMTP" ) == 0 ) { smtp = static_cast<SMTPaccount *>(it); - if ( smtp->getMail().compare( from ) == 0 ) { + if ( smtp->getName()== name ) { qDebug( "SMTPaccount found for" ); - qDebug( from ); + qDebug( name ); return smtp; } } } return NULL; } QString SMTPwrapper::getTmpFile() { int num = 0; QString unique; QDir dir( "/tmp" ); - QStringList::Iterator it; QStringList list = dir.entryList( "opiemail-tmp-*" ); + do { unique.setNum( num++ ); } while ( list.contains( "opiemail-tmp-" + unique ) > 0 ); return "/tmp/opiemail-tmp-" + unique; } void SMTPwrapper::writeToFile(const QString&file, mailmime *mail ) { FILE *f; int err, col = 0; f = fopen( file.latin1(), "w" ); if ( f == NULL ) { qDebug( "writeToFile: error opening file" ); return; } err = mailmime_write( f, &col, mail ); if ( err != MAILIMF_NO_ERROR ) { fclose( f ); qDebug( "writeToFile: error writing mailmime" ); return; } fclose( f ); } void SMTPwrapper::readFromFile(const QString&file, char **data, size_t *size ) { QFile msg_cache(file); QString msg = ""; msg_cache.open(IO_ReadOnly); char*message = new char[4096]; memset(message,0,4096); while (msg_cache.readBlock(message,4095)>0) { msg+=message; memset(message,0,4096); } delete message; *data = (char*)malloc(msg.length()+1*sizeof(char)); memset(*data,0,msg.length()+1); memcpy(*data,msg.ascii(),msg.length()); *size=msg.length(); - -#if 0 - char *buf; - struct stat st; - int fd, count = 0, total = 0; - - fd = open( file.latin1(), O_RDONLY, 0 ); - if ( fd == -1 ) return; - - if ( fstat( fd, &st ) != 0 ) goto err_close; - if ( !st.st_size ) goto err_close; - - buf = (char *) malloc( st.st_size ); - if ( !buf ) goto err_close; - - while ( ( total < st.st_size ) && ( count >= 0 ) ) { - count = read( fd, buf + total, st.st_size - total ); - total += count; - } - if ( count < 0 ) goto err_free; - - *data = buf; - *size = st.st_size; - - close( fd ); - - return; // Success :) - -err_free: - free( buf ); -err_close: - close( fd ); -#endif } void SMTPwrapper::progress( size_t current, size_t maximum ) { - qDebug( "Current: %i of %i", current, maximum ); +// qDebug( "Current: %i of %i", current, maximum ); } void SMTPwrapper::storeMail(char*mail, size_t length, const QString&box) { if (!mail) return; QString localfolders = (QString) getenv( "HOME" ) + QString("/Applications/opiemail/localmail/"); MBOXwrapper*wrap = new MBOXwrapper(localfolders); wrap->storeMessage(mail,length,box); delete wrap; } -void SMTPwrapper::smtpSend( mailmime *mail,bool later ) +void SMTPwrapper::smtpSend( mailmime *mail,bool later, SMTPaccount *smtp ) { - mailsmtp *session; - clist *rcpts; - char *from, *data, *server, *user = NULL, *pass = NULL; + clist *rcpts = 0; + char *from, *data; size_t size; - int err; - bool ssl; - uint16_t port; - - from = getFrom( mail ); - SMTPaccount *smtp = getAccount( from ); if ( smtp == NULL ) { - free(from); return; } - rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); - + from = data = 0; + QString file = getTmpFile(); writeToFile( file, mail ); - readFromFile( file, &data, &size ); QFile f( file ); f.remove(); - storeMail(data,size,(later?"Outgoing":"Sent")); - if (later) { - smtp_address_list_free( rcpts ); + storeMail(data,size,"Outgoing"); if (data) free( data ); - if (from) free(from); return; } + from = getFrom( mail ); + rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); + smtpSend(from,rcpts,data,size,smtp); +} + +int SMTPwrapper::smtpSend(char*from,clist*rcpts,char*data,size_t size, SMTPaccount *smtp ) +{ + char *server, *user, *pass; + bool ssl; + uint16_t port; + mailsmtp *session; + int err,result; + + result = 1; + server = user = pass = 0; server = strdup( smtp->getServer().latin1() ); ssl = smtp->getSSL(); port = smtp->getPort().toUInt(); session = mailsmtp_new( 20, &progress ); if ( session == NULL ) goto free_mem; 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 ) goto free_mem_session; + if ( err != MAILSMTP_NO_ERROR ) {result = 0;goto free_mem_session;} err = mailsmtp_init( session ); - if ( err != MAILSMTP_NO_ERROR ) goto free_con_session; + if ( err != MAILSMTP_NO_ERROR ) {result = 0; goto free_con_session;} qDebug( "INIT OK" ); if ( smtp->getLogin() ) { 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 = strdup( login.getUser().latin1() ); pass = strdup( login.getPassword().latin1() ); } else { - goto free_con_session; + result = 0; goto free_con_session; } } else { user = strdup( smtp->getUser().latin1() ); pass = strdup( smtp->getPassword().latin1() ); } qDebug( "session->auth: %i", session->auth); err = mailsmtp_auth( session, user, pass ); if ( err == MAILSMTP_NO_ERROR ) qDebug("auth ok"); qDebug( "Done auth!" ); } err = mailsmtp_send( session, from, rcpts, data, size ); - if ( err != MAILSMTP_NO_ERROR ) goto free_con_session; + if ( err != MAILSMTP_NO_ERROR ) {result = 0; goto free_con_session;} qDebug( "Mail sent." ); + storeMail(data,size,"Sent"); free_con_session: mailsmtp_quit( session ); free_mem_session: mailsmtp_free( session ); free_mem: - smtp_address_list_free( rcpts ); + if (rcpts) smtp_address_list_free( rcpts ); if (data) free( data ); - if (from) free(from); if (server) free( server ); + if (from) free( from ); if ( smtp->getLogin() ) { free( user ); free( pass ); } - free( from ); + return result; } void SMTPwrapper::sendMail(const Mail&mail,bool later ) { mailmime * mimeMail; - + + SMTPaccount *smtp = getAccount(mail.getName()); + mimeMail = createMimeMail(mail ); if ( mimeMail == NULL ) { qDebug( "sendMail: error creating mime mail" ); } else { - smtpSend( mimeMail,later ); + smtpSend( mimeMail,later,smtp); mailmime_free( mimeMail ); + qDebug("Clean up done"); + } +} + +int SMTPwrapper::sendQueuedMail(MBOXwrapper*wrap,SMTPaccount*smtp,RecMail*which) +{ + char*data = 0; + size_t length = 0; + size_t curTok = 0; + mailimf_fields *fields = 0; + mailimf_field*ffrom = 0; + clist *rcpts = 0; + char*from = 0; + + wrap->fetchRawBody(*which,&data,&length); + if (!data) return 0; + int err = mailimf_fields_parse( data, length, &curTok, &fields ); + if (err != MAILIMF_NO_ERROR) { + free(data); + delete wrap; + return 0; + } + + rcpts = createRcptList( fields ); + ffrom = getField(fields, MAILIMF_FIELD_FROM ); + from = getFrom(ffrom); + qDebug("Size: %i vs. %i",length,strlen(data)); + if (rcpts && from) { + return smtpSend(from,rcpts,data,strlen(data),smtp ); } + return 0; +} + +/* this is a special fun */ +void SMTPwrapper::flushOutbox(SMTPaccount*smtp) +{ + if (!smtp) return; + QString localfolders = (QString) getenv( "HOME" ) + QString("/Applications/opiemail/localmail/"); + MBOXwrapper*wrap = new MBOXwrapper(localfolders); + if (!wrap) { + qDebug("memory error"); + return; + } + QList<RecMail> mailsToSend; + QList<RecMail> mailsToRemove; + QString mbox("Outgoing"); + wrap->listMessages(mbox,mailsToSend); + if (mailsToSend.count()==0) { + delete wrap; + return; + } + mailsToSend.setAutoDelete(false); + 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")); + break; + } + mailsToRemove.append(mailsToSend.at(0)); + mailsToSend.removeFirst(); + } + wrap->deleteMails(mbox,mailsToRemove); + mailsToSend.setAutoDelete(true); + delete wrap; } diff --git a/noncore/net/mail/smtpwrapper.h b/noncore/net/mail/smtpwrapper.h index 41e9a8c..c0dcc11 100644 --- a/noncore/net/mail/smtpwrapper.h +++ b/noncore/net/mail/smtpwrapper.h @@ -1,55 +1,63 @@ #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 MBOXwrapper; +class RecMail; class Attachment; struct mailimf_fields; struct mailimf_field; struct mailimf_mailbox; struct mailmime; struct mailimf_address_list; class SMTPwrapper : public QObject { Q_OBJECT public: SMTPwrapper( Settings *s ); virtual ~SMTPwrapper(){} void sendMail(const Mail& mail,bool later=false ); + void flushOutbox(SMTPaccount*smtp); 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 ); - void smtpSend( mailmime *mail,bool later ); - mailimf_field *getField( mailimf_fields *fields, int type ); + mailmime *buildFilePart(const QString&filename,const QString&mimetype,const QString&content); + void smtpSend( mailmime *mail,bool later, SMTPaccount *smtp ); clist *createRcptList( mailimf_fields *fields ); - char *getFrom( mailmime *mail ); SMTPaccount *getAccount(const QString&from ); void writeToFile(const QString&file, mailmime *mail ); void readFromFile(const QString&file, char **data, size_t *size ); - void storeMail(char*mail, size_t length, const QString&box); + static void storeMail(char*mail, size_t length, const QString&box); static QString mailsmtpError( int err ); static QString getTmpFile(); 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 smtpSend(char*from,clist*rcpts,char*data,size_t size, SMTPaccount *smtp ); + void storeMail(mailmime*mail, const QString&box); Settings *settings; + + int sendQueuedMail(MBOXwrapper*wrap,SMTPaccount*smtp,RecMail*which); }; #endif |