Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

imapwrapper.cpp

Go to the documentation of this file.
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 /* to avoid to often select statements in loops etc.
00026    we trust that we are logged in and connection is established!*/
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     /* we are connected this moment */
00110     /* TODO: setup a timer holding the line or if connection closed - delete the value */
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         // ok
00127         user = login.getUser().latin1();
00128         pass = login.getPassword().latin1();
00129       } else {
00130         // cancel
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     /* connect */
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     /* login */
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     /* select mailbox READONLY for operations */
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     /* the range has to start at 1!!! not with 0!!!! */
00241     set = mailimap_set_new_interval( 1, last );
00242 
00243 
00244     fetchType = mailimap_fetch_type_new_all();
00245 /*
00246     fetchType = mailimap_fetch_type_new_fetch_att_list_empty();
00247     mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_envelope());
00248     mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_flags());
00249     mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_internaldate());
00250     mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_rfc822_size());
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  * First we have to check for INBOX 'cause it sometimes it's not inside the path.
00296  * We must not forget to filter them out in next loop!
00297  * it seems like ugly code. and yes - it is ugly code. but the best way.
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             // it is better use the deep copy mechanism of qt itself
00311             // instead of using strdup!
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  * second stage - get the other then inbox folders
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             // it is better use the deep copy mechanism of qt itself
00345             // instead of using strdup!
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:  /* \Answered flag */
00400                         mFlags.setBit(FLAG_ANSWERED);
00401                         break;
00402                     case MAILIMAP_FLAG_FLAGGED:   /* \Flagged flag */
00403                         mFlags.setBit(FLAG_FLAGGED);
00404                         break;
00405                     case MAILIMAP_FLAG_DELETED:   /* \Deleted flag */
00406                         mFlags.setBit(FLAG_DELETED);
00407                         break;
00408                     case MAILIMAP_FLAG_SEEN:      /* \Seen flag */
00409                         mFlags.setBit(FLAG_SEEN);
00410                         break;
00411                     case MAILIMAP_FLAG_DRAFT:     /* \Draft flag */
00412                         mFlags.setBit(FLAG_DRAFT);
00413                         break;
00414                     case MAILIMAP_FLAG_KEYWORD:   /* keyword flag */
00415                         break;
00416                     case MAILIMAP_FLAG_EXTENSION: /* \extension flag */
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             /* reply to address, eg. email. */
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             // not used this moment
00474         } else if (item->att_data.att_static->att_type==MAILIMAP_MSG_ATT_RFC822_SIZE) {
00475             //size = item->att_data.att_static->att_data.att_rfc822_size;
00476             m->setMsgsize(item->att_data.att_static->att_data.att_rfc822_size);
00477         }
00478     }
00479     /* msg is already deleted */
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     /* the range has to start at 1!!! not with 0!!!! */
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     /* if path == empty then its a request for the whole rfc822 mail and generates
00603        a "fetch <id> (body[])" statement on imap server */
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                     /* detach - we take over the content */
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 /* current_recursion is for recursive calls.
00648    current_count means the position inside the internal loop! */
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         /* important: Check for is NULL 'cause a body can be empty!
00672            And we put it only into the mail if it is the FIRST part */
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     /* we set this type to text/plain */
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     /* should we realy do that at this moment? */
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     /* should we realy do that at this moment? */
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     // dummy
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 }

Generated on Sat Nov 5 16:17:37 2005 for OPIE by  doxygen 1.4.2