X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/47c7a64acebb31f5b11e79d3da2e3cdcd56b3f68..064a94c915ab9d962a876049ed864a56dc2c7af4:/src/src/deliver.c diff --git a/src/src/deliver.c b/src/src/deliver.c index 23875d959..e1e3714cc 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/deliver.c,v 1.21 2005/06/28 10:23:35 ph10 Exp $ */ +/* $Cambridge: exim/src/src/deliver.c,v 1.28 2006/02/08 16:10:46 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2006 */ /* See the file NOTICE for conditions of use and distribution. */ /* The main code for delivering a message. */ @@ -1304,6 +1304,14 @@ else if (tp->expand_gid != NULL) } } +/* If the transport did not set a group, see if the router did. */ + +if (!gid_set && testflag(addr, af_gid_set)) + { + *gidp = addr->gid; + gid_set = TRUE; + } + /* Pick up a uid from the transport if one is set. */ if (tp->uid_set) *uidp = tp->uid; @@ -1339,20 +1347,13 @@ else if (tp->deliver_as_creator) } } -/* Otherwise see if the address specifies the uid and if so, take its -initgroups flag. The gid from the address is taken only if the transport hasn't -set it. In other words, a gid on the transport overrides the gid on the -address. */ +/* Otherwise see if the address specifies the uid and if so, take it and its +initgroups flag. */ else if (testflag(addr, af_uid_set)) { *uidp = addr->uid; *igfp = testflag(addr, af_initgroups); - if (!gid_set) - { - *gidp = addr->gid; - gid_set = TRUE; - } } /* Nothing has specified the uid - default to the Exim user, and group if the @@ -1368,7 +1369,9 @@ else } } -/* If no gid is set, it is a disaster. */ +/* If no gid is set, it is a disaster. We default to the Exim gid only if +defaulting to the Exim uid. In other words, if the configuration has specified +a uid, it must also provide a gid. */ if (!gid_set) { @@ -1487,6 +1490,44 @@ return FALSE; +/****************************************************** +* Check for a given header in a header string * +******************************************************/ + +/* This function is used when generating quota warnings. The configuration may +specify any header lines it likes in quota_warn_message. If certain of them are +missing, defaults are inserted, so we need to be able to test for the presence +of a given header. + +Arguments: + hdr the required header name + hstring the header string + +Returns: TRUE the header is in the string + FALSE the header is not in the string +*/ + +static BOOL +contains_header(uschar *hdr, uschar *hstring) +{ +int len = Ustrlen(hdr); +uschar *p = hstring; +while (*p != 0) + { + if (strncmpic(p, hdr, len) == 0) + { + p += len; + while (*p == ' ' || *p == '\t') p++; + if (*p == ':') return TRUE; + } + while (*p != 0 && *p != '\n') p++; + if (*p == '\n') p++; + } +return FALSE; +} + + + /************************************************* * Perform a local delivery * @@ -1988,12 +2029,13 @@ if (addr->special_action == SPECIAL_WARN && if (pid > 0) { FILE *f = fdopen(fd, "wb"); - - if (errors_reply_to != NULL) + if (errors_reply_to != NULL && + !contains_header(US"Reply-To", warn_message)) fprintf(f, "Reply-To: %s\n", errors_reply_to); - fprintf(f, "Auto-Submitted: auto-generated\n"); - fprintf(f, "From: Mail Delivery System \n", - qualify_domain_sender); + fprintf(f, "Auto-Submitted: auto-replied\n"); + if (!contains_header(US"From", warn_message)) + fprintf(f, "From: Mail Delivery System \n", + qualify_domain_sender); fprintf(f, "%s", CS warn_message); /* Close and wait for child process to complete, without a timeout. */ @@ -2247,10 +2289,12 @@ while (addr_local != NULL) DEBUG(D_retry) { - debug_printf("retry record exists: age=%d (max=%d)\n", - (int)(now - retry_record->time_stamp), retry_data_expire); - debug_printf(" time to retry = %d expired = %d\n", - (int)(now - retry_record->next_try), retry_record->expired); + debug_printf("retry record exists: age=%s ", + readconf_printtime(now - retry_record->time_stamp)); + debug_printf("(max %s)\n", readconf_printtime(retry_data_expire)); + debug_printf(" time to retry = %s expired = %d\n", + readconf_printtime(retry_record->next_try - now), + retry_record->expired); } if (queue_running && !deliver_force) @@ -2279,9 +2323,18 @@ while (addr_local != NULL) for (last_rule = retry->rules; last_rule->next != NULL; last_rule = last_rule->next); + DEBUG(D_deliver|D_retry) + debug_printf("now=%d received_time=%d diff=%d timeout=%d\n", + (int)now, received_time, (int)now - received_time, + last_rule->timeout); if (now - received_time > last_rule->timeout) ok = TRUE; } - else ok = TRUE; /* No rule => timed out */ + else + { + DEBUG(D_deliver|D_retry) + debug_printf("no retry rule found: assume timed out\n"); + ok = TRUE; /* No rule => timed out */ + } DEBUG(D_deliver|D_retry) { @@ -5172,7 +5225,20 @@ while (addr_new != NULL) /* Loop until all addresses dealt with */ if (testflag(addr, af_pfr)) { - int offset = testflag(addr->parent, af_homonym)? 3:0; + /* If an autoreply in a filter could not generate a syntactically valid + address, give up forthwith. Set af_ignore_error so that we don't try to + generate a bounce. */ + + if (testflag(addr, af_bad_reply)) + { + addr->basic_errno = ERRNO_BADADDRESS2; + addr->local_part = addr->address; + addr->message = + US"filter autoreply generated syntactically invalid recipient"; + setflag(addr, af_ignore_error); + (void)post_process_one(addr, FAIL, LOG_MAIN, DTYPE_ROUTER, 0); + continue; /* with the next new address */ + } /* If two different users specify delivery to the same pipe or file or autoreply, there should be two different deliveries, so build a unique @@ -5180,7 +5246,8 @@ while (addr_new != NULL) /* Loop until all addresses dealt with */ duplicate testing and recording delivery, and also for retrying. */ addr->unique = - string_sprintf("%s:%s", addr->address, addr->parent->unique + offset); + string_sprintf("%s:%s", addr->address, addr->parent->unique + + (testflag(addr->parent, af_homonym)? 3:0)); addr->address_retry_key = addr->domain_retry_key = string_sprintf("T:%s", addr->unique); @@ -5856,6 +5923,15 @@ deliveries are done first, then remote ones. If ever the problems of how to handle fallback transports are figured out, this section can be put into a loop for handling fallbacks, though the uid switching will have to be revised. */ +/* Precompile a regex that is used to recognize a parameter in response +to an LHLO command, if is isn't already compiled. This may be used on both +local and remote LMTP deliveries. */ + +if (regex_IGNOREQUOTA == NULL) regex_IGNOREQUOTA = + regex_must_compile(US"\\n250[\\s\\-]IGNOREQUOTA(\\s|\\n|$)", FALSE, TRUE); + +/* Handle local deliveries */ + if (addr_local != NULL) { DEBUG(D_deliver|D_transport) @@ -6168,7 +6244,7 @@ while (addr_failed != NULL) if (errors_reply_to != NULL) fprintf(f, "Reply-To: %s\n", errors_reply_to); - fprintf(f, "Auto-Submitted: auto-generated\n"); + fprintf(f, "Auto-Submitted: auto-replied\n"); fprintf(f, "From: Mail Delivery System \n", qualify_domain_sender); fprintf(f, "To: %s\n", bounce_recipient); @@ -6690,7 +6766,7 @@ else if (addr_defer != (address_item *)(+1)) if (errors_reply_to != NULL) fprintf(f, "Reply-To: %s\n", errors_reply_to); - fprintf(f, "Auto-Submitted: auto-generated\n"); + fprintf(f, "Auto-Submitted: auto-replied\n"); fprintf(f, "From: Mail Delivery System \n", qualify_domain_sender); fprintf(f, "To: %s\n", recipients);