/------------------------ SNIP ----------------------/ The following patch can be applied to the current postfix vanilla. It was made to work on 2.1.5 but it may work on newer versions too. After applying the patch, you will be able to modify all the error messages postfix will issue in various cases. These are the following: var_smtpd_ok var_smtpd_bye var_error_unkn_command var_error_no_hello var_error_nested_mail var_error_no_mail var_error_too_many_recipients var_error_need_rcpt var_error_msg_too_large var_error_bad_recipients var_error_too_many_hops var_error_queue_file var_error_mail_transaction var_error_parameter_syntax var_error_auth var_error_attrib_value var_error_attr_too_long var_error_bad_syntax var_error_bad_command For example to change the response postfix issues to clients when closing transmission (used to be "Bye!"), you could enter in main.cf: var_smtpd_bye="Hakuna Matatta!" The rest are pretty self explanatory and they can be looked up. Comments and insults to: SevenRains - /-----------------------SNIP----------------------/ --- postfix-2.1.5.old/src/smtpd/smtpd.c 2004-08-14 01:28:41.000000000 +0300 +++ postfix-2.1.5/src/smtpd/smtpd.c 2005-03-26 17:23:49.000000000 +0200 @@ -681,6 +681,28 @@ int var_smtpd_hard_erlim; int var_queue_minfree; /* XXX use off_t */ char *var_smtpd_banner; + +char *var_smtpd_ok; +char *var_smtpd_bye; + +char *var_error_unkn_command; +char *var_error_no_hello; +char *var_error_nested_mail; +char *var_error_no_mail; +char *var_error_too_many_recipients; +char *var_error_need_rcpt; +char *var_error_msg_too_large; +char *var_error_bad_recipients; +char *var_error_too_many_hops; +char *var_error_queue_file; +char *var_error_mail_transaction; +char *var_error_parameter_syntax; +char *var_error_auth; +char *var_error_attrib_value; +char *var_error_attr_too_long; +char *var_error_bad_syntax; +char *var_error_bad_command; + char *var_notify_classes; char *var_client_checks; char *var_helo_checks; @@ -1201,14 +1223,14 @@ */ if (var_helo_required && state->helo_name == 0) { state->error_mask |= MAIL_ERROR_POLICY; - smtpd_chat_reply(state, "503 Error: send HELO/EHLO first"); + smtpd_chat_reply(state, "503 %s", var_error_no_hello); return (-1); } #define IN_MAIL_TRANSACTION(state) ((state)->sender != 0) if (IN_MAIL_TRANSACTION(state)) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "503 Error: nested MAIL command"); + smtpd_chat_reply(state, "503 %s", var_error_nested_mail); return (-1); } if (argc < 3 @@ -1308,7 +1330,7 @@ state->verp_delims = mystrdup(verp_delims); if (USE_SMTPD_PROXY(state)) state->proxy_mail = mystrdup(STR(state->buffer)); - smtpd_chat_reply(state, "250 Ok"); + smtpd_chat_reply(state, "250: %s", var_smtpd_ok); return (0); } @@ -1395,7 +1417,7 @@ */ if (!IN_MAIL_TRANSACTION(state)) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "503 Error: need MAIL command"); + smtpd_chat_reply(state, "503 %s", var_error_no_mail); return (-1); } if (argc < 3 @@ -1423,7 +1445,7 @@ } } if (var_smtpd_rcpt_limit && state->rcpt_count >= var_smtpd_rcpt_limit) { - smtpd_chat_reply(state, "452 Error: too many recipients"); + smtpd_chat_reply(state, "452 %s", var_error_too_many_recipients); if (state->rcpt_overshoot++ < var_smtpd_rcpt_overlim) return (0); state->error_mask |= MAIL_ERROR_POLICY; @@ -1488,7 +1510,7 @@ rec_fputs(state->cleanup, REC_TYPE_RCPT, argv[2].strval); vstream_fflush(state->cleanup); } - smtpd_chat_reply(state, "250 Ok"); + smtpd_chat_reply(state, "250: %s", var_smtpd_ok); return (0); } @@ -1531,9 +1553,9 @@ if (state->rcpt_count == 0) { if (!IN_MAIL_TRANSACTION(state)) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "503 Error: need RCPT command"); + smtpd_chat_reply(state, "503 %s", var_error_need_rcpt); } else { - smtpd_chat_reply(state, "554 Error: no valid recipients"); + smtpd_chat_reply(state, "554 %s", var_error_bad_recipients); } return (-1); } @@ -1685,7 +1707,7 @@ state->error_mask |= MAIL_ERROR_SOFTWARE; state->err |= CLEANUP_STAT_PROXY; vstring_sprintf(state->proxy_buffer, - "451 Error: queue file write error"); + "451 %s", var_error_queue_file); } } @@ -1720,7 +1742,7 @@ state->error_mask = 0; state->junk_cmds = 0; if (state->queue_id) - smtpd_chat_reply(state, "250 Ok: queued as %s", state->queue_id); + smtpd_chat_reply(state, "250 %s: queued as %s", var_smtpd_ok, state->queue_id); else smtpd_chat_reply(state, "%s", STR(state->proxy_buffer)); } else if ((state->err & CLEANUP_STAT_BAD) != 0) { @@ -1728,10 +1750,10 @@ smtpd_chat_reply(state, "451 Error: internal error %d", state->err); } else if ((state->err & CLEANUP_STAT_SIZE) != 0) { state->error_mask |= MAIL_ERROR_BOUNCE; - smtpd_chat_reply(state, "552 Error: message too large"); + smtpd_chat_reply(state, "552 %s", var_error_msg_too_large); } else if ((state->err & CLEANUP_STAT_HOPS) != 0) { state->error_mask |= MAIL_ERROR_BOUNCE; - smtpd_chat_reply(state, "554 Error: too many hops"); + smtpd_chat_reply(state, "554 %s", var_error_too_many_hops); } else if ((state->err & CLEANUP_STAT_CONT) != 0) { state->error_mask |= MAIL_ERROR_POLICY; if (state->proxy_buffer) @@ -1741,7 +1763,7 @@ STR(why) : "content rejected"); } else if ((state->err & CLEANUP_STAT_WRITE) != 0) { state->error_mask |= MAIL_ERROR_RESOURCE; - smtpd_chat_reply(state, "451 Error: queue file write error"); + smtpd_chat_reply(state, "451 %s", var_error_queue_file); } else if ((state->err & CLEANUP_STAT_PROXY) != 0) { state->error_mask |= MAIL_ERROR_SOFTWARE; smtpd_chat_reply(state, "%s", STR(state->proxy_buffer)); @@ -1788,7 +1810,7 @@ chat_reset(state, var_smtpd_hist_thrsh); mail_reset(state); rcpt_reset(state); - smtpd_chat_reply(state, "250 Ok"); + smtpd_chat_reply(state, "250: %s", var_smtpd_ok); return (0); } @@ -1815,7 +1837,7 @@ return (-1); } #endif - smtpd_chat_reply(state, "250 Ok"); + smtpd_chat_reply(state, "250: %s", var_smtpd_ok); return (0); } @@ -1896,12 +1918,12 @@ */ if (var_helo_required && state->helo_name == 0) { state->error_mask |= MAIL_ERROR_POLICY; - smtpd_chat_reply(state, "503 Error: send HELO/EHLO first"); + smtpd_chat_reply(state, "503 %s", var_error_no_hello); return (-1); } if (IN_MAIL_TRANSACTION(state)) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "503 Error: MAIL transaction in progress"); + smtpd_chat_reply(state, "503 %s", var_error_mail_transaction); return (-1); } if (argc != 2) { @@ -1913,7 +1935,7 @@ argv[1].strval++; if (!valid_hostname(argv[1].strval, DONT_GRIPE)) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "501 Error: invalid parameter syntax"); + smtpd_chat_reply(state, "501 %s", var_error_parameter_syntax); return (-1); } @@ -1961,7 +1983,7 @@ /* * Don't bother checking the syntax. */ - smtpd_chat_reply(state, "221 Bye"); + smtpd_chat_reply(state, "221: %s", var_smtpd_bye); /* * When the "." and quit replies are pipelined, make sure they are @@ -1998,7 +2020,7 @@ */ if (IN_MAIL_TRANSACTION(state)) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "503 Error: MAIL transaction in progress"); + smtpd_chat_reply(state, "503 %s", var_error_mail_transaction); return (-1); } if (argc < 2) { @@ -2009,7 +2031,7 @@ } if (!xclient_allowed) { state->error_mask |= MAIL_ERROR_POLICY; - smtpd_chat_reply(state, "554 Error: insufficient authorization"); + smtpd_chat_reply(state, "554 %s", var_error_auth); return (-1); } #define STREQ(x,y) (strcasecmp((x), (y)) == 0) @@ -2030,7 +2052,7 @@ */ if ((attr_value = split_at(attr_name, '=')) == 0 || *attr_value == 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "501 Error: attribute=value expected"); + smtpd_chat_reply(state, "501 %s", var_error_attrib_value); return (-1); } printable(attr_value, '?'); @@ -2127,7 +2149,7 @@ state->namaddr = concatenate(state->name, "[", state->addr, "]", (char *) 0); } - smtpd_chat_reply(state, "250 Ok"); + smtpd_chat_reply(state, "250: %s", var_smtpd_ok); return (0); } @@ -2153,7 +2175,7 @@ */ if (IN_MAIL_TRANSACTION(state)) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "503 Error: MAIL transaction in progress"); + smtpd_chat_reply(state, "503 %s", var_error_mail_transaction); return (-1); } if (argc < 2) { @@ -2164,7 +2186,7 @@ } if (!xforward_allowed) { state->error_mask |= MAIL_ERROR_POLICY; - smtpd_chat_reply(state, "554 Error: insufficient authorization"); + smtpd_chat_reply(state, "554 %s", var_error_auth); return (-1); } @@ -2186,12 +2208,12 @@ */ if ((attr_value = split_at(attr_name, '=')) == 0 || *attr_value == 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "501 Error: attribute=value expected"); + smtpd_chat_reply(state, "501 %s", var_error_attrib_value); return (-1); } if (strlen(attr_value) > 255) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "501 Error: attribute value too long"); + smtpd_chat_reply(state, "501 %s", var_error_attr_too_long); return (-1); } printable(attr_value, '?'); @@ -2285,7 +2307,7 @@ state->xforward.addr, "]", (char *) 0) : mystrdup(state->xforward.name); } - smtpd_chat_reply(state, "250 Ok"); + smtpd_chat_reply(state, "250: %s", var_smtpd_ok); return (0); } @@ -2455,13 +2477,13 @@ smtpd_chat_query(state); if ((argc = smtpd_token(vstring_str(state->buffer), &argv)) == 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "500 Error: bad syntax"); + smtpd_chat_reply(state, "500 %s", var_error_bad_syntax); state->error_count++; continue; } if (*var_smtpd_noop_cmds && string_list_match(smtpd_noop_cmds, argv[0].strval)) { - smtpd_chat_reply(state, "250 Ok"); + smtpd_chat_reply(state, "250: %s", var_smtpd_ok); if (state->junk_cmds++ > var_smtpd_junk_cmd_limit) state->error_count++; continue; @@ -2470,7 +2492,7 @@ if (strcasecmp(argv[0].strval, cmdp->name) == 0) break; if (cmdp->name == 0) { - smtpd_chat_reply(state, "502 Error: command not implemented"); + smtpd_chat_reply(state, "502 %s", var_error_unkn_command); state->error_mask |= MAIL_ERROR_PROTOCOL; state->error_count++; continue; @@ -2478,7 +2500,7 @@ if (cmdp->flags & SMTPD_CMD_FLAG_FORBID) { msg_warn("%s sent non-SMTP command: %.100s", state->namaddr, vstring_str(state->buffer)); - smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye."); + smtpd_chat_reply(state, "221 %s", var_error_bad_command); break; } /* XXX We use the real client for connect access control. */ @@ -2740,6 +2762,28 @@ }; static CONFIG_STR_TABLE str_table[] = { VAR_SMTPD_BANNER, DEF_SMTPD_BANNER, &var_smtpd_banner, 1, 0, + + VAR_SMTPD_BYE, DEF_SMTPD_BYE, &var_smtpd_bye, 1, 0, + VAR_SMTPD_OK, DEF_SMTPD_OK, &var_smtpd_ok, 1, 0, + + VAR_ERROR_UNKN_COMMAND, DEF_ERROR_UNKN_COMMAND, &var_error_unkn_command, 1, 0, + VAR_ERROR_NO_HELLO, DEF_ERROR_NO_HELLO, &var_error_no_hello, 1, 0, + VAR_ERROR_NESTED_MAIL, DEF_ERROR_NESTED_MAIL, &var_error_nested_mail, 1, 0, + VAR_ERROR_NO_MAIL, DEF_ERROR_NO_MAIL, &var_error_no_mail, 1, 0, + VAR_ERROR_TOO_MANY_RECIPIENTS, DEF_ERROR_TOO_MANY_RECIPIENTS, &var_error_too_many_recipients, 1, 0, + VAR_ERROR_NEED_RCPT, DEF_ERROR_NEED_TCPT, &var_error_need_rcpt, 1, 0, + VAR_ERROR_MSG_TOO_LARGE, DEF_ERROR_MSG_TOO_LARGE, &var_error_msg_too_large, 1, 0, + VAR_ERROR_BAD_RECIPIENTS, DEF_ERROR_BAD_RECIPIENTS, &var_error_bad_recipients, 1, 0, + VAR_ERROR_TOO_MANY_HOPS, DEF_ERROR_TOO_MANY_HOPS, &var_error_too_many_hops, 1, 0, + VAR_ERROR_QUEUE_FILE, DEF_ERROR_QUEUE_FILE, &var_error_queue_file, 1, 0, + VAR_ERROR_MAIL_TRANSACTION, DEF_ERROR_MAIL_TRANSACTION, &var_error_mail_transaction, 1, 0, + VAR_ERROR_PARAMETER_SYNTAX, DEF_ERROR_PARAMETER_SYNTAX, &var_error_parameter_syntax, 1, 0, + VAR_ERROR_AUTH, DEF_ERROR_AUTH, &var_error_auth, 1, 0, + VAR_ERROR_ATTRIB_VALUE, DEF_ERROR_ATTRIB_VALUE, &var_error_attrib_value, 1, 0, + VAR_ERROR_ATTR_TOO_LONG, DEF_ERROR_ATTR_TOO_LONG, &var_error_attr_too_long, 1, 0, + VAR_ERROR_BAD_SYNTAX, DEF_ERROR_BAD_SYNTAX, &var_error_bad_syntax, 1, 0, + VAR_ERROR_BAD_COMMAND, DEF_ERROR_BAD_COMMAND, &var_error_bad_command, 1, 0, + VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0, VAR_CLIENT_CHECKS, DEF_CLIENT_CHECKS, &var_client_checks, 0, 0, VAR_HELO_CHECKS, DEF_HELO_CHECKS, &var_helo_checks, 0, 0, --- postfix-2.1.5.old/src/global/mail_params.h 2004-04-21 21:56:04.000000000 +0300 +++ postfix-2.1.5/src/global/mail_params.h 2005-03-26 17:23:52.000000000 +0200 @@ -1271,6 +1271,87 @@ extern bool var_allow_untrust_route; /* + * Custom error messages for smtpd replies + * + */ + +#define VAR_SMTPD_BYE "smtpd_rbye" +#define DEF_SMTPD_BYE "Bye" +extern char *var_smtpd_bye; + +#define VAR_SMTPD_OK "smtpd_rok" +#define DEF_SMTPD_OK "Ok" +extern char *var_smtpd_ok; + +#define VAR_ERROR_UNKN_COMMAND "smtpd_rcom" +#define DEF_ERROR_UNKN_COMMAND "Error: command not implemented" +extern char *var_error_unkn_command; + +#define VAR_ERROR_NO_HELLO "error_no_hello" +#define DEF_ERROR_NO_HELLO "Error: send HELO/EHLO first" +extern char *var_error_no_hello; + +#define VAR_ERROR_NESTED_MAIL "error_nested_mail" +#define DEF_ERROR_NESTED_MAIL "Error: nested MAIL command" +extern char *var_error_nested_mail; + +#define VAR_ERROR_NO_MAIL "error_no_mail" +#define DEF_ERROR_NO_MAIL "Error: need MAIL command" +extern char *var_error_no_mail; + +#define VAR_ERROR_TOO_MANY_RECIPIENTS "error_too_many_recipients" +#define DEF_ERROR_TOO_MANY_RECIPIENTS "Error: too many recipients" +extern char *var_error_too_many_reipients; + +#define VAR_ERROR_NEED_RCPT "error_need_rcpt" +#define DEF_ERROR_NEED_TCPT "Error: need RCPT command" +extern char *var_error_need_rcpt; + +#define VAR_ERROR_MSG_TOO_LARGE "error_msg_too_large" +#define DEF_ERROR_MSG_TOO_LARGE "Error: message too large" +extern char *var_error_msg_too_large; + +#define VAR_ERROR_BAD_RECIPIENTS "error_bad_recipients" +#define DEF_ERROR_BAD_RECIPIENTS "Error: no valid recipients" +extern char *var_error_bad_recipients; + +#define VAR_ERROR_TOO_MANY_HOPS "error_too_many_hops" +#define DEF_ERROR_TOO_MANY_HOPS "Error: too many hops" +extern char *var_error_too_many_hops; + +#define VAR_ERROR_QUEUE_FILE "error_queue_file" +#define DEF_ERROR_QUEUE_FILE "Error: queue file write error" +extern char *var_error_queue_file; + +#define VAR_ERROR_MAIL_TRANSACTION "error_mail_transaction" +#define DEF_ERROR_MAIL_TRANSACTION "Error: MAIL transaction in progress" +extern char *var_error_mail_transaction; + +#define VAR_ERROR_PARAMETER_SYNTAX "error_parameter_syntax" +#define DEF_ERROR_PARAMETER_SYNTAX "Error: invalid parameter syntax" +extern char *var_error_parameter_syntax; + +#define VAR_ERROR_AUTH "error_auth" +#define DEF_ERROR_AUTH "Error: insufficient authorization" +extern char *var_error_auth; + +#define VAR_ERROR_ATTRIB_VALUE "error_attrib_value" +#define DEF_ERROR_ATTRIB_VALUE "Error: attribute=value expected" +extern char *var_error_attrib_value; + +#define VAR_ERROR_ATTR_TOO_LONG "error_attr_too_long" +#define DEF_ERROR_ATTR_TOO_LONG "Error: attribute value too long" +extern char *var_error_attr_too_long; + +#define VAR_ERROR_BAD_SYNTAX "error_bad_syntax" +#define DEF_ERROR_BAD_SYNTAX "Error: bad syntax" +extern char *var_error_bad_syntax; + +#define VAR_ERROR_BAD_COMMAND "error_bad_command" +#define DEF_ERROR_BAD_COMMAND "Error: I can break rules, too. Goodbye." +extern char *var_error_bad_command; + + /* * Names of specific restrictions, and the corresponding configuration * parameters that control the status codes sent in response to rejected * requests.