+ /* Handle normal addresses. First, split up into local part and domain,
+ handling the %-hack if necessary. There is the possibility of a defer from
+ a lookup in percent_hack_domains. */
+
+ if ((rc = deliver_split_address(addr)) == DEFER)
+ {
+ addr->message = US"cannot check percent_hack_domains";
+ addr->basic_errno = ERRNO_LISTDEFER;
+ (void)post_process_one(addr, DEFER, LOG_MAIN, EXIM_DTYPE_NONE, 0);
+ continue;
+ }
+
+ /* Check to see if the domain is held. If so, proceed only if the
+ delivery was forced by hand. */
+
+ deliver_domain = addr->domain; /* set $domain */
+ if ( !forced && hold_domains
+ && (rc = match_isinlist(addr->domain, (const uschar **)&hold_domains, 0,
+ &domainlist_anchor, addr->domain_cache, MCL_DOMAIN, TRUE,
+ NULL)) != FAIL
+ )
+ {
+ if (rc == DEFER)
+ {
+ addr->message = US"hold_domains lookup deferred";
+ addr->basic_errno = ERRNO_LISTDEFER;
+ }
+ else
+ {
+ addr->message = US"domain is held";
+ addr->basic_errno = ERRNO_HELD;
+ }
+ (void)post_process_one(addr, DEFER, LOG_MAIN, EXIM_DTYPE_NONE, 0);
+ continue;
+ }
+
+ /* Now we can check for duplicates and previously delivered addresses. In
+ order to do this, we have to generate a "unique" value for each address,
+ because there may be identical actual addresses in a line of descendents.
+ The "unique" field is initialized to the same value as the "address" field,
+ but gets changed here to cope with identically-named descendents. */
+
+ for (parent = addr->parent; parent; parent = parent->parent)
+ if (strcmpic(addr->address, parent->address) == 0) break;
+
+ /* If there's an ancestor with the same name, set the homonym flag. This
+ influences how deliveries are recorded. Then add a prefix on the front of
+ the unique address. We use \n\ where n starts at 0 and increases each time.
+ It is unlikely to pass 9, but if it does, it may look odd but will still
+ work. This means that siblings or cousins with the same names are treated
+ as duplicates, which is what we want. */
+
+ if (parent)
+ {
+ setflag(addr, af_homonym);
+ if (parent->unique[0] != '\\')
+ addr->unique = string_sprintf("\\0\\%s", addr->address);
+ else
+ addr->unique = string_sprintf("\\%c\\%s", parent->unique[1] + 1,
+ addr->address);
+ }
+
+ /* Ensure that the domain in the unique field is lower cased, because
+ domains are always handled caselessly. */
+
+ for (uschar * p = Ustrrchr(addr->unique, '@'); *p; p++) *p = tolower(*p);
+
+ DEBUG(D_deliver|D_route) debug_printf("unique = %s\n", addr->unique);
+
+ if (tree_search(tree_nonrecipients, addr->unique))
+ {
+ DEBUG(D_deliver|D_route)
+ debug_printf("%s was previously delivered: discarded\n", addr->unique);
+ child_done(addr, tod_stamp(tod_log));
+ continue;
+ }
+
+ /* Get the routing retry status, saving the two retry keys (with and
+ without the local part) for subsequent use. If there is no retry record for
+ the standard address routing retry key, we look for the same key with the
+ sender attached, because this form is used by the smtp transport after a
+ 4xx response to RCPT when address_retry_include_sender is true. */
+
+ addr->domain_retry_key = string_sprintf("R:%s", addr->domain);
+ addr->address_retry_key = string_sprintf("R:%s@%s", addr->local_part,
+ addr->domain);
+
+ if (dbm_file)
+ {
+ domain_retry_record = dbfn_read(dbm_file, addr->domain_retry_key);
+ if ( domain_retry_record
+ && now - domain_retry_record->time_stamp > retry_data_expire
+ )
+ {
+ DEBUG(D_deliver|D_retry)
+ debug_printf("domain retry record present but expired\n");
+ domain_retry_record = NULL; /* Ignore if too old */
+ }
+
+ address_retry_record = dbfn_read(dbm_file, addr->address_retry_key);
+ if ( address_retry_record
+ && now - address_retry_record->time_stamp > retry_data_expire
+ )
+ {
+ DEBUG(D_deliver|D_retry)
+ debug_printf("address retry record present but expired\n");
+ address_retry_record = NULL; /* Ignore if too old */
+ }
+
+ if (!address_retry_record)
+ {
+ uschar *altkey = string_sprintf("%s:<%s>", addr->address_retry_key,
+ sender_address);
+ address_retry_record = dbfn_read(dbm_file, altkey);
+ if ( address_retry_record
+ && now - address_retry_record->time_stamp > retry_data_expire)
+ {
+ DEBUG(D_deliver|D_retry)
+ debug_printf("address<sender> retry record present but expired\n");
+ address_retry_record = NULL; /* Ignore if too old */
+ }
+ }
+ }
+ else
+ domain_retry_record = address_retry_record = NULL;
+
+ DEBUG(D_deliver|D_retry)
+ {
+ if (!domain_retry_record)
+ debug_printf("no domain retry record\n");
+ else
+ debug_printf("have domain retry record; next_try = now%+d\n",
+ f.running_in_test_harness ? 0 :
+ (int)(domain_retry_record->next_try - now));
+
+ if (!address_retry_record)
+ debug_printf("no address retry record\n");
+ else
+ debug_printf("have address retry record; next_try = now%+d\n",
+ f.running_in_test_harness ? 0 :
+ (int)(address_retry_record->next_try - now));
+ }
+
+ /* If we are sending a message down an existing SMTP connection, we must
+ assume that the message which created the connection managed to route
+ an address to that connection. We do not want to run the risk of taking
+ a long time over routing here, because if we do, the server at the other
+ end of the connection may time it out. This is especially true for messages
+ with lots of addresses. For this kind of delivery, queue_running is not
+ set, so we would normally route all addresses. We take a pragmatic approach
+ and defer routing any addresses that have any kind of domain retry record.
+ That is, we don't even look at their retry times. It doesn't matter if this
+ doesn't work occasionally. This is all just an optimization, after all.
+
+ The reason for not doing the same for address retries is that they normally
+ arise from 4xx responses, not DNS timeouts. */
+
+ if (continue_hostname && domain_retry_record)
+ {
+ addr->message = US"reusing SMTP connection skips previous routing defer";
+ addr->basic_errno = ERRNO_RRETRY;
+ (void)post_process_one(addr, DEFER, LOG_MAIN, EXIM_DTYPE_ROUTER, 0);
+
+ addr->message = domain_retry_record->text;
+ setflag(addr, af_pass_message);
+ }