summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2021-11-24 08:49:34 +0100
committerAnton Khirnov <anton@khirnov.net>2021-11-24 08:50:47 +0100
commitdf4adbe93a861bc1a092c066dbb9f855475427f2 (patch)
treebbcdb3df1394d82d527e8ca0085a24ea6f42fae0
parent74e77ea975804229779115286ddd023b73955557 (diff)
commands/thread: move determining reply recipients to mail/reply
-rw-r--r--alot/commands/thread.py96
-rw-r--r--alot/mail/reply.py96
2 files changed, 100 insertions, 92 deletions
diff --git a/alot/commands/thread.py b/alot/commands/thread.py
index 9b3c56b9..5ec8eac4 100644
--- a/alot/commands/thread.py
+++ b/alot/commands/thread.py
@@ -7,7 +7,6 @@ import argparse
import asyncio
import email
import email.policy
-from email.utils import getaddresses, parseaddr
import logging
import mailcap
import os
@@ -42,35 +41,6 @@ from ..utils.mailcap import MailcapHandler
MODE = 'thread'
-def ensure_unique_address(recipients):
- """
- clean up a list of name,address pairs so that
- no address appears multiple times.
- """
- res = dict()
- for name, address in getaddresses(recipients):
- res[address] = name
- logging.debug(res)
- urecipients = [formataddr((n, a)) for a, n in res.items()]
- return sorted(urecipients)
-
-def clear_my_address(my_account, value):
- """return recipient header without the addresses in my_account
-
- :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)
- :returns: a new, potentially shortend list
- :rtype: list(str)
- """
- new_value = []
- for name, address in getaddresses(value):
- if not my_account.matches_address(address):
- new_value.append(formataddr((name, address)))
- return new_value
-
@registerCommand(MODE, 'reply', arguments=[
(['--all'], {'action': 'store_true', 'help': 'reply to all'}),
(['--list'], {'action': cargparse.BooleanAction, 'default': None,
@@ -105,66 +75,6 @@ class ReplyCommand(Command):
return bool(self._force_list_reply)
- def _determine_recipients(self, message, account):
- # set To
- sender = (message.headers.get(HDR.REPLY_TO) or
- message.headers.get(HDR.FROM) or '')
- sender_address = parseaddr(sender)[1]
- cc = []
-
- # check if reply is to self sent message
- if account.matches_address(sender_address):
- recipients = message.headers.get_all(HDR.TO)
- emsg = 'Replying to own message, set recipients to: %s' \
- % recipients
- logging.debug(emsg)
- else:
- 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 = message.headers.get_all(HDR.MAIL_FOLLOWUP_TO)
- followupto = clear_my_address(account, MFT)
- if followupto and settings.get('honor_followup_to'):
- logging.debug('honor followup to: %s', ', '.join(followupto))
- recipients = followupto
- # since Mail-Followup-To was set, ignore the Cc header
- else:
- if sender != message.headers.get(HDR.FROM):
- recipients.append(message.headers.get(HDR.FROM))
-
- # append To addresses if not replying to self sent message
- if not account.matches_address(sender_address):
- cleared = clear_my_address(account,
- message.headers.get_all(HDR.TO))
- recipients.extend(cleared)
-
- # copy cc for group-replies
- if HDR.CC in message.headers:
- cc = clear_my_address(account, message.headers.get_all(HDR.CC))
-
- to = ', '.join(ensure_unique_address(recipients))
- cc = ', '.join(cc)
- logging.debug('reply to: %s', to)
-
- if self._list_reply(message):
- # To choose the target of the reply --list
- # Reply-To is standart reply target RFC 2822:, RFC 1036: 2.2.1
- # X-BeenThere is needed by sourceforge ML also winehq
- # X-Mailing-List is also standart and is used by git-send-mail
- to = (message.headers.get(HDR.REPLY_TO) or
- message.headers.get(HDR.X_BEEN_THERE) or
- message.headers.get(HDR.X_MAILING_LIST))
-
- # Some mail server (gmail) will not resend you own mail, so you
- # have to deal with the one in sent
- if to is None:
- to = message.headers[HDR.TO]
- logging.debug('mail list reply to: %s', to)
-
- return to, cc
-
async def apply(self, ui):
message = ui.current_buffer.get_selected_message()
@@ -183,7 +93,11 @@ class ReplyCommand(Command):
headers[HDR.FROM] = from_header
# set the recipients
- to, cc = self._determine_recipients(message, account)
+ mode = reply.ReplyMode.LIST if self._list_reply(message) else \
+ reply.ReplyMode.GROUP if self.groupreply else \
+ reply.ReplyMode.AUTHOR
+
+ to, cc = reply.determine_recipients(message, account, mode)
headers[HDR.TO] = to
if cc:
headers[HDR.CC] = cc
diff --git a/alot/mail/reply.py b/alot/mail/reply.py
index 0e7d897e..4a69ecee 100644
--- a/alot/mail/reply.py
+++ b/alot/mail/reply.py
@@ -2,7 +2,8 @@
# For further details see the COPYING file
import email.policy
-from email.utils import getaddresses
+from email.utils import getaddresses, parseaddr
+from enum import Enum, auto
import logging
from . import headers as HDR
@@ -69,6 +70,99 @@ def determine_account(headers, action = ACT_REPLY):
from_value = formataddr((realname, str(address)))
return from_value, account
+class ReplyMode(Enum):
+ AUTHOR = auto()
+ GROUP = auto()
+ LIST = auto()
+
+def _ensure_unique_address(recipients):
+ """
+ clean up a list of name,address pairs so that
+ no address appears multiple times.
+ """
+ res = dict()
+ for name, address in getaddresses(recipients):
+ res[address] = name
+ logging.debug(res)
+ urecipients = [formataddr((n, a)) for a, n in res.items()]
+ return sorted(urecipients)
+
+def _clear_my_address(my_account, value):
+ """return recipient header without the addresses in my_account
+
+ :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)
+ :returns: a new, potentially shortend list
+ :rtype: list(str)
+ """
+ new_value = []
+ for name, address in getaddresses(value):
+ if not my_account.matches_address(address):
+ new_value.append(formataddr((name, address)))
+ return new_value
+
+def determine_recipients(message, account, mode):
+ # set To
+ sender = (message.headers.get(HDR.REPLY_TO) or
+ message.headers.get(HDR.FROM) or '')
+ sender_address = parseaddr(sender)[1]
+ cc = []
+
+ # check if reply is to self sent message
+ if account.matches_address(sender_address):
+ recipients = message.headers.get_all(HDR.TO)
+ emsg = 'Replying to own message, set recipients to: %s' \
+ % recipients
+ logging.debug(emsg)
+ else:
+ recipients = [sender]
+
+ if mode == ReplyMode.GROUP:
+ # make sure that our own address is not included
+ # if the message was self-sent, then our address is not included
+ MFT = message.headers.get_all(HDR.MAIL_FOLLOWUP_TO)
+ followupto = _clear_my_address(account, MFT)
+ if followupto and settings.get('honor_followup_to'):
+ logging.debug('honor followup to: %s', ', '.join(followupto))
+ recipients = followupto
+ # since Mail-Followup-To was set, ignore the Cc header
+ else:
+ if sender != message.headers.get(HDR.FROM):
+ recipients.append(message.headers.get(HDR.FROM))
+
+ # append To addresses if not replying to self sent message
+ if not account.matches_address(sender_address):
+ cleared = _clear_my_address(account,
+ message.headers.get_all(HDR.TO))
+ recipients.extend(cleared)
+
+ # copy cc for group-replies
+ if HDR.CC in message.headers:
+ cc = _clear_my_address(account, message.headers.get_all(HDR.CC))
+
+ to = ', '.join(_ensure_unique_address(recipients))
+ cc = ', '.join(cc)
+ logging.debug('reply to: %s', to)
+
+ if mode == ReplyMode.LIST:
+ # To choose the target of the reply --list
+ # Reply-To is standart reply target RFC 2822:, RFC 1036: 2.2.1
+ # X-BeenThere is needed by sourceforge ML also winehq
+ # X-Mailing-List is also standart and is used by git-send-mail
+ to = (message.headers.get(HDR.REPLY_TO) or
+ message.headers.get(HDR.X_BEEN_THERE) or
+ message.headers.get(HDR.X_MAILING_LIST))
+
+ # Some mail server (gmail) will not resend you own mail, so you
+ # have to deal with the one in sent
+ if to is None:
+ to = message.headers[HDR.TO]
+ logging.debug('mail list reply to: %s', to)
+
+ return to, cc
def subject(message):
subject = message.headers.get(HDR.SUBJECT) or ''