00001 #include <stdlib.h>
00002 #include <libetpan/libetpan.h>
00003 #include <qpe/global.h>
00004 #include <opie2/oapplication.h>
00005 #include <opie2/odebug.h>
00006
00007 #include "imapwrapper.h"
00008 #include "mailtypes.h"
00009 #include "logindialog.h"
00010
00011 using namespace Opie::Core;
00012 IMAPwrapper::IMAPwrapper( IMAPaccount *a )
00013 : AbstractMail(),MailStatics()
00014 {
00015 account = a;
00016 m_imap = 0;
00017 m_Lastmbox = "";
00018 }
00019
00020 IMAPwrapper::~IMAPwrapper()
00021 {
00022 logout();
00023 }
00024
00025
00026
00027 int IMAPwrapper::selectMbox(const QString&mbox)
00028 {
00029 if (mbox == m_Lastmbox) {
00030 return MAILIMAP_NO_ERROR;
00031 }
00032 int err = mailimap_select( m_imap, (char*)mbox.latin1());
00033 if ( err != MAILIMAP_NO_ERROR ) {
00034 odebug << "error selecting mailbox: " << m_imap->imap_response << "" << oendl;
00035 m_Lastmbox = "";
00036 return err;
00037 }
00038 m_Lastmbox = mbox;
00039 return err;
00040 }
00041
00042 void IMAPwrapper::imap_progress( size_t current, size_t maximum )
00043 {
00044 qApp->processEvents();
00045 odebug << "IMAP: " << current << " of " << maximum << "" << oendl;
00046 }
00047
00048 bool IMAPwrapper::start_tls(bool force_tls)
00049 {
00050 int err;
00051 bool try_tls=false;
00052 mailimap_capability_data * cap_data = 0;
00053
00054 err = mailimap_capability(m_imap,&cap_data);
00055 if (err != MAILIMAP_NO_ERROR) {
00056 Global::statusMessage("error getting capabilities!");
00057 odebug << "error getting capabilities!" << oendl;
00058 return false;
00059 }
00060 clistiter * cur;
00061 for(cur = clist_begin(cap_data->cap_list) ; cur != NULL;cur = clist_next(cur)) {
00062 struct mailimap_capability * cap;
00063 cap = (struct mailimap_capability *)clist_content(cur);
00064 if (cap->cap_type == MAILIMAP_CAPABILITY_NAME) {
00065 if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) {
00066 try_tls = true;
00067 break;
00068 }
00069 }
00070 }
00071 if (cap_data) {
00072 mailimap_capability_data_free(cap_data);
00073 }
00074 if (try_tls) {
00075 err = mailimap_starttls(m_imap);
00076 if (err != MAILIMAP_NO_ERROR) {
00077 if (force_tls) {
00078 Global::statusMessage(tr("Server has no TLS support!"));
00079 odebug << "Server has no TLS support!" << oendl;
00080 }
00081 try_tls = false;
00082 } else {
00083 mailstream_low * low;
00084 mailstream_low * new_low;
00085 low = mailstream_get_low(m_imap->imap_stream);
00086 if (!low) {
00087 try_tls = false;
00088 } else {
00089 int fd = mailstream_low_get_fd(low);
00090 if (fd > -1 && (new_low = mailstream_low_ssl_open(fd))!=0) {
00091 mailstream_low_free(low);
00092 mailstream_set_low(m_imap->imap_stream, new_low);
00093 } else {
00094 try_tls = false;
00095 }
00096 }
00097 }
00098 }
00099 return try_tls;
00100 }
00101
00102 void IMAPwrapper::login()
00103 {
00104 const char *server, *user, *pass;
00105 uint16_t port;
00106 int err = MAILIMAP_NO_ERROR;
00107
00108 if (account->getOffline()) return;
00109
00110
00111 if (m_imap) {
00112 err = mailimap_noop(m_imap);
00113 if (err!=MAILIMAP_NO_ERROR) {
00114 logout();
00115 } else {
00116 mailstream_flush(m_imap->imap_stream);
00117 return;
00118 }
00119 }
00120 server = account->getServer().latin1();
00121 port = account->getPort().toUInt();
00122 if ( account->getUser().isEmpty() || account->getPassword().isEmpty() ) {
00123 LoginDialog login( account->getUser(), account->getPassword(), NULL, 0, true );
00124 login.show();
00125 if ( QDialog::Accepted == login.exec() ) {
00126
00127 user = login.getUser().latin1();
00128 pass = login.getPassword().latin1();
00129 } else {
00130
00131 odebug << "IMAP: Login canceled" << oendl;
00132 return;
00133 }
00134 } else {
00135 user = account->getUser().latin1();
00136 pass = account->getPassword().latin1();
00137 }
00138
00139 m_imap = mailimap_new( 20, &imap_progress );
00140
00141
00142 bool ssl = false;
00143 bool try_tls = false;
00144 bool force_tls = false;
00145
00146 if ( account->ConnectionType() == 2 ) {
00147 ssl = true;
00148 }
00149 if (account->ConnectionType()==1) {
00150 force_tls = true;
00151 }
00152
00153 if ( ssl ) {
00154 odebug << "using ssl" << oendl;
00155 err = mailimap_ssl_connect( m_imap, (char*)server, port );
00156 } else {
00157 err = mailimap_socket_connect( m_imap, (char*)server, port );
00158 }
00159
00160 if ( err != MAILIMAP_NO_ERROR &&
00161 err != MAILIMAP_NO_ERROR_AUTHENTICATED &&
00162 err != MAILIMAP_NO_ERROR_NON_AUTHENTICATED ) {
00163 QString failure = "";
00164 if (err == MAILIMAP_ERROR_CONNECTION_REFUSED) {
00165 failure="Connection refused";
00166 } else {
00167 failure="Unknown failure";
00168 }
00169 Global::statusMessage(tr("error connecting imap server: %1").arg(failure));
00170 mailimap_free( m_imap );
00171 m_imap = 0;
00172 return;
00173 }
00174
00175 if (!ssl) {
00176 try_tls = start_tls(force_tls);
00177 }
00178
00179 bool ok = true;
00180 if (force_tls && !try_tls) {
00181 Global::statusMessage(tr("Server has no TLS support!"));
00182 odebug << "Server has no TLS support!" << oendl;
00183 ok = false;
00184 }
00185
00186
00187
00188
00189 if (ok) {
00190 err = mailimap_login( m_imap, (char*)user, (char*)pass );
00191 if ( err != MAILIMAP_NO_ERROR ) {
00192 Global::statusMessage(tr("error logging in imap server: %1").arg(m_imap->imap_response));
00193 ok = false;
00194 }
00195 }
00196 if (!ok) {
00197 err = mailimap_close( m_imap );
00198 mailimap_free( m_imap );
00199 m_imap = 0;
00200 }
00201 }
00202
00203 void IMAPwrapper::logout()
00204 {
00205 int err = MAILIMAP_NO_ERROR;
00206 if (!m_imap) return;
00207 err = mailimap_logout( m_imap );
00208 err = mailimap_close( m_imap );
00209 mailimap_free( m_imap );
00210 m_imap = 0;
00211 m_Lastmbox = "";
00212 }
00213
00214 void IMAPwrapper::listMessages(const QString&mailbox,QValueList<Opie::Core::OSmartPointer<RecMail> > &target )
00215 {
00216 int err = MAILIMAP_NO_ERROR;
00217 clist *result = 0;
00218 clistcell *current;
00219 mailimap_fetch_type *fetchType = 0;
00220 mailimap_set *set = 0;
00221
00222 login();
00223 if (!m_imap) {
00224 return;
00225 }
00226
00227 err = selectMbox(mailbox);
00228 if ( err != MAILIMAP_NO_ERROR ) {
00229 return;
00230 }
00231
00232 int last = m_imap->imap_selection_info->sel_exists;
00233
00234 if (last == 0) {
00235 Global::statusMessage(tr("Mailbox has no mails"));
00236 return;
00237 } else {
00238 }
00239
00240
00241 set = mailimap_set_new_interval( 1, last );
00242
00243
00244 fetchType = mailimap_fetch_type_new_all();
00245
00246
00247
00248
00249
00250
00251
00252 err = mailimap_fetch( m_imap, set, fetchType, &result );
00253 mailimap_set_free( set );
00254 mailimap_fetch_type_free( fetchType );
00255
00256 QString date,subject,from;
00257
00258 if ( err == MAILIMAP_NO_ERROR ) {
00259 mailimap_msg_att * msg_att;
00260 int i = 0;
00261 for (current = clist_begin(result); current != 0; current=clist_next(current)) {
00262 ++i;
00263 msg_att = (mailimap_msg_att*)current->data;
00264 RecMail*m = parse_list_result(msg_att);
00265 if (m) {
00266 m->setNumber(i);
00267 m->setMbox(mailbox);
00268 m->setWrapper(this);
00269 target.append(m);
00270 }
00271 }
00272 Global::statusMessage(tr("Mailbox has %1 mails").arg(target.count()));
00273 } else {
00274 Global::statusMessage(tr("Error fetching headers: %1").arg(m_imap->imap_response));
00275 }
00276 if (result) mailimap_fetch_list_free(result);
00277 }
00278
00279 QValueList<Opie::Core::OSmartPointer<Folder> >* IMAPwrapper::listFolders()
00280 {
00281 const char *path, *mask;
00282 int err = MAILIMAP_NO_ERROR;
00283 clist *result = 0;
00284 clistcell *current = 0;
00285 clistcell*cur_flag = 0;
00286 mailimap_mbx_list_flags*bflags = 0;
00287
00288 QValueList<FolderP>* folders = new QValueList<FolderP>();
00289 login();
00290 if (!m_imap) {
00291 return folders;
00292 }
00293
00294
00295
00296
00297
00298
00299 QString temp;
00300 mask = "INBOX" ;
00301 mailimap_mailbox_list *list;
00302 err = mailimap_list( m_imap, (char*)"", (char*)mask, &result );
00303 QString del;
00304 bool selectable = true;
00305 bool no_inferiors = false;
00306 if ( err == MAILIMAP_NO_ERROR ) {
00307 current = result->first;
00308 for ( int i = result->count; i > 0; i-- ) {
00309 list = (mailimap_mailbox_list *) current->data;
00310
00311
00312 temp = list->mb_name;
00313 del = list->mb_delimiter;
00314 current = current->next;
00315 if ( (bflags = list->mb_flag) ) {
00316 selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&&
00317 bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT);
00318 for(cur_flag=clist_begin(bflags->mbf_oflags);cur_flag;cur_flag=clist_next(cur_flag)) {
00319 if ( ((mailimap_mbx_list_oflag*)cur_flag->data)->of_type==MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS) {
00320 no_inferiors = true;
00321 }
00322 }
00323 }
00324 folders->append( new IMAPFolder(temp,del,selectable,no_inferiors,account->getPrefix()));
00325 }
00326 } else {
00327 odebug << "error fetching folders: " << m_imap->imap_response << "" << oendl;
00328 }
00329 mailimap_list_result_free( result );
00330
00331
00332
00333
00334 mask = "*" ;
00335 path = account->getPrefix().latin1();
00336 if (!path) path = "";
00337 odebug << path << oendl;
00338 err = mailimap_list( m_imap, (char*)path, (char*)mask, &result );
00339 if ( err == MAILIMAP_NO_ERROR ) {
00340 current = result->first;
00341 for ( current=clist_begin(result);current!=NULL;current=clist_next(current)) {
00342 no_inferiors = false;
00343 list = (mailimap_mailbox_list *) current->data;
00344
00345
00346 temp = list->mb_name;
00347 if (temp.lower()=="inbox")
00348 continue;
00349 if (temp.lower()==account->getPrefix().lower())
00350 continue;
00351 if ( (bflags = list->mb_flag) ) {
00352 selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&&
00353 bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT);
00354 for(cur_flag=clist_begin(bflags->mbf_oflags);cur_flag;cur_flag=clist_next(cur_flag)) {
00355 if ( ((mailimap_mbx_list_oflag*)cur_flag->data)->of_type==MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS) {
00356 no_inferiors = true;
00357 }
00358 }
00359 }
00360 del = list->mb_delimiter;
00361 folders->append(new IMAPFolder(temp,del,selectable,no_inferiors,account->getPrefix()));
00362 }
00363 } else {
00364 odebug << "error fetching folders " << m_imap->imap_response << "" << oendl;
00365 }
00366 if (result) mailimap_list_result_free( result );
00367 return folders;
00368 }
00369
00370 RecMail*IMAPwrapper::parse_list_result(mailimap_msg_att* m_att)
00371 {
00372 RecMail * m = 0;
00373 mailimap_msg_att_item *item=0;
00374 clistcell *current,*c,*cf;
00375 mailimap_msg_att_dynamic*flist;
00376 mailimap_flag_fetch*cflag;
00377 int size,toffset;
00378 QBitArray mFlags(7);
00379 QStringList addresslist;
00380
00381 if (!m_att) {
00382 return m;
00383 }
00384 size = 0;
00385 m = new RecMail();
00386 for (c = clist_begin(m_att->att_list); c!=NULL;c=clist_next(c) ) {
00387 current = c;
00388 item = (mailimap_msg_att_item*)current->data;
00389 if (item->att_type!=MAILIMAP_MSG_ATT_ITEM_STATIC) {
00390 flist = (mailimap_msg_att_dynamic*)item->att_data.att_dyn;
00391 if (!flist->att_list) {
00392 continue;
00393 }
00394 cf = flist->att_list->first;
00395 for (cf = clist_begin(flist->att_list); cf!=NULL; cf = clist_next(cf)) {
00396 cflag = (mailimap_flag_fetch*)cf->data;
00397 if (cflag->fl_type==MAILIMAP_FLAG_FETCH_OTHER && cflag->fl_flag!=0) {
00398 switch (cflag->fl_flag->fl_type) {
00399 case MAILIMAP_FLAG_ANSWERED:
00400 mFlags.setBit(FLAG_ANSWERED);
00401 break;
00402 case MAILIMAP_FLAG_FLAGGED:
00403 mFlags.setBit(FLAG_FLAGGED);
00404 break;
00405 case MAILIMAP_FLAG_DELETED:
00406 mFlags.setBit(FLAG_DELETED);
00407 break;
00408 case MAILIMAP_FLAG_SEEN:
00409 mFlags.setBit(FLAG_SEEN);
00410 break;
00411 case MAILIMAP_FLAG_DRAFT:
00412 mFlags.setBit(FLAG_DRAFT);
00413 break;
00414 case MAILIMAP_FLAG_KEYWORD:
00415 break;
00416 case MAILIMAP_FLAG_EXTENSION:
00417 break;
00418 default:
00419 break;
00420 }
00421 } else if (cflag->fl_type==MAILIMAP_FLAG_FETCH_RECENT) {
00422 mFlags.setBit(FLAG_RECENT);
00423 }
00424 }
00425 continue;
00426 }
00427 if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_ENVELOPE) {
00428 mailimap_envelope * head = item->att_data.att_static->att_data.att_env;
00429 QDateTime d = parseDateTime(head->env_date,toffset);
00430 m->setDate(d,toffset);
00431 m->setSubject(convert_String((const char*)head->env_subject));
00432 if (head->env_from!=NULL) {
00433 addresslist = address_list_to_stringlist(head->env_from->frm_list);
00434 if (addresslist.count()) {
00435 m->setFrom(addresslist.first());
00436 }
00437 }
00438 if (head->env_to!=NULL) {
00439 addresslist = address_list_to_stringlist(head->env_to->to_list);
00440 m->setTo(addresslist);
00441 }
00442 if (head->env_cc!=NULL) {
00443 addresslist = address_list_to_stringlist(head->env_cc->cc_list);
00444 m->setCC(addresslist);
00445 }
00446 if (head->env_bcc!=NULL) {
00447 addresslist = address_list_to_stringlist(head->env_bcc->bcc_list);
00448 m->setBcc(addresslist);
00449 }
00450
00451 if (head->env_reply_to!=NULL) {
00452 addresslist = address_list_to_stringlist(head->env_reply_to->rt_list);
00453 if (addresslist.count()) {
00454 m->setReplyto(addresslist.first());
00455 }
00456 }
00457 if (head->env_in_reply_to!=NULL) {
00458 QString h(head->env_in_reply_to);
00459 while (h.length()>0 && h[0]=='<') {
00460 h.remove(0,1);
00461 }
00462 while (h.length()>0 && h[h.length()-1]=='>') {
00463 h.remove(h.length()-1,1);
00464 }
00465 if (h.length()>0) {
00466 m->setInreply(QStringList(h));
00467 }
00468 }
00469 if (head->env_message_id) {
00470 m->setMsgid(QString(head->env_message_id));
00471 }
00472 } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_INTERNALDATE) {
00473
00474 } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_RFC822_SIZE) {
00475
00476 m->setMsgsize(item->att_data.att_static->att_data.att_rfc822_size);
00477 }
00478 }
00479
00480 if (mFlags.testBit(FLAG_DELETED) && m) {
00481 delete m;
00482 m = 0;
00483 }
00484 if (m) {
00485 m->setFlags(mFlags);
00486 }
00487 return m;
00488 }
00489
00490 RecBodyP IMAPwrapper::fetchBody(const RecMailP&mail)
00491 {
00492 RecBodyP body = new RecBody();
00493 const char *mb;
00494 int err = MAILIMAP_NO_ERROR;
00495 clist *result = 0;
00496 clistcell *current;
00497 mailimap_fetch_att *fetchAtt = 0;
00498 mailimap_fetch_type *fetchType = 0;
00499 mailimap_set *set = 0;
00500 mailimap_body*body_desc = 0;
00501
00502 mb = mail->getMbox().latin1();
00503
00504 login();
00505 if (!m_imap) {
00506 return body;
00507 }
00508 err = selectMbox(mail->getMbox());
00509 if ( err != MAILIMAP_NO_ERROR ) {
00510 return body;
00511 }
00512
00513
00514 set = mailimap_set_new_interval( mail->getNumber(),mail->getNumber() );
00515 fetchAtt = mailimap_fetch_att_new_bodystructure();
00516 fetchType = mailimap_fetch_type_new_fetch_att(fetchAtt);
00517 err = mailimap_fetch( m_imap, set, fetchType, &result );
00518 mailimap_set_free( set );
00519 mailimap_fetch_type_free( fetchType );
00520
00521 if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) {
00522 mailimap_msg_att * msg_att;
00523 msg_att = (mailimap_msg_att*)current->data;
00524 mailimap_msg_att_item*item = (mailimap_msg_att_item*)msg_att->att_list->first->data;
00525 QValueList<int> path;
00526 body_desc = item->att_data.att_static->att_data.att_body;
00527 traverseBody(mail,body_desc,body,0,path);
00528 } else {
00529 odebug << "error fetching body: " << m_imap->imap_response << "" << oendl;
00530 }
00531 if (result) mailimap_fetch_list_free(result);
00532 return body;
00533 }
00534
00535 QStringList IMAPwrapper::address_list_to_stringlist(clist*list)
00536 {
00537 QStringList l;
00538 QString from;
00539 bool named_from;
00540 clistcell *current = NULL;
00541 mailimap_address * current_address=NULL;
00542 if (!list) {
00543 return l;
00544 }
00545 unsigned int count = 0;
00546 for (current=clist_begin(list);current!= NULL;current=clist_next(current)) {
00547 from = "";
00548 named_from = false;
00549 current_address=(mailimap_address*)current->data;
00550 if (current_address->ad_personal_name){
00551 from+=convert_String((const char*)current_address->ad_personal_name);
00552 from+=" ";
00553 named_from = true;
00554 }
00555 if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) {
00556 from+="<";
00557 }
00558 if (current_address->ad_mailbox_name) {
00559 from+=QString(current_address->ad_mailbox_name);
00560 from+="@";
00561 }
00562 if (current_address->ad_host_name) {
00563 from+=QString(current_address->ad_host_name);
00564 }
00565 if (named_from && (current_address->ad_mailbox_name || current_address->ad_host_name)) {
00566 from+=">";
00567 }
00568 l.append(QString(from));
00569 if (++count > 99) {
00570 break;
00571 }
00572 }
00573 return l;
00574 }
00575
00576 encodedString*IMAPwrapper::fetchRawPart(const RecMailP&mail,const QValueList<int>&path,bool internal_call)
00577 {
00578 encodedString*res=new encodedString;
00579 int err;
00580 mailimap_fetch_type *fetchType;
00581 mailimap_set *set;
00582 clistcell*current,*cur;
00583 mailimap_section_part * section_part = 0;
00584 mailimap_section_spec * section_spec = 0;
00585 mailimap_section * section = 0;
00586 mailimap_fetch_att * fetch_att = 0;
00587
00588 login();
00589 if (!m_imap) {
00590 return res;
00591 }
00592 if (!internal_call) {
00593 err = selectMbox(mail->getMbox());
00594 if ( err != MAILIMAP_NO_ERROR ) {
00595 return res;
00596 }
00597 }
00598 set = mailimap_set_new_single(mail->getNumber());
00599
00600 clist*id_list = 0;
00601
00602
00603
00604 if (path.count()>0 ) {
00605 id_list = clist_new();
00606 for (unsigned j=0; j < path.count();++j) {
00607 uint32_t * p_id = (uint32_t *)malloc(sizeof(*p_id));
00608 *p_id = path[j];
00609 clist_append(id_list,p_id);
00610 }
00611 section_part = mailimap_section_part_new(id_list);
00612 section_spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, NULL, section_part, NULL);
00613 }
00614
00615 section = mailimap_section_new(section_spec);
00616 fetch_att = mailimap_fetch_att_new_body_section(section);
00617 fetchType = mailimap_fetch_type_new_fetch_att(fetch_att);
00618
00619 clist*result = 0;
00620
00621 err = mailimap_fetch( m_imap, set, fetchType, &result );
00622 mailimap_set_free( set );
00623 mailimap_fetch_type_free( fetchType );
00624
00625 if (err == MAILIMAP_NO_ERROR && (current=clist_begin(result)) ) {
00626 mailimap_msg_att * msg_att;
00627 msg_att = (mailimap_msg_att*)current->data;
00628 mailimap_msg_att_item*msg_att_item;
00629 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; cur = clist_next(cur)) {
00630 msg_att_item = (mailimap_msg_att_item*)clist_content(cur);
00631 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
00632 if (msg_att_item->att_data.att_static->att_type == MAILIMAP_MSG_ATT_BODY_SECTION) {
00633 char*text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
00634
00635 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = 0L;
00636 res->setContent(text,msg_att_item->att_data.att_static->att_data.att_body_section->sec_length);
00637 }
00638 }
00639 }
00640 } else {
00641 odebug << "error fetching text: " << m_imap->imap_response << "" << oendl;
00642 }
00643 if (result) mailimap_fetch_list_free(result);
00644 return res;
00645 }
00646
00647
00648
00649 void IMAPwrapper::traverseBody(const RecMailP&mail,mailimap_body*body,RecBodyP&target_body,
00650 int current_recursion,QValueList<int>recList,int current_count)
00651 {
00652 if (!body || current_recursion>=10) {
00653 return;
00654 }
00655 switch (body->bd_type) {
00656 case MAILIMAP_BODY_1PART:
00657 {
00658 QValueList<int>countlist = recList;
00659 countlist.append(current_count);
00660 RecPartP currentPart = new RecPart();
00661 mailimap_body_type_1part*part1 = body->bd_data.bd_body_1part;
00662 QString id("");
00663 currentPart->setPositionlist(countlist);
00664 for (unsigned int j = 0; j < countlist.count();++j) {
00665 id+=(j>0?" ":"");
00666 id+=QString("%1").arg(countlist[j]);
00667 }
00668 odebug << "ID = " << id.latin1() << "" << oendl;
00669 currentPart->setIdentifier(id);
00670 fillSinglePart(currentPart,part1);
00671
00672
00673 if (part1->bd_type==MAILIMAP_BODY_TYPE_1PART_TEXT && target_body->Bodytext().isNull() && countlist[0]==1) {
00674 QString body_text = fetchTextPart(mail,countlist,true,currentPart->Encoding());
00675 target_body->setDescription(currentPart);
00676 target_body->setBodytext(body_text);
00677 if (countlist.count()>1) {
00678 target_body->addPart(currentPart);
00679 }
00680 } else {
00681 target_body->addPart(currentPart);
00682 }
00683 if (part1->bd_type==MAILIMAP_BODY_TYPE_1PART_MSG) {
00684 traverseBody(mail,part1->bd_data.bd_type_msg->bd_body,target_body,current_recursion+1,countlist);
00685 }
00686 }
00687 break;
00688 case MAILIMAP_BODY_MPART:
00689 {
00690 QValueList<int>countlist = recList;
00691 clistcell*current=0;
00692 mailimap_body*current_body=0;
00693 unsigned int ccount = 1;
00694 mailimap_body_type_mpart*mailDescription = body->bd_data.bd_body_mpart;
00695 for (current=clist_begin(mailDescription->bd_list);current!=0;current=clist_next(current)) {
00696 current_body = (mailimap_body*)current->data;
00697 if (current_body->bd_type==MAILIMAP_BODY_MPART) {
00698 RecPartP targetPart = new RecPart();
00699 targetPart->setType("multipart");
00700 fillMultiPart(targetPart,mailDescription);
00701 countlist.append(current_count);
00702 targetPart->setPositionlist(countlist);
00703 target_body->addPart(targetPart);
00704 QString id("");
00705 for (unsigned int j = 0; j < countlist.count();++j) {
00706 id+=(j>0?" ":"");
00707 id+=QString("%1").arg(countlist[j]);
00708 }
00709 odebug << "ID(mpart) = " << id.latin1() << "" << oendl;
00710 }
00711 traverseBody(mail,current_body,target_body,current_recursion+1,countlist,ccount);
00712 if (current_body->bd_type==MAILIMAP_BODY_MPART) {
00713 countlist = recList;
00714 }
00715 ++ccount;
00716 }
00717 }
00718 break;
00719 default:
00720 break;
00721 }
00722 }
00723
00724 void IMAPwrapper::fillSinglePart(RecPartP&target_part,mailimap_body_type_1part*Description)
00725 {
00726 if (!Description) {
00727 return;
00728 }
00729 switch (Description->bd_type) {
00730 case MAILIMAP_BODY_TYPE_1PART_TEXT:
00731 target_part->setType("text");
00732 fillSingleTextPart(target_part,Description->bd_data.bd_type_text);
00733 break;
00734 case MAILIMAP_BODY_TYPE_1PART_BASIC:
00735 fillSingleBasicPart(target_part,Description->bd_data.bd_type_basic);
00736 break;
00737 case MAILIMAP_BODY_TYPE_1PART_MSG:
00738 target_part->setType("message");
00739 fillSingleMsgPart(target_part,Description->bd_data.bd_type_msg);
00740 break;
00741 default:
00742 break;
00743 }
00744 }
00745
00746 void IMAPwrapper::fillSingleTextPart(RecPartP&target_part,mailimap_body_type_text*which)
00747 {
00748 if (!which) {
00749 return;
00750 }
00751 QString sub;
00752 sub = which->bd_media_text;
00753 odebug << "Type= text/" << which->bd_media_text << "" << oendl;
00754 target_part->setSubtype(sub.lower());
00755 target_part->setLines(which->bd_lines);
00756 fillBodyFields(target_part,which->bd_fields);
00757 }
00758
00759 void IMAPwrapper::fillSingleMsgPart(RecPartP&target_part,mailimap_body_type_msg*which)
00760 {
00761 if (!which) {
00762 return;
00763 }
00764 target_part->setSubtype("rfc822");
00765 odebug << "Message part" << oendl;
00766
00767 target_part->setLines(which->bd_lines);
00768 fillBodyFields(target_part,which->bd_fields);
00769 }
00770
00771 void IMAPwrapper::fillMultiPart(RecPartP&target_part,mailimap_body_type_mpart*which)
00772 {
00773 if (!which) return;
00774 QString sub = which->bd_media_subtype;
00775 target_part->setSubtype(sub.lower());
00776 if (which->bd_ext_mpart && which->bd_ext_mpart->bd_parameter && which->bd_ext_mpart->bd_parameter->pa_list) {
00777 clistcell*cur = 0;
00778 mailimap_single_body_fld_param*param=0;
00779 for (cur = clist_begin(which->bd_ext_mpart->bd_parameter->pa_list);cur!=NULL;cur=clist_next(cur)) {
00780 param = (mailimap_single_body_fld_param*)cur->data;
00781 if (param) {
00782 target_part->addParameter(QString(param->pa_name).lower(),QString(param->pa_value));
00783 }
00784 }
00785 }
00786 }
00787
00788 void IMAPwrapper::fillSingleBasicPart(RecPartP&target_part,mailimap_body_type_basic*which)
00789 {
00790 if (!which) {
00791 return;
00792 }
00793 QString type,sub;
00794 switch (which->bd_media_basic->med_type) {
00795 case MAILIMAP_MEDIA_BASIC_APPLICATION:
00796 type = "application";
00797 break;
00798 case MAILIMAP_MEDIA_BASIC_AUDIO:
00799 type = "audio";
00800 break;
00801 case MAILIMAP_MEDIA_BASIC_IMAGE:
00802 type = "image";
00803 break;
00804 case MAILIMAP_MEDIA_BASIC_MESSAGE:
00805 type = "message";
00806 break;
00807 case MAILIMAP_MEDIA_BASIC_VIDEO:
00808 type = "video";
00809 break;
00810 case MAILIMAP_MEDIA_BASIC_OTHER:
00811 default:
00812 if (which->bd_media_basic->med_basic_type) {
00813 type = which->bd_media_basic->med_basic_type;
00814 } else {
00815 type = "";
00816 }
00817 break;
00818 }
00819 if (which->bd_media_basic->med_subtype) {
00820 sub = which->bd_media_basic->med_subtype;
00821 } else {
00822 sub = "";
00823 }
00824 odebug << "Type = " << type.latin1() << "/" << sub.latin1() << "" << oendl;
00825 target_part->setType(type.lower());
00826 target_part->setSubtype(sub.lower());
00827 fillBodyFields(target_part,which->bd_fields);
00828 }
00829
00830 void IMAPwrapper::fillBodyFields(RecPartP&target_part,mailimap_body_fields*which)
00831 {
00832 if (!which) return;
00833 if (which->bd_parameter && which->bd_parameter->pa_list && which->bd_parameter->pa_list->count>0) {
00834 clistcell*cur;
00835 mailimap_single_body_fld_param*param=0;
00836 for (cur = clist_begin(which->bd_parameter->pa_list);cur!=NULL;cur=clist_next(cur)) {
00837 param = (mailimap_single_body_fld_param*)cur->data;
00838 if (param) {
00839 target_part->addParameter(QString(param->pa_name).lower(),QString(param->pa_value));
00840 }
00841 }
00842 }
00843 mailimap_body_fld_enc*enc = which->bd_encoding;
00844 QString encoding("");
00845 switch (enc->enc_type) {
00846 case MAILIMAP_BODY_FLD_ENC_7BIT:
00847 encoding = "7bit";
00848 break;
00849 case MAILIMAP_BODY_FLD_ENC_8BIT:
00850 encoding = "8bit";
00851 break;
00852 case MAILIMAP_BODY_FLD_ENC_BINARY:
00853 encoding="binary";
00854 break;
00855 case MAILIMAP_BODY_FLD_ENC_BASE64:
00856 encoding="base64";
00857 break;
00858 case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE:
00859 encoding="quoted-printable";
00860 break;
00861 case MAILIMAP_BODY_FLD_ENC_OTHER:
00862 default:
00863 if (enc->enc_value) {
00864 char*t=enc->enc_value;
00865 encoding=QString(enc->enc_value);
00866 enc->enc_value=0L;
00867 free(t);
00868 }
00869 }
00870 if (which->bd_description) {
00871 target_part->setDescription(QString(which->bd_description));
00872 }
00873 target_part->setEncoding(encoding);
00874 target_part->setSize(which->bd_size);
00875 }
00876
00877 void IMAPwrapper::deleteMail(const RecMailP&mail)
00878 {
00879 mailimap_flag_list*flist;
00880 mailimap_set *set;
00881 mailimap_store_att_flags * store_flags;
00882 int err;
00883 login();
00884 if (!m_imap) {
00885 return;
00886 }
00887 err = selectMbox(mail->getMbox());
00888 if ( err != MAILIMAP_NO_ERROR ) {
00889 return;
00890 }
00891 flist = mailimap_flag_list_new_empty();
00892 mailimap_flag_list_add(flist,mailimap_flag_new_deleted());
00893 store_flags = mailimap_store_att_flags_new_set_flags(flist);
00894 set = mailimap_set_new_single(mail->getNumber());
00895 err = mailimap_store(m_imap,set,store_flags);
00896 mailimap_set_free( set );
00897 mailimap_store_att_flags_free(store_flags);
00898
00899 if (err != MAILIMAP_NO_ERROR) {
00900 odebug << "error deleting mail: " << m_imap->imap_response << "" << oendl;
00901 return;
00902 }
00903 odebug << "deleting mail: " << m_imap->imap_response << "" << oendl;
00904
00905 err = mailimap_expunge(m_imap);
00906 if (err != MAILIMAP_NO_ERROR) {
00907 odebug << "error deleting mail: " << m_imap->imap_response << "" << oendl;
00908 }
00909 odebug << "Delete successfull " << m_imap->imap_response << "" << oendl;
00910 }
00911
00912 void IMAPwrapper::answeredMail(const RecMailP&mail)
00913 {
00914 mailimap_flag_list*flist;
00915 mailimap_set *set;
00916 mailimap_store_att_flags * store_flags;
00917 int err;
00918 login();
00919 if (!m_imap) {
00920 return;
00921 }
00922 err = selectMbox(mail->getMbox());
00923 if ( err != MAILIMAP_NO_ERROR ) {
00924 return;
00925 }
00926 flist = mailimap_flag_list_new_empty();
00927 mailimap_flag_list_add(flist,mailimap_flag_new_answered());
00928 store_flags = mailimap_store_att_flags_new_add_flags(flist);
00929 set = mailimap_set_new_single(mail->getNumber());
00930 err = mailimap_store(m_imap,set,store_flags);
00931 mailimap_set_free( set );
00932 mailimap_store_att_flags_free(store_flags);
00933
00934 if (err != MAILIMAP_NO_ERROR) {
00935 odebug << "error marking mail: " << m_imap->imap_response << "" << oendl;
00936 return;
00937 }
00938 }
00939
00940 QString IMAPwrapper::fetchTextPart(const RecMailP&mail,const QValueList<int>&path,bool internal_call,const QString&enc)
00941 {
00942 QString body("");
00943 encodedString*res = fetchRawPart(mail,path,internal_call);
00944 encodedString*r = decode_String(res,enc);
00945 delete res;
00946 if (r) {
00947 if (r->Length()>0) {
00948 body = r->Content();
00949 }
00950 delete r;
00951 }
00952 return body;
00953 }
00954
00955 QString IMAPwrapper::fetchTextPart(const RecMailP&mail,const RecPartP&part)
00956 {
00957 return fetchTextPart(mail,part->Positionlist(),false,part->Encoding());
00958 }
00959
00960 encodedString* IMAPwrapper::fetchDecodedPart(const RecMailP&mail,const RecPartP&part)
00961 {
00962 encodedString*res = fetchRawPart(mail,part->Positionlist(),false);
00963 encodedString*r = decode_String(res,part->Encoding());
00964 delete res;
00965 return r;
00966 }
00967
00968 encodedString* IMAPwrapper::fetchRawPart(const RecMailP&mail,const RecPartP&part)
00969 {
00970 return fetchRawPart(mail,part->Positionlist(),false);
00971 }
00972
00973 int IMAPwrapper::deleteAllMail(const FolderP&folder)
00974 {
00975 login();
00976 if (!m_imap) {
00977 return 0;
00978 }
00979 mailimap_flag_list*flist;
00980 mailimap_set *set;
00981 mailimap_store_att_flags * store_flags;
00982 int err = selectMbox(folder->getName());
00983 if ( err != MAILIMAP_NO_ERROR ) {
00984 return 0;
00985 }
00986
00987 int last = m_imap->imap_selection_info->sel_exists;
00988 if (last == 0) {
00989 Global::statusMessage(tr("Mailbox has no mails!"));
00990 return 0;
00991 }
00992 flist = mailimap_flag_list_new_empty();
00993 mailimap_flag_list_add(flist,mailimap_flag_new_deleted());
00994 store_flags = mailimap_store_att_flags_new_set_flags(flist);
00995 set = mailimap_set_new_interval( 1, last );
00996 err = mailimap_store(m_imap,set,store_flags);
00997 mailimap_set_free( set );
00998 mailimap_store_att_flags_free(store_flags);
00999 if (err != MAILIMAP_NO_ERROR) {
01000 Global::statusMessage(tr("error deleting mail: %s").arg(m_imap->imap_response));
01001 return 0;
01002 }
01003 odebug << "deleting mail: " << m_imap->imap_response << "" << oendl;
01004
01005 err = mailimap_expunge(m_imap);
01006 if (err != MAILIMAP_NO_ERROR) {
01007 Global::statusMessage(tr("error deleting mail: %s").arg(m_imap->imap_response));
01008 return 0;
01009 }
01010 odebug << "Delete successfull " << m_imap->imap_response << "" << oendl;
01011 return 1;
01012 }
01013
01014 int IMAPwrapper::createMbox(const QString&folder,const FolderP&parentfolder,const QString& delemiter,bool getsubfolder)
01015 {
01016 if (folder.length()==0) return 0;
01017 login();
01018 if (!m_imap) {return 0;}
01019 QString pre = account->getPrefix();
01020 if (delemiter.length()>0 && pre.findRev(delemiter)!=pre.length()-1) {
01021 pre+=delemiter;
01022 }
01023 if (parentfolder) {
01024 pre += parentfolder->getDisplayName()+delemiter;
01025 }
01026 pre+=folder;
01027 if (getsubfolder) {
01028 if (delemiter.length()>0) {
01029 pre+=delemiter;
01030 } else {
01031 Global::statusMessage(tr("Cannot create folder %1 for holding subfolders").arg(pre));
01032 return 0;
01033 }
01034 }
01035 odebug << "Creating " << pre.latin1() << "" << oendl;
01036 int res = mailimap_create(m_imap,pre.latin1());
01037 if (res != MAILIMAP_NO_ERROR) {
01038 Global::statusMessage(tr("%1").arg(m_imap->imap_response));
01039 return 0;
01040 }
01041 return 1;
01042 }
01043
01044 int IMAPwrapper::deleteMbox(const FolderP&folder)
01045 {
01046 if (!folder) return 0;
01047 login();
01048 if (!m_imap) {return 0;}
01049 int res = mailimap_delete(m_imap,folder->getName());
01050 if (res != MAILIMAP_NO_ERROR) {
01051 Global::statusMessage(tr("%1").arg(m_imap->imap_response));
01052 return 0;
01053 }
01054 return 1;
01055 }
01056
01057 void IMAPwrapper::statusFolder(folderStat&target_stat,const QString & mailbox)
01058 {
01059 mailimap_status_att_list * att_list =0;
01060 mailimap_mailbox_data_status * status=0;
01061 clistiter * cur = 0;
01062 int r = 0;
01063 target_stat.message_count = 0;
01064 target_stat.message_unseen = 0;
01065 target_stat.message_recent = 0;
01066 login();
01067 if (!m_imap) {
01068 return;
01069 }
01070 att_list = mailimap_status_att_list_new_empty();
01071 if (!att_list) return;
01072 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES);
01073 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT);
01074 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN);
01075 r = mailimap_status(m_imap, mailbox.latin1(), att_list, &status);
01076 if (r==MAILIMAP_NO_ERROR&&status->st_info_list!=0) {
01077 for (cur = clist_begin(status->st_info_list);
01078 cur != NULL ; cur = clist_next(cur)) {
01079 mailimap_status_info * status_info;
01080 status_info = (mailimap_status_info *)clist_content(cur);
01081 switch (status_info->st_att) {
01082 case MAILIMAP_STATUS_ATT_MESSAGES:
01083 target_stat.message_count = status_info->st_value;
01084 break;
01085 case MAILIMAP_STATUS_ATT_RECENT:
01086 target_stat.message_recent = status_info->st_value;
01087 break;
01088 case MAILIMAP_STATUS_ATT_UNSEEN:
01089 target_stat.message_unseen = status_info->st_value;
01090 break;
01091 }
01092 }
01093 } else {
01094 odebug << "Error retrieving status" << oendl;
01095 }
01096 if (status) mailimap_mailbox_data_status_free(status);
01097 if (att_list) mailimap_status_att_list_free(att_list);
01098 }
01099
01100 void IMAPwrapper::storeMessage(const char*msg,size_t length, const QString&folder)
01101 {
01102 login();
01103 if (!m_imap) return;
01104 if (!msg) return;
01105 int r = mailimap_append(m_imap,(char*)folder.latin1(),0,0,msg,length);
01106 if (r != MAILIMAP_NO_ERROR) {
01107 Global::statusMessage("Error storing mail!");
01108 }
01109 }
01110
01111 MAILLIB::ATYPE IMAPwrapper::getType()const
01112 {
01113 return account->getType();
01114 }
01115
01116 const QString&IMAPwrapper::getName()const
01117 {
01118 odebug << "Get name: " << account->getAccountName().latin1() << "" << oendl;
01119 return account->getAccountName();
01120 }
01121
01122 encodedString* IMAPwrapper::fetchRawBody(const RecMailP&mail)
01123 {
01124
01125 QValueList<int> path;
01126 return fetchRawPart(mail,path,false);
01127 }
01128
01129 void IMAPwrapper::mvcpAllMails(const FolderP&fromFolder,
01130 const QString&targetFolder,AbstractMail*targetWrapper,bool moveit)
01131 {
01132 if (targetWrapper != this) {
01133 AbstractMail::mvcpAllMails(fromFolder,targetFolder,targetWrapper,moveit);
01134 odebug << "Using generic" << oendl;
01135 return;
01136 }
01137 mailimap_set *set = 0;
01138 login();
01139 if (!m_imap) {
01140 return;
01141 }
01142 int err = selectMbox(fromFolder->getName());
01143 if ( err != MAILIMAP_NO_ERROR ) {
01144 return;
01145 }
01146 int last = m_imap->imap_selection_info->sel_exists;
01147 set = mailimap_set_new_interval( 1, last );
01148 err = mailimap_copy(m_imap,set,targetFolder.latin1());
01149 mailimap_set_free( set );
01150 if ( err != MAILIMAP_NO_ERROR ) {
01151 QString error_msg = tr("error copy mails: %1").arg(m_imap->imap_response);
01152 Global::statusMessage(error_msg);
01153 odebug << error_msg << oendl;
01154 return;
01155 }
01156 if (moveit) {
01157 deleteAllMail(fromFolder);
01158 }
01159 }
01160
01161 void IMAPwrapper::mvcpMail(const RecMailP&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit)
01162 {
01163 if (targetWrapper != this) {
01164 odebug << "Using generic" << oendl;
01165 AbstractMail::mvcpMail(mail,targetFolder,targetWrapper,moveit);
01166 return;
01167 }
01168 mailimap_set *set = 0;
01169 login();
01170 if (!m_imap) {
01171 return;
01172 }
01173 int err = selectMbox(mail->getMbox());
01174 if ( err != MAILIMAP_NO_ERROR ) {
01175 return;
01176 }
01177 set = mailimap_set_new_single(mail->getNumber());
01178 err = mailimap_copy(m_imap,set,targetFolder.latin1());
01179 mailimap_set_free( set );
01180 if ( err != MAILIMAP_NO_ERROR ) {
01181 QString error_msg = tr("error copy mail: %1").arg(m_imap->imap_response);
01182 Global::statusMessage(error_msg);
01183 odebug << error_msg << oendl;
01184 return;
01185 }
01186 if (moveit) {
01187 deleteMail(mail);
01188 }
01189 }