mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-23 19:38:07 +01:00
cli: refactor reply from guessing
The guess_from_received_header() function had grown quite big. Chop it up into smaller functions. No functional changes.
This commit is contained in:
parent
6d0a17c46e
commit
998a8a95c3
1 changed files with 121 additions and 75 deletions
196
notmuch-reply.c
196
notmuch-reply.c
|
@ -369,78 +369,44 @@ add_recipients_from_message (GMimeMessage *reply,
|
||||||
return from_addr;
|
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 *
|
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;
|
const char *ptr;
|
||||||
char *mta,*ptr,*token;
|
|
||||||
char *domain=NULL;
|
|
||||||
char *tld=NULL;
|
|
||||||
const char *delim=". \t";
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
const char *to_headers[] = {
|
ptr = strstr (received, " for ");
|
||||||
"Envelope-to",
|
if (! ptr)
|
||||||
"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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* First we look for a " for <email@add.res>" in the received
|
return user_address_in_string (ptr, config);
|
||||||
* header
|
}
|
||||||
*/
|
|
||||||
ptr = strstr (received, " for ");
|
|
||||||
|
|
||||||
/* Note: ptr potentially contains a list of email addresses. */
|
/*
|
||||||
addr = user_address_in_string (ptr, config);
|
* Parse all the " by MTA ..." parts in received headers to guess the
|
||||||
if (addr)
|
* email address that this was originally delivered to.
|
||||||
return addr;
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
/* Finally, we parse all the " by MTA ..." headers to guess the
|
while ((by = strstr (by, " by ")) != NULL) {
|
||||||
* 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) {
|
|
||||||
by += 4;
|
by += 4;
|
||||||
if (*by == '\0')
|
if (*by == '\0')
|
||||||
break;
|
break;
|
||||||
|
@ -450,11 +416,12 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message
|
||||||
free (mta);
|
free (mta);
|
||||||
break;
|
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;
|
domain = tld = NULL;
|
||||||
while ((ptr = strsep (&token, delim)) != NULL) {
|
while ((ptr = strsep (&token, ". \t")) != NULL) {
|
||||||
if (*ptr == '\0')
|
if (*ptr == '\0')
|
||||||
continue;
|
continue;
|
||||||
domain = tld;
|
domain = tld;
|
||||||
|
@ -462,13 +429,14 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domain) {
|
if (domain) {
|
||||||
/* Recombine domain and tld and look for it among the configured
|
/*
|
||||||
* email addresses.
|
* Recombine domain and tld and look for it among the
|
||||||
* This time we have a known domain name and nothing else - so
|
* configured email addresses. This time we have a known
|
||||||
* the test is the other way around: we check if this is a
|
* domain name and nothing else - so the test is the other
|
||||||
* substring of one of the email addresses.
|
* 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);
|
addr = string_in_user_address (domain, config);
|
||||||
if (addr) {
|
if (addr) {
|
||||||
|
@ -482,6 +450,63 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message
|
||||||
return NULL;
|
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 *
|
static GMimeMessage *
|
||||||
create_reply_message(void *ctx,
|
create_reply_message(void *ctx,
|
||||||
notmuch_config_t *config,
|
notmuch_config_t *config,
|
||||||
|
@ -508,9 +533,30 @@ create_reply_message(void *ctx,
|
||||||
from_addr = add_recipients_from_message (reply, config,
|
from_addr = add_recipients_from_message (reply, config,
|
||||||
message, reply_all);
|
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)
|
if (from_addr == NULL)
|
||||||
from_addr = guess_from_received_header (config, message);
|
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_in_received_headers (config, message);
|
||||||
|
|
||||||
|
/* Default to user's primary address. */
|
||||||
if (from_addr == NULL)
|
if (from_addr == NULL)
|
||||||
from_addr = notmuch_config_get_user_primary_email (config);
|
from_addr = notmuch_config_get_user_primary_email (config);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue