summaryrefslogtreecommitdiffabout
path: root/kmicromail/libmailwrapper/imapwrapper.cpp
Unidiff
Diffstat (limited to 'kmicromail/libmailwrapper/imapwrapper.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libmailwrapper/imapwrapper.cpp1182
1 files changed, 1182 insertions, 0 deletions
diff --git a/kmicromail/libmailwrapper/imapwrapper.cpp b/kmicromail/libmailwrapper/imapwrapper.cpp
new file mode 100644
index 0000000..e0fb6f9
--- a/dev/null
+++ b/kmicromail/libmailwrapper/imapwrapper.cpp
@@ -0,0 +1,1182 @@
1#include <stdlib.h>
2#include <libetpan/libetpan.h>
3#include <qpe/global.h>
4#include <qapplication.h>
5#include "imapwrapper.h"
6#include "mailtypes.h"
7#include "logindialog.h"
8
9using namespace Opie::Core;
10IMAPwrapper::IMAPwrapper( IMAPaccount *a )
11 : AbstractMail()
12{
13 account = a;
14 m_imap = 0;
15 m_Lastmbox = "";
16}
17
18IMAPwrapper::~IMAPwrapper()
19{
20 logout();
21}
22
23/* to avoid to often select statements in loops etc.
24 we trust that we are logged in and connection is established!*/
25int IMAPwrapper::selectMbox(const QString&mbox)
26{
27 if (mbox == m_Lastmbox) {
28 return MAILIMAP_NO_ERROR;
29 }
30 int err = mailimap_select( m_imap, (char*)mbox.latin1());
31 if ( err != MAILIMAP_NO_ERROR ) {
32 m_Lastmbox = "";
33 return err;
34 }
35 m_Lastmbox = mbox;
36 return err;
37}
38
39void IMAPwrapper::imap_progress( size_t current, size_t maximum )
40{
41 qApp->processEvents();
42 qDebug("imap progress %d of %d ",current,maximum );
43}
44
45bool IMAPwrapper::start_tls(bool force_tls)
46{
47 int err;
48 bool try_tls;
49 mailimap_capability_data * cap_data = 0;
50
51 err = mailimap_capability(m_imap,&cap_data);
52 if (err != MAILIMAP_NO_ERROR) {
53 Global::statusMessage("error getting capabilities!");
54 return false;
55 }
56 clistiter * cur;
57 for(cur = clist_begin(cap_data->cap_list) ; cur != NULL;cur = clist_next(cur)) {
58 struct mailimap_capability * cap;
59 cap = (struct mailimap_capability *)clist_content(cur);
60 if (cap->cap_type == MAILIMAP_CAPABILITY_NAME) {
61 if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) {
62 try_tls = true;
63 break;
64 }
65 }
66 }
67 if (cap_data) {
68 mailimap_capability_data_free(cap_data);
69 }
70 if (try_tls) {
71 err = mailimap_starttls(m_imap);
72 if (err != MAILIMAP_NO_ERROR && force_tls) {
73 Global::statusMessage(tr("Server has no TLS support!"));
74 try_tls = false;
75 } else {
76 mailstream_low * low;
77 mailstream_low * new_low;
78 low = mailstream_get_low(m_imap->imap_stream);
79 if (!low) {
80 try_tls = false;
81 } else {
82 int fd = mailstream_low_get_fd(low);
83 if (fd > -1 && (new_low = mailstream_low_ssl_open(fd))!=0) {
84 mailstream_low_free(low);
85 mailstream_set_low(m_imap->imap_stream, new_low);
86 } else {
87 try_tls = false;
88 }
89 }
90 }
91 }
92 return try_tls;
93}
94
95void IMAPwrapper::login()
96{
97 const char *server, *user, *pass;
98 uint16_t port;
99 int err = MAILIMAP_NO_ERROR;
100
101 if (account->getOffline()) return;
102 /* we are connected this moment */
103 /* TODO: setup a timer holding the line or if connection closed - delete the value */
104 if (m_imap) {
105 err = mailimap_noop(m_imap);
106 if (err!=MAILIMAP_NO_ERROR) {
107 logout();
108 } else {
109 mailstream_flush(m_imap->imap_stream);
110 return;
111 }
112 }
113 server = account->getServer().latin1();
114 port = account->getPort().toUInt();
115 if ( account->getUser().isEmpty() || account->getPassword().isEmpty() ) {
116 LoginDialog login( account->getUser(), account->getPassword(), NULL, 0, true );
117 login.show();
118 if ( QDialog::Accepted == login.exec() ) {
119 // ok
120 user = login.getUser().latin1();
121 pass = login.getPassword().latin1();
122 } else {
123 // cancel
124 return;
125 }
126 } else {
127 user = account->getUser().latin1();
128 pass = account->getPassword().latin1();
129 }
130
131 m_imap = mailimap_new( 20, &imap_progress );
132
133 /* connect */
134 bool ssl = false;
135 bool try_tls = false;
136 bool force_tls = false;
137
138 if ( account->ConnectionType() == 2 ) {
139 ssl = true;
140 }
141 if (account->ConnectionType()==1) {
142 force_tls = true;
143 }
144
145 if ( ssl ) {
146 qDebug("using ssl ");
147 err = mailimap_ssl_connect( m_imap, (char*)server, port );
148 } else {
149 err = mailimap_socket_connect( m_imap, (char*)server, port );
150 }
151
152 if ( err != MAILIMAP_NO_ERROR &&
153 err != MAILIMAP_NO_ERROR_AUTHENTICATED &&
154 err != MAILIMAP_NO_ERROR_NON_AUTHENTICATED ) {
155 QString failure = "";
156 if (err == MAILIMAP_ERROR_CONNECTION_REFUSED) {
157 failure="Connection refused";
158 } else {
159 failure="Unknown failure";
160 }
161 Global::statusMessage(tr("error connecting imap server: %1").arg(failure));
162 mailimap_free( m_imap );
163 m_imap = 0;
164 return;
165 }
166
167 if (!ssl) {
168 try_tls = start_tls(force_tls);
169 }
170
171 bool ok = true;
172 if (force_tls && !try_tls) {
173 Global::statusMessage(tr("Server has no TLS support!"));
174 ok = false;
175 }
176
177
178 /* login */
179
180 if (ok) {
181 err = mailimap_login_simple( m_imap, (char*)user, (char*)pass );
182 if ( err != MAILIMAP_NO_ERROR ) {
183 Global::statusMessage(tr("error logging in imap server: %1").arg(m_imap->imap_response));
184 ok = false;
185 }
186 }
187 if (!ok) {
188 err = mailimap_close( m_imap );
189 mailimap_free( m_imap );
190 m_imap = 0;
191 }
192}
193
194void IMAPwrapper::logout()
195{
196 int err = MAILIMAP_NO_ERROR;
197 if (!m_imap) return;
198 err = mailimap_logout( m_imap );
199 err = mailimap_close( m_imap );
200 mailimap_free( m_imap );
201 m_imap = 0;
202 m_Lastmbox = "";
203}
204
205void IMAPwrapper::listMessages(const QString&mailbox,QValueList<Opie::Core::OSmartPointer<RecMail> > &target )
206{
207 int err = MAILIMAP_NO_ERROR;
208 clist *result = 0;
209 clistcell *current;
210 mailimap_fetch_type *fetchType = 0;
211 mailimap_set *set = 0;
212
213 login();
214 if (!m_imap) {
215 return;
216 }
217 /* select mailbox READONLY for operations */
218 err = selectMbox(mailbox);
219 if ( err != MAILIMAP_NO_ERROR ) {
220 return;
221 }
222
223 int last = m_imap->imap_selection_info->sel_exists;
224
225 if (last == 0) {
226 Global::statusMessage(tr("Mailbox has no mails"));
227 return;
228 } else {
229 }
230
231 /* the range has to start at 1!!! not with 0!!!! */
232 set = mailimap_set_new_interval( 1, last );
233 fetchType = mailimap_fetch_type_new_fetch_att_list_empty();
234 mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_envelope());
235 mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_flags());
236 mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_internaldate());
237 mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_rfc822_size());
238
239 err = mailimap_fetch( m_imap, set, fetchType, &result );
240 mailimap_set_free( set );
241 mailimap_fetch_type_free( fetchType );
242
243 QString date,subject,from;
244
245 if ( err == MAILIMAP_NO_ERROR ) {
246 mailimap_msg_att * msg_att;
247 int i = 0;
248 for (current = clist_begin(result); current != 0; current=clist_next(current)) {
249 ++i;
250 msg_att = (mailimap_msg_att*)current->data;
251 RecMail*m = parse_list_result(msg_att);
252 if (m) {
253 m->setNumber(i);
254 m->setMbox(mailbox);
255 m->setWrapper(this);
256 target.append(m);
257 }
258 }
259 Global::statusMessage(tr("Mailbox has %1 mails").arg(target.count()));
260 } else {
261 Global::statusMessage(tr("Error fetching headers: %1").arg(m_imap->imap_response));
262 }
263 if (result) mailimap_fetch_list_free(result);
264}
265
266QValueList<Opie::Core::OSmartPointer<Folder> >* IMAPwrapper::listFolders()
267{
268 const char *path, *mask;
269 int err = MAILIMAP_NO_ERROR;
270 clist *result = 0;
271 clistcell *current = 0;
272 clistcell*cur_flag = 0;
273 mailimap_mbx_list_flags*bflags = 0;
274
275 QValueList<FolderP>* folders = new QValueList<FolderP>();
276 login();
277 if (!m_imap) {
278 return folders;
279 }
280
281/*
282 * First we have to check for INBOX 'cause it sometimes it's not inside the path.
283 * We must not forget to filter them out in next loop!
284 * it seems like ugly code. and yes - it is ugly code. but the best way.
285 */
286 QString temp;
287 mask = "INBOX" ;
288 mailimap_mailbox_list *list;
289 err = mailimap_list( m_imap, (char*)"", (char*)mask, &result );
290 QString del;
291 bool selectable = true;
292 bool no_inferiors = false;
293 if ( err == MAILIMAP_NO_ERROR ) {
294 current = result->first;
295 for ( int i = result->count; i > 0; i-- ) {
296 list = (mailimap_mailbox_list *) current->data;
297 // it is better use the deep copy mechanism of qt itself
298 // instead of using strdup!
299 temp = list->mb_name;
300 del = list->mb_delimiter;
301 current = current->next;
302 if ( (bflags = list->mb_flag) ) {
303 selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&&
304 bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT);
305 for(cur_flag=clist_begin(bflags->mbf_oflags);cur_flag;cur_flag=clist_next(cur_flag)) {
306 if ( ((mailimap_mbx_list_oflag*)cur_flag->data)->of_type==MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS) {
307 no_inferiors = true;
308 }
309 }
310 }
311 folders->append( new IMAPFolder(temp,del,selectable,no_inferiors,account->getPrefix()));
312 }
313 } else {
314 qDebug("error fetching folders: ");
315
316 }
317 mailimap_list_result_free( result );
318
319/*
320 * second stage - get the other then inbox folders
321 */
322 mask = "*" ;
323 path = account->getPrefix().latin1();
324 if (!path) path = "";
325 err = mailimap_list( m_imap, (char*)path, (char*)mask, &result );
326 if ( err == MAILIMAP_NO_ERROR ) {
327 current = result->first;
328 for ( current=clist_begin(result);current!=NULL;current=clist_next(current)) {
329 no_inferiors = false;
330 list = (mailimap_mailbox_list *) current->data;
331 // it is better use the deep copy mechanism of qt itself
332 // instead of using strdup!
333 temp = list->mb_name;
334 if (temp.lower()=="inbox")
335 continue;
336 if (temp.lower()==account->getPrefix().lower())
337 continue;
338 if ( (bflags = list->mb_flag) ) {
339 selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&&
340 bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT);
341 for(cur_flag=clist_begin(bflags->mbf_oflags);cur_flag;cur_flag=clist_next(cur_flag)) {
342 if ( ((mailimap_mbx_list_oflag*)cur_flag->data)->of_type==MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS) {
343 no_inferiors = true;
344 }
345 }
346 }
347 del = list->mb_delimiter;
348 folders->append(new IMAPFolder(temp,del,selectable,no_inferiors,account->getPrefix()));
349 }
350 } else {
351 qDebug("error fetching folders ");
352
353 }
354 if (result) mailimap_list_result_free( result );
355 return folders;
356}
357
358RecMail*IMAPwrapper::parse_list_result(mailimap_msg_att* m_att)
359{
360 RecMail * m = 0;
361 mailimap_msg_att_item *item=0;
362 clistcell *current,*c,*cf;
363 mailimap_msg_att_dynamic*flist;
364 mailimap_flag_fetch*cflag;
365 int size;
366 QBitArray mFlags(7);
367 QStringList addresslist;
368
369 if (!m_att) {
370 return m;
371 }
372 m = new RecMail();
373 for (c = clist_begin(m_att->att_list); c!=NULL;c=clist_next(c) ) {
374 current = c;
375 size = 0;
376 item = (mailimap_msg_att_item*)current->data;
377 if (item->att_type!=MAILIMAP_MSG_ATT_ITEM_STATIC) {
378 flist = (mailimap_msg_att_dynamic*)item->att_data.att_dyn;
379 if (!flist->att_list) {
380 continue;
381 }
382 cf = flist->att_list->first;
383 for (cf = clist_begin(flist->att_list); cf!=NULL; cf = clist_next(cf)) {
384 cflag = (mailimap_flag_fetch*)cf->data;
385 if (cflag->fl_type==MAILIMAP_FLAG_FETCH_OTHER && cflag->fl_flag!=0) {
386 switch (cflag->fl_flag->fl_type) {
387 case MAILIMAP_FLAG_ANSWERED: /* \Answered flag */
388 mFlags.setBit(FLAG_ANSWERED);
389 break;
390 case MAILIMAP_FLAG_FLAGGED: /* \Flagged flag */
391 mFlags.setBit(FLAG_FLAGGED);
392 break;
393 case MAILIMAP_FLAG_DELETED: /* \Deleted flag */
394 mFlags.setBit(FLAG_DELETED);
395 break;
396 case MAILIMAP_FLAG_SEEN: /* \Seen flag */
397 mFlags.setBit(FLAG_SEEN);
398 break;
399 case MAILIMAP_FLAG_DRAFT: /* \Draft flag */
400 mFlags.setBit(FLAG_DRAFT);
401 break;
402 case MAILIMAP_FLAG_KEYWORD: /* keyword flag */
403 break;
404 case MAILIMAP_FLAG_EXTENSION: /* \extension flag */
405 break;
406 default:
407 break;
408 }
409 } else if (cflag->fl_type==MAILIMAP_FLAG_FETCH_RECENT) {
410 mFlags.setBit(FLAG_RECENT);
411 }
412 }
413 continue;
414 }
415 if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_ENVELOPE) {
416 mailimap_envelope * head = item->att_data.att_static->att_data.att_env;
417 m->setDate(head->env_date);
418 m->setSubject(convert_String((const char*)head->env_subject));
419 //m->setSubject(head->env_subject);
420 if (head->env_from!=NULL) {
421 addresslist = address_list_to_stringlist(head->env_from->frm_list);
422 if (addresslist.count()) {
423 m->setFrom(addresslist.first());
424 }
425 }
426 if (head->env_to!=NULL) {
427 addresslist = address_list_to_stringlist(head->env_to->to_list);
428 m->setTo(addresslist);
429 }
430 if (head->env_cc!=NULL) {
431 addresslist = address_list_to_stringlist(head->env_cc->cc_list);
432 m->setCC(addresslist);
433 }
434 if (head->env_bcc!=NULL) {
435 addresslist = address_list_to_stringlist(head->env_bcc->bcc_list);
436 m->setBcc(addresslist);
437 }
438 /* reply to address, eg. email. */
439 if (head->env_reply_to!=NULL) {
440 addresslist = address_list_to_stringlist(head->env_reply_to->rt_list);
441 if (addresslist.count()) {
442 m->setReplyto(addresslist.first());
443 }
444 }
445 if (head->env_in_reply_to!=NULL) {
446 QString h(head->env_in_reply_to);
447 while (h.length()>0 && h[0]=='<') {
448 h.remove(0,1);
449 }
450 while (h.length()>0 && h[h.length()-1]=='>') {
451 h.remove(h.length()-1,1);
452 }
453 if (h.length()>0) {
454 m->setInreply(QStringList(h));
455 }
456 }
457 if (head->env_message_id) {
458 m->setMsgid(QString(head->env_message_id));
459 }
460 } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_INTERNALDATE) {
461#if 0
462 mailimap_date_time*d = item->att_data.att_static->att_data.att_internal_date;
463 QDateTime da(QDate(d->dt_year,d->dt_month,d->dt_day),QTime(d->dt_hour,d->dt_min,d->dt_sec));
464 //odebug << "" << d->dt_year << " " << d->dt_month << " " << d->dt_day << " - " << d->dt_hour << " " << d->dt_min << " " << d->dt_sec << "" << oendl;
465 //odebug << da.toString() << oendl;
466#endif
467 } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_RFC822_SIZE) {
468 size = item->att_data.att_static->att_data.att_rfc822_size;
469 }
470 }
471 /* msg is already deleted */
472 if (mFlags.testBit(FLAG_DELETED) && m) {
473 delete m;
474 m = 0;
475 }
476 if (m) {
477 m->setFlags(mFlags);
478 m->setMsgsize(size);
479 }
480 return m;
481}
482
483RecBodyP IMAPwrapper::fetchBody(const RecMailP&mail)
484{
485 RecBodyP body = new RecBody();
486 const char *mb;
487 int err = MAILIMAP_NO_ERROR;
488 clist *result = 0;
489 clistcell *current;
490 mailimap_fetch_att *fetchAtt = 0;
491 mailimap_fetch_type *fetchType = 0;
492 mailimap_set *set = 0;
493 mailimap_body*body_desc = 0;
494
495 mb = mail->getMbox().latin1();
496
497 login();
498 if (!m_imap) {
499 return body;
500 }
501 err = selectMbox(mail->getMbox());
502 if ( err != MAILIMAP_NO_ERROR ) {
503 return body;
504 }
505
506 /* the range has to start at 1!!! not with 0!!!! */
507 set = mailimap_set_new_interval( mail->getNumber(),mail->getNumber() );
508 fetchAtt = mailimap_fetch_att_new_bodystructure();
509 fetchType = mailimap_fetch_type_new_fetch_att(fetchAtt);
510 err = mailimap_fetch( m_imap, set, fetchType, &result );
511 mailimap_set_free( set );
512 mailimap_fetch_type_free( fetchType );
513
514 if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) {
515 mailimap_msg_att * msg_att;
516 msg_att = (mailimap_msg_att*)current->data;
517 mailimap_msg_att_item*item = (mailimap_msg_att_item*)msg_att->att_list->first->data;
518 QValueList<int> path;
519 body_desc = item->att_data.att_static->att_data.att_body;
520 traverseBody(mail,body_desc,body,0,path);
521 } else {
522 //odebug << "error fetching body: " << m_imap->imap_response << "" << oendl;
523 }
524 if (result) mailimap_fetch_list_free(result);
525 return body;
526}
527
528QStringList IMAPwrapper::address_list_to_stringlist(clist*list)
529{
530 QStringList l;
531 QString from;
532 bool named_from;
533 clistcell *current = NULL;
534 mailimap_address * current_address=NULL;
535 if (!list) {
536 return l;
537 }
538 unsigned int count = 0;
539 for (current=clist_begin(list);current!= NULL;current=clist_next(current)) {
540 from = "";
541 named_from = false;
542 current_address=(mailimap_address*)current->data;
543 if (current_address->ad_personal_name){
544 from+=convert_String((const char*)current_address->ad_personal_name);
545 from+=" ";
546 named_from = true;
547 }
548 if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) {
549 from+="<";
550 }
551 if (current_address->ad_mailbox_name) {
552 from+=QString(current_address->ad_mailbox_name);
553 from+="@";
554 }
555 if (current_address->ad_host_name) {
556 from+=QString(current_address->ad_host_name);
557 }
558 if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) {
559 from+=">";
560 }
561 l.append(QString(from));
562 if (++count > 99) {
563 break;
564 }
565 }
566 return l;
567}
568
569encodedString*IMAPwrapper::fetchRawPart(const RecMailP&mail,const QValueList<int>&path,bool internal_call)
570{
571 encodedString*res=new encodedString;
572 int err;
573 mailimap_fetch_type *fetchType;
574 mailimap_set *set;
575 clistcell*current,*cur;
576 mailimap_section_part * section_part = 0;
577 mailimap_section_spec * section_spec = 0;
578 mailimap_section * section = 0;
579 mailimap_fetch_att * fetch_att = 0;
580
581 login();
582 if (!m_imap) {
583 return res;
584 }
585 if (!internal_call) {
586 err = selectMbox(mail->getMbox());
587 if ( err != MAILIMAP_NO_ERROR ) {
588 return res;
589 }
590 }
591 set = mailimap_set_new_single(mail->getNumber());
592
593 clist*id_list = 0;
594
595 /* if path == empty then its a request for the whole rfc822 mail and generates
596 a "fetch <id> (body[])" statement on imap server */
597 if (path.count()>0 ) {
598 id_list = clist_new();
599 for (unsigned j=0; j < path.count();++j) {
600 uint32_t * p_id = (uint32_t *)malloc(sizeof(*p_id));
601 *p_id = path[j];
602 clist_append(id_list,p_id);
603 }
604 section_part = mailimap_section_part_new(id_list);
605 section_spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, NULL, section_part, NULL);
606 }
607
608 section = mailimap_section_new(section_spec);
609 fetch_att = mailimap_fetch_att_new_body_section(section);
610 fetchType = mailimap_fetch_type_new_fetch_att(fetch_att);
611
612 clist*result = 0;
613
614 err = mailimap_fetch( m_imap, set, fetchType, &result );
615 mailimap_set_free( set );
616 mailimap_fetch_type_free( fetchType );
617
618 if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) {
619 mailimap_msg_att * msg_att;
620 msg_att = (mailimap_msg_att*)current->data;
621 mailimap_msg_att_item*msg_att_item;
622 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; cur = clist_next(cur)) {
623 msg_att_item = (mailimap_msg_att_item*)clist_content(cur);
624 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
625 if (msg_att_item->att_data.att_static->att_type == MAILIMAP_MSG_ATT_BODY_SECTION) {
626 char*text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
627 /* detach - we take over the content */
628 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = 0L;
629 res->setContent(text,msg_att_item->att_data.att_static->att_data.att_body_section->sec_length);
630 }
631 }
632 }
633 } else {
634 ;//odebug << "error fetching text: " << m_imap->imap_response << "" << oendl;
635 }
636 if (result) mailimap_fetch_list_free(result);
637 return res;
638}
639
640/* current_recursion is for recursive calls.
641 current_count means the position inside the internal loop! */
642void IMAPwrapper::traverseBody(const RecMailP&mail,mailimap_body*body,RecBodyP&target_body,
643 int current_recursion,QValueList<int>recList,int current_count)
644{
645 if (!body || current_recursion>=10) {
646 return;
647 }
648 switch (body->bd_type) {
649 case MAILIMAP_BODY_1PART:
650 {
651 QValueList<int>countlist = recList;
652 countlist.append(current_count);
653 RecPartP currentPart = new RecPart();
654 mailimap_body_type_1part*part1 = body->bd_data.bd_body_1part;
655 QString id("");
656 currentPart->setPositionlist(countlist);
657 for (unsigned int j = 0; j < countlist.count();++j) {
658 id+=(j>0?" ":"");
659 id+=QString("%1").arg(countlist[j]);
660 }
661 //odebug << "ID = " << id.latin1() << "" << oendl;
662 currentPart->setIdentifier(id);
663 fillSinglePart(currentPart,part1);
664 /* important: Check for is NULL 'cause a body can be empty!
665 And we put it only into the mail if it is the FIRST part */
666 if (part1->bd_type==MAILIMAP_BODY_TYPE_1PART_TEXT && target_body->Bodytext().isNull() && countlist[0]==1) {
667 QString body_text = fetchTextPart(mail,countlist,true,currentPart->Encoding());
668 target_body->setDescription(currentPart);
669 target_body->setBodytext(body_text);
670 if (countlist.count()>1) {
671 target_body->addPart(currentPart);
672 }
673 } else {
674 target_body->addPart(currentPart);
675 }
676 if (part1->bd_type==MAILIMAP_BODY_TYPE_1PART_MSG) {
677 traverseBody(mail,part1->bd_data.bd_type_msg->bd_body,target_body,current_recursion+1,countlist);
678 }
679 }
680 break;
681 case MAILIMAP_BODY_MPART:
682 {
683 QValueList<int>countlist = recList;
684 clistcell*current=0;
685 mailimap_body*current_body=0;
686 unsigned int ccount = 1;
687 mailimap_body_type_mpart*mailDescription = body->bd_data.bd_body_mpart;
688 for (current=clist_begin(mailDescription->bd_list);current!=0;current=clist_next(current)) {
689 current_body = (mailimap_body*)current->data;
690 if (current_body->bd_type==MAILIMAP_BODY_MPART) {
691 RecPartP targetPart = new RecPart();
692 targetPart->setType("multipart");
693 fillMultiPart(targetPart,mailDescription);
694 countlist.append(current_count);
695 targetPart->setPositionlist(countlist);
696 target_body->addPart(targetPart);
697 QString id("");
698 for (unsigned int j = 0; j < countlist.count();++j) {
699 id+=(j>0?" ":"");
700 id+=QString("%1").arg(countlist[j]);
701 }
702 // odebug << "ID(mpart) = " << id.latin1() << "" << oendl;
703 }
704 traverseBody(mail,current_body,target_body,current_recursion+1,countlist,ccount);
705 if (current_body->bd_type==MAILIMAP_BODY_MPART) {
706 countlist = recList;
707 }
708 ++ccount;
709 }
710 }
711 break;
712 default:
713 break;
714 }
715}
716
717void IMAPwrapper::fillSinglePart(RecPartP&target_part,mailimap_body_type_1part*Description)
718{
719 if (!Description) {
720 return;
721 }
722 switch (Description->bd_type) {
723 case MAILIMAP_BODY_TYPE_1PART_TEXT:
724 target_part->setType("text");
725 fillSingleTextPart(target_part,Description->bd_data.bd_type_text);
726 break;
727 case MAILIMAP_BODY_TYPE_1PART_BASIC:
728 fillSingleBasicPart(target_part,Description->bd_data.bd_type_basic);
729 break;
730 case MAILIMAP_BODY_TYPE_1PART_MSG:
731 target_part->setType("message");
732 fillSingleMsgPart(target_part,Description->bd_data.bd_type_msg);
733 break;
734 default:
735 break;
736 }
737}
738
739void IMAPwrapper::fillSingleTextPart(RecPartP&target_part,mailimap_body_type_text*which)
740{
741 if (!which) {
742 return;
743 }
744 QString sub;
745 sub = which->bd_media_text;
746 //odebug << "Type= text/" << which->bd_media_text << "" << oendl;
747 target_part->setSubtype(sub.lower());
748 target_part->setLines(which->bd_lines);
749 fillBodyFields(target_part,which->bd_fields);
750}
751
752void IMAPwrapper::fillSingleMsgPart(RecPartP&target_part,mailimap_body_type_msg*which)
753{
754 if (!which) {
755 return;
756 }
757 target_part->setSubtype("rfc822");
758 //odebug << "Message part" << oendl;
759 /* we set this type to text/plain */
760 target_part->setLines(which->bd_lines);
761 fillBodyFields(target_part,which->bd_fields);
762}
763
764void IMAPwrapper::fillMultiPart(RecPartP&target_part,mailimap_body_type_mpart*which)
765{
766 if (!which) return;
767 QString sub = which->bd_media_subtype;
768 target_part->setSubtype(sub.lower());
769 if (which->bd_ext_mpart && which->bd_ext_mpart->bd_parameter && which->bd_ext_mpart->bd_parameter->pa_list) {
770 clistcell*cur = 0;
771 mailimap_single_body_fld_param*param=0;
772 for (cur = clist_begin(which->bd_ext_mpart->bd_parameter->pa_list);cur!=NULL;cur=clist_next(cur)) {
773 param = (mailimap_single_body_fld_param*)cur->data;
774 if (param) {
775 target_part->addParameter(QString(param->pa_name).lower(),QString(param->pa_value));
776 }
777 }
778 }
779}
780
781void IMAPwrapper::fillSingleBasicPart(RecPartP&target_part,mailimap_body_type_basic*which)
782{
783 if (!which) {
784 return;
785 }
786 QString type,sub;
787 switch (which->bd_media_basic->med_type) {
788 case MAILIMAP_MEDIA_BASIC_APPLICATION:
789 type = "application";
790 break;
791 case MAILIMAP_MEDIA_BASIC_AUDIO:
792 type = "audio";
793 break;
794 case MAILIMAP_MEDIA_BASIC_IMAGE:
795 type = "image";
796 break;
797 case MAILIMAP_MEDIA_BASIC_MESSAGE:
798 type = "message";
799 break;
800 case MAILIMAP_MEDIA_BASIC_VIDEO:
801 type = "video";
802 break;
803 case MAILIMAP_MEDIA_BASIC_OTHER:
804 default:
805 if (which->bd_media_basic->med_basic_type) {
806 type = which->bd_media_basic->med_basic_type;
807 } else {
808 type = "";
809 }
810 break;
811 }
812 if (which->bd_media_basic->med_subtype) {
813 sub = which->bd_media_basic->med_subtype;
814 } else {
815 sub = "";
816 }
817 // odebug << "Type = " << type.latin1() << "/" << sub.latin1() << "" << oendl;
818 target_part->setType(type.lower());
819 target_part->setSubtype(sub.lower());
820 fillBodyFields(target_part,which->bd_fields);
821}
822
823void IMAPwrapper::fillBodyFields(RecPartP&target_part,mailimap_body_fields*which)
824{
825 if (!which) return;
826 if (which->bd_parameter && which->bd_parameter->pa_list && which->bd_parameter->pa_list->count>0) {
827 clistcell*cur;
828 mailimap_single_body_fld_param*param=0;
829 for (cur = clist_begin(which->bd_parameter->pa_list);cur!=NULL;cur=clist_next(cur)) {
830 param = (mailimap_single_body_fld_param*)cur->data;
831 if (param) {
832 target_part->addParameter(QString(param->pa_name).lower(),QString(param->pa_value));
833 }
834 }
835 }
836 mailimap_body_fld_enc*enc = which->bd_encoding;
837 QString encoding("");
838 switch (enc->enc_type) {
839 case MAILIMAP_BODY_FLD_ENC_7BIT:
840 encoding = "7bit";
841 break;
842 case MAILIMAP_BODY_FLD_ENC_8BIT:
843 encoding = "8bit";
844 break;
845 case MAILIMAP_BODY_FLD_ENC_BINARY:
846 encoding="binary";
847 break;
848 case MAILIMAP_BODY_FLD_ENC_BASE64:
849 encoding="base64";
850 break;
851 case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE:
852 encoding="quoted-printable";
853 break;
854 case MAILIMAP_BODY_FLD_ENC_OTHER:
855 default:
856 if (enc->enc_value) {
857 char*t=enc->enc_value;
858 encoding=QString(enc->enc_value);
859 enc->enc_value=0L;
860 free(t);
861 }
862 }
863 if (which->bd_description) {
864 target_part->setDescription(QString(which->bd_description));
865 }
866 target_part->setEncoding(encoding);
867 target_part->setSize(which->bd_size);
868}
869
870void IMAPwrapper::deleteMail(const RecMailP&mail)
871{
872 mailimap_flag_list*flist;
873 mailimap_set *set;
874 mailimap_store_att_flags * store_flags;
875 int err;
876 login();
877 if (!m_imap) {
878 return;
879 }
880 err = selectMbox(mail->getMbox());
881 if ( err != MAILIMAP_NO_ERROR ) {
882 return;
883 }
884 flist = mailimap_flag_list_new_empty();
885 mailimap_flag_list_add(flist,mailimap_flag_new_deleted());
886 store_flags = mailimap_store_att_flags_new_set_flags(flist);
887 set = mailimap_set_new_single(mail->getNumber());
888 err = mailimap_store(m_imap,set,store_flags);
889 mailimap_set_free( set );
890 mailimap_store_att_flags_free(store_flags);
891
892 if (err != MAILIMAP_NO_ERROR) {
893 // odebug << "error deleting mail: " << m_imap->imap_response << "" << oendl;
894 return;
895 }
896 // odebug << "deleting mail: " << m_imap->imap_response << "" << oendl;
897 /* should we realy do that at this moment? */
898 err = mailimap_expunge(m_imap);
899 if (err != MAILIMAP_NO_ERROR) {
900 // odebug << "error deleting mail: " << m_imap->imap_response << "" << oendl;
901 }
902 // odebug << "Delete successfull " << m_imap->imap_response << "" << oendl;
903}
904
905void IMAPwrapper::answeredMail(const RecMailP&mail)
906{
907 mailimap_flag_list*flist;
908 mailimap_set *set;
909 mailimap_store_att_flags * store_flags;
910 int err;
911 login();
912 if (!m_imap) {
913 return;
914 }
915 err = selectMbox(mail->getMbox());
916 if ( err != MAILIMAP_NO_ERROR ) {
917 return;
918 }
919 flist = mailimap_flag_list_new_empty();
920 mailimap_flag_list_add(flist,mailimap_flag_new_answered());
921 store_flags = mailimap_store_att_flags_new_add_flags(flist);
922 set = mailimap_set_new_single(mail->getNumber());
923 err = mailimap_store(m_imap,set,store_flags);
924 mailimap_set_free( set );
925 mailimap_store_att_flags_free(store_flags);
926
927 if (err != MAILIMAP_NO_ERROR) {
928 // odebug << "error marking mail: " << m_imap->imap_response << "" << oendl;
929 return;
930 }
931}
932
933QString IMAPwrapper::fetchTextPart(const RecMailP&mail,const QValueList<int>&path,bool internal_call,const QString&enc)
934{
935 QString body("");
936 encodedString*res = fetchRawPart(mail,path,internal_call);
937 encodedString*r = decode_String(res,enc);
938 delete res;
939 if (r) {
940 if (r->Length()>0) {
941 body = r->Content();
942 }
943 delete r;
944 }
945 return body;
946}
947
948QString IMAPwrapper::fetchTextPart(const RecMailP&mail,const RecPartP&part)
949{
950 return fetchTextPart(mail,part->Positionlist(),false,part->Encoding());
951}
952
953encodedString* IMAPwrapper::fetchDecodedPart(const RecMailP&mail,const RecPartP&part)
954{
955 encodedString*res = fetchRawPart(mail,part->Positionlist(),false);
956 encodedString*r = decode_String(res,part->Encoding());
957 delete res;
958 return r;
959}
960
961encodedString* IMAPwrapper::fetchRawPart(const RecMailP&mail,const RecPartP&part)
962{
963 return fetchRawPart(mail,part->Positionlist(),false);
964}
965
966int IMAPwrapper::deleteAllMail(const FolderP&folder)
967{
968 login();
969 if (!m_imap) {
970 return 0;
971 }
972 mailimap_flag_list*flist;
973 mailimap_set *set;
974 mailimap_store_att_flags * store_flags;
975 int err = selectMbox(folder->getName());
976 if ( err != MAILIMAP_NO_ERROR ) {
977 return 0;
978 }
979
980 int last = m_imap->imap_selection_info->sel_exists;
981 if (last == 0) {
982 Global::statusMessage(tr("Mailbox has no mails!"));
983 return 0;
984 }
985 flist = mailimap_flag_list_new_empty();
986 mailimap_flag_list_add(flist,mailimap_flag_new_deleted());
987 store_flags = mailimap_store_att_flags_new_set_flags(flist);
988 set = mailimap_set_new_interval( 1, last );
989 err = mailimap_store(m_imap,set,store_flags);
990 mailimap_set_free( set );
991 mailimap_store_att_flags_free(store_flags);
992 if (err != MAILIMAP_NO_ERROR) {
993 Global::statusMessage(tr("error deleting mail: %s").arg(m_imap->imap_response));
994 return 0;
995 }
996 // odebug << "deleting mail: " << m_imap->imap_response << "" << oendl;
997 /* should we realy do that at this moment? */
998 err = mailimap_expunge(m_imap);
999 if (err != MAILIMAP_NO_ERROR) {
1000 Global::statusMessage(tr("error deleting mail: %s").arg(m_imap->imap_response));
1001 return 0;
1002 }
1003 // odebug << "Delete successfull " << m_imap->imap_response << "" << oendl;
1004 return 1;
1005}
1006
1007int IMAPwrapper::createMbox(const QString&folder,const FolderP&parentfolder,const QString& delemiter,bool getsubfolder)
1008{
1009 if (folder.length()==0) return 0;
1010 login();
1011 if (!m_imap) {return 0;}
1012 QString pre = account->getPrefix();
1013 if (delemiter.length()>0 && pre.findRev(delemiter)!=pre.length()-1) {
1014 pre+=delemiter;
1015 }
1016 if (parentfolder) {
1017 pre += parentfolder->getDisplayName()+delemiter;
1018 }
1019 pre+=folder;
1020 if (getsubfolder) {
1021 if (delemiter.length()>0) {
1022 pre+=delemiter;
1023 } else {
1024 Global::statusMessage(tr("Cannot create folder %1 for holding subfolders").arg(pre));
1025 return 0;
1026 }
1027 }
1028 // odebug << "Creating " << pre.latin1() << "" << oendl;
1029 int res = mailimap_create(m_imap,pre.latin1());
1030 if (res != MAILIMAP_NO_ERROR) {
1031 Global::statusMessage(tr("%1").arg(m_imap->imap_response));
1032 return 0;
1033 }
1034 return 1;
1035}
1036
1037int IMAPwrapper::deleteMbox(const FolderP&folder)
1038{
1039 if (!folder) return 0;
1040 login();
1041 if (!m_imap) {return 0;}
1042 int res = mailimap_delete(m_imap,folder->getName());
1043 if (res != MAILIMAP_NO_ERROR) {
1044 Global::statusMessage(tr("%1").arg(m_imap->imap_response));
1045 return 0;
1046 }
1047 return 1;
1048}
1049
1050void IMAPwrapper::statusFolder(folderStat&target_stat,const QString & mailbox)
1051{
1052 mailimap_status_att_list * att_list =0;
1053 mailimap_mailbox_data_status * status=0;
1054 clistiter * cur = 0;
1055 int r = 0;
1056 target_stat.message_count = 0;
1057 target_stat.message_unseen = 0;
1058 target_stat.message_recent = 0;
1059 login();
1060 if (!m_imap) {
1061 return;
1062 }
1063 att_list = mailimap_status_att_list_new_empty();
1064 if (!att_list) return;
1065 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES);
1066 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT);
1067 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN);
1068 r = mailimap_status(m_imap, mailbox.latin1(), att_list, &status);
1069 if (r==MAILIMAP_NO_ERROR&&status->st_info_list!=0) {
1070 for (cur = clist_begin(status->st_info_list);
1071 cur != NULL ; cur = clist_next(cur)) {
1072 mailimap_status_info * status_info;
1073 status_info = (mailimap_status_info *)clist_content(cur);
1074 switch (status_info->st_att) {
1075 case MAILIMAP_STATUS_ATT_MESSAGES:
1076 target_stat.message_count = status_info->st_value;
1077 break;
1078 case MAILIMAP_STATUS_ATT_RECENT:
1079 target_stat.message_recent = status_info->st_value;
1080 break;
1081 case MAILIMAP_STATUS_ATT_UNSEEN:
1082 target_stat.message_unseen = status_info->st_value;
1083 break;
1084 }
1085 }
1086 } else {
1087 // odebug << "Error retrieving status" << oendl;
1088 }
1089 if (status) mailimap_mailbox_data_status_free(status);
1090 if (att_list) mailimap_status_att_list_free(att_list);
1091}
1092
1093void IMAPwrapper::storeMessage(const char*msg,size_t length, const QString&folder)
1094{
1095 login();
1096 if (!m_imap) return;
1097 if (!msg) return;
1098 int r = mailimap_append(m_imap,(char*)folder.latin1(),0,0,msg,length);
1099 if (r != MAILIMAP_NO_ERROR) {
1100 Global::statusMessage("Error storing mail!");
1101 }
1102}
1103
1104MAILLIB::ATYPE IMAPwrapper::getType()const
1105{
1106 return account->getType();
1107}
1108
1109const QString&IMAPwrapper::getName()const
1110{
1111 // odebug << "Get name: " << account->getAccountName().latin1() << "" << oendl;
1112 return account->getAccountName();
1113}
1114
1115encodedString* IMAPwrapper::fetchRawBody(const RecMailP&mail)
1116{
1117 // dummy
1118 QValueList<int> path;
1119 return fetchRawPart(mail,path,false);
1120}
1121
1122void IMAPwrapper::mvcpAllMails(const FolderP&fromFolder,
1123 const QString&targetFolder,AbstractMail*targetWrapper,bool moveit)
1124{
1125 if (targetWrapper != this) {
1126 AbstractMail::mvcpAllMails(fromFolder,targetFolder,targetWrapper,moveit);
1127 // odebug << "Using generic" << oendl;
1128 return;
1129 }
1130 mailimap_set *set = 0;
1131 login();
1132 if (!m_imap) {
1133 return;
1134 }
1135 int err = selectMbox(fromFolder->getName());
1136 if ( err != MAILIMAP_NO_ERROR ) {
1137 return;
1138 }
1139 int last = m_imap->imap_selection_info->sel_exists;
1140 set = mailimap_set_new_interval( 1, last );
1141 err = mailimap_copy(m_imap,set,targetFolder.latin1());
1142 mailimap_set_free( set );
1143 if ( err != MAILIMAP_NO_ERROR ) {
1144 QString error_msg = tr("error copy mails: %1").arg(m_imap->imap_response);
1145 Global::statusMessage(error_msg);
1146 // odebug << error_msg << oendl;
1147 return;
1148 }
1149 if (moveit) {
1150 deleteAllMail(fromFolder);
1151 }
1152}
1153
1154void IMAPwrapper::mvcpMail(const RecMailP&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit)
1155{
1156 if (targetWrapper != this) {
1157 // odebug << "Using generic" << oendl;
1158 AbstractMail::mvcpMail(mail,targetFolder,targetWrapper,moveit);
1159 return;
1160 }
1161 mailimap_set *set = 0;
1162 login();
1163 if (!m_imap) {
1164 return;
1165 }
1166 int err = selectMbox(mail->getMbox());
1167 if ( err != MAILIMAP_NO_ERROR ) {
1168 return;
1169 }
1170 set = mailimap_set_new_single(mail->getNumber());
1171 err = mailimap_copy(m_imap,set,targetFolder.latin1());
1172 mailimap_set_free( set );
1173 if ( err != MAILIMAP_NO_ERROR ) {
1174 QString error_msg = tr("error copy mail: %1").arg(m_imap->imap_response);
1175 Global::statusMessage(error_msg);
1176 // odebug << error_msg << oendl;
1177 return;
1178 }
1179 if (moveit) {
1180 deleteMail(mail);
1181 }
1182}