ByeBye kmsender, you're the first victim of Akonadi.

svn path=/branches/work/akonadi-ports/kdepim/; revision=987696
wilder-work
Thomas McGuire 17 years ago
parent 457f89ccea
commit eb34f3c843
  1. 1
      CMakeLists.txt
  2. 777
      kmsender.cpp
  3. 139
      kmsender.h

@ -106,7 +106,6 @@ set(kmailprivate_LIB_SRCS
kmfolderdir.cpp
kmfoldermgr.cpp
kmfoldernode.cpp
kmsender.cpp
akonadisender.cpp
kmacctseldlg.cpp
kmfiltermgr.cpp

@ -1,777 +0,0 @@
/*
* 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 "stringutil.h"
#include <mimelib/mediatyp.h>
#include <mimelib/enum.h>
#include <mimelib/param.h>
static const QString SENDER_GROUP( "sending mail" );
using namespace KMail;
//-----------------------------------------------------------------------------
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();
}
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( StringUtil::generateMessageId( m->sender() ) );
}
}
//-----------------------------------------------------------------------------
bool KMSender::doSend(KMMessage *aMsg, short sendNow )
{
if ( !aMsg ) {
return false;
}
if ( !TransportManager::self()->checkTransport( 0 ) ) {
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 ( !TransportManager::self()->checkTransport( 0 ) ) {
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() << "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() ;
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>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
KMTrashMsgCommand *cmd =
new KMTrashMsgCommand( folder, folder->getMsg( index ) );
cmd->start();
} else {
folder->setStatus( index, status );
}
} else {
kWarning() <<"Cannot update linked message, it could not be found!";
}
}
}
#include "kmsender.moc"

@ -1,139 +0,0 @@
/*
* 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.
*/
#ifndef kmsender_h
#define kmsender_h
#include "messagesender.h"
#ifndef KDE_USE_FINAL
# ifndef REALLY_WANT_KMSENDER
# error Do not include kmsender.h, but messagesender.h.
# endif
#endif
#include <QByteArray>
#include <QString>
#include <QStringList>
#include <QMap>
#include <QObject>
class KMMessage;
class KMFolder;
class KJob;
namespace KPIM {
class ProgressItem;
}
namespace MailTransport {
class TransportJob;
}
class KMSender: public QObject, public KMail::MessageSender
{
Q_OBJECT
public:
KMSender();
~KMSender();
protected:
/** Send given message. The message is either queued or sent
immediately. The default behaviour, as selected with
setSendImmediate(), can be overwritten with the parameter
sendNow (by specifying true or false).
The sender takes ownership of the given message on success,
so DO NOT DELETE OR MODIFY the message further.
Returns true on success. */
bool doSend(KMMessage* msg, short sendNow);
/** Send queued messages, using the specified transport or the
* default, if none is given.
*/
bool doSendQueued( const QString& transport=QString() );
private:
/** Returns true if sending is in progress. */
bool sending() const { return mSendInProgress; }
public:
/** Shall messages be sent immediately (true), or shall they be
queued and sent later upon call of sendQueued() ? */
bool sendImmediate() const { return mSendImmediate; }
void setSendImmediate(bool);
/** Shall messages be sent quoted-printable encoded. No encoding
happens otherwise. */
bool sendQuotedPrintable() const { return mSendQuotedPrintable; }
void setSendQuotedPrintable(bool);
public:
/** Read configuration from global config. */
void readConfig();
/** Write configuration to global config with optional sync() */
void writeConfig(bool withSync=true);
private:
/** sets a status msg and emits statusMsg() */
void setStatusMsg(const QString&);
/** sets replied/forwarded status in the linked message for @p aMsg. */
void setStatusByLink(const KMMessage *aMsg);
private slots:
void slotResult( KJob* job );
/** This slot should be called when the mail sending progress changes.
It updates the progressbar. */
void slotProcessedSize( KJob *job, qulonglong size );
/** abort sending of the current message */
void slotAbortSend();
/** note when a msg gets added to outbox during sending */
void outboxMsgAdded(int idx);
private:
/** handle sending of messages */
void doSendMsg();
/** cleanup after sending */
void cleanup();
private:
bool mSendImmediate;
bool mSendQuotedPrintable;
MailTransport::TransportJob* mTransportJob;
QString mCustomTransport;
bool mSentOk, mSendAborted;
QString mErrorMsg;
QString mMethodStr;
bool mSendProcStarted;
bool mSendInProgress;
KMFolder *mOutboxFolder;
KMFolder *mSentFolder;
KMMessage * mCurrentMsg;
KPIM::ProgressItem* mProgressItem;
int mSentMessages, mTotalMessages;
int mSentBytes, mTotalBytes;
int mFailedMessages;
};
#endif /*kmsender_h*/
Loading…
Cancel
Save