+/* Does the address in the Reply-To header of 'message' already appear
+ * in either the 'To' or 'Cc' header of the message?
+ */
+static int
+reply_to_header_is_redundant (notmuch_message_t *message)
+{
+ const char *header, *addr;
+ InternetAddressList *list;
+ InternetAddress *address;
+ InternetAddressMailbox *mailbox;
+
+ header = notmuch_message_get_header (message, "reply-to");
+ if (*header == '\0')
+ return 0;
+
+ list = internet_address_list_parse_string (header);
+
+ if (internet_address_list_length (list) != 1)
+ return 0;
+
+ address = internet_address_list_get_address (list, 0);
+ if (INTERNET_ADDRESS_IS_GROUP (address))
+ return 0;
+
+ mailbox = INTERNET_ADDRESS_MAILBOX (address);
+ addr = internet_address_mailbox_get_addr (mailbox);
+
+ if (strstr (notmuch_message_get_header (message, "to"), addr) != 0 ||
+ strstr (notmuch_message_get_header (message, "cc"), addr) != 0)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Augments the recipients of reply from the headers of message.
+ *
+ * If any of the user's addresses were found in these headers, the first
+ * of these returned, otherwise NULL is returned.
+ */
+static const char *
+add_recipients_from_message (GMimeMessage *reply,
+ notmuch_config_t *config,
+ notmuch_message_t *message)
+{
+ struct {
+ const char *header;
+ const char *fallback;
+ GMimeRecipientType recipient_type;
+ } reply_to_map[] = {
+ { "reply-to", "from", GMIME_RECIPIENT_TYPE_TO },
+ { "to", NULL, GMIME_RECIPIENT_TYPE_TO },
+ { "cc", NULL, GMIME_RECIPIENT_TYPE_CC },
+ { "bcc", NULL, GMIME_RECIPIENT_TYPE_BCC }
+ };
+ const char *from_addr = NULL;
+ unsigned int i;
+
+ /* Some mailing lists munge the Reply-To header despite it being A Bad
+ * Thing, see http://www.unicom.com/pw/reply-to-harmful.html
+ *
+ * The munging is easy to detect, because it results in a
+ * redundant reply-to header, (with an address that already exists
+ * in either To or Cc). So in this case, we ignore the Reply-To
+ * field and use the From header. Thie ensures the original sender
+ * will get the reply even if not subscribed to the list. Note
+ * that the address in the Reply-To header will always appear in
+ * the reply.
+ */
+ if (reply_to_header_is_redundant (message)) {
+ reply_to_map[0].header = "from";
+ reply_to_map[0].fallback = NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE (reply_to_map); i++) {
+ const char *addr, *recipients;
+
+ recipients = notmuch_message_get_header (message,
+ reply_to_map[i].header);
+ if ((recipients == NULL || recipients[0] == '\0') && reply_to_map[i].fallback)
+ recipients = notmuch_message_get_header (message,
+ reply_to_map[i].fallback);
+
+ addr = add_recipients_for_string (reply, config,
+ reply_to_map[i].recipient_type,
+ recipients);
+ if (from_addr == NULL)
+ from_addr = addr;
+ }
+
+ return from_addr;
+}
+
+static const char *
+guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message)
+{
+ const char *received,*primary;
+ char **other;
+ char *by,*mta,*ptr,*token;
+ char *domain=NULL;
+ char *tld=NULL;
+ const char *delim=". \t";
+ size_t i,other_len;
+
+ received = notmuch_message_get_header (message, "received");
+ by = strstr (received, " by ");
+ if (by && *(by+4)) {
+ /* sadly, the format of Received: headers is a bit inconsistent,
+ * depending on the MTA used. So we try to 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 last receiving server
+ */
+ mta = strdup (by+4);
+ if (mta == NULL)
+ return NULL;
+ token = strtok(mta," \t");
+ if (token == NULL)
+ return NULL;
+ /* Now extract the last two components of the MTA host name
+ * as domain and tld
+ */
+ 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
+ */
+ *(tld-1) = '.';
+ primary = notmuch_config_get_user_primary_email (config);
+ if (strcasestr (primary, domain)) {
+ free (mta);
+ return primary;
+ }
+ other = notmuch_config_get_user_other_email (config, &other_len);
+ for (i = 0; i < other_len; i++)
+ if (strcasestr (other[i], domain)) {
+ free (mta);
+ return other[i];
+ }
+ }
+
+ free (mta);
+ }
+
+ return NULL;
+}
+