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.
500 lines
14 KiB
500 lines
14 KiB
// KMail Account |
|
|
|
#include "kmaccount.h" |
|
|
|
#include "accountmanager.h" |
|
using KMail::AccountManager; |
|
#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 <kpimidentities/identitymanager.h> |
|
#include <kpimidentities/identity.h> |
|
|
|
using KMail::FolderJob; |
|
|
|
#include <klocale.h> |
|
#include <kmessagebox.h> |
|
#include <kdebug.h> |
|
#include <kconfig.h> |
|
#include <kconfiggroup.h> |
|
#include <kstringhandler.h> |
|
|
|
#include <QList> |
|
#include <QEventLoop> |
|
#include <QByteArray> |
|
|
|
#include <cstdlib> |
|
#include <unistd.h> |
|
#include <cerrno> |
|
|
|
#include <cassert> |
|
|
|
//---------------------- |
|
#include "kmaccount.moc" |
|
|
|
//----------------------------------------------------------------------------- |
|
KMPrecommand::KMPrecommand(const QString &precommand, QObject *parent) |
|
: QObject(parent), mPrecommand(precommand) |
|
{ |
|
BroadcastStatus::instance()->setStatusMsg( |
|
i18n("Executing precommand %1", precommand )); |
|
|
|
mPrecommandProcess.setShellCommand(precommand); |
|
|
|
connect(&mPrecommandProcess, SIGNAL(processFinished(int, QProcess::ExitStatus)), |
|
SLOT(precommandExited(int, QProcess::ExitStatus))); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
KMPrecommand::~KMPrecommand() |
|
{ |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMPrecommand::start() |
|
{ |
|
mPrecommandProcess.start(); |
|
const bool ok = mPrecommandProcess.waitForStarted(); |
|
if (!ok) KMessageBox::error(0, i18n("Could not execute precommand '%1'.", |
|
mPrecommand)); |
|
return ok; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMPrecommand::precommandExited(int exitCode, QProcess::ExitStatus) |
|
{ |
|
|
|
if (exitCode != 0) |
|
KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2", |
|
exitCode, strerror(exitCode))); |
|
emit finished(exitCode == 0); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
KMAccount::KMAccount(AccountManager* aOwner, const QString& 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), |
|
mUseDefaultIdentity(true), |
|
mHasInbox(false), |
|
mMailCheckProgressItem(0) |
|
{ |
|
assert(aOwner != 0); |
|
mIdentityId = kmkernel->identityManager()->defaultIdentity().uoid(); |
|
|
|
connect( kmkernel->identityManager(), SIGNAL( changed() ), |
|
this, SLOT( slotIdentitiesChanged() ) ); |
|
} |
|
|
|
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 QString& aName) |
|
{ |
|
mName = aName; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::clearPasswd() |
|
{ |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::setFolder(KMFolder* aFolder, bool addAccount) |
|
{ |
|
if(!aFolder) { |
|
//kDebug(5006) <<"KMAccount::setFolder() : aFolder == 0"; |
|
mFolder = 0; |
|
return; |
|
} |
|
mFolder = (KMAcctFolder*)aFolder; |
|
if (addAccount) mFolder->addAccount(this); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::readConfig(KConfigGroup& config) |
|
{ |
|
QString folderName; |
|
mFolder = 0; |
|
folderName = config.readEntry("Folder"); |
|
setCheckInterval(config.readEntry("check-interval", 0 ) ); |
|
setTrash(config.readEntry("trash", kmkernel->trashFolder()->idString())); |
|
setCheckExclude(config.readEntry("check-exclude", false ) ); |
|
setPrecommand(config.readPathEntry("precommand", QString())); |
|
|
|
uint defaultIdentity = kmkernel->identityManager()->defaultIdentity().uoid(); |
|
setIdentityId( config.readEntry( "identity-id", defaultIdentity ) ); |
|
mUseDefaultIdentity = config.readEntry( "use-default-identity", true ); |
|
slotIdentitiesChanged(); |
|
|
|
if ( !folderName.isEmpty() ) { |
|
setFolder (kmkernel->folderMgr()->findIdString( folderName ), true ); |
|
} |
|
|
|
if (mInterval == 0) |
|
deinstallTimer(); |
|
else |
|
installTimer(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::writeConfig(KConfigGroup& config) |
|
{ |
|
// ID, Name |
|
KAccount::writeConfig(config); |
|
|
|
config.writeEntry("Type", KAccount::nameForType( type() ) ); |
|
config.writeEntry("Folder", mFolder ? mFolder->idString() : QString()); |
|
config.writeEntry("check-interval", mInterval); |
|
config.writeEntry("check-exclude", mExclude); |
|
config.writePathEntry("precommand", mPrecommand); |
|
config.writeEntry("trash", mTrash); |
|
config.writeEntry( "use-default-identity", mUseDefaultIdentity ); |
|
config.writeEntry( "identity-id", mIdentityId ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::sendReceipt(KMMessage* aMsg) |
|
{ |
|
bool sendReceipts; |
|
|
|
KConfigGroup cfg( KMKernel::config(), "General" ); |
|
|
|
sendReceipts = cfg.readEntry("send-receipts", false ); |
|
if (!sendReceipts) return; |
|
|
|
KMMessage *newMsg = aMsg->createDeliveryReceipt(); |
|
if (newMsg) { |
|
mReceipts.append(newMsg); |
|
QTimer::singleShot( 0, this, SLOT( sendReceipts() ) ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMAccount::processNewMsg(KMMessage* aMsg) |
|
{ |
|
int rc, processResult; |
|
|
|
assert(aMsg != 0); |
|
|
|
// Save this one for readding |
|
KMFolderCachedImap* parent = 0; |
|
if( type() == KAccount::DImap ) |
|
parent = static_cast<KMFolderCachedImap*>( 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() != KAccount::DImap && type() != KAccount::Imap ) { |
|
if ( aMsg->status().isOld() ) |
|
aMsg->setStatus( MessageStatus::statusUnread() ); // -sanders |
|
// aMsg->setStatus( MessageStatus::statusRead() ); |
|
else |
|
aMsg->setStatus( MessageStatus::statusNew() ); |
|
} |
|
/* |
|
QFile fileD0( "testdat_xx-kmaccount-0" ); |
|
if( fileD0.open( QIODevice::WriteOnly ) ) { |
|
QDataStream ds( &fileD0 ); |
|
ds.writeRawData( 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: ")) + QString::fromLocal8Bit(strerror(errno))); |
|
return false; |
|
} |
|
else if (processResult == 1) |
|
{ |
|
if( type() == KAccount::DImap ) |
|
; // 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); |
|
/* |
|
QFile fileD0( "testdat_xx-kmaccount-1" ); |
|
if( fileD0.open( QIODevice::WriteOnly ) ) { |
|
QDataStream ds( &fileD0 ); |
|
ds.writeRawData( 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") + |
|
QString(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 |
|
QString folderId; |
|
if ( processResult == 1 ) { |
|
folderId = ( type() == KAccount::DImap ) ? 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 qMax( mInterval, GlobalSettings::self()->minimumCheckInterval() ); |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
void KMAccount::deleteFolderJobs() |
|
{ |
|
qDeleteAll( mJobList ); |
|
mJobList.clear(); |
|
} |
|
|
|
//---------------------------------------------------------------------------- |
|
void KMAccount::ignoreJobsForMessage( KMMessage* msg ) |
|
{ |
|
//FIXME: remove, make folders handle those |
|
QList<FolderJob*>::iterator it; |
|
for( it = mJobList.begin(); it != mJobList.end(); ++it ) { |
|
if ( (*it)->msgList().first() == msg) { |
|
FolderJob *job = (*it); |
|
it = mJobList.erase( it ); |
|
delete job; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::setCheckExclude(bool aExclude) |
|
{ |
|
mExclude = aExclude; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::installTimer() |
|
{ |
|
if (mInterval <= 0) return; |
|
if(!mTimer) |
|
{ |
|
mTimer = new QTimer(); |
|
connect(mTimer,SIGNAL(timeout()),SLOT(mailCheck())); |
|
} |
|
else |
|
{ |
|
mTimer->stop(); |
|
} |
|
mTimer->start( checkInterval() * 60000 ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::deinstallTimer() |
|
{ |
|
delete mTimer; |
|
mTimer = 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool KMAccount::runPrecommand(const QString &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", precommand )); |
|
|
|
connect(&precommandProcess, SIGNAL(finished(bool)), |
|
SLOT(precommandExited(bool))); |
|
|
|
kDebug(5006) <<"Running precommand" << precommand; |
|
if (!precommandProcess.start()) return false; |
|
|
|
QEventLoop ().exec(); |
|
|
|
return mPrecommandSuccess; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::precommandExited(bool success) |
|
{ |
|
mPrecommandSuccess = success; |
|
|
|
QEventLoop ().exit (); |
|
} |
|
|
|
void KMAccount::slotIdentitiesChanged() |
|
{ |
|
// Fall back to the default identity if the one used currently is invalid |
|
if ( kmkernel->identityManager()->identityForUoid( mIdentityId ).isNull() ) { |
|
mIdentityId = kmkernel->identityManager()->defaultIdentity().uoid(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::mailCheck() |
|
{ |
|
if (mTimer) |
|
mTimer->stop(); |
|
|
|
if ( kmkernel ) { |
|
AccountManager *acctmgr = kmkernel->acctMgr(); |
|
if ( acctmgr ) { |
|
acctmgr->singleCheckMail( this, false ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::sendReceipts() |
|
{ |
|
QList<KMMessage*>::Iterator it; |
|
for(it = mReceipts.begin(); it != mReceipts.end(); ++it) |
|
kmkernel->msgSender()->send(*it); //might process events |
|
mReceipts.clear(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
QString KMAccount::importPassword(const QString &aStr) |
|
{ |
|
unsigned int i, val; |
|
unsigned int len = aStr.length(); |
|
QByteArray result; |
|
result.resize(len); |
|
|
|
for (i=0; i<len; i++) |
|
{ |
|
val = aStr[i].toLatin1() - ' '; |
|
val = (255-' ') - val; |
|
result[i] = (char)(val + ' '); |
|
} |
|
result[i] = '\0'; |
|
|
|
return KStringHandler::obscure(result); |
|
} |
|
|
|
void KMAccount::invalidateIMAPFolders() |
|
{ |
|
// Default: Don't do anything. The IMAP account will handle it |
|
} |
|
|
|
void KMAccount::pseudoAssign( const KMAccount * a ) { |
|
if ( !a ) return; |
|
|
|
setName( a->name() ); |
|
setId( a->id() ); |
|
setCheckInterval( a->checkInterval() ); |
|
setCheckExclude( a->checkExclude() ); |
|
setFolder( a->folder() ); |
|
setPrecommand( a->precommand() ); |
|
setTrash( a->trash() ); |
|
setIdentityId( a->identityId() ); |
|
setUseDefaultIdentity( a->useDefaultIdentity() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
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 ) { |
|
mMailCheckProgressItem->setComplete(); // that will delete it |
|
mMailCheckProgressItem = 0; |
|
} |
|
|
|
emit newMailsProcessed( mNewInFolder ); |
|
emit finishedCheck( newmail, status ); |
|
mNewInFolder.clear(); |
|
} |
|
|
|
uint KMAccount::identityId() const |
|
{ |
|
if ( mUseDefaultIdentity ) |
|
return kmkernel->identityManager()->defaultIdentity().uoid(); |
|
else |
|
return mIdentityId; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void KMAccount::addToNewInFolder( const QString &folderId, int num ) |
|
{ |
|
if ( mNewInFolder.find( folderId ) == mNewInFolder.end() ) |
|
mNewInFolder[folderId] = num; |
|
else |
|
mNewInFolder[folderId] += num; |
|
}
|
|
|