diff -urN src.orig/acl.c src/acl.c --- src.orig/acl.c Mon Jan 8 16:25:36 2007 +++ src/acl.c Fri Mar 9 17:14:33 2007 @@ -960,6 +960,16 @@ newtype = htype_add_bot; p += 8; } + else if (strncmpic(p, US":delete:", 8) == 0) + { + newtype = htype_add_del; + p += 8; + } + else if (strncmpic(p, US":replace:", 9) == 0) + { + newtype = htype_add_rep; + p += 9; + } while (*p == ' ' || *p == '\t') p++; } diff -urN src.orig/macros.h src/macros.h --- src.orig/macros.h Mon Jan 8 16:25:36 2007 +++ src/macros.h Fri Mar 9 17:14:33 2007 @@ -569,6 +569,8 @@ #define htype_add_rec 'r' #define htype_add_bot 'z' #define htype_add_rfc 'f' +#define htype_add_del 'l' +#define htype_add_rep 'u' /* Types of item in options lists. These are the bottom 8 bits of the "type" field, which is an int. The opt_void value is used for entries in tables that diff -urN src.orig/receive.c src/receive.c --- src.orig/receive.c Mon Jan 8 16:25:36 2007 +++ src/receive.c Fri Mar 9 17:14:33 2007 @@ -896,8 +896,10 @@ static void add_acl_headers(uschar *acl_name) { -header_line *h, *next; +header_line *h, *next, *rep; header_line *last_received = NULL; +int occ; +uschar *tagend, *value, oldtagend; if (acl_added_headers == NULL) return; DEBUG(D_receive|D_acl) debug_printf(">>Headers added by %s ACL:\n", acl_name); @@ -944,7 +946,47 @@ DEBUG(D_receive|D_acl) debug_printf(" (before any non-Received: or Resent-*: header)"); break; - default: + case htype_add_del: + /* Delete one or all headers which match this tag */ + for (tagend = h->text; *tagend && *tagend != ':' && *tagend != ' ' && *tagend != '\t'; ++tagend) 1; + for (value = tagend; *value == ' ' || *tagend == '\t'; ++value) 1; + ++value; + oldtagend = *tagend; *tagend = '\0'; + occ = (*value ? atoi(value) : 0); + header_remove(occ, h->text); + *tagend = oldtagend; + /* Add to the top as a deleted header */ + h->type = htype_old; + h->next = header_list; + header_list = h; + DEBUG(D_receive|D_acl) debug_printf(" (deleted)"); + break; + + case htype_add_rep: + /* Replace the first matching header. If none match, add to the end */ + for (tagend = h->text; *tagend && *tagend != ':' && *tagend != ' ' && *tagend != '\t'; ++tagend) 1; + oldtagend = *tagend; *tagend = '\0'; + for (rep = header_list; rep != NULL; rep = rep->next) + { + if (header_testname(rep, h->text, tagend - h->text, TRUE)) + { + h->next = rep->next; + rep->next = h; + rep->type = htype_old; + DEBUG(D_receive|D_acl) debug_printf(" (replaced)"); + break; + } + } + *tagend = oldtagend; + /* If we didn't replace one, append it */ + if (!rep) + { + h->next = NULL; + header_last->next = h; + } + break; + + default: /* htype_add_bot */ h->next = NULL; header_last->next = h; break; @@ -958,8 +1000,12 @@ for existence tests when messages are received. So discard any lower case flag values. */ - h->type = header_checkname(h, FALSE); - if (h->type >= 'a') h->type = htype_other; + /* The new header may already have been marked as deleted */ + if (h->type != htype_old) + { + h->type = header_checkname(h, FALSE); + if (h->type >= 'a') h->type = htype_other; + } DEBUG(D_receive|D_acl) debug_printf(" %s", header_last->text); }