/* This list of names is used for performing the smtp_no_mail logging action.
It must be kept in step with the SCH_xxx enumerations. */
-static uschar *smtp_names[] =
+uschar * smtp_names[] =
{
US"NONE", US"AUTH", US"DATA", US"BDAT", US"EHLO", US"ETRN", US"EXPN",
US"HELO", US"HELP", US"MAIL", US"NOOP", US"QUIT", US"RCPT", US"RSET",
return;
case QUIT_CMD:
+ f.smtp_in_quit = TRUE;
smtp_printf("221 %s closing connection\r\n", FALSE, smtp_active_hostname);
mac_smtp_fflush();
return;
if (LOGGING(tls_peerdn) && tls_in.peerdn)
g = string_append(g, 3, US" DN=\"", string_printing(tls_in.peerdn), US"\"");
if (LOGGING(tls_sni) && tls_in.sni)
- g = string_append(g, 3, US" SNI=\"", string_printing(tls_in.sni), US"\"");
+ g = string_append(g, 2, US" SNI=", string_printing2(tls_in.sni, SP_TAB|SP_SPACE));
return g;
}
#endif
+
+
+static gstring *
+s_connhad_log(gstring * g)
+{
+const uschar * sep = smtp_connection_had[SMTP_HBUFF_SIZE-1] != SCH_NONE
+ ? US" C=..." : US" C=";
+
+for (int i = smtp_ch_index; i < SMTP_HBUFF_SIZE; i++)
+ if (smtp_connection_had[i] != SCH_NONE)
+ {
+ g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
+ sep = US",";
+ }
+for (int i = 0; i < smtp_ch_index; i++, sep = US",")
+ g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
+return g;
+}
+
+
/*************************************************
* Log lack of MAIL if so configured *
*************************************************/
void
smtp_log_no_mail(void)
{
-uschar * sep, * s;
+uschar * s;
gstring * g = NULL;
if (smtp_mailcmd_count > 0 || !LOGGING(smtp_no_mail))
g = s_tlslog(g);
#endif
-sep = smtp_connection_had[SMTP_HBUFF_SIZE-1] != SCH_NONE ? US" C=..." : US" C=";
-
-for (int i = smtp_ch_index; i < SMTP_HBUFF_SIZE; i++)
- if (smtp_connection_had[i] != SCH_NONE)
- {
- g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
- sep = US",";
- }
-
-for (int i = 0; i < smtp_ch_index; i++)
- {
- g = string_append(g, 2, sep, smtp_names[smtp_connection_had[i]]);
- sep = US",";
- }
+g = s_connhad_log(g);
if (!(s = string_from_gstring(g))) s = US"";
raw_recipients_count = recipients_count = recipients_list_max = 0;
message_linecount = 0;
message_size = -1;
+message_body = message_body_end = NULL;
acl_added_headers = NULL;
acl_removed_headers = NULL;
f.queue_only_policy = FALSE;
rcpt_smtp_response = NULL;
fl.rcpt_smtp_response_same = TRUE;
fl.rcpt_in_progress = FALSE;
-f.deliver_freeze = FALSE; /* Can be set by ACL */
-freeze_tell = freeze_tell_config; /* Can be set by ACL */
-fake_response = OK; /* Can be set by ACL */
+f.deliver_freeze = FALSE; /* Can be set by ACL */
+freeze_tell = freeze_tell_config; /* Can be set by ACL */
+fake_response = OK; /* Can be set by ACL */
#ifdef WITH_CONTENT_SCAN
-f.no_mbox_unspool = FALSE; /* Can be set by ACL */
+f.no_mbox_unspool = FALSE; /* Can be set by ACL */
#endif
-f.submission_mode = FALSE; /* Can be set by ACL */
+f.submission_mode = FALSE; /* Can be set by ACL */
f.suppress_local_fixups = f.suppress_local_fixups_default; /* Can be set by ACL */
-f.active_local_from_check = local_from_check; /* Can be set by ACL */
-f.active_local_sender_retain = local_sender_retain; /* Can be set by ACL */
+f.active_local_from_check = local_from_check; /* Can be set by ACL */
+f.active_local_sender_retain = local_sender_retain; /* Can be set by ACL */
sending_ip_address = NULL;
return_path = sender_address = NULL;
deliver_localpart_data = deliver_domain_data =
recipient_data = sender_data = NULL; /* Can be set by ACL */
+recipient_verify_failure = NULL;
deliver_localpart_parent = deliver_localpart_orig = NULL;
deliver_domain_parent = deliver_domain_orig = NULL;
callout_address = NULL;
-submission_name = NULL; /* Can be set by ACL */
+submission_name = NULL; /* Can be set by ACL */
raw_sender = NULL; /* After SMTP rewrite, before qualifying */
sender_address_unrewritten = NULL; /* Set only after verify rewrite */
sender_verified_list = NULL; /* No senders verified */
acl_var_m = NULL;
-/* The message body variables use malloc store. They may be set if this is
-not the first message in an SMTP session and the previous message caused them
-to be referenced in an ACL. */
-
-if (message_body)
- {
- store_free(message_body);
- message_body = NULL;
- }
-
-if (message_body_end)
- {
- store_free(message_body_end);
- message_body_end = NULL;
- }
-
-/* Warning log messages are also saved in malloc store. They are saved to avoid
+/* Warning log messages are saved in malloc store. They are saved to avoid
repetition in the same message, but it seems right to repeat them for different
messages. */
break;
- case EOF_CMD:
case QUIT_CMD:
+ f.smtp_in_quit = TRUE;
+ case EOF_CMD:
done = 2;
break;
int yield = -1;
log_write(type, LOG_MAIN, "SMTP %s error in \"%s\" %s %s",
- (type == L_smtp_syntax_error)? "syntax" : "protocol",
+ type == L_smtp_syntax_error ? "syntax" : "protocol",
string_printing(smtp_cmd_buffer), host_and_ident(TRUE), errmess);
if (++synprot_error_count > smtp_max_synprot_errors)
{
yield = 1;
log_write(0, LOG_MAIN|LOG_REJECT, "SMTP call from %s dropped: too many "
- "syntax or protocol errors (last command was \"%s\")",
- host_and_ident(FALSE), string_printing(smtp_cmd_buffer));
+ "syntax or protocol errors (last command was \"%s\", %s)",
+ host_and_ident(FALSE), string_printing(smtp_cmd_buffer),
+ string_from_gstring(s_connhad_log(NULL))
+ );
}
if (code > 0)
smtp_quit_handler(uschar ** user_msgp, uschar ** log_msgp)
{
HAD(SCH_QUIT);
+f.smtp_in_quit = TRUE;
incomplete_transaction_log(US"QUIT");
-if (acl_smtp_quit)
- {
- int rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, user_msgp, log_msgp);
- if (rc == ERROR)
+if ( acl_smtp_quit
+ && acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, user_msgp, log_msgp)
+ == ERROR)
log_write(0, LOG_MAIN|LOG_PANIC, "ACL for QUIT returned ERROR: %s",
*log_msgp);
- }
#ifdef TCP_CORK
(void) setsockopt(fileno(smtp_out), IPPROTO_TCP, TCP_CORK, US &on, sizeof(on));
if (++synprot_error_count > smtp_max_synprot_errors)
{
log_write(0, LOG_MAIN|LOG_REJECT, "SMTP call from %s dropped: too many "
- "syntax or protocol errors (last command was \"%s\")",
- host_and_ident(FALSE), string_printing(smtp_cmd_buffer));
+ "syntax or protocol errors (last command was \"%s\", %s)",
+ host_and_ident(FALSE), string_printing(smtp_cmd_buffer),
+ string_from_gstring(s_connhad_log(NULL))
+ );
done = 1;
}
# endif
else
#endif
+ (void) fwrite(g->s, 1, g->ptr, smtp_out);
- {
- int i = fwrite(g->s, 1, g->ptr, smtp_out); i = i; /* compiler quietening */
- }
DEBUG(D_receive)
{
uschar *cr;
}
if (f.smtp_in_pipelining_advertised && last_was_rcpt)
smtp_printf("503 Valid RCPT command must precede %s\r\n", FALSE,
- smtp_names[smtp_connection_had[smtp_ch_index-1]]);
+ smtp_names[smtp_connection_had[SMTP_HBUFF_PREV(smtp_ch_index)]]);
else
done = synprot_error(L_smtp_protocol_error, 503, NULL,
- smtp_connection_had[smtp_ch_index-1] == SCH_DATA
+ smtp_connection_had[SMTP_HBUFF_PREV(smtp_ch_index)] == SCH_DATA
? US"valid RCPT command must precede DATA"
: US"valid RCPT command must precede BDAT");
some sense is perhaps "right". */
case QUIT_CMD:
+ f.smtp_in_quit = TRUE;
user_msg = NULL;
if ( acl_smtp_quit
&& ((rc = acl_check(ACL_WHERE_QUIT, NULL, acl_smtp_quit, &user_msg,