1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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
|