X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/059ec3d9952740285fb1ebf47961b8aca2eb1b4a..e4a89c47c2a7d9a9268f36728b4b4f1b028b17b1:/src/src/deliver.c diff --git a/src/src/deliver.c b/src/src/deliver.c index 741d7b79c..ac23a33aa 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/deliver.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */ +/* $Cambridge: exim/src/src/deliver.c,v 1.11 2005/04/06 14:40:24 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* Copyright (c) University of Cambridge 1995 - 2005 */ /* See the file NOTICE for conditions of use and distribution. */ /* The main code for delivering a message. */ @@ -156,6 +156,13 @@ deliver_localpart_data = addr->p.localpart_data; deliver_domain = addr->domain; self_hostname = addr->self_hostname; +#ifdef EXPERIMENTAL_BRIGHTMAIL +bmi_deliver = 1; /* deliver by default */ +bmi_alt_location = NULL; +bmi_base64_verdict = NULL; +bmi_base64_tracker_verdict = NULL; +#endif + /* If there's only one address we can set everything. */ if (addr->next == NULL) @@ -205,6 +212,19 @@ if (addr->next == NULL) deliver_localpart_suffix = addr->parent->suffix; } } + +#ifdef EXPERIMENTAL_BRIGHTMAIL + /* Set expansion variables related to Brightmail AntiSpam */ + bmi_base64_verdict = bmi_get_base64_verdict(deliver_localpart_orig, deliver_domain_orig); + bmi_base64_tracker_verdict = bmi_get_base64_tracker_verdict(bmi_base64_verdict); + /* get message delivery status (0 - don't deliver | 1 - deliver) */ + bmi_deliver = bmi_get_delivery_status(bmi_base64_verdict); + /* if message is to be delivered, get eventual alternate location */ + if (bmi_deliver == 1) { + bmi_alt_location = bmi_get_alt_location(bmi_base64_verdict); + }; +#endif + } /* For multiple addresses, don't set local part, and leave the domain and @@ -709,9 +729,27 @@ else if (driver_type == DTYPE_ROUTER) /* If there's an error message set, ensure that it contains only printing characters - it should, but occasionally things slip in and this at least -stops the log format from getting wrecked. */ +stops the log format from getting wrecked. We also scan the message for an LDAP +expansion item that has a password setting, and flatten the password. This is a +fudge, but I don't know a cleaner way of doing this. (If the item is badly +malformed, it won't ever have gone near LDAP.) */ -if (addr->message != NULL) addr->message = string_printing(addr->message); +if (addr->message != NULL) + { + addr->message = string_printing(addr->message); + if (Ustrstr(addr->message, "failed to expand") != NULL && + (Ustrstr(addr->message, "ldap:") != NULL || + Ustrstr(addr->message, "ldapdn:") != NULL || + Ustrstr(addr->message, "ldapm:") != NULL)) + { + uschar *p = Ustrstr(addr->message, "pass="); + if (p != NULL) + { + p += 5; + while (*p != 0 && !isspace(*p)) *p++ = 'x'; + } + } + } /* If we used a transport that has one of the "return_output" options set, and if it did in fact generate some output, then for return_output we treat the @@ -1046,12 +1084,15 @@ else setflag(addr, af_ignore_error); /* Freeze the message if requested, or if this is a bounce message (or other - message with null sender). However, don't freeze if errors are being ignored. - The actual code to ignore occurs later, instead of sending a message. Logging - of freezing occurs later, just before writing the -H file. */ + message with null sender) and this address does not have its own errors + address. However, don't freeze if errors are being ignored. The actual code + to ignore occurs later, instead of sending a message. Logging of freezing + occurs later, just before writing the -H file. */ if (!testflag(addr, af_ignore_error) && - (addr->special_action == SPECIAL_FREEZE || sender_address[0] == 0)) + (addr->special_action == SPECIAL_FREEZE || + (sender_address[0] == 0 && addr->p.errors_address == NULL) + )) { frozen_info = (addr->special_action == SPECIAL_FREEZE)? US"" : (sender_local && !local_error_message)? @@ -1408,18 +1449,21 @@ return rc; *************************************************/ /* Check that this base address hasn't previously been delivered to its routed -transport. The check is necessary at delivery time in order to handle homonymic -addresses correctly in cases where the pattern of redirection changes between -delivery attempts (so the unique fields change). Non-homonymic previous -delivery is detected earlier, at routing time (which saves unnecessary -routing). +transport. If it has been delivered, mark it done. The check is necessary at +delivery time in order to handle homonymic addresses correctly in cases where +the pattern of redirection changes between delivery attempts (so the unique +fields change). Non-homonymic previous delivery is detected earlier, at routing +time (which saves unnecessary routing). + +Arguments: + addr the address item + testing TRUE if testing wanted only, without side effects -Argument: the address item Returns: TRUE if previously delivered by the transport */ static BOOL -previously_transported(address_item *addr) +previously_transported(address_item *addr, BOOL testing) { (void)string_format(big_buffer, big_buffer_size, "%s/%s", addr->unique + (testflag(addr, af_homonym)? 3:0), addr->transport->name); @@ -1429,7 +1473,7 @@ if (tree_search(tree_nonrecipients, big_buffer) != 0) DEBUG(D_deliver|D_route|D_transport) debug_printf("%s was previously delivered (%s transport): discarded\n", addr->address, addr->transport->name); - child_done(addr, tod_stamp(tod_log)); + if (!testing) child_done(addr, tod_stamp(tod_log)); return TRUE; } @@ -2016,7 +2060,7 @@ while (addr_local != NULL) attempts. Non-homonymic previous delivery is detected earlier, at routing time. */ - if (previously_transported(addr)) continue; + if (previously_transported(addr, FALSE)) continue; /* There are weird cases where logging is disabled */ @@ -2057,6 +2101,7 @@ while (addr_local != NULL) same characteristics. These are: same transport + not previously delivered (see comment about 50 lines above) same local part if the transport's configuration contains $local_part same domain if the transport's configuration contains $domain same errors address @@ -2070,6 +2115,7 @@ while (addr_local != NULL) { BOOL ok = tp == next->transport && + !previously_transported(next, TRUE) && (!uses_lp || Ustrcmp(next->local_part, addr->local_part) == 0) && (!uses_dom || Ustrcmp(next->domain, addr->domain) == 0) && same_strings(next->p.errors_address, addr->p.errors_address) && @@ -2533,13 +2579,13 @@ also by optional retry data. Read in large chunks into the big buffer and then scan through, interpreting the data therein. In most cases, only a single read will be necessary. No -individual item will ever be anywhere near 500 bytes in length, so by ensuring -that we read the next chunk when there is less than 500 bytes left in the -non-final chunk, we can assume each item is complete in store before handling -it. Actually, each item is written using a single write(), which is atomic for -small items (less than PIPE_BUF, which seems to be at least 512 in any Unix) so -even if we are reading while the subprocess is still going, we should never -have only a partial item in the buffer. +individual item will ever be anywhere near 2500 bytes in length, so by ensuring +that we read the next chunk when there is less than 2500 bytes left in the +non-final chunk, we can assume each item is complete in the buffer before +handling it. Each item is written using a single write(), which is atomic for +small items (less than PIPE_BUF, which seems to be at least 512 in any Unix and +often bigger) so even if we are reading while the subprocess is still going, we +should never have only a partial item in the buffer. Argument: poffset the offset of the parlist item @@ -2575,7 +2621,9 @@ completed. Each separate item is written to the pipe in a single write(), and as they are all short items, the writes will all be atomic and we should never find -ourselves in the position of having read an incomplete item. */ +ourselves in the position of having read an incomplete item. "Short" in this +case can mean up to about 1K in the case when there is a long error message +associated with an address. */ DEBUG(D_deliver) debug_printf("reading pipe for subprocess %d (%s)\n", (int)p->pid, eop? "ended" : "not ended"); @@ -2589,7 +2637,7 @@ while (!done) There will be only one read if we get all the available data (i.e. don't fill the buffer completely). */ - if (remaining < 500 && unfinished) + if (remaining < 2500 && unfinished) { int len; int available = big_buffer_size - remaining; @@ -3345,7 +3393,7 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) attempts. Non-homonymic previous delivery is detected earlier, at routing time. */ - if (previously_transported(addr)) continue; + if (previously_transported(addr, FALSE)) continue; /* Force failure if the message is too big. */ @@ -4614,6 +4662,8 @@ else if (system_filter != NULL && process_recipients != RECIP_FAIL_TIMEOUT) RDO_REWRITE, NULL, /* No :include: restriction (not used in filter) */ NULL, /* No sieve vacation directory (not sieve!) */ + NULL, /* No sieve user address (not sieve!) */ + NULL, /* No sieve subaddress (not sieve!) */ &ugid, /* uid/gid data */ &addr_new, /* Where to hang generated addresses */ &filter_message, /* Where to put error message */ @@ -6319,7 +6369,14 @@ if (addr_defer == NULL) sprintf(CS spoolname, "%s/input/%s/%s-H", spool_directory, message_subdir, id); if (Uunlink(spoolname) < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to unlink %s", spoolname); - log_write(0, LOG_MAIN, "Completed"); + + /* Log the end of this message, with queue time if requested. */ + + if ((log_extra_selector & LX_queue_time_overall) != 0) + log_write(0, LOG_MAIN, "Completed QT=%s", + readconf_printtime(time(NULL) - received_time)); + else + log_write(0, LOG_MAIN, "Completed"); } /* If there are deferred addresses, we are keeping this message because it is