From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 583E4431FDB for ; Sat, 30 Nov 2013 07:34:16 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" X-Spam-Flag: NO X-Spam-Score: -0.7 X-Spam-Level: X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5 tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id XzhUjj97E1Rg for ; Sat, 30 Nov 2013 07:34:09 -0800 (PST) Received: from mail-ea0-f172.google.com (mail-ea0-f172.google.com [209.85.215.172]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id 3F7B6431FBC for ; Sat, 30 Nov 2013 07:34:06 -0800 (PST) Received: by mail-ea0-f172.google.com with SMTP id q10so7520437ead.17 for ; Sat, 30 Nov 2013 07:34:05 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=zoe9OLsyJ3LsuNeOyW7iaJql4J5nfEBgb4WIHrp3w80=; b=AlrPC0vcIV01vOF6eqvsnr+4wAPHrRBG+TC8E3lmkI9VPFWepaZYZueBHt7K9sWF1a 8zOI491KcMpOTxHJNW6a0ugdwRnHPzUZ9ZAWNSTwfoZij2HAtMa8n9F4NiM47eb1EvbG 7gb1iYMuMEEd9sOE6Gu34cwT6rzXKmr4ST2K/okE/BWL4iM25LU1jDHmm4WXWksGcWjJ RhltnRci+qhxfzLIrR9KceecJhfqBWyrp9CQIOSOODYW94sP0lBaZhx4D5aGKGe2dXbJ IiqQi7teBOJ8K0qcw1QbqZOvQ/uQfGVOcHH0jWrz0AgmXOs1705MaGqS4p86KWOJAOLh BDoQ== X-Gm-Message-State: ALoCoQkxdJzqLxjO6L8RyLdoRYc4yowXg5yJ3+vyz7N/bbGrBx4ci+d6GYS/saYeq+Znhz/5Y7X/ X-Received: by 10.15.101.9 with SMTP id bo9mr7572255eeb.32.1385825645230; Sat, 30 Nov 2013 07:34:05 -0800 (PST) Received: from localhost (dsl-hkibrasgw2-58c36f-91.dhcp.inet.fi. [88.195.111.91]) by mx.google.com with ESMTPSA id o47sm52032280eem.21.2013.11.30.07.34.03 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 30 Nov 2013 07:34:04 -0800 (PST) From: Jani Nikula To: notmuch@notmuchmail.org Subject: [PATCH v2 2/7] cli: refactor reply from guessing Date: Sat, 30 Nov 2013 17:33:51 +0200 Message-Id: X-Mailer: git-send-email 1.8.4.2 In-Reply-To: References: In-Reply-To: References: X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 30 Nov 2013 15:34:16 -0000 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 " 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 ) 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 " 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. + */ +static const char * +from_from_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,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