summaryrefslogtreecommitdiff
path: root/alot/mail/reply.py
diff options
context:
space:
mode:
Diffstat (limited to 'alot/mail/reply.py')
-rw-r--r--alot/mail/reply.py129
1 files changed, 129 insertions, 0 deletions
diff --git a/alot/mail/reply.py b/alot/mail/reply.py
new file mode 100644
index 00000000..0e7d897e
--- /dev/null
+++ b/alot/mail/reply.py
@@ -0,0 +1,129 @@
+# This file is released under the GNU GPL, version 3 or a later revision.
+# For further details see the COPYING file
+
+import email.policy
+from email.utils import getaddresses
+import logging
+
+from . import headers as HDR
+
+from ..helper import formataddr
+from ..settings.const import settings
+
+ACT_REPLY = 'reply'
+ACT_BOUNCE = 'bounce'
+ACT_FWD = 'forward'
+
+def determine_account(headers, action = ACT_REPLY):
+ """
+ Determine the local account to use for acting on a message with the given
+ headers.
+
+ :param headers: headers of the email to inspect
+ :type headers: `db.message._MessageHeaders`
+ :param action: intended use case: one of the ACT_* constants
+ :type action: str
+ :returns: 2-tuple of (from address, account)
+ """
+ # get accounts
+ my_accounts = settings.get_accounts()
+ assert my_accounts, 'no accounts set!'
+
+ # extract list of addresses to check for my address
+ # X-Envelope-To and Envelope-To are used to store the recipient address
+ # if not included in other fields
+ # Process the headers in order of importance: if a mail was sent with
+ # account X, with account Y in e.g. CC or delivered-to, make sure that
+ # account X is the one selected and not account Y.
+ for candidate_header in settings.get("reply_account_header_priority"):
+ candidate_addresses = getaddresses(headers.get_all(candidate_header))
+
+ logging.debug('candidate addresses: %s', candidate_addresses)
+ # pick the most important account that has an address in candidates
+ # and use that account's realname and the address found here
+ for account in my_accounts:
+ 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 = str(account.address)
+ else:
+ address = seen_address
+
+ logging.debug('using realname: "%s"', realname)
+ logging.debug('using address: %s', address)
+
+ from_value = formataddr((realname, address))
+ return from_value, account
+
+ # revert to default account if nothing found
+ account = my_accounts[0]
+ realname = account.realname
+ address = account.address
+ logging.debug('using realname: "%s"', realname)
+ logging.debug('using address: %s', address)
+
+ from_value = formataddr((realname, str(address)))
+ return from_value, account
+
+
+def subject(message):
+ subject = message.headers.get(HDR.SUBJECT) or ''
+ reply_subject_hook = settings.get_hook('reply_subject')
+ if reply_subject_hook:
+ subject = reply_subject_hook(subject)
+ else:
+ rsp = settings.get('reply_subject_prefix')
+ if not subject.lower().startswith(('re:', rsp.lower())):
+ subject = rsp + subject
+
+ return subject
+
+def body_text(message, ui):
+ name, address = message.get_author()
+ timestamp = message.date
+ qf = settings.get_hook('reply_prefix')
+ if qf:
+ mail = email.message_from_bytes(message.as_bytes(),
+ policy = email.policy.SMTP)
+ quotestring = qf(name, address, timestamp,
+ message=mail, ui=ui, dbm=ui.dbman)
+ else:
+ quotestring = 'Quoting %s (%s)\n' % (name or address, timestamp)
+ mailcontent = quotestring
+ quotehook = settings.get_hook('text_quote')
+ if quotehook:
+ mailcontent += quotehook(message.get_body_text())
+ else:
+ quote_prefix = settings.get('quote_prefix')
+ for line in message.get_body_text().splitlines():
+ mailcontent += quote_prefix + line + '\n'
+
+ return mailcontent
+
+def references(message):
+ old_references = message.headers.get(HDR.REFERENCES)
+ references = []
+
+ if old_references:
+ references = old_references.split()
+ # limit to 16 references, including the one we add
+ del references[1:-14]
+
+ references.append('<%s>' % message.id)
+ return ' '.join(references)
+
+def mail_followup_to(recipients):
+ if not settings.get('followup_to'):
+ return None
+
+ lists = settings.get('mailinglists')
+
+ # check if any recipient address matches a known mailing list
+ if any(addr in lists for n, addr in getaddresses(recipients)):
+ followupto = ', '.join(recipients)
+ logging.debug('mail followup to: %s', followupto)
+ return followupto