be terminated by colon or white space, because it may contain a wide variety of
characters. Note also that braces must &'not'& be used.
+.vitem &$headers_added$&
+.vindex "&$headers_added$&"
+Within an ACL this variable contains the headers added so far by
+the ACL modifier add_header (section &<<SECTaddheadacl>>&).
+The headers are a newline-separated list.
+
.vitem &$home$&
.vindex "&$home$&"
When the &%check_local_user%& option is set for a router, the user's home
are included in the entry that is written to the reject log.
.cindex "header lines" "added; visibility of"
-Header lines are not visible in string expansions until they are added to the
+Header lines are not visible in string expansions
+of message headers
+until they are added to the
message. It follows that header lines defined in the MAIL, RCPT, and predata
ACLs are not visible until the DATA ACL and MIME ACLs are run. Similarly,
header lines that are added by the DATA or MIME ACLs are not visible in those
this, you can use ACL variables, as described in section
&<<SECTaclvariables>>&.
+The list of headers yet to be added is given by the &%$headers_added%& variable.
+
The &%add_header%& modifier acts immediately as it is encountered during the
processing of an ACL. Notice the difference between these two cases:
.display
+/*************************************************
+* List the added header lines *
+*************************************************/
+uschar *
+fn_hdrs_added(void)
+{
+uschar * ret = NULL;
+header_line * h = acl_added_headers;
+uschar * s;
+uschar * cp;
+int size = 0;
+int ptr = 0;
+
+if (!h) return NULL;
+
+do
+ {
+ s = h->text;
+ while ((cp = Ustrchr(s, '\n')) != NULL)
+ {
+ if (cp[1] == '\0') break;
+
+ /* contains embedded newline; needs doubling */
+ ret = string_cat(ret, &size, &ptr, s, cp-s+1);
+ ret = string_cat(ret, &size, &ptr, "\n", 1);
+ s = cp+1;
+ }
+ /* last bit of header */
+
+ ret = string_cat(ret, &size, &ptr, s, cp-s+1); /* newline-sep list */
+ }
+while(h = h->next);
+
+ret[ptr-1] = '\0'; /* overwrite last newline */
+return ret;
+}
+
+
/*************************************************
* Set up removed header line(s) *
*************************************************/
vtype_msgheaders_raw, /* the message's headers, unprocessed */
vtype_localpart, /* extract local part from string */
vtype_domain, /* extract domain from string */
- vtype_recipients, /* extract recipients from recipients list */
- /* (available only in system filters, ACLs, and */
- /* local_scan()) */
+ vtype_string_func, /* value is string returned by given function */
vtype_todbsdin, /* value not used; generate BSD inbox tod */
vtype_tode, /* value not used; generate tod in epoch format */
vtype_todel, /* value not used; generate tod in epoch/usec format */
#endif
};
+static uschar * fn_recipients(void);
+
/* This table must be kept in alphabetical order. */
static var_entry var_table[] = {
#ifdef WITH_OLD_DEMIME
{ "found_extension", vtype_stringptr, &found_extension },
#endif
+ { "headers_added", vtype_string_func, &fn_hdrs_added },
{ "home", vtype_stringptr, &deliver_home },
{ "host", vtype_stringptr, &deliver_host },
{ "host_address", vtype_stringptr, &deliver_host_address },
{ "received_time", vtype_int, &received_time },
{ "recipient_data", vtype_stringptr, &recipient_data },
{ "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure },
- { "recipients", vtype_recipients, NULL },
+ { "recipients", vtype_string_func, &fn_recipients },
{ "recipients_count", vtype_int, &recipients_count },
#ifdef WITH_CONTENT_SCAN
{ "regex_match_string", vtype_stringptr, ®ex_match_string },
+/*************************************************
+* Return list of recipients *
+*************************************************/
+/* A recipients list is available only during system message filtering,
+during ACL processing after DATA, and while expanding pipe commands
+generated from a system filter, but not elsewhere. */
+
+static uschar *
+fn_recipients(void)
+{
+if (!enable_dollar_recipients) return NULL; else
+ {
+ int size = 128;
+ int ptr = 0;
+ int i;
+ uschar * s = store_get(size);
+ for (i = 0; i < recipients_count; i++)
+ {
+ if (i != 0) s = string_cat(s, &size, &ptr, US", ", 2);
+ s = string_cat(s, &size, &ptr, recipients_list[i].address,
+ Ustrlen(recipients_list[i].address));
+ }
+ s[ptr] = 0; /* string_cat() leaves room */
+ return s;
+ }
+}
+
+
/*************************************************
* Find value of a variable *
*************************************************/
}
return (s == NULL)? US"" : s;
- /* A recipients list is available only during system message filtering,
- during ACL processing after DATA, and while expanding pipe commands
- generated from a system filter, but not elsewhere. */
-
- case vtype_recipients:
- if (!enable_dollar_recipients) return NULL; else
+ case vtype_string_func:
{
- int size = 128;
- int ptr = 0;
- int i;
- s = store_get(size);
- for (i = 0; i < recipients_count; i++)
- {
- if (i != 0) s = string_cat(s, &size, &ptr, US", ", 2);
- s = string_cat(s, &size, &ptr, recipients_list[i].address,
- Ustrlen(recipients_list[i].address));
- }
- s[ptr] = 0; /* string_cat() leaves room */
+ uschar * (*fn)() = var_table[middle].value;
+ return fn();
}
- return s;
case vtype_pspace:
{