int KMFilterMgr::process(Q_UINT32 serNum, const KMFilter *filter) { bool stopIt = false; int result = 1; if(!filter) return 1; if(isMatching(serNum, filter)) { KMFolder *folder = 0; int idx = -1; // get the message with the serNum KMMsgDict::instance()->getLocation(serNum, &folder, &idx); if(!folder || (idx == -1) || (idx >= folder->count())) { return 1; } KMFolderOpener openFolder(folder, "filtermgr"); KMMsgBase *msgBase = folder->getMsgBase(idx); bool unGet = !msgBase->isMessage(); KMMessage *msg = folder->getMsg(idx); // do the actual filtering stuff if(!msg || !beginFiltering(msg)) { if(unGet) folder->unGetMsg(idx); return 1; } if(filter->execActions(msg, stopIt) == KMFilter::CriticalError) { if(unGet) folder->unGetMsg(idx); return 2; } KMFolder *targetFolder = MessageProperty::filterFolder(msg); endFiltering(msg); if(targetFolder) { tempOpenFolder(targetFolder); msg->setTransferInProgress(false); result = targetFolder->moveMsg(msg); msg->setTransferInProgress(true); } if(unGet) folder->unGetMsg(idx); } else { result = 1; } return result; }
int KMFilterMgr::process(KMMessage *msg, const KMFilter *filter) { if(!msg || !filter || !beginFiltering(msg)) return 1; bool stopIt = false; int result = 1; if(FilterLog::instance()->isLogging()) { QString logText(i18n("<b>Evaluating filter rules:</b> ")); logText.append(filter->pattern()->asString()); FilterLog::instance()->add(logText, FilterLog::patternDesc); } if(filter->pattern()->matches(msg)) { if(FilterLog::instance()->isLogging()) { FilterLog::instance()->add(i18n("<b>Filter rules have matched.</b>"), FilterLog::patternResult); } if(filter->execActions(msg, stopIt) == KMFilter::CriticalError) return 2; KMFolder *folder = MessageProperty::filterFolder(msg); endFiltering(msg); if(folder) { tempOpenFolder(folder); result = folder->moveMsg(msg); } } else { endFiltering(msg); result = 1; } return result; }
//----------------------------------------------------------------------------- int KMFolder::compact(void) { KMFolder* tempFolder; KMMessage* msg; QString tempName, msgStr; int openCount = mOpenCount; int num, numStatus; if (!needsCompact) { //debug ("Not compacting %s; it's clean", name().data()); return 0; } debug ("Compacting %s ", name().data()); tempName = "." + name(); tempName.detach(); tempName += ".compacted"; unlink(tempName); //tempFolder = parent()->createFolder(tempName); //sven: shouldn't be in list tempFolder = new KMFolder(parent(), tempName); //sven: we create it if(tempFolder->create()) { debug("KMFolder::compact() Creating tempFolder failed!\n"); delete tempFolder; //sven: and we delete it return 0; } quiet(TRUE); tempFolder->open(); open(); for(num=1,numStatus=9; count() > 0; num++, numStatus--) { if (numStatus <= 0) { msgStr.sprintf(i18n("Compacting folder: %d messages done"), num); emit statusMsg(msgStr); numStatus = 10; } msg = getMsg(0); if(msg) tempFolder->moveMsg(msg); } tempName = tempFolder->location(); tempFolder->close(TRUE); close(TRUE); mMsgList.clear(TRUE); _rename(tempName, location()); _rename(tempFolder->indexLocation(), indexLocation()); // Now really free all memory delete tempFolder; //sven: we delete it, not the manager if (openCount > 0) { open(); mOpenCount = openCount; } quiet(FALSE); if (!mQuiet) emit changed(); needsCompact = false; // We are clean now return 0; }
int KMFilterMgr::process(KMMessage *msg, FilterSet set, bool account, uint accountId) { if(bPopFilter) return processPop(msg); if(set == NoSet) { kdDebug(5006) << "KMFilterMgr: process() called with not filter set selected" << endl; return 1; } bool stopIt = false; bool atLeastOneRuleMatched = false; if(!beginFiltering(msg)) return 1; for(QValueListConstIterator<KMFilter *> it = mFilters.constBegin(); !stopIt && it != mFilters.constEnd() ; ++it) { if((((set & Inbound) && (*it)->applyOnInbound()) && (!account || (account && (*it)->applyOnAccount(accountId)))) || ((set & Outbound) && (*it)->applyOnOutbound()) || ((set & Explicit) && (*it)->applyOnExplicit())) { // filter is applicable if(FilterLog::instance()->isLogging()) { QString logText(i18n("<b>Evaluating filter rules:</b> ")); logText.append((*it)->pattern()->asString()); FilterLog::instance()->add(logText, FilterLog::patternDesc); } if((*it)->pattern()->matches(msg)) { // filter matches if(FilterLog::instance()->isLogging()) { FilterLog::instance()->add(i18n("<b>Filter rules have matched.</b>"), FilterLog::patternResult); } atLeastOneRuleMatched = true; // execute actions: if((*it)->execActions(msg, stopIt) == KMFilter::CriticalError) return 2; } } } KMFolder *folder = MessageProperty::filterFolder(msg); /* endFilter does a take() and addButKeepUID() to ensure the changed * message is on disk. This is unnessecary if nothing matched, so just * reset state and don't update the listview at all. */ if(atLeastOneRuleMatched) endFiltering(msg); else MessageProperty::setFiltering(msg, false); if(folder) { tempOpenFolder(folder); folder->moveMsg(msg); return 0; } return 1; }
//----------------------------------------------------------------------------- void KMSender::doSendMsg() { if(!kmkernel) //To handle message sending in progress when kaplan is exited return; //TODO: handle this case better const bool someSent = mCurrentMsg; if(someSent) { mSentMessages++; mSentBytes += mCurrentMsg->msgSize(); } // Post-process sent message (filtering) KMFolder *sentFolder = 0, *imapSentFolder = 0; if(mCurrentMsg && kmkernel->filterMgr()) { mCurrentMsg->setTransferInProgress(false); if(mCurrentMsg->hasUnencryptedMsg()) { kdDebug(5006) << "KMSender::doSendMsg() post-processing: replace mCurrentMsg body by unencryptedMsg data" << endl; // delete all current body parts mCurrentMsg->deleteBodyParts(); // copy Content-[..] headers from unencrypted message to current one KMMessage &newMsg(*mCurrentMsg->unencryptedMsg()); mCurrentMsg->dwContentType() = newMsg.dwContentType(); mCurrentMsg->setContentTransferEncodingStr(newMsg.contentTransferEncodingStr()); QCString newDispo = newMsg.headerField("Content-Disposition").latin1(); if(newDispo.isEmpty()) mCurrentMsg->removeHeaderField("Content-Disposition"); else mCurrentMsg->setHeaderField("Content-Disposition", newDispo); // copy the body mCurrentMsg->setBody(newMsg.body()); // copy all the body parts KMMessagePart msgPart; for(int i = 0; i < newMsg.numBodyParts(); ++i) { newMsg.bodyPart(i, &msgPart); mCurrentMsg->addBodyPart(&msgPart); } } mCurrentMsg->setStatus(KMMsgStatusSent); mCurrentMsg->setStatus(KMMsgStatusRead); // otherwise it defaults to new on imap mCurrentMsg->updateAttachmentState(); const KPIM::Identity &id = kmkernel->identityManager() ->identityForUoidOrDefault(mCurrentMsg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt()); if(!mCurrentMsg->fcc().isEmpty()) { sentFolder = kmkernel->folderMgr()->findIdString(mCurrentMsg->fcc()); if(sentFolder == 0) // This is *NOT* supposed to be imapSentFolder! sentFolder = kmkernel->dimapFolderMgr()->findIdString(mCurrentMsg->fcc()); if(sentFolder == 0) imapSentFolder = kmkernel->imapFolderMgr()->findIdString(mCurrentMsg->fcc()); } // No, or no usable sentFolder, and no, or no usable imapSentFolder, // let's try the on in the identity if((sentFolder == 0 || sentFolder->isReadOnly()) && (imapSentFolder == 0 || imapSentFolder->isReadOnly()) && !id.fcc().isEmpty()) { sentFolder = kmkernel->folderMgr()->findIdString(id.fcc()); if(sentFolder == 0) // This is *NOT* supposed to be imapSentFolder! sentFolder = kmkernel->dimapFolderMgr()->findIdString(id.fcc()); if(sentFolder == 0) imapSentFolder = kmkernel->imapFolderMgr()->findIdString(id.fcc()); } if(imapSentFolder && (imapSentFolder->noContent() || imapSentFolder->isReadOnly())) imapSentFolder = 0; if(sentFolder == 0 || sentFolder->isReadOnly()) sentFolder = kmkernel->sentFolder(); if(sentFolder) { if(const int err = sentFolder->open("sentFolder")) { Q_UNUSED(err); cleanup(); return; } } // Disable the emitting of msgAdded signal, because the message is taken out of the // current folder (outbox) and re-added, to make filter actions changing the message // work. We don't want that to screw up message counts. if(mCurrentMsg->parent()) mCurrentMsg->parent()->quiet(true); const int processResult = kmkernel->filterMgr()->process(mCurrentMsg, KMFilterMgr::Outbound); if(mCurrentMsg->parent()) mCurrentMsg->parent()->quiet(false); // 0==processed ok, 1==no filter matched, 2==critical error, abort! switch(processResult) { case 2: perror("Critical error: Unable to process sent mail (out of space?)"); KMessageBox::information(0, i18n("Critical error: " "Unable to process sent mail (out of space?)" "Moving failing message to \"sent-mail\" folder.")); if(sentFolder) { sentFolder->moveMsg(mCurrentMsg); sentFolder->close("sentFolder"); } cleanup(); return; case 1: if(sentFolder && sentFolder->moveMsg(mCurrentMsg) != 0) { KMessageBox::error(0, i18n("Moving the sent message \"%1\" from the " "\"outbox\" to the \"sent-mail\" folder failed.\n" "Possible reasons are lack of disk space or write permission. " "Please try to fix the problem and move the message manually.") .arg(mCurrentMsg->subject())); cleanup(); return; } if(imapSentFolder) { // Does proper folder refcounting and message locking KMCommand *command = new KMMoveCommand(imapSentFolder, mCurrentMsg); command->keepFolderOpen(sentFolder); // will open it, and close it once done command->start(); } default: break; } setStatusByLink(mCurrentMsg); if(mCurrentMsg->parent() && !imapSentFolder) { // for speed optimization, this code assumes that mCurrentMsg is the // last one in it's parent folder; make sure that's really the case: assert(mCurrentMsg->parent()->find(mCurrentMsg) == mCurrentMsg->parent()->count() - 1); // unGet this message: mCurrentMsg->parent()->unGetMsg(mCurrentMsg->parent()->count() - 1); } mCurrentMsg = 0; } // See if there is another queued message mCurrentMsg = mOutboxFolder->getMsg(mFailedMessages); if(mCurrentMsg && !mCurrentMsg->transferInProgress() && mCurrentMsg->sender().isEmpty()) { // if we do not have a sender address then use the email address of the // message's identity or of the default identity unless those two are also // empty const KPIM::Identity &id = kmkernel->identityManager() ->identityForUoidOrDefault(mCurrentMsg->headerField("X-KMail-Identity").stripWhiteSpace().toUInt()); if(!id.emailAddr().isEmpty()) { mCurrentMsg->setFrom(id.fullEmailAddr()); } else if(!kmkernel->identityManager()->defaultIdentity().emailAddr().isEmpty()) { mCurrentMsg->setFrom(kmkernel->identityManager()->defaultIdentity().fullEmailAddr()); } else { KMessageBox::sorry(0, i18n("It's not possible to send messages " "without specifying a sender address.\n" "Please set the email address of " "identity '%1' in the Identities " "section of the configuration dialog " "and then try again.") .arg(id.identityName())); mOutboxFolder->unGetMsg(mFailedMessages); mCurrentMsg = 0; } } if(!mCurrentMsg || mCurrentMsg->transferInProgress()) { // a message is locked finish the send if(mCurrentMsg && mCurrentMsg->transferInProgress()) mCurrentMsg = 0; // no more message: cleanup and done if(sentFolder != 0) sentFolder->close("sentFolder"); if(someSent) { if(mSentMessages == mTotalMessages) { setStatusMsg(i18n("%n queued message successfully sent.", "%n queued messages successfully sent.", mSentMessages)); } else { setStatusMsg(i18n("%1 of %2 queued messages successfully sent.") .arg(mSentMessages).arg(mTotalMessages)); } } cleanup(); return; } mCurrentMsg->setTransferInProgress(true); // start the sender process or initialize communication if(!mSendInProgress) { Q_ASSERT(!mProgressItem); mProgressItem = KPIM::ProgressManager::createProgressItem( "Sender", i18n("Sending messages"), i18n("Initiating sender process..."), true); connect(mProgressItem, SIGNAL(progressItemCanceled(KPIM::ProgressItem *)), this, SLOT(slotAbortSend())); kapp->ref(); mSendInProgress = true; }