unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
From: Dirk Hohndel <hohndel@infradead.org>
To: <notmuch@notmuchmail.org>
Subject: [PATCH 1/2] Make Received: header special in notmuch_message_file_get_header
Date: Mon, 26 Apr 2010 12:58:34 -0700	[thread overview]
Message-ID: <1272311915-30575-2-git-send-email-hohndel@infradead.org> (raw)
In-Reply-To: <1272311915-30575-1-git-send-email-hohndel@infradead.org>

With this patch the Received: header becomes special in the way
we treat headers - this is the only header for which we concatenate
all the instances we find (instead of just returning the first one).

This will be used in the From guessing code for replies as we need to
be able to walk ALL of the Received: headers in a message to have a
good chance to guess which mailbox this email was delivered to.

Signed-off-by: Dirk Hohndel <hohndel@infradead.org>
---
 lib/message-file.c    |   58 ++++++++++++++++++++++++++++++++++++++-----------
 lib/notmuch-private.h |    3 ++
 2 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/lib/message-file.c b/lib/message-file.c
index 0c152a3..7722832 100644
--- a/lib/message-file.c
+++ b/lib/message-file.c
@@ -209,17 +209,24 @@ copy_header_unfolding (header_value_closure_t *value,
 
 /* As a special-case, a value of NULL for header_desired will force
  * the entire header to be parsed if it is not parsed already. This is
- * used by the _notmuch_message_file_get_headers_end function. */
+ * used by the _notmuch_message_file_get_headers_end function.
+ * Another special case is the Received: header. For this header we
+ * want to concatenate all instances of the header instead of just
+ * hashing the first instance as we use this when analyzing the path
+ * the mail has taken from sender to recipient.
+ */
 const char *
 notmuch_message_file_get_header (notmuch_message_file_t *message,
 				 const char *header_desired)
 {
     int contains;
-    char *header, *decoded_value;
+    char *header, *decoded_value, *header_sofar, *combined_header;
     const char *s, *colon;
-    int match;
+    int match, newhdr, hdrsofar, is_received;
     static int initialized = 0;
 
+    is_received = (strcmp(header_desired,"received") == 0);
+
     if (! initialized) {
 	g_mime_init (0);
 	initialized = 1;
@@ -312,22 +319,39 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,
 
 	NEXT_HEADER_LINE (&message->value);
 
-	if (header_desired == 0)
+	if (header_desired == NULL)
 	    match = 0;
 	else
 	    match = (strcasecmp (header, header_desired) == 0);
 
 	decoded_value = g_mime_utils_header_decode_text (message->value.str);
-	if (g_hash_table_lookup (message->headers, header) == NULL) {
-	    /* Only insert if we don't have a value for this header, yet.
-	     * This way we always return the FIRST instance of any header
-	     * we search for
-	     * FIXME: we should be returning ALL instances of a header
-	     *        or at least provide a way to iterate over them
-	     */
-	    g_hash_table_insert (message->headers, header, decoded_value);
+	header_sofar = (char *)g_hash_table_lookup (message->headers, header);
+	/* we treat the Received: header special - we want to concat ALL of 
+	 * the Received: headers we encounter.
+	 * for everything else we return the first instance of a header */
+	if (is_received) {
+	    if (header_sofar == NULL) {
+		/* first Received: header we encountered; just add it */
+		g_hash_table_insert (message->headers, header, decoded_value);
+	    } else {
+		/* we need to add the header to those we already collected */
+		newhdr = strlen(decoded_value);
+		hdrsofar = strlen(header_sofar);
+		combined_header = xmalloc(hdrsofar + newhdr + 2);
+		strncpy(combined_header,header_sofar,hdrsofar);
+		*(combined_header+hdrsofar) = ' ';
+		strncpy(combined_header+hdrsofar+1,decoded_value,newhdr+1);
+		g_hash_table_insert (message->headers, header, combined_header);
+	    }
+	} else {
+	    if (header_sofar == NULL) {
+		/* Only insert if we don't have a value for this header, yet. */
+		g_hash_table_insert (message->headers, header, decoded_value);
+	    }
 	}
-	if (match)
+	/* if we found a match we can bail - unless of course we are
+	 * collecting all the Received: headers */
+	if (match && !is_received)
 	    return decoded_value;
     }
 
@@ -347,6 +371,14 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,
 	message->value.len = 0;
     }
 
+    /* For the Received: header we actually might end up here even
+     * though we found the header (as we force continued parsing
+     * in that case). So let's check if that's the header we were
+     * looking for and return the value that we found (if any)
+     */
+    if (is_received)
+	return (char *)g_hash_table_lookup (message->headers, "received");
+
     /* We've parsed all headers and never found the one we're looking
      * for. It's probably just not there, but let's check that we
      * didn't make a mistake preventing us from seeing it. */
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 6e83cc3..3768d6f 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -344,6 +344,9 @@ notmuch_message_file_restrict_headersv (notmuch_message_file_t *message,
  *
  * The header name is case insensitive.
  *
+ * The Received: header is special - for it all Received: headers in
+ * the message are concatenated
+ *
  * The returned value is owned by the notmuch message and is valid
  * only until the message is closed. The caller should copy it if
  * needing to modify the value or to hold onto it for longer.
-- 
1.6.6.1

  reply	other threads:[~2010-04-26 19:58 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-24  5:08 [PATCH] Rearchitect the way the Received: header is concatenated Dirk Hohndel
2010-04-26 19:58 ` For 0.3 - cleaned up patches rebased on origin/master Dirk Hohndel
2010-04-26 19:58   ` Dirk Hohndel [this message]
2010-04-26 19:58     ` [PATCH 2/2] Rearchitect From: header guessing code for replies Dirk Hohndel
2010-04-26 21:48   ` For 0.3 - cleaned up patches rebased on origin/master Carl Worth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://notmuchmail.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1272311915-30575-2-git-send-email-hohndel@infradead.org \
    --to=hohndel@infradead.org \
    --cc=notmuch@notmuchmail.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).