diff --git a/mailpile/config/defaults.py b/mailpile/config/defaults.py index 8de28a1..e4e54a1 100644 --- a/mailpile/config/defaults.py +++ b/mailpile/config/defaults.py @@ -154,6 +154,7 @@ CONFIG_RULES = { 'rescan_command': (_('Command run before rescanning'), str, ''), 'default_email': (_('Default outgoing e-mail address'), 'email', ''), 'default_route': (_('Default outgoing mail route'), str, ''), + 'msgid_domain': (_('Default outgoing message-id domain'), str, 'mailpile'), 'line_length': (_('Target line length, <40 disables reflow'), int, 65), 'always_bcc_self': (_('Always BCC self on outgoing mail'), bool, True), diff --git a/mailpile/mailutils/emails.py b/mailpile/mailutils/emails.py index 379781e..cb773d0 100644 --- a/mailpile/mailutils/emails.py +++ b/mailpile/mailutils/emails.py @@ -58,12 +58,15 @@ def MakeBoundary(): return '==%s==' % okay_random(30) -def MakeMessageID(): +def MakeMessageID(config): # We generate a message-ID which is almost entirely random; we # include an element of the local time (give-or-take 36 hours) # to further reduce the odds of any collision. - return '<%s%x@mailpile>' % ( - okay_random(40), time.time() // (3600*48)) + + domain = config.prefs.get('msgid_domain') or 'mailpile' + + return '<%s%x@%s>' % ( + okay_random(40), time.time() // (3600*48), domain) def MakeMessageDate(ts=None): @@ -407,7 +410,7 @@ class Email(object): msg['From'] = cls.encoded_hdr(None, 'from', value=msg_from) msg['Date'] = MakeMessageDate(msg_ts) - msg['Message-Id'] = msg_id or MakeMessageID() + msg['Message-Id'] = msg_id or MakeMessageID(idx.config) msg_subj = (msg_subject or '') msg['Subject'] = cls.encoded_hdr(None, 'subject', value=msg_subj) diff --git a/mailpile/plugins/compose.py b/mailpile/plugins/compose.py index 95cd53d..45fab14 100644 --- a/mailpile/plugins/compose.py +++ b/mailpile/plugins/compose.py @@ -113,7 +113,7 @@ def AddComposeMethods(cls): etype, etarg, msgid = msgid.split('-', 2) if etarg not in ('all', 'att'): msgid = etarg + '-' + msgid - msgid = '<%s>' % msgid.replace('_', '@') + msgid = '<%s>' % self._deesc_msgid(msgid) etype = etype.lower() enc_msgid = idx._encode_msg_id(msgid) @@ -142,6 +142,24 @@ def AddComposeMethods(cls): return Email(idx, e.msg_idx_pos) + def _new_msgid(self): + return MakeMessageID(self.session.config) + + @classmethod + # Make a Message-ID safe for CSS/JS, escape @ and ., + # and also _ so we can use as an escape character + def _esc_msgid(cls, msgid): + return (msgid.replace('_', '_0') + .replace('@', '_1') + .replace('.', '_2')) + + @classmethod + # Un-escape a Message-ID + def _deesc_msgid(cls, msgid): + return (msgid.replace('_2', '.') + .replace('_1', '@') + .replace('_0', '_')) + return newcls @@ -164,11 +182,6 @@ class CompositionCommand(AddComposeMethods(Search)): UPDATE_HEADERS = ('Subject', 'From', 'To', 'Cc', 'Bcc', 'Encryption', 'Attach-PGP-Pubkey') - def _new_msgid(self): - msgid = (MakeMessageID() - .replace('.', '-') # Dots may bother JS/CSS - .replace('_', '-')) # We use _ to encode the @ later on - return msgid def _get_email_updates(self, idx, create=False, noneok=False, emails=None): # Split the argument list into files and message IDs @@ -337,7 +350,7 @@ class Compose(CompositionCommand): local_id, lmbox = session.config.open_local_mailbox(session) else: local_id, lmbox = -1, None - ephemeral = ['new-E-%s-mail' % msgid[1:-1].replace('@', '_')] + ephemeral = ['new-E-%s-mail' % cls._esc_msgid(msgid[1:-1])] profiles = session.config.vcards.find_vcards([], kinds=['profile']) return (Email.Create(idx, local_id, lmbox, save=(not ephemeral), @@ -509,7 +522,7 @@ class Reply(RelativeCompose): else: local_id, lmbox = -1, None fmt = 'reply-all-%s-%s' if reply_all else 'reply-%s-%s' - ephemeral = [fmt % (msgid[1:-1].replace('@', '_'), + ephemeral = [fmt % (cls._esc_msgid(msgid[1:-1]), refs[0].msg_mid())] if 'cc' in headers: @@ -635,7 +648,7 @@ class Forward(RelativeCompose): else: local_id, lmbox = -1, None fmt = 'forward-att-%s-%s' if msg_atts else 'forward-%s-%s' - ephemeral = [fmt % (msgid[1:-1].replace('@', '_'), + ephemeral = [fmt % (cls._esc_msgid(msgid[1:-1]), refs[0].msg_mid())] if cid: