[PATCH v2 2/7] cli: refactor reply from guessing
Mark Walters
markwalters1009 at gmail.com
Sun Feb 2 10:21:28 PST 2014
On Sat, 30 Nov 2013, Jani Nikula <jani at nikula.org> wrote:
> The guess_from_received_header() function had grown quite big. Chop it
> up into smaller functions.
>
> No functional changes.
> ---
> notmuch-reply.c | 178 +++++++++++++++++++++++++++++++++-----------------------
> 1 file changed, 105 insertions(+), 73 deletions(-)
>
> diff --git a/notmuch-reply.c b/notmuch-reply.c
> index 9d6f843..ca41405 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_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
> - */
I like having the logic laid out in a comment as above so would prefer
to see something similar included (that is points 1-6) but I am happy to
be overruled.
> - 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_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;
> @@ -454,7 +420,7 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message
> * 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 +428,13 @@ 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 +448,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_received_header (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_received_for (config, received);
> + if (! addr)
> + addr = guess_from_received_by (config, received);
> +
> + return addr;
> +}
> +
> +/*
> + * Try to find user's email address in one of the extra To-like
> + * headers, such as Envelope-To, X-Original-To, and
> + * Delivered-To.
> + *
> + * Return the address that was found, if any, and NULL otherwise.
> + */
I would prefer to replace the "extra To-like headers, such as ..." by
something more explicit: eg "extra To-like headers: Envelope-To,
X-Original-To, and Delivered-To (searched in that order)"
> +static const char *
> +from_from_to_headers (notmuch_config_t *config, notmuch_message_t *message)
I am not keen on this name, but I am not sure I have a better
suggestion.
Best wishes
Mark
> +{
> + 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,6 +531,15 @@ 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. So we are trying a number of
> + * heuristics which hopefully will answer this question.
> + */
> + if (from_addr == NULL)
> + from_addr = from_from_to_headers (config, message);
> +
> if (from_addr == NULL)
> from_addr = guess_from_received_header (config, message);
>
> --
> 1.8.4.2
>
> _______________________________________________
> notmuch mailing list
> notmuch at notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch
More information about the notmuch
mailing list