[Remail] [RFC/RFT V2 patch 2/2] remail: Provide a less convoluted From: header mangling
Thomas Gleixner
tglx at linutronix.de
Tue Jun 13 21:43:23 CEST 2023
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:
The default 'From:' header mangling converts the original sender mail
address '[Name] <mailname at sender.domain> to:
'list-name for mailname_at_sender_domain' <list-name at list.domain>
This is hard to read and follow.
Add a new option to make this less hideous. So the 'From:' mangling results
in:
'Name via list-name' <list-name at 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 at 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 at linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
---
V2: Remove the stray colon and fix the mistyped import
---
Documentation/man5/remail.config.rst | 22 +++++++++++++++++++
remail/config.py | 1
remail/mail.py | 7 ++++++
remail/maillist.py | 39 ++++++++++++++++++++++++++---------
4 files changed, 60 insertions(+), 9 deletions(-)
--- a/Documentation/man5/remail.config.rst
+++ b/Documentation/man5/remail.config.rst
@@ -264,6 +264,7 @@ Base configuration items
moderated: True
attach_sender_info: False
set_original_from: False
+ mangle_from_v2: False
listid: ...
archive:
...
@@ -282,6 +283,7 @@ Base configuration items
moderated: True
attach_sender_info: False
set_original_from: False
+ mangle_from_v2: False
enabled:
@@ -312,6 +314,26 @@ Base configuration items
original 'From:' mail header, which has to be rewritten due to
re-encryption.
+ mangle_from_v2:
+
+ The default 'From:' header mangling converts the original sender mail
+ address to:
+
+ 'list-name for mailname_at_sender_domain' <list-name at list.domain>
+
+ This is hard to read and follow. Set this option to true if you want
+ to have a more readable variant:
+
+ 'Name via list-name' <list-name at 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 at list.domain>
+
+ The 'via list-name' add on is technically not required but is useful to
+ visually differentiate the name in auto-completion.
+
listid:
Optional item to override the default list-id with a custom value.
--- a/remail/config.py
+++ b/remail/config.py
@@ -269,6 +269,7 @@ list_defaults = {
'moderated' : False,
'attach_sender_info' : False,
'set_original_from' : False,
+ 'mangle_from_v2' : False,
}
class list_config(object):
--- a/remail/mail.py
+++ b/remail/mail.py
@@ -159,6 +159,13 @@ re_mail = re.compile('^\w+([\.-]?\w+)*@\
except:
return addr
+def get_name_and_email_addr(addr):
+ try:
+ name, addr = addr.split('<')
+ except:
+ name = ''
+ return name.strip(), addr.lstrip('<').rstrip('>')
+
re_compress_space = re.compile('\s+')
def decode_hdr(hdr):
--- a/remail/maillist.py
+++ b/remail/maillist.py
@@ -8,6 +8,7 @@ from remail.mail import msg_set_header,
from remail.mail import msg_sanitize_incoming, msg_is_autoreply
from remail.mail import get_raw_email_addr, decode_addrs
from remail.mail import msg_from_string, sender_info
+from remail.mail import get_name_and_email_addr
from remail.smime import smime_crypt, RemailSmimeException
from remail.gpg import gpg_crypt, RemailGPGException
@@ -230,24 +231,43 @@ import os
dest.toadmins = True
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':
- From: $LISTNAME for $ORIGINAL_FROM <$LISTADDRESS>
+ mangle_from_v1:
- If $ORIGINAL_FROM does not contain a name, mangle the email
- address by replacing @ with _at_
+ Mangle the email address @mfrom by replacing '@' with '_at_'
+ and replacing the 'From:' header with:
+
+ 'list-name for @mfrom' <list-name at list.domain>
+
+ mangle_from_v2:
+
+ If @name is non-empty then replace the 'From:' header with:
+
+ '@name via list-name' <list-name at list.domain>
+
+ 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 at list.domain>
'''
mfrom = mfrom.replace('@','_at_')
- return '%s for %s <%s>' % (self.config.name, mfrom,
- self.config.listaddrs.post)
+
+ if not self.config.mangle_from_v2:
+ return '%s for %s <%s>' %(self.config.name, mfrom,
+ self.config.listaddrs.post)
+ if len(name) == 0:
+ name = mfrom
+
+ return '%s via %s <%s>' %(name, self.config.name,
+ self.config.listaddrs.post)
def do_process_mail(self, msg, dest):
msgid = msg.get('Message-Id', '<No ID>')
msgto = msg.get('To')
origfrom = msg.get('From')
- msgfrom = get_raw_email_addr(origfrom)
+ name, msgfrom = get_name_and_email_addr(origfrom)
sinfo = sender_info(msg)
# Archive the incoming mail
@@ -266,7 +286,8 @@ import os
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?
if self.config.attach_sender_info:
# Only do so for non-subscribers
More information about the Remail
mailing list