using the List-Post header to reply to mailing lists

Kushal Kumaran kushal.kumaran+notmuch at gmail.com
Tue Dec 4 01:42:50 PST 2012


Hi,

I've been using notmuch with emacs for a while now.  I subscribe to a
few mailing lists where Reply-To-All is severely frowned upon, so I
wanted to be able to use the List-Post header (RFC2369) when replying to
mailing list posts.  I've hacked notmuch-reply.c for my purposes, but I
was wondering how other people manage.

As it stands, this patch is entirely unsuitable for merging.  At least
the following issues will need to be resolved first:

- should an additional command-line option be added to invoke this
  behaviour?  My personal preference is to just use the List-Post header
  whenever possible, if --reply-to=all is not given.

- should anything be done if the List-Post header has a URL which is not
  a mailto: URL (start a web browser?).  None of the mailing lists I'm
  subscribed to puts anything other than mailto.  The patch ignores the
  header if the URL is not a mailto.

- needs tests

- needs documentation

If anyone has alternatives to doing this kind of URL parsing, I'm
interested.  Comments regarding my pathetic knowledge of gmime are also
welcome.  If no one things notmuch needs this functionality, I will just
hold on to it for my personal use.

---
 notmuch-reply.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 60 insertions(+), 8 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index e60a264..82f5a35 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -172,6 +172,11 @@ address_is_users (const char *address, notmuch_config_t *config)
     return address_match (address, config, STRING_IS_USER_ADDRESS) != NULL;
 }

+typedef enum {
+    rfc822,
+    url
+} address_format_t;
+
 /* Scan addresses in 'list'.
  *
  * If 'message' is non-NULL, then for each address in 'list' that is
@@ -231,6 +236,37 @@ scan_address_list (InternetAddressList *list,
     return n;
 }

+InternetAddressList *list_post_url_to_address_list(const char *header_value) {
+    size_t recipients_len = strlen(header_value);
+    size_t list_post_prefix_len = strlen("<mailto:");
+    char *list_post_url;
+    InternetAddressList *list;
+    InternetAddress *list_post_addr;
+
+    recipients_len = strlen(header_value);
+
+    if (strncmp(header_value, "<mailto:", list_post_prefix_len) != 0) {
+	return NULL;
+    }
+
+    if (header_value[recipients_len - 1] != '>') {
+	return NULL;
+    }
+
+    list_post_url = xstrdup(header_value);
+    list_post_url[recipients_len - 1] = '\0';
+    list_post_addr = internet_address_mailbox_new(NULL, list_post_url +
+						  list_post_prefix_len);
+    list = internet_address_list_new();
+    if (list == NULL) {
+	return NULL;
+    }
+    internet_address_list_add(list, list_post_addr);
+    free(list_post_url);
+
+    return list;
+}
+
 /* Scan addresses in 'recipients'.
  *
  * See the documentation of scan_address_list() above. This function
@@ -242,6 +278,7 @@ scan_address_string (const char *recipients,
		     notmuch_config_t *config,
		     GMimeMessage *message,
		     GMimeRecipientType type,
+		     address_format_t format,
		     const char **user_from)
 {
     InternetAddressList *list;
@@ -249,9 +286,21 @@ scan_address_string (const char *recipients,
     if (recipients == NULL)
	return 0;

-    list = internet_address_list_parse_string (recipients);
-    if (list == NULL)
-	return 0;
+    switch (format) {
+    case rfc822:
+	list = internet_address_list_parse_string (recipients);
+	if (list == NULL)
+	    return 0;
+
+	break;
+
+    case url:
+	list = list_post_url_to_address_list (recipients);
+	if (list == NULL)
+	    return 0;
+
+	break;
+    }

     return scan_address_list (list, config, message, type, user_from);
 }
@@ -317,11 +366,13 @@ add_recipients_from_message (GMimeMessage *reply,
	const char *header;
	const char *fallback;
	GMimeRecipientType recipient_type;
+	address_format_t format;
     } reply_to_map[] = {
-	{ "reply-to", "from", GMIME_RECIPIENT_TYPE_TO  },
-	{ "to",         NULL, GMIME_RECIPIENT_TYPE_TO  },
-	{ "cc",         NULL, GMIME_RECIPIENT_TYPE_CC  },
-	{ "bcc",        NULL, GMIME_RECIPIENT_TYPE_BCC }
+	{ "list-post",  NULL, GMIME_RECIPIENT_TYPE_TO,  url },
+	{ "reply-to", "from", GMIME_RECIPIENT_TYPE_TO,  rfc822  },
+	{ "to",         NULL, GMIME_RECIPIENT_TYPE_TO,  rfc822  },
+	{ "cc",         NULL, GMIME_RECIPIENT_TYPE_CC,  rfc822  },
+	{ "bcc",        NULL, GMIME_RECIPIENT_TYPE_BCC, rfc822  }
     };
     const char *from_addr = NULL;
     unsigned int i;
@@ -353,7 +404,8 @@ add_recipients_from_message (GMimeMessage *reply,
						     reply_to_map[i].fallback);

	n += scan_address_string (recipients, config, reply,
-				  reply_to_map[i].recipient_type, &from_addr);
+				  reply_to_map[i].recipient_type,
+				  reply_to_map[i].format, &from_addr);

	if (!reply_all && n) {
	    /* Stop adding new recipients in reply-to-sender mode if
[ 2-line signature. Click/Enter to show. ]
-- 
1.7.10.4


More information about the notmuch mailing list