+/* Everything has now been done for a successful message except logging its
+arrival, and outputting an SMTP response. While writing to the log, set a flag
+to cause a call to receive_bomb_out() if the log cannot be opened. */
+
+receive_call_bombout = TRUE;
+
+/* Before sending an SMTP response in a TCP/IP session, we check to see if
+there is unconsumed input (which there shouldn't be) or if the connection has
+gone away. This can be done because the end of a message is always a
+synchronization point. If the connection is still present, but there is no
+pending input, the result of a select() call will be zero. If, however, the
+connection has gone away, or if there is pending input, the result of select()
+will be non-zero. The two cases can be distinguished by trying to read the next
+input character. Of course, since TCP/IP is asynchronous, there is always a
+chance that the connection will vanish between the time of this test and the
+sending of the response, but the chance of this happening should be small.
+
+We also check for input that has already been received and is in the local
+input buffer (plain SMTP or TLS) by calling receive_smtp_buffered(). */
+
+if (smtp_input && sender_host_address != NULL && !sender_host_notsocket)
+ {
+ struct timeval tv;
+ fd_set select_check;
+ FD_ZERO(&select_check);
+ FD_SET(fileno(smtp_in), &select_check);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ if (select(fileno(smtp_in) + 1, &select_check, NULL, NULL, &tv) != 0 ||
+ receive_smtp_buffered())
+ {
+ uschar *msg;
+ if ((RECEIVE_GETC)() == EOF)
+ {
+ msg = US"SMTP connection lost after final dot";
+ smtp_reply = US""; /* No attempt to send a response */
+ }
+ else
+ {
+ msg = US"Synchronization error (data after final dot)";
+ smtp_reply = US"550 Synchronization error (data after final dot)";
+ }
+
+ /* Overwrite the log line workspace */
+
+ sptr = 0;
+ s = string_cat(s, &size, &sptr, msg, Ustrlen(msg));
+ s = add_host_info_for_log(s, &size, &sptr);
+ s[sptr] = 0;
+ log_write(0, LOG_MAIN, "%s", s);
+
+ /* We now have to delete the files for this aborted message. */
+
+ sprintf(CS spool_name, "%s/input/%s/%s-D", spool_directory, message_subdir,
+ message_id);
+ Uunlink(spool_name);
+
+ sprintf(CS spool_name, "%s/input/%s/%s-H", spool_directory, message_subdir,
+ message_id);
+ Uunlink(spool_name);
+
+ sprintf(CS spool_name, "%s/msglog/%s/%s", spool_directory, message_subdir,
+ message_id);
+ Uunlink(spool_name);
+
+ /* Do not accept any more messages on this connection. */
+
+ smtp_yield = FALSE;
+ goto TIDYUP;
+ }
+ }
+
+/* The connection has not gone away; we really are going to take responsibility
+for this message. */
+
+log_write(0, LOG_MAIN |
+ (((log_extra_selector & LX_received_recipients) != 0)? LOG_RECIPIENTS : 0) |
+ (((log_extra_selector & LX_received_sender) != 0)? LOG_SENDER : 0),
+ "%s", s);
+receive_call_bombout = FALSE;
+
+/* Log any control actions taken by an ACL or local_scan(). */
+
+if (deliver_freeze) log_write(0, LOG_MAIN, "frozen by %s", frozen_by);
+if (queue_only_policy) log_write(L_delay_delivery, LOG_MAIN,
+ "no immediate delivery: queued by %s", queued_by);
+