--- /dev/null
+Return-Path: <jani@nikula.org>\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 583E4431FDB\r
+ for <notmuch@notmuchmail.org>; Sat, 30 Nov 2013 07:34:16 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References"\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.7\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
+ tests=[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 XzhUjj97E1Rg for <notmuch@notmuchmail.org>;\r
+ Sat, 30 Nov 2013 07:34:09 -0800 (PST)\r
+Received: from mail-ea0-f172.google.com (mail-ea0-f172.google.com\r
+ [209.85.215.172]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+ (No client certificate requested)\r
+ by olra.theworths.org (Postfix) with ESMTPS id 3F7B6431FBC\r
+ for <notmuch@notmuchmail.org>; Sat, 30 Nov 2013 07:34:06 -0800 (PST)\r
+Received: by mail-ea0-f172.google.com with SMTP id q10so7520437ead.17\r
+ for <notmuch@notmuchmail.org>; Sat, 30 Nov 2013 07:34:05 -0800 (PST)\r
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+ d=1e100.net; s=20130820;\r
+ h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\r
+ :references:in-reply-to:references;\r
+ bh=zoe9OLsyJ3LsuNeOyW7iaJql4J5nfEBgb4WIHrp3w80=;\r
+ b=AlrPC0vcIV01vOF6eqvsnr+4wAPHrRBG+TC8E3lmkI9VPFWepaZYZueBHt7K9sWF1a\r
+ 8zOI491KcMpOTxHJNW6a0ugdwRnHPzUZ9ZAWNSTwfoZij2HAtMa8n9F4NiM47eb1EvbG\r
+ 7gb1iYMuMEEd9sOE6Gu34cwT6rzXKmr4ST2K/okE/BWL4iM25LU1jDHmm4WXWksGcWjJ\r
+ RhltnRci+qhxfzLIrR9KceecJhfqBWyrp9CQIOSOODYW94sP0lBaZhx4D5aGKGe2dXbJ\r
+ IiqQi7teBOJ8K0qcw1QbqZOvQ/uQfGVOcHH0jWrz0AgmXOs1705MaGqS4p86KWOJAOLh\r
+ BDoQ==\r
+X-Gm-Message-State:\r
+ ALoCoQkxdJzqLxjO6L8RyLdoRYc4yowXg5yJ3+vyz7N/bbGrBx4ci+d6GYS/saYeq+Znhz/5Y7X/\r
+X-Received: by 10.15.101.9 with SMTP id bo9mr7572255eeb.32.1385825645230;\r
+ Sat, 30 Nov 2013 07:34:05 -0800 (PST)\r
+Received: from localhost (dsl-hkibrasgw2-58c36f-91.dhcp.inet.fi.\r
+ [88.195.111.91]) by mx.google.com with ESMTPSA id\r
+ o47sm52032280eem.21.2013.11.30.07.34.03 for <multiple recipients>\r
+ (version=TLSv1.2 cipher=RC4-SHA bits=128/128);\r
+ Sat, 30 Nov 2013 07:34:04 -0800 (PST)\r
+From: Jani Nikula <jani@nikula.org>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v2 2/7] cli: refactor reply from guessing\r
+Date: Sat, 30 Nov 2013 17:33:51 +0200\r
+Message-Id:\r
+ <c877beb316c1ebab5d5b7224483ce9fac4f69598.1385825425.git.jani@nikula.org>\r
+X-Mailer: git-send-email 1.8.4.2\r
+In-Reply-To: <cover.1385825425.git.jani@nikula.org>\r
+References: <cover.1385825425.git.jani@nikula.org>\r
+In-Reply-To: <cover.1385825425.git.jani@nikula.org>\r
+References: <cover.1385825425.git.jani@nikula.org>\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: Sat, 30 Nov 2013 15:34:16 -0000\r
+\r
+The guess_from_received_header() function had grown quite big. Chop it\r
+up into smaller functions.\r
+\r
+No functional changes.\r
+---\r
+ notmuch-reply.c | 178 +++++++++++++++++++++++++++++++++-----------------------\r
+ 1 file changed, 105 insertions(+), 73 deletions(-)\r
+\r
+diff --git a/notmuch-reply.c b/notmuch-reply.c\r
+index 9d6f843..ca41405 100644\r
+--- a/notmuch-reply.c\r
++++ b/notmuch-reply.c\r
+@@ -369,78 +369,44 @@ add_recipients_from_message (GMimeMessage *reply,\r
+ return from_addr;\r
+ }\r
+ \r
++/*\r
++ * Look for the user's address in " for <email@add.res>" in the\r
++ * received headers.\r
++ *\r
++ * Return the address that was found, if any, and NULL otherwise.\r
++ */\r
+ static const char *\r
+-guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message)\r
++guess_from_received_for (notmuch_config_t *config, const char *received)\r
+ {\r
+- const char *addr, *received, *by;\r
+- char *mta,*ptr,*token;\r
+- char *domain=NULL;\r
+- char *tld=NULL;\r
+- const char *delim=". \t";\r
+- size_t i;\r
+-\r
+- const char *to_headers[] = {\r
+- "Envelope-to",\r
+- "X-Original-To",\r
+- "Delivered-To",\r
+- };\r
+-\r
+- /* sadly, there is no standard way to find out to which email\r
+- * address a mail was delivered - what is in the headers depends\r
+- * on the MTAs used along the way. So we are trying a number of\r
+- * heuristics which hopefully will answer this question.\r
+-\r
+- * We only got here if none of the users email addresses are in\r
+- * the To: or Cc: header. From here we try the following in order:\r
+- * 1) check for an Envelope-to: header\r
+- * 2) check for an X-Original-To: header\r
+- * 3) check for a Delivered-To: header\r
+- * 4) check for a (for <email@add.res>) clause in Received: headers\r
+- * 5) check for the domain part of known email addresses in the\r
+- * 'by' part of Received headers\r
+- * If none of these work, we give up and return NULL\r
+- */\r
+- for (i = 0; i < ARRAY_SIZE (to_headers); i++) {\r
+- const char *tohdr = notmuch_message_get_header (message, to_headers[i]);\r
+-\r
+- /* Note: tohdr potentially contains a list of email addresses. */\r
+- addr = user_address_in_string (tohdr, config);\r
+- if (addr)\r
+- return addr;\r
+- }\r
++ const char *ptr;\r
+ \r
+- /* We get the concatenated Received: headers and search from the\r
+- * front (last Received: header added) and try to extract from\r
+- * them indications to which email address this message was\r
+- * delivered.\r
+- * The Received: header is special in our get_header function\r
+- * and is always concatenated.\r
+- */\r
+- received = notmuch_message_get_header (message, "received");\r
+- if (received == NULL)\r
++ ptr = strstr (received, " for ");\r
++ if (! ptr)\r
+ return NULL;\r
+ \r
+- /* First we look for a " for <email@add.res>" in the received\r
+- * header\r
+- */\r
+- ptr = strstr (received, " for ");\r
++ return user_address_in_string (ptr, config);\r
++}\r
+ \r
+- /* Note: ptr potentially contains a list of email addresses. */\r
+- addr = user_address_in_string (ptr, config);\r
+- if (addr)\r
+- return addr;\r
+-\r
+- /* Finally, we parse all the " by MTA ..." headers to guess the\r
+- * email address that this was originally delivered to.\r
+- * We extract just the MTA here by removing leading whitespace and\r
+- * assuming that the MTA name ends at the next whitespace.\r
+- * We test for *(by+4) to be non-'\0' to make sure there's\r
+- * something there at all - and then assume that the first\r
+- * whitespace delimited token that follows is the receiving\r
+- * system in this step of the receive chain\r
+- */\r
+- by = received;\r
+- while((by = strstr (by, " by ")) != NULL) {\r
++/*\r
++ * Parse all the " by MTA ..." parts in received headers to guess the\r
++ * email address that this was originally delivered to.\r
++ *\r
++ * Extract just the MTA here by removing leading whitespace and\r
++ * assuming that the MTA name ends at the next whitespace. Test for\r
++ * *(by+4) to be non-'\0' to make sure there's something there at all\r
++ * - and then assume that the first whitespace delimited token that\r
++ * follows is the receiving system in this step of the receive chain.\r
++ *\r
++ * Return the address that was found, if any, and NULL otherwise.\r
++ */\r
++static const char *\r
++guess_from_received_by (notmuch_config_t *config, const char *received)\r
++{\r
++ const char *addr;\r
++ const char *by = received;\r
++ char *domain, *tld, *mta, *ptr, *token;\r
++\r
++ while ((by = strstr (by, " by ")) != NULL) {\r
+ by += 4;\r
+ if (*by == '\0')\r
+ break;\r
+@@ -454,7 +420,7 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message\r
+ * as domain and tld.\r
+ */\r
+ domain = tld = NULL;\r
+- while ((ptr = strsep (&token, delim)) != NULL) {\r
++ while ((ptr = strsep (&token, ". \t")) != NULL) {\r
+ if (*ptr == '\0')\r
+ continue;\r
+ domain = tld;\r
+@@ -462,13 +428,13 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message\r
+ }\r
+ \r
+ if (domain) {\r
+- /* Recombine domain and tld and look for it among the configured\r
+- * email addresses.\r
+- * This time we have a known domain name and nothing else - so\r
+- * the test is the other way around: we check if this is a\r
+- * substring of one of the email addresses.\r
++ /* Recombine domain and tld and look for it among the\r
++ * configured email addresses. This time we have a known\r
++ * domain name and nothing else - so the test is the other\r
++ * way around: we check if this is a substring of one of\r
++ * the email addresses.\r
+ */\r
+- *(tld-1) = '.';\r
++ *(tld - 1) = '.';\r
+ \r
+ addr = string_in_user_address (domain, config);\r
+ if (addr) {\r
+@@ -482,6 +448,63 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message\r
+ return NULL;\r
+ }\r
+ \r
++/*\r
++ * Get the concatenated Received: headers and search from the front\r
++ * (last Received: header added) and try to extract from them\r
++ * indications to which email address this message was delivered.\r
++ *\r
++ * The Received: header is special in our get_header function and is\r
++ * always concatenated.\r
++ *\r
++ * Return the address that was found, if any, and NULL otherwise.\r
++ */\r
++static const char *\r
++guess_from_received_header (notmuch_config_t *config,\r
++ notmuch_message_t *message)\r
++{\r
++ const char *received, *addr;\r
++\r
++ received = notmuch_message_get_header (message, "received");\r
++ if (! received)\r
++ return NULL;\r
++\r
++ addr = guess_from_received_for (config, received);\r
++ if (! addr)\r
++ addr = guess_from_received_by (config, received);\r
++\r
++ return addr;\r
++}\r
++\r
++/*\r
++ * Try to find user's email address in one of the extra To-like\r
++ * headers, such as Envelope-To, X-Original-To, and\r
++ * Delivered-To.\r
++ *\r
++ * Return the address that was found, if any, and NULL otherwise.\r
++ */\r
++static const char *\r
++from_from_to_headers (notmuch_config_t *config, notmuch_message_t *message)\r
++{\r
++ size_t i;\r
++ const char *tohdr, *addr;\r
++ const char *to_headers[] = {\r
++ "Envelope-to",\r
++ "X-Original-To",\r
++ "Delivered-To",\r
++ };\r
++\r
++ for (i = 0; i < ARRAY_SIZE (to_headers); i++) {\r
++ tohdr = notmuch_message_get_header (message, to_headers[i]);\r
++\r
++ /* Note: tohdr potentially contains a list of email addresses. */\r
++ addr = user_address_in_string (tohdr, config);\r
++ if (addr)\r
++ return addr;\r
++ }\r
++\r
++ return NULL;\r
++}\r
++\r
+ static GMimeMessage *\r
+ create_reply_message(void *ctx,\r
+ notmuch_config_t *config,\r
+@@ -508,6 +531,15 @@ create_reply_message(void *ctx,\r
+ from_addr = add_recipients_from_message (reply, config,\r
+ message, reply_all);\r
+ \r
++ /*\r
++ * Sadly, there is no standard way to find out to which email\r
++ * address a mail was delivered - what is in the headers depends\r
++ * on the MTAs used along the way. So we are trying a number of\r
++ * heuristics which hopefully will answer this question.\r
++ */\r
++ if (from_addr == NULL)\r
++ from_addr = from_from_to_headers (config, message);\r
++\r
+ if (from_addr == NULL)\r
+ from_addr = guess_from_received_header (config, message);\r
+ \r
+-- \r
+1.8.4.2\r
+\r