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 
31 using namespace KMail;
32 
33 //-----------------------------------------------------------------------------
35  :TQObject(), mNewMailArrived( false ), mInteractive( false ),
36  mTotalNewMailsArrived( 0 ), mDisplaySummary( false )
37 {
38  mAcctChecking.clear();
39  mAcctTodo.clear();
40 }
41 
42 //-----------------------------------------------------------------------------
43 AccountManager::~AccountManager()
44 {
45  writeConfig( false );
46 }
47 
48 
49 //-----------------------------------------------------------------------------
50 void 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 //-----------------------------------------------------------------------------
113 void 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 //-----------------------------------------------------------------------------
137 void 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 //-----------------------------------------------------------------------------
237 KMAccount* 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 //-----------------------------------------------------------------------------
268 void 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 //-----------------------------------------------------------------------------
284 KMAccount* 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 //-----------------------------------------------------------------------------
296 KMAccount* 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 //-----------------------------------------------------------------------------
307 KMAccount* AccountManager::first()
308 {
309  if ( !mAcctList.empty() ) {
310  mPtrListInterfaceProxyIterator = mAcctList.begin();
311  return *mPtrListInterfaceProxyIterator;
312  } else {
313  return 0;
314  }
315 }
316 
317 //-----------------------------------------------------------------------------
318 KMAccount* AccountManager::next()
319 {
320  ++mPtrListInterfaceProxyIterator;
321  if ( mPtrListInterfaceProxyIterator == mAcctList.end() )
322  return 0;
323  else
324  return *mPtrListInterfaceProxyIterator;
325 }
326 
327 //-----------------------------------------------------------------------------
328 bool AccountManager::remove( KMAccount* acct )
329 {
330  if( !acct || mAcctList.find( acct ) == mAcctList.end() )
331  return false;
332 
333  // Stop automatic checks and remove any pending references before deleting
334  // the account. Otherwise queued or periodic checks may access it after the
335  // account has been removed from the manager.
336  acct->deinstallTimer();
337  mAcctTodo.remove( acct );
338 
339  const bool wasChecking = mAcctChecking.find( acct ) != mAcctChecking.end();
340  if ( wasChecking ) {
341  disconnect( acct, TQ_SIGNAL( finishedCheck( bool, CheckStatus ) ),
342  this, TQ_SLOT( processNextCheck( bool ) ) );
343  mAcctChecking.remove( acct );
344  acct->setCheckingMail( false );
345  }
346 
347  mAcctList.remove( acct );
348  emit accountRemoved( acct );
349  delete acct;
350 
351  if ( wasChecking ) {
352  kmkernel->filterMgr()->deref();
353  processNextCheck( false );
354  }
355 
356  return true;
357 }
358 
359 //-----------------------------------------------------------------------------
360 void AccountManager::checkMail( bool _interactive )
361 {
362  mNewMailArrived = false;
363 
364  if ( mAcctList.isEmpty() ) {
365  KMessageBox::information( 0,i18n("You need to add an account in the network "
366  "section of the settings in order to receive mail.") );
367  return;
368  }
369  mDisplaySummary = true;
370 
371  mTotalNewMailsArrived=0;
372  mTotalNewInFolder.clear();
373 
374  for ( AccountList::Iterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
375  if ( !(*it)->checkExclude() )
376  singleCheckMail( (*it), _interactive);
377  }
378 }
379 
380 
381 //-----------------------------------------------------------------------------
382 void AccountManager::singleInvalidateIMAPFolders(KMAccount *account) {
383  account->invalidateIMAPFolders();
384 }
385 
386 
388 {
389  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it )
390  singleInvalidateIMAPFolders( *it );
391 }
392 
393 
394 //-----------------------------------------------------------------------------
395 TQStringList AccountManager::getAccounts() const
396 {
397  TQStringList strList;
398  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
399  strList.append( (*it)->name() );
400  }
401  return strList;
402 }
403 
404 //-----------------------------------------------------------------------------
405 void AccountManager::intCheckMail(int item, bool _interactive)
406 {
407  mNewMailArrived = false;
408  mTotalNewMailsArrived = 0;
409  mTotalNewInFolder.clear();
410  if ( KMAccount *acct = mAcctList[ item ] )
411  singleCheckMail( acct, _interactive );
412  mDisplaySummary = false;
413 }
414 
415 
416 //-----------------------------------------------------------------------------
417 void AccountManager::addToTotalNewMailCount( const TQMap<TQString, int> & newInFolder )
418 {
419  for ( TQMap<TQString, int>::const_iterator it = newInFolder.begin();
420  it != newInFolder.end(); ++it ) {
421  mTotalNewMailsArrived += it.data();
422  if ( mTotalNewInFolder.find( it.key() ) == mTotalNewInFolder.end() )
423  mTotalNewInFolder[it.key()] = it.data();
424  else
425  mTotalNewInFolder[it.key()] += it.data();
426  }
427 }
428 
429 //-----------------------------------------------------------------------------
430 uint AccountManager::createId()
431 {
432  TQValueList<uint> usedIds;
433  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
434  usedIds << (*it)->id();
435  }
436 
437  usedIds << 0; // 0 is default for unknown
438  int newId;
439  do
440  {
441  newId = tdeApp->random();
442  } while ( usedIds.find(newId) != usedIds.end() );
443 
444  return newId;
445 }
446 
447 //-----------------------------------------------------------------------------
449 {
450  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
451  (*it)->cancelMailCheck();
452  }
453 }
454 
455 
456 //-----------------------------------------------------------------------------
458 {
459  for ( AccountList::ConstIterator it( mAcctList.begin() ), end( mAcctList.end() ); it != end; ++it ) {
460  NetworkAccount *acct = dynamic_cast<NetworkAccount*>( (*it) );
461  if ( acct )
462  acct->readPassword();
463  }
464 }
465 
466 #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
void readPasswords()
Read passwords of all accounts from the wallet.
void readConfig(void)
Completely reload accounts from config.
KMAccount * findByName(const TQString &name) const
Find account by name.
const KMAccount * first() const
First account of the list.
const KMAccount * next() const
Next account of the list.
void accountAdded(KMAccount *account)
emitted when an account is added
bool remove(KMAccount *)
Physically remove account.
AccountManager()
Initializes the account manager.
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