X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/184e88237dea64ce48076cdd0184612d057cbafd..ca86f471bf30f4630e96e24f6c13de269f380f41:/src/src/smtp_in.c diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 7e80c6209..c9c5842b1 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/smtp_in.c,v 1.49 2007/01/08 10:50:18 ph10 Exp $ */ +/* $Cambridge: exim/src/src/smtp_in.c,v 1.54 2007/02/20 11:37:16 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -96,6 +96,13 @@ enum { TOO_MANY_NONMAIL_CMD }; +/* This is a convenience macro for adding the identity of an SMTP command +to the circular buffer that holds a list of the last n received. */ + +#define HAD(n) \ + smtp_connection_had[smtp_ch_index++] = n; \ + if (smtp_ch_index >= SMTP_HBUFF_SIZE) smtp_ch_index = 0 + /************************************************* * Local static variables * @@ -119,6 +126,9 @@ static int unknown_command_count; static int sync_cmd_limit; static int smtp_write_error = 0; +static uschar *smtp_data_buffer; +static uschar *smtp_cmd_data; + /* We need to know the position of RSET, HELO, EHLO, AUTH, and STARTTLS. Their final fields of all except AUTH are forced TRUE at the start of a new message setup, to allow one of each between messages that is not counted as a nonmail @@ -165,6 +175,15 @@ static smtp_cmd_list *cmd_list_end = #define CMD_LIST_AUTH 3 #define CMD_LIST_STARTTLS 4 +/* 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[] = + { + US"NONE", US"AUTH", US"DATA", US"EHLO", US"ETRN", US"EXPN", US"HELO", + US"HELP", US"MAIL", US"NOOP", US"QUIT", US"RCPT", US"RSET", US"STARTTLS", + US"VRFY" }; + static uschar *protocols[] = { US"local-smtp", /* HELO */ US"local-smtps", /* The rare case EHLO->STARTTLS->HELO */ @@ -536,11 +555,16 @@ for (p = cmd_list; p < cmd_list_end; p++) !sender_host_notsocket) /* Really is a socket */ return BADSYN_CMD; - /* Point after the command, but don't skip over leading spaces till after - the following test, so that if it fails, the command name can easily be - logged. */ + /* The variables $smtp_command and $smtp_command_argument point into the + unmodified input buffer. A copy of the latter is taken for actual + processing, so that it can be chopped up into separate parts if necessary, + for example, when processing a MAIL command options such as SIZE that can + follow the sender address. */ smtp_cmd_argument = smtp_cmd_buffer + p->len; + while (isspace(*smtp_cmd_argument)) smtp_cmd_argument++; + Ustrcpy(smtp_data_buffer, smtp_cmd_argument); + smtp_cmd_data = smtp_data_buffer; /* Count non-mail commands from those hosts that are controlled in this way. The default is all hosts. We don't waste effort checking the list @@ -558,11 +582,10 @@ for (p = cmd_list; p < cmd_list_end; p++) return TOO_MANY_NONMAIL_CMD; } - /* Get the data pointer over leading spaces and return; if there is data - for a command that does not expect it, give the error centrally here. */ + /* If there is data for a command that does not expect it, generate the + error here. */ - while (isspace(*smtp_cmd_argument)) smtp_cmd_argument++; - return (p->has_arg || *smtp_cmd_argument == 0)? p->cmd : BADARG_CMD; + return (p->has_arg || *smtp_cmd_data == 0)? p->cmd : BADARG_CMD; } } @@ -666,6 +689,74 @@ return string_sprintf("SMTP connection from %s", hostname); +/************************************************* +* Log lack of MAIL if so configured * +*************************************************/ + +/* This function is called when an SMTP session ends. If the log selector +smtp_no_mail is set, write a log line giving some details of what has happened +in the SMTP session. + +Arguments: none +Returns: nothing +*/ + +void +smtp_log_no_mail(void) +{ +int size, ptr, i; +uschar *s, *sep; + +if (smtp_mailcmd_count > 0 || (log_extra_selector & LX_smtp_no_mail) == 0) + return; + +s = NULL; +size = ptr = 0; + +if (sender_host_authenticated != NULL) + { + s = string_append(s, &size, &ptr, 2, US" A=", sender_host_authenticated); + if (authenticated_id != NULL) + s = string_append(s, &size, &ptr, 2, US":", authenticated_id); + } + +#ifdef SUPPORT_TLS +if ((log_extra_selector & LX_tls_cipher) != 0 && tls_cipher != NULL) + s = string_append(s, &size, &ptr, 2, US" X=", tls_cipher); +if ((log_extra_selector & LX_tls_certificate_verified) != 0 && + tls_cipher != NULL) + s = string_append(s, &size, &ptr, 2, US" CV=", + tls_certificate_verified? "yes":"no"); +if ((log_extra_selector & LX_tls_peerdn) != 0 && tls_peerdn != NULL) + s = string_append(s, &size, &ptr, 3, US" DN=\"", tls_peerdn, US"\""); +#endif + +sep = (smtp_connection_had[SMTP_HBUFF_SIZE-1] != SCH_NONE)? + US" C=..." : US" C="; +for (i = smtp_ch_index; i < SMTP_HBUFF_SIZE; i++) + { + if (smtp_connection_had[i] != SCH_NONE) + { + s = string_append(s, &size, &ptr, 2, sep, + smtp_names[smtp_connection_had[i]]); + sep = US","; + } + } + +for (i = 0; i < smtp_ch_index; i++) + { + s = string_append(s, &size, &ptr, 2, sep, smtp_names[smtp_connection_had[i]]); + sep = US","; + } + +if (s != NULL) s[ptr] = 0; else s = US""; +log_write(0, LOG_MAIN, "no MAIL in SMTP connection from %s D=%s%s", + host_and_ident(FALSE), + readconf_printtime(time(NULL) - smtp_connection_start), s); +} + + + /************************************************* * Check HELO line and set sender_helo_name * *************************************************/ @@ -755,7 +846,7 @@ return yield; * Extract SMTP command option * *************************************************/ -/* This function picks the next option setting off the end of smtp_cmd_argument. It +/* This function picks the next option setting off the end of smtp_cmd_data. It is called for MAIL FROM and RCPT TO commands, to pick off the optional ESMTP things that can appear there. @@ -770,11 +861,11 @@ static BOOL extract_option(uschar **name, uschar **value) { uschar *n; -uschar *v = smtp_cmd_argument + Ustrlen(smtp_cmd_argument) -1; +uschar *v = smtp_cmd_data + Ustrlen(smtp_cmd_data) - 1; while (isspace(*v)) v--; v[1] = 0; -while (v > smtp_cmd_argument && *v != '=' && !isspace(*v)) v--; +while (v > smtp_cmd_data && *v != '=' && !isspace(*v)) v--; if (*v != '=') return FALSE; n = v; @@ -938,7 +1029,7 @@ while (done <= 0) case HELO_CMD: case EHLO_CMD: - check_helo(smtp_cmd_argument); + check_helo(smtp_cmd_data); /* Fall through */ case RSET_CMD: @@ -958,7 +1049,7 @@ while (done <= 0) /* The function moan_smtp_batch() does not return. */ moan_smtp_batch(smtp_cmd_buffer, "503 Sender already given"); - if (smtp_cmd_argument[0] == 0) + if (smtp_cmd_data[0] == 0) /* The function moan_smtp_batch() does not return. */ moan_smtp_batch(smtp_cmd_buffer, "501 MAIL FROM must have an address operand"); @@ -969,8 +1060,8 @@ while (done <= 0) /* Apply SMTP rewrite */ raw_sender = ((rewrite_existflags & rewrite_smtp) != 0)? - rewrite_one(smtp_cmd_argument, rewrite_smtp|rewrite_smtp_sender, NULL, FALSE, - US"", global_rewrite_rules) : smtp_cmd_argument; + rewrite_one(smtp_cmd_data, rewrite_smtp|rewrite_smtp_sender, NULL, FALSE, + US"", global_rewrite_rules) : smtp_cmd_data; /* Extract the address; the TRUE flag allows <> as valid */ @@ -1013,7 +1104,7 @@ while (done <= 0) /* The function moan_smtp_batch() does not return. */ moan_smtp_batch(smtp_cmd_buffer, "503 No sender yet given"); - if (smtp_cmd_argument[0] == 0) + if (smtp_cmd_data[0] == 0) /* The function moan_smtp_batch() does not return. */ moan_smtp_batch(smtp_cmd_buffer, "501 RCPT TO must have an address operand"); @@ -1028,8 +1119,8 @@ while (done <= 0) recipient address */ recipient = ((rewrite_existflags & rewrite_smtp) != 0)? - rewrite_one(smtp_cmd_argument, rewrite_smtp, NULL, FALSE, US"", - global_rewrite_rules) : smtp_cmd_argument; + rewrite_one(smtp_cmd_data, rewrite_smtp, NULL, FALSE, US"", + global_rewrite_rules) : smtp_cmd_data; /* rfc821_domains = TRUE; << no longer needed */ recipient = parse_extract_address(recipient, &errmess, &start, &end, @@ -1146,14 +1237,21 @@ uschar *user_msg, *log_msg; uschar *code, *esc; uschar *p, *s, *ss; +smtp_connection_start = time(NULL); +for (smtp_ch_index = 0; smtp_ch_index < SMTP_HBUFF_SIZE; smtp_ch_index++) + smtp_connection_had[smtp_ch_index] = SCH_NONE; +smtp_ch_index = 0; + /* Default values for certain variables */ helo_seen = esmtp = helo_accept_junk = FALSE; +smtp_mailcmd_count = 0; count_nonmail = TRUE_UNSET; synprot_error_count = unknown_command_count = nonmail_command_count = 0; smtp_delay_mail = smtp_rlm_base; auth_advertised = FALSE; pipelining_advertised = FALSE; +pipelining_enable = TRUE; sync_cmd_limit = NON_SYNC_CMD_NON_PIPELINING; memset(sender_host_cache, 0, sizeof(sender_host_cache)); @@ -1173,12 +1271,13 @@ tls_advertised = FALSE; acl_var_c = NULL; -/* Allow for trailing 0 in the command buffer. */ +/* Allow for trailing 0 in the command and data buffers. */ -smtp_cmd_buffer = (uschar *)malloc(smtp_cmd_buffer_size + 1); +smtp_cmd_buffer = (uschar *)malloc(2*smtp_cmd_buffer_size + 2); if (smtp_cmd_buffer == NULL) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "malloc() failed for SMTP command buffer"); +smtp_data_buffer = smtp_cmd_buffer + smtp_cmd_buffer_size + 1; /* For batched input, the protocol setting can be overridden from the command line by a trusted caller. */ @@ -1450,7 +1549,9 @@ if (!sender_host_unknown) smtps port for use with older style SSL MTAs. */ #ifdef SUPPORT_TLS - if (tls_on_connect && tls_server_start(tls_require_ciphers) != OK) + if (tls_on_connect && + tls_server_start(tls_require_ciphers, + gnutls_require_mac, gnutls_require_kx, gnutls_require_proto) != OK) return FALSE; #endif @@ -1502,18 +1603,18 @@ if (!sender_host_unknown) } #endif - /* Check for reserved slots. Note that the count value doesn't include - this process, as it gets upped in the parent process. */ + /* Check for reserved slots. The value of smtp_accept_count has already been + incremented to include this process. */ if (smtp_accept_max > 0 && - smtp_accept_count + 1 > smtp_accept_max - smtp_accept_reserve) + smtp_accept_count > smtp_accept_max - smtp_accept_reserve) { if ((rc = verify_check_host(&smtp_reserve_hosts)) != OK) { log_write(L_connection_reject, LOG_MAIN, "temporarily refused connection from %s: not in " "reserve list: connected=%d max=%d reserve=%d%s", - host_and_ident(FALSE), smtp_accept_count, smtp_accept_max, + host_and_ident(FALSE), smtp_accept_count - 1, smtp_accept_max, smtp_accept_reserve, (rc == DEFER)? " (lookup deferred)" : ""); smtp_printf("421 %s: Too many concurrent SMTP connections; " "please try again later\r\n", smtp_active_hostname); @@ -1948,9 +2049,9 @@ uschar *what = #endif (where == ACL_WHERE_PREDATA)? US"DATA" : (where == ACL_WHERE_DATA)? US"after DATA" : - (smtp_cmd_argument == NULL)? + (smtp_cmd_data == NULL)? string_sprintf("%s in \"connect\" ACL", acl_wherenames[where]) : - string_sprintf("%s %s", acl_wherenames[where], smtp_cmd_argument); + string_sprintf("%s %s", acl_wherenames[where], smtp_cmd_data); if (drop) rc = FAIL; @@ -2335,6 +2436,7 @@ while (done <= 0) AUTHS will eventually hit the nonmail threshold. */ case AUTH_CMD: + HAD(SCH_AUTH); authentication_failed = TRUE; cmd_list[CMD_LIST_AUTH].is_mail_cmd = FALSE; @@ -2371,8 +2473,8 @@ while (done <= 0) /* Find the name of the requested authentication mechanism. */ - s = smtp_cmd_argument; - while ((c = *smtp_cmd_argument) != 0 && !isspace(c)) + s = smtp_cmd_data; + while ((c = *smtp_cmd_data) != 0 && !isspace(c)) { if (!isalnum(c) && c != '-' && c != '_') { @@ -2380,16 +2482,16 @@ while (done <= 0) US"invalid character in authentication mechanism name"); goto COMMAND_LOOP; } - smtp_cmd_argument++; + smtp_cmd_data++; } /* If not at the end of the line, we must be at white space. Terminate the name and move the pointer on to any data that may be present. */ - if (*smtp_cmd_argument != 0) + if (*smtp_cmd_data != 0) { - *smtp_cmd_argument++ = 0; - while (isspace(*smtp_cmd_argument)) smtp_cmd_argument++; + *smtp_cmd_data++ = 0; + while (isspace(*smtp_cmd_data)) smtp_cmd_data++; } /* Search for an authentication mechanism which is configured for use @@ -2425,7 +2527,7 @@ while (done <= 0) expand_nmax = 0; expand_nlength[0] = 0; /* $0 contains nothing */ - c = (au->info->servercode)(au, smtp_cmd_argument); + c = (au->info->servercode)(au, smtp_cmd_data); if (au->set_id != NULL) set_id = expand_string(au->set_id); expand_nmax = -1; /* Reset numeric variables */ for (i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL; /* Reset $auth */ @@ -2527,11 +2629,13 @@ while (done <= 0) it did the reset first. */ case HELO_CMD: + HAD(SCH_HELO); hello = US"HELO"; esmtp = FALSE; goto HELO_EHLO; case EHLO_CMD: + HAD(SCH_EHLO); hello = US"EHLO"; esmtp = TRUE; @@ -2542,7 +2646,7 @@ while (done <= 0) /* Reject the HELO if its argument was invalid or non-existent. A successful check causes the argument to be saved in malloc store. */ - if (!check_helo(smtp_cmd_argument)) + if (!check_helo(smtp_cmd_data)) { smtp_printf("501 Syntactically invalid %s argument(s)\r\n", hello); @@ -2572,7 +2676,7 @@ while (done <= 0) if (!sender_host_unknown) { BOOL old_helo_verified = helo_verified; - uschar *p = smtp_cmd_argument; + uschar *p = smtp_cmd_data; while (*p != 0 && !isspace(*p)) { *p = tolower(*p); p++; } *p = 0; @@ -2756,7 +2860,8 @@ while (done <= 0) /* Exim is quite happy with pipelining, so let the other end know that it is safe to use it, unless advertising is disabled. */ - if (verify_check_host(&pipelining_advertise_hosts) == OK) + if (pipelining_enable && + verify_check_host(&pipelining_advertise_hosts) == OK) { s = string_cat(s, &size, &ptr, smtp_code, 3); s = string_cat(s, &size, &ptr, US"-PIPELINING\r\n", 13); @@ -2870,6 +2975,7 @@ while (done <= 0) it is the canonical extracted address which is all that is kept. */ case MAIL_CMD: + HAD(SCH_MAIL); smtp_mailcmd_count++; /* Count for limit and ratelimit */ was_rej_mail = TRUE; /* Reset if accepted */ @@ -2888,7 +2994,7 @@ while (done <= 0) break; } - if (smtp_cmd_argument[0] == 0) + if (smtp_cmd_data[0] == 0) { done = synprot_error(L_smtp_protocol_error, 501, NULL, US"MAIL must have an address operand"); @@ -3047,8 +3153,8 @@ while (done <= 0) TRUE flag allows "<>" as a sender address. */ raw_sender = ((rewrite_existflags & rewrite_smtp) != 0)? - rewrite_one(smtp_cmd_argument, rewrite_smtp, NULL, FALSE, US"", - global_rewrite_rules) : smtp_cmd_argument; + rewrite_one(smtp_cmd_data, rewrite_smtp, NULL, FALSE, US"", + global_rewrite_rules) : smtp_cmd_data; /* rfc821_domains = TRUE; << no longer needed */ raw_sender = @@ -3058,7 +3164,7 @@ while (done <= 0) if (raw_sender == NULL) { - done = synprot_error(L_smtp_syntax_error, 501, smtp_cmd_argument, errmess); + done = synprot_error(L_smtp_syntax_error, 501, smtp_cmd_data, errmess); break; } @@ -3118,7 +3224,7 @@ while (done <= 0) else { smtp_printf("501 %s: sender address must contain a domain\r\n", - smtp_cmd_argument); + smtp_cmd_data); log_write(L_smtp_syntax_error, LOG_MAIN|LOG_REJECT, "unqualified sender rejected: <%s> %s%s", @@ -3159,6 +3265,7 @@ while (done <= 0) extracted address. */ case RCPT_CMD: + HAD(SCH_RCPT); rcpt_count++; was_rcpt = TRUE; @@ -3186,7 +3293,7 @@ while (done <= 0) /* Check for an operand */ - if (smtp_cmd_argument[0] == 0) + if (smtp_cmd_data[0] == 0) { done = synprot_error(L_smtp_syntax_error, 501, NULL, US"RCPT must have an address operand"); @@ -3198,8 +3305,8 @@ while (done <= 0) as a recipient address */ recipient = ((rewrite_existflags & rewrite_smtp) != 0)? - rewrite_one(smtp_cmd_argument, rewrite_smtp, NULL, FALSE, US"", - global_rewrite_rules) : smtp_cmd_argument; + rewrite_one(smtp_cmd_data, rewrite_smtp, NULL, FALSE, US"", + global_rewrite_rules) : smtp_cmd_data; /* rfc821_domains = TRUE; << no longer needed */ recipient = parse_extract_address(recipient, &errmess, &start, &end, @@ -3208,7 +3315,7 @@ while (done <= 0) if (recipient == NULL) { - done = synprot_error(L_smtp_syntax_error, 501, smtp_cmd_argument, errmess); + done = synprot_error(L_smtp_syntax_error, 501, smtp_cmd_data, errmess); rcpt_fail_count++; break; } @@ -3238,7 +3345,7 @@ while (done <= 0) { rcpt_fail_count++; smtp_printf("501 %s: recipient address must contain a domain\r\n", - smtp_cmd_argument); + smtp_cmd_data); log_write(L_smtp_syntax_error, LOG_MAIN|LOG_REJECT, "unqualified recipient rejected: " "<%s> %s%s", recipient, host_and_ident(TRUE), @@ -3346,6 +3453,7 @@ while (done <= 0) because it is the same whether pipelining is in use or not. */ case DATA_CMD: + HAD(SCH_DATA); if (!discarded && recipients_count <= 0) { if (pipelining_advertised && last_was_rcpt) @@ -3390,6 +3498,7 @@ while (done <= 0) case VRFY_CMD: + HAD(SCH_VRFY); rc = acl_check(ACL_WHERE_VRFY, NULL, acl_smtp_vrfy, &user_msg, &log_msg); if (rc != OK) done = smtp_handle_acl_fail(ACL_WHERE_VRFY, rc, user_msg, log_msg); @@ -3399,7 +3508,7 @@ while (done <= 0) uschar *s = NULL; /* rfc821_domains = TRUE; << no longer needed */ - address = parse_extract_address(smtp_cmd_argument, &errmess, &start, &end, + address = parse_extract_address(smtp_cmd_data, &errmess, &start, &end, &recipient_domain, FALSE); /* rfc821_domains = FALSE; << no longer needed */ @@ -3437,6 +3546,7 @@ while (done <= 0) case EXPN_CMD: + HAD(SCH_EXPN); rc = acl_check(ACL_WHERE_EXPN, NULL, acl_smtp_expn, &user_msg, &log_msg); if (rc != OK) done = smtp_handle_acl_fail(ACL_WHERE_EXPN, rc, user_msg, log_msg); @@ -3444,7 +3554,7 @@ while (done <= 0) { BOOL save_log_testing_mode = log_testing_mode; address_test_mode = log_testing_mode = TRUE; - (void) verify_address(deliver_make_addr(smtp_cmd_argument, FALSE), + (void) verify_address(deliver_make_addr(smtp_cmd_data, FALSE), smtp_out, vopt_is_recipient | vopt_qualify | vopt_expn, -1, -1, -1, NULL, NULL, NULL); address_test_mode = FALSE; @@ -3456,6 +3566,7 @@ while (done <= 0) #ifdef SUPPORT_TLS case STARTTLS_CMD: + HAD(SCH_STARTTLS); if (!tls_advertised) { done = synprot_error(L_smtp_protocol_error, 503, NULL, @@ -3494,7 +3605,8 @@ while (done <= 0) We must allow for an extra EHLO command and an extra AUTH command after STARTTLS that don't add to the nonmail command count. */ - if ((rc = tls_server_start(tls_require_ciphers)) == OK) + if ((rc = tls_server_start(tls_require_ciphers, gnutls_require_mac, + gnutls_require_kx, gnutls_require_proto)) == OK) { if (!tls_remember_esmtp) helo_seen = esmtp = auth_advertised = pipelining_advertised = FALSE; @@ -3569,6 +3681,7 @@ while (done <= 0) message. */ case QUIT_CMD: + HAD(SCH_QUIT); incomplete_transaction_log(US"QUIT"); if (acl_smtp_quit != NULL) @@ -3595,6 +3708,7 @@ while (done <= 0) case RSET_CMD: + HAD(SCH_RSET); incomplete_transaction_log(US"RSET"); smtp_reset(reset_point); toomany = FALSE; @@ -3604,6 +3718,7 @@ while (done <= 0) case NOOP_CMD: + HAD(SCH_NOOP); smtp_printf("250 OK\r\n"); break; @@ -3613,6 +3728,7 @@ while (done <= 0) permitted hosts. */ case HELP_CMD: + HAD(SCH_HELP); smtp_printf("214-Commands supported:\r\n"); { uschar buffer[256]; @@ -3654,6 +3770,7 @@ while (done <= 0) case ETRN_CMD: + HAD(SCH_ETRN); if (sender_address != NULL) { done = synprot_error(L_smtp_protocol_error, 503, NULL, @@ -3673,7 +3790,7 @@ while (done <= 0) /* Compute the serialization key for this command. */ - etrn_serialize_key = string_sprintf("etrn-%s\n", smtp_cmd_argument); + etrn_serialize_key = string_sprintf("etrn-%s\n", smtp_cmd_data); /* If a command has been specified for running as a result of ETRN, we permit any argument to ETRN. If not, only the # standard form is permitted, @@ -3685,7 +3802,7 @@ while (done <= 0) uschar *error; BOOL rc; etrn_command = smtp_etrn_command; - deliver_domain = smtp_cmd_argument; + deliver_domain = smtp_cmd_data; rc = transport_set_up_command(&argv, smtp_etrn_command, TRUE, 0, NULL, US"ETRN processing", &error); deliver_domain = NULL; @@ -3702,7 +3819,7 @@ while (done <= 0) else { - if (*smtp_cmd_argument++ != '#') + if (*smtp_cmd_data++ != '#') { done = synprot_error(L_smtp_syntax_error, 501, NULL, US"argument must begin with #"); @@ -3710,7 +3827,7 @@ while (done <= 0) } etrn_command = US"exim -R"; argv = child_exec_exim(CEE_RETURN_ARGV, TRUE, NULL, TRUE, 2, US"-R", - smtp_cmd_argument); + smtp_cmd_data); } /* If we are host-testing, don't actually do anything. */ @@ -3733,7 +3850,7 @@ while (done <= 0) if (smtp_etrn_serialize && !enq_start(etrn_serialize_key)) { - smtp_printf("458 Already processing %s\r\n", smtp_cmd_argument); + smtp_printf("458 Already processing %s\r\n", smtp_cmd_data); break; } @@ -3843,10 +3960,12 @@ while (done <= 0) case TOO_MANY_NONMAIL_CMD: + s = smtp_cmd_buffer; + while (*s != 0 && !isspace(*s)) s++; incomplete_transaction_log(US"too many non-mail commands"); log_write(0, LOG_MAIN|LOG_REJECT, "SMTP call from %s dropped: too many " "nonmail commands (last was \"%.*s\")", host_and_ident(FALSE), - smtp_cmd_argument - smtp_cmd_buffer, smtp_cmd_buffer); + s - smtp_cmd_buffer, smtp_cmd_buffer); smtp_printf("554 Too many nonmail commands\r\n"); done = 1; /* Pretend eof - drops connection */ break;