-rw-r--r-- | kmicromail/libmailwrapper/imapwrapper.cpp | 13 | ||||
-rw-r--r-- | kmicromail/libmailwrapper/imapwrapper.h | 2 |
2 files changed, 11 insertions, 4 deletions
diff --git a/kmicromail/libmailwrapper/imapwrapper.cpp b/kmicromail/libmailwrapper/imapwrapper.cpp index 93fb7de..09e52b8 100644 --- a/kmicromail/libmailwrapper/imapwrapper.cpp +++ b/kmicromail/libmailwrapper/imapwrapper.cpp @@ -1,470 +1,477 @@ // CHANGED 2004-09-31 Lutz Rogowski #include <stdlib.h> #include <libetpan/libetpan.h> #include <qpe/global.h> #include <qapplication.h> #include "imapwrapper.h" #include "mailtypes.h" #include "logindialog.h" #include <qprogressbar.h> #include "genericwrapper.h" #include <kglobal.h> using namespace Opie::Core; int IMAPwrapper::mMax = 0; int IMAPwrapper::mCurrent = 0; IMAPwrapper::IMAPwrapper( IMAPaccount *a ) : AbstractMail() { account = a; m_imap = 0; m_Lastmbox = ""; mCurrent = 0; mMax = 0; } IMAPwrapper::~IMAPwrapper() { logout(); } /* to avoid to often select statements in loops etc. we trust that we are logged in and connection is established!*/ int IMAPwrapper::selectMbox(const QString&mbox) { if (mbox == m_Lastmbox) { return MAILIMAP_NO_ERROR; } int err = mailimap_select( m_imap, (char*)mbox.latin1()); if ( err != MAILIMAP_NO_ERROR ) { m_Lastmbox = ""; return err; } m_Lastmbox = mbox; return err; } void IMAPwrapper::imap_progress( size_t current, size_t maximum ) { qApp->processEvents(); return; //qDebug("imap progress %d of %d ",current,maximum ); //Global::statusMessage(i18n("Downloading message %1 of %2").arg( current).arg(maximum)); //qApp->processEvents() static unsigned int last = 0; if ( last != current ) IMAPwrapper::progress(); last = current; } void IMAPwrapper::progress( QString m ) { static QString mProgrMess; if ( m != QString::null ) { mProgrMess = m; mCurrent = 1; return; } QString mess; //qDebug("progress "); if ( mMax ) mess = mProgrMess +i18n(" message %1 of %2").arg( mCurrent++).arg(mMax); else mess = mProgrMess +i18n(" message %1").arg( mCurrent++); Global::statusMessage(mess); //qDebug("Progress %s %s", mess.latin1(), m.latin1()); qApp->processEvents(); } bool IMAPwrapper::start_tls(bool force_tls) { int err; bool try_tls = force_tls; mailimap_capability_data * cap_data = 0; err = mailimap_capability(m_imap,&cap_data); if (err != MAILIMAP_NO_ERROR) { Global::statusMessage("error getting capabilities!"); return false; } clistiter * cur; for(cur = clist_begin(cap_data->cap_list) ; cur != NULL;cur = clist_next(cur)) { struct mailimap_capability * cap; cap = (struct mailimap_capability *)clist_content(cur); if (cap->cap_type == MAILIMAP_CAPABILITY_NAME) { if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) { try_tls = true; break; } } } if (cap_data) { mailimap_capability_data_free(cap_data); } if (try_tls) { err = mailimap_starttls(m_imap); if (err != MAILIMAP_NO_ERROR && force_tls) { Global::statusMessage(i18n("Server has no TLS support!")); try_tls = false; } else { mailstream_low * low; mailstream_low * new_low; low = mailstream_get_low(m_imap->imap_stream); if (!low) { try_tls = false; } else { int fd = mailstream_low_get_fd(low); if (fd > -1 && (new_low = mailstream_low_ssl_open(fd))!=0) { mailstream_low_free(low); mailstream_set_low(m_imap->imap_stream, new_low); } else { try_tls = false; } } } } return try_tls; } -void IMAPwrapper::login() +void IMAPwrapper::login(bool tryTLS) // = true) { QString server, user, pass; uint16_t port; int err = MAILIMAP_NO_ERROR; if (account->getOffline()) return; /* we are connected this moment */ /* TODO: setup a timer holding the line or if connection closed - delete the value */ if (m_imap) { err = mailimap_noop(m_imap); if (err!=MAILIMAP_NO_ERROR) { logout(); } else { mailstream_flush(m_imap->imap_stream); return; } } server = account->getServer(); port = account->getPort().toUInt(); if ( account->getUser().isEmpty() || account->getPassword().isEmpty() ) { LoginDialog login( account->getUser(), account->getPassword(), NULL, 0, true ); login.show(); if ( QDialog::Accepted == login.exec() ) { // ok user = login.getUser(); pass = login.getPassword(); } else { // cancel return; } } else { user = account->getUser(); pass = account->getPassword(); } m_imap = mailimap_new( 20, &imap_progress ); /* connect */ bool ssl = false; bool try_tls = false; bool force_tls = false; if ( account->ConnectionType() == 2 ) { ssl = true; } if (account->ConnectionType()==1) { force_tls = true; } if ( ssl ) { qDebug("using ssl "); err = mailimap_ssl_connect( m_imap, (char*)server.latin1(), port ); qDebug("back "); } else { err = mailimap_socket_connect( m_imap, (char*)server.latin1(), port ); } if ( err != MAILIMAP_NO_ERROR && err != MAILIMAP_NO_ERROR_AUTHENTICATED && err != MAILIMAP_NO_ERROR_NON_AUTHENTICATED ) { QString failure = ""; if (err == MAILIMAP_ERROR_CONNECTION_REFUSED) { failure="Connection refused"; } else { failure="Unknown failure"; } Global::statusMessage(i18n("error connecting imap server: %1").arg(failure)); mailimap_free( m_imap ); m_imap = 0; return; } - + if ( tryTLS ) { if (!ssl) { try_tls = start_tls(force_tls); } - + } bool ok = true; if (force_tls && !try_tls) { Global::statusMessage(i18n("Server has no TLS support!")); ok = false; } /* login */ if (ok) { err = mailimap_login_simple( m_imap, (char*)user.latin1(), (char*)pass.latin1() ); if ( err != MAILIMAP_NO_ERROR ) { + if ( tryTLS && !force_tls && !try_tls ) { + err = mailimap_close( m_imap ); + mailimap_free( m_imap ); + m_imap = 0; + login( false ); + return; + } Global::statusMessage(i18n("error logging in imap server: %1").arg(m_imap->imap_response)); ok = false; } } if (!ok) { err = mailimap_close( m_imap ); mailimap_free( m_imap ); m_imap = 0; } } void IMAPwrapper::logout() { int err = MAILIMAP_NO_ERROR; if (!m_imap) return; err = mailimap_logout( m_imap ); err = mailimap_close( m_imap ); mailimap_free( m_imap ); m_imap = 0; m_Lastmbox = ""; } void IMAPwrapper::listMessages(const QString&mailbox,QValueList<Opie::Core::OSmartPointer<RecMail> > &target , int maxSizeInKb) { int tryAgain = 1; while ( tryAgain >= 0 ) { int err = MAILIMAP_NO_ERROR; clist *result = 0; clistcell *current; mailimap_fetch_type *fetchType = 0; mailimap_set *set = 0; login(); if (!m_imap) { return; } /* select mailbox READONLY for operations */ err = selectMbox(mailbox); if ( err != MAILIMAP_NO_ERROR ) { return; } int last = m_imap->imap_selection_info->sel_exists; if (last == 0) { Global::statusMessage(i18n("Mailbox has no mails")); return; } else { } progress( i18n("Fetch ")); mMax = last; //qDebug("last %d ", last); Global::statusMessage(i18n("Fetching header list")); qApp->processEvents(); /* the range has to start at 1!!! not with 0!!!! */ //LR the access to web.de imap server is no working with value 1 //qDebug("interval %d - %d ", tryAgain, last-1+tryAgain ); set = mailimap_set_new_interval( tryAgain, last ); fetchType = mailimap_fetch_type_new_fetch_att_list_empty(); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_envelope()); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_flags()); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_internaldate()); mailimap_fetch_type_new_fetch_att_list_add(fetchType,mailimap_fetch_att_new_rfc822_size()); err = mailimap_fetch( m_imap, set, fetchType, &result ); mailimap_set_free( set ); mailimap_fetch_type_free( fetchType ); QString date,subject,from; if ( err == MAILIMAP_NO_ERROR ) { tryAgain = -1; mailimap_msg_att * msg_att; int i = 0; for (current = clist_begin(result); current != 0; current=clist_next(current)) { ++i; //qDebug("iii %d ",i); msg_att = (mailimap_msg_att*)current->data; RecMail*m = parse_list_result(msg_att); if (m) { if ( maxSizeInKb == 0 || m->Msgsize()<=(unsigned int ) maxSizeInKb*1024 ) { m->setNumber(i); m->setMbox(mailbox); m->setWrapper(this); target.append(m); } } } Global::statusMessage(i18n("Mailbox has %1 mails").arg(target.count())); } else { --tryAgain; --tryAgain;//disabled tryagain by adding this line if ( tryAgain < 0 ) Global::statusMessage(i18n("Error fetching headers: %1").arg(m_imap->imap_response)); else qDebug("try again... "); } if (result) mailimap_fetch_list_free(result); } } QValueList<Opie::Core::OSmartPointer<Folder> >* IMAPwrapper::listFolders() { const char *path, *mask; int err = MAILIMAP_NO_ERROR; clist *result = 0; clistcell *current = 0; clistcell*cur_flag = 0; mailimap_mbx_list_flags*bflags = 0; QValueList<FolderP>* folders = new QValueList<FolderP>(); login(); if (!m_imap) { return folders; } /* * First we have to check for INBOX 'cause it sometimes it's not inside the path. * We must not forget to filter them out in next loop! * it seems like ugly code. and yes - it is ugly code. but the best way. */ Global::statusMessage(i18n("Fetching folder list")); qApp->processEvents(); QString temp; mask = "INBOX" ; mailimap_mailbox_list *list; err = mailimap_list( m_imap, (char*)"", (char*)mask, &result ); QString del; bool selectable = true; bool no_inferiors = false; if ( err == MAILIMAP_NO_ERROR ) { current = result->first; for ( int i = result->count; i > 0; i-- ) { list = (mailimap_mailbox_list *) current->data; // it is better use the deep copy mechanism of qt itself // instead of using strdup! temp = list->mb_name; del = list->mb_delimiter; current = current->next; if ( (bflags = list->mb_flag) ) { selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&& bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT); for(cur_flag=clist_begin(bflags->mbf_oflags);cur_flag;cur_flag=clist_next(cur_flag)) { if ( ((mailimap_mbx_list_oflag*)cur_flag->data)->of_type==MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS) { no_inferiors = true; } } } folders->append( new IMAPFolder(temp,del,selectable,no_inferiors,account->getPrefix())); } } else { qDebug("error fetching folders: "); } mailimap_list_result_free( result ); /* * second stage - get the other then inbox folders */ mask = "*" ; path = account->getPrefix().latin1(); if (!path) path = ""; err = mailimap_list( m_imap, (char*)path, (char*)mask, &result ); if ( err == MAILIMAP_NO_ERROR ) { current = result->first; for ( current=clist_begin(result);current!=NULL;current=clist_next(current)) { no_inferiors = false; list = (mailimap_mailbox_list *) current->data; // it is better use the deep copy mechanism of qt itself // instead of using strdup! temp = list->mb_name; if (temp.lower()=="inbox") continue; if (temp.lower()==account->getPrefix().lower()) continue; if ( (bflags = list->mb_flag) ) { selectable = !(bflags->mbf_type==MAILIMAP_MBX_LIST_FLAGS_SFLAG&& bflags->mbf_sflag==MAILIMAP_MBX_LIST_SFLAG_NOSELECT); for(cur_flag=clist_begin(bflags->mbf_oflags);cur_flag;cur_flag=clist_next(cur_flag)) { if ( ((mailimap_mbx_list_oflag*)cur_flag->data)->of_type==MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS) { no_inferiors = true; } } } del = list->mb_delimiter; folders->append(new IMAPFolder(temp,del,selectable,no_inferiors,account->getPrefix())); } } else { qDebug("error fetching folders "); } if (result) mailimap_list_result_free( result ); return folders; } RecMail*IMAPwrapper::parse_list_result(mailimap_msg_att* m_att) { RecMail * m = 0; mailimap_msg_att_item *item=0; clistcell *current,*c,*cf; mailimap_msg_att_dynamic*flist; mailimap_flag_fetch*cflag; int size = 0; QBitArray mFlags(7); QStringList addresslist; if (!m_att) { return m; } m = new RecMail(); for (c = clist_begin(m_att->att_list); c!=NULL;c=clist_next(c) ) { current = c; size = 0; item = (mailimap_msg_att_item*)current->data; if ( !item ) continue; if (item->att_type!=MAILIMAP_MSG_ATT_ITEM_STATIC) { flist = (mailimap_msg_att_dynamic*)item->att_data.att_dyn; if (!flist || !flist->att_list) { continue; } cf = flist->att_list->first; if( cf ) { for (cf = clist_begin(flist->att_list); cf!=NULL; cf = clist_next(cf)) { cflag = (mailimap_flag_fetch*)cf->data; if( ! cflag ) qDebug("imap:NO cflag "); else { if (cflag->fl_type==MAILIMAP_FLAG_FETCH_OTHER && cflag->fl_flag!=0) { switch (cflag->fl_flag->fl_type) { case MAILIMAP_FLAG_ANSWERED: /* \Answered flag */ mFlags.setBit(FLAG_ANSWERED); break; case MAILIMAP_FLAG_FLAGGED: /* \Flagged flag */ mFlags.setBit(FLAG_FLAGGED); break; case MAILIMAP_FLAG_DELETED: /* \Deleted flag */ mFlags.setBit(FLAG_DELETED); break; case MAILIMAP_FLAG_SEEN: /* \Seen flag */ mFlags.setBit(FLAG_SEEN); break; case MAILIMAP_FLAG_DRAFT: /* \Draft flag */ mFlags.setBit(FLAG_DRAFT); break; case MAILIMAP_FLAG_KEYWORD: /* keyword flag */ break; case MAILIMAP_FLAG_EXTENSION: /* \extension flag */ break; default: break; } } else if (cflag->fl_type==MAILIMAP_FLAG_FETCH_RECENT) { mFlags.setBit(FLAG_RECENT); diff --git a/kmicromail/libmailwrapper/imapwrapper.h b/kmicromail/libmailwrapper/imapwrapper.h index 5535d8d..31c60a8 100644 --- a/kmicromail/libmailwrapper/imapwrapper.h +++ b/kmicromail/libmailwrapper/imapwrapper.h @@ -1,85 +1,85 @@ // CHANGED 2004-09-31 Lutz Rogowski #ifndef __IMAPWRAPPER #define __IMAPWRAPPER #include <qlist.h> #include "mailwrapper.h" #include "abstractmail.h" #include <libetpan/clist.h> struct mailimap; struct mailimap_body; struct mailimap_body_type_1part; struct mailimap_body_type_text; struct mailimap_body_type_basic; struct mailimap_body_type_msg; struct mailimap_body_type_mpart; struct mailimap_body_fields; struct mailimap_msg_att; class encodedString; class IMAPwrapper : public AbstractMail { Q_OBJECT public: IMAPwrapper( IMAPaccount *a ); virtual ~IMAPwrapper(); virtual QValueList<Opie::Core::OSmartPointer<Folder> >* listFolders(); virtual void listMessages(const QString & mailbox,QValueList<Opie::Core::OSmartPointer<RecMail> >&target , int sizeInKb = 0); virtual void statusFolder(folderStat&target_stat,const QString & mailbox="INBOX"); virtual void deleteMail(const RecMailP&mail); void deleteMailList(const QValueList<RecMailP>&target); virtual void answeredMail(const RecMailP&mail); virtual int deleteAllMail(const Opie::Core::OSmartPointer<Folder>&folder); virtual void storeMessage(const char*msg,size_t length, const QString&folder); virtual void mvcpAllMails(const Opie::Core::OSmartPointer<Folder>&fromFolder, const QString&targetFolder,AbstractMail*targetWrapper,bool moveit,int sizeInKb = 0); virtual void mvcpMail(const RecMailP&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit); virtual RecBodyP fetchBody(const RecMailP&mail); virtual QString fetchTextPart(const RecMailP&mail,const RecPartP&part); virtual encodedString* fetchDecodedPart(const RecMailP&mail,const RecPartP&part); virtual encodedString* fetchRawPart(const RecMailP&mail,const RecPartP&part); virtual encodedString* fetchRawBody(const RecMailP&mail); virtual int createMbox(const QString&,const Opie::Core::OSmartPointer<Folder>&parentfolder=0, const QString& delemiter="/",bool getsubfolder=false); virtual int deleteMbox(const Opie::Core::OSmartPointer<Folder>&folder); static void imap_progress( size_t current, size_t maximum ); virtual void logout(); virtual MAILLIB::ATYPE getType()const; virtual const QString&getName()const; virtual Account* getAccount() { return account; }; protected: RecMail*parse_list_result(mailimap_msg_att*); - void login(); + void login(bool tryTLS = true); bool start_tls(bool force=true); virtual QString fetchTextPart(const RecMailP&mail,const QValueList<int>&path,bool internal_call=false,const QString&enc=""); virtual encodedString*fetchRawPart(const RecMailP&mail,const QValueList<int>&path,bool internal_call); int selectMbox(const QString&mbox); void fillSinglePart(RecPartP&target_part,mailimap_body_type_1part*Description); void fillSingleTextPart(RecPartP&target_part,mailimap_body_type_text*which); void fillSingleBasicPart(RecPartP&target_part,mailimap_body_type_basic*which); void fillSingleMsgPart(RecPartP&target_part,mailimap_body_type_msg*which); void fillMultiPart(RecPartP&target_part,mailimap_body_type_mpart*which); void traverseBody(const RecMailP&mail,mailimap_body*body,RecBodyP&target_body,int current_recursion,QValueList<int>recList,int current_count=1); /* just helpers */ static void fillBodyFields(RecPartP&target_part,mailimap_body_fields*which); static QStringList address_list_to_stringlist(clist*list); static void progress(QString mess = QString::null); static int mCurrent; static int mMax; IMAPaccount *account; mailimap *m_imap; QString m_Lastmbox; }; #endif |