00001 #include "generatemail.h"
00002 #include "mailwrapper.h"
00003
00004 #include <libetpan/libetpan.h>
00005
00006 #include <opie2/odebug.h>
00007
00008 #include <qt.h>
00009
00010 using namespace Opie::Core;
00011 const char* Generatemail::USER_AGENT="OpieMail v0.6";
00012
00013 Generatemail::Generatemail()
00014 {
00015 }
00016
00017 Generatemail::~Generatemail()
00018 {
00019 }
00020
00021 void Generatemail::addRcpts( clist *list, mailimf_address_list *addr_list ) {
00022 clistiter *it, *it2;
00023
00024 for ( it = clist_begin( addr_list->ad_list ); it; it = it->next ) {
00025 mailimf_address *addr;
00026 addr = (mailimf_address *) it->data;
00027
00028 if ( addr->ad_type == MAILIMF_ADDRESS_MAILBOX ) {
00029 esmtp_address_list_add( list, addr->ad_data.ad_mailbox->mb_addr_spec, 0, NULL );
00030 } else if ( addr->ad_type == MAILIMF_ADDRESS_GROUP ) {
00031 clist *l = addr->ad_data.ad_group->grp_mb_list->mb_list;
00032 for ( it2 = clist_begin( l ); it2; it2 = it2->next ) {
00033 mailimf_mailbox *mbox;
00034 mbox = (mailimf_mailbox *) it2->data;
00035 esmtp_address_list_add( list, mbox->mb_addr_spec, 0, NULL );
00036 }
00037 }
00038 }
00039 }
00040
00041 char *Generatemail::getFrom( mailimf_field *ffrom) {
00042 char *from = NULL;
00043 if ( ffrom && (ffrom->fld_type == MAILIMF_FIELD_FROM)
00044 && ffrom->fld_data.fld_from->frm_mb_list && ffrom->fld_data.fld_from->frm_mb_list->mb_list ) {
00045 clist *cl = ffrom->fld_data.fld_from->frm_mb_list->mb_list;
00046 clistiter *it;
00047 for ( it = clist_begin( cl ); it; it = it->next ) {
00048 mailimf_mailbox *mb = (mailimf_mailbox *) it->data;
00049 from = strdup( mb->mb_addr_spec );
00050 }
00051 }
00052
00053 return from;
00054 }
00055
00056 char *Generatemail::getFrom( mailmime *mail ) {
00057
00058 mailimf_field *ffrom = 0;
00059 ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM );
00060 return getFrom(ffrom);
00061 }
00062
00063 mailimf_field *Generatemail::getField( mailimf_fields *fields, int type ) {
00064 mailimf_field *field;
00065 clistiter *it;
00066
00067 it = clist_begin( fields->fld_list );
00068 while ( it ) {
00069 field = (mailimf_field *) it->data;
00070 if ( field->fld_type == type ) {
00071 return field;
00072 }
00073 it = it->next;
00074 }
00075
00076 return NULL;
00077 }
00078
00079 mailimf_address_list *Generatemail::parseAddresses(const QString&addr ) {
00080 mailimf_address_list *addresses;
00081
00082 if ( addr.isEmpty() )
00083 return NULL;
00084
00085 addresses = mailimf_address_list_new_empty();
00086
00087 bool literal_open = false;
00088 unsigned int startpos = 0;
00089 QStringList list;
00090 QString s;
00091 unsigned int i = 0;
00092 for (; i < addr.length();++i) {
00093 switch (addr[i]) {
00094 case '\"':
00095 literal_open = !literal_open;
00096 break;
00097 case ',':
00098 if (!literal_open) {
00099 s = addr.mid(startpos,i-startpos);
00100 if (!s.isEmpty()) {
00101 list.append(s);
00102 odebug << "Appended " << s.latin1() << "" << oendl;
00103 }
00104
00105 startpos = ++i;
00106 }
00107 break;
00108 default:
00109 break;
00110 }
00111 }
00112 s = addr.mid(startpos,i-startpos);
00113 if (!s.isEmpty()) {
00114 list.append(s);
00115 odebug << "Appended " << s.latin1() << "" << oendl;
00116 }
00117 QStringList::Iterator it;
00118 for ( it = list.begin(); it != list.end(); it++ ) {
00119 int err = mailimf_address_list_add_parse( addresses, (char*)(*it).latin1() );
00120 if ( err != MAILIMF_NO_ERROR ) {
00121 odebug << "Error parsing" << oendl;
00122 odebug << *it << oendl;
00123 } else {
00124 odebug << "Parse success! " << (*it).latin1() << "" << oendl;
00125 }
00126 }
00127 return addresses;
00128 }
00129
00130 mailmime *Generatemail::buildFilePart(const QString&filename,const QString&mimetype,const QString&TextContent ) {
00131 mailmime * filePart = 0;
00132 mailmime_fields * fields = 0;
00133 mailmime_content * content = 0;
00134 mailmime_parameter * param = 0;
00135 char*name = 0;
00136 char*file = 0;
00137 int err;
00138
00139 int pos = filename.findRev( '/' );
00140
00141 if (filename.length()>0) {
00142 QString tmp = filename.right( filename.length() - ( pos + 1 ) );
00143 name = strdup( tmp.latin1() );
00144 file = strdup( filename.latin1() );
00145 }
00146
00147 int disptype = MAILMIME_DISPOSITION_TYPE_ATTACHMENT;
00148 int mechanism = MAILMIME_MECHANISM_BASE64;
00149
00150 if ( mimetype.startsWith( "text/" ) ) {
00151 param = mailmime_parameter_new( strdup( "charset" ),
00152 strdup( "iso-8859-1" ) );
00153 mechanism = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
00154 }
00155
00156 fields = mailmime_fields_new_filename(
00157 disptype, name,
00158 mechanism );
00159 content = mailmime_content_new_with_str( (char*)mimetype.latin1() );
00160 if (content!=0 && fields != 0) {
00161 if (param) {
00162 clist_append(content->ct_parameters,param);
00163 param = 0;
00164 }
00165 if (filename.length()>0) {
00166 QFileInfo f(filename);
00167 param = mailmime_parameter_new(strdup("name"),strdup(f.fileName().latin1()));
00168 clist_append(content->ct_parameters,param);
00169 param = 0;
00170 }
00171 filePart = mailmime_new_empty( content, fields );
00172 }
00173 if (filePart) {
00174 if (filename.length()>0) {
00175 err = mailmime_set_body_file( filePart, file );
00176 } else {
00177 err = mailmime_set_body_text(filePart,strdup(TextContent.data()),TextContent.length());
00178 }
00179 if (err != MAILIMF_NO_ERROR) {
00180 odebug << "Error setting body with file " << file << "" << oendl;
00181 mailmime_free( filePart );
00182 filePart = 0;
00183 }
00184 }
00185
00186 if (!filePart) {
00187 if ( param != NULL ) {
00188 mailmime_parameter_free( param );
00189 }
00190 if (content) {
00191 mailmime_content_free( content );
00192 }
00193 if (fields) {
00194 mailmime_fields_free( fields );
00195 } else {
00196 if (name) {
00197 free( name );
00198 }
00199 if (file) {
00200 free( file );
00201 }
00202 }
00203 }
00204 return filePart;
00205
00206 }
00207
00208 void Generatemail::addFileParts( mailmime *message,const QList<Attachment>&files ) {
00209 const Attachment *it;
00210 unsigned int count = files.count();
00211 odebug << "List contains " << count << " values" << oendl;
00212 for ( unsigned int i = 0; i < count; ++i ) {
00213 odebug << "Adding file" << oendl;
00214 mailmime *filePart;
00215 int err;
00216 it = ((QList<Attachment>)files).at(i);
00217
00218 filePart = buildFilePart( it->getFileName(), it->getMimeType(),"" );
00219 if ( filePart == NULL ) {
00220 odebug << "addFileParts: error adding file:" << oendl;
00221 odebug << it->getFileName() << oendl;
00222 continue;
00223 }
00224 err = mailmime_smart_add_part( message, filePart );
00225 if ( err != MAILIMF_NO_ERROR ) {
00226 mailmime_free( filePart );
00227 odebug << "error smart add" << oendl;
00228 }
00229 }
00230 }
00231
00232 mailmime *Generatemail::buildTxtPart(const QString&str ) {
00233 mailmime *txtPart;
00234 mailmime_fields *fields;
00235 mailmime_content *content;
00236 mailmime_parameter *param;
00237 int err;
00238
00239 param = mailmime_parameter_new( strdup( "charset" ),
00240 strdup( "iso-8859-1" ) );
00241 if ( param == NULL )
00242 goto err_free;
00243
00244 content = mailmime_content_new_with_str( "text/plain" );
00245 if ( content == NULL )
00246 goto err_free_param;
00247
00248 err = clist_append( content->ct_parameters, param );
00249 if ( err != MAILIMF_NO_ERROR )
00250 goto err_free_content;
00251
00252 fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT);
00253 if ( fields == NULL )
00254 goto err_free_content;
00255
00256 txtPart = mailmime_new_empty( content, fields );
00257 if ( txtPart == NULL )
00258 goto err_free_fields;
00259
00260 err = mailmime_set_body_text( txtPart, (char*)str.data(), str.length() );
00261 if ( err != MAILIMF_NO_ERROR )
00262 goto err_free_txtPart;
00263
00264 return txtPart;
00265
00266 err_free_txtPart:
00267 mailmime_free( txtPart );
00268 err_free_fields:
00269 mailmime_fields_free( fields );
00270 err_free_content:
00271 mailmime_content_free( content );
00272 err_free_param:
00273 mailmime_parameter_free( param );
00274 err_free:
00275 odebug << "buildTxtPart - error" << oendl;
00276
00277 return NULL;
00278 }
00279
00280 mailimf_mailbox *Generatemail::newMailbox(const QString&name, const QString&mail ) {
00281 return mailimf_mailbox_new( strdup( name.latin1() ),
00282 strdup( mail.latin1() ) );
00283 }
00284
00285 mailimf_fields *Generatemail::createImfFields(const Opie::Core::OSmartPointer<Mail>&mail )
00286 {
00287 mailimf_fields *fields = NULL;
00288 mailimf_field *xmailer = NULL;
00289 mailimf_mailbox *sender=0,*fromBox=0;
00290 mailimf_mailbox_list *from=0;
00291 mailimf_address_list *to=0, *cc=0, *bcc=0, *reply=0;
00292 clist*in_reply_to = 0;
00293 char *subject = strdup( mail->getSubject().latin1() );
00294 int err;
00295 int res = 1;
00296
00297 sender = newMailbox( mail->getName(), mail->getMail() );
00298 if ( sender == NULL ) {
00299 res = 0;
00300 }
00301
00302 if (res) {
00303 fromBox = newMailbox( mail->getName(), mail->getMail() );
00304 }
00305 if ( fromBox == NULL ) {
00306 res = 0;
00307 }
00308
00309 if (res) {
00310 from = mailimf_mailbox_list_new_empty();
00311 }
00312 if ( from == NULL ) {
00313 res = 0;
00314 }
00315
00316 if (res && from) {
00317 err = mailimf_mailbox_list_add( from, fromBox );
00318 if ( err != MAILIMF_NO_ERROR ) {
00319 res = 0;
00320 }
00321 }
00322
00323 if (res) to = parseAddresses( mail->getTo() );
00324 if (res) cc = parseAddresses( mail->getCC() );
00325 if (res) bcc = parseAddresses( mail->getBCC() );
00326 if (res) reply = parseAddresses( mail->getReply() );
00327
00328 if (res && mail->Inreply().count()>0) {
00329 in_reply_to = clist_new();
00330 char*c_reply;
00331 unsigned int nsize = 0;
00332 for (QStringList::ConstIterator it=mail->Inreply().begin();
00333 it != mail->Inreply().end();++it) {
00334 if ((*it).isEmpty())
00335 continue;
00336 QString h((*it));
00337 while (h.length()>0 && h[0]=='<') {
00338 h.remove(0,1);
00339 }
00340 while (h.length()>0 && h[h.length()-1]=='>') {
00341 h.remove(h.length()-1,1);
00342 }
00343 if (h.isEmpty()) continue;
00344 nsize = strlen(h.latin1());
00345
00346 c_reply = (char*)malloc( (nsize+1)*sizeof(char));
00347 memset(c_reply,0,nsize+1);
00348 memcpy(c_reply,h.latin1(),nsize);
00349 clist_append(in_reply_to,c_reply);
00350 odebug << "In reply to: " << c_reply << "" << oendl;
00351 }
00352 }
00353
00354 if (res) {
00355 fields = mailimf_fields_new_with_data( from, sender, reply, to, cc, bcc,
00356 in_reply_to, NULL, subject );
00357 if ( fields == NULL ) {
00358 odebug << "Error creating mailimf fields" << oendl;
00359 res = 0;
00360 }
00361 }
00362 if (res) xmailer = mailimf_field_new_custom( strdup( "User-Agent" ),
00363 strdup( USER_AGENT ) );
00364 if ( xmailer == NULL ) {
00365 res = 0;
00366 } else {
00367 err = mailimf_fields_add( fields, xmailer );
00368 if ( err != MAILIMF_NO_ERROR ) {
00369 res = 0;
00370 }
00371 }
00372 if (!res ) {
00373 if (xmailer) {
00374 mailimf_field_free( xmailer );
00375 xmailer = NULL;
00376 }
00377 if (fields) {
00378 mailimf_fields_free( fields );
00379 fields = NULL;
00380 } else {
00381 if (reply)
00382 mailimf_address_list_free( reply );
00383 if (bcc)
00384 mailimf_address_list_free( bcc );
00385 if (cc)
00386 mailimf_address_list_free( cc );
00387 if (to)
00388 mailimf_address_list_free( to );
00389 if (fromBox) {
00390 mailimf_mailbox_free( fromBox );
00391 } else if (from) {
00392 mailimf_mailbox_list_free( from );
00393 }
00394 if (sender) {
00395 mailimf_mailbox_free( sender );
00396 }
00397 if (subject) {
00398 free( subject );
00399 }
00400 }
00401 }
00402 return fields;
00403 }
00404
00405 mailmime *Generatemail::createMimeMail(const Opie::Core::OSmartPointer<Mail> &mail ) {
00406 mailmime *message, *txtPart;
00407 mailimf_fields *fields;
00408 int err;
00409
00410 fields = createImfFields( mail );
00411 if ( fields == NULL )
00412 goto err_free;
00413
00414 message = mailmime_new_message_data( NULL );
00415 if ( message == NULL )
00416 goto err_free_fields;
00417
00418 mailmime_set_imf_fields( message, fields );
00419
00420 txtPart = buildTxtPart( mail->getMessage() );
00421
00422 if ( txtPart == NULL )
00423 goto err_free_message;
00424
00425 err = mailmime_smart_add_part( message, txtPart );
00426 if ( err != MAILIMF_NO_ERROR )
00427 goto err_free_txtPart;
00428
00429 addFileParts( message, mail->getAttachments() );
00430
00431 return message;
00432
00433 err_free_txtPart:
00434 mailmime_free( txtPart );
00435 err_free_message:
00436 mailmime_free( message );
00437 err_free_fields:
00438 mailimf_fields_free( fields );
00439 err_free:
00440 odebug << "createMimeMail: error" << oendl;
00441
00442 return NULL;
00443 }
00444
00445 clist *Generatemail::createRcptList( mailimf_fields *fields ) {
00446 clist *rcptList;
00447 mailimf_field *field;
00448
00449 rcptList = esmtp_address_list_new();
00450
00451 field = getField( fields, MAILIMF_FIELD_TO );
00452 if ( field && (field->fld_type == MAILIMF_FIELD_TO)
00453 && field->fld_data.fld_to->to_addr_list ) {
00454 addRcpts( rcptList, field->fld_data.fld_to->to_addr_list );
00455 }
00456
00457 field = getField( fields, MAILIMF_FIELD_CC );
00458 if ( field && (field->fld_type == MAILIMF_FIELD_CC)
00459 && field->fld_data.fld_cc->cc_addr_list ) {
00460 addRcpts( rcptList, field->fld_data.fld_cc->cc_addr_list );
00461 }
00462
00463 field = getField( fields, MAILIMF_FIELD_BCC );
00464 if ( field && (field->fld_type == MAILIMF_FIELD_BCC)
00465 && field->fld_data.fld_bcc->bcc_addr_list ) {
00466 addRcpts( rcptList, field->fld_data.fld_bcc->bcc_addr_list );
00467 }
00468
00469 return rcptList;
00470 }