From fddd3d831b6a34a47b1e68fcaa1bc63d54240df5 Mon Sep 17 00:00:00 2001 From: Jed Brown Date: Sun, 29 Nov 2009 00:19:36 +0100 Subject: [PATCH] notmuch-reply.c: Handle munged `Reply-To' headers. Some mailing lists engage in the evil practice of changing the Reply-To header so that replies from all mailers go to the list by default, at the expense of not responding to the person who actually sent the message. When this is detected, we reply to `From' and remove the duplicate response to the mailing list. Consider a reply to the following message. From: Some User To: Sample users list Reply-To: Sample users list Prior to this patch, `notmuch reply' produces To: Sample users list , Sample users list and after the patch, To: Some User , Sample users list Signed-off-by: Jed Brown --- notmuch-reply.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/notmuch-reply.c b/notmuch-reply.c index 3ec30345..cb42de45 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -188,6 +188,39 @@ add_recipients_for_string (GMimeMessage *message, return add_recipients_for_address_list (message, config, type, list); } +/* Some mailing lists munge the Reply-To header despite it being A Bad + * Thing, see http://www.unicom.com/pw/reply-to-harmful.html + * + * This function detects such munging so that reasonable headers can be + * generated anyway. Returns 1 if munged, else 0. + * + * The current logic is fairly naive, Reply-To is diagnosed as munged if + * it contains exactly one address, and this address is also present in + * the To or Cc fields. + */ +static int +mailing_list_munged_reply_to (notmuch_message_t *message) +{ + const char *header, *addr; + InternetAddressList *list; + InternetAddress *address; + InternetAddressMailbox *mailbox; + + header = notmuch_message_get_header (message, "reply-to"); + list = internet_address_list_parse_string (header); + if (internet_address_list_length (list) != 1) + return 0; + address = internet_address_list_get_address (list, 0); + if (INTERNET_ADDRESS_IS_GROUP (address)) + return 0; + mailbox = INTERNET_ADDRESS_MAILBOX (address); + addr = internet_address_mailbox_get_addr (mailbox); + /* Note that strcasestr() is a GNU extension, strstr() might be sufficient */ + if (strcasestr (notmuch_message_get_header (message, "to"), addr) == 0 || + strcasestr (notmuch_message_get_header (message, "cc"), addr) == 0) + return 1; + return 0; } + /* Augments the recipients of reply from the headers of message. * * If any of the user's addresses were found in these headers, the first @@ -198,7 +231,7 @@ add_recipients_from_message (GMimeMessage *reply, notmuch_config_t *config, notmuch_message_t *message) { - static const struct { + struct { const char *header; const char *fallback; GMimeRecipientType recipient_type; @@ -211,6 +244,18 @@ add_recipients_from_message (GMimeMessage *reply, const char *from_addr = NULL; unsigned int i; + /* When we have detected Reply-To munging, we ignore the Reply-To + * field (because it appears in the To or Cc headers) and use the + * From header so that person will get pinged and will actually + * receive the response if not subscribed to the list. Note that + * under no circumstances does this fail to reply to the address in + * the Reply-To header. + */ + if (mailing_list_munged_reply_to (message)) { + reply_to_map[0].header = "from"; + reply_to_map[0].fallback = NULL; + } + for (i = 0; i < ARRAY_SIZE (reply_to_map); i++) { const char *addr, *recipients;