diff options
Diffstat (limited to 'alot')
-rw-r--r-- | alot/account.py | 25 | ||||
-rw-r--r-- | alot/commands/thread.py | 46 | ||||
-rw-r--r-- | alot/db/thread.py | 16 | ||||
-rw-r--r-- | alot/settings/manager.py | 8 |
4 files changed, 53 insertions, 42 deletions
diff --git a/alot/account.py b/alot/account.py index c8f3c09a..116c3417 100644 --- a/alot/account.py +++ b/alot/account.py @@ -9,6 +9,7 @@ import logging import mailbox import operator import os +import re from .helper import call_cmd_async from .helper import split_commandstring @@ -176,7 +177,7 @@ class Account(object): """this accounts main email address""" aliases = [] """list of alternative addresses""" - alias_regexp = [] + alias_regexp = "" """regex matching alternative addresses""" realname = None """real name used to format from-headers""" @@ -243,12 +244,34 @@ class Account(object): encrypt_by_default = u"none" logging.info(msg) self.encrypt_by_default = encrypt_by_default + # cache alias_regexp regexes + if self.alias_regexp != "": + self._alias_regexp = re.compile( + u'^' + str(self.alias_regexp) + u'$', + flags=0 if case_sensitive_username else re.IGNORECASE) + def get_addresses(self): """return all email addresses connected to this account, in order of their importance""" return [self.address] + self.aliases + def matches_address(self, address): + """returns whether this account knows about an email address + + :param str address: address to look up + :rtype: bool + """ + if self.address == address: + return True + for alias in self.aliases: + if alias == address: + return True + if self._alias_regexp is not None: + if self._alias_regexp.match(address): + return True + return False + @staticmethod def store_mail(mbx, mail): """ diff --git a/alot/commands/thread.py b/alot/commands/thread.py index f68e5405..3fbe8148 100644 --- a/alot/commands/thread.py +++ b/alot/commands/thread.py @@ -6,7 +6,6 @@ import argparse import logging import mailcap import os -import re import subprocess import tempfile import email @@ -69,35 +68,23 @@ def determine_sender(mail, action='reply'): logging.debug('candidate addresses: %s', candidate_addresses) # pick the most important account that has an address in candidates - # and use that accounts realname and the address found here + # and use that account's realname and the address found here for account in my_accounts: - acc_addresses = [ - re.escape(str(a)) for a in account.get_addresses()] - if account.alias_regexp is not None: - acc_addresses.append(account.alias_regexp) - for alias in acc_addresses: - regex = re.compile( - u'^' + str(alias) + u'$', - flags=( - re.IGNORECASE if not account.address.case_sensitive - else 0)) - for seen_name, seen_address in candidate_addresses: - if not regex.match(seen_address): - continue - logging.debug("match!: '%s' '%s'", seen_address, alias) + for seen_name, seen_address in candidate_addresses: + if account.matches_address(seen_address): if settings.get(action + '_force_realname'): realname = account.realname else: realname = seen_name if settings.get(action + '_force_address'): - address = account.address + address = str(account.address) else: address = seen_address logging.debug('using realname: "%s"', realname) logging.debug('using address: %s', address) - from_value = formataddr((realname, str(address))) + from_value = formataddr((realname, address)) return from_value, account # revert to default account if nothing found @@ -199,24 +186,23 @@ class ReplyCommand(Command): # set To sender = mail['Reply-To'] or mail['From'] - my_addresses = settings.get_addresses() sender_address = parseaddr(sender)[1] cc = [] # check if reply is to self sent message - if sender_address in my_addresses: + if account.matches_address(sender_address): recipients = mail.get_all('To', []) emsg = 'Replying to own message, set recipients to: %s' \ % recipients logging.debug(emsg) else: - recipients = self.clear_my_address([], [sender]) + recipients = [sender] if self.groupreply: # make sure that our own address is not included # if the message was self-sent, then our address is not included MFT = mail.get_all('Mail-Followup-To', []) - followupto = self.clear_my_address(my_addresses, MFT) + followupto = self.clear_my_address(account, MFT) if followupto and settings.get('honor_followup_to'): logging.debug('honor followup to: %s', ', '.join(followupto)) recipients = followupto @@ -226,15 +212,15 @@ class ReplyCommand(Command): recipients.append(mail['From']) # append To addresses if not replying to self sent message - if sender_address not in my_addresses: + if not account.matches_address(sender_address): cleared = self.clear_my_address( - my_addresses, mail.get_all('To', [])) + account, mail.get_all('To', [])) recipients.extend(cleared) # copy cc for group-replies if 'Cc' in mail: cc = self.clear_my_address( - my_addresses, mail.get_all('Cc', [])) + account, mail.get_all('Cc', [])) envelope.add('Cc', decode_header(', '.join(cc))) to = ', '.join(self.ensure_unique_address(recipients)) @@ -293,11 +279,11 @@ class ReplyCommand(Command): encrypt=encrypt)) @staticmethod - def clear_my_address(my_addresses, value): - """return recipient header without the addresses in my_addresses + def clear_my_address(my_account, value): + """return recipient header without the addresses in my_account - :param my_addresses: a list of my email addresses (no real name part) - :type my_addresses: list(str) + :param my_account: my account + :type my_account: :class:`Account` :param value: a list of recipient or sender strings (with or without real names as taken from email headers) :type value: list(str) @@ -306,7 +292,7 @@ class ReplyCommand(Command): """ new_value = [] for name, address in getaddresses(value): - if address not in my_addresses: + if not my_account.matches_address(address): new_value.append(formataddr((name, str(address)))) return new_value diff --git a/alot/db/thread.py b/alot/db/thread.py index fe7ea10f..0943d815 100644 --- a/alot/db/thread.py +++ b/alot/db/thread.py @@ -174,14 +174,14 @@ class Thread(object): return self._authors - def get_authors_string(self, own_addrs=None, replace_own=None): + def get_authors_string(self, own_accts=None, replace_own=None): """ returns a string of comma-separated authors Depending on settings, it will substitute "me" for author name if address is user's own. - :param own_addrs: list of own email addresses to replace - :type own_addrs: list of str + :param own_accts: list of own accounts to replace + :type own_accts: list of :class:`Account` :param replace_own: whether or not to actually do replacement :type replace_own: bool :rtype: str @@ -189,12 +189,14 @@ class Thread(object): if replace_own is None: replace_own = settings.get('thread_authors_replace_me') if replace_own: - if own_addrs is None: - own_addrs = settings.get_addresses() + if own_accts is None: + own_accts = settings.get_accounts() authorslist = [] for aname, aaddress in self.get_authors(): - if aaddress in own_addrs: - aname = settings.get('thread_authors_me') + for account in own_accts: + if account.matches_address(aaddress): + aname = settings.get('thread_authors_me') + break if not aname: aname = aaddress if aname not in authorslist: diff --git a/alot/settings/manager.py b/alot/settings/manager.py index d1f57083..87ae14c7 100644 --- a/alot/settings/manager.py +++ b/alot/settings/manager.py @@ -469,16 +469,16 @@ class SettingsManager(object): :param str address: address to look up. A realname part will be ignored. :param bool return_default: If True and no address can be found, then - the default account wil be returned + the default account wil be returned. :rtype: :class:`Account` :raises ~alot.settings.errors.NoMatchingAccount: If no account can be found. This includes if return_default is True and there are no accounts defined. """ _, address = email.utils.parseaddr(address) - for myad in self.get_addresses(): - if myad == address: - return self._accountmap[myad] + for account in self.get_accounts(): + if account.matches_address(address): + return account if return_default: try: return self.get_accounts()[0] |