[Exim] Re: Envelope-to header max. one address ? [PATCH]

Top Page
Delete this message
Reply to this message
Author: Miquel van Smoorenburg
Date:  
To: exim-users
Subject: [Exim] Re: Envelope-to header max. one address ? [PATCH]
In article <Pine.SOL.4.44.0203061058110.24317-100000@???>,
Philip Hazel <ph10@???> wrote:
>On Wed, 6 Mar 2002, Miquel van Smoorenburg wrote:
>
>> It adds a member "dupbackptr" to struct address_item. For every
>> duplicate found, dupbackptr is set to the struct address_item
>> it is a duplicate from (hmm, perhaps 'dupfrom' is a better name).
>>
>That's certainly one way of achieving what you want. Doing what some
>other people want (not dropping duplicates) would require fundamental
>redesign to incorporate a unique identification for each address
>(currently it's the address itself). I had been thinking of that
>problem when considering how hard this change would be.


Ok, I see. I'm just caring about the Envelope-to: header here.
You know what it's used for; to make it possible to re-deliver
mail already delivered in a mailbox. It has to preserve the
correct envelope-to.

>> - in a .forward file of the following structure:
>>
>> myself
>> other_user
>>
>> which is meant to keep a local copy and send a copy to 'other_user',
>> it would be desireable to set the envelope-to header for the copy
>> delivered to 'other_user' to 'other_user' instead of 'myself' since
>> the message is in fact re-sent.
>
>I disagree with this. Envelope-to is supposed to represent the envelope
>that caused this delivery. Forwarding is redirecting rather than
>resending. If you want to resend, you can use procmail and really resend.


I can see that .. now I've done something that you are probably
going to hate, so please be gentle with me ;) I've added the syntax
!address which is somewhat \address in that it adds a flag to do
something special. It means 'set-envelope-to-header'.

Now if you use !address in a forward or alias file, it means that
for that delivery *that* address is added to the envelope-to header.

So in this situation:

# aliases
testalias1: stuser
testalias2: stuser

# .forward file of "stuser"
stuser
!miquels

if I send mail to testalias1,testalias2 then the Envelope-to in the
'stuser' mailbox will have "testalias1,testalias2" while the
Envelope-to: header in the 'miquels' mailbox will have just 'miquels'.

In other words, that provides control over _just_ the envelope-to header.
It doesn't change anything else in directing or routing.

Even though I think you'll have your reservations I'm still
going to attach the patch ;)

By the way, exim isn't really indented the way I'm used to, yet
it's pretty easy to find my way around it. It's really nicely coded.

diff -ruN o/exim-3.34/src/deliver.c exim-3.34/src/deliver.c
--- o/exim-3.34/src/deliver.c    Wed Dec 19 12:50:27 2001
+++ exim-3.34/src/deliver.c    Wed Mar  6 00:28:10 2002
@@ -81,6 +81,7 @@
   NULL,                 /* parent */
   NULL,                 /* shadow_parent */
   NULL,                 /* first */
+  NULL,                 /* dupbackptr */
   0,                    /* flags */
   NULL,                 /* onetime_parent */
   NULL,                 /* orig */
@@ -3679,6 +3680,7 @@
 int process_recipients = RECIP_ACCEPT;
 open_db dbblock;
 open_db *dbm_file;
+tree_node *tnode;


 if (queue_run_pid == (pid_t)0)
   {
@@ -4396,11 +4398,12 @@
             addr->unique = string_sprintf(">%s", addr->unique);
           }


-        else if (tree_search(tree_duplicates, addr->unique) != NULL)
+        else if ((tnode = tree_search(tree_duplicates, addr->unique)) != NULL)
           {
           DEBUG(9) debug_printf("%s is a duplicate address: discarded\n",
             addr->orig);
           addr->next = addr_duplicate;
+          addr->dupbackptr = tnode->data.ptr;
           addr_duplicate = addr;
           continue;
           }
@@ -4419,7 +4422,7 @@


         /* Save for checking future duplicates */


-        tree_add_duplicate(addr->unique, TRUE);
+        tree_add_duplicate(addr->unique, addr, TRUE);


         /* Set local part and domain */


@@ -4630,19 +4633,20 @@
       /* Check for duplication. Remember duplicated addresses so they can
       be marked "delivered" when the duplicate is delivered. */


-      if (tree_search_addr(tree_duplicates, addr->unique,
-           testflag(addr, af_pfr)) != NULL)
+      if ((tnode = tree_search_addr(tree_duplicates, addr->unique,
+           testflag(addr, af_pfr))) != NULL)
         {
         DEBUG(9) debug_printf("%s is a duplicate address: discarded\n",
           addr->unique);
         addr->next = addr_duplicate;
+        addr->dupbackptr = tnode->data.ptr;
         addr_duplicate = addr;
         continue;
         }


       /* Remember the first, to check for subsequent duplicates. */


-      tree_add_duplicate(addr->unique, testflag(addr, af_pfr));
+      tree_add_duplicate(addr->unique, addr, testflag(addr, af_pfr));


       /* If the address is local, check on directing retry status, and add
       either to the directing chain or the defer chain. */
diff -ruN o/exim-3.34/src/functions.h exim-3.34/src/functions.h
--- o/exim-3.34/src/functions.h    Wed Dec 19 12:50:28 2001
+++ exim-3.34/src/functions.h    Wed Mar  6 00:21:03 2002
@@ -266,7 +266,7 @@
 extern BOOL  transport_write_string(int, char *, ...);
 extern BOOL  transport_write_message(address_item *, int, int, int, char *,
                char *, char *, char *, rewrite_rule *, int);
-extern void  tree_add_duplicate(char *, BOOL);
+extern void  tree_add_duplicate(char *, address_item *, BOOL);
 extern void  tree_add_nonrecipient(char *, BOOL);
 extern void  tree_add_unusable(host_item *);
 extern int   tree_insertnode(tree_node **, tree_node *);
diff -ruN o/exim-3.34/src/parse.c exim-3.34/src/parse.c
--- o/exim-3.34/src/parse.c    Wed Dec 19 12:50:29 2001
+++ exim-3.34/src/parse.c    Wed Mar  6 13:25:05 2002
@@ -1380,6 +1380,7 @@
   else
     {
     int start, end, domain;
+    int extraflag = 0;
     char *recipient = NULL;
     int save = s[len];
     s[len] = 0;
@@ -1398,6 +1399,14 @@
           string_sprintf("%s@%s", recipient, incoming_domain);
       }


+    /* If it starts with '!' it means 'set envelope-to'. */
+    if (*s == '!')
+      {
+      recipient =
+        parse_extract_address(s+1, error, &start, &end, &domain, FALSE);
+      if (recipient != NULL) extraflag = af_set_envto_hdr;
+      }
+
     /* Try parsing the item as an address. */


     if (recipient == NULL) recipient =
@@ -1485,6 +1494,7 @@
       store_pool = POOL_MAIN;
       addr = deliver_make_addr(recipient, TRUE);  /* TRUE => copy recipient */
       store_pool = pool_reset;
+      if (addr) addr->flags |= extraflag;
       }


     /* Restore the final character in the original data, and add to the
diff -ruN o/exim-3.34/src/structs.h exim-3.34/src/structs.h
--- o/exim-3.34/src/structs.h    Wed Dec 19 12:50:30 2001
+++ exim-3.34/src/structs.h    Wed Mar  6 13:25:04 2002
@@ -500,6 +500,7 @@
   struct address_item *parent;   /* parent address */
   struct address_item *shadow_parent; /* parent when shadow delivering */
   struct address_item *first;    /* point to first after group delivery */
+  struct address_item *dupbackptr; /* if dup, points back to active addr */
   unsigned int flags;            /* a row of bits, defined below */
   char *onetime_parent;          /* saved original parent for onetime */
   char *orig;                    /* as read from the spool */
@@ -578,6 +579,7 @@
 #define af_rewrite_headers     0x00010000 /* set TRUE by routers that want it done */
 #define af_uid_set             0x00020000 /* uid field is set */
 #define af_hide_child          0x00040000 /* hide child in bounce/defer msgs */
+#define af_set_envto_hdr       0x00080000 /* set Envelope_to: to this address */


/* Tables of normal and resent- header names consist of items of this type */

diff -ruN o/exim-3.34/src/transport.c exim-3.34/src/transport.c
--- o/exim-3.34/src/transport.c    Wed Dec 19 12:50:31 2001
+++ exim-3.34/src/transport.c    Wed Mar  6 13:56:43 2002
@@ -536,7 +536,14 @@
       struct aci *plist = NULL;
       void *reset_point = store_get(0);


-      for (pp = p; pp->parent != NULL; pp = pp->parent);
+      /* Loop over all parents, any of them might match a dupbackptr
+      in the add_duplicate list. Yes we should indent this better
+      but the patch is clearer this way, I think ;) */
+
+      for (pp = p; pp->parent != NULL; pp = pp->parent)
+      {
+
+        if (pp->flags & af_set_envto_hdr) break;


       /* Scan for any duplicates that relate to this address, and include their
       ultimate parents. However, we want to avoid duplication in the list,
@@ -547,19 +554,20 @@


       for (dup = addr_duplicate; dup != NULL; dup = dup->next)
         {
-        if (strcmpic(dup->orig, p->orig) == 0)
+        if (dup->dupbackptr == pp)
           {
           address_item *dup_orig;
           struct aci *ppp;


           for (dup_orig = dup; dup_orig->parent != NULL;
-            dup_orig = dup_orig->parent);
+            dup_orig = dup_orig->parent)
+              if (dup_orig->flags & af_set_envto_hdr) break;


           /* If the parent is the parent of the main address item, skip it.
           Otherwise, scan the list of already output parents, and skip if
           we've done this one already. */


-          if (dup_orig == pp) continue;
+          /*if (dup_orig == pp) continue;*/
           for (ppp = plist; ppp != NULL; ppp = ppp->next)
             {
             if (dup_orig == ppp->ptr) break;
@@ -581,6 +589,7 @@
           len = 0;
           }
         }
+      }


       store_reset(reset_point);


diff -ruN o/exim-3.34/src/tree.c exim-3.34/src/tree.c
--- o/exim-3.34/src/tree.c    Wed Dec 19 12:50:31 2001
+++ exim-3.34/src/tree.c    Wed Mar  6 00:23:57 2002
@@ -85,11 +85,11 @@
 */


void
-tree_add_duplicate(char *s, BOOL pfr)
+tree_add_duplicate(char *s, address_item *a, BOOL pfr)
{
tree_node *node = store_get(sizeof(tree_node) + (int)strlen(s));
strcpy(node->name, pfr? s : address_prepare(s));
-node->data.ptr = NULL;
+node->data.ptr = a;
if (!tree_insertnode(&tree_duplicates, node)) store_reset(node);
}

--
Computers are useless, they only give answers. --Pablo Picasso