kmail

kmaccount.cpp
1// KMail Account
2#include <config.h>
3
4#include "kmaccount.h"
5
6#include "accountmanager.h"
8#include "globalsettings.h"
9#include "kmacctfolder.h"
10#include "kmfoldermgr.h"
11#include "kmfiltermgr.h"
12#include "messagesender.h"
13#include "kmmessage.h"
14#include "broadcaststatus.h"
15using KPIM::BroadcastStatus;
16#include "kmfoldercachedimap.h"
17
18#include "progressmanager.h"
19using KPIM::ProgressItem;
20using KPIM::ProgressManager;
21
22#include <libkpimidentities/identitymanager.h>
23#include <libkpimidentities/identity.h>
24
25using KMail::FolderJob;
26
27#include <tdeapplication.h>
28#include <tdelocale.h>
29#include <tdemessagebox.h>
30#include <kdebug.h>
31#include <tdeconfig.h>
32
33#include <tqeventloop.h>
34
35#include <stdlib.h>
36#include <unistd.h>
37#include <errno.h>
38
39#include <assert.h>
40
41//----------------------
42#include "kmaccount.moc"
43
44//-----------------------------------------------------------------------------
45KMPrecommand::KMPrecommand(const TQString &precommand, TQObject *parent)
46 : TQObject(parent), mPrecommand(precommand)
47{
48 BroadcastStatus::instance()->setStatusMsg(
49 i18n("Executing precommand %1").arg(precommand ));
50
51 mPrecommandProcess.setUseShell(true);
52 mPrecommandProcess << precommand;
53
54 connect(&mPrecommandProcess, TQ_SIGNAL(processExited(TDEProcess *)),
55 TQ_SLOT(precommandExited(TDEProcess *)));
56}
57
58//-----------------------------------------------------------------------------
59KMPrecommand::~KMPrecommand()
60{
61}
62
63
64//-----------------------------------------------------------------------------
65bool KMPrecommand::start()
66{
67 bool ok = mPrecommandProcess.start( TDEProcess::NotifyOnExit );
68 if (!ok) KMessageBox::error(0, i18n("Could not execute precommand '%1'.")
69 .arg(mPrecommand));
70 return ok;
71}
72
73
74//-----------------------------------------------------------------------------
75void KMPrecommand::precommandExited(TDEProcess *p)
76{
77 int exitCode = p->normalExit() ? p->exitStatus() : -1;
78 if (exitCode)
79 KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2")
80 .arg(exitCode).arg(strerror(exitCode)));
81 emit finished(!exitCode);
82}
83
84
85//-----------------------------------------------------------------------------
86KMAccount::KMAccount(AccountManager* aOwner, const TQString& aName, uint id)
87 : KAccount( id, aName ),
88 mTrash(KMKernel::self()->trashFolder()->idString()),
89 mOwner(aOwner),
90 mFolder(0),
91 mTimer(0),
92 mInterval(0),
93 mExclude(false),
94 mCheckingMail(false),
95 mPrecommandSuccess(true),
96 mHasInbox(false),
97 mMailCheckProgressItem(0),
98 mIdentityId(0)
99{
100 assert(aOwner != 0);
101}
102
103void KMAccount::init() {
104 mTrash = kmkernel->trashFolder()->idString();
105 mExclude = false;
106 mInterval = 0;
107 mNewInFolder.clear();
108}
109
110//-----------------------------------------------------------------------------
111KMAccount::~KMAccount()
112{
113 if ( (kmkernel && !kmkernel->shuttingDown()) && mFolder ) mFolder->removeAccount(this);
114 if (mTimer) deinstallTimer();
115}
116
117
118//-----------------------------------------------------------------------------
119void KMAccount::setName(const TQString& aName)
120{
121 mName = aName;
122}
123
124
125//-----------------------------------------------------------------------------
126void KMAccount::clearPasswd()
127{
128}
129
130
131//-----------------------------------------------------------------------------
132void KMAccount::setFolder(KMFolder* aFolder, bool addAccount)
133{
134 if(!aFolder) {
135 //kdDebug(5006) << "KMAccount::setFolder() : aFolder == 0" << endl;
136 mFolder = 0;
137 return;
138 }
139 mFolder = (KMAcctFolder*)aFolder;
140 if (addAccount) mFolder->addAccount(this);
141}
142
143
144//-----------------------------------------------------------------------------
145void KMAccount::readConfig(TDEConfig& config)
146{
147 TQString folderName;
148 mFolder = 0;
149 folderName = config.readEntry("Folder");
150 setCheckInterval(config.readNumEntry("check-interval", 0));
151 setTrash(config.readEntry("trash", kmkernel->trashFolder()->idString()));
152 setCheckExclude(config.readBoolEntry("check-exclude", false));
153 setPrecommand(config.readPathEntry("precommand"));
154 setIdentityId(config.readNumEntry("identity-id", 0));
155 if (!folderName.isEmpty())
156 {
157 setFolder(kmkernel->folderMgr()->findIdString(folderName), true);
158 }
159
160 if (mInterval == 0)
161 deinstallTimer();
162 else
163 installTimer();
164}
165
166void KMAccount::readTimerConfig()
167{
168 // Re-reads and checks check-interval value and deinstalls timer incase check-interval
169 // for mail check is disabled.
170 // Or else, the mail sync goes into a infinite loop (kolab/issue2607)
171 if (mInterval == 0)
172 deinstallTimer();
173 else
174 installTimer();
175}
176
177//-----------------------------------------------------------------------------
178void KMAccount::writeConfig(TDEConfig& config)
179{
180 // ID, Name
181 KAccount::writeConfig(config);
182
183 config.writeEntry("Type", type());
184 config.writeEntry("Folder", mFolder ? mFolder->idString() : TQString());
185 config.writeEntry("check-interval", mInterval);
186 config.writeEntry("check-exclude", mExclude);
187 config.writePathEntry("precommand", mPrecommand);
188 config.writeEntry("trash", mTrash);
189 if ( mIdentityId && mIdentityId != kmkernel->identityManager()->defaultIdentity().uoid() )
190 config.writeEntry("identity-id", mIdentityId);
191 else
192 config.deleteEntry("identity-id");
193}
194
195
196//-----------------------------------------------------------------------------
197void KMAccount::sendReceipt(KMMessage* aMsg)
198{
199 TDEConfig* cfg = KMKernel::config();
200 bool sendReceipts;
201
202 TDEConfigGroupSaver saver(cfg, "General");
203
204 sendReceipts = cfg->readBoolEntry("send-receipts", false);
205 if (!sendReceipts) return;
206
207 KMMessage *newMsg = aMsg->createDeliveryReceipt();
208 if (newMsg) {
209 mReceipts.append(newMsg);
210 TQTimer::singleShot( 0, this, TQ_SLOT( sendReceipts() ) );
211 }
212}
213
214
215//-----------------------------------------------------------------------------
216bool KMAccount::processNewMsg(KMMessage* aMsg)
217{
218 int rc, processResult;
219
220 assert(aMsg != 0);
221
222 // Save this one for readding
223 KMFolderCachedImap* parent = 0;
224 if( type() == "cachedimap" )
225 parent = static_cast<KMFolderCachedImap*>( aMsg->storage() );
226
227 // checks whether we should send delivery receipts
228 // and sends them.
229 sendReceipt(aMsg);
230
231 // Set status of new messages that are marked as old to read, otherwise
232 // the user won't see which messages newly arrived.
233 // This is only valid for pop accounts and produces wrong stati for imap.
234 if ( type() != "cachedimap" && type() != "imap" ) {
235 if ( aMsg->isOld() )
236 aMsg->setStatus(KMMsgStatusUnread); // -sanders
237 // aMsg->setStatus(KMMsgStatusRead);
238 else
239 aMsg->setStatus(KMMsgStatusNew);
240 }
241/*
242TQFile fileD0( "testdat_xx-kmaccount-0" );
243if( fileD0.open( IO_WriteOnly ) ) {
244 TQDataStream ds( &fileD0 );
245 ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() );
246 fileD0.close(); // If data is 0 we just create a zero length file.
247}
248*/
249 // 0==message moved; 1==processing ok, no move; 2==critical error, abort!
250
251 processResult = kmkernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound,true,id());
252 if (processResult == 2) {
253 perror("Critical error: Unable to collect mail (out of space?)");
254 KMessageBox::information(0,(i18n("Critical error: "
255 "Unable to collect mail: ")) + TQString::fromLocal8Bit(strerror(errno)));
256 return false;
257 }
258 else if (processResult == 1)
259 {
260 if( type() == "cachedimap" )
261 ; // already done by caller: parent->addMsgInternal( aMsg, false );
262 else {
263 // TODO: Perhaps it would be best, if this if was handled by a virtual
264 // method, so the if( !dimap ) above could die?
265 kmkernel->filterMgr()->tempOpenFolder(mFolder);
266 rc = mFolder->addMsg(aMsg);
267/*
268TQFile fileD0( "testdat_xx-kmaccount-1" );
269if( fileD0.open( IO_WriteOnly ) ) {
270 TQDataStream ds( &fileD0 );
271 ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() );
272 fileD0.close(); // If data is 0 we just create a zero length file.
273}
274*/
275 if (rc) {
276 perror("failed to add message");
277 KMessageBox::information(0, i18n("Failed to add message:\n") +
278 TQString(strerror(rc)));
279 return false;
280 }
281 int count = mFolder->count();
282 // If count == 1, the message is immediately displayed
283 if (count != 1) mFolder->unGetMsg(count - 1);
284 }
285 }
286
287 // Count number of new messages for each folder
288 TQString folderId;
289 if ( processResult == 1 ) {
290 folderId = ( type() == "cachedimap" ) ? parent->folder()->idString()
291 : mFolder->idString();
292 }
293 else {
294 folderId = aMsg->parent()->idString();
295 }
296 addToNewInFolder( folderId, 1 );
297
298 return true; //Everything's fine - message has been added by filter }
299}
300
301//-----------------------------------------------------------------------------
302void KMAccount::setCheckInterval(int aInterval)
303{
304 if (aInterval <= 0)
305 mInterval = 0;
306 else
307 mInterval = aInterval;
308 // Don't call installTimer from here! See #117935.
309}
310
311int KMAccount::checkInterval() const
312{
313 if ( mInterval <= 0 )
314 return mInterval;
315 return TQMAX( mInterval, GlobalSettings::self()->minimumCheckInterval() );
316}
317
318//----------------------------------------------------------------------------
319void KMAccount::deleteFolderJobs()
320{
321 mJobList.setAutoDelete(true);
322 mJobList.clear();
323 mJobList.setAutoDelete(false);
324}
325
326//----------------------------------------------------------------------------
327void KMAccount::ignoreJobsForMessage( KMMessage* msg )
328{
329 //FIXME: remove, make folders handle those
330 for( TQPtrListIterator<FolderJob> it(mJobList); it.current(); ++it ) {
331 if ( it.current()->msgList().first() == msg) {
332 FolderJob *job = it.current();
333 mJobList.remove( job );
334 delete job;
335 break;
336 }
337 }
338}
339
340//-----------------------------------------------------------------------------
341void KMAccount::setCheckExclude(bool aExclude)
342{
343 mExclude = aExclude;
344}
345
346
347//-----------------------------------------------------------------------------
348void KMAccount::installTimer()
349{
350 if (mInterval <= 0) return;
351 if(!mTimer)
352 {
353 mTimer = new TQTimer(0, "mTimer");
354 connect(mTimer,TQ_SIGNAL(timeout()),TQ_SLOT(mailCheck()));
355 }
356 else
357 {
358 mTimer->stop();
359 }
360 mTimer->start( checkInterval() * 60000 );
361}
362
363
364//-----------------------------------------------------------------------------
365void KMAccount::deinstallTimer()
366{
367 delete mTimer;
368 mTimer = 0;
369}
370
371//-----------------------------------------------------------------------------
372bool KMAccount::runPrecommand(const TQString &precommand)
373{
374 // Run the pre command if there is one
375 if ( precommand.isEmpty() )
376 return true;
377
378 KMPrecommand precommandProcess(precommand, this);
379
380 BroadcastStatus::instance()->setStatusMsg(
381 i18n("Executing precommand %1").arg(precommand ));
382
383 connect(&precommandProcess, TQ_SIGNAL(finished(bool)),
384 TQ_SLOT(precommandExited(bool)));
385
386 kdDebug(5006) << "Running precommand " << precommand << endl;
387 if (!precommandProcess.start()) return false;
388
389 tdeApp->eventLoop()->enterLoop();
390
391 return mPrecommandSuccess;
392}
393
394//-----------------------------------------------------------------------------
395void KMAccount::precommandExited(bool success)
396{
397 mPrecommandSuccess = success;
398 tdeApp->eventLoop()->exitLoop();
399}
400
401//-----------------------------------------------------------------------------
402void KMAccount::mailCheck()
403{
404 if (mTimer)
405 mTimer->stop();
406
407 if ( kmkernel ) {
408 AccountManager *acctmgr = kmkernel->acctMgr();
409 if ( acctmgr )
410 acctmgr->singleCheckMail(this, false);
411 }
412}
413
414//-----------------------------------------------------------------------------
415void KMAccount::sendReceipts()
416{
417 TQValueList<KMMessage*>::Iterator it;
418 for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
419 kmkernel->msgSender()->send(*it); //might process events
420 mReceipts.clear();
421}
422
423//-----------------------------------------------------------------------------
424TQString KMAccount::encryptStr(const TQString &aStr)
425{
426 TQString result;
427 for (uint i = 0; i < aStr.length(); i++)
428 /* yes, no typo. can't encode ' ' or '!' because
429 they're the unicode BOM. stupid scrambling. stupid. */
430 result += (aStr[i].unicode() <= 0x21 ) ? aStr[i] :
431 TQChar(0x1001F - aStr[i].unicode());
432 return result;
433}
434
435//-----------------------------------------------------------------------------
436TQString KMAccount::importPassword(const TQString &aStr)
437{
438 unsigned int i, val;
439 unsigned int len = aStr.length();
440 TQCString result;
441 result.resize(len+1);
442
443 for (i=0; i<len; i++)
444 {
445 val = aStr[i] - ' ';
446 val = (255-' ') - val;
447 result[i] = (char)(val + ' ');
448 }
449 result[i] = '\0';
450
451 return encryptStr(result);
452}
453
454void KMAccount::invalidateIMAPFolders()
455{
456 // Default: Don't do anything. The IMAP account will handle it
457}
458
459void KMAccount::pseudoAssign( const KMAccount * a ) {
460 if ( !a ) return;
461
462 setName( a->name() );
463 setId( a->id() );
464 setCheckInterval( a->checkInterval() );
465 setCheckExclude( a->checkExclude() );
466 setFolder( a->folder() );
467 setPrecommand( a->precommand() );
468 setTrash( a->trash() );
469 setIdentityId( a->identityId() );
470}
471
472//-----------------------------------------------------------------------------
473void KMAccount::checkDone( bool newmail, CheckStatus status )
474{
475 setCheckingMail( false );
476 // Reset the timeout for automatic mailchecking. The user might have
477 // triggered the check manually.
478 if (mTimer)
479 mTimer->start( checkInterval() * 60000 );
480 if ( mMailCheckProgressItem ) {
481 // set mMailCheckProgressItem = 0 before calling setComplete() to prevent
482 // a race condition
483 ProgressItem *savedMailCheckProgressItem = mMailCheckProgressItem;
484 mMailCheckProgressItem = 0;
485 savedMailCheckProgressItem->setComplete(); // that will delete it
486 }
487
488 emit newMailsProcessed( mNewInFolder );
489 emit finishedCheck( newmail, status );
490 mNewInFolder.clear();
491}
492
493//-----------------------------------------------------------------------------
494void KMAccount::addToNewInFolder( TQString folderId, int num )
495{
496 if ( mNewInFolder.find( folderId ) == mNewInFolder.end() )
497 mNewInFolder[folderId] = num;
498 else
499 mNewInFolder[folderId] += num;
500}
Simple wrapper class that contains the kmail account handling stuff that is usually not required outs...
Definition: kmacctfolder.h:35
Mail folder.
Definition: kmfolder.h:69
Central point of coordination in KMail.
Definition: kmkernel.h:92
This is a Mime Message.
Definition: kmmessage.h:68
void setStatus(const KMMsgStatus status, int idx=-1)
Set status and mark dirty.
Definition: kmmessage.cpp:4153
KMMessage * createDeliveryReceipt() const
Create a new message that is a delivery receipt of this message, filling required header fileds with ...
Definition: kmmessage.cpp:1635
The account manager is responsible for creating accounts of various types via the factory method crea...