summaryrefslogtreecommitdiff
path: root/noncore/net/mail/libmailwrapper/mailwrapper.cpp
Unidiff
Diffstat (limited to 'noncore/net/mail/libmailwrapper/mailwrapper.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/net/mail/libmailwrapper/mailwrapper.cpp643
1 files changed, 643 insertions, 0 deletions
diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.cpp b/noncore/net/mail/libmailwrapper/mailwrapper.cpp
new file mode 100644
index 0000000..17bed65
--- a/dev/null
+++ b/noncore/net/mail/libmailwrapper/mailwrapper.cpp
@@ -0,0 +1,643 @@
1#include <qfileinfo.h>
2#include <stdlib.h>
3#include <sys/stat.h>
4#include <sys/types.h>
5#include <unistd.h>
6#include <fcntl.h>
7#include <string.h>
8#include <qdir.h>
9#include <qtextstream.h>
10
11#include "mailwrapper.h"
12#include "logindialog.h"
13#include "mail.h"
14#include "defines.h"
15
16Attachment::Attachment( DocLnk lnk )
17{
18 doc = lnk;
19 size = QFileInfo( doc.file() ).size();
20}
21
22Folder::Folder(const QString&tmp_name )
23{
24 name = tmp_name;
25 nameDisplay = name;
26
27 for ( int pos = nameDisplay.find( '&' ); pos != -1;
28 pos = nameDisplay.find( '&' ) ) {
29 int end = nameDisplay.find( '-' );
30 if ( end == -1 || end <= pos ) break;
31 QString str64 = nameDisplay.mid( pos + 1, end - pos - 1 );
32 // TODO: do real base64 decoding here !
33 if ( str64.compare( "APw" ) == 0 ) {
34 nameDisplay = nameDisplay.replace( pos, end - pos + 1, "ue" );
35 } else if ( str64.compare( "APY" ) == 0 ) {
36 nameDisplay = nameDisplay.replace( pos, end - pos + 1, "oe" );
37 }
38 }
39
40 qDebug( "folder " + name + " - displayed as " + nameDisplay );
41}
42
43MailWrapper::MailWrapper( Settings *s )
44 : QObject()
45{
46 settings = s;
47}
48
49QString MailWrapper::mailsmtpError( int errnum )
50{
51 switch ( errnum ) {
52 case MAILSMTP_NO_ERROR:
53 return tr( "No error" );
54 case MAILSMTP_ERROR_UNEXPECTED_CODE:
55 return tr( "Unexpected error code" );
56 case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE:
57 return tr( "Service not available" );
58 case MAILSMTP_ERROR_STREAM:
59 return tr( "Stream error" );
60 case MAILSMTP_ERROR_HOSTNAME:
61 return tr( "gethostname() failed" );
62 case MAILSMTP_ERROR_NOT_IMPLEMENTED:
63 return tr( "Not implemented" );
64 case MAILSMTP_ERROR_ACTION_NOT_TAKEN:
65 return tr( "Error, action not taken" );
66 case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION:
67 return tr( "Data exceeds storage allocation" );
68 case MAILSMTP_ERROR_IN_PROCESSING:
69 return tr( "Error in processing" );
70 // case MAILSMTP_ERROR_INSUFFISANT_SYSTEM_STORAGE:
71 // return tr( "Insufficient system storage" );
72 case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE:
73 return tr( "Mailbox unavailable" );
74 case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED:
75 return tr( "Mailbox name not allowed" );
76 case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND:
77 return tr( "Bad command sequence" );
78 case MAILSMTP_ERROR_USER_NOT_LOCAL:
79 return tr( "User not local" );
80 case MAILSMTP_ERROR_TRANSACTION_FAILED:
81 return tr( "Transaction failed" );
82 case MAILSMTP_ERROR_MEMORY:
83 return tr( "Memory error" );
84 case MAILSMTP_ERROR_CONNECTION_REFUSED:
85 return tr( "Connection refused" );
86 default:
87 return tr( "Unknown error code" );
88 }
89}
90
91mailimf_mailbox *MailWrapper::newMailbox(const QString&name, const QString&mail )
92{
93 return mailimf_mailbox_new( strdup( name.latin1() ),
94 strdup( mail.latin1() ) );
95}
96
97mailimf_address_list *MailWrapper::parseAddresses(const QString&addr )
98{
99 mailimf_address_list *addresses;
100
101 if ( addr.isEmpty() ) return NULL;
102
103 addresses = mailimf_address_list_new_empty();
104
105 QStringList list = QStringList::split( ',', addr );
106 QStringList::Iterator it;
107 for ( it = list.begin(); it != list.end(); it++ ) {
108 char *str = strdup( (*it).latin1() );
109 int err = mailimf_address_list_add_parse( addresses, str );
110 if ( err != MAILIMF_NO_ERROR ) {
111 qDebug( "Error parsing" );
112 qDebug( *it );
113 free( str );
114 } else {
115 qDebug( "Parse success! :)" );
116 }
117 }
118
119 return addresses;
120}
121
122mailimf_fields *MailWrapper::createImfFields( Mail *mail )
123{
124 mailimf_fields *fields;
125 mailimf_field *xmailer;
126 mailimf_mailbox *sender, *fromBox;
127 mailimf_mailbox_list *from;
128 mailimf_address_list *to, *cc, *bcc, *reply;
129 char *subject = strdup( mail->getSubject().latin1() );
130 int err;
131
132 sender = newMailbox( mail->getName(), mail->getMail() );
133 if ( sender == NULL ) goto err_free;
134
135 fromBox = newMailbox( mail->getName(), mail->getMail() );
136 if ( fromBox == NULL ) goto err_free_sender;
137
138 from = mailimf_mailbox_list_new_empty();
139 if ( from == NULL ) goto err_free_fromBox;
140
141 err = mailimf_mailbox_list_add( from, fromBox );
142 if ( err != MAILIMF_NO_ERROR ) goto err_free_from;
143
144 to = parseAddresses( mail->getTo() );
145 if ( to == NULL ) goto err_free_from;
146
147 cc = parseAddresses( mail->getCC() );
148 bcc = parseAddresses( mail->getBCC() );
149 reply = parseAddresses( mail->getReply() );
150
151 fields = mailimf_fields_new_with_data( from, sender, reply, to, cc, bcc,
152 NULL, NULL, subject );
153 if ( fields == NULL ) goto err_free_reply;
154
155 xmailer = mailimf_field_new_custom( strdup( "User-Agent" ),
156 strdup( USER_AGENT ) );
157 if ( xmailer == NULL ) goto err_free_fields;
158
159 err = mailimf_fields_add( fields, xmailer );
160 if ( err != MAILIMF_NO_ERROR ) goto err_free_xmailer;
161
162 return fields; // Success :)
163
164err_free_xmailer:
165 mailimf_field_free( xmailer );
166err_free_fields:
167 mailimf_fields_free( fields );
168err_free_reply:
169 mailimf_address_list_free( reply );
170 mailimf_address_list_free( bcc );
171 mailimf_address_list_free( cc );
172 mailimf_address_list_free( to );
173err_free_from:
174 mailimf_mailbox_list_free( from );
175err_free_fromBox:
176 mailimf_mailbox_free( fromBox );
177err_free_sender:
178 mailimf_mailbox_free( sender );
179err_free:
180 free( subject );
181 qDebug( "createImfFields - error" );
182
183 return NULL; // Error :(
184}
185
186mailmime *MailWrapper::buildTxtPart( QString str )
187{
188 mailmime *txtPart;
189 mailmime_fields *fields;
190 mailmime_content *content;
191 mailmime_parameter *param;
192 char *txt = strdup( str.latin1() );
193 int err;
194
195 param = mailmime_parameter_new( strdup( "charset" ),
196 strdup( "iso-8859-1" ) );
197 if ( param == NULL ) goto err_free;
198
199 content = mailmime_content_new_with_str( "text/plain" );
200 if ( content == NULL ) goto err_free_param;
201
202 err = clist_append( content->parameters, param );
203 if ( err != MAILIMF_NO_ERROR ) goto err_free_content;
204
205 fields = mailmime_fields_new_encoding( MAILMIME_MECHANISM_8BIT );
206 if ( fields == NULL ) goto err_free_content;
207
208 txtPart = mailmime_new_empty( content, fields );
209 if ( txtPart == NULL ) goto err_free_fields;
210
211 err = mailmime_set_body_text( txtPart, txt, strlen( txt ) );
212 if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart;
213
214 return txtPart; // Success :)
215
216err_free_txtPart:
217 mailmime_free( txtPart );
218err_free_fields:
219 mailmime_fields_free( fields );
220err_free_content:
221 mailmime_content_free( content );
222err_free_param:
223 mailmime_parameter_free( param );
224err_free:
225 free( txt );
226 qDebug( "buildTxtPart - error" );
227
228 return NULL; // Error :(
229}
230
231mailmime *MailWrapper::buildFilePart( QString filename, QString mimetype )
232{
233 mailmime * filePart;
234 mailmime_fields * fields;
235 mailmime_content * content;
236 mailmime_parameter * param = NULL;
237 int err;
238
239 int pos = filename.findRev( '/' );
240 QString tmp = filename.right( filename.length() - ( pos + 1 ) );
241 char *name = strdup( tmp.latin1() ); // just filename
242 char *file = strdup( filename.latin1() ); // full name with path
243 char *mime = strdup( mimetype.latin1() ); // mimetype -e.g. text/plain
244
245 fields = mailmime_fields_new_filename(
246 MAILMIME_DISPOSITION_TYPE_ATTACHMENT, name,
247 MAILMIME_MECHANISM_BASE64 );
248 if ( fields == NULL ) goto err_free;
249
250 content = mailmime_content_new_with_str( mime );
251 if ( content == NULL ) goto err_free_fields;
252
253 if ( mimetype.compare( "text/plain" ) == 0 ) {
254 param = mailmime_parameter_new( strdup( "charset" ),
255 strdup( "iso-8859-1" ) );
256 if ( param == NULL ) goto err_free_content;
257
258 err = clist_append( content->parameters, param );
259 if ( err != MAILIMF_NO_ERROR ) goto err_free_param;
260 }
261
262 filePart = mailmime_new_empty( content, fields );
263 if ( filePart == NULL ) goto err_free_param;
264
265 err = mailmime_set_body_file( filePart, file );
266 if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart;
267
268 return filePart; // Success :)
269
270err_free_filePart:
271 mailmime_free( filePart );
272err_free_param:
273 if ( param != NULL ) mailmime_parameter_free( param );
274err_free_content:
275 mailmime_content_free( content );
276err_free_fields:
277 mailmime_fields_free( fields );
278err_free:
279 free( name );
280 free( mime );
281 free( file );
282 qDebug( "buildFilePart - error" );
283
284 return NULL; // Error :(
285}
286
287void MailWrapper::addFileParts( mailmime *message, QList<Attachment> files )
288{
289 Attachment *it;
290 for ( it = files.first(); it; it = files.next() ) {
291 qDebug( "Adding file" );
292 mailmime *filePart;
293 int err;
294
295 filePart = buildFilePart( it->getFileName(), it->getMimeType() );
296 if ( filePart == NULL ) goto err_free;
297
298 err = mailmime_smart_add_part( message, filePart );
299 if ( err != MAILIMF_NO_ERROR ) goto err_free_filePart;
300
301 continue; // Success :)
302
303 err_free_filePart:
304 mailmime_free( filePart );
305 err_free:
306 qDebug( "addFileParts: error adding file:" );
307 qDebug( it->getFileName() );
308 }
309}
310
311mailmime *MailWrapper::createMimeMail( Mail *mail )
312{
313 mailmime *message, *txtPart;
314 mailimf_fields *fields;
315 int err;
316
317 fields = createImfFields( mail );
318 if ( fields == NULL ) goto err_free;
319
320 message = mailmime_new_message_data( NULL );
321 if ( message == NULL ) goto err_free_fields;
322
323 mailmime_set_imf_fields( message, fields );
324
325 txtPart = buildTxtPart( mail->getMessage() );
326 if ( txtPart == NULL ) goto err_free_message;
327
328 err = mailmime_smart_add_part( message, txtPart );
329 if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart;
330
331 addFileParts( message, mail->getAttachments() );
332
333 return message; // Success :)
334
335err_free_txtPart:
336 mailmime_free( txtPart );
337err_free_message:
338 mailmime_free( message );
339err_free_fields:
340 mailimf_fields_free( fields );
341err_free:
342 qDebug( "createMimeMail: error" );
343
344 return NULL; // Error :(
345}
346
347mailimf_field *MailWrapper::getField( mailimf_fields *fields, int type )
348{
349 mailimf_field *field;
350 clistiter *it;
351
352 it = clist_begin( fields->list );
353 while ( it ) {
354 field = (mailimf_field *) it->data;
355 if ( field->type == type ) {
356 return field;
357 }
358 it = it->next;
359 }
360
361 return NULL;
362}
363
364static void addRcpts( clist *list, mailimf_address_list *addr_list )
365{
366 clistiter *it, *it2;
367
368 for ( it = clist_begin( addr_list->list ); it; it = it->next ) {
369 mailimf_address *addr;
370 addr = (mailimf_address *) it->data;
371
372 if ( addr->type == MAILIMF_ADDRESS_MAILBOX ) {
373 esmtp_address_list_add( list, addr->mailbox->addr_spec, 0, NULL );
374 } else if ( addr->type == MAILIMF_ADDRESS_GROUP ) {
375 clist *l = addr->group->mb_list->list;
376 for ( it2 = clist_begin( l ); it2; it2 = it2->next ) {
377 mailimf_mailbox *mbox;
378 mbox = (mailimf_mailbox *) it2->data;
379 esmtp_address_list_add( list, mbox->addr_spec, 0, NULL );
380 }
381 }
382 }
383}
384
385clist *MailWrapper::createRcptList( mailimf_fields *fields )
386{
387 clist *rcptList;
388 mailimf_field *field;
389
390 rcptList = esmtp_address_list_new();
391
392 field = getField( fields, MAILIMF_FIELD_TO );
393 if ( field && (field->type == MAILIMF_FIELD_TO)
394 && field->field.to->addr_list ) {
395 addRcpts( rcptList, field->field.to->addr_list );
396 }
397
398 field = getField( fields, MAILIMF_FIELD_CC );
399 if ( field && (field->type == MAILIMF_FIELD_CC)
400 && field->field.cc->addr_list ) {
401 addRcpts( rcptList, field->field.cc->addr_list );
402 }
403
404 field = getField( fields, MAILIMF_FIELD_BCC );
405 if ( field && (field->type == MAILIMF_FIELD_BCC)
406 && field->field.bcc->addr_list ) {
407 addRcpts( rcptList, field->field.bcc->addr_list );
408 }
409
410 return rcptList;
411}
412
413char *MailWrapper::getFrom( mailmime *mail )
414{
415 char *from = NULL;
416
417 mailimf_field *ffrom;
418 ffrom = getField( mail->fields, MAILIMF_FIELD_FROM );
419 if ( ffrom && (ffrom->type == MAILIMF_FIELD_FROM)
420 && ffrom->field.from->mb_list && ffrom->field.from->mb_list->list ) {
421 clist *cl = ffrom->field.from->mb_list->list;
422 clistiter *it;
423 for ( it = clist_begin( cl ); it; it = it->next ) {
424 mailimf_mailbox *mb = (mailimf_mailbox *) it->data;
425 from = strdup( mb->addr_spec );
426 }
427 }
428
429 return from;
430}
431
432SMTPaccount *MailWrapper::getAccount( QString from )
433{
434 SMTPaccount *smtp;
435
436 QList<Account> list = settings->getAccounts();
437 Account *it;
438 for ( it = list.first(); it; it = list.next() ) {
439 if ( it->getType().compare( "SMTP" ) == 0 ) {
440 smtp = static_cast<SMTPaccount *>(it);
441 if ( smtp->getMail().compare( from ) == 0 ) {
442 qDebug( "SMTPaccount found for" );
443 qDebug( from );
444 return smtp;
445 }
446 }
447 }
448
449 return NULL;
450}
451
452QString MailWrapper::getTmpFile() {
453 int num = 0;
454 QString unique;
455
456 QDir dir( "/tmp" );
457 QStringList::Iterator it;
458
459 QStringList list = dir.entryList( "opiemail-tmp-*" );
460 do {
461 unique.setNum( num++ );
462 } while ( list.contains( "opiemail-tmp-" + unique ) > 0 );
463
464 return "/tmp/opiemail-tmp-" + unique;
465}
466
467void MailWrapper::writeToFile( QString file, mailmime *mail )
468{
469 FILE *f;
470 int err, col = 0;
471
472 f = fopen( file.latin1(), "w" );
473 if ( f == NULL ) {
474 qDebug( "writeToFile: error opening file" );
475 return;
476 }
477
478 err = mailmime_write( f, &col, mail );
479 if ( err != MAILIMF_NO_ERROR ) {
480 fclose( f );
481 qDebug( "writeToFile: error writing mailmime" );
482 return;
483 }
484
485 fclose( f );
486}
487
488void MailWrapper::readFromFile( QString file, char **data, size_t *size )
489{
490 char *buf;
491 struct stat st;
492 int fd, count = 0, total = 0;
493
494 fd = open( file.latin1(), O_RDONLY, 0 );
495 if ( fd == -1 ) return;
496
497 if ( fstat( fd, &st ) != 0 ) goto err_close;
498 if ( !st.st_size ) goto err_close;
499
500 buf = (char *) malloc( st.st_size );
501 if ( !buf ) goto err_close;
502
503 while ( ( total < st.st_size ) && ( count >= 0 ) ) {
504 count = read( fd, buf + total, st.st_size - total );
505 total += count;
506 }
507 if ( count < 0 ) goto err_free;
508
509 *data = buf;
510 *size = st.st_size;
511
512 close( fd );
513
514 return; // Success :)
515
516err_free:
517 free( buf );
518err_close:
519 close( fd );
520}
521
522void progress( size_t current, size_t maximum )
523{
524 qDebug( "Current: %i of %i", current, maximum );
525}
526
527void MailWrapper::smtpSend( mailmime *mail )
528{
529 mailsmtp *session;
530 clist *rcpts;
531 char *from, *data, *server, *user = NULL, *pass = NULL;
532 size_t size;
533 int err;
534 bool ssl;
535 uint16_t port;
536
537
538 from = getFrom( mail );
539 SMTPaccount *smtp = getAccount( from );
540 if ( smtp == NULL ) {
541 free(from);
542 return;
543 }
544 server = strdup( smtp->getServer().latin1() );
545 ssl = smtp->getSSL();
546 port = smtp->getPort().toUInt();
547 rcpts = createRcptList( mail->fields );
548
549 QString file = getTmpFile();
550 writeToFile( file, mail );
551 readFromFile( file, &data, &size );
552 QFile f( file );
553 f.remove();
554
555 session = mailsmtp_new( 20, &progress );
556 if ( session == NULL ) goto free_mem;
557
558 qDebug( "Servername %s at port %i", server, port );
559 if ( ssl ) {
560 qDebug( "SSL session" );
561 err = mailsmtp_ssl_connect( session, server, port );
562 } else {
563 qDebug( "No SSL session" );
564 err = mailsmtp_socket_connect( session, server, port );
565 }
566 if ( err != MAILSMTP_NO_ERROR ) goto free_mem_session;
567
568 err = mailsmtp_init( session );
569 if ( err != MAILSMTP_NO_ERROR ) goto free_con_session;
570
571 qDebug( "INIT OK" );
572
573 if ( smtp->getLogin() ) {
574 if ( smtp->getUser().isEmpty() || smtp->getPassword().isEmpty() ) {
575 // get'em
576 LoginDialog login( smtp->getUser(), smtp->getPassword(), NULL, 0, true );
577 login.show();
578 if ( QDialog::Accepted == login.exec() ) {
579 // ok
580 user = strdup( login.getUser().latin1() );
581 pass = strdup( login.getPassword().latin1() );
582 } else {
583 goto free_con_session;
584 }
585 } else {
586 user = strdup( smtp->getUser().latin1() );
587 pass = strdup( smtp->getPassword().latin1() );
588 }
589 qDebug( "session->auth: %i", session->auth);
590 err = mailsmtp_auth( session, user, pass );
591 if ( err == MAILSMTP_NO_ERROR ) qDebug("auth ok");
592 qDebug( "Done auth!" );
593 }
594
595 err = mailsmtp_send( session, from, rcpts, data, size );
596 if ( err != MAILSMTP_NO_ERROR ) goto free_con_session;
597
598 qDebug( "Mail sent." );
599
600free_con_session:
601 mailsmtp_quit( session );
602free_mem_session:
603 mailsmtp_free( session );
604free_mem:
605 smtp_address_list_free( rcpts );
606 free( data );
607 free( server );
608 if ( smtp->getLogin() ) {
609 free( user );
610 free( pass );
611 }
612 free( from );
613}
614
615void MailWrapper::sendMail( Mail mail )
616{
617 mailmime *mimeMail;
618
619 mimeMail = createMimeMail( &mail );
620 if ( mimeMail == NULL ) {
621 qDebug( "sendMail: error creating mime mail" );
622 } else {
623 smtpSend( mimeMail );
624 mailmime_free( mimeMail );
625 }
626}
627
628Mail::Mail()
629 :name(""), mail(""), to(""), cc(""), bcc(""), reply(""), subject(""), message("")
630{
631}
632
633RecMail::RecMail()
634 :subject(""),date(""),msg_number(0),msg_flags(7)
635{
636}
637
638#if 0
639void RecMail::setDate(const QString&aDate)
640{
641 mDate = QDateTime::fromString(aDate);
642}
643#endif