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.
501 lines
14 KiB
501 lines
14 KiB
// KMail Account
|
|
#include <config.h>
|
|
|
|
#include "kmaccount.h"
|
|
|
|
#include "accountmanager.h"
|
|
using KMail::AccountManager;
|
|
#include "globalsettings.h"
|
|
#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 <libkpimidentities/identitymanager.h>
|
|
#include <libkpimidentities/identity.h>
|
|
|
|
using KMail::FolderJob;
|
|
|
|
#include <kapplication.h>
|
|
#include <klocale.h>
|
|
#include <kmessagebox.h>
|
|
#include <kdebug.h>
|
|
#include <kconfig.h>
|
|
|
|
#include <tqeventloop.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
|
|
#include <assert.h>
|
|
|
|
//----------------------
|
|
#include "kmaccount.moc"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
KMPrecommand::KMPrecommand(const TQString &precommand, TQObject *parent)
|
|
: TQObject(parent), mPrecommand(precommand)
|
|
{
|
|
BroadcastStatus::instance()->seStatusMsg(
|
|
i18n("Executing precommand %1").tqarg(precommand ));
|
|
|
|
mPrecommandProcess.setUseShell(true);
|
|
mPrecommandProcess << precommand;
|
|
|
|
connect(&mPrecommandProcess, TQT_SIGNAL(processExited(KProcess *)),
|
|
TQT_SLOT(precommandExited(KProcess *)));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
KMPrecommand::~KMPrecommand()
|
|
{
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool KMPrecommand::start()
|
|
{
|
|
bool ok = mPrecommandProcess.start( KProcess::NotifyOnExit );
|
|
if (!ok) KMessageBox::error(0, i18n("Could not execute precommand '%1'.")
|
|
.tqarg(mPrecommand));
|
|
return ok;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMPrecommand::precommandExited(KProcess *p)
|
|
{
|
|
int exitCode = p->normalExit() ? p->exitStatus() : -1;
|
|
if (exitCode)
|
|
KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2")
|
|
.tqarg(exitCode).tqarg(strerror(exitCode)));
|
|
emit finished(!exitCode);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
KMAccount::KMAccount(AccountManager* aOwner, const TQString& 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),
|
|
mHasInbox(false),
|
|
mMailCheckProgressItem(0),
|
|
mIdentityId(0)
|
|
{
|
|
assert(aOwner != 0);
|
|
}
|
|
|
|
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 TQString& aName)
|
|
{
|
|
mName = aName;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::clearPasswd()
|
|
{
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::setFolder(KMFolder* aFolder, bool addAccount)
|
|
{
|
|
if(!aFolder) {
|
|
//kdDebug(5006) << "KMAccount::setFolder() : aFolder == 0" << endl;
|
|
mFolder = 0;
|
|
return;
|
|
}
|
|
mFolder = (KMAcctFolder*)aFolder;
|
|
if (addAccount) mFolder->addAccount(this);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::readConfig(KConfig& config)
|
|
{
|
|
TQString folderName;
|
|
mFolder = 0;
|
|
folderName = config.readEntry("Folder");
|
|
setCheckInterval(config.readNumEntry("check-interval", 0));
|
|
setTrash(config.readEntry("trash", kmkernel->trashFolder()->idString()));
|
|
setCheckExclude(config.readBoolEntry("check-exclude", false));
|
|
setPrecommand(config.readPathEntry("precommand"));
|
|
setIdentityId(config.readNumEntry("identity-id", 0));
|
|
if (!folderName.isEmpty())
|
|
{
|
|
setFolder(kmkernel->folderMgr()->findIdString(folderName), true);
|
|
}
|
|
|
|
if (mInterval == 0)
|
|
deinstallTimer();
|
|
else
|
|
installTimer();
|
|
}
|
|
|
|
void KMAccount::readTimerConfig()
|
|
{
|
|
// Re-reads and checks check-interval value and deinstalls timer incase check-interval
|
|
// for mail check is disabled.
|
|
// Or else, the mail sync goes into a infinite loop (kolab/issue2607)
|
|
if (mInterval == 0)
|
|
deinstallTimer();
|
|
else
|
|
installTimer();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::writeConfig(KConfig& config)
|
|
{
|
|
// ID, Name
|
|
KAccount::writeConfig(config);
|
|
|
|
config.writeEntry("Type", type());
|
|
config.writeEntry("Folder", mFolder ? mFolder->idString() : TQString());
|
|
config.writeEntry("check-interval", mInterval);
|
|
config.writeEntry("check-exclude", mExclude);
|
|
config.writePathEntry("precommand", mPrecommand);
|
|
config.writeEntry("trash", mTrash);
|
|
if ( mIdentityId && mIdentityId != kmkernel->identityManager()->defaultIdentity().uoid() )
|
|
config.writeEntry("identity-id", mIdentityId);
|
|
else
|
|
config.deleteEntry("identity-id");
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::sendReceipt(KMMessage* aMsg)
|
|
{
|
|
KConfig* cfg = KMKernel::config();
|
|
bool sendReceipts;
|
|
|
|
KConfigGroupSaver saver(cfg, "General");
|
|
|
|
sendReceipts = cfg->readBoolEntry("send-receipts", false);
|
|
if (!sendReceipts) return;
|
|
|
|
KMMessage *newMsg = aMsg->createDeliveryReceipt();
|
|
if (newMsg) {
|
|
mReceipts.append(newMsg);
|
|
TQTimer::singleShot( 0, this, TQT_SLOT( sendReceipts() ) );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool KMAccount::processNewMsg(KMMessage* aMsg)
|
|
{
|
|
int rc, processResult;
|
|
|
|
assert(aMsg != 0);
|
|
|
|
// Save this one for readding
|
|
KMFolderCachedImap* parent = 0;
|
|
if( type() == "cachedimap" )
|
|
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() != "cachedimap" && type() != "imap" ) {
|
|
if ( aMsg->isOld() )
|
|
aMsg->setqStatus(KMMsgStatusUnread); // -sanders
|
|
// aMsg->setqStatus(KMMsgStatusRead);
|
|
else
|
|
aMsg->setqStatus(KMMsgStatusNew);
|
|
}
|
|
/*
|
|
TQFile fileD0( "testdat_xx-kmaccount-0" );
|
|
if( fileD0.open( IO_WriteOnly ) ) {
|
|
TQDataStream ds( &fileD0 );
|
|
ds.writeRawBytes( 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: ")) + TQString::fromLocal8Bit(strerror(errno)));
|
|
return false;
|
|
}
|
|
else if (processResult == 1)
|
|
{
|
|
if( type() == "cachedimap" )
|
|
; // 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);
|
|
/*
|
|
TQFile fileD0( "testdat_xx-kmaccount-1" );
|
|
if( fileD0.open( IO_WriteOnly ) ) {
|
|
TQDataStream ds( &fileD0 );
|
|
ds.writeRawBytes( 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") +
|
|
TQString(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
|
|
TQString folderId;
|
|
if ( processResult == 1 ) {
|
|
folderId = ( type() == "cachedimap" ) ? 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 TQMAX( mInterval, GlobalSettings::self()->minimumCheckInterval() );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void KMAccount::deleteFolderJobs()
|
|
{
|
|
mJobList.setAutoDelete(true);
|
|
mJobList.clear();
|
|
mJobList.setAutoDelete(false);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void KMAccount::ignoreJobsForMessage( KMMessage* msg )
|
|
{
|
|
//FIXME: remove, make folders handle those
|
|
for( TQPtrListIterator<FolderJob> it(mJobList); it.current(); ++it ) {
|
|
if ( it.current()->msgList().first() == msg) {
|
|
FolderJob *job = it.current();
|
|
mJobList.remove( job );
|
|
delete job;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::setCheckExclude(bool aExclude)
|
|
{
|
|
mExclude = aExclude;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::installTimer()
|
|
{
|
|
if (mInterval <= 0) return;
|
|
if(!mTimer)
|
|
{
|
|
mTimer = new TQTimer(0, "mTimer");
|
|
connect(mTimer,TQT_SIGNAL(timeout()),TQT_SLOT(mailCheck()));
|
|
}
|
|
else
|
|
{
|
|
mTimer->stop();
|
|
}
|
|
mTimer->start( checkInterval() * 60000 );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::deinstallTimer()
|
|
{
|
|
delete mTimer;
|
|
mTimer = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool KMAccount::runPrecommand(const TQString &precommand)
|
|
{
|
|
// Run the pre command if there is one
|
|
if ( precommand.isEmpty() )
|
|
return true;
|
|
|
|
KMPrecommand precommandProcess(precommand, this);
|
|
|
|
BroadcastStatus::instance()->seStatusMsg(
|
|
i18n("Executing precommand %1").tqarg(precommand ));
|
|
|
|
connect(&precommandProcess, TQT_SIGNAL(finished(bool)),
|
|
TQT_SLOT(precommandExited(bool)));
|
|
|
|
kdDebug(5006) << "Running precommand " << precommand << endl;
|
|
if (!precommandProcess.start()) return false;
|
|
|
|
kapp->eventLoop()->enterLoop();
|
|
|
|
return mPrecommandSuccess;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::precommandExited(bool success)
|
|
{
|
|
mPrecommandSuccess = success;
|
|
kapp->eventLoop()->exitLoop();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::mailCheck()
|
|
{
|
|
if (mTimer)
|
|
mTimer->stop();
|
|
|
|
if ( kmkernel ) {
|
|
AccountManager *acctmgr = kmkernel->acctMgr();
|
|
if ( acctmgr )
|
|
acctmgr->singleCheckMail(this, false);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::sendReceipts()
|
|
{
|
|
TQValueList<KMMessage*>::Iterator it;
|
|
for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
|
|
kmkernel->msgSender()->send(*it); //might process events
|
|
mReceipts.clear();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
TQString KMAccount::encryptStr(const TQString &aStr)
|
|
{
|
|
TQString result;
|
|
for (uint i = 0; i < aStr.length(); i++)
|
|
/* yes, no typo. can't encode ' ' or '!' because
|
|
they're the tqunicode BOM. stupid scrambling. stupid. */
|
|
result += (aStr[i].tqunicode() <= 0x21 ) ? aStr[i] :
|
|
TQChar(0x1001F - aStr[i].tqunicode());
|
|
return result;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
TQString KMAccount::importPassword(const TQString &aStr)
|
|
{
|
|
unsigned int i, val;
|
|
unsigned int len = aStr.length();
|
|
TQCString result;
|
|
result.resize(len+1);
|
|
|
|
for (i=0; i<len; i++)
|
|
{
|
|
val = aStr[i] - ' ';
|
|
val = (255-' ') - val;
|
|
result[i] = (char)(val + ' ');
|
|
}
|
|
result[i] = '\0';
|
|
|
|
return encryptStr(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() );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::checkDone( bool newmail, ChecktqStatus 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 ) {
|
|
// set mMailCheckProgressItem = 0 before calling setComplete() to prevent
|
|
// a race condition
|
|
ProgressItem *savedMailCheckProgressItem = mMailCheckProgressItem;
|
|
mMailCheckProgressItem = 0;
|
|
savedMailCheckProgressItem->setComplete(); // that will delete it
|
|
}
|
|
|
|
emit newMailsProcessed( mNewInFolder );
|
|
emit finishedCheck( newmail, status );
|
|
mNewInFolder.clear();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void KMAccount::addToNewInFolder( TQString folderId, int num )
|
|
{
|
|
if ( mNewInFolder.find( folderId ) == mNewInFolder.end() )
|
|
mNewInFolder[folderId] = num;
|
|
else
|
|
mNewInFolder[folderId] += num;
|
|
}
|