X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/911f6fde86bcc031ffd71f05651348c03622a6a0..929ba01ccb7fafbe89e4fa60e93ab2b5f4aab1df:/src/src/deliver.c diff --git a/src/src/deliver.c b/src/src/deliver.c index 655ec9b8e..dda4897b9 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/deliver.c,v 1.24 2005/12/12 11:41:50 ph10 Exp $ */ +/* $Cambridge: exim/src/src/deliver.c,v 1.29 2006/02/21 16:24:19 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. */ @@ -1490,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 * @@ -1705,7 +1743,7 @@ if ((pid = fork()) == 0) if (addr->transport->setup != NULL) { - switch((addr->transport->setup)(addr->transport, addr, NULL, + switch((addr->transport->setup)(addr->transport, addr, NULL, uid, gid, &(addr->message))) { case DEFER: @@ -1991,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-replied\n"); - fprintf(f, "From: Mail Delivery System \n", - qualify_domain_sender); + 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. */ @@ -2250,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) @@ -2282,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) { @@ -3567,12 +3617,25 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) else return_path = new_return_path; } + /* Find the uid, gid, and use_initgroups setting for this transport. Failure + logs and sets up error messages, so we just post-process and continue with + the next address. */ + + if (!findugid(addr, tp, &uid, &gid, &use_initgroups)) + { + remote_post_process(addr, LOG_MAIN|LOG_PANIC, NULL, fallback); + continue; + } + /* If this transport has a setup function, call it now so that it gets run in this process and not in any subprocess. That way, the results of - any setup that are retained by the transport can be reusable. */ + any setup that are retained by the transport can be reusable. One of the + things the setup does is to set the fallback host lists in the addresses. + That is why it is called at this point, before the continue delivery + processing, because that might use the fallback hosts. */ if (tp->setup != NULL) - (void)((tp->setup)(addr->transport, addr, NULL, NULL)); + (void)((tp->setup)(addr->transport, addr, NULL, uid, gid, NULL)); /* If this is a run to continue delivery down an already-established channel, check that this set of addresses matches the transport and @@ -3648,16 +3711,6 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) transport_filter_argv = NULL; - /* Find the uid, gid, and use_initgroups setting for this transport. Failure - logs and sets up error messages, so we just post-process and continue with - the next address. */ - - if (!findugid(addr, tp, &uid, &gid, &use_initgroups)) - { - remote_post_process(addr, LOG_MAIN|LOG_PANIC, NULL, fallback); - continue; - } - /* Create the pipe for inter-process communication. If pipe creation fails, it is probably because the value of remote_max_parallel is so large that too many file descriptors for pipes have been created. Arrange @@ -5175,7 +5228,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 @@ -5183,7 +5249,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);