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
00167
00168 void KMAccount::writeConfig(KConfig& config)
00169 {
00170
00171 KAccount::writeConfig(config);
00172
00173 config.writeEntry("Type", type());
00174 config.writeEntry("Folder", mFolder ? mFolder->idString() : QString::null);
00175 config.writeEntry("check-interval", mInterval);
00176 config.writeEntry("check-exclude", mExclude);
00177 config.writePathEntry("precommand", mPrecommand);
00178 config.writeEntry("trash", mTrash);
00179 if ( mIdentityId && mIdentityId != kmkernel->identityManager()->defaultIdentity().uoid() )
00180 config.writeEntry("identity-id", mIdentityId);
00181 else
00182 config.deleteEntry("identity-id");
00183 }
00184
00185
00186
00187 void KMAccount::sendReceipt(KMMessage* aMsg)
00188 {
00189 KConfig* cfg = KMKernel::config();
00190 bool sendReceipts;
00191
00192 KConfigGroupSaver saver(cfg, "General");
00193
00194 sendReceipts = cfg->readBoolEntry("send-receipts", false);
00195 if (!sendReceipts) return;
00196
00197 KMMessage *newMsg = aMsg->createDeliveryReceipt();
00198 if (newMsg) {
00199 mReceipts.append(newMsg);
00200 QTimer::singleShot( 0, this, SLOT( sendReceipts() ) );
00201 }
00202 }
00203
00204
00205
00206 bool KMAccount::processNewMsg(KMMessage* aMsg)
00207 {
00208 int rc, processResult;
00209
00210 assert(aMsg != 0);
00211
00212
00213 KMFolderCachedImap* parent = 0;
00214 if( type() == "cachedimap" )
00215 parent = static_cast<KMFolderCachedImap*>( aMsg->storage() );
00216
00217
00218
00219 sendReceipt(aMsg);
00220
00221
00222
00223
00224 if ( type() != "cachedimap" && type() != "imap" ) {
00225 if ( aMsg->isOld() )
00226 aMsg->setStatus(KMMsgStatusUnread);
00227
00228 else
00229 aMsg->setStatus(KMMsgStatusNew);
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 processResult = kmkernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound,true,id());
00242 if (processResult == 2) {
00243 perror("Critical error: Unable to collect mail (out of space?)");
00244 KMessageBox::information(0,(i18n("Critical error: "
00245 "Unable to collect mail: ")) + QString::fromLocal8Bit(strerror(errno)));
00246 return false;
00247 }
00248 else if (processResult == 1)
00249 {
00250 if( type() == "cachedimap" )
00251 ;
00252 else {
00253
00254
00255 kmkernel->filterMgr()->tempOpenFolder(mFolder);
00256 rc = mFolder->addMsg(aMsg);
00257
00258
00259
00260
00261
00262
00263
00264
00265 if (rc) {
00266 perror("failed to add message");
00267 KMessageBox::information(0, i18n("Failed to add message:\n") +
00268 QString(strerror(rc)));
00269 return false;
00270 }
00271 int count = mFolder->count();
00272
00273 if (count != 1) mFolder->unGetMsg(count - 1);
00274 }
00275 }
00276
00277
00278 QString folderId;
00279 if ( processResult == 1 ) {
00280 folderId = ( type() == "cachedimap" ) ? parent->folder()->idString()
00281 : mFolder->idString();
00282 }
00283 else {
00284 folderId = aMsg->parent()->idString();
00285 }
00286 addToNewInFolder( folderId, 1 );
00287
00288 return true;
00289 }
00290
00291
00292 void KMAccount::setCheckInterval(int aInterval)
00293 {
00294 if (aInterval <= 0)
00295 mInterval = 0;
00296 else
00297 mInterval = aInterval;
00298
00299 }
00300
00301 int KMAccount::checkInterval() const
00302 {
00303 if ( mInterval <= 0 )
00304 return mInterval;
00305 return QMAX( mInterval, GlobalSettings::self()->minimumCheckInterval() );
00306 }
00307
00308
00309 void KMAccount::deleteFolderJobs()
00310 {
00311 mJobList.setAutoDelete(true);
00312 mJobList.clear();
00313 mJobList.setAutoDelete(false);
00314 }
00315
00316
00317 void KMAccount::ignoreJobsForMessage( KMMessage* msg )
00318 {
00319
00320 for( QPtrListIterator<FolderJob> it(mJobList); it.current(); ++it ) {
00321 if ( it.current()->msgList().first() == msg) {
00322 FolderJob *job = it.current();
00323 mJobList.remove( job );
00324 delete job;
00325 break;
00326 }
00327 }
00328 }
00329
00330
00331 void KMAccount::setCheckExclude(bool aExclude)
00332 {
00333 mExclude = aExclude;
00334 }
00335
00336
00337
00338 void KMAccount::installTimer()
00339 {
00340 if (mInterval <= 0) return;
00341 if(!mTimer)
00342 {
00343 mTimer = new QTimer(0, "mTimer");
00344 connect(mTimer,SIGNAL(timeout()),SLOT(mailCheck()));
00345 }
00346 else
00347 {
00348 mTimer->stop();
00349 }
00350 mTimer->start( checkInterval() * 60000 );
00351 }
00352
00353
00354
00355 void KMAccount::deinstallTimer()
00356 {
00357 delete mTimer;
00358 mTimer = 0;
00359 }
00360
00361
00362 bool KMAccount::runPrecommand(const QString &precommand)
00363 {
00364
00365 if ( precommand.isEmpty() )
00366 return true;
00367
00368 KMPrecommand precommandProcess(precommand, this);
00369
00370 BroadcastStatus::instance()->setStatusMsg(
00371 i18n("Executing precommand %1").arg(precommand ));
00372
00373 connect(&precommandProcess, SIGNAL(finished(bool)),
00374 SLOT(precommandExited(bool)));
00375
00376 kdDebug(5006) << "Running precommand " << precommand << endl;
00377 if (!precommandProcess.start()) return false;
00378
00379 kapp->eventLoop()->enterLoop();
00380
00381 return mPrecommandSuccess;
00382 }
00383
00384
00385 void KMAccount::precommandExited(bool success)
00386 {
00387 mPrecommandSuccess = success;
00388 kapp->eventLoop()->exitLoop();
00389 }
00390
00391
00392 void KMAccount::mailCheck()
00393 {
00394 if (mTimer)
00395 mTimer->stop();
00396
00397 if ( kmkernel ) {
00398 AccountManager *acctmgr = kmkernel->acctMgr();
00399 if ( acctmgr )
00400 acctmgr->singleCheckMail(this, false);
00401 }
00402 }
00403
00404
00405 void KMAccount::sendReceipts()
00406 {
00407 QValueList<KMMessage*>::Iterator it;
00408 for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
00409 kmkernel->msgSender()->send(*it);
00410 mReceipts.clear();
00411 }
00412
00413
00414 QString KMAccount::encryptStr(const QString &aStr)
00415 {
00416 QString result;
00417 for (uint i = 0; i < aStr.length(); i++)
00418
00419
00420 result += (aStr[i].unicode() <= 0x21 ) ? aStr[i] :
00421 QChar(0x1001F - aStr[i].unicode());
00422 return result;
00423 }
00424
00425
00426 QString KMAccount::importPassword(const QString &aStr)
00427 {
00428 unsigned int i, val;
00429 unsigned int len = aStr.length();
00430 QCString result;
00431 result.resize(len+1);
00432
00433 for (i=0; i<len; i++)
00434 {
00435 val = aStr[i] - ' ';
00436 val = (255-' ') - val;
00437 result[i] = (char)(val + ' ');
00438 }
00439 result[i] = '\0';
00440
00441 return encryptStr(result);
00442 }
00443
00444 void KMAccount::invalidateIMAPFolders()
00445 {
00446
00447 }
00448
00449 void KMAccount::pseudoAssign( const KMAccount * a ) {
00450 if ( !a ) return;
00451
00452 setName( a->name() );
00453 setId( a->id() );
00454 setCheckInterval( a->checkInterval() );
00455 setCheckExclude( a->checkExclude() );
00456 setFolder( a->folder() );
00457 setPrecommand( a->precommand() );
00458 setTrash( a->trash() );
00459 setIdentityId( a->identityId() );
00460 }
00461
00462
00463 void KMAccount::checkDone( bool newmail, CheckStatus status )
00464 {
00465 setCheckingMail( false );
00466
00467
00468 if (mTimer)
00469 mTimer->start( checkInterval() * 60000 );
00470 if ( mMailCheckProgressItem ) {
00471
00472
00473 ProgressItem *savedMailCheckProgressItem = mMailCheckProgressItem;
00474 mMailCheckProgressItem = 0;
00475 savedMailCheckProgressItem->setComplete();
00476 }
00477
00478 emit newMailsProcessed( mNewInFolder );
00479 emit finishedCheck( newmail, status );
00480 mNewInFolder.clear();
00481 }
00482
00483
00484 void KMAccount::addToNewInFolder( QString folderId, int num )
00485 {
00486 if ( mNewInFolder.find( folderId ) == mNewInFolder.end() )
00487 mNewInFolder[folderId] = num;
00488 else
00489 mNewInFolder[folderId] += num;
00490 }