using the List-Post header to reply to mailing lists
authorKushal Kumaran <kushal.kumaran+notmuch@gmail.com>
Tue, 4 Dec 2012 09:42:50 +0000 (15:12 +0530)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:51:26 +0000 (09:51 -0800)
ee/980266331ced4f76e83c88ec555569839ca1d4 [new file with mode: 0644]

diff --git a/ee/980266331ced4f76e83c88ec555569839ca1d4 b/ee/980266331ced4f76e83c88ec555569839ca1d4
new file mode 100644 (file)
index 0000000..48d6549
--- /dev/null
@@ -0,0 +1,216 @@
+Return-Path: <kushal.kumaran@gmail.com>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id 5A524431FB6\r
+       for <notmuch@notmuchmail.org>; Tue,  4 Dec 2012 01:42:58 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.799\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.799 tagged_above=-999 required=5\r
+       tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
+       FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id tBvTCPWgo2bO for <notmuch@notmuchmail.org>;\r
+       Tue,  4 Dec 2012 01:42:57 -0800 (PST)\r
+Received: from mail-pa0-f53.google.com (mail-pa0-f53.google.com\r
+       [209.85.220.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id A5C23431FAE\r
+       for <notmuch@notmuchmail.org>; Tue,  4 Dec 2012 01:42:57 -0800 (PST)\r
+Received: by mail-pa0-f53.google.com with SMTP id hz1so2720336pad.26\r
+       for <notmuch@notmuchmail.org>; Tue, 04 Dec 2012 01:42:56 -0800 (PST)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;\r
+       h=sender:from:to:subject:user-agent:date:message-id:mime-version\r
+       :content-type; bh=DtnATiaPfUta2NiUFCsfruTt4XpISb+275heM/CvfeI=;\r
+       b=DSEOS+sa77FEdGTIi4uAwfRcoHOfofPn3lhCSShjN7AmPaGqovqgh5MPoJT0zItbNP\r
+       H2z3DZdYVKRfMLIM1qTlFQxJLWczw3UhMP+fHt9AhiefqwtJ6fHgOlfCrJ29t1bYu6ZY\r
+       GqNJo0Qny/SpsbR+/Lar2Cjnf05PxbBiisV+S2RjOrj32wyqN5sRE5ln3+YBNZrGXKFR\r
+       5MqJWg84E9VND9gmRBwSWRPR9kN+34iuVxwgXi1dhLksFIQWaSFIYGk2KmruwR+rNmIF\r
+       0YK1M+L42Vj5u5R6TgHyA9ejff/lv+aNTbJKh6FYkbcY2USgespBQ6wiDtZgm9EbDSI+\r
+       xHFw==\r
+Received: by 10.68.232.195 with SMTP id tq3mr37183050pbc.70.1354614176862;\r
+       Tue, 04 Dec 2012 01:42:56 -0800 (PST)\r
+Received: from nitrogen ([117.219.4.209])\r
+       by mx.google.com with ESMTPS id ay5sm534700pab.1.2012.12.04.01.42.54\r
+       (version=TLSv1/SSLv3 cipher=OTHER);\r
+       Tue, 04 Dec 2012 01:42:56 -0800 (PST)\r
+Sender: Kushal Kumaran <kushal.kumaran@gmail.com>\r
+Received: by nitrogen (Postfix, from userid 1000)\r
+       id 230581201C1; Tue,  4 Dec 2012 15:12:50 +0530 (IST)\r
+From: Kushal Kumaran <kushal.kumaran+notmuch@gmail.com>\r
+To: notmuch@notmuchmail.org\r
+Subject: using the List-Post header to reply to mailing lists\r
+User-Agent: Notmuch/0.14+83~gae459a3 (http://notmuchmail.org) Emacs/24.1.1\r
+       (x86_64-pc-linux-gnu)\r
+Date: Tue, 04 Dec 2012 15:12:50 +0530\r
+Message-ID: <50bdc5a0.8557420a.08a9.324b@mx.google.com>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Tue, 04 Dec 2012 09:42:58 -0000\r
+\r
+Hi,\r
+\r
+I've been using notmuch with emacs for a while now.  I subscribe to a\r
+few mailing lists where Reply-To-All is severely frowned upon, so I\r
+wanted to be able to use the List-Post header (RFC2369) when replying to\r
+mailing list posts.  I've hacked notmuch-reply.c for my purposes, but I\r
+was wondering how other people manage.\r
+\r
+As it stands, this patch is entirely unsuitable for merging.  At least\r
+the following issues will need to be resolved first:\r
+\r
+- should an additional command-line option be added to invoke this\r
+  behaviour?  My personal preference is to just use the List-Post header\r
+  whenever possible, if --reply-to=all is not given.\r
+\r
+- should anything be done if the List-Post header has a URL which is not\r
+  a mailto: URL (start a web browser?).  None of the mailing lists I'm\r
+  subscribed to puts anything other than mailto.  The patch ignores the\r
+  header if the URL is not a mailto.\r
+\r
+- needs tests\r
+\r
+- needs documentation\r
+\r
+If anyone has alternatives to doing this kind of URL parsing, I'm\r
+interested.  Comments regarding my pathetic knowledge of gmime are also\r
+welcome.  If no one things notmuch needs this functionality, I will just\r
+hold on to it for my personal use.\r
+\r
+---\r
+ notmuch-reply.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++-------\r
+ 1 file changed, 60 insertions(+), 8 deletions(-)\r
+\r
+diff --git a/notmuch-reply.c b/notmuch-reply.c\r
+index e60a264..82f5a35 100644\r
+--- a/notmuch-reply.c\r
++++ b/notmuch-reply.c\r
+@@ -172,6 +172,11 @@ address_is_users (const char *address, notmuch_config_t *config)\r
+     return address_match (address, config, STRING_IS_USER_ADDRESS) != NULL;\r
+ }\r
+\r
++typedef enum {\r
++    rfc822,\r
++    url\r
++} address_format_t;\r
++\r
+ /* Scan addresses in 'list'.\r
+  *\r
+  * If 'message' is non-NULL, then for each address in 'list' that is\r
+@@ -231,6 +236,37 @@ scan_address_list (InternetAddressList *list,\r
+     return n;\r
+ }\r
+\r
++InternetAddressList *list_post_url_to_address_list(const char *header_value) {\r
++    size_t recipients_len = strlen(header_value);\r
++    size_t list_post_prefix_len = strlen("<mailto:");\r
++    char *list_post_url;\r
++    InternetAddressList *list;\r
++    InternetAddress *list_post_addr;\r
++\r
++    recipients_len = strlen(header_value);\r
++\r
++    if (strncmp(header_value, "<mailto:", list_post_prefix_len) != 0) {\r
++      return NULL;\r
++    }\r
++\r
++    if (header_value[recipients_len - 1] != '>') {\r
++      return NULL;\r
++    }\r
++\r
++    list_post_url = xstrdup(header_value);\r
++    list_post_url[recipients_len - 1] = '\0';\r
++    list_post_addr = internet_address_mailbox_new(NULL, list_post_url +\r
++                                                list_post_prefix_len);\r
++    list = internet_address_list_new();\r
++    if (list == NULL) {\r
++      return NULL;\r
++    }\r
++    internet_address_list_add(list, list_post_addr);\r
++    free(list_post_url);\r
++\r
++    return list;\r
++}\r
++\r
+ /* Scan addresses in 'recipients'.\r
+  *\r
+  * See the documentation of scan_address_list() above. This function\r
+@@ -242,6 +278,7 @@ scan_address_string (const char *recipients,\r
+                    notmuch_config_t *config,\r
+                    GMimeMessage *message,\r
+                    GMimeRecipientType type,\r
++                   address_format_t format,\r
+                    const char **user_from)\r
+ {\r
+     InternetAddressList *list;\r
+@@ -249,9 +286,21 @@ scan_address_string (const char *recipients,\r
+     if (recipients == NULL)\r
+       return 0;\r
+\r
+-    list = internet_address_list_parse_string (recipients);\r
+-    if (list == NULL)\r
+-      return 0;\r
++    switch (format) {\r
++    case rfc822:\r
++      list = internet_address_list_parse_string (recipients);\r
++      if (list == NULL)\r
++          return 0;\r
++\r
++      break;\r
++\r
++    case url:\r
++      list = list_post_url_to_address_list (recipients);\r
++      if (list == NULL)\r
++          return 0;\r
++\r
++      break;\r
++    }\r
+\r
+     return scan_address_list (list, config, message, type, user_from);\r
+ }\r
+@@ -317,11 +366,13 @@ add_recipients_from_message (GMimeMessage *reply,\r
+       const char *header;\r
+       const char *fallback;\r
+       GMimeRecipientType recipient_type;\r
++      address_format_t format;\r
+     } reply_to_map[] = {\r
+-      { "reply-to", "from", GMIME_RECIPIENT_TYPE_TO  },\r
+-      { "to",         NULL, GMIME_RECIPIENT_TYPE_TO  },\r
+-      { "cc",         NULL, GMIME_RECIPIENT_TYPE_CC  },\r
+-      { "bcc",        NULL, GMIME_RECIPIENT_TYPE_BCC }\r
++      { "list-post",  NULL, GMIME_RECIPIENT_TYPE_TO,  url },\r
++      { "reply-to", "from", GMIME_RECIPIENT_TYPE_TO,  rfc822  },\r
++      { "to",         NULL, GMIME_RECIPIENT_TYPE_TO,  rfc822  },\r
++      { "cc",         NULL, GMIME_RECIPIENT_TYPE_CC,  rfc822  },\r
++      { "bcc",        NULL, GMIME_RECIPIENT_TYPE_BCC, rfc822  }\r
+     };\r
+     const char *from_addr = NULL;\r
+     unsigned int i;\r
+@@ -353,7 +404,8 @@ add_recipients_from_message (GMimeMessage *reply,\r
+                                                    reply_to_map[i].fallback);\r
+\r
+       n += scan_address_string (recipients, config, reply,\r
+-                                reply_to_map[i].recipient_type, &from_addr);\r
++                                reply_to_map[i].recipient_type,\r
++                                reply_to_map[i].format, &from_addr);\r
+\r
+       if (!reply_all && n) {\r
+           /* Stop adding new recipients in reply-to-sender mode if\r
+[ 2-line signature. Click/Enter to show. ]\r
+-- \r
+1.7.10.4\r