From 9dcd85e422fae608e773acf8d29fb96ea4d4681a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 3 Feb 2014 21:51:42 +0200 Subject: [PATCH] [PATCH v3 2/6] cli: refactor reply from guessing --- cd/00ef31f44b175ec928b671413c0e263cded75b | 328 ++++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 cd/00ef31f44b175ec928b671413c0e263cded75b diff --git a/cd/00ef31f44b175ec928b671413c0e263cded75b b/cd/00ef31f44b175ec928b671413c0e263cded75b new file mode 100644 index 000000000..73f84f0e9 --- /dev/null +++ b/cd/00ef31f44b175ec928b671413c0e263cded75b @@ -0,0 +1,328 @@ +Return-Path: +X-Original-To: notmuch@notmuchmail.org +Delivered-To: notmuch@notmuchmail.org +Received: from localhost (localhost [127.0.0.1]) + by olra.theworths.org (Postfix) with ESMTP id 39DC9431FBC + for ; Mon, 3 Feb 2014 11:52:06 -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 mr5GTSKgSzzv for ; + Mon, 3 Feb 2014 11:52:02 -0800 (PST) +Received: from mail-ea0-f175.google.com (mail-ea0-f175.google.com + [209.85.215.175]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) + (No client certificate requested) + by olra.theworths.org (Postfix) with ESMTPS id 56581431FC9 + for ; Mon, 3 Feb 2014 11:52:01 -0800 (PST) +Received: by mail-ea0-f175.google.com with SMTP id z10so3917405ead.6 + for ; Mon, 03 Feb 2014 11:52:00 -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=4e8aKDlGpBD64reo7VuZkvREzQASRH8PEYY2XRnTaAc=; + b=DAAcyEskFTYZhNdg5t+3RUoAno0Dil3RBKCiXYTQD5u0KmShRJxQjLm0K0Yx+IuZRr + BKVuOSYcx3U87VSDFFtgd4XuCJNI6fICavDEq6hCLMtenSz4awDNGiVZfiwBYPC+WUQK + aazXTo1TyHvAVOJ6Xw8TQg7e8svfCDqJyad7F/MBCuHIgRKkxxhmLGdU+CgyG+Ab1muT + Kkbypfxk1wWZOJLqCysDDzhhZI/YymdLe6fLWwBFtInbMY0arF0EJOW0rD5t144ZaJTN + ZrMuHc+P05zek/EN4uQZrU3/Ag6RZtggXSZNIf99IKql23lMb0sfpNfG8zXGextDnkrt + Kmow== +X-Gm-Message-State: + ALoCoQliQ2WJoaGom0rxSqK6i2iZ4BHQXJp8IDWmonxJWGdeN+E4vW/ouqmL3gUrVkgEVA7lLQy5 +X-Received: by 10.14.246.68 with SMTP id p44mr5139536eer.72.1391457120191; + Mon, 03 Feb 2014 11:52:00 -0800 (PST) +Received: from localhost (dsl-hkibrasgw2-58c36f-91.dhcp.inet.fi. + [88.195.111.91]) by mx.google.com with ESMTPSA id + y47sm31524300eel.14.2014.02.03.11.51.58 for + (version=TLSv1.2 cipher=RC4-SHA bits=128/128); + Mon, 03 Feb 2014 11:51:59 -0800 (PST) +From: Jani Nikula +To: notmuch@notmuchmail.org +Subject: [PATCH v3 2/6] cli: refactor reply from guessing +Date: Mon, 3 Feb 2014 21:51:42 +0200 +Message-Id: + +X-Mailer: git-send-email 1.8.5.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: Mon, 03 Feb 2014 19:52:06 -0000 + +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 " 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 ) 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_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 ) 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 + -- 2.26.2