def init(self): with self._lock: if self._disposed: raise InvalidOperationException("Daemon has been disposed") if self._initialized: raise InvalidOperationException( "Daemon has already been initialized") self._cfg = read_cfg() accountman = AccountManager() accountman.load_from_cfg(self._cfg, enabled_only=True) self._accounts = accountman.to_list() self._hookreg = HookRegistry() self._conntest = ConnectivityTest(testmode_mapping[self._cfg.get( 'core', 'connectivity_test')]) memorizer = Memorizer() memorizer.load() self._mailchecker = MailChecker(self._cfg, memorizer, self._hookreg, self._conntest) # Note: all code following _load_plugins() should be executed # asynchronously because the dbus plugin requires an active mainloop # (usually started in the programs main function). self._load_plugins(self._cfg, self._hookreg, memorizer) # Start checking for mails asynchronously. self._start_thread = threading.Thread(target=self._start) self._start_thread.start() self._initialized = True
def init(self): with self._lock: if self._disposed: raise InvalidOperationException("Daemon has been disposed") if self._initialized: raise InvalidOperationException("Daemon has already been initialized") self._cfg = read_cfg() accountman = AccountManager(CredentialStore.from_string(self._cfg.get('core', 'credentialstore'))) accountman.load_from_cfg(self._cfg, enabled_only = True) self._accounts = accountman.to_list() self._hookreg = HookRegistry() self._conntest = ConnectivityTest(testmode_mapping[self._cfg.get('core', 'connectivity_test')]) memorizer = Memorizer() memorizer.load() self._mailchecker = MailChecker(self._cfg, memorizer, self._hookreg, self._conntest) # Note: all code following _load_plugins() should be executed # asynchronously because the dbus plugin requires an active mainloop # (usually started in the programs main function). self._load_plugins(self._cfg, self._hookreg, memorizer) # Start checking for mails asynchronously. self._start_thread = threading.Thread(target = self._start) self._start_thread.start() self._initialized = True
def __init__(self, fatal_error_handler=None, shutdown_request_handler=None): self._fatal_error_handler = fatal_error_handler self._shutdown_request_handler = shutdown_request_handler self._plugins = [] self._poll_thread = None self._poll_thread_stop = threading.Event() self._idlrunner = None self._disposed = False self._cfg = read_cfg() accountman = AccountManager() accountman.load_from_cfg(self._cfg, enabled_only=True) self._accounts = accountman.to_list() self._hookreg = HookRegistry() self._conntest = ConnectivityTest(testmode_mapping[self._cfg.get( 'core', 'connectivity_test')]) self._memorizer = Memorizer() self._memorizer.load() dbus_service = DBusService(self) self._mailchecker = MailChecker(self._cfg, self._memorizer, self._hookreg, self._conntest, dbus_service) # Note: all code following _load_plugins() should be executed # asynchronously because the dbus plugin requires an active mainloop # (usually started in the programs main function). self._load_plugins(self._cfg) # Start checking for mails asynchronously. self._start_thread = threading.Thread(target=self._start) self._start_thread.start()
class MailnagDaemon(MailnagController): def __init__(self, fatal_error_handler=None, shutdown_request_handler=None): self._fatal_error_handler = fatal_error_handler self._shutdown_request_handler = shutdown_request_handler self._plugins = [] self._poll_thread = None self._poll_thread_stop = threading.Event() self._idlrunner = None self._disposed = False self._cfg = read_cfg() accountman = AccountManager() accountman.load_from_cfg(self._cfg, enabled_only=True) self._accounts = accountman.to_list() self._hookreg = HookRegistry() self._conntest = ConnectivityTest(testmode_mapping[self._cfg.get( 'core', 'connectivity_test')]) self._memorizer = Memorizer() self._memorizer.load() dbus_service = DBusService(self) self._mailchecker = MailChecker(self._cfg, self._memorizer, self._hookreg, self._conntest, dbus_service) # Note: all code following _load_plugins() should be executed # asynchronously because the dbus plugin requires an active mainloop # (usually started in the programs main function). self._load_plugins(self._cfg) # Start checking for mails asynchronously. self._start_thread = threading.Thread(target=self._start) self._start_thread.start() def dispose(self): if self._disposed: return # Note: _disposed must be set # before cleaning up resources # (in case an exception occurs) # and before unloading plugins. # Also required by _wait_for_inet_connection(). self._disposed = True # clean up resources if (self._start_thread != None) and (self._start_thread.is_alive()): self._start_thread.join() logging.info('Starter thread exited successfully.') if (self._poll_thread != None) and (self._poll_thread.is_alive()): self._poll_thread_stop.set() self._poll_thread.join() logging.info('Polling thread exited successfully.') if self._idlrunner != None: self._idlrunner.dispose() if self._accounts != None: for acc in self._accounts: if acc.is_open(): acc.close() self._unload_plugins() def is_disposed(self): return self._disposed # Part of MailnagController interface def get_hooks(self): # Note: ensure_not_disposed() cannot be called here # because plugins are calling get_hooks() when being disabled in dispose(). # self._ensure_not_disposed() return self._hookreg # Part of MailnagController interface def shutdown(self): if self._shutdown_request_handler != None: self._shutdown_request_handler() # Part of MailnagController interface def mark_mail_as_read(self, mail_id): # Note: ensure_not_disposed() is not really necessary here # (the memorizer object is available in dispose()), # but better be consistent with other daemon methods. self._ensure_not_disposed() self._memorizer.set_to_seen(mail_id) self._memorizer.save() # Enforces manual mail checks # Part of MailnagController interface def check_for_mails(self): # Don't allow mail checks after object disposal. # F.i. plugins may not be unloaded completely or # connections may have been closed already. self._ensure_not_disposed() non_idle_accounts = self._get_non_idle_accounts(self._accounts) self._mailchecker.check(non_idle_accounts) def _ensure_not_disposed(self): if self._disposed: raise InvalidOperationException("Daemon has been disposed") def _start(self): try: # Call Accounts-Loaded plugin hooks for f in self._hookreg.get_hook_funcs(HookTypes.ACCOUNTS_LOADED): try_call(lambda: f(self._accounts)) if not self._wait_for_inet_connection(): return # Immediate check, check *all* accounts try: self._mailchecker.check(self._accounts) except: logging.exception('Caught an exception.') idle_accounts = self._get_idle_accounts(self._accounts) non_idle_accounts = self._get_non_idle_accounts(self._accounts) # start polling thread for POP3 accounts and # IMAP accounts without idle support if len(non_idle_accounts) > 0: poll_interval = int(self._cfg.get('core', 'poll_interval')) def poll_func(): try: while True: self._poll_thread_stop.wait(timeout=60.0 * poll_interval) if self._poll_thread_stop.is_set(): break self._mailchecker.check(non_idle_accounts) except: logging.exception('Caught an exception.') self._poll_thread = threading.Thread(target=poll_func) self._poll_thread.start() # start idler threads for IMAP accounts with idle support if len(idle_accounts) > 0: def sync_func(account): try: self._mailchecker.check([account]) except: logging.exception('Caught an exception.') idle_timeout = int(self._cfg.get('core', 'imap_idle_timeout')) self._idlrunner = IdlerRunner(idle_accounts, sync_func, idle_timeout) self._idlrunner.start() except Exception as ex: logging.exception('Caught an exception.') if self._fatal_error_handler != None: self._fatal_error_handler(ex) def _wait_for_inet_connection(self): if self._conntest.is_offline(): logging.info('Waiting for internet connection...') while True: if self._disposed: return False if not self._conntest.is_offline(): return True # Note: don't sleep too long # (see timeout in mailnag.cleanup()) # ..but also don't sleep to short in case of a ping connection test. time.sleep(3) def _get_idle_accounts(self, accounts): return [acc for acc in self._accounts if acc.supports_notifications()] def _get_non_idle_accounts(self, accounts): return [ acc for acc in self._accounts if not acc.supports_notifications() ] def _load_plugins(self, cfg): enabled_lst = cfg.get('core', 'enabled_plugins').split(',') enabled_lst = [s for s in [s.strip() for s in enabled_lst] if s != ''] self._plugins = Plugin.load_plugins(cfg, self, enabled_lst) for p in self._plugins: try: p.enable() logging.info("Successfully enabled plugin '%s'." % p.get_modname()) except: logging.error("Failed to enable plugin '%s'." % p.get_modname()) def _unload_plugins(self): if len(self._plugins) > 0: err = False for p in self._plugins: try: p.disable() except: err = True logging.error("Failed to disable plugin '%s'." % p.get_modname()) if not err: logging.info('Plugins disabled successfully.')