In article <Pine.SOL.4.44.0203050849320.18501-100000@???>,
Philip Hazel <ph10@???> wrote:
>I'm afraid this is pretty fundamental to the way Exim works, and it is
>the same in Exim 4.
>I note the problem, but I don't think there's anything I can do about it
>in a hurry. Sorry.
Okay, I spent some time mucking around with the exim source today
and I came up with the following patch.
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).
This way, we can much better decide when we build the envelope-to
header how the duplicate addresses were collapsed and what the
real original addresses were.
The patch isn't that big, and is attached below. I'd like to
know what you think.
Things TODO perhaps:
- 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. This might be achieved in
directors/forwardfile.c by setting a special flag in the generated
address if it's a new address which is not us. The code for envelope-to
should only take the immidiate parent if this flag is set.
- Because it's common in a .forwardfile to list ones own address
to leave a local copy, perhaps a special syntax should be invented
for that - I'm thinking of :self:
- For exim4, which I haven't looked at, you might want to do away
with the global addr_duplicate list and add duplicates to the
addresses themselves. This would be a tad cleaner.
Anyway, that is of later concern. The patch that solves my
immidiate problem is below - against 3.34. Comments welcome, I'm
not sure I know what I am doing here ;)
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/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 00:27:35 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 */
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 00:19:07 2002
@@ -536,7 +536,12 @@
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)
+ {
/* Scan for any duplicates that relate to this address, and include their
ultimate parents. However, we want to avoid duplication in the list,
@@ -547,7 +552,7 @@
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;
@@ -581,6 +586,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