00001
00002 #include <config.h>
00003
00004 #include "kmaccount.h"
00005
00006 #include "accountmanager.h"
00007 using KMail::AccountManager;
00008 #include "globalsettings.h"
00009 #include "kmacctfolder.h"
00010 #include "kmfoldermgr.h"
00011 #include "kmfiltermgr.h"
00012 #include "messagesender.h"
00013 #include "kmmessage.h"
00014 #include "broadcaststatus.h"
00015 using KPIM::BroadcastStatus;
00016 #include "kmfoldercachedimap.h"
00017
00018 #include "progressmanager.h"
00019 using KPIM::ProgressItem;
00020 using KPIM::ProgressManager;
00021
00022 #include <libkpimidentities/identitymanager.h>
00023 #include <libkpimidentities/identity.h>
00024
00025 using KMail::FolderJob;
00026
00027 #include <kapplication.h>
00028 #include <klocale.h>
00029 #include <kmessagebox.h>
00030 #include <kdebug.h>
00031 #include <kconfig.h>
00032
00033 #include <qeventloop.h>
00034
00035 #include <stdlib.h>
00036 #include <unistd.h>
00037 #include <errno.h>
00038
00039 #include <assert.h>
00040
00041
00042 #include "kmaccount.moc"
00043
00044
00045 KMPrecommand::KMPrecommand(const QString &precommand, QObject *parent)
00046 : QObject(parent), mPrecommand(precommand)
00047 {
00048 BroadcastStatus::instance()->setStatusMsg(
00049 i18n("Executing precommand %1").arg(precommand ));
00050
00051 mPrecommandProcess.setUseShell(true);
00052 mPrecommandProcess << precommand;
00053
00054 connect(&mPrecommandProcess, SIGNAL(processExited(KProcess *)),
00055 SLOT(precommandExited(KProcess *)));
00056 }
00057
00058
00059 KMPrecommand::~KMPrecommand()
00060 {
00061 }
00062
00063
00064
00065 bool KMPrecommand::start()
00066 {
00067 bool ok = mPrecommandProcess.start( KProcess::NotifyOnExit );
00068 if (!ok) KMessageBox::error(0, i18n("Could not execute precommand '%1'.")
00069 .arg(mPrecommand));
00070 return ok;
00071 }
00072
00073
00074
00075 void KMPrecommand::precommandExited(KProcess *p)
00076 {
00077 int exitCode = p->normalExit() ? p->exitStatus() : -1;
00078 if (exitCode)
00079 KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2")
00080 .arg(exitCode).arg(strerror(exitCode)));
00081 emit finished(!exitCode);
00082 }
00083
00084
00085
00086 KMAccount::KMAccount(AccountManager* aOwner, const QString& aName, uint id)
00087 : KAccount( id, aName ),
00088 mTrash(KMKernel::self()->trashFolder()->idString()),
00089 mOwner(aOwner),
00090 mFolder(0),
00091 mTimer(0),
00092 mInterval(0),
00093 mExclude(false),
00094 mCheckingMail(false),
00095 mPrecommandSuccess(true),
00096 mHasInbox(false),
00097 mMailCheckProgressItem(0),
00098 mIdentityId(0)
00099 {
00100 assert(aOwner != 0);
00101 }
00102
00103 void KMAccount::init() {
00104 mTrash = kmkernel->trashFolder()->idString();
00105 mExclude = false;
00106 mInterval = 0;
00107 mNewInFolder.clear();
00108 }
00109
00110
00111 KMAccount::~KMAccount()
00112 {
00113 if ( (kmkernel && !kmkernel->shuttingDown()) && mFolder ) mFolder->removeAccount(this);
00114 if (mTimer) deinstallTimer();
00115 }
00116
00117
00118
00119 void KMAccount::setName(const QString& aName)
00120 {
00121 mName = aName;
00122 }
00123
00124
00125
00126 void KMAccount::clearPasswd()
00127 {
00128 }
00129
00130
00131
00132 void KMAccount::setFolder(KMFolder* aFolder, bool addAccount)
00133 {
00134 if(!aFolder) {
00135
00136 mFolder = 0;
00137 return;
00138 }
00139 mFolder = (KMAcctFolder*)aFolder;
00140 if (addAccount) mFolder->addAccount(this);
00141 }
00142
00143
00144
00145 void KMAccount::readConfig(KConfig& config)
00146 {
00147 QString folderName;
00148 mFolder = 0;
00149 folderName = config.readEntry("Folder");
00150 setCheckInterval(config.readNumEntry("check-interval", 0));
00151 setTrash(config.readEntry("trash", kmkernel->trashFolder()->idString()));
00152 setCheckExclude(config.readBoolEntry("check-exclude", false));
00153 setPrecommand(config.readPathEntry("precommand"));
00154 setIdentityId(config.readNumEntry("identity-id", 0));
00155 if (!folderName.isEmpty())
00156 {
00157 setFolder(kmkernel->folderMgr()->findIdString(folderName), true);
00158 }
00159
00160 if (mInterval == 0)
00161 deinstallTimer();
00162 else
00163 installTimer();
00164 }
00165
00166 void KMAccount::readTimerConfig()
00167 {
00168
00169
00170
00171 if (mInterval == 0)
00172 deinstallTimer();
00173 else
00174 installTimer();
00175 }
00176
00177
00178 void KMAccount::writeConfig(KConfig& config)
00179 {
00180
00181 KAccount::writeConfig(config);
00182
00183 config.writeEntry("Type", type());
00184 config.writeEntry("Folder", mFolder ? mFolder->idString() : QString::null);
00185 config.writeEntry("check-interval", mInterval);
00186 config.writeEntry("check-exclude", mExclude);
00187 config.writePathEntry("precommand", mPrecommand);
00188 config.writeEntry("trash", mTrash);
00189 if ( mIdentityId && mIdentityId != kmkernel->identityManager()->defaultIdentity().uoid() )
00190 config.writeEntry("identity-id", mIdentityId);
00191 else
00192 config.deleteEntry("identity-id");
00193 }
00194
00195
00196
00197 void KMAccount::sendReceipt(KMMessage* aMsg)
00198 {
00199 KConfig* cfg = KMKernel::config();
00200 bool sendReceipts;
00201
00202 KConfigGroupSaver saver(cfg, "General");
00203
00204 sendReceipts = cfg->readBoolEntry("send-receipts", false);
00205 if (!sendReceipts) return;
00206
00207 KMMessage *newMsg = aMsg->createDeliveryReceipt();
00208 if (newMsg) {
00209 mReceipts.append(newMsg);
00210 QTimer::singleShot( 0, this, SLOT( sendReceipts() ) );
00211 }
00212 }
00213
00214
00215
00216 bool KMAccount::processNewMsg(KMMessage* aMsg)
00217 {
00218 int rc, processResult;
00219
00220 assert(aMsg != 0);
00221
00222
00223 KMFolderCachedImap* parent = 0;
00224 if( type() == "cachedimap" )
00225 parent = static_cast<KMFolderCachedImap*>( aMsg->storage() );
00226
00227
00228
00229 sendReceipt(aMsg);
00230
00231
00232
00233
00234 if ( type() != "cachedimap" && type() != "imap" ) {
00235 if ( aMsg->isOld() )
00236 aMsg->setStatus(KMMsgStatusUnread);
00237
00238 else
00239 aMsg->setStatus(KMMsgStatusNew);
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 processResult = kmkernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound,true,id());
00252 if (processResult == 2) {
00253 perror("Critical error: Unable to collect mail (out of space?)");
00254 KMessageBox::information(0,(i18n("Critical error: "
00255 "Unable to collect mail: ")) + QString::fromLocal8Bit(strerror(errno)));
00256 return false;
00257 }
00258 else if (processResult == 1)
00259 {
00260 if( type() == "cachedimap" )
00261 ;
00262 else {
00263
00264
00265 kmkernel->filterMgr()->tempOpenFolder(mFolder);
00266 rc = mFolder->addMsg(aMsg);
00267
00268
00269
00270
00271
00272
00273
00274
00275 if (rc) {
00276 perror("failed to add message");
00277 KMessageBox::information(0, i18n("Failed to add message:\n") +
00278 QString(strerror(rc)));
00279 return false;
00280 }
00281 int count = mFolder->count();
00282
00283 if (count != 1) mFolder->unGetMsg(count - 1);
00284 }
00285 }
00286
00287
00288 QString folderId;
00289 if ( processResult == 1 ) {
00290 folderId = ( type() == "cachedimap" ) ? parent->folder()->idString()
00291 : mFolder->idString();
00292 }
00293 else {
00294 folderId = aMsg->parent()->idString();
00295 }
00296 addToNewInFolder( folderId, 1 );
00297
00298 return true;
00299 }
00300
00301
00302 void KMAccount::setCheckInterval(int aInterval)
00303 {
00304 if (aInterval <= 0)
00305 mInterval = 0;
00306 else
00307 mInterval = aInterval;
00308
00309 }
00310
00311 int KMAccount::checkInterval() const
00312 {
00313 if ( mInterval <= 0 )
00314 return mInterval;
00315 return QMAX( mInterval, GlobalSettings::self()->minimumCheckInterval() );
00316 }
00317
00318
00319 void KMAccount::deleteFolderJobs()
00320 {
00321 mJobList.setAutoDelete(true);
00322 mJobList.clear();
00323 mJobList.setAutoDelete(false);
00324 }
00325
00326
00327 void KMAccount::ignoreJobsForMessage( KMMessage* msg )
00328 {
00329
00330 for( QPtrListIterator<FolderJob> it(mJobList); it.current(); ++it ) {
00331 if ( it.current()->msgList().first() == msg) {
00332 FolderJob *job = it.current();
00333 mJobList.remove( job );
00334 delete job;
00335 break;
00336 }
00337 }
00338 }
00339
00340
00341 void KMAccount::setCheckExclude(bool aExclude)
00342 {
00343 mExclude = aExclude;
00344 }
00345
00346
00347
00348 void KMAccount::installTimer()
00349 {
00350 if (mInterval <= 0) return;
00351 if(!mTimer)
00352 {
00353 mTimer = new QTimer(0, "mTimer");
00354 connect(mTimer,SIGNAL(timeout()),SLOT(mailCheck()));
00355 }
00356 else
00357 {
00358 mTimer->stop();
00359 }
00360 mTimer->start( checkInterval() * 60000 );
00361 }
00362
00363
00364
00365 void KMAccount::deinstallTimer()
00366 {
00367 delete mTimer;
00368 mTimer = 0;
00369 }
00370
00371
00372 bool KMAccount::runPrecommand(const QString &precommand)
00373 {
00374
00375 if ( precommand.isEmpty() )
00376 return true;
00377
00378 KMPrecommand precommandProcess(precommand, this);
00379
00380 BroadcastStatus::instance()->setStatusMsg(
00381 i18n("Executing precommand %1").arg(precommand ));
00382
00383 connect(&precommandProcess, SIGNAL(finished(bool)),
00384 SLOT(precommandExited(bool)));
00385
00386 kdDebug(5006) << "Running precommand " << precommand << endl;
00387 if (!precommandProcess.start()) return false;
00388
00389 kapp->eventLoop()->enterLoop();
00390
00391 return mPrecommandSuccess;
00392 }
00393
00394
00395 void KMAccount::precommandExited(bool success)
00396 {
00397 mPrecommandSuccess = success;
00398 kapp->eventLoop()->exitLoop();
00399 }
00400
00401
00402 void KMAccount::mailCheck()
00403 {
00404 if (mTimer)
00405 mTimer->stop();
00406
00407 if ( kmkernel ) {
00408 AccountManager *acctmgr = kmkernel->acctMgr();
00409 if ( acctmgr )
00410 acctmgr->singleCheckMail(this, false);
00411 }
00412 }
00413
00414
00415 void KMAccount::sendReceipts()
00416 {
00417 QValueList<KMMessage*>::Iterator it;
00418 for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
00419 kmkernel->msgSender()->send(*it);
00420 mReceipts.clear();
00421 }
00422
00423
00424 QString KMAccount::encryptStr(const QString &aStr)
00425 {
00426 QString result;
00427 for (uint i = 0; i < aStr.length(); i++)
00428
00429
00430 result += (aStr[i].unicode() <= 0x21 ) ? aStr[i] :
00431 QChar(0x1001F - aStr[i].unicode());
00432 return result;
00433 }
00434
00435
00436 QString KMAccount::importPassword(const QString &aStr)
00437 {
00438 unsigned int i, val;
00439 unsigned int len = aStr.length();
00440 QCString result;
00441 result.resize(len+1);
00442
00443 for (i=0; i<len; i++)
00444 {
00445 val = aStr[i] - ' ';
00446 val = (255-' ') - val;
00447 result[i] = (char)(val + ' ');
00448 }
00449 result[i] = '\0';
00450
00451 return encryptStr(result);
00452 }
00453
00454 void KMAccount::invalidateIMAPFolders()
00455 {
00456
00457 }
00458
00459 void KMAccount::pseudoAssign( const KMAccount * a ) {
00460 if ( !a ) return;
00461
00462 setName( a->name() );
00463 setId( a->id() );
00464 setCheckInterval( a->checkInterval() );
00465 setCheckExclude( a->checkExclude() );
00466 setFolder( a->folder() );
00467 setPrecommand( a->precommand() );
00468 setTrash( a->trash() );
00469 setIdentityId( a->identityId() );
00470 }
00471
00472
00473 void KMAccount::checkDone( bool newmail, CheckStatus status )
00474 {
00475 setCheckingMail( false );
00476
00477
00478 if (mTimer)
00479 mTimer->start( checkInterval() * 60000 );
00480 if ( mMailCheckProgressItem ) {
00481
00482
00483 ProgressItem *savedMailCheckProgressItem = mMailCheckProgressItem;
00484 mMailCheckProgressItem = 0;
00485 savedMailCheckProgressItem->setComplete();
00486 }
00487
00488 emit newMailsProcessed( mNewInFolder );
00489 emit finishedCheck( newmail, status );
00490 mNewInFolder.clear();
00491 }
00492
00493
00494 void KMAccount::addToNewInFolder( QString folderId, int num )
00495 {
00496 if ( mNewInFolder.find( folderId ) == mNewInFolder.end() )
00497 mNewInFolder[folderId] = num;
00498 else
00499 mNewInFolder[folderId] += num;
00500 }