/* * 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_in_received_for (notmuch_config_t *config, const char *received) { const char *ptr; ptr = strstr (received, " for "); if (! ptr) return NULL; return user_address_in_string (ptr, config); }
/* * 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 const char * guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message) { 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; } /* 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; /* First we look for a " for <*****@*****.**>" in the received * header */ ptr = strstr (received, " for "); /* 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) { by += 4; if (*by == '\0') break; mta = xstrdup (by); token = strtok(mta," \t"); if (token == NULL) { free (mta); break; } /* Now extract the last two components of the MTA host name * as domain and tld. */ domain = tld = NULL; while ((ptr = strsep (&token, delim)) != NULL) { if (*ptr == '\0') continue; domain = tld; tld = ptr; } 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. */ *(tld-1) = '.'; addr = string_in_user_address (domain, config); if (addr) { free (mta); return addr; } } free (mta); } return NULL; }