You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

784 lines
25 KiB

/*
* kmail: KDE mail client
* Copyright (c) 1996-1998 Stefan Taferner <taferner@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define REALLY_WANT_KMSENDER
#include "kmsender.h"
#undef REALLY_WANT_KMSENDER
#include <kmime/kmime_header_parsing.h>
#include <QByteArray>
using namespace KMime::Types;
#include <kpimidentities/identity.h>
#include <kpimidentities/identitymanager.h>
#include <mailtransport/transport.h>
#include <mailtransport/transportjob.h>
#include <mailtransport/transportmanager.h>
using namespace MailTransport;
#include <kio/passworddialog.h>
#include <kio/scheduler.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <kdebug.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "globalsettings.h"
#include "kmfiltermgr.h"
#include "kcursorsaver.h"
#include "progressmanager.h"
#include "kmaccount.h"
#include "kmfolderindex.h"
#include "kmfoldermgr.h"
#include "kmmsgdict.h"
#include "kmmsgpart.h"
#include "protocols.h"
#include "kmcommands.h"
#include <mimelib/mediatyp.h>
#include <mimelib/enum.h>
#include <mimelib/param.h>
#define SENDER_GROUP "sending mail"
//-----------------------------------------------------------------------------
KMSender::KMSender()
: mTransportJob( 0 ), mOutboxFolder( 0 ), mSentFolder( 0 )
{
mSendProcStarted = false;
mSendInProgress = false;
mCurrentMsg = 0;
readConfig();
mSendAborted = false;
mSentMessages = 0;
mTotalMessages = 0;
mFailedMessages = 0;
mSentBytes = 0;
mTotalBytes = 0;
mProgressItem = 0;
}
//-----------------------------------------------------------------------------
KMSender::~KMSender()
{
writeConfig(false);
}
//-----------------------------------------------------------------------------
void KMSender::setStatusMsg(const QString &msg)
{
if ( mProgressItem )
mProgressItem->setStatus(msg);
}
//-----------------------------------------------------------------------------
void KMSender::readConfig(void)
{
QString str;
KConfigGroup config(KMKernel::config(), SENDER_GROUP);
mSendImmediate = config.readEntry( "Immediate", true );
mSendQuotedPrintable = config.readEntry( "Quoted-Printable", true );
}
//-----------------------------------------------------------------------------
void KMSender::writeConfig(bool aWithSync)
{
KConfigGroup config(KMKernel::config(), SENDER_GROUP);
config.writeEntry("Immediate", mSendImmediate);
config.writeEntry("Quoted-Printable", mSendQuotedPrintable);
if (aWithSync) config.sync();
}
//-----------------------------------------------------------------------------
bool KMSender::settingsOk() const
{
if ( TransportManager::self()->transportNames().isEmpty() ) {
KMessageBox::information( 0,
i18n("Please create an account for sending and try again.") );
return false;
}
return true;
}
static void handleRedirections( KMMessage *m ) {
const QString from = m->headerField( "X-KMail-Redirect-From" );
const QString msgId = m->msgId();
if ( from.isEmpty() || msgId.isEmpty() ) {
m->setMsgId( KMMessage::generateMessageId( m->sender() ) );
}
}
//-----------------------------------------------------------------------------
bool KMSender::doSend(KMMessage *aMsg, short sendNow )
{
if ( !aMsg ) {
return false;
}
if ( !settingsOk() ) {
return false;
}
if ( aMsg->to().isEmpty() ) {
// RFC822 says:
// Note that the "Bcc" field may be empty, while the "To" field is
// required to have at least one address.
//
// however:
//
// The following string is accepted according to RFC 2822,
// section 3.4 "Address Specification" where they say:
//
// "An address may either be an individual mailbox,
// or a group of mailboxes."
// and:
// "group + display-name ":" [mailbox-list / CFWS] ";"
// [CFWS]"
//
// In this syntax our "undisclosed-recipients: ;"
// just specifies an empty group.
//
// In further explanations RFC 2822 states that it *is*
// allowed to have a ZERO number of mailboxes in the "mailbox-list".
aMsg->setTo( "Undisclosed.Recipients: ;" );
}
handleRedirections( aMsg );
if ( sendNow == -1 ) {
sendNow = mSendImmediate;
}
KMFolder * const outbox = kmkernel->outboxFolder();
const KMFolderOpener openOutbox( outbox, "KMSender" );
aMsg->setStatus( MessageStatus::statusQueued() );
if ( const int err = openOutbox.folder()->addMsg( aMsg ) ) {
Q_UNUSED( err );
KMessageBox::information( 0, i18n("Cannot add message to outbox folder") );
return false;
}
//Ensure the message is correctly and fully parsed
openOutbox.folder()->unGetMsg( openOutbox.folder()->count() - 1 );
if ( !sendNow || mSendInProgress ) {
return true;
}
return sendQueued();
}
//-----------------------------------------------------------------------------
void KMSender::outboxMsgAdded( int idx )
{
++mTotalMessages;
KMMsgBase* msg = kmkernel->outboxFolder()->getMsgBase( idx );
Q_ASSERT( msg );
if ( msg ) {
mTotalBytes += msg->msgSize();
}
}
//-----------------------------------------------------------------------------
bool KMSender::doSendQueued( const QString &customTransport )
{
if ( !settingsOk() ) {
return false;
}
if ( mSendInProgress ) {
return false;
}
// open necessary folders
mOutboxFolder = kmkernel->outboxFolder();
mOutboxFolder->open( "dosendoutbox" );
mTotalMessages = mOutboxFolder->count();
if ( mTotalMessages == 0 ) {
// Nothing in the outbox. We are done.
mOutboxFolder->close( "dosendoutbox" );
mOutboxFolder = 0;
return true;
}
mTotalBytes = 0;
for( int i = 0 ; i<mTotalMessages ; ++i ) {
mTotalBytes += mOutboxFolder->getMsgBase(i)->msgSize();
}
connect( mOutboxFolder, SIGNAL( msgAdded( int ) ),
this, SLOT( outboxMsgAdded( int ) ) );
mCurrentMsg = 0;
mSentFolder = kmkernel->sentFolder();
mSentFolder->open( "dosendsent" );
kmkernel->filterMgr()->ref();
// start sending the messages
mCustomTransport = customTransport;
doSendMsg();
return true;
}
//-----------------------------------------------------------------------------
void KMSender::slotProcessedSize( KJob *, qulonglong size )
{
int percent = (mTotalBytes) ? ( 100 * (mSentBytes+size) / mTotalBytes ) : 0;
if (percent > 100) percent = 100;
mProgressItem->setProgress(percent);
}
static bool messageIsDispositionNotificationReport( KMMessage *msg )
{
if ( msg->type() == DwMime::kTypeMessage &&
msg->subtype() == DwMime::kSubtypeDispositionNotification )
return true;
if ( msg->type() != DwMime::kTypeMultipart ||
msg->subtype() != DwMime::kSubtypeReport )
return false;
DwMediaType& ct = msg->dwContentType();
DwParameter *param = ct.FirstParameter();
while( param ) {
if ( !qstricmp( param->Attribute().c_str(), "report-type")
&& !qstricmp( param->Value().c_str(), "disposition-notification" ) )
return true;
else
param = param->Next();
}
return false;
}
static QStringList addrSpecListToStringList( const AddrSpecList & l, bool allowEmpty=false ) {
QStringList result;
for ( AddrSpecList::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it ) {
const QString s = (*it).asString();
if ( allowEmpty || !s.isEmpty() )
result.push_back( s );
}
return result;
}
static void extractSenderToCCAndBcc( KMMessage * aMsg, QString * sender, QStringList * to, QStringList * cc, QStringList * bcc ) {
if ( sender ) *sender = aMsg->sender();
if( !aMsg->headerField("X-KMail-Recipients").isEmpty() ) {
// extended BCC handling to prevent TOs and CCs from seeing
// BBC information by looking at source of an OpenPGP encrypted mail
if ( to ) *to = addrSpecListToStringList( aMsg->extractAddrSpecs( "X-KMail-Recipients" ) );
aMsg->removeHeaderField( "X-KMail-Recipients" );
} else {
if ( to ) *to = addrSpecListToStringList( aMsg->extractAddrSpecs( "To" ) );
if ( cc ) *cc = addrSpecListToStringList( aMsg->extractAddrSpecs( "Cc" ) );
if ( bcc ) *bcc = addrSpecListToStringList( aMsg->extractAddrSpecs( "Bcc" ) );
}
}
//-----------------------------------------------------------------------------
void KMSender::doSendMsg()
{
if ( !kmkernel ) { //To handle message sending in progress when exiting
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() ) {
kDebug(5006) << "Post-processing: replace mCurrentMsg body by unencryptedMsg data";
// 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() );
QByteArray newDispo =
newMsg.headerField( "Content-Disposition" ).toLatin1();
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 );
}
}
MessageStatus status = MessageStatus::statusSent();
status.setRead(); // otherwise it defaults to new on imap
mCurrentMsg->setStatus( status );
mCurrentMsg->updateAttachmentState();
const KPIMIdentities::Identity & id =
kmkernel->identityManager()->identityForUoidOrDefault(
mCurrentMsg->headerField( "X-KMail-Identity" ).trimmed().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 ( 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->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.",
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 when 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 KPIMIdentities::Identity &id =
kmkernel->identityManager()->identityForUoidOrDefault(
mCurrentMsg->headerField( "X-KMail-Identity" ).trimmed().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 is 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.",
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(i18np("%1 queued message successfully sent.",
"%1 queued messages successfully sent.",
mSentMessages));
} else {
setStatusMsg(i18n("%1 of %2 queued messages successfully sent.",
mSentMessages, 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() ) );
KGlobal::ref();
mSendInProgress = true;
}
QString msgTransport = mCustomTransport;
if ( msgTransport.isEmpty() )
msgTransport = mCurrentMsg->headerField( "X-KMail-Transport" );
if ( msgTransport.isEmpty() )
msgTransport = TransportManager::self()->defaultTransportName();
if ( !mTransportJob ) {
mMethodStr = msgTransport;
mTransportJob = TransportManager::self()->createTransportJob( msgTransport );
if ( !mTransportJob ) {
KMessageBox::error( 0, i18n( "Transport '%1' is invalid.", mMethodStr ),
i18n( "Sending failed" ) );
mProgressItem->cancel();
mProgressItem->setComplete();
cleanup();
return;
}
if ( mTransportJob->transport()->encryption() == Transport::EnumEncryption::TLS ||
mTransportJob->transport()->encryption() == Transport::EnumEncryption::SSL ) {
mProgressItem->setUsesCrypto( true );
} else if ( !mCustomTransport.isEmpty() ) {
int result = KMessageBox::warningContinueCancel(
0,
i18n( "You have chosen to send all queued email using an unencrypted transport, do you want to continue? "),
i18n( "Security Warning" ),
KGuiItem( i18n( "Send Unencrypted" ) ),
KStandardGuiItem::cancel(),
"useCustomTransportWithoutAsking", false );
if ( result == KMessageBox::Cancel ) {
mProgressItem->cancel();
mProgressItem->setComplete();
slotAbortSend();
cleanup();
return;
}
}
setStatusMsg( i18nc("%3: subject of message","Sending message %1 of %2: %3",
mSentMessages+mFailedMessages+1, mTotalMessages,
mCurrentMsg->subject()) );
QStringList to, cc, bcc;
QString sender;
extractSenderToCCAndBcc( mCurrentMsg, &sender, &to, &cc, &bcc );
// MDNs are required to have an empty envelope from as per RFC2298.
if ( messageIsDispositionNotificationReport( mCurrentMsg ) && GlobalSettings::self()->sendMDNsWithEmptySender() )
sender = "<>";
const QByteArray message = mCurrentMsg->asSendableString();
if ( sender.isEmpty() ) {
if ( mCurrentMsg )
mCurrentMsg->setTransferInProgress( false );
if ( mOutboxFolder )
mOutboxFolder->unGetMsg( mFailedMessages );
mCurrentMsg = 0;
cleanup();
setStatusMsg(i18n("Failed to send (some) queued messages."));
return;
}
mTransportJob->setSender( sender );
mTransportJob->setTo( to );
mTransportJob->setCc( cc );
mTransportJob->setBcc( bcc );
mTransportJob->setData( message );
connect( mTransportJob, SIGNAL(result(KJob*)), SLOT(slotResult(KJob*)) );
connect( mTransportJob, SIGNAL(processedSize(KJob *, qulonglong)),
SLOT( slotProcessedSize(KJob *, qulonglong)) );
mSendProcStarted = true;
mTransportJob->start();
}
}
//-----------------------------------------------------------------------------
void KMSender::cleanup( void )
{
kDebug(5006) ;
if ( mTransportJob && mSendProcStarted ) {
mTransportJob->kill();
}
mTransportJob = 0;
mSendProcStarted = false;
if ( mSendInProgress ) {
KGlobal::deref();
}
mSendInProgress = false;
if ( mCurrentMsg ) {
mCurrentMsg->setTransferInProgress( false );
mCurrentMsg = 0;
}
if ( mSentFolder ) {
mSentFolder->close( "dosendsent" );
mSentFolder = 0;
}
if ( mOutboxFolder ) {
disconnect( mOutboxFolder, SIGNAL(msgAdded(int)),
this, SLOT(outboxMsgAdded(int)) );
mOutboxFolder->close( "dosendoutbox" );
if ( mOutboxFolder->count( true ) == 0 ) {
mOutboxFolder->expunge();
} else if ( mOutboxFolder->needsCompacting() ) {
mOutboxFolder->compact( KMFolder::CompactSilentlyNow );
}
mOutboxFolder = 0;
}
mSendAborted = false;
mSentMessages = 0;
mFailedMessages = 0;
mSentBytes = 0;
if ( mProgressItem ) {
mProgressItem->setComplete();
}
mProgressItem = 0;
kmkernel->filterMgr()->deref();
}
//-----------------------------------------------------------------------------
void KMSender::slotAbortSend()
{
mSendAborted = true;
if ( mTransportJob ) {
mTransportJob->kill( KJob::EmitResult );
}
}
//-----------------------------------------------------------------------------
void KMSender::slotResult( KJob *job )
{
assert( mTransportJob == job );
mTransportJob = 0;
mSendProcStarted = false;
QString msg;
QString errString = job->errorString();
if ( mSendAborted ) {
// sending of message aborted
if ( mCurrentMsg ) {
mCurrentMsg->setTransferInProgress( false );
if ( mOutboxFolder ) {
mOutboxFolder->unGetMsg( mFailedMessages );
}
mCurrentMsg = 0;
}
msg = i18n("Sending aborted:\n%1\n"
"The message will stay in the 'outbox' folder until you either "
"fix the problem (e.g. a broken address) or remove the message "
"from the 'outbox' folder.\n"
"The following transport was used:\n %2",
errString,
mMethodStr);
if (!errString.isEmpty()) KMessageBox::error(0,msg);
setStatusMsg( i18n( "Sending aborted." ) );
} else {
if ( job->error() ) {
if ( mCurrentMsg ) {
mCurrentMsg->setTransferInProgress( false );
}
if ( mOutboxFolder ) {
mOutboxFolder->unGetMsg( mFailedMessages );
}
mCurrentMsg = 0;
mFailedMessages++;
// Sending of message failed.
if ( !errString.isEmpty() ) {
int res = KMessageBox::Yes;
if ( mSentMessages+mFailedMessages != mTotalMessages ) {
msg = i18n("<p>Sending failed:</p>"
"<p>%1</p>"
"<p>The message will stay in the 'outbox' folder until you either "
"fix the problem (e.g. a broken address) or remove the message "
"from the 'outbox' folder.</p>"
"<p>The following transport was used: %2</p>"
"<p>Do you want me to continue sending the remaining messages?</p>",
errString,
mMethodStr);
res = KMessageBox::warningYesNo( 0, msg,
i18n( "Continue Sending" ), KGuiItem(i18n( "&Continue Sending" )),
KGuiItem(i18n("&Abort Sending")) );
} else {
msg = i18n("Sending failed:\n%1\n"
"The message will stay in the 'outbox' folder until you either "
"fix the problem (e.g. a broken address) or remove the message "
"from the 'outbox' folder.\n"
"The following transport was used:\n %2",
errString,
mMethodStr);
KMessageBox::error(0,msg);
}
if (res == KMessageBox::Yes) {
// Try the next one.
doSendMsg();
return;
} else {
setStatusMsg( i18n( "Sending aborted." ) );
}
}
} else {
// Sending suceeded.
doSendMsg();
return;
}
}
cleanup();
}
//-----------------------------------------------------------------------------
void KMSender::setSendImmediate(bool aSendImmediate)
{
mSendImmediate = aSendImmediate;
}
//-----------------------------------------------------------------------------
void KMSender::setSendQuotedPrintable(bool aSendQuotedPrintable)
{
mSendQuotedPrintable = aSendQuotedPrintable;
}
//-----------------------------------------------------------------------------
void KMSender::setStatusByLink( const KMMessage *aMsg )
{
int n = 0;
while ( 1 ) {
ulong msn;
MessageStatus status;
aMsg->getLink( n, &msn, status );
if ( !msn || status.isOfUnknownStatus() ) {
break;
}
n++;
KMFolder *folder = 0;
int index = -1;
KMMsgDict::instance()->getLocation( msn, &folder, &index );
if ( folder && index != -1 ) {
KMFolderOpener openFolder( folder, "setstatus" );
if ( status.isDeleted() ) {
// Move the message to the trash folder
KMDeleteMsgCommand *cmd =
new KMDeleteMsgCommand( folder, folder->getMsg( index ) );
cmd->start();
} else {
folder->setStatus( index, status );
}
} else {
kWarning(5006) <<"Cannot update linked message, it could not be found!";
}
}
}
#include "kmsender.moc"