def test_syncing_without_account_should_keep_already_synced_messages(): syncer = MailSyncer([]) account = FakeAccount() messages = make_messages(0, 10) account.set_current_messages(messages) mails_in_first_sync = syncer.sync([account]) mails_in_second_sync = syncer.sync([]) assert mails_in_first_sync == mails_in_second_sync
def test_syncing_account_multiple_times_should_not_affect(): syncer = MailSyncer([]) account = FakeAccount() messages = make_messages(0, 10) account.set_current_messages(messages) mails_in_first_sync = syncer.sync([account]) mails_in_second_sync = syncer.sync([account]) assert mails_in_first_sync == mails_in_second_sync
def test_syncing_should_update_messages(): syncer = MailSyncer([]) account = FakeAccount() messages = make_messages(0, 10) account.set_current_messages(messages) mails_in_first_sync = syncer.sync([account]) new_messages = make_messages(10, 14) account.set_current_messages(messages[3:] + new_messages) mails_in_second_sync = syncer.sync([account]) assert len(mails_in_second_sync) == 11
def test_syncing_should_remove_read_messages(): syncer = MailSyncer([]) account = FakeAccount() messages = make_messages(0, 10) account.set_current_messages(messages) mails_in_first_sync = syncer.sync([account]) account.set_current_messages(messages[3:]) mails_in_second_sync = syncer.sync([account]) assert len(mails_in_second_sync) == 7 assert all(mail in mails_in_first_sync for mail in mails_in_second_sync)
def test_syncing_should_add_new_messages(): syncer = MailSyncer([]) account = FakeAccount() messages = make_messages(0, 10) account.set_current_messages(messages) mails_in_first_sync = syncer.sync([account]) new_messages = make_messages(10, 14) account.set_current_messages(messages + new_messages) mails_in_second_sync = syncer.sync([account]) assert len(mails_in_second_sync) == 14 assert all(mail in mails_in_second_sync for mail in mails_in_first_sync)
def test_syncing_multiple_account_separately_should_collect_all_messages(): syncer = MailSyncer([]) # Note: Accounts are identified by user, server and folders attributes, # see Account.get_id() account1 = FakeAccount(name='1', user='******') account2 = FakeAccount(name='2', server='b') account3 = FakeAccount(name='3') account1.set_current_messages(make_messages(0, 10)) account2.set_current_messages(make_messages(10, 20)) account3.set_current_messages(make_messages(20, 30)) syncer.sync([account1]) syncer.sync([account2]) mails = syncer.sync([account3]) assert len(mails) == 30
def test_mails_in_an_account(): syncer = MailSyncer([]) account = FakeAccount() messages = make_messages(0, 10) account.set_current_messages(messages) mails = syncer.sync([account]) assert len(mails) == 10
def test_syncing_same_mail_twice_from_same_account(): syncer = MailSyncer([]) account = FakeAccount() messages1 = make_messages(0, 1) messages2 = make_messages(0, 1) account.set_current_messages(messages1 + messages2) mails = syncer.sync([account]) assert len(mails) == 1
def test_syncing_multiple_accounts_should_collect_all_messages(): syncer = MailSyncer([]) account1 = FakeAccount() account2 = FakeAccount() account3 = FakeAccount() account1.set_current_messages(make_messages(0, 10)) account2.set_current_messages(make_messages(10, 20)) account3.set_current_messages(make_messages(20, 30)) mails = syncer.sync([account1, account2, account3]) assert len(mails) == 30
def test_syncing_same_mail_from_different_accounts(): syncer = MailSyncer([]) account1 = FakeAccount(name='1', user='******') account2 = FakeAccount(name='2', server='b') messages1 = make_messages(0, 1) messages2 = make_messages(0, 1) account1.set_current_messages(messages1) account2.set_current_messages(messages2) mails = syncer.sync([account1, account2]) # Note: Is this ok, or should it list message in both accounts? assert len(mails) == 1
def test_syncing_with_messages_without_message_ids(): syncer = MailSyncer([]) account1 = FakeAccount(name='1', user='******') account2 = FakeAccount(name='2', server='b') account3 = FakeAccount(name='3') messages1 = make_messages_without_mid() messages2 = make_messages_without_mid() messages3 = make_messages_without_mid() account1.set_current_messages(messages1) account2.set_current_messages(messages2) account3.set_current_messages(messages3) mails = syncer.sync([account1, account2, account3]) assert len(mails) == 3
class MailChecker: def __init__(self, cfg, memorizer, hookreg, conntest, dbus_service): self._firstcheck = True # first check after startup self._mailcheck_lock = threading.Lock() self._mailsyncer = MailSyncer(cfg) self._mailbox_seen_flags = bool(cfg.get('core', 'mailbox_seen_flags')) self._memorizer = memorizer self._hookreg = hookreg self._conntest = conntest self._dbus_service = dbus_service self._count_on_last_check = 0 def check(self, accounts): # make sure multiple threads (idler and polling thread) # don't check for mails simultaneously. with self._mailcheck_lock: logging.info('Checking %s email account(s).' % len(accounts)) for f in self._hookreg.get_hook_funcs(HookTypes.MAIL_CHECK): try_call(f) if self._conntest.is_offline(): logging.warning('No internet connection.') return all_mails = self._mailsyncer.sync(accounts) unseen_mails = [] new_mails = [] seen_mails_by_account = {} for mail in all_mails: if self._memorizer.contains( mail.id): # mail was fetched before if self._memorizer.is_unseen( mail.id): # mail was not marked as seen unseen_mails.append(mail) if self._firstcheck: new_mails.append(mail) elif self._mailbox_seen_flags: # if the mail account supports tagging mails as seen (e.g. IMAP), # mark the mail as seen on the server as well. if mail.account.supports_mark_as_seen(): if not mail.account in seen_mails_by_account: seen_mails_by_account[mail.account] = [] seen_mails_by_account[mail.account].append(mail) else: # mail is fetched the first time unseen_mails.append(mail) new_mails.append(mail) # Flag mails to seen on server for acc, mails in seen_mails_by_account.items(): acc.mark_as_seen(mails) self._memorizer.sync(all_mails) self._memorizer.save() self._firstcheck = False # apply filter plugin hooks filtered_unseen_mails = unseen_mails for f in self._hookreg.get_hook_funcs(HookTypes.FILTER_MAILS): filtered_unseen_mails = try_call( lambda: f(filtered_unseen_mails), filtered_unseen_mails) filtered_new_mails = [ m for m in new_mails if m in filtered_unseen_mails ] if len(filtered_new_mails) > 0: self._dbus_service.signal_mails_added(filtered_new_mails, filtered_unseen_mails) for f in self._hookreg.get_hook_funcs(HookTypes.MAILS_ADDED): try_call( lambda: f(filtered_new_mails, filtered_unseen_mails)) elif len(filtered_unseen_mails) != self._count_on_last_check: self._dbus_service.signal_mails_removed(filtered_unseen_mails) for f in self._hookreg.get_hook_funcs(HookTypes.MAILS_REMOVED): try_call(lambda: f(filtered_unseen_mails)) self._count_on_last_check = len(filtered_unseen_mails) return
def test_no_mails_in_an_account(): syncer = MailSyncer([]) account = FakeAccount() mails = syncer.sync([account]) assert len(mails) == 0
def test_no_mails_with_no_accounts(): syncer = MailSyncer([]) accounts = [] mails = syncer.sync(accounts) assert len(mails) == 0
class MailChecker: def __init__(self, cfg, memorizer, hookreg, conntest, dbus_service): self._firstcheck = True # first check after startup self._mailcheck_lock = threading.Lock() self._mailsyncer = MailSyncer(cfg) self._memorizer = memorizer self._hookreg = hookreg self._conntest = conntest self._dbus_service = dbus_service self._zero_mails_on_last_check = True def check(self, accounts): # make sure multiple threads (idler and polling thread) # don't check for mails simultaneously. with self._mailcheck_lock: logging.info('Checking %s email account(s).' % len(accounts)) for f in self._hookreg.get_hook_funcs(HookTypes.MAIL_CHECK): try_call(f) if self._conntest.is_offline(): logging.warning('No internet connection.') return all_mails = self._mailsyncer.sync(accounts) unseen_mails = [] new_mails = [] for mail in all_mails: if self._memorizer.contains( mail.id): # mail was fetched before if self._memorizer.is_unseen( mail.id): # mail was not marked as seen unseen_mails.append(mail) if self._firstcheck: new_mails.append(mail) else: # mail is fetched the first time unseen_mails.append(mail) new_mails.append(mail) self._memorizer.sync(all_mails) self._memorizer.save() self._firstcheck = False # apply filter plugin hooks filtered_unseen_mails = unseen_mails for f in self._hookreg.get_hook_funcs(HookTypes.FILTER_MAILS): filtered_unseen_mails = try_call( lambda: f(filtered_unseen_mails), filtered_unseen_mails) filtered_new_mails = [ m for m in new_mails if m in filtered_unseen_mails ] if len(filtered_new_mails) > 0: self._dbus_service.signal_mails_added(filtered_new_mails, filtered_unseen_mails) for f in self._hookreg.get_hook_funcs(HookTypes.MAILS_ADDED): try_call( lambda: f(filtered_new_mails, filtered_unseen_mails)) elif (not self._zero_mails_on_last_check) and ( len(filtered_unseen_mails) == 0): # TODO : signal MailsRemoved if not all mails have been removed # (i.e. if mailcount has been decreased) self._dbus_service.signal_mails_removed(filtered_unseen_mails) for f in self._hookreg.get_hook_funcs(HookTypes.MAILS_REMOVED): try_call(lambda: f(filtered_unseen_mails)) self._zero_mails_on_last_check = (len(filtered_unseen_mails) == 0) return
class MailChecker: def __init__(self, cfg, memorizer, hookreg, conntest): self._firstcheck = True # first check after startup self._mailcheck_lock = threading.Lock() self._mailsyncer = MailSyncer(cfg) self._memorizer = memorizer self._hookreg = hookreg self._conntest = conntest self._zero_mails_on_last_check = True def check(self, accounts): # make sure multiple threads (idler and polling thread) # don't check for mails simultaneously. with self._mailcheck_lock: logging.info('Checking %s email account(s).' % len(accounts)) for f in self._hookreg.get_hook_funcs(HookTypes.MAIL_CHECK): try_call( f ) if self._conntest.is_offline(): logging.warning('No internet connection.') return all_mails = self._mailsyncer.sync(accounts) unseen_mails = [] new_mails = [] for mail in all_mails: if self._memorizer.contains(mail.id): # mail was fetched before if self._memorizer.is_unseen(mail.id): # mail was not marked as seen unseen_mails.append(mail) if self._firstcheck: new_mails.append(mail) else: # mail is fetched the first time unseen_mails.append(mail) new_mails.append(mail) self._memorizer.sync(all_mails) self._memorizer.save() self._firstcheck = False # apply filter plugin hooks filtered_unseen_mails = unseen_mails for f in self._hookreg.get_hook_funcs(HookTypes.FILTER_MAILS): filtered_unseen_mails = try_call( lambda: f(filtered_unseen_mails), filtered_unseen_mails ) filtered_new_mails = [m for m in new_mails if m in filtered_unseen_mails] if len(filtered_new_mails) > 0: for f in self._hookreg.get_hook_funcs(HookTypes.MAILS_ADDED): try_call( lambda: f(filtered_new_mails, filtered_unseen_mails) ) elif (not self._zero_mails_on_last_check) and (len(filtered_unseen_mails) == 0): # TODO : signal MailsRemoved if not all mails have been removed # (i.e. if mailcount has been decreased) for f in self._hookreg.get_hook_funcs(HookTypes.MAILS_REMOVED): try_call( lambda: f(filtered_unseen_mails) ) self._zero_mails_on_last_check = (filtered_unseen_mails == 0) return