kmail

accountmanager.cpp
1// KMail Account Manager
2
3#ifdef HAVE_CONFIG_H
4#include <config.h>
5#endif
6
7#include "accountmanager.h"
8
9#include "kmaccount.h"
10#include "kmacctfolder.h"
11#include "kmacctmaildir.h"
12#include "kmacctlocal.h"
13#include "popaccount.h"
14#include "kmacctimap.h"
15#include "networkaccount.h"
16#include "kmacctcachedimap.h"
17#include "broadcaststatus.h"
18#include "kmfiltermgr.h"
19#include "globalsettings.h"
20
21#include <dcopclient.h>
22#include <tdelocale.h>
23#include <tdemessagebox.h>
24#include <kdebug.h>
25#include <tdeconfig.h>
26#include <tdeapplication.h>
27
28#include <tqregexp.h>
29#include <tqvaluelist.h>
30
31using namespace KMail;
32
33//-----------------------------------------------------------------------------
34AccountManager::AccountManager()
35 :TQObject(), mNewMailArrived( false ), mInteractive( false ),
36 mTotalNewMailsArrived( 0 ), mDisplaySummary( false )
37{
38 mAcctChecking.clear();
39 mAcctTodo.clear();
40}
41
42//-----------------------------------------------------------------------------
43AccountManager::~AccountManager()
44{
45 writeConfig( false );
46}
47
48
49//-----------------------------------------------------------------------------
50void AccountManager::writeConfig( bool withSync )
51{
52 TDEConfig* config = KMKernel::config();
53 TQString groupName;
54
55 TDEConfigGroupSaver saver(config, "General");
56 config->writeEntry("accounts", mAcctList.count());
57
58 // first delete all account groups in the config file:
59 TQStringList accountGroups =
60 config->groupList().grep( TQRegExp( "Account \\d+" ) );
61 for ( TQStringList::Iterator it = accountGroups.begin() ;
62 it != accountGroups.end() ; ++it )
63 config->deleteGroup( *it );
64
65 // now write new account groups:
66 int i = 1;
67 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it, ++i ) {
68 groupName.sprintf("Account %d", i);
69 TDEConfigGroupSaver saver(config, groupName);
70 (*it)->writeConfig(*config);
71 }
72 if (withSync) config->sync();
73}
74
75
76//-----------------------------------------------------------------------------
78{
79 TDEConfig* config = KMKernel::config();
80 KMAccount* acct;
81 TQString acctType, acctName;
82 TQCString groupName;
83 int i, num;
84 uint id;
85
86 for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
87 delete *it;
88 mAcctList.clear();
89
90 TDEConfigGroup general(config, "General");
91 num = general.readNumEntry("accounts", 0);
92
93 for (i=1; i<=num; i++)
94 {
95 groupName.sprintf("Account %d", i);
96 TDEConfigGroupSaver saver(config, groupName);
97 acctType = config->readEntry("Type");
98 // Provide backwards compatibility
99 if (acctType == "advanced pop" || acctType == "experimental pop")
100 acctType = "pop";
101 acctName = config->readEntry("Name");
102 id = config->readUnsignedNumEntry("Id", 0);
103 if (acctName.isEmpty()) acctName = i18n("Account %1").arg(i);
104 acct = create(acctType, acctName, id);
105 if (!acct) continue;
106 add(acct);
107 acct->readConfig(*config);
108 }
109}
110
111
112//-----------------------------------------------------------------------------
113void AccountManager::singleCheckMail(KMAccount *account, bool interactive)
114{
115 mNewMailArrived = false;
116 mInteractive = interactive;
117
118 // if sync has been requested by the user then check if check-interval was disabled by user, if yes, then
119 // de-install the timer
120 // Safe guard against an infinite sync loop (kolab/issue2607)
121 if ( mInteractive )
122 account->readTimerConfig();
123
124 // queue the account
125 mAcctTodo.append(account);
126
127 if (account->checkingMail())
128 {
129 kdDebug(5006) << "account " << account->name() << " busy, queuing" << endl;
130 return;
131 }
132
133 processNextCheck(false);
134}
135
136//-----------------------------------------------------------------------------
137void AccountManager::processNextCheck( bool _newMail )
138{
139 kdDebug(5006) << "processNextCheck, remaining " << mAcctTodo.count() << endl;
140 if ( _newMail )
141 mNewMailArrived = true;
142
143 for ( AccountList::Iterator it( mAcctChecking.begin() ), end( mAcctChecking.end() ); it != end; ) {
144 KMAccount* acct = *it;
145 ++it;
146 if ( acct->checkingMail() )
147 continue;
148 // check done
149 kdDebug(5006) << "account " << acct->name() << " finished check" << endl;
150 mAcctChecking.remove( acct );
151 kmkernel->filterMgr()->deref();
152 disconnect( acct, TQ_SIGNAL( finishedCheck( bool, CheckStatus ) ),
153 this, TQ_SLOT( processNextCheck( bool ) ) );
154 }
155 if ( mAcctChecking.isEmpty() ) {
156 // all checks finished, display summary
157 if ( mDisplaySummary )
158 KPIM::BroadcastStatus::instance()->setStatusMsgTransmissionCompleted(
159 mTotalNewMailsArrived );
160 emit checkedMail( mNewMailArrived, mInteractive, mTotalNewInFolder );
161 mTotalNewMailsArrived = 0;
162 mTotalNewInFolder.clear();
163 mDisplaySummary = false;
164 }
165 if ( mAcctTodo.isEmpty() ) return;
166
167 TQString accountHostName;
168
169 KMAccount *curAccount = 0;
170 for ( AccountList::Iterator it ( mAcctTodo.begin() ), last ( mAcctTodo.end() ); it != last; ) {
171 KMAccount *acct = *it;
172 ++it;
173 if ( !acct->checkingMail() && acct->mailCheckCanProceed() ) {
174 curAccount = acct;
175 mAcctTodo.remove( acct );
176 break;
177 }
178 }
179 if ( !curAccount ) return; // no account or all of them are already checking
180
181 if ( curAccount->type() != "imap" && curAccount->type() != "cachedimap" &&
182 curAccount->folder() == 0 ) {
183 TQString tmp = i18n("Account %1 has no mailbox defined:\n"
184 "mail checking aborted;\n"
185 "check your account settings.")
186 .arg(curAccount->name());
187 KMessageBox::information(0,tmp);
188 emit checkedMail( false, mInteractive, mTotalNewInFolder );
189 mTotalNewMailsArrived = 0;
190 mTotalNewInFolder.clear();
191 return;
192 }
193
194 if ( curAccount->type() == "imap" || curAccount->type() == "cachedimap" || curAccount->type() == "pop" )
195 {
196 // Check with the network status daemon whether the network is available
197 const int NetWorkStatusUnknown = 1;
198 const int NetWorkStatusOnline = 8;
199 TQCString replyType;
200 TQByteArray params;
201 TQByteArray reply;
202
203 TQDataStream stream( params, IO_WriteOnly );
204 stream << static_cast<NetworkAccount*>( curAccount )->host();
205
206 if ( tdeApp->dcopClient()->call( "kded", "networkstatus", "status(TQString)",
207 params, replyType, reply ) && ( replyType == "int" ) )
208 {
209 int result;
210 TQDataStream stream2( reply, IO_ReadOnly );
211 stream2 >> result;
212 kdDebug() << k_funcinfo << "networkstatus status = " << result << endl;
213 // if it's not unknown (no networks announced by network control apps), and not offline, give up now
214 if ( ( result != NetWorkStatusUnknown ) && ( result != NetWorkStatusOnline ) )
215 {
216 emit checkedMail( false, mInteractive, mTotalNewInFolder );
217 return;
218 }
219 }
220 }
221
222 connect( curAccount, TQ_SIGNAL( finishedCheck( bool, CheckStatus ) ),
223 this, TQ_SLOT( processNextCheck( bool ) ) );
224
225 KPIM::BroadcastStatus::instance()->setStatusMsg(
226 i18n("Checking account %1 for new mail").arg(curAccount->name()));
227
228 kdDebug(5006) << "processing next mail check for " << curAccount->name() << endl;
229
230 curAccount->setCheckingMail( true );
231 mAcctChecking.append( curAccount );
232 kmkernel->filterMgr()->ref();
233 curAccount->processNewMail( mInteractive );
234}
235
236//-----------------------------------------------------------------------------
237KMAccount* AccountManager::create( const TQString &aType, const TQString &aName, uint id )
238{
239 KMAccount* act = 0;
240 if ( id == 0 )
241 id = createId();
242
243 if ( aType == "local" ) {
244 act = new KMAcctLocal(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
245 act->setFolder( kmkernel->inboxFolder() );
246 } else if ( aType == "maildir" ) {
247 act = new KMAcctMaildir(this, aName.isEmpty() ? i18n("Local Account") : aName, id);
248 act->setFolder( kmkernel->inboxFolder() );
249 } else if ( aType == "pop" ) {
250 act = new KMail::PopAccount(this, aName.isEmpty() ? i18n("POP Account") : aName, id);
251 act->setFolder( kmkernel->inboxFolder() );
252 } else if ( aType == "imap" ) {
253 act = new KMAcctImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
254 } else if (aType == "cachedimap") {
255 act = new KMAcctCachedImap(this, aName.isEmpty() ? i18n("IMAP Account") : aName, id);
256 }
257 if ( !act ) {
258 kdWarning(5006) << "Attempt to instantiate a non-existing account type!" << endl;
259 return 0;
260 }
261 connect( act, TQ_SIGNAL( newMailsProcessed( const TQMap<TQString, int> & ) ),
262 this, TQ_SLOT( addToTotalNewMailCount( const TQMap<TQString, int> & ) ) );
263 return act;
264}
265
266
267//-----------------------------------------------------------------------------
268void AccountManager::add( KMAccount *account )
269{
270 if ( account ) {
271 mAcctList.append( account );
272 // init folder's account list
273 KMAcctFolder *folder = static_cast<KMAcctFolder*>( account->folder() );
274 if ( folder && !folder->hasAccounts() ) {
275 folder->addAccount( account );
276 }
277 emit accountAdded( account );
278 account->installTimer();
279 }
280}
281
282
283//-----------------------------------------------------------------------------
284KMAccount* AccountManager::findByName(const TQString &aName) const
285{
286 if ( aName.isEmpty() ) return 0;
287
288 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
289 if ( (*it)->name() == aName ) return (*it);
290 }
291 return 0;
292}
293
294
295//-----------------------------------------------------------------------------
296KMAccount* AccountManager::find( const uint id ) const
297{
298 if (id == 0) return 0;
299 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
300 if ( (*it)->id() == id ) return (*it);
301 }
302 return 0;
303}
304
305
306//-----------------------------------------------------------------------------
307KMAccount* AccountManager::first()
308{
309 if ( !mAcctList.empty() ) {
310 mPtrListInterfaceProxyIterator = mAcctList.begin();
311 return *mPtrListInterfaceProxyIterator;
312 } else {
313 return 0;
314 }
315}
316
317//-----------------------------------------------------------------------------
318KMAccount* AccountManager::next()
319{
320 ++mPtrListInterfaceProxyIterator;
321 if ( mPtrListInterfaceProxyIterator == mAcctList.end() )
322 return 0;
323 else
324 return *mPtrListInterfaceProxyIterator;
325}
326
327//-----------------------------------------------------------------------------
328bool AccountManager::remove( KMAccount* acct )
329{
330 if( !acct )
331 return false;
332 mAcctList.remove( acct );
333 emit accountRemoved( acct );
334 return true;
335}
336
337//-----------------------------------------------------------------------------
338void AccountManager::checkMail( bool _interactive )
339{
340 mNewMailArrived = false;
341
342 if ( mAcctList.isEmpty() ) {
343 KMessageBox::information( 0,i18n("You need to add an account in the network "
344 "section of the settings in order to receive mail.") );
345 return;
346 }
347 mDisplaySummary = true;
348
349 mTotalNewMailsArrived=0;
350 mTotalNewInFolder.clear();
351
352 for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
353 if ( !(*it)->checkExclude() )
354 singleCheckMail( (*it), _interactive);
355 }
356}
357
358
359//-----------------------------------------------------------------------------
360void AccountManager::singleInvalidateIMAPFolders(KMAccount *account) {
361 account->invalidateIMAPFolders();
362}
363
364
366{
367 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
368 singleInvalidateIMAPFolders( *it );
369}
370
371
372//-----------------------------------------------------------------------------
373TQStringList AccountManager::getAccounts() const
374{
375 TQStringList strList;
376 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
377 strList.append( (*it)->name() );
378 }
379 return strList;
380}
381
382//-----------------------------------------------------------------------------
383void AccountManager::intCheckMail(int item, bool _interactive)
384{
385 mNewMailArrived = false;
386 mTotalNewMailsArrived = 0;
387 mTotalNewInFolder.clear();
388 if ( KMAccount *acct = mAcctList[ item ] )
389 singleCheckMail( acct, _interactive );
390 mDisplaySummary = false;
391}
392
393
394//-----------------------------------------------------------------------------
395void AccountManager::addToTotalNewMailCount( const TQMap<TQString, int> & newInFolder )
396{
397 for ( TQMap<TQString, int>::const_iterator it = newInFolder.begin();
398 it != newInFolder.end(); ++it ) {
399 mTotalNewMailsArrived += it.data();
400 if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
401 mTotalNewInFolder[it.key()] = it.data();
402 else
403 mTotalNewInFolder[it.key()] += it.data();
404 }
405}
406
407//-----------------------------------------------------------------------------
408uint AccountManager::createId()
409{
410 TQValueList<uint> usedIds;
411 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
412 usedIds << (*it)->id();
413 }
414
415 usedIds << 0; // 0 is default for unknown
416 int newId;
417 do
418 {
419 newId = tdeApp->random();
420 } while ( usedIds.find(newId) != usedIds.end() );
421
422 return newId;
423}
424
425//-----------------------------------------------------------------------------
427{
428 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
429 (*it)->cancelMailCheck();
430 }
431}
432
433
434//-----------------------------------------------------------------------------
436{
437 for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
438 NetworkAccount *acct = dynamic_cast<NetworkAccount*>( (*it) );
439 if ( acct )
440 acct->readPassword();
441 }
442}
443
444#include "accountmanager.moc"
Simple wrapper class that contains the kmail account handling stuff that is usually not required outs...
Definition: kmacctfolder.h:35
void addAccount(KMAccount *)
Add given account to the list.
bool hasAccounts() const
Returns TRUE if accounts are associated with this folder.
Definition: kmfolder.h:128
void checkMail(bool interactive=true)
Processes all accounts looking for new mail.
void accountRemoved(KMAccount *account)
emitted when an account is removed
const KMAccount * next() const
Next account of the list.
void readPasswords()
Read passwords of all accounts from the wallet.
const KMAccount * first() const
First account of the list.
void readConfig(void)
Completely reload accounts from config.
KMAccount * findByName(const TQString &name) const
Find account by name.
void accountAdded(KMAccount *account)
emitted when an account is added
bool remove(KMAccount *)
Physically remove account.
void writeConfig(bool withSync=true)
Write accounts to config.
void add(KMAccount *account)
Adds an account to the list of accounts.
void cancelMailCheck()
Called on exit (KMMainWin::queryExit)
void checkedMail(bool newMail, bool interactive, const TQMap< TQString, int > &newInFolder)
Emitted if new mail has been collected.
KMAccount * find(const uint id) const
Find account by id.
void addToTotalNewMailCount(const TQMap< TQString, int > &newInFolder)
this slot increases the count of new mails to show a total number after checking in multiple accounts...
KMAccount * create(const TQString &type, const TQString &name=TQString(), uint id=0)
Create a new account of given type with given name.
void invalidateIMAPFolders()
Delete all IMAP folders and resync them.
KMail account for pop mail account.
Definition: popaccount.h:27
folderdiaquotatab.h
Definition: aboutdata.cpp:40