X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fdeliver.c;h=23e63d553d188426538ad0e826a0b72d090812db;hb=fd98a5c6771f3a5a686e54370b0525dcc3dca2f9;hp=34f75fe13c42a03f2cebc1f13f67b3c2362208a9;hpb=1ac6b2e7857d7b6645dbd09047c4c2ac3b6cef1d;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/deliver.c b/src/src/deliver.c index 34f75fe13..23e63d553 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -785,6 +785,11 @@ else } } + #ifdef EXPERIMENTAL_PRDR + if (addr->flags & af_prdr_used) + s = string_append(s, &size, &ptr, 1, US" PRDR"); + #endif + if ((log_extra_selector & LX_smtp_confirmation) != 0 && addr->message != NULL) { @@ -1871,6 +1876,9 @@ if ((pid = fork()) == 0) set_process_info("delivering %s to %s using %s", message_id, addr->local_part, addr->transport->name); + /* Setting this global in the subprocess means we need never clear it */ + transport_name = addr->transport->name; + /* If a transport filter has been specified, set up its argument list. Any errors will get put into the address, and FALSE yielded. */ @@ -2386,45 +2394,8 @@ while (addr_local != NULL) to do, which is for the ultimate address timeout. */ if (!ok) - { - retry_config *retry = - retry_find_config(retry_key+2, addr2->domain, - retry_record->basic_errno, - retry_record->more_errno); - - DEBUG(D_deliver|D_retry) - { - debug_printf("retry time not reached for %s: " - "checking ultimate address timeout\n", addr2->address); - debug_printf(" now=%d first_failed=%d next_try=%d expired=%d\n", - (int)now, (int)retry_record->first_failed, - (int)retry_record->next_try, retry_record->expired); - } - - if (retry != NULL && retry->rules != NULL) - { - retry_rule *last_rule; - for (last_rule = retry->rules; - last_rule->next != NULL; - last_rule = last_rule->next); - DEBUG(D_deliver|D_retry) - debug_printf(" received_time=%d diff=%d timeout=%d\n", - received_time, (int)now - received_time, last_rule->timeout); - if (now - received_time > last_rule->timeout) ok = TRUE; - } - 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) - { - if (ok) debug_printf("on queue longer than maximum retry for " - "address - allowing delivery\n"); - } - } + ok = retry_ultimate_address_timeout(retry_key, addr2->domain, + retry_record, now); } } else DEBUG(D_retry) debug_printf("no retry record exists\n"); @@ -2947,6 +2918,11 @@ while (!done) while (*ptr++); break; +#ifdef EXPERIMENTAL_PRDR + case 'P': + addr->flags |= af_prdr_used; break; +#endif + case 'A': if (addr == NULL) { @@ -3892,8 +3868,10 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) int fd = pfd[pipe_write]; host_item *h; - /* There are weird circumstances in which logging is disabled */ + /* Setting this global in the subprocess means we need never clear it */ + transport_name = tp->name; + /* There are weird circumstances in which logging is disabled */ disable_logging = tp->disable_logging; /* Show pids on debug output if parallelism possible */ @@ -4049,6 +4027,10 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++) rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer); } + #ifdef EXPERIMENTAL_PRDR + if (addr->flags & af_prdr_used) rmt_dlv_checked_write(fd, "P", 1); + #endif + /* Retry information: for most success cases this will be null. */ for (r = addr->retries; r != NULL; r = r->next) @@ -5656,7 +5638,18 @@ while (addr_new != NULL) /* Loop until all addresses dealt with */ will be far too many attempts for an address that gets a 4xx error. In fact, after such an error, we should not get here because, the host should not be remembered as one this message needs. However, there was a bug that - used to cause this to happen, so it is best to be on the safe side. */ + used to cause this to happen, so it is best to be on the safe side. + + Even if we haven't reached the retry time in the hints, there is one more + check to do, which is for the ultimate address timeout. We only do this + check if there is an address retry record and there is not a domain retry + record; this implies that previous attempts to handle the address had the + retry_use_local_parts option turned on. We use this as an approximation + for the destination being like a local delivery, for example delivery over + LMTP to an IMAP message store. In this situation users are liable to bump + into their quota and thereby have intermittently successful deliveries, + which keep the retry record fresh, which can lead to us perpetually + deferring messages. */ else if (((queue_running && !deliver_force) || continue_hostname != NULL) && @@ -5666,7 +5659,11 @@ while (addr_new != NULL) /* Loop until all addresses dealt with */ || (address_retry_record != NULL && now < address_retry_record->next_try)) - ) + && + (domain_retry_record != NULL || + address_retry_record == NULL || + !retry_ultimate_address_timeout(addr->address_retry_key, + addr->domain, address_retry_record, now))) { addr->message = US"retry time not reached"; addr->basic_errno = ERRNO_RRETRY; @@ -6118,6 +6115,11 @@ if (addr_remote != NULL) regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE); #endif + #ifdef EXPERIMENTAL_PRDR + if (regex_PRDR == NULL) regex_PRDR = + regex_must_compile(US"\\n250[\\s\\-]PRDR(\\s|\\n|$)", FALSE, TRUE); + #endif + /* Now sort the addresses if required, and do the deliveries. The yield of do_remote_deliveries is FALSE when mua_wrapper is set and all addresses cannot be delivered in one transaction. */