mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/tglx/remail.git
synced 2024-11-25 13:52:38 +01:00
remail: Make From header mangling less convoluted
Due to the requirement to reencrypt the incoming mail, remail must rewrite the mail headers and create a new email with the 'From:' header being the list address. So remail implemented a scheme to mangle the original senders name into the reencrypted mails 'From:' header. That fell flat on its nose when there was an incoming mail which had no name part and just consisted of the actual email address. Instead of differentiating between these cases the authors sleep deprived and grump laden brain decided to implement 'From:' mangling in the way it is now. It converts the original sender mail address '[Name] <mailname@sender.domain>' to: 'list-name for mailname_at_sender.domain' <list-name@list.domain> This is hard to read and follow. Use the common format: 'Name via list-name' <list-name@list.domain> Except for the case where the original 'From:' header is a plain email address without a name. This will mangle it to: 'mailname at sender.domain via list-name' <list-name@list.domain> The 'via list-name' add on is technically not required but is useful to visually differentiate the name in auto-completion. Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
424944ad36
commit
dc68e97937
1 changed files with 44 additions and 11 deletions
|
@ -14,7 +14,7 @@ from remail.gpg import gpg_crypt, RemailGPGException
|
||||||
from remail.tracking import account_tracking
|
from remail.tracking import account_tracking
|
||||||
from remail.config import accounts_config, gpg_config, smime_config
|
from remail.config import accounts_config, gpg_config, smime_config
|
||||||
|
|
||||||
from email.utils import make_msgid, formatdate, getaddresses
|
from email.utils import make_msgid, formatdate, getaddresses, parseaddr
|
||||||
from email.policy import EmailPolicy
|
from email.policy import EmailPolicy
|
||||||
from flufl.bounce import all_failures
|
from flufl.bounce import all_failures
|
||||||
|
|
||||||
|
@ -22,6 +22,10 @@ from ruamel.yaml import YAML
|
||||||
|
|
||||||
import mailbox
|
import mailbox
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
mustquote = re.compile(r'[][\\()<>@,:;".]')
|
||||||
|
escapedquote = re.compile(r'[\\"]')
|
||||||
|
|
||||||
class maillist(object):
|
class maillist(object):
|
||||||
'''
|
'''
|
||||||
|
@ -228,24 +232,52 @@ class maillist(object):
|
||||||
dest.toadmins = True
|
dest.toadmins = True
|
||||||
dest.accounts = self.config.admins
|
dest.accounts = self.config.admins
|
||||||
|
|
||||||
def mangle_from(self, msg, mfrom):
|
def mangle_from(self, msg, name, mfrom):
|
||||||
'''
|
'''
|
||||||
Build 'From' string so the original 'From' is 'visible':
|
If @name is non-empty then replace the 'From:' header with:
|
||||||
From: $LISTNAME for $ORIGINAL_FROM <$LISTADDRESS>
|
|
||||||
|
|
||||||
If $ORIGINAL_FROM does not contain a name, mangle the email
|
'@name via list-name' <list-name@list.domain>
|
||||||
address by replacing @ with _at_
|
|
||||||
|
If @name is empty mangle the email address @mfrom by replacing
|
||||||
|
'@' with at and setting the 'From:' header to:
|
||||||
|
|
||||||
|
'@mfrom via list-name' <list-name@list.domain>
|
||||||
'''
|
'''
|
||||||
mfrom = mfrom.replace('@','_at_')
|
if not len(name):
|
||||||
return '%s for %s <%s>' % (self.config.name, mfrom,
|
name = mfrom.replace('@',' at ')
|
||||||
self.config.listaddrs.post)
|
|
||||||
|
# Compose the display name
|
||||||
|
name = '%s via %s' %(name, self.config.name)
|
||||||
|
|
||||||
|
# Check whether it must be quoted
|
||||||
|
#
|
||||||
|
# email.utils.formataddr() fails to do so for non-ascii display
|
||||||
|
# names which causes some email-clients to display completely
|
||||||
|
# nonsensical names. Especially for the typical big corporate
|
||||||
|
# "name, surname" patterns as the resulting header entry becomes
|
||||||
|
#
|
||||||
|
# From: =?utf-8?q?NAME?=, =?utf-8?q?SURNAME?= <n@doma.in>
|
||||||
|
# which some clients render as:
|
||||||
|
# NAME@$SOMEMADEUPDOMAIN, SURNAME <n@doma.in>
|
||||||
|
#
|
||||||
|
# instead of
|
||||||
|
# From: =?utf-8?q?NAME=2C_SURNAME?= <n.doma.in>
|
||||||
|
# which they correctly render as:
|
||||||
|
# "NAME, SURNAME" <n@doma.in>
|
||||||
|
#
|
||||||
|
if mustquote.search(name):
|
||||||
|
name = escapedquote.sub(r'\\\g<0>', name)
|
||||||
|
name = '"%s"' %name
|
||||||
|
|
||||||
|
# The result is correcly handled by msg['From'] = result
|
||||||
|
return '%s <%s>' %(name, self.config.listaddrs.post)
|
||||||
|
|
||||||
def do_process_mail(self, msg, dest):
|
def do_process_mail(self, msg, dest):
|
||||||
|
|
||||||
msgid = msg.get('Message-Id', '<No ID>')
|
msgid = msg.get('Message-Id', '<No ID>')
|
||||||
msgto = msg.get('To')
|
msgto = msg.get('To')
|
||||||
origfrom = msg.get('From')
|
origfrom = msg.get('From')
|
||||||
msgfrom = get_raw_email_addr(origfrom)
|
name, msgfrom = parseaddr(origfrom)
|
||||||
sinfo = sender_info(msg)
|
sinfo = sender_info(msg)
|
||||||
|
|
||||||
# Archive the incoming mail
|
# Archive the incoming mail
|
||||||
|
@ -264,7 +296,8 @@ class maillist(object):
|
||||||
|
|
||||||
self.archive_mail(msg_plain, admin=dest.toadmin)
|
self.archive_mail(msg_plain, admin=dest.toadmin)
|
||||||
|
|
||||||
mfrom = self.mangle_from(msg, msgfrom)
|
mfrom = self.mangle_from(msg, name, msgfrom)
|
||||||
|
|
||||||
# Save sender information in the outgoing message?
|
# Save sender information in the outgoing message?
|
||||||
if self.config.attach_sender_info:
|
if self.config.attach_sender_info:
|
||||||
# Only do so for non-subscribers
|
# Only do so for non-subscribers
|
||||||
|
|
Loading…
Reference in a new issue