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 <some.user@example.com>
  To: Sample users list <sample-users@sample.org>
  Reply-To: Sample users list <sample-users@sample.org>

Prior to this patch, `notmuch reply' produces

  To: Sample users list <sample-users@sample.org>,
      Sample users list <sample-users@sample.org>

and after the patch,

  To: Some User <some.user@example.com>,
      Sample users list <sample-users@sample.org>

Signed-off-by: Jed Brown <jed@59A2.org>
This commit is contained in:
Jed Brown 2009-11-29 00:19:36 +01:00 committed by Carl Worth
parent fb50f31048
commit fddd3d831b

View file

@ -188,6 +188,39 @@ add_recipients_for_string (GMimeMessage *message,
return add_recipients_for_address_list (message, config, type, list); 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. /* Augments the recipients of reply from the headers of message.
* *
* If any of the user's addresses were found in these headers, the first * 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_config_t *config,
notmuch_message_t *message) notmuch_message_t *message)
{ {
static const struct { struct {
const char *header; const char *header;
const char *fallback; const char *fallback;
GMimeRecipientType recipient_type; GMimeRecipientType recipient_type;
@ -211,6 +244,18 @@ add_recipients_from_message (GMimeMessage *reply,
const char *from_addr = NULL; const char *from_addr = NULL;
unsigned int i; 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++) { for (i = 0; i < ARRAY_SIZE (reply_to_map); i++) {
const char *addr, *recipients; const char *addr, *recipients;