bool MessageCopyHelper::inReadOnlyFolder(const QList< quint32 > & sernums)
{
  KMFolder *f = 0;
  int index;
  for ( QList<quint32>::ConstIterator it = sernums.begin(); it != sernums.end(); ++it ) {
    KMMsgDict::instance()->getLocation( *it, &f, &index );
    if ( !f ) // not found
      continue;
    if ( f->isReadOnly() )
      return true;
  }
  return false;
}
Exemple #2
0
//-----------------------------------------------------------------------------
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;
    }