From: Jani Nikula <jani@nikula.org>
To: notmuch@notmuchmail.org
Subject: [PATCH v3 2/6] cli: refactor reply from guessing
Date: Mon, 3 Feb 2014 21:51:42 +0200 [thread overview]
Message-ID: <db939e2df53b4cb9e333b1696daf2e8962bc8d15.1391456555.git.jani@nikula.org> (raw)
In-Reply-To: <cover.1391456555.git.jani@nikula.org>
In-Reply-To: <cover.1391456555.git.jani@nikula.org>
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@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@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@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@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
next prev parent reply other threads:[~2014-02-03 19:52 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-03 19:51 [PATCH v3 0/6] lib: replace the message header parser with gmime Jani Nikula
2014-02-03 19:51 ` [PATCH v3 1/6] cli: sanitize tabs and newlines to spaces in notmuch search Jani Nikula
2014-02-03 19:51 ` Jani Nikula [this message]
2014-02-03 19:51 ` [PATCH v3 3/6] util: make sanitize string available in string util for reuse Jani Nikula
2014-03-08 11:32 ` David Bremner
2014-03-09 13:19 ` David Bremner
2014-02-03 19:51 ` [PATCH v3 4/6] cli: sanitize the received header before scanning for replies Jani Nikula
2014-02-03 20:46 ` Austin Clements
2014-03-19 16:44 ` [PATCH] " Jani Nikula
2014-03-26 0:33 ` David Bremner
2014-02-03 19:51 ` [PATCH v3 5/6] lib: replace the header parser with gmime Jani Nikula
2014-02-03 21:31 ` Austin Clements
2014-02-03 19:51 ` [PATCH v3 6/6] lib: parse messages only once Jani Nikula
2014-02-03 21:40 ` Austin Clements
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://notmuchmail.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=db939e2df53b4cb9e333b1696daf2e8962bc8d15.1391456555.git.jani@nikula.org \
--to=jani@nikula.org \
--cc=notmuch@notmuchmail.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://yhetil.org/notmuch.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).