-rw-r--r-- | noncore/net/mail/accountview.cpp | 64 | ||||
-rw-r--r-- | noncore/net/mail/accountview.h | 18 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/abstractmail.cpp | 3 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/genericwrapper.cpp | 8 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/genericwrapper.h | 4 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/libmailwrapper.pro | 6 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mailwrapper.cpp | 18 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mailwrapper.h | 9 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mboxwrapper.h | 1 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mhwrapper.cpp | 330 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mhwrapper.h | 50 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/smtpwrapper.cpp | 3 |
12 files changed, 467 insertions, 47 deletions
diff --git a/noncore/net/mail/accountview.cpp b/noncore/net/mail/accountview.cpp index 9f4f358..62cbf62 100644 --- a/noncore/net/mail/accountview.cpp +++ b/noncore/net/mail/accountview.cpp @@ -68,835 +68,835 @@ RecBody POP3viewItem::fetchBody( const RecMail &mail ) { qDebug( "POP3 fetchBody" ); return wrapper->fetchBody( mail ); } QPopupMenu * POP3viewItem::getContextMenu() { QPopupMenu *m = new QPopupMenu(0); if (m) { if (!account->getOffline()) { m->insertItem(QObject::tr("Disconnect",contextName),0); m->insertItem(QObject::tr("Set offline",contextName),1); } else { m->insertItem(QObject::tr("Set online",contextName),1); } } return m; } void POP3viewItem::disconnect() { QListViewItem *child = firstChild(); while ( child ) { QListViewItem *tmp = child; child = child->nextSibling(); delete tmp; } wrapper->logout(); } void POP3viewItem::setOnOffline() { if (!account->getOffline()) { disconnect(); } account->setOffline(!account->getOffline()); account->save(); SETPIX(PIXMAP_POP3FOLDER); refresh(); } void POP3viewItem::contextMenuSelected(int which) { switch (which) { case 0: disconnect(); break; case 1: setOnOffline(); break; } } POP3folderItem::~POP3folderItem() { delete folder; } POP3folderItem::POP3folderItem( Folder *folderInit, POP3viewItem *parent , QListViewItem*after ) : AccountViewItem( parent,after ) { folder = folderInit; pop3 = parent; if (folder->getDisplayName().lower()!="inbox") { setPixmap( 0, PIXMAP_POP3FOLDER ); } else { setPixmap( 0, PIXMAP_INBOXFOLDER); } setText( 0, folder->getDisplayName() ); } void POP3folderItem::refresh(QList<RecMail>&target) { if (folder->may_select()) pop3->getWrapper()->listMessages( folder->getName(),target ); } RecBody POP3folderItem::fetchBody(const RecMail&aMail) { return pop3->getWrapper()->fetchBody(aMail); } QPopupMenu * POP3folderItem::getContextMenu() { QPopupMenu *m = new QPopupMenu(0); if (m) { m->insertItem(QObject::tr("Refresh header list",contextName),0); m->insertItem(QObject::tr("Delete all mails",contextName),1); m->insertItem(QObject::tr("Move/Copie all mails",contextName),2); } return m; } void POP3folderItem::downloadMails() { AccountView*bl = pop3->accountView(); if (!bl) return; bl->downloadMails(folder,pop3->getWrapper()); } void POP3folderItem::contextMenuSelected(int which) { AccountView * view = (AccountView*)listView(); switch (which) { case 0: /* must be 'cause pop3 lists are cached */ pop3->getWrapper()->logout(); view->refreshCurrent(); break; case 1: deleteAllMail(pop3->getWrapper(),folder); break; case 2: downloadMails(); break; default: break; } } /** * IMAP Account stuff */ IMAPviewItem::IMAPviewItem( IMAPaccount *a, AccountView *parent ) : AccountViewItem( parent ) { account = a; wrapper = AbstractMail::getWrapper( account ); SETPIX(PIXMAP_IMAPFOLDER); setText( 0, account->getAccountName() ); setOpen( true ); } IMAPviewItem::~IMAPviewItem() { delete wrapper; } AbstractMail *IMAPviewItem::getWrapper() { return wrapper; } IMAPfolderItem*IMAPviewItem::findSubItem(const QString&path,IMAPfolderItem*start) { IMAPfolderItem*pitem,*sitem; if (!start) pitem = (IMAPfolderItem*)firstChild(); else pitem = (IMAPfolderItem*)start->firstChild(); while (pitem) { if (pitem->matchName(path)) { break; } if (pitem->childCount()>0) { sitem = findSubItem(path,pitem); if (sitem) { pitem = sitem; break; } } pitem=(IMAPfolderItem*)pitem->nextSibling(); } return pitem; } void IMAPviewItem::refresh(QList<RecMail>&) { refreshFolders(false); } void IMAPviewItem::removeChilds() { QListViewItem *child = firstChild(); while ( child ) { QListViewItem *tmp = child; child = child->nextSibling(); delete tmp; } } const QStringList&IMAPviewItem::subFolders() { return currentFolders; } void IMAPviewItem::refreshFolders(bool force) { if (childCount()>0 && force==false) return; if (account->getOffline()) return; removeChilds(); currentFolders.clear(); QList<Folder> *folders = wrapper->listFolders(); Folder *it; QListViewItem*item = 0; QListViewItem*titem = 0; QString fname,del,search; int pos; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! folders->setAutoDelete(false); for ( it = folders->first(); it; it = folders->next() ) { if (it->getDisplayName().lower()=="inbox") { item = new IMAPfolderItem( it, this , item ); folders->remove(it); qDebug("inbox found"); break; } } for ( it = folders->first(); it; it = folders->next() ) { fname = it->getDisplayName(); currentFolders.append(it->getName()); pos = fname.findRev(it->Separator()); if (pos != -1) { fname = fname.left(pos); } IMAPfolderItem*pitem = findSubItem(fname); if (pitem) { titem = item; item = new IMAPfolderItem(it,pitem,pitem->firstChild(),this); /* setup the short name */ item->setText(0,it->getDisplayName().right(it->getDisplayName().length()-pos-1)); item = titem; } else { item = new IMAPfolderItem( it, this , item ); } } delete folders; } QPopupMenu * IMAPviewItem::getContextMenu() { QPopupMenu *m = new QPopupMenu(0); if (m) { if (!account->getOffline()) { m->insertItem(QObject::tr("Refresh folder list",contextName),0); m->insertItem(QObject::tr("Create new folder",contextName),1); m->insertSeparator(); m->insertItem(QObject::tr("Disconnect",contextName),2); m->insertItem(QObject::tr("Set offline",contextName),3); } else { m->insertItem(QObject::tr("Set online",contextName),3); } } return m; } void IMAPviewItem::createNewFolder() { Newmdirdlg ndirdlg; ndirdlg.showMaximized(); if (ndirdlg.exec()) { QString ndir = ndirdlg.Newdir(); bool makesubs = ndirdlg.subpossible(); QString delemiter = "/"; IMAPfolderItem*item = (IMAPfolderItem*)firstChild(); if (item) { delemiter = item->Delemiter(); } if (wrapper->createMbox(ndir,0,delemiter,makesubs)) { refreshFolders(true); } } } void IMAPviewItem::contextMenuSelected(int id) { qDebug("Id selected: %i",id); switch (id) { case 0: refreshFolders(true); break; case 1: createNewFolder(); break; case 2: removeChilds(); wrapper->logout(); break; case 3: if (account->getOffline()==false) { removeChilds(); wrapper->logout(); } account->setOffline(!account->getOffline()); account->save(); SETPIX(PIXMAP_IMAPFOLDER); refreshFolders(false); break; default: break; } } RecBody IMAPviewItem::fetchBody(const RecMail&) { return RecBody(); } bool IMAPviewItem::offline() { return account->getOffline(); } IMAPfolderItem::IMAPfolderItem( Folder *folderInit, IMAPviewItem *parent , QListViewItem*after ) : AccountViewItem( parent , after ) { folder = folderInit; imap = parent; if (folder->getDisplayName().lower()!="inbox") { setPixmap( 0, PIXMAP_IMAPFOLDER ); } else { setPixmap( 0, PIXMAP_INBOXFOLDER); } setText( 0, folder->getDisplayName() ); } IMAPfolderItem::IMAPfolderItem( Folder *folderInit, IMAPfolderItem *parent , QListViewItem*after, IMAPviewItem *master ) : AccountViewItem( parent,after ) { folder = folderInit; imap = master; if (folder->getDisplayName().lower()!="inbox") { setPixmap( 0, PIXMAP_IMAPFOLDER ); } else { setPixmap( 0, PIXMAP_INBOXFOLDER); } setText( 0, folder->getDisplayName() ); } IMAPfolderItem::~IMAPfolderItem() { delete folder; } const QString& IMAPfolderItem::Delemiter()const { return folder->Separator(); } bool IMAPfolderItem::matchName(const QString&name)const { return folder->getDisplayName()==name; } void IMAPfolderItem::refresh(QList<RecMail>&target) { if (folder->may_select()) { imap->getWrapper()->listMessages( folder->getName(),target ); } else { target.clear(); } } RecBody IMAPfolderItem::fetchBody(const RecMail&aMail) { return imap->getWrapper()->fetchBody(aMail); } QPopupMenu * IMAPfolderItem::getContextMenu() { QPopupMenu *m = new QPopupMenu(0); if (m) { if (folder->may_select()) { m->insertItem(QObject::tr("Refresh header list",contextName),0); m->insertItem(QObject::tr("Move/Copie all mails",contextName),4); m->insertItem(QObject::tr("Delete all mails",contextName),1); } if (folder->no_inferior()==false) { m->insertItem(QObject::tr("Create new subfolder",contextName),2); } if (folder->getDisplayName().lower()!="inbox") { m->insertItem(QObject::tr("Delete folder",contextName),3); } } return m; } void IMAPfolderItem::createNewFolder() { Newmdirdlg ndirdlg; ndirdlg.showMaximized(); if (ndirdlg.exec()) { QString ndir = ndirdlg.Newdir(); bool makesubs = ndirdlg.subpossible(); QString delemiter = Delemiter(); if (imap->wrapper->createMbox(ndir,folder,delemiter,makesubs)) { imap->refreshFolders(true); } } } void IMAPfolderItem::deleteFolder() { int yesno = QMessageBox::warning(0,QObject::tr("Delete folder",contextName), QObject::tr("<center>Realy delete folder <br><b>%1</b><br>and all if it content?</center>",contextName).arg(folder->getDisplayName()), QObject::tr("Yes",contextName), QObject::tr("No",contextName),QString::null,1,1); qDebug("Auswahl: %i",yesno); if (yesno == 0) { if (imap->getWrapper()->deleteMbox(folder)) { QListView*v=listView(); IMAPviewItem * box = imap; /* be carefull - after that this object is destroyd so don't use * any member of it after that call!!*/ imap->refreshFolders(true); if (v) { v->setSelected(box,true); } } } } void IMAPfolderItem::downloadMails() { AccountView*bl = imap->accountView(); if (!bl) return; bl->downloadMails(folder,imap->getWrapper()); } void IMAPfolderItem::contextMenuSelected(int id) { qDebug("Selected id: %i",id); AccountView * view = (AccountView*)listView(); switch(id) { case 0: view->refreshCurrent(); break; case 1: deleteAllMail(imap->getWrapper(),folder); break; case 2: createNewFolder(); break; case 3: deleteFolder(); break; case 4: downloadMails(); break; default: break; } } /** * Generic stuff */ const QString AccountViewItem::contextName="AccountViewItem"; AccountViewItem::AccountViewItem( AccountView *parent ) : QListViewItem( parent ) { m_Backlink = parent; } AccountViewItem::AccountViewItem( QListViewItem *parent) : QListViewItem( parent) { m_Backlink = 0; } AccountViewItem::AccountViewItem( QListViewItem *parent , QListViewItem*after ) :QListViewItem( parent,after ) { m_Backlink = 0; } AccountViewItem::~AccountViewItem() { } AccountView*AccountViewItem::accountView() { return m_Backlink; } void AccountViewItem::deleteAllMail(AbstractMail*wrapper,Folder*folder) { if (!wrapper) return; QString fname=""; if (folder) fname = folder->getDisplayName(); int yesno = QMessageBox::warning(0,QObject::tr("Delete all mails",contextName), QObject::tr("<center>Realy delete all mails in box <br>%1</center>",contextName). arg(fname), QObject::tr("Yes",contextName), QObject::tr("No",contextName),QString::null,1,1); qDebug("Auswahl: %i",yesno); if (yesno == 0) { if (wrapper->deleteAllMail(folder)) { AccountView * view = (AccountView*)listView(); if (view) view->refreshCurrent(); } } } AccountView::AccountView( QWidget *parent, const char *name, WFlags flags ) : QListView( parent, name, flags ) { connect( this, SIGNAL( selectionChanged( QListViewItem * ) ), SLOT( refresh( QListViewItem * ) ) ); connect( this, SIGNAL( mouseButtonPressed(int, QListViewItem *,const QPoint&,int ) ),this, SLOT( slotHold( int, QListViewItem *,const QPoint&,int ) ) ); setSorting(0); } AccountView::~AccountView() { imapAccounts.clear(); - mboxAccounts.clear(); + mhAccounts.clear(); } void AccountView::slotContextMenu(int id) { AccountViewItem *view = static_cast<AccountViewItem *>(currentItem()); if (!view) return; view->contextMenuSelected(id); } void AccountView::slotHold(int button, QListViewItem * item,const QPoint&,int) { if (button==1) {return;} if (!item) return; AccountViewItem *view = static_cast<AccountViewItem *>(item); QPopupMenu*m = view->getContextMenu(); if (!m) return; connect(m,SIGNAL(activated(int)),this,SLOT(slotContextMenu(int))); m->setFocus(); m->exec( QPoint( QCursor::pos().x(), QCursor::pos().y()) ); delete m; } void AccountView::populate( QList<Account> list ) { clear(); imapAccounts.clear(); - mboxAccounts.clear(); + mhAccounts.clear(); - mboxAccounts.append(new MBOXviewItem(AbstractMail::defaultLocalfolder(),this)); + mhAccounts.append(new MHviewItem(AbstractMail::defaultLocalfolder(),this)); Account *it; for ( it = list.first(); it; it = list.next() ) { if ( it->getType().compare( "IMAP" ) == 0 ) { IMAPaccount *imap = static_cast<IMAPaccount *>(it); qDebug( "added IMAP " + imap->getAccountName() ); imapAccounts.append(new IMAPviewItem( imap, this )); } else if ( it->getType().compare( "POP3" ) == 0 ) { POP3account *pop3 = static_cast<POP3account *>(it); qDebug( "added POP3 " + pop3->getAccountName() ); /* must not be hold 'cause it isn't required */ (void) new POP3viewItem( pop3, this ); } } } void AccountView::refresh(QListViewItem *item) { qDebug("AccountView refresh..."); if ( item ) { m_currentItem = item; QList<RecMail> headerlist; headerlist.setAutoDelete(true); AccountViewItem *view = static_cast<AccountViewItem *>(item); view->refresh(headerlist); emit refreshMailview(&headerlist); } } void AccountView::refreshCurrent() { m_currentItem = currentItem(); if ( !m_currentItem ) return; QList<RecMail> headerlist; headerlist.setAutoDelete(true); AccountViewItem *view = static_cast<AccountViewItem *>(m_currentItem); view->refresh(headerlist); emit refreshMailview(&headerlist); } void AccountView::refreshAll() { } RecBody AccountView::fetchBody(const RecMail&aMail) { QListViewItem*item = selectedItem (); if (!item) return RecBody(); AccountViewItem *view = static_cast<AccountViewItem *>(item); return view->fetchBody(aMail); } void AccountView::setupFolderselect(Selectstore*sels) { sels->showMaximized(); QStringList sFolders; unsigned int i = 0; - for (i=0; i < mboxAccounts.count();++i) { - mboxAccounts[i]->refresh(false); - sFolders = mboxAccounts[i]->subFolders(); - sels->addAccounts(mboxAccounts[i]->getWrapper(),sFolders); + for (i=0; i < mhAccounts.count();++i) { + mhAccounts[i]->refresh(false); + sFolders = mhAccounts[i]->subFolders(); + sels->addAccounts(mhAccounts[i]->getWrapper(),sFolders); } for (i=0; i < imapAccounts.count();++i) { if (imapAccounts[i]->offline()) continue; imapAccounts[i]->refreshFolders(false); sels->addAccounts(imapAccounts[i]->getWrapper(),imapAccounts[i]->subFolders()); } } void AccountView::downloadMails(Folder*fromFolder,AbstractMail*fromWrapper) { AbstractMail*targetMail = 0; QString targetFolder = ""; Selectstore sels; setupFolderselect(&sels); if (!sels.exec()) return; targetMail = sels.currentMail(); targetFolder = sels.currentFolder(); if ( (fromWrapper==targetMail && fromFolder->getName()==targetFolder) || targetFolder.isEmpty()) { return; } if (sels.newFolder() && !targetMail->createMbox(targetFolder)) { QMessageBox::critical(0,tr("Error creating new Folder"), tr("<center>Error while creating<br>new folder - breaking.</center>")); return; } qDebug("Targetfolder: %s",targetFolder.latin1()); qDebug("Fromfolder: %s",fromFolder->getName().latin1()); fromWrapper->mvcpAllMails(fromFolder,targetFolder,targetMail,sels.moveMails()); refreshCurrent(); } /** - * MBOX Account stuff + * MH Account stuff */ -MBOXviewItem::MBOXviewItem( const QString&aPath, AccountView *parent ) +MHviewItem::MHviewItem( const QString&aPath, AccountView *parent ) : AccountViewItem( parent ) { m_Path = aPath; /* be carefull - the space within settext is wanted - thats why the string twice */ wrapper = AbstractMail::getWrapper( m_Path,"Local Folders"); setPixmap( 0, PIXMAP_LOCALFOLDER ); setText( 0, " Local Folders" ); setOpen( true ); } -MBOXviewItem::~MBOXviewItem() +MHviewItem::~MHviewItem() { delete wrapper; } -AbstractMail *MBOXviewItem::getWrapper() +AbstractMail *MHviewItem::getWrapper() { return wrapper; } -void MBOXviewItem::refresh( QList<RecMail> & ) +void MHviewItem::refresh( QList<RecMail> & ) { refresh(false); } -void MBOXviewItem::refresh(bool force) +void MHviewItem::refresh(bool force) { if (childCount()>0 && force==false) return; QList<Folder> *folders = wrapper->listFolders(); QListViewItem *child = firstChild(); while ( child ) { QListViewItem *tmp = child; child = child->nextSibling(); delete tmp; } Folder *it; QListViewItem*item = 0; for ( it = folders->first(); it; it = folders->next() ) { - item = new MBOXfolderItem( it, this , item ); + item = new MHfolderItem( it, this , item ); item->setSelectable(it->may_select()); } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! folders->setAutoDelete(false); delete folders; } -RecBody MBOXviewItem::fetchBody( const RecMail &mail ) +RecBody MHviewItem::fetchBody( const RecMail &mail ) { - qDebug( "MBOX fetchBody" ); + qDebug( "MH fetchBody" ); return wrapper->fetchBody( mail ); } -QPopupMenu * MBOXviewItem::getContextMenu() +QPopupMenu * MHviewItem::getContextMenu() { QPopupMenu *m = new QPopupMenu(0); if (m) { m->insertItem(QObject::tr("Refresh folder list",contextName),0); m->insertItem(QObject::tr("Create new folder",contextName),1); } return m; } -void MBOXviewItem::createFolder() +void MHviewItem::createFolder() { Newmdirdlg ndirdlg(0,0,true); ndirdlg.showMaximized(); if (ndirdlg.exec()) { QString ndir = ndirdlg.Newdir(); if (wrapper->createMbox(ndir)) { refresh(true); } } } -QStringList MBOXviewItem::subFolders() +QStringList MHviewItem::subFolders() { QStringList result; QListViewItem *child = firstChild(); while ( child ) { - MBOXfolderItem *tmp = (MBOXfolderItem*)child; + MHfolderItem *tmp = (MHfolderItem*)child; child = child->nextSibling(); - result.append(tmp->getFolder()->getName()); + result.append(tmp->getFolder()->getDisplayName()); } qDebug("Size of result: %i",result.count()); return result; } -void MBOXviewItem::contextMenuSelected(int which) +void MHviewItem::contextMenuSelected(int which) { switch (which) { case 0: refresh(true); break; case 1: createFolder(); break; default: break; } } -MBOXfolderItem::~MBOXfolderItem() +MHfolderItem::~MHfolderItem() { delete folder; } -MBOXfolderItem::MBOXfolderItem( Folder *folderInit, MBOXviewItem *parent , QListViewItem*after ) +MHfolderItem::MHfolderItem( Folder *folderInit, MHviewItem *parent , QListViewItem*after ) : AccountViewItem( parent,after ) { folder = folderInit; mbox = parent; if (folder->getDisplayName().lower() == "outgoing") { setPixmap( 0, PIXMAP_OUTBOXFOLDER ); } else if (folder->getDisplayName().lower() == "inbox") { setPixmap( 0, PIXMAP_INBOXFOLDER); } else { setPixmap( 0, PIXMAP_MBOXFOLDER ); } setText( 0, folder->getDisplayName() ); } -Folder*MBOXfolderItem::getFolder() +Folder*MHfolderItem::getFolder() { return folder; } -void MBOXfolderItem::refresh(QList<RecMail>&target) +void MHfolderItem::refresh(QList<RecMail>&target) { if (folder->may_select()) mbox->getWrapper()->listMessages( folder->getName(),target ); } -RecBody MBOXfolderItem::fetchBody(const RecMail&aMail) +RecBody MHfolderItem::fetchBody(const RecMail&aMail) { return mbox->getWrapper()->fetchBody(aMail); } -void MBOXfolderItem::deleteFolder() +void MHfolderItem::deleteFolder() { int yesno = QMessageBox::warning(0,QObject::tr("Delete folder",contextName), QObject::tr("<center>Realy delete folder <br><b>%1</b><br>and all if it content?</center>",contextName).arg(folder->getDisplayName()), QObject::tr("Yes",contextName), QObject::tr("No",contextName),QString::null,1,1); qDebug("Auswahl: %i",yesno); if (yesno == 0) { if (mbox->getWrapper()->deleteMbox(folder)) { QListView*v=listView(); - MBOXviewItem * box = mbox; + MHviewItem * box = mbox; /* be carefull - after that this object is destroyd so don't use * any member of it after that call!!*/ mbox->refresh(true); if (v) { v->setSelected(box,true); } } } } -QPopupMenu * MBOXfolderItem::getContextMenu() +QPopupMenu * MHfolderItem::getContextMenu() { QPopupMenu *m = new QPopupMenu(0); if (m) { m->insertItem(QObject::tr("Delete all mails",contextName),0); m->insertItem(QObject::tr("Delete folder",contextName),1); m->insertItem(QObject::tr("Move/Copie all mails",contextName),2); } return m; } -void MBOXfolderItem::downloadMails() +void MHfolderItem::downloadMails() { AccountView*bl = mbox->accountView(); if (!bl) return; bl->downloadMails(folder,mbox->getWrapper()); } -void MBOXfolderItem::contextMenuSelected(int which) +void MHfolderItem::contextMenuSelected(int which) { switch(which) { case 0: deleteAllMail(mbox->getWrapper(),folder); break; case 1: deleteFolder(); break; case 2: downloadMails(); break; default: break; } } diff --git a/noncore/net/mail/accountview.h b/noncore/net/mail/accountview.h index d9b5558..f5a2973 100644 --- a/noncore/net/mail/accountview.h +++ b/noncore/net/mail/accountview.h @@ -1,190 +1,190 @@ #ifndef ACCOUNTVIEW_H #define ACCOUNTVIEW_H #include <qlistview.h> #include <qlist.h> #include <libmailwrapper/settings.h> #include <libmailwrapper/mailwrapper.h> #include <libmailwrapper/abstractmail.h> class POP3wrapper; class RecMail; class RecBody; class QPopupMenu; class Selectstore; class AccountView; class AccountViewItem : public QListViewItem { public: AccountViewItem( AccountView *parent ); AccountViewItem( QListViewItem *parent); AccountViewItem( QListViewItem *parent , QListViewItem*after ); virtual ~AccountViewItem(); virtual void refresh(QList<RecMail>&)=0; virtual RecBody fetchBody(const RecMail&)=0; virtual QPopupMenu * getContextMenu(){return 0;}; virtual void contextMenuSelected(int){} virtual AccountView*accountView(); protected: virtual void deleteAllMail(AbstractMail*wrapper,Folder*f); static const QString contextName; AccountView*m_Backlink; }; class POP3viewItem : public AccountViewItem { public: POP3viewItem( POP3account *a, AccountView *parent ); virtual ~POP3viewItem(); virtual void refresh( QList<RecMail> &target ); virtual RecBody fetchBody( const RecMail &mail ); AbstractMail *getWrapper(); virtual QPopupMenu * getContextMenu(); virtual void contextMenuSelected(int); protected: POP3account *account; virtual void refresh(); AbstractMail *wrapper; void disconnect(); void setOnOffline(); }; class POP3folderItem : public AccountViewItem { public: POP3folderItem( Folder *folder, POP3viewItem *parent , QListViewItem*after ); virtual ~POP3folderItem(); virtual void refresh(QList<RecMail>&); virtual RecBody fetchBody(const RecMail&); virtual QPopupMenu * getContextMenu(); virtual void contextMenuSelected(int); protected: void downloadMails(); Folder *folder; POP3viewItem *pop3; }; class IMAPfolderItem; class IMAPviewItem : public AccountViewItem { friend class IMAPfolderItem; public: IMAPviewItem( IMAPaccount *a, AccountView *parent ); virtual ~IMAPviewItem(); virtual void refresh(QList<RecMail>&); virtual RecBody fetchBody(const RecMail&); AbstractMail *getWrapper(); virtual QPopupMenu * getContextMenu(); virtual void contextMenuSelected(int); const QStringList&subFolders(); virtual void refreshFolders(bool force=false); bool offline(); protected: IMAPfolderItem*findSubItem(const QString&path,IMAPfolderItem*start=0); virtual void createNewFolder(); virtual void removeChilds(); IMAPaccount *account; AbstractMail *wrapper; QStringList currentFolders; }; class IMAPfolderItem : public AccountViewItem { public: IMAPfolderItem( Folder *folder, IMAPviewItem *parent , QListViewItem*after ); IMAPfolderItem( Folder *folder, IMAPfolderItem *parent , QListViewItem*after, IMAPviewItem *master ); virtual ~IMAPfolderItem(); virtual void refresh(QList<RecMail>&); virtual RecBody fetchBody(const RecMail&); bool matchName(const QString&name)const; virtual QPopupMenu * getContextMenu(); virtual void contextMenuSelected(int); virtual const QString& Delemiter()const; protected: virtual void createNewFolder(); virtual void deleteFolder(); virtual void downloadMails(); Folder *folder; IMAPviewItem *imap; }; -class MBOXviewItem : public AccountViewItem +class MHviewItem : public AccountViewItem { - friend class MBOXfolderItem; + friend class MHfolderItem; public: - MBOXviewItem( const QString&aMboxPath, AccountView *parent ); - virtual ~MBOXviewItem(); + MHviewItem( const QString&aMboxPath, AccountView *parent ); + virtual ~MHviewItem(); virtual void refresh( QList<RecMail> &target ); virtual RecBody fetchBody( const RecMail &mail ); AbstractMail *getWrapper(); virtual QPopupMenu * getContextMenu(); virtual void contextMenuSelected(int); QStringList subFolders(); virtual void refresh(bool force=false); protected: virtual void createFolder(); QString m_Path; AbstractMail *wrapper; }; -class MBOXfolderItem : public AccountViewItem +class MHfolderItem : public AccountViewItem { public: - MBOXfolderItem( Folder *folder, MBOXviewItem *parent , QListViewItem*after ); - virtual ~MBOXfolderItem(); + MHfolderItem( Folder *folder, MHviewItem *parent , QListViewItem*after ); + virtual ~MHfolderItem(); virtual void refresh(QList<RecMail>&); virtual RecBody fetchBody(const RecMail&); virtual QPopupMenu * getContextMenu(); virtual void contextMenuSelected(int); virtual Folder*getFolder(); protected: void downloadMails(); virtual void deleteFolder(); Folder *folder; - MBOXviewItem *mbox; + MHviewItem *mbox; }; class AccountView : public QListView { Q_OBJECT public: AccountView( QWidget *parent = 0, const char *name = 0, WFlags flags = 0 ); virtual ~AccountView(); virtual void populate( QList<Account> list ); virtual RecBody fetchBody(const RecMail&aMail); virtual void downloadMails(Folder*fromFolder,AbstractMail*fromWrapper); public slots: virtual void refreshAll(); virtual void refresh(QListViewItem *item); virtual void refreshCurrent(); virtual void slotHold(int, QListViewItem *,const QPoint&,int); virtual void slotContextMenu(int id); void setupFolderselect(Selectstore*sels); signals: void refreshMailview(QList<RecMail>*); protected: QListViewItem* m_currentItem; QValueList<IMAPviewItem*> imapAccounts; - QValueList<MBOXviewItem*> mboxAccounts; + QValueList<MHviewItem*> mhAccounts; }; #endif diff --git a/noncore/net/mail/libmailwrapper/abstractmail.cpp b/noncore/net/mail/libmailwrapper/abstractmail.cpp index 0280803..592cd5e 100644 --- a/noncore/net/mail/libmailwrapper/abstractmail.cpp +++ b/noncore/net/mail/libmailwrapper/abstractmail.cpp @@ -1,138 +1,139 @@ #include "abstractmail.h" #include "imapwrapper.h" #include "pop3wrapper.h" +#include "mhwrapper.h" #include "mboxwrapper.h" #include "mailtypes.h" #include <qstring.h> #include <qfile.h> #include <qtextstream.h> #include <stdlib.h> #include <libetpan/mailmime_content.h> #include <libetpan/mailmime.h> AbstractMail* AbstractMail::getWrapper(IMAPaccount *a) { return new IMAPwrapper(a); } AbstractMail* AbstractMail::getWrapper(POP3account *a) { return new POP3wrapper(a); } AbstractMail* AbstractMail::getWrapper(const QString&a,const QString&name) { - return new MBOXwrapper(a,name); + return new MHwrapper(a,name); } encodedString* AbstractMail::decode_String(const encodedString*text,const QString&enc) { qDebug("Decode string start"); char*result_text; size_t index = 0; /* reset for recursive use! */ size_t target_length = 0; result_text = 0; int mimetype = MAILMIME_MECHANISM_7BIT; if (enc.lower()=="quoted-printable") { mimetype = MAILMIME_MECHANISM_QUOTED_PRINTABLE; } else if (enc.lower()=="base64") { mimetype = MAILMIME_MECHANISM_BASE64; } else if (enc.lower()=="8bit") { mimetype = MAILMIME_MECHANISM_8BIT; } else if (enc.lower()=="binary") { mimetype = MAILMIME_MECHANISM_BINARY; } int err = mailmime_part_parse(text->Content(),text->Length(),&index,mimetype, &result_text,&target_length); encodedString* result = new encodedString(); if (err == MAILIMF_NO_ERROR) { result->setContent(result_text,target_length); } qDebug("Decode string finished"); return result; } QString AbstractMail::convert_String(const char*text) { size_t index = 0; char*res = 0; /* attention - doesn't work with arm systems! */ int err = mailmime_encoded_phrase_parse("iso-8859-1", text, strlen(text),&index, "iso-8859-1",&res); if (err != MAILIMF_NO_ERROR) { if (res) free(res); return QString(text); } if (res) { QString result(res); free(res); return result; } return QString(text); } /* cp & paste from launcher */ QString AbstractMail::gen_attachment_id() { QFile file( "/proc/sys/kernel/random/uuid" ); if (!file.open(IO_ReadOnly ) ) return QString::null; QTextStream stream(&file); return "{" + stream.read().stripWhiteSpace() + "}"; } int AbstractMail::createMbox(const QString&,const Folder*,const QString& delemiter,bool) { return 0; } QString AbstractMail::defaultLocalfolder() { QString f = getenv( "HOME" ); f += "/Applications/opiemail/localmail"; return f; } /* temporary - will be removed when implemented in all classes */ void AbstractMail::deleteMails(const QString &,QList<RecMail> &) { } void AbstractMail::mvcpAllMails(Folder*fromFolder,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit) { QList<RecMail> t; listMessages(fromFolder->getName(),t); encodedString*st = 0; while (t.count()>0) { RecMail*r = t.at(0); st = fetchRawBody(*r); if (st) { targetWrapper->storeMessage(st->Content(),st->Length(),targetFolder); delete st; } t.removeFirst(); } if (moveit) { deleteAllMail(fromFolder); } } void AbstractMail::mvcpMail(const RecMail&mail,const QString&targetFolder,AbstractMail*targetWrapper,bool moveit) { encodedString*st = 0; st = fetchRawBody(mail); if (st) { targetWrapper->storeMessage(st->Content(),st->Length(),targetFolder); delete st; } if (moveit) { deleteMail(mail); } } diff --git a/noncore/net/mail/libmailwrapper/genericwrapper.cpp b/noncore/net/mail/libmailwrapper/genericwrapper.cpp index 2d1596d..b1e4459 100644 --- a/noncore/net/mail/libmailwrapper/genericwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/genericwrapper.cpp @@ -1,504 +1,512 @@ #include "genericwrapper.h" #include <libetpan/libetpan.h> #include "mailtypes.h" Genericwrapper::Genericwrapper() : AbstractMail() { bodyCache.clear(); + m_storage = 0; + m_folder = 0; } Genericwrapper::~Genericwrapper() { + if (m_folder) { + mailfolder_free(m_folder); + } + if (m_storage) { + mailstorage_free(m_storage); + } cleanMimeCache(); } void Genericwrapper::fillSingleBody(RecPart&target,mailmessage*,mailmime*mime) { if (!mime) { return; } mailmime_field*field = 0; mailmime_single_fields fields; memset(&fields, 0, sizeof(struct mailmime_single_fields)); if (mime->mm_mime_fields != NULL) { mailmime_single_fields_init(&fields, mime->mm_mime_fields, mime->mm_content_type); } mailmime_content*type = fields.fld_content; clistcell*current; if (!type) { target.setType("text"); target.setSubtype("plain"); } else { target.setSubtype(type->ct_subtype); switch(type->ct_type->tp_data.tp_discrete_type->dt_type) { case MAILMIME_DISCRETE_TYPE_TEXT: target.setType("text"); break; case MAILMIME_DISCRETE_TYPE_IMAGE: target.setType("image"); break; case MAILMIME_DISCRETE_TYPE_AUDIO: target.setType("audio"); break; case MAILMIME_DISCRETE_TYPE_VIDEO: target.setType("video"); break; case MAILMIME_DISCRETE_TYPE_APPLICATION: target.setType("application"); break; case MAILMIME_DISCRETE_TYPE_EXTENSION: default: if (type->ct_type->tp_data.tp_discrete_type->dt_extension) { target.setType(type->ct_type->tp_data.tp_discrete_type->dt_extension); } break; } if (type->ct_parameters) { fillParameters(target,type->ct_parameters); } } if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list) { for (current=clist_begin(mime->mm_mime_fields->fld_list);current!=0;current=clist_next(current)) { field = (mailmime_field*)current->data; switch(field->fld_type) { case MAILMIME_FIELD_TRANSFER_ENCODING: target.setEncoding(getencoding(field->fld_data.fld_encoding)); break; case MAILMIME_FIELD_ID: target.setIdentifier(field->fld_data.fld_id); break; case MAILMIME_FIELD_DESCRIPTION: target.setDescription(field->fld_data.fld_description); break; default: break; } } } } void Genericwrapper::fillParameters(RecPart&target,clist*parameters) { if (!parameters) {return;} clistcell*current=0; mailmime_parameter*param; for (current=clist_begin(parameters);current!=0;current=clist_next(current)) { param = (mailmime_parameter*)current->data; if (param) { target.addParameter(QString(param->pa_name).lower(),QString(param->pa_value)); } } } QString Genericwrapper::getencoding(mailmime_mechanism*aEnc) { QString enc="7bit"; if (!aEnc) return enc; switch(aEnc->enc_type) { case MAILMIME_MECHANISM_7BIT: enc = "7bit"; break; case MAILMIME_MECHANISM_8BIT: enc = "8bit"; break; case MAILMIME_MECHANISM_BINARY: enc = "binary"; break; case MAILMIME_MECHANISM_QUOTED_PRINTABLE: enc = "quoted-printable"; break; case MAILMIME_MECHANISM_BASE64: enc = "base64"; break; case MAILMIME_MECHANISM_TOKEN: default: if (aEnc->enc_token) { enc = QString(aEnc->enc_token); } break; } return enc; } void Genericwrapper::traverseBody(RecBody&target,mailmessage*message,mailmime*mime,QValueList<int>recList,unsigned int current_rec,int current_count) { if (current_rec >= 10) { qDebug("too deep recursion!"); } if (!message || !mime) { return; } int r; char*data = 0; size_t len; clistiter * cur = 0; QString b; RecPart part; switch (mime->mm_type) { case MAILMIME_SINGLE: { QValueList<int>countlist = recList; countlist.append(current_count); r = mailmessage_fetch_section(message,mime,&data,&len); part.setSize(len); part.setPositionlist(countlist); b = gen_attachment_id(); part.setIdentifier(b); fillSingleBody(part,message,mime); if (part.Type()=="text" && target.Bodytext().isNull()) { encodedString*r = new encodedString(); r->setContent(data,len); encodedString*res = decode_String(r,part.Encoding()); if (countlist.count()>2) { bodyCache[b]=r; target.addPart(part); } else { delete r; } b = QString(res->Content()); delete res; target.setBodytext(b); target.setDescription(part); } else { bodyCache[b]=new encodedString(data,len); target.addPart(part); } } break; case MAILMIME_MULTIPLE: { unsigned int ccount = 1; mailmime*cbody=0; QValueList<int>countlist = recList; for (cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; cur = clist_next(cur)) { cbody = (mailmime*)clist_content(cur); if (cbody->mm_type==MAILMIME_MULTIPLE) { RecPart targetPart; targetPart.setType("multipart"); countlist.append(current_count); targetPart.setPositionlist(countlist); target.addPart(targetPart); } traverseBody(target,message, cbody,countlist,current_rec+1,ccount); if (cbody->mm_type==MAILMIME_MULTIPLE) { countlist = recList; } ++ccount; } } break; case MAILMIME_MESSAGE: { QValueList<int>countlist = recList; countlist.append(current_count); /* the own header is always at recursion 0 - we don't need that */ if (current_rec > 0) { part.setPositionlist(countlist); r = mailmessage_fetch_section(message,mime,&data,&len); part.setSize(len); part.setPositionlist(countlist); b = gen_attachment_id(); part.setIdentifier(b); part.setType("message"); part.setSubtype("rfc822"); bodyCache[b]=new encodedString(data,len); target.addPart(part); } if (mime->mm_data.mm_message.mm_msg_mime != NULL) { traverseBody(target,message,mime->mm_data.mm_message.mm_msg_mime,countlist,current_rec+1); } } break; } } RecBody Genericwrapper::parseMail( mailmessage * msg ) { int err = MAILIMF_NO_ERROR; mailmime_single_fields fields; /* is bound to msg and will be freed there */ mailmime * mime=0; RecBody body; memset(&fields, 0, sizeof(struct mailmime_single_fields)); err = mailmessage_get_bodystructure(msg,&mime); QValueList<int>recList; traverseBody(body,msg,mime,recList); return body; } RecMail *Genericwrapper::parseHeader( const char *header ) { int err = MAILIMF_NO_ERROR; size_t curTok = 0; RecMail *mail = new RecMail(); mailimf_fields *fields = 0; mailimf_references * refs = 0; mailimf_keywords*keys = 0; QString status; QString value; QBitArray mFlags(7); err = mailimf_fields_parse( (char *) header, strlen( header ), &curTok, &fields ); for ( clistiter *current = clist_begin( fields->fld_list ); current != NULL; current = current->next ) { mailimf_field *field = (mailimf_field *) current->data; switch ( field->fld_type ) { case MAILIMF_FIELD_FROM: mail->setFrom( parseMailboxList( field->fld_data.fld_from->frm_mb_list ) ); break; case MAILIMF_FIELD_TO: mail->setTo( parseAddressList( field->fld_data.fld_to->to_addr_list ) ); break; case MAILIMF_FIELD_CC: mail->setCC( parseAddressList( field->fld_data.fld_cc->cc_addr_list ) ); break; case MAILIMF_FIELD_BCC: mail->setBcc( parseAddressList( field->fld_data.fld_bcc->bcc_addr_list ) ); break; case MAILIMF_FIELD_SUBJECT: mail->setSubject(convert_String( field->fld_data.fld_subject->sbj_value ) ); break; case MAILIMF_FIELD_ORIG_DATE: mail->setDate( parseDateTime( field->fld_data.fld_orig_date->dt_date_time ) ); break; case MAILIMF_FIELD_MESSAGE_ID: mail->setMsgid(QString(field->fld_data.fld_message_id->mid_value)); break; case MAILIMF_FIELD_REFERENCES: refs = field->fld_data.fld_references; if (refs && refs->mid_list && clist_count(refs->mid_list)) { char * text = (char*)refs->mid_list->first->data; mail->setReplyto(QString(text)); } break; case MAILIMF_FIELD_KEYWORDS: keys = field->fld_data.fld_keywords; for (clistcell*cur = clist_begin(keys->kw_list);cur!=0;cur=clist_next(cur)) { qDebug("Keyword: %s",(char*)cur->data); } break; case MAILIMF_FIELD_OPTIONAL_FIELD: status = field->fld_data.fld_optional_field->fld_name; value = field->fld_data.fld_optional_field->fld_value; if (status.lower()=="status") { if (value.lower()=="ro") { mFlags.setBit(FLAG_SEEN); } } else if (status.lower()=="x-status") { qDebug("X-Status: %s",value.latin1()); if (value.lower()=="a") { mFlags.setBit(FLAG_ANSWERED); } } else { // qDebug("Optionales feld: %s -> %s)",field->fld_data.fld_optional_field->fld_name, // field->fld_data.fld_optional_field->fld_value); } break; default: qDebug("Non parsed field"); break; } } if (fields) mailimf_fields_free(fields); mail->setFlags(mFlags); return mail; } QString Genericwrapper::parseDateTime( mailimf_date_time *date ) { char tmp[23]; snprintf( tmp, 23, "%02i.%02i.%04i %02i:%02i:%02i %+05i", date->dt_day, date->dt_month, date->dt_year, date->dt_hour, date->dt_min, date->dt_sec, date->dt_zone ); return QString( tmp ); } QString Genericwrapper::parseAddressList( mailimf_address_list *list ) { QString result( "" ); bool first = true; if (list == 0) return result; for ( clistiter *current = clist_begin( list->ad_list ); current != NULL; current = current->next ) { mailimf_address *addr = (mailimf_address *) current->data; if ( !first ) { result.append( "," ); } else { first = false; } switch ( addr->ad_type ) { case MAILIMF_ADDRESS_MAILBOX: result.append( parseMailbox( addr->ad_data.ad_mailbox ) ); break; case MAILIMF_ADDRESS_GROUP: result.append( parseGroup( addr->ad_data.ad_group ) ); break; default: qDebug( "Generic: unkown mailimf address type" ); break; } } return result; } QString Genericwrapper::parseGroup( mailimf_group *group ) { QString result( "" ); result.append( group->grp_display_name ); result.append( ": " ); if ( group->grp_mb_list != NULL ) { result.append( parseMailboxList( group->grp_mb_list ) ); } result.append( ";" ); return result; } QString Genericwrapper::parseMailbox( mailimf_mailbox *box ) { QString result( "" ); if ( box->mb_display_name == NULL ) { result.append( box->mb_addr_spec ); } else { result.append( convert_String(box->mb_display_name).latin1() ); result.append( " <" ); result.append( box->mb_addr_spec ); result.append( ">" ); } return result; } QString Genericwrapper::parseMailboxList( mailimf_mailbox_list *list ) { QString result( "" ); bool first = true; for ( clistiter *current = clist_begin( list->mb_list ); current != NULL; current = current->next ) { mailimf_mailbox *box = (mailimf_mailbox *) current->data; if ( !first ) { result.append( "," ); } else { first = false; } result.append( parseMailbox( box ) ); } return result; } encodedString* Genericwrapper::fetchDecodedPart(const RecMail&,const RecPart&part) { QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part.Identifier()); if (it==bodyCache.end()) return new encodedString(); encodedString*t = decode_String(it.data(),part.Encoding()); return t; } encodedString* Genericwrapper::fetchRawPart(const RecMail&mail,const RecPart&part) { QMap<QString,encodedString*>::ConstIterator it = bodyCache.find(part.Identifier()); if (it==bodyCache.end()) return new encodedString(); encodedString*t = it.data(); return t; } QString Genericwrapper::fetchTextPart(const RecMail&mail,const RecPart&part) { encodedString*t = fetchDecodedPart(mail,part); QString text=t->Content(); delete t; return text; } void Genericwrapper::cleanMimeCache() { QMap<QString,encodedString*>::Iterator it = bodyCache.begin(); for (;it!=bodyCache.end();++it) { encodedString*t = it.data(); //it.setValue(0); if (t) delete t; } bodyCache.clear(); qDebug("Genericwrapper: cache cleaned"); } void Genericwrapper::parseList(QList<RecMail> &target,mailsession*session,const QString&mailbox) { int r; mailmessage_list * env_list = 0; r = mailsession_get_messages_list(session,&env_list); if (r != MAIL_NO_ERROR) { qDebug("Error message list"); return; } r = mailsession_get_envelopes_list(session, env_list); if (r != MAIL_NO_ERROR) { qDebug("Error filling message list"); if (env_list) { mailmessage_list_free(env_list); } return; } mailimf_references * refs; uint32_t i = 0; for(; i < carray_count(env_list->msg_tab) ; ++i) { mailmessage * msg; QBitArray mFlags(7); msg = (mailmessage*)carray_get(env_list->msg_tab, i); if (msg->msg_fields == NULL) { qDebug("could not fetch envelope of message %i", i); continue; } RecMail * mail = new RecMail(); mail->setWrapper(this); mail_flags * flag_result = 0; r = mailmessage_get_flags(msg,&flag_result); if (r == MAIL_ERROR_NOT_IMPLEMENTED) { mFlags.setBit(FLAG_SEEN); } mailimf_single_fields single_fields; mailimf_single_fields_init(&single_fields, msg->msg_fields); mail->setMsgsize(msg->msg_size); mail->setFlags(mFlags); mail->setMbox(mailbox); mail->setNumber(msg->msg_index); if (single_fields.fld_subject) mail->setSubject( convert_String(single_fields.fld_subject->sbj_value)); if (single_fields.fld_from) mail->setFrom(parseMailboxList(single_fields.fld_from->frm_mb_list)); if (single_fields.fld_to) mail->setTo( parseAddressList( single_fields.fld_to->to_addr_list ) ); if (single_fields.fld_cc) mail->setCC( parseAddressList( single_fields.fld_cc->cc_addr_list ) ); if (single_fields.fld_bcc) mail->setBcc( parseAddressList( single_fields.fld_bcc->bcc_addr_list ) ); if (single_fields.fld_orig_date) mail->setDate( parseDateTime( single_fields.fld_orig_date->dt_date_time ) ); // crashes when accessing pop3 account // if (single_fields.fld_message_id->mid_value) // mail->setMsgid(QString(single_fields.fld_message_id->mid_value)); refs = single_fields.fld_references; if (refs && refs->mid_list && clist_count(refs->mid_list)) { char * text = (char*)refs->mid_list->first->data; mail->setReplyto(QString(text)); } target.append(mail); } if (env_list) { mailmessage_list_free(env_list); } } diff --git a/noncore/net/mail/libmailwrapper/genericwrapper.h b/noncore/net/mail/libmailwrapper/genericwrapper.h index 1d65c0a..e471dc8 100644 --- a/noncore/net/mail/libmailwrapper/genericwrapper.h +++ b/noncore/net/mail/libmailwrapper/genericwrapper.h @@ -1,62 +1,66 @@ #ifndef __GENERIC_WRAPPER_H #define __GENERIC_WRAPPER_H #include "abstractmail.h" #include <qmap.h> #include <qstring.h> #include <libetpan/clist.h> class RecMail; class RecBody; class encodedString; struct mailpop3; struct mailmessage; struct mailmime; struct mailmime_mechanism; struct mailimf_mailbox_list; struct mailimf_mailbox; struct mailimf_date_time; struct mailimf_group; struct mailimf_address_list; struct mailsession; +struct mailstorage; +struct mailfolder; /* this class hold just the funs shared between * mbox and pop3 (later mh, too) mail access. * it is not desigend to make a instance of it! */ class Genericwrapper : public AbstractMail { Q_OBJECT public: Genericwrapper(); virtual ~Genericwrapper(); virtual encodedString* fetchDecodedPart(const RecMail&mail,const RecPart&part); virtual encodedString* fetchRawPart(const RecMail&mail,const RecPart&part); virtual QString fetchTextPart(const RecMail&mail,const RecPart&part); virtual void cleanMimeCache(); virtual int deleteMbox(const Folder*){return 1;} virtual void logout(){}; virtual void storeMessage(const char*msg,size_t length, const QString&folder){}; protected: RecMail *parseHeader( const char *header ); RecBody parseMail( mailmessage * msg ); QString parseMailboxList( mailimf_mailbox_list *list ); QString parseMailbox( mailimf_mailbox *box ); QString parseGroup( mailimf_group *group ); QString parseAddressList( mailimf_address_list *list ); QString parseDateTime( mailimf_date_time *date ); void traverseBody(RecBody&target,mailmessage*message,mailmime*mime,QValueList<int>recList,unsigned int current_rek=0,int current_count=1); static void fillSingleBody(RecPart&target,mailmessage*message,mailmime*mime); static void fillParameters(RecPart&target,clist*parameters); static QString getencoding(mailmime_mechanism*aEnc); virtual void parseList(QList<RecMail> &target,mailsession*session,const QString&mailbox); QString msgTempName; unsigned int last_msg_id; QMap<QString,encodedString*> bodyCache; + mailstorage * m_storage; + mailfolder*m_folder; }; #endif diff --git a/noncore/net/mail/libmailwrapper/libmailwrapper.pro b/noncore/net/mail/libmailwrapper/libmailwrapper.pro index 18583bb..71f6cca 100644 --- a/noncore/net/mail/libmailwrapper/libmailwrapper.pro +++ b/noncore/net/mail/libmailwrapper/libmailwrapper.pro @@ -1,46 +1,48 @@ TEMPLATE = lib CONFIG += qt warn_on debug HEADERS = mailwrapper.h \ imapwrapper.h \ mailtypes.h \ pop3wrapper.h \ abstractmail.h \ smtpwrapper.h \ genericwrapper.h \ mboxwrapper.h \ settings.h \ logindialog.h \ sendmailprogress.h \ - statusmail.h + statusmail.h \ + mhwrapper.h SOURCES = imapwrapper.cpp \ mailwrapper.cpp \ mailtypes.cpp \ pop3wrapper.cpp \ abstractmail.cpp \ smtpwrapper.cpp \ genericwrapper.cpp \ mboxwrapper.cpp \ settings.cpp \ logindialog.cpp \ sendmailprogress.cpp \ - statusmail.cpp + statusmail.cpp \ + mhwrapper.cpp INTERFACES = logindialogui.ui \ sendmailprogressui.ui INCLUDEPATH += $(OPIEDIR)/include CONFTEST = $$system( echo $CONFIG_TARGET_MACOSX ) contains( CONFTEST, y ){ LIBS += -lqpe -letpan -lssl -lcrypto -liconv }else{ LIBS += -lqpe -letpan -lssl -lcrypto } DESTDIR = $(OPIEDIR)/lib$(PROJMAK) TARGET = mailwrapper include ( $(OPIEDIR)/include.pro ) diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.cpp b/noncore/net/mail/libmailwrapper/mailwrapper.cpp index 75b9343..ebdbf4b 100644 --- a/noncore/net/mail/libmailwrapper/mailwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/mailwrapper.cpp @@ -1,148 +1,164 @@ #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <qdir.h> #include "mailwrapper.h" //#include "logindialog.h" //#include "defines.h" #define UNDEFINED 64 #define MAXLINE 76 #define UTF16MASK 0x03FFUL #define UTF16SHIFT 10 #define UTF16BASE 0x10000UL #define UTF16HIGHSTART 0xD800UL #define UTF16HIGHEND 0xDBFFUL #define UTF16LOSTART 0xDC00UL #define UTF16LOEND 0xDFFFUL Attachment::Attachment( DocLnk lnk ) { doc = lnk; size = QFileInfo( doc.file() ).size(); } Folder::Folder(const QString&tmp_name, const QString&sep ) { name = tmp_name; nameDisplay = name; separator = sep; + prefix = ""; } const QString& Folder::Separator()const { return separator; } -IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,bool no_inf, const QString&prefix ) +IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,bool no_inf, const QString&aprefix ) : Folder( name,sep ),m_MaySelect(select),m_NoInferior(no_inf) { // Decode IMAP foldername nameDisplay = IMAPFolder::decodeFolderName( name ); qDebug( "folder " + name + " - displayed as " + nameDisplay ); + prefix = aprefix; if (prefix.length()>0) { if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) { nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length()); } } } static unsigned char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; /** * Decodes base64 encoded parts of the imapfolder name * Code taken from kde cvs: kdebase/kioslave/imap4/rfcdecoder.cc */ QString IMAPFolder::decodeFolderName( const QString &name ) { unsigned char c, i, bitcount; unsigned long ucs4, utf16, bitbuf; unsigned char base64[256], utf8[6]; unsigned long srcPtr = 0; QCString dst = ""; QCString src = name.ascii(); /* initialize modified base64 decoding table */ memset(base64, UNDEFINED, sizeof(base64)); for (i = 0; i < sizeof(base64chars); ++i) { base64[(int)base64chars[i]] = i; } /* loop until end of string */ while (srcPtr < src.length ()) { c = src[srcPtr++]; /* deal with literal characters and &- */ if (c != '&' || src[srcPtr] == '-') { /* encode literally */ dst += c; /* skip over the '-' if this is an &- sequence */ if (c == '&') srcPtr++; } else { /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */ bitbuf = 0; bitcount = 0; ucs4 = 0; while ((c = base64[(unsigned char) src[srcPtr]]) != UNDEFINED) { ++srcPtr; bitbuf = (bitbuf << 6) | c; bitcount += 6; /* enough bits for a UTF-16 character? */ if (bitcount >= 16) { bitcount -= 16; utf16 = (bitcount ? bitbuf >> bitcount : bitbuf) & 0xffff; /* convert UTF16 to UCS4 */ if (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) { ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT; continue; } else if (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) { ucs4 += utf16 - UTF16LOSTART + UTF16BASE; } else { ucs4 = utf16; } /* convert UTF-16 range of UCS4 to UTF-8 */ if (ucs4 <= 0x7fUL) { utf8[0] = ucs4; i = 1; } else if (ucs4 <= 0x7ffUL) { utf8[0] = 0xc0 | (ucs4 >> 6); utf8[1] = 0x80 | (ucs4 & 0x3f); i = 2; } else if (ucs4 <= 0xffffUL) { utf8[0] = 0xe0 | (ucs4 >> 12); utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f); utf8[2] = 0x80 | (ucs4 & 0x3f); i = 3; } else { utf8[0] = 0xf0 | (ucs4 >> 18); utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f); utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f); utf8[3] = 0x80 | (ucs4 & 0x3f); i = 4; } /* copy it */ for (c = 0; c < i; ++c) { dst += utf8[c]; } } } /* skip over trailing '-' in modified UTF-7 encoding */ if (src[srcPtr] == '-') ++srcPtr; } } return QString::fromUtf8( dst.data() ); } Mail::Mail() :name(""), mail(""), to(""), cc(""), bcc(""), reply(""), subject(""), message("") { } + +MHFolder::MHFolder(const QString&disp_name,const QString&mbox) + : Folder( disp_name,"/" ) +{ + separator = "/"; + name = mbox; + if (!disp_name.startsWith("/") && disp_name.length()>0) + name+="/"; + name+=disp_name; + if (disp_name.length()==0) { + nameDisplay = separator; + } + prefix = mbox; +} diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.h b/noncore/net/mail/libmailwrapper/mailwrapper.h index a60777d..caaa3a2 100644 --- a/noncore/net/mail/libmailwrapper/mailwrapper.h +++ b/noncore/net/mail/libmailwrapper/mailwrapper.h @@ -1,92 +1,99 @@ #ifndef MAILWRAPPER_H #define MAILWRAPPER_H #include <qpe/applnk.h> #include <qbitarray.h> #include <qdatetime.h> #include "settings.h" class Attachment { public: Attachment( DocLnk lnk ); virtual ~Attachment(){} const QString getFileName()const{ return doc.file(); } const QString getName()const{ return doc.name(); } const QString getMimeType()const{ return doc.type(); } const QPixmap getPixmap()const{ return doc.pixmap(); } const int getSize()const { return size; } DocLnk getDocLnk() { return doc; } protected: DocLnk doc; int size; }; class Mail { public: Mail(); /* Possible that this destructor must not be declared virtual * 'cause it seems that it will never have some child classes. * in this case this object will not get a virtual table -> memory and * speed will be a little bit better? */ virtual ~Mail(){} void addAttachment( Attachment *att ) { attList.append( att ); } const QList<Attachment>& getAttachments()const { return attList; } void removeAttachment( Attachment *att ) { attList.remove( att ); } const QString&getName()const { return name; } void setName( QString s ) { name = s; } const QString&getMail()const{ return mail; } void setMail( const QString&s ) { mail = s; } const QString&getTo()const{ return to; } void setTo( const QString&s ) { to = s; } const QString&getCC()const{ return cc; } void setCC( const QString&s ) { cc = s; } const QString&getBCC()const { return bcc; } void setBCC( const QString&s ) { bcc = s; } const QString&getMessage()const { return message; } void setMessage( const QString&s ) { message = s; } const QString&getSubject()const { return subject; } void setSubject( const QString&s ) { subject = s; } const QString&getReply()const{ return reply; } void setReply( const QString&a ) { reply = a; } private: QList<Attachment> attList; QString name, mail, to, cc, bcc, reply, subject, message; }; class Folder : public QObject { Q_OBJECT public: Folder( const QString&init_name,const QString&sep ); const QString&getDisplayName()const { return nameDisplay; } const QString&getName()const { return name; } + const QString&getPrefix()const{return prefix; } virtual bool may_select()const{return true;} virtual bool no_inferior()const{return true;} const QString&Separator()const; protected: - QString nameDisplay, name, separator; + QString nameDisplay, name, separator,prefix; +}; +class MHFolder : public Folder +{ + Q_OBJECT +public: + MHFolder(const QString&disp_name,const QString&mbox); }; class IMAPFolder : public Folder { public: IMAPFolder(const QString&name, const QString&sep, bool select=true,bool noinf=false,const QString&prefix="" ); virtual bool may_select()const{return m_MaySelect;} virtual bool no_inferior()const{return m_NoInferior;} private: static QString decodeFolderName( const QString &name ); bool m_MaySelect,m_NoInferior; }; #endif diff --git a/noncore/net/mail/libmailwrapper/mboxwrapper.h b/noncore/net/mail/libmailwrapper/mboxwrapper.h index 194ff86..a579a3d 100644 --- a/noncore/net/mail/libmailwrapper/mboxwrapper.h +++ b/noncore/net/mail/libmailwrapper/mboxwrapper.h @@ -1,47 +1,48 @@ #ifndef __MBOX_WRAPPER_H #define __MBOX_WRAPPER_H #include "genericwrapper.h" #include <qstring.h> class RecMail; class RecBody; class encodedString; struct mailmbox_folder; class MBOXwrapper : public Genericwrapper { Q_OBJECT + public: MBOXwrapper(const QString & dir,const QString&name); virtual ~MBOXwrapper(); virtual void listMessages(const QString & mailbox, QList<RecMail> &target ); virtual QList<Folder>* listFolders(); virtual void statusFolder(folderStat&target_stat,const QString & mailbox="INBOX"); virtual void deleteMail(const RecMail&mail); virtual void answeredMail(const RecMail&mail); virtual int createMbox(const QString&folder,const Folder*f=0,const QString&d="",bool s=false); virtual int deleteMbox(const Folder*); virtual void storeMessage(const char*msg,size_t length, const QString&folder); virtual RecBody fetchBody( const RecMail &mail ); static void mbox_progress( size_t current, size_t maximum ); virtual encodedString* fetchRawBody(const RecMail&mail); virtual void deleteMails(const QString & FolderName,QList<RecMail> &target); virtual int deleteAllMail(const Folder*); virtual const QString&getType()const; virtual const QString&getName()const; protected: static void deleteMails(mailmbox_folder*f,QList<RecMail> &target); QString MBOXPath; QString MBOXName; static const QString wrapperType; }; #endif diff --git a/noncore/net/mail/libmailwrapper/mhwrapper.cpp b/noncore/net/mail/libmailwrapper/mhwrapper.cpp new file mode 100644 index 0000000..85f9cf0 --- a/dev/null +++ b/noncore/net/mail/libmailwrapper/mhwrapper.cpp @@ -0,0 +1,330 @@ +#include "mhwrapper.h" +#include "mailtypes.h" +#include "mailwrapper.h" +#include <libetpan/libetpan.h> +#include <qdir.h> +#include <stdlib.h> +#include <qpe/global.h> + +const QString MHwrapper::wrapperType="MH"; + +MHwrapper::MHwrapper(const QString & mbox_dir,const QString&mbox_name) + : Genericwrapper(),MHPath(mbox_dir),MHName(mbox_name) +{ + if (MHPath.length()>0) { + if (MHPath[MHPath.length()-1]=='/') { + MHPath=MHPath.left(MHPath.length()-1); + } + qDebug(MHPath); + QDir dir(MHPath); + if (!dir.exists()) { + dir.mkdir(MHPath); + } + init_storage(); + } +} + +void MHwrapper::init_storage() +{ + int r; + QString pre = MHPath; + if (!m_storage) { + m_storage = mailstorage_new(NULL); + r = mh_mailstorage_init(m_storage,(char*)pre.latin1(),0,0,0); + if (r != MAIL_NO_ERROR) { + qDebug("error initializing storage"); + mailstorage_free(m_storage); + m_storage = 0; + return; + } + } + r = mailstorage_connect(m_storage); + if (r!=MAIL_NO_ERROR) { + qDebug("error connecting storage"); + mailstorage_free(m_storage); + m_storage = 0; + } +} + +void MHwrapper::clean_storage() +{ + if (m_storage) { + mailstorage_disconnect(m_storage); + mailstorage_free(m_storage); + m_storage = 0; + } +} + +MHwrapper::~MHwrapper() +{ + clean_storage(); +} + +void MHwrapper::listMessages(const QString & mailbox, QList<RecMail> &target ) +{ + init_storage(); + if (!m_storage) { + return; + } + QString f = buildPath(mailbox); + int r = mailsession_select_folder(m_storage->sto_session,(char*)mailbox.latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting folder!"); + return; + } + parseList(target,m_storage->sto_session,f); + Global::statusMessage(tr("Mailbox has %1 mail(s)").arg(target.count())); +} + +QList<Folder>* MHwrapper::listFolders() +{ + QList<Folder> * folders = new QList<Folder>(); + folders->setAutoDelete( false ); + init_storage(); + if (!m_storage) { + return folders; + } + mail_list*flist = 0; + clistcell*current=0; + int r = mailsession_list_folders(m_storage->sto_session,NULL,&flist); + if (r != MAIL_NO_ERROR || !flist) { + qDebug("error getting folder list"); + return folders; + } + for (current=clist_begin(flist->mb_list);current!=0;current=clist_next(current)) { + QString t = (char*)current->data; + t.replace(0,MHPath.length(),""); + folders->append(new MHFolder(t,MHPath)); + } + mail_list_free(flist); + return folders; +} + +void MHwrapper::deleteMail(const RecMail&mail) +{ + init_storage(); + if (!m_storage) { + return; + } + int r = mailsession_select_folder(m_storage->sto_session,(char*)mail.getMbox().latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting folder!"); + return; + } + r = mailsession_remove_message(m_storage->sto_session,mail.getNumber()); + if (r != MAIL_NO_ERROR) { + qDebug("error deleting mail"); + } +} + +void MHwrapper::answeredMail(const RecMail&) +{ +} + +RecBody MHwrapper::fetchBody( const RecMail &mail ) +{ + RecBody body; + init_storage(); + if (!m_storage) { + return body; + } + mailmessage * msg; + char*data=0; + size_t size; + + /* mail should hold the complete path! */ + int r = mailsession_select_folder(m_storage->sto_session,(char*)mail.getMbox().latin1()); + if (r != MAIL_NO_ERROR) { + return body; + } + r = mailsession_get_message(m_storage->sto_session, mail.getNumber(), &msg); + if (r != MAIL_NO_ERROR) { + qDebug("Error fetching mail %i",mail.getNumber()); + return body; + } + body = parseMail(msg); + mailmessage_fetch_result_free(msg,data); + return body; +} + +void MHwrapper::mbox_progress( size_t current, size_t maximum ) +{ + qDebug("MH %i von %i",current,maximum); +} + +QString MHwrapper::buildPath(const QString&p) +{ + QString f=""; + if (p.length()==0||p=="/") + return MHPath; + if (!p.startsWith(MHPath)) { + f+=MHPath; + } + if (!p.startsWith("/")) { + f+="/"; + } + f+=p; + return f; +} + +int MHwrapper::createMbox(const QString&folder,const Folder*,const QString&,bool ) +{ + init_storage(); + if (!m_storage) { + return 0; + } + QString f = buildPath(folder); + int r = mailsession_create_folder(m_storage->sto_session,(char*)f.latin1()); + if (r != MAIL_NO_ERROR) { + qDebug("error creating folder"); + return 0; + } + qDebug("Folder created"); + mailstorage_disconnect(m_storage); + return 1; +} + +void MHwrapper::storeMessage(const char*msg,size_t length, const QString&Folder) +{ + init_storage(); + if (!m_storage) { + return; + } + QString f = buildPath(Folder); + int r = mailsession_select_folder(m_storage->sto_session,(char*)f.latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting folder!"); + return; + } + r = mailsession_append_message(m_storage->sto_session,(char*)msg,length); + if (r!=MAIL_NO_ERROR) { + qDebug("error storing mail"); + } + return; +} + +encodedString* MHwrapper::fetchRawBody(const RecMail&mail) +{ + encodedString*result = 0; + init_storage(); + if (!m_storage) { + return result; + } + mailmessage * msg = 0; + char*data=0; + size_t size; + int r = mailsession_select_folder(m_storage->sto_session,(char*)mail.getMbox().latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting folder!"); + return result; + } + r = mailsession_get_message(m_storage->sto_session, mail.getNumber(), &msg); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error fetching mail %i").arg(mail.getNumber())); + return 0; + } + r = mailmessage_fetch(msg,&data,&size); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error fetching mail %i").arg(mail.getNumber())); + if (msg) mailmessage_free(msg); + return 0; + } + result = new encodedString(data,size); + if (msg) mailmessage_free(msg); + return result; +} + +void MHwrapper::deleteMails(const QString & mailbox,QList<RecMail> &target) +{ +#if 0 + QString p = MHPath+"/"; + p+=mailbox; + mailmbox_folder*f = 0; + int r = mailmbox_init(p.latin1(),0,1,0,&f); + if (r != MAIL_NO_ERROR) { + qDebug("Error init folder"); + return; + } + deleteMails(f,target); + mailmbox_done(f); +#endif +} + +int MHwrapper::deleteAllMail(const Folder*tfolder) +{ + init_storage(); + if (!m_storage) { + return 0; + } + int res = 1; + if (!tfolder) return 0; + int r = mailsession_select_folder(m_storage->sto_session,(char*)tfolder->getName().latin1()); + if (r!=MAIL_NO_ERROR) { + qDebug("error selecting folder!"); + return 0; + } + mailmessage_list*l=0; + r = mailsession_get_messages_list(m_storage->sto_session,&l); + if (r != MAIL_NO_ERROR) { + qDebug("Error message list"); + res = 0; + } + unsigned j = 0; + for(unsigned int i = 0 ; l!= 0 && res==1 && i < carray_count(l->msg_tab) ; ++i) { + mailmessage * msg; + msg = (mailmessage*)carray_get(l->msg_tab, i); + j = msg->msg_index; + r = mailsession_remove_message(m_storage->sto_session,j); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error deleting mail %1").arg(i+1)); + res = 0; + break; + } + } + if (l) mailmessage_list_free(l); + return res; +} + +int MHwrapper::deleteMbox(const Folder*tfolder) +{ + init_storage(); + if (!m_storage) { + return 0; + } + if (!tfolder) return 0; + int r = mailsession_delete_folder(m_storage->sto_session,(char*)tfolder->getName().latin1()); + if (r != MAIL_NO_ERROR) { + qDebug("error deleting mail box"); + return 0; + } + qDebug("mail box deleted"); + mailstorage_disconnect(m_storage); + return 1; +} + +void MHwrapper::statusFolder(folderStat&target_stat,const QString & mailbox) +{ + init_storage(); + if (!m_storage) { + return; + } + target_stat.message_count = 0; + target_stat.message_unseen = 0; + target_stat.message_recent = 0; + QString f = buildPath(mailbox); + int r = mailsession_status_folder(m_storage->sto_session,(char*)f.latin1(),&target_stat.message_count, + &target_stat.message_recent,&target_stat.message_unseen); + if (r != MAIL_NO_ERROR) { + Global::statusMessage(tr("Error retrieving status")); + } +} + +const QString&MHwrapper::getType()const +{ + return wrapperType; +} + +const QString&MHwrapper::getName()const +{ + return MHName; +} diff --git a/noncore/net/mail/libmailwrapper/mhwrapper.h b/noncore/net/mail/libmailwrapper/mhwrapper.h new file mode 100644 index 0000000..7f028b4 --- a/dev/null +++ b/noncore/net/mail/libmailwrapper/mhwrapper.h @@ -0,0 +1,50 @@ +#ifndef __MH_WRAPPER_H +#define __MH_WRAPPER_H + +#include "genericwrapper.h" +#include <qstring.h> + +class RecMail; +class RecBody; +class encodedString; +struct mailmbox_folder; + +class MHwrapper : public Genericwrapper +{ + Q_OBJECT +public: + MHwrapper(const QString & dir,const QString&name); + virtual ~MHwrapper(); + + virtual void listMessages(const QString & mailbox, QList<RecMail> &target ); + virtual QList<Folder>* listFolders(); + virtual void statusFolder(folderStat&target_stat,const QString & mailbox="INBOX"); + + virtual void deleteMail(const RecMail&mail); + virtual void answeredMail(const RecMail&mail); + + virtual int createMbox(const QString&folder,const Folder*f=0,const QString&d="",bool s=false); + virtual int deleteMbox(const Folder*); + + virtual void storeMessage(const char*msg,size_t length, const QString&folder); + + virtual RecBody fetchBody( const RecMail &mail ); + static void mbox_progress( size_t current, size_t maximum ); + + virtual encodedString* fetchRawBody(const RecMail&mail); + virtual void deleteMails(const QString & FolderName,QList<RecMail> &target); + virtual int deleteAllMail(const Folder*); + virtual const QString&getType()const; + virtual const QString&getName()const; + +protected: + QString buildPath(const QString&p); + QString MHPath; + QString MHName; + static const QString wrapperType; + + void init_storage(); + void clean_storage(); +}; + +#endif diff --git a/noncore/net/mail/libmailwrapper/smtpwrapper.cpp b/noncore/net/mail/libmailwrapper/smtpwrapper.cpp index 281b88e..08f6bb7 100644 --- a/noncore/net/mail/libmailwrapper/smtpwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/smtpwrapper.cpp @@ -1,727 +1,728 @@ #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <qdir.h> #include <qt.h> #include <qpe/config.h> #include <qpe/qcopenvelope_qws.h> #include <libetpan/libetpan.h> #include "smtpwrapper.h" #include "mailwrapper.h" -#include "mboxwrapper.h" +#include "abstractmail.h" #include "logindialog.h" #include "mailtypes.h" //#include "defines.h" #include "sendmailprogress.h" const char* SMTPwrapper::USER_AGENT="OpieMail v0.3"; progressMailSend*SMTPwrapper::sendProgress = 0; SMTPwrapper::SMTPwrapper( Settings *s ) : QObject() { settings = s; Config cfg( "mail" ); cfg.setGroup( "Status" ); m_queuedMail = cfg.readNumEntry( "outgoing", 0 ); emit queuedMails( m_queuedMail ); connect( this, SIGNAL( queuedMails( int ) ), this, SLOT( emitQCop( int ) ) ); } void SMTPwrapper::emitQCop( int queued ) { QCopEnvelope env( "QPE/Pim", "outgoingMails(int)" ); env << queued; } QString SMTPwrapper::mailsmtpError( int errnum ) { switch ( errnum ) { case MAILSMTP_NO_ERROR: return tr( "No error" ); case MAILSMTP_ERROR_UNEXPECTED_CODE: return tr( "Unexpected error code" ); case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: return tr( "Service not available" ); case MAILSMTP_ERROR_STREAM: return tr( "Stream error" ); case MAILSMTP_ERROR_HOSTNAME: return tr( "gethostname() failed" ); case MAILSMTP_ERROR_NOT_IMPLEMENTED: return tr( "Not implemented" ); case MAILSMTP_ERROR_ACTION_NOT_TAKEN: return tr( "Error, action not taken" ); case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: return tr( "Data exceeds storage allocation" ); case MAILSMTP_ERROR_IN_PROCESSING: return tr( "Error in processing" ); // case MAILSMTP_ERROR_INSUFFISANT_SYSTEM_STORAGE: // return tr( "Insufficient system storage" ); case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: return tr( "Mailbox unavailable" ); case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: return tr( "Mailbox name not allowed" ); case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: return tr( "Bad command sequence" ); case MAILSMTP_ERROR_USER_NOT_LOCAL: return tr( "User not local" ); case MAILSMTP_ERROR_TRANSACTION_FAILED: return tr( "Transaction failed" ); case MAILSMTP_ERROR_MEMORY: return tr( "Memory error" ); case MAILSMTP_ERROR_CONNECTION_REFUSED: return tr( "Connection refused" ); default: return tr( "Unknown error code" ); } } mailimf_mailbox *SMTPwrapper::newMailbox(const QString&name, const QString&mail ) { return mailimf_mailbox_new( strdup( name.latin1() ), strdup( mail.latin1() ) ); } mailimf_address_list *SMTPwrapper::parseAddresses(const QString&addr ) { mailimf_address_list *addresses; if ( addr.isEmpty() ) return NULL; addresses = mailimf_address_list_new_empty(); bool literal_open = false; unsigned int startpos = 0; QStringList list; QString s; unsigned int i = 0; for (; i < addr.length();++i) { switch (addr[i]) { case '\"': literal_open = !literal_open; break; case ',': if (!literal_open) { s = addr.mid(startpos,i-startpos); if (!s.isEmpty()) { list.append(s); qDebug("Appended %s",s.latin1()); } // !!!! this is a MUST BE! startpos = ++i; } break; default: break; } } s = addr.mid(startpos,i-startpos); if (!s.isEmpty()) { list.append(s); qDebug("Appended %s",s.latin1()); } QStringList::Iterator it; for ( it = list.begin(); it != list.end(); it++ ) { int err = mailimf_address_list_add_parse( addresses, (char*)(*it).latin1() ); if ( err != MAILIMF_NO_ERROR ) { qDebug( "Error parsing" ); qDebug( *it ); } else { qDebug( "Parse success! %s",(*it).latin1()); } } return addresses; } mailimf_fields *SMTPwrapper::createImfFields(const Mail&mail ) { mailimf_fields *fields; mailimf_field *xmailer; mailimf_mailbox *sender=0,*fromBox=0; mailimf_mailbox_list *from=0; mailimf_address_list *to=0, *cc=0, *bcc=0, *reply=0; char *subject = strdup( mail.getSubject().latin1() ); int err; sender = newMailbox( mail.getName(), mail.getMail() ); if ( sender == NULL ) goto err_free; fromBox = newMailbox( mail.getName(), mail.getMail() ); if ( fromBox == NULL ) goto err_free_sender; from = mailimf_mailbox_list_new_empty(); if ( from == NULL ) goto err_free_fromBox; err = mailimf_mailbox_list_add( from, fromBox ); if ( err != MAILIMF_NO_ERROR ) goto err_free_from; to = parseAddresses( mail.getTo() ); if ( to == NULL ) goto err_free_from; cc = parseAddresses( mail.getCC() ); bcc = parseAddresses( mail.getBCC() ); reply = parseAddresses( mail.getReply() ); fields = mailimf_fields_new_with_data( from, sender, reply, to, cc, bcc, NULL, NULL, subject ); if ( fields == NULL ) goto err_free_reply; xmailer = mailimf_field_new_custom( strdup( "User-Agent" ), strdup( USER_AGENT ) ); if ( xmailer == NULL ) goto err_free_fields; err = mailimf_fields_add( fields, xmailer ); if ( err != MAILIMF_NO_ERROR ) goto err_free_xmailer; return fields; // Success :) err_free_xmailer: if (xmailer) mailimf_field_free( xmailer ); err_free_fields: if (fields) mailimf_fields_free( fields ); err_free_reply: if (reply) mailimf_address_list_free( reply ); if (bcc) mailimf_address_list_free( bcc ); if (cc) mailimf_address_list_free( cc ); if (to) mailimf_address_list_free( to ); err_free_from: if (from) mailimf_mailbox_list_free( from ); err_free_fromBox: mailimf_mailbox_free( fromBox ); err_free_sender: if (sender) mailimf_mailbox_free( sender ); err_free: if (subject) free( subject ); qDebug( "createImfFields - error" ); return NULL; // Error :( } mailmime *SMTPwrapper::buildTxtPart(const QString&str ) { mailmime *txtPart; mailmime_fields *fields; mailmime_content *content; mailmime_parameter *param; int err; param = mailmime_parameter_new( strdup( "charset" ), strdup( "iso-8859-1" ) ); if ( param == NULL ) goto err_free; content = mailmime_content_new_with_str( "text/plain" ); if ( content == NULL ) goto err_free_param; err = clist_append( content->ct_parameters, param ); if ( err != MAILIMF_NO_ERROR ) goto err_free_content; fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); if ( fields == NULL ) goto err_free_content; txtPart = mailmime_new_empty( content, fields ); if ( txtPart == NULL ) goto err_free_fields; err = mailmime_set_body_text( txtPart, (char*)str.data(), str.length() ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; return txtPart; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_fields: mailmime_fields_free( fields ); err_free_content: mailmime_content_free( content ); err_free_param: mailmime_parameter_free( param ); err_free: qDebug( "buildTxtPart - error" ); return NULL; // Error :( } mailmime *SMTPwrapper::buildFilePart(const QString&filename,const QString&mimetype,const QString&TextContent ) { mailmime * filePart = 0; mailmime_fields * fields = 0; mailmime_content * content = 0; mailmime_parameter * param = 0; char*name = 0; char*file = 0; int err; int pos = filename.findRev( '/' ); if (filename.length()>0) { QString tmp = filename.right( filename.length() - ( pos + 1 ) ); name = strdup( tmp.latin1() ); // just filename file = strdup( filename.latin1() ); // full name with path } int disptype = MAILMIME_DISPOSITION_TYPE_ATTACHMENT; int mechanism = MAILMIME_MECHANISM_BASE64; if ( mimetype.startsWith( "text/" ) ) { param = mailmime_parameter_new( strdup( "charset" ), strdup( "iso-8859-1" ) ); mechanism = MAILMIME_MECHANISM_QUOTED_PRINTABLE; } fields = mailmime_fields_new_filename( disptype, name, mechanism ); content = mailmime_content_new_with_str( (char*)mimetype.latin1() ); if (content!=0 && fields != 0) { if (param) { clist_append(content->ct_parameters,param); param = 0; } if (filename.length()>0) { QFileInfo f(filename); param = mailmime_parameter_new(strdup("name"),strdup(f.fileName().latin1())); clist_append(content->ct_parameters,param); param = 0; } filePart = mailmime_new_empty( content, fields ); } if (filePart) { if (filename.length()>0) { err = mailmime_set_body_file( filePart, file ); } else { err = mailmime_set_body_text(filePart,strdup(TextContent.data()),TextContent.length()); } if (err != MAILIMF_NO_ERROR) { qDebug("Error setting body with file %s",file); mailmime_free( filePart ); filePart = 0; } } if (!filePart) { if ( param != NULL ) { mailmime_parameter_free( param ); } if (content) { mailmime_content_free( content ); } if (fields) { mailmime_fields_free( fields ); } else { if (name) { free( name ); } if (file) { free( file ); } } } return filePart; // Success :) } void SMTPwrapper::addFileParts( mailmime *message,const QList<Attachment>&files ) { const Attachment *it; unsigned int count = files.count(); qDebug("List contains %i values",count); for ( unsigned int i = 0; i < count; ++i ) { qDebug( "Adding file" ); mailmime *filePart; int err; it = ((QList<Attachment>)files).at(i); filePart = buildFilePart( it->getFileName(), it->getMimeType(),"" ); if ( filePart == NULL ) { qDebug( "addFileParts: error adding file:" ); qDebug( it->getFileName() ); continue; } err = mailmime_smart_add_part( message, filePart ); if ( err != MAILIMF_NO_ERROR ) { mailmime_free( filePart ); qDebug("error smart add"); } } } mailmime *SMTPwrapper::createMimeMail(const Mail &mail ) { mailmime *message, *txtPart; mailimf_fields *fields; int err; fields = createImfFields( mail ); if ( fields == NULL ) goto err_free; message = mailmime_new_message_data( NULL ); if ( message == NULL ) goto err_free_fields; mailmime_set_imf_fields( message, fields ); txtPart = buildTxtPart( mail.getMessage() ); if ( txtPart == NULL ) goto err_free_message; err = mailmime_smart_add_part( message, txtPart ); if ( err != MAILIMF_NO_ERROR ) goto err_free_txtPart; addFileParts( message, mail.getAttachments() ); return message; // Success :) err_free_txtPart: mailmime_free( txtPart ); err_free_message: mailmime_free( message ); err_free_fields: mailimf_fields_free( fields ); err_free: qDebug( "createMimeMail: error" ); return NULL; // Error :( } mailimf_field *SMTPwrapper::getField( mailimf_fields *fields, int type ) { mailimf_field *field; clistiter *it; it = clist_begin( fields->fld_list ); while ( it ) { field = (mailimf_field *) it->data; if ( field->fld_type == type ) { return field; } it = it->next; } return NULL; } void SMTPwrapper::addRcpts( clist *list, mailimf_address_list *addr_list ) { clistiter *it, *it2; for ( it = clist_begin( addr_list->ad_list ); it; it = it->next ) { mailimf_address *addr; addr = (mailimf_address *) it->data; if ( addr->ad_type == MAILIMF_ADDRESS_MAILBOX ) { esmtp_address_list_add( list, addr->ad_data.ad_mailbox->mb_addr_spec, 0, NULL ); } else if ( addr->ad_type == MAILIMF_ADDRESS_GROUP ) { clist *l = addr->ad_data.ad_group->grp_mb_list->mb_list; for ( it2 = clist_begin( l ); it2; it2 = it2->next ) { mailimf_mailbox *mbox; mbox = (mailimf_mailbox *) it2->data; esmtp_address_list_add( list, mbox->mb_addr_spec, 0, NULL ); } } } } clist *SMTPwrapper::createRcptList( mailimf_fields *fields ) { clist *rcptList; mailimf_field *field; rcptList = esmtp_address_list_new(); field = getField( fields, MAILIMF_FIELD_TO ); if ( field && (field->fld_type == MAILIMF_FIELD_TO) && field->fld_data.fld_to->to_addr_list ) { addRcpts( rcptList, field->fld_data.fld_to->to_addr_list ); } field = getField( fields, MAILIMF_FIELD_CC ); if ( field && (field->fld_type == MAILIMF_FIELD_CC) && field->fld_data.fld_cc->cc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_cc->cc_addr_list ); } field = getField( fields, MAILIMF_FIELD_BCC ); if ( field && (field->fld_type == MAILIMF_FIELD_BCC) && field->fld_data.fld_bcc->bcc_addr_list ) { addRcpts( rcptList, field->fld_data.fld_bcc->bcc_addr_list ); } return rcptList; } char *SMTPwrapper::getFrom( mailimf_field *ffrom) { char *from = NULL; if ( ffrom && (ffrom->fld_type == MAILIMF_FIELD_FROM) && ffrom->fld_data.fld_from->frm_mb_list && ffrom->fld_data.fld_from->frm_mb_list->mb_list ) { clist *cl = ffrom->fld_data.fld_from->frm_mb_list->mb_list; clistiter *it; for ( it = clist_begin( cl ); it; it = it->next ) { mailimf_mailbox *mb = (mailimf_mailbox *) it->data; from = strdup( mb->mb_addr_spec ); } } return from; } char *SMTPwrapper::getFrom( mailmime *mail ) { /* no need to delete - its just a pointer to structure content */ mailimf_field *ffrom = 0; ffrom = getField( mail->mm_data.mm_message.mm_fields, MAILIMF_FIELD_FROM ); return getFrom(ffrom); } void SMTPwrapper::progress( size_t current, size_t maximum ) { if (SMTPwrapper::sendProgress) { SMTPwrapper::sendProgress->setSingleMail(current, maximum ); qApp->processEvents(); } } void SMTPwrapper::storeMail(const char*mail, size_t length, const QString&box) { if (!mail) return; QString localfolders = AbstractMail::defaultLocalfolder(); AbstractMail*wrap = AbstractMail::getWrapper(localfolders); + wrap->createMbox(box); wrap->storeMessage(mail,length,box); delete wrap; } void SMTPwrapper::smtpSend( mailmime *mail,bool later, SMTPaccount *smtp ) { clist *rcpts = 0; char *from, *data; size_t size; if ( smtp == NULL ) { return; } from = data = 0; mailmessage * msg = 0; msg = mime_message_init(mail); mime_message_set_tmpdir(msg,getenv( "HOME" )); int r = mailmessage_fetch(msg,&data,&size); mime_message_detach_mime(msg); mailmessage_free(msg); if (r != MAIL_NO_ERROR || !data) { if (data) free(data); qDebug("Error fetching mime..."); return; } msg = 0; if (later) { storeMail(data,size,"Outgoing"); if (data) free( data ); Config cfg( "mail" ); cfg.setGroup( "Status" ); cfg.writeEntry( "outgoing", ++m_queuedMail ); emit queuedMails( m_queuedMail ); return; } from = getFrom( mail ); rcpts = createRcptList( mail->mm_data.mm_message.mm_fields ); smtpSend(from,rcpts,data,size,smtp); if (data) {free(data);} if (from) {free(from);} if (rcpts) smtp_address_list_free( rcpts ); } int SMTPwrapper::smtpSend(char*from,clist*rcpts,const char*data,size_t size, SMTPaccount *smtp ) { const char *server, *user, *pass; bool ssl; uint16_t port; mailsmtp *session; int err,result; result = 1; server = user = pass = 0; server = smtp->getServer().latin1(); ssl = smtp->getSSL(); port = smtp->getPort().toUInt(); session = mailsmtp_new( 20, &progress ); if ( session == NULL ) goto free_mem; qDebug( "Servername %s at port %i", server, port ); if ( ssl ) { qDebug( "SSL session" ); err = mailsmtp_ssl_connect( session, server, port ); } else { qDebug( "No SSL session" ); err = mailsmtp_socket_connect( session, server, port ); } if ( err != MAILSMTP_NO_ERROR ) {qDebug("Error init connection");result = 0;goto free_mem_session;} err = mailsmtp_init( session ); if ( err != MAILSMTP_NO_ERROR ) {result = 0; goto free_con_session;} qDebug( "INIT OK" ); if ( smtp->getLogin() ) { qDebug("smtp with auth"); if ( smtp->getUser().isEmpty() || smtp->getPassword().isEmpty() ) { // get'em LoginDialog login( smtp->getUser(), smtp->getPassword(), NULL, 0, true ); login.show(); if ( QDialog::Accepted == login.exec() ) { // ok user = login.getUser().latin1(); pass = login.getPassword().latin1(); } else { result = 0; goto free_con_session; } } else { user = smtp->getUser().latin1(); pass = smtp->getPassword().latin1(); } qDebug( "session->auth: %i", session->auth); err = mailsmtp_auth( session, (char*)user, (char*)pass ); if ( err == MAILSMTP_NO_ERROR ) qDebug("auth ok"); qDebug( "Done auth!" ); } else { qDebug("SMTP without auth"); } err = mailsmtp_send( session, from, rcpts, data, size ); if ( err != MAILSMTP_NO_ERROR ) { qDebug("Error sending mail: %s",mailsmtpError(err).latin1()); result = 0; goto free_con_session; } qDebug( "Mail sent." ); storeMail(data,size,"Sent"); free_con_session: mailsmtp_quit( session ); free_mem_session: mailsmtp_free( session ); free_mem: return result; } void SMTPwrapper::sendMail(const Mail&mail,SMTPaccount*aSmtp,bool later ) { mailmime * mimeMail; SMTPaccount *smtp = aSmtp; if (!later && !smtp) { qDebug("Didn't get any send method - giving up"); return; } mimeMail = createMimeMail(mail ); if ( mimeMail == NULL ) { qDebug( "sendMail: error creating mime mail" ); } else { sendProgress = new progressMailSend(); sendProgress->show(); sendProgress->setMaxMails(1); smtpSend( mimeMail,later,smtp); qDebug("Clean up done"); sendProgress->hide(); delete sendProgress; sendProgress = 0; mailmime_free( mimeMail ); } } int SMTPwrapper::sendQueuedMail(AbstractMail*wrap,SMTPaccount*smtp,RecMail*which) { size_t curTok = 0; mailimf_fields *fields = 0; mailimf_field*ffrom = 0; clist *rcpts = 0; char*from = 0; int res = 0; encodedString * data = wrap->fetchRawBody(*which); if (!data) return 0; int err = mailimf_fields_parse( data->Content(), data->Length(), &curTok, &fields ); if (err != MAILIMF_NO_ERROR) { delete data; delete wrap; return 0; } rcpts = createRcptList( fields ); ffrom = getField(fields, MAILIMF_FIELD_FROM ); from = getFrom(ffrom); if (rcpts && from) { res = smtpSend(from,rcpts,data->Content(),data->Length(),smtp ); } if (fields) { mailimf_fields_free(fields); fields = 0; } if (data) { delete data; } if (from) { free(from); } if (rcpts) { smtp_address_list_free( rcpts ); } return res; } /* this is a special fun */ bool SMTPwrapper::flushOutbox(SMTPaccount*smtp) { bool returnValue = true; if (!smtp) return false; QString localfolders = AbstractMail::defaultLocalfolder(); AbstractMail*wrap = AbstractMail::getWrapper(localfolders); if (!wrap) { qDebug("memory error"); return false; } QList<RecMail> mailsToSend; QList<RecMail> mailsToRemove; QString mbox("Outgoing"); wrap->listMessages(mbox,mailsToSend); if (mailsToSend.count()==0) { delete wrap; return false; } mailsToSend.setAutoDelete(false); sendProgress = new progressMailSend(); sendProgress->show(); sendProgress->setMaxMails(mailsToSend.count()); while (mailsToSend.count()>0) { if (sendQueuedMail(wrap,smtp,mailsToSend.at(0))==0) { QMessageBox::critical(0,tr("Error sending mail"), tr("Error sending queued mail - breaking")); returnValue = false; break; } mailsToRemove.append(mailsToSend.at(0)); mailsToSend.removeFirst(); sendProgress->setCurrentMails(mailsToRemove.count()); } Config cfg( "mail" ); cfg.setGroup( "Status" ); m_queuedMail = 0; cfg.writeEntry( "outgoing", m_queuedMail ); emit queuedMails( m_queuedMail ); sendProgress->hide(); delete sendProgress; sendProgress = 0; wrap->deleteMails(mbox,mailsToRemove); mailsToSend.setAutoDelete(true); delete wrap; return returnValue; } |