+#endif
+ }
+
+ if ( (cutthrough.delivery || options & vopt_callout_hold)
+ && rcpt_count == 1
+ && done
+ && yield == OK
+ && (options & (vopt_callout_recipsender|vopt_callout_recippmaster|vopt_success_on_redirect))
+ == vopt_callout_recipsender
+ && !random_local_part
+ && !pm_mailfrom
+ && cutthrough.cctx.sock < 0
+ && !sx.lmtp
+ )
+ {
+ address_item * parent, * caddr;
+
+ HDEBUG(D_acl|D_v) debug_printf_indent("holding verify callout open for %s\n",
+ cutthrough.delivery
+ ? "cutthrough delivery" : "potential further verifies and delivery");
+
+ cutthrough.callout_hold_only = !cutthrough.delivery;
+ cutthrough.is_tls = tls_out.active.sock >= 0;
+ /* We assume no buffer in use in the outblock */
+ cutthrough.cctx = sx.cctx;
+ cutthrough.nrcpt = 1;
+ cutthrough.transport = addr->transport->name;
+ cutthrough.interface = interface;
+ cutthrough.snd_port = sending_port;
+ cutthrough.peer_options = smtp_peer_options;
+ cutthrough.host = *host;
+ {
+ int oldpool = store_pool;
+ store_pool = POOL_PERM;
+ cutthrough.snd_ip = string_copy(sending_ip_address);
+ cutthrough.host.name = string_copy(host->name);
+ cutthrough.host.address = string_copy(host->address);
+ store_pool = oldpool;
+ }
+
+ /* Save the address_item and parent chain for later logging */
+ cutthrough.addr = *addr;
+ cutthrough.addr.next = NULL;
+ cutthrough.addr.host_used = &cutthrough.host;
+ for (caddr = &cutthrough.addr, parent = addr->parent;
+ parent;
+ caddr = caddr->parent, parent = parent->parent)
+ *(caddr->parent = store_get(sizeof(address_item))) = *parent;
+
+ ctctx.outblock.buffer = ctbuffer;
+ ctctx.outblock.buffersize = sizeof(ctbuffer);
+ ctctx.outblock.ptr = ctbuffer;
+ /* ctctx.outblock.cmd_count = 0; ctctx.outblock.authenticating = FALSE; */
+ ctctx.outblock.cctx = &cutthrough.cctx;
+ }
+ else
+ {
+ /* Ensure no cutthrough on multiple verifies that were incompatible */
+ if (options & vopt_callout_recipsender)
+ cancel_cutthrough_connection(TRUE, US"not usable for cutthrough");
+ if (sx.send_quit)
+ {
+ (void) smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n");
+
+ /* Wait a short time for response, and discard it */
+ smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', 1);
+ }
+
+ if (sx.cctx.sock >= 0)
+ {
+#ifdef SUPPORT_TLS
+ if (sx.cctx.tls_ctx)
+ {
+ tls_close(sx.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
+ sx.cctx.tls_ctx = NULL;
+ }
+#endif
+ HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP(close)>>\n");
+ (void)close(sx.cctx.sock);
+ sx.cctx.sock = -1;
+#ifndef DISABLE_EVENT
+ (void) event_raise(addr->transport->event_action, US"tcp:close", NULL);
+#endif
+ }
+ }
+
+ if (!done || yield != OK)
+ addr->message = string_sprintf("%s [%s] : %s", host->name, host->address,
+ addr->message);
+ } /* Loop through all hosts, while !done */
+ }
+
+/* If we get here with done == TRUE, a successful callout happened, and yield
+will be set OK or FAIL according to the response to the RCPT command.
+Otherwise, we looped through the hosts but couldn't complete the business.
+However, there may be domain-specific information to cache in both cases. */
+
+if (!(options & vopt_callout_no_cache))
+ cache_callout_write(&new_domain_record, addr->domain,
+ done, &new_address_record, address_key);
+
+/* Failure to connect to any host, or any response other than 2xx or 5xx is a
+temporary error. If there was only one host, and a response was received, leave
+it alone if supplying details. Otherwise, give a generic response. */
+
+if (!done)
+ {
+ uschar * dullmsg = string_sprintf("Could not complete %s verify callout",
+ options & vopt_is_recipient ? "recipient" : "sender");
+ yield = DEFER;
+
+ addr->message = host_list->next || !addr->message
+ ? dullmsg : string_sprintf("%s: %s", dullmsg, addr->message);
+
+ addr->user_message = smtp_return_error_details
+ ? string_sprintf("%s for <%s>.\n"
+ "The mail server(s) for the domain may be temporarily unreachable, or\n"
+ "they may be permanently unreachable from this server. In the latter case,\n%s",
+ dullmsg, addr->address,
+ options & vopt_is_recipient
+ ? "the address will never be accepted."
+ : "you need to change the address or create an MX record for its domain\n"
+ "if it is supposed to be generally accessible from the Internet.\n"
+ "Talk to your mail administrator for details.")
+ : dullmsg;
+
+ /* Force a specific error code */
+
+ addr->basic_errno = ERRNO_CALLOUTDEFER;
+ }
+
+/* Come here from within the cache-reading code on fast-track exit. */
+
+END_CALLOUT:
+tls_modify_variables(&tls_in);
+return yield;
+}
+
+
+
+/* Called after recipient-acl to get a cutthrough connection open when
+ one was requested and a recipient-verify wasn't subsequently done.
+*/
+int
+open_cutthrough_connection(address_item * addr)
+{
+address_item addr2;
+int rc;