Esempio n. 1
0
/*
 * 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);
}
Esempio n. 2
0
/*
 * 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;
}
Esempio n. 3
0
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;
}