kmail Library API Documentation

kmaccount.cpp

00001 // KMail Account
00002 #include <config.h>
00003 
00004 #include "kmaccount.h"
00005 
00006 #include "kmacctmgr.h"
00007 #include "kmacctfolder.h"
00008 #include "kmfoldermgr.h"
00009 #include "kmfiltermgr.h"
00010 #include "messagesender.h"
00011 #include "kmkernel.h"
00012 #include "broadcaststatus.h"
00013 using KPIM::BroadcastStatus;
00014 #include "kmfoldercachedimap.h"
00015 
00016 #include "progressmanager.h"
00017 using KPIM::ProgressItem;
00018 using KPIM::ProgressManager;
00019 
00020 using KMail::FolderJob;
00021 
00022 #include <kapplication.h>
00023 #include <klocale.h>
00024 #include <kmessagebox.h>
00025 #include <kdebug.h>
00026 #include <kconfig.h>
00027 
00028 #include <qeventloop.h>
00029 
00030 #include <stdlib.h>
00031 #include <unistd.h>
00032 #include <errno.h>
00033 
00034 #include <assert.h>
00035 
00036 //----------------------
00037 #include "kmaccount.moc"
00038 
00039 //-----------------------------------------------------------------------------
00040 KMPrecommand::KMPrecommand(const QString &precommand, QObject *parent)
00041   : QObject(parent), mPrecommand(precommand)
00042 {
00043   BroadcastStatus::instance()->setStatusMsg(
00044       i18n("Executing precommand %1").arg(precommand ));
00045 
00046   mPrecommandProcess.setUseShell(true);
00047   mPrecommandProcess << precommand;
00048 
00049   connect(&mPrecommandProcess, SIGNAL(processExited(KProcess *)),
00050           SLOT(precommandExited(KProcess *)));
00051 }
00052 
00053 //-----------------------------------------------------------------------------
00054 KMPrecommand::~KMPrecommand()
00055 {
00056 }
00057 
00058 
00059 //-----------------------------------------------------------------------------
00060 bool KMPrecommand::start()
00061 {
00062   bool ok = mPrecommandProcess.start( KProcess::NotifyOnExit );
00063   if (!ok) KMessageBox::error(0, i18n("Could not execute precommand '%1'.")
00064     .arg(mPrecommand));
00065   return ok;
00066 }
00067 
00068 
00069 //-----------------------------------------------------------------------------
00070 void KMPrecommand::precommandExited(KProcess *p)
00071 {
00072   int exitCode = p->normalExit() ? p->exitStatus() : -1;
00073   if (exitCode)
00074     KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2")
00075       .arg(exitCode).arg(strerror(exitCode)));
00076   emit finished(!exitCode);
00077 }
00078 
00079 
00080 //-----------------------------------------------------------------------------
00081 KMAccount::KMAccount(KMAcctMgr* aOwner, const QString& aName, uint id)
00082   : KAccount( id, aName ),
00083     mTrash(KMKernel::self()->trashFolder()->idString()),
00084     mOwner(aOwner),
00085     mFolder(0),
00086     mTimer(0),
00087     mInterval(0),
00088     mExclude(false),
00089     mCheckingMail(false),
00090     mPrecommandSuccess(true),
00091     mHasInbox(false),
00092     mMailCheckProgressItem(0)
00093 {
00094   assert(aOwner != 0);
00095 
00096   connect(&mReceiptTimer,SIGNAL(timeout()),SLOT(sendReceipts()));
00097 }
00098 
00099 void KMAccount::init() {
00100   mTrash = kmkernel->trashFolder()->idString();
00101   mExclude = false;
00102   mInterval = 0;
00103   mNewInFolder.clear();
00104 }
00105 
00106 //-----------------------------------------------------------------------------
00107 KMAccount::~KMAccount()
00108 {
00109   if ( (kmkernel && !kmkernel->shuttingDown()) && mFolder ) mFolder->removeAccount(this);
00110   if (mTimer) deinstallTimer();
00111 }
00112 
00113 
00114 //-----------------------------------------------------------------------------
00115 void KMAccount::setName(const QString& aName)
00116 {
00117   mName = (aName.isEmpty()) ? i18n("Unnamed") : aName;
00118 }
00119 
00120 
00121 //-----------------------------------------------------------------------------
00122 void KMAccount::clearPasswd()
00123 {
00124 }
00125 
00126 
00127 //-----------------------------------------------------------------------------
00128 void KMAccount::setFolder(KMFolder* aFolder, bool addAccount)
00129 {
00130   if(!aFolder) {
00131     //kdDebug(5006) << "KMAccount::setFolder() : aFolder == 0" << endl;
00132     mFolder = 0;
00133     return;
00134   }
00135   mFolder = (KMAcctFolder*)aFolder;
00136   if (addAccount) mFolder->addAccount(this);
00137 }
00138 
00139 
00140 //-----------------------------------------------------------------------------
00141 void KMAccount::readConfig(KConfig& config)
00142 {
00143   QString folderName;
00144   mFolder = 0;
00145   folderName = config.readEntry("Folder");
00146   setCheckInterval(config.readNumEntry("check-interval", 0));
00147   setTrash(config.readEntry("trash", kmkernel->trashFolder()->idString()));
00148   setCheckExclude(config.readBoolEntry("check-exclude", false));
00149   setPrecommand(config.readPathEntry("precommand"));
00150 
00151   if (!folderName.isEmpty())
00152   {
00153     setFolder(kmkernel->folderMgr()->findIdString(folderName), true);
00154   }
00155 
00156   if (mInterval == 0)
00157     deinstallTimer();
00158   else
00159     installTimer();
00160 }
00161 
00162 
00163 //-----------------------------------------------------------------------------
00164 void KMAccount::writeConfig(KConfig& config)
00165 {
00166   // ID, Name
00167   KAccount::writeConfig(config);
00168 
00169   config.writeEntry("Type", type());
00170   config.writeEntry("Folder", mFolder ? mFolder->idString() : QString::null);
00171   config.writeEntry("check-interval", mInterval);
00172   config.writeEntry("check-exclude", mExclude);
00173   config.writePathEntry("precommand", mPrecommand);
00174   config.writeEntry("trash", mTrash);
00175 }
00176 
00177 
00178 //-----------------------------------------------------------------------------
00179 void KMAccount::sendReceipt(KMMessage* aMsg)
00180 {
00181   KConfig* cfg = KMKernel::config();
00182   bool sendReceipts;
00183 
00184   KConfigGroupSaver saver(cfg, "General");
00185 
00186   sendReceipts = cfg->readBoolEntry("send-receipts", false);
00187   if (!sendReceipts) return;
00188 
00189   KMMessage *newMsg = aMsg->createDeliveryReceipt();
00190   if (newMsg) {
00191     mReceipts.append(newMsg);
00192     mReceiptTimer.start(0,true);
00193   }
00194 }
00195 
00196 
00197 //-----------------------------------------------------------------------------
00198 bool KMAccount::processNewMsg(KMMessage* aMsg)
00199 {
00200   int rc, processResult;
00201 
00202   assert(aMsg != 0);
00203 
00204   // Save this one for readding
00205   KMFolderCachedImap* parent = 0;
00206   if( type() == "cachedimap" )
00207     parent = static_cast<KMFolderCachedImap*>( aMsg->storage() );
00208 
00209   // checks whether we should send delivery receipts
00210   // and sends them.
00211   sendReceipt(aMsg);
00212 
00213   // Set status of new messages that are marked as old to read, otherwise
00214   // the user won't see which messages newly arrived.
00215   // This is only valid for pop accounts and produces wrong stati for imap.
00216   if ( type() != "cachedimap" && type() != "imap" ) {
00217     if ( aMsg->isOld() )
00218       aMsg->setStatus(KMMsgStatusUnread);  // -sanders
00219     //    aMsg->setStatus(KMMsgStatusRead);
00220     else
00221       aMsg->setStatus(KMMsgStatusNew);
00222   }
00223 /*
00224 QFile fileD0( "testdat_xx-kmaccount-0" );
00225 if( fileD0.open( IO_WriteOnly ) ) {
00226     QDataStream ds( &fileD0 );
00227     ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() );
00228     fileD0.close();  // If data is 0 we just create a zero length file.
00229 }
00230 */
00231   // 0==message moved; 1==processing ok, no move; 2==critical error, abort!
00232 
00233   processResult = kmkernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound);
00234   if (processResult == 2) {
00235     perror("Critical error: Unable to collect mail (out of space?)");
00236     KMessageBox::information(0,(i18n("Critical error: "
00237       "Unable to collect mail: ")) + QString::fromLocal8Bit(strerror(errno)));
00238     return false;
00239   }
00240   else if (processResult == 1)
00241   {
00242     if( type() == "cachedimap" )
00243       ; // already done by caller: parent->addMsgInternal( aMsg, false );
00244     else {
00245       // TODO: Perhaps it would be best, if this if was handled by a virtual
00246       // method, so the if( !dimap ) above could die?
00247       kmkernel->filterMgr()->tempOpenFolder(mFolder);
00248       rc = mFolder->addMsg(aMsg);
00249 /*
00250 QFile fileD0( "testdat_xx-kmaccount-1" );
00251 if( fileD0.open( IO_WriteOnly ) ) {
00252     QDataStream ds( &fileD0 );
00253     ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() );
00254     fileD0.close();  // If data is 0 we just create a zero length file.
00255 }
00256 */
00257       if (rc) {
00258         perror("failed to add message");
00259         KMessageBox::information(0, i18n("Failed to add message:\n") +
00260                                  QString(strerror(rc)));
00261         return false;
00262       }
00263       int count = mFolder->count();
00264       // If count == 1, the message is immediately displayed
00265       if (count != 1) mFolder->unGetMsg(count - 1);
00266     }
00267   }
00268 
00269   // Count number of new messages for each folder
00270   QString folderId;
00271   if ( processResult == 1 ) {
00272     folderId = ( type() == "cachedimap" ) ? parent->folder()->idString()
00273                                           : mFolder->idString();
00274   }
00275   else {
00276     folderId = aMsg->parent()->idString();
00277   }
00278   addToNewInFolder( folderId, 1 );
00279 
00280   return true; //Everything's fine - message has been added by filter  }
00281 }
00282 
00283 
00284 //-----------------------------------------------------------------------------
00285 void KMAccount::setCheckInterval(int aInterval)
00286 {
00287   if (aInterval <= 0)
00288     mInterval = 0;
00289   else
00290     mInterval = aInterval;
00291   // Don't call installTimer from here! See #117935.
00292 }
00293 
00294 int KMAccount::checkInterval() const
00295 {
00296   if ( mInterval <= 0 )
00297     return mInterval;
00298   return QMAX( mInterval, GlobalSettings::self()->minimumCheckInterval() );
00299 }
00300 
00301 //----------------------------------------------------------------------------
00302 void KMAccount::deleteFolderJobs()
00303 {
00304   mJobList.setAutoDelete(true);
00305   mJobList.clear();
00306   mJobList.setAutoDelete(false);
00307 }
00308 
00309 //----------------------------------------------------------------------------
00310 void KMAccount::ignoreJobsForMessage( KMMessage* msg )
00311 {
00312   //FIXME: remove, make folders handle those
00313   for( QPtrListIterator<FolderJob> it(mJobList); it.current(); ++it ) {
00314     if ( it.current()->msgList().first() == msg) {
00315       FolderJob *job = it.current();
00316       mJobList.remove( job );
00317       delete job;
00318       break;
00319     }
00320   }
00321 }
00322 
00323 //-----------------------------------------------------------------------------
00324 void KMAccount::setCheckExclude(bool aExclude)
00325 {
00326   mExclude = aExclude;
00327 }
00328 
00329 
00330 //-----------------------------------------------------------------------------
00331 void KMAccount::installTimer()
00332 {
00333   if (mInterval <= 0) return;
00334   if(!mTimer)
00335   {
00336     mTimer = new QTimer();
00337     connect(mTimer,SIGNAL(timeout()),SLOT(mailCheck()));
00338   }
00339   else
00340   {
00341     mTimer->stop();
00342   }
00343   mTimer->start( checkInterval() * 60000 );
00344 }
00345 
00346 
00347 //-----------------------------------------------------------------------------
00348 void KMAccount::deinstallTimer()
00349 {
00350   delete mTimer;
00351   mTimer = 0;
00352 }
00353 
00354 //-----------------------------------------------------------------------------
00355 bool KMAccount::runPrecommand(const QString &precommand)
00356 {
00357   // Run the pre command if there is one
00358   if ( precommand.isEmpty() )
00359     return true;
00360 
00361   KMPrecommand precommandProcess(precommand, this);
00362 
00363   BroadcastStatus::instance()->setStatusMsg(
00364       i18n("Executing precommand %1").arg(precommand ));
00365 
00366   connect(&precommandProcess, SIGNAL(finished(bool)),
00367           SLOT(precommandExited(bool)));
00368 
00369   kdDebug(5006) << "Running precommand " << precommand << endl;
00370   if (!precommandProcess.start()) return false;
00371 
00372   kapp->eventLoop()->enterLoop();
00373 
00374   return mPrecommandSuccess;
00375 }
00376 
00377 //-----------------------------------------------------------------------------
00378 void KMAccount::precommandExited(bool success)
00379 {
00380   mPrecommandSuccess = success;
00381   kapp->eventLoop()->exitLoop();
00382 }
00383 
00384 //-----------------------------------------------------------------------------
00385 void KMAccount::mailCheck()
00386 {
00387   if (mTimer)
00388     mTimer->stop();
00389   kmkernel->acctMgr()->singleCheckMail(this, false);
00390 }
00391 
00392 //-----------------------------------------------------------------------------
00393 void KMAccount::sendReceipts()
00394 {
00395   QValueList<KMMessage*>::Iterator it;
00396   for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
00397     kmkernel->msgSender()->send(*it); //might process events
00398   mReceipts.clear();
00399 }
00400 
00401 //-----------------------------------------------------------------------------
00402 QString KMAccount::encryptStr(const QString &aStr)
00403 {
00404   QString result;
00405   for (uint i = 0; i < aStr.length(); i++)
00406     result += (aStr[i].unicode() < 0x20) ? aStr[i] :
00407       QChar(0x1001F - aStr[i].unicode());
00408   return result;
00409 }
00410 
00411 //-----------------------------------------------------------------------------
00412 QString KMAccount::importPassword(const QString &aStr)
00413 {
00414   unsigned int i, val;
00415   unsigned int len = aStr.length();
00416   QCString result;
00417   result.resize(len+1);
00418 
00419   for (i=0; i<len; i++)
00420   {
00421     val = aStr[i] - ' ';
00422     val = (255-' ') - val;
00423     result[i] = (char)(val + ' ');
00424   }
00425   result[i] = '\0';
00426 
00427   return encryptStr(result);
00428 }
00429 
00430 void KMAccount::invalidateIMAPFolders()
00431 {
00432   // Default: Don't do anything. The IMAP account will handle it
00433 }
00434 
00435 void KMAccount::pseudoAssign( const KMAccount * a ) {
00436   if ( !a ) return;
00437 
00438   setName( a->name() );
00439   setId( a->id() );
00440   setCheckInterval( a->checkInterval() );
00441   setCheckExclude( a->checkExclude() );
00442   setFolder( a->folder() );
00443   setPrecommand( a->precommand() );
00444   setTrash( a->trash() );
00445 }
00446 
00447 //-----------------------------------------------------------------------------
00448 void KMAccount::checkDone( bool newmail, CheckStatus status )
00449 {
00450   mCheckingMail = false;
00451   // Reset the timeout for automatic mailchecking. The user might have
00452   // triggered the check manually.
00453   if (mTimer)
00454     mTimer->start( checkInterval() * 60000 );
00455   if ( mMailCheckProgressItem ) {
00456     mMailCheckProgressItem->setComplete(); // that will delete it
00457     mMailCheckProgressItem = 0;
00458   }
00459 
00460   emit newMailsProcessed( mNewInFolder );
00461   emit finishedCheck( newmail, status );
00462   mNewInFolder.clear();
00463 }
00464 
00465 //-----------------------------------------------------------------------------
00466 void KMAccount::addToNewInFolder( QString folderId, int num )
00467 {
00468   if ( mNewInFolder.find( folderId ) == mNewInFolder.end() )
00469     mNewInFolder[folderId] = num;
00470   else
00471     mNewInFolder[folderId] += num;
00472 }
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Oct 17 09:55:23 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003