[PATCH v3 2/6] cli: refactor reply from guessing
Jani Nikula
jani at nikula.org
Mon Feb 3 11:51:42 PST 2014
The guess_from_received_header() function had grown quite big. Chop it
up into smaller functions.
No functional changes.
---
notmuch-reply.c | 198 ++++++++++++++++++++++++++++++++++----------------------
1 file changed, 122 insertions(+), 76 deletions(-)
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 79cdc83..47993d2 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -369,78 +369,44 @@ add_recipients_from_message (GMimeMessage *reply,
return from_addr;
}
+/*
+ * Look for the user's address in " for <email at add.res>" in the
+ * received headers.
+ *
+ * Return the address that was found, if any, and NULL otherwise.
+ */
static const char *
-guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message)
+guess_from_in_received_for (notmuch_config_t *config, const char *received)
{
- const char *addr, *received, *by;
- char *mta,*ptr,*token;
- char *domain=NULL;
- char *tld=NULL;
- const char *delim=". \t";
- size_t i;
-
- const char *to_headers[] = {
- "Envelope-to",
- "X-Original-To",
- "Delivered-To",
- };
-
- /* sadly, there is no standard way to find out to which email
- * address a mail was delivered - what is in the headers depends
- * on the MTAs used along the way. So we are trying a number of
- * heuristics which hopefully will answer this question.
-
- * We only got here if none of the users email addresses are in
- * the To: or Cc: header. From here we try the following in order:
- * 1) check for an Envelope-to: header
- * 2) check for an X-Original-To: header
- * 3) check for a Delivered-To: header
- * 4) check for a (for <email at add.res>) clause in Received: headers
- * 5) check for the domain part of known email addresses in the
- * 'by' part of Received headers
- * If none of these work, we give up and return NULL
- */
- for (i = 0; i < ARRAY_SIZE (to_headers); i++) {
- const char *tohdr = notmuch_message_get_header (message, to_headers[i]);
-
- /* Note: tohdr potentially contains a list of email addresses. */
- addr = user_address_in_string (tohdr, config);
- if (addr)
- return addr;
- }
+ const char *ptr;
- /* We get the concatenated Received: headers and search from the
- * front (last Received: header added) and try to extract from
- * them indications to which email address this message was
- * delivered.
- * The Received: header is special in our get_header function
- * and is always concatenated.
- */
- received = notmuch_message_get_header (message, "received");
- if (received == NULL)
+ ptr = strstr (received, " for ");
+ if (! ptr)
return NULL;
- /* First we look for a " for <email at add.res>" in the received
- * header
- */
- ptr = strstr (received, " for ");
+ return user_address_in_string (ptr, config);
+}
- /* Note: ptr potentially contains a list of email addresses. */
- addr = user_address_in_string (ptr, config);
- if (addr)
- return addr;
-
- /* Finally, we parse all the " by MTA ..." headers to guess the
- * email address that this was originally delivered to.
- * We extract just the MTA here by removing leading whitespace and
- * assuming that the MTA name ends at the next whitespace.
- * We test for *(by+4) to be non-'\0' to make sure there's
- * something there at all - and then assume that the first
- * whitespace delimited token that follows is the receiving
- * system in this step of the receive chain
- */
- by = received;
- while((by = strstr (by, " by ")) != NULL) {
+/*
+ * Parse all the " by MTA ..." parts in received headers to guess the
+ * email address that this was originally delivered to.
+ *
+ * Extract just the MTA here by removing leading whitespace and
+ * assuming that the MTA name ends at the next whitespace. Test for
+ * *(by+4) to be non-'\0' to make sure there's something there at all
+ * - and then assume that the first whitespace delimited token that
+ * follows is the receiving system in this step of the receive chain.
+ *
+ * Return the address that was found, if any, and NULL otherwise.
+ */
+static const char *
+guess_from_in_received_by (notmuch_config_t *config, const char *received)
+{
+ const char *addr;
+ const char *by = received;
+ char *domain, *tld, *mta, *ptr, *token;
+
+ while ((by = strstr (by, " by ")) != NULL) {
by += 4;
if (*by == '\0')
break;
@@ -450,11 +416,12 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message
free (mta);
break;
}
- /* Now extract the last two components of the MTA host name
- * as domain and tld.
+ /*
+ * Now extract the last two components of the MTA host name as
+ * domain and tld.
*/
domain = tld = NULL;
- while ((ptr = strsep (&token, delim)) != NULL) {
+ while ((ptr = strsep (&token, ". \t")) != NULL) {
if (*ptr == '\0')
continue;
domain = tld;
@@ -462,13 +429,14 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message
}
if (domain) {
- /* Recombine domain and tld and look for it among the configured
- * email addresses.
- * This time we have a known domain name and nothing else - so
- * the test is the other way around: we check if this is a
- * substring of one of the email addresses.
+ /*
+ * Recombine domain and tld and look for it among the
+ * configured email addresses. This time we have a known
+ * domain name and nothing else - so the test is the other
+ * way around: we check if this is a substring of one of
+ * the email addresses.
*/
- *(tld-1) = '.';
+ *(tld - 1) = '.';
addr = string_in_user_address (domain, config);
if (addr) {
@@ -482,6 +450,63 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message
return NULL;
}
+/*
+ * Get the concatenated Received: headers and search from the front
+ * (last Received: header added) and try to extract from them
+ * indications to which email address this message was delivered.
+ *
+ * The Received: header is special in our get_header function and is
+ * always concatenated.
+ *
+ * Return the address that was found, if any, and NULL otherwise.
+ */
+static const char *
+guess_from_in_received_headers (notmuch_config_t *config,
+ notmuch_message_t *message)
+{
+ const char *received, *addr;
+
+ received = notmuch_message_get_header (message, "received");
+ if (! received)
+ return NULL;
+
+ addr = guess_from_in_received_for (config, received);
+ if (! addr)
+ addr = guess_from_in_received_by (config, received);
+
+ return addr;
+}
+
+/*
+ * Try to find user's email address in one of the extra To-like
+ * headers: Envelope-To, X-Original-To, and Delivered-To (searched in
+ * that order).
+ *
+ * Return the address that was found, if any, and NULL otherwise.
+ */
+static const char *
+get_from_in_to_headers (notmuch_config_t *config, notmuch_message_t *message)
+{
+ size_t i;
+ const char *tohdr, *addr;
+ const char *to_headers[] = {
+ "Envelope-to",
+ "X-Original-To",
+ "Delivered-To",
+ };
+
+ for (i = 0; i < ARRAY_SIZE (to_headers); i++) {
+ tohdr = notmuch_message_get_header (message, to_headers[i]);
+
+ /* Note: tohdr potentially contains a list of email addresses. */
+ addr = user_address_in_string (tohdr, config);
+ if (addr)
+ return addr;
+ }
+
+ return NULL;
+}
+
static GMimeMessage *
create_reply_message(void *ctx,
notmuch_config_t *config,
@@ -508,9 +533,30 @@ create_reply_message(void *ctx,
from_addr = add_recipients_from_message (reply, config,
message, reply_all);
+ /*
+ * Sadly, there is no standard way to find out to which email
+ * address a mail was delivered - what is in the headers depends
+ * on the MTAs used along the way.
+ *
+ * If none of the user's email addresses are in the To: or Cc:
+ * headers, we try a number of heuristics which hopefully will
+ * answer this question.
+ *
+ * First, check for Envelope-To:, X-Original-To:, and
+ * Delivered-To: headers.
+ */
+ if (from_addr == NULL)
+ from_addr = get_from_in_to_headers (config, message);
+
+ /*
+ * Check for a (for <email at add.res>) clause in Received: headers,
+ * and the domain part of known email addresses in the 'by' part
+ * of Received: headers
+ */
if (from_addr == NULL)
- from_addr = guess_from_received_header (config, message);
+ from_addr = guess_from_in_received_headers (config, message);
+ /* Default to user's primary address. */
if (from_addr == NULL)
from_addr = notmuch_config_get_user_primary_email (config);
--
1.8.5.2
More information about the notmuch
mailing list