// KMail Account #include #include "kmaccount.h" #include "accountmanager.h" using KMail::AccountManager; #include "globalsettings.h" #include "kmacctfolder.h" #include "kmfoldermgr.h" #include "kmfiltermgr.h" #include "messagesender.h" #include "kmmessage.h" #include "broadcaststatus.h" using KPIM::BroadcastStatus; #include "kmfoldercachedimap.h" #include "progressmanager.h" using KPIM::ProgressItem; using KPIM::ProgressManager; #include #include using KMail::FolderJob; #include #include #include #include #include #include #include #include #include #include //---------------------- #include "kmaccount.moc" //----------------------------------------------------------------------------- KMPrecommand::KMPrecommand(const TQString &precommand, TQObject *parent) : TQObject(parent), mPrecommand(precommand) { BroadcastStatus::instance()->setStatusMsg( i18n("Executing precommand %1").arg(precommand )); mPrecommandProcess.setUseShell(true); mPrecommandProcess << precommand; connect(&mPrecommandProcess, TQT_SIGNAL(processExited(TDEProcess *)), TQT_SLOT(precommandExited(TDEProcess *))); } //----------------------------------------------------------------------------- KMPrecommand::~KMPrecommand() { } //----------------------------------------------------------------------------- bool KMPrecommand::start() { bool ok = mPrecommandProcess.start( TDEProcess::NotifyOnExit ); if (!ok) KMessageBox::error(0, i18n("Could not execute precommand '%1'.") .arg(mPrecommand)); return ok; } //----------------------------------------------------------------------------- void KMPrecommand::precommandExited(TDEProcess *p) { int exitCode = p->normalExit() ? p->exitStatus() : -1; if (exitCode) KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2") .arg(exitCode).arg(strerror(exitCode))); emit finished(!exitCode); } //----------------------------------------------------------------------------- KMAccount::KMAccount(AccountManager* aOwner, const TQString& aName, uint id) : KAccount( id, aName ), mTrash(KMKernel::self()->trashFolder()->idString()), mOwner(aOwner), mFolder(0), mTimer(0), mInterval(0), mExclude(false), mCheckingMail(false), mPrecommandSuccess(true), mHasInbox(false), mMailCheckProgressItem(0), mIdentityId(0) { assert(aOwner != 0); } void KMAccount::init() { mTrash = kmkernel->trashFolder()->idString(); mExclude = false; mInterval = 0; mNewInFolder.clear(); } //----------------------------------------------------------------------------- KMAccount::~KMAccount() { if ( (kmkernel && !kmkernel->shuttingDown()) && mFolder ) mFolder->removeAccount(this); if (mTimer) deinstallTimer(); } //----------------------------------------------------------------------------- void KMAccount::setName(const TQString& aName) { mName = aName; } //----------------------------------------------------------------------------- void KMAccount::clearPasswd() { } //----------------------------------------------------------------------------- void KMAccount::setFolder(KMFolder* aFolder, bool addAccount) { if(!aFolder) { //kdDebug(5006) << "KMAccount::setFolder() : aFolder == 0" << endl; mFolder = 0; return; } mFolder = (KMAcctFolder*)aFolder; if (addAccount) mFolder->addAccount(this); } //----------------------------------------------------------------------------- void KMAccount::readConfig(TDEConfig& config) { TQString folderName; mFolder = 0; folderName = config.readEntry("Folder"); setCheckInterval(config.readNumEntry("check-interval", 0)); setTrash(config.readEntry("trash", kmkernel->trashFolder()->idString())); setCheckExclude(config.readBoolEntry("check-exclude", false)); setPrecommand(config.readPathEntry("precommand")); setIdentityId(config.readNumEntry("identity-id", 0)); if (!folderName.isEmpty()) { setFolder(kmkernel->folderMgr()->findIdString(folderName), true); } if (mInterval == 0) deinstallTimer(); else installTimer(); } void KMAccount::readTimerConfig() { // Re-reads and checks check-interval value and deinstalls timer incase check-interval // for mail check is disabled. // Or else, the mail sync goes into a infinite loop (kolab/issue2607) if (mInterval == 0) deinstallTimer(); else installTimer(); } //----------------------------------------------------------------------------- void KMAccount::writeConfig(TDEConfig& config) { // ID, Name KAccount::writeConfig(config); config.writeEntry("Type", type()); config.writeEntry("Folder", mFolder ? mFolder->idString() : TQString()); config.writeEntry("check-interval", mInterval); config.writeEntry("check-exclude", mExclude); config.writePathEntry("precommand", mPrecommand); config.writeEntry("trash", mTrash); if ( mIdentityId && mIdentityId != kmkernel->identityManager()->defaultIdentity().uoid() ) config.writeEntry("identity-id", mIdentityId); else config.deleteEntry("identity-id"); } //----------------------------------------------------------------------------- void KMAccount::sendReceipt(KMMessage* aMsg) { TDEConfig* cfg = KMKernel::config(); bool sendReceipts; TDEConfigGroupSaver saver(cfg, "General"); sendReceipts = cfg->readBoolEntry("send-receipts", false); if (!sendReceipts) return; KMMessage *newMsg = aMsg->createDeliveryReceipt(); if (newMsg) { mReceipts.append(newMsg); TQTimer::singleShot( 0, this, TQT_SLOT( sendReceipts() ) ); } } //----------------------------------------------------------------------------- bool KMAccount::processNewMsg(KMMessage* aMsg) { int rc, processResult; assert(aMsg != 0); // Save this one for readding KMFolderCachedImap* parent = 0; if( type() == "cachedimap" ) parent = static_cast( aMsg->storage() ); // checks whether we should send delivery receipts // and sends them. sendReceipt(aMsg); // Set status of new messages that are marked as old to read, otherwise // the user won't see which messages newly arrived. // This is only valid for pop accounts and produces wrong stati for imap. if ( type() != "cachedimap" && type() != "imap" ) { if ( aMsg->isOld() ) aMsg->setStatus(KMMsgStatusUnread); // -sanders // aMsg->setStatus(KMMsgStatusRead); else aMsg->setStatus(KMMsgStatusNew); } /* TQFile fileD0( "testdat_xx-kmaccount-0" ); if( fileD0.open( IO_WriteOnly ) ) { TQDataStream ds( &fileD0 ); ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() ); fileD0.close(); // If data is 0 we just create a zero length file. } */ // 0==message moved; 1==processing ok, no move; 2==critical error, abort! processResult = kmkernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound,true,id()); if (processResult == 2) { perror("Critical error: Unable to collect mail (out of space?)"); KMessageBox::information(0,(i18n("Critical error: " "Unable to collect mail: ")) + TQString::fromLocal8Bit(strerror(errno))); return false; } else if (processResult == 1) { if( type() == "cachedimap" ) ; // already done by caller: parent->addMsgInternal( aMsg, false ); else { // TODO: Perhaps it would be best, if this if was handled by a virtual // method, so the if( !dimap ) above could die? kmkernel->filterMgr()->tempOpenFolder(mFolder); rc = mFolder->addMsg(aMsg); /* TQFile fileD0( "testdat_xx-kmaccount-1" ); if( fileD0.open( IO_WriteOnly ) ) { TQDataStream ds( &fileD0 ); ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() ); fileD0.close(); // If data is 0 we just create a zero length file. } */ if (rc) { perror("failed to add message"); KMessageBox::information(0, i18n("Failed to add message:\n") + TQString(strerror(rc))); return false; } int count = mFolder->count(); // If count == 1, the message is immediately displayed if (count != 1) mFolder->unGetMsg(count - 1); } } // Count number of new messages for each folder TQString folderId; if ( processResult == 1 ) { folderId = ( type() == "cachedimap" ) ? parent->folder()->idString() : mFolder->idString(); } else { folderId = aMsg->parent()->idString(); } addToNewInFolder( folderId, 1 ); return true; //Everything's fine - message has been added by filter } } //----------------------------------------------------------------------------- void KMAccount::setCheckInterval(int aInterval) { if (aInterval <= 0) mInterval = 0; else mInterval = aInterval; // Don't call installTimer from here! See #117935. } int KMAccount::checkInterval() const { if ( mInterval <= 0 ) return mInterval; return TQMAX( mInterval, GlobalSettings::self()->minimumCheckInterval() ); } //---------------------------------------------------------------------------- void KMAccount::deleteFolderJobs() { mJobList.setAutoDelete(true); mJobList.clear(); mJobList.setAutoDelete(false); } //---------------------------------------------------------------------------- void KMAccount::ignoreJobsForMessage( KMMessage* msg ) { //FIXME: remove, make folders handle those for( TQPtrListIterator it(mJobList); it.current(); ++it ) { if ( it.current()->msgList().first() == msg) { FolderJob *job = it.current(); mJobList.remove( job ); delete job; break; } } } //----------------------------------------------------------------------------- void KMAccount::setCheckExclude(bool aExclude) { mExclude = aExclude; } //----------------------------------------------------------------------------- void KMAccount::installTimer() { if (mInterval <= 0) return; if(!mTimer) { mTimer = new TQTimer(0, "mTimer"); connect(mTimer,TQT_SIGNAL(timeout()),TQT_SLOT(mailCheck())); } else { mTimer->stop(); } mTimer->start( checkInterval() * 60000 ); } //----------------------------------------------------------------------------- void KMAccount::deinstallTimer() { delete mTimer; mTimer = 0; } //----------------------------------------------------------------------------- bool KMAccount::runPrecommand(const TQString &precommand) { // Run the pre command if there is one if ( precommand.isEmpty() ) return true; KMPrecommand precommandProcess(precommand, this); BroadcastStatus::instance()->setStatusMsg( i18n("Executing precommand %1").arg(precommand )); connect(&precommandProcess, TQT_SIGNAL(finished(bool)), TQT_SLOT(precommandExited(bool))); kdDebug(5006) << "Running precommand " << precommand << endl; if (!precommandProcess.start()) return false; kapp->eventLoop()->enterLoop(); return mPrecommandSuccess; } //----------------------------------------------------------------------------- void KMAccount::precommandExited(bool success) { mPrecommandSuccess = success; kapp->eventLoop()->exitLoop(); } //----------------------------------------------------------------------------- void KMAccount::mailCheck() { if (mTimer) mTimer->stop(); if ( kmkernel ) { AccountManager *acctmgr = kmkernel->acctMgr(); if ( acctmgr ) acctmgr->singleCheckMail(this, false); } } //----------------------------------------------------------------------------- void KMAccount::sendReceipts() { TQValueList::Iterator it; for(it = mReceipts.begin(); it != mReceipts.end(); ++it) kmkernel->msgSender()->send(*it); //might process events mReceipts.clear(); } //----------------------------------------------------------------------------- TQString KMAccount::encryptStr(const TQString &aStr) { TQString result; for (uint i = 0; i < aStr.length(); i++) /* yes, no typo. can't encode ' ' or '!' because they're the unicode BOM. stupid scrambling. stupid. */ result += (aStr[i].unicode() <= 0x21 ) ? aStr[i] : TQChar(0x1001F - aStr[i].unicode()); return result; } //----------------------------------------------------------------------------- TQString KMAccount::importPassword(const TQString &aStr) { unsigned int i, val; unsigned int len = aStr.length(); TQCString result; result.resize(len+1); for (i=0; iname() ); setId( a->id() ); setCheckInterval( a->checkInterval() ); setCheckExclude( a->checkExclude() ); setFolder( a->folder() ); setPrecommand( a->precommand() ); setTrash( a->trash() ); setIdentityId( a->identityId() ); } //----------------------------------------------------------------------------- void KMAccount::checkDone( bool newmail, CheckStatus status ) { setCheckingMail( false ); // Reset the timeout for automatic mailchecking. The user might have // triggered the check manually. if (mTimer) mTimer->start( checkInterval() * 60000 ); if ( mMailCheckProgressItem ) { // set mMailCheckProgressItem = 0 before calling setComplete() to prevent // a race condition ProgressItem *savedMailCheckProgressItem = mMailCheckProgressItem; mMailCheckProgressItem = 0; savedMailCheckProgressItem->setComplete(); // that will delete it } emit newMailsProcessed( mNewInFolder ); emit finishedCheck( newmail, status ); mNewInFolder.clear(); } //----------------------------------------------------------------------------- void KMAccount::addToNewInFolder( TQString folderId, int num ) { if ( mNewInFolder.find( folderId ) == mNewInFolder.end() ) mNewInFolder[folderId] = num; else mNewInFolder[folderId] += num; }