Le dim. 12 janv. 2020 à 21:28, Wietse Venema <wie...@porcupine.org> a écrit : > Viktor Dukhovni: > > My instinct was to suggest that the filter goes first, and then the > > footer gets added, but usability rather depends on how the pending > > multi-line response is presented to the filter. If it is easy for the > > filter to match and selectively retain the footer, then you're probably > > right and the filter should have the final say. If, on the other hand, > > it becomes hard to selectively retain the footer, then I'd be tempted to > > add it last. > > > > The "\c" trick no longer works once the footer is combined with the > > original text, because (at least in principle) by that point the > > original text could have a verbatim "\c" in it, that is not intended to > > become a line-break. > > \c in a reply filter? I don't see any need for any special > sequences other than ${number} which is already supported.
My opinion is mostly the same : if we introduce a new smtpd_reject_filter_maps parameter it would be executed first : the purpose is indeed to replace hard-coded internal message by another one at first. Secondly, if the reply message currently processed has not been replaced the code would check smtpd_reject_footer_maps and apply the footer if the message match. My thinking is that an administrator have to choose between selective replacement and selective footer, there is no really need to execute both : you can do it all at once with smtpd_reject_filter_maps (and managing the sequence of the two would be hard to debug : does the second regexp applies before or after text replacement ?) Thirdly, like the current behavior of postfix, smtpd_reject_footer must not be executed if smtpd_reject_footer_maps has matched, however whatever the execution of smtpd_reject_filter_maps the smtpd_reject_footer is executed ! we don't want to repeat ourself by adding a common footer to all the replacement text. Here is an example : smtpd_reject_footer_maps = regexp:$postfix_config_dir/amend_smtpd_responses.regexp smtpd_reject_filter_maps = regexp:$postfix_config_dir/replace_smtpd_responses.regexp smtpd_reject_footer = \c. Pour assistance, appelez-le 800-555-0101. amend_smtpd_responses.regexp: # this file add a footer to the reply with the same error message but in french # only for the example, this regexp is ignored because smtpd_reject_filter_maps define the same rule # 550 5.1.1 <f...@domain.tld>: Recipient address rejected: User unknown /^550 5.1.1 (<[^>]*>):/ $1: Adresse destinataire invalide. # 504 5.5.2 <foo@domain>: Sender address rejected: need fully-qualified address /^504 5.5.2 (<[^>]*>):/ $1: Emetteur invalide. replace_smtpd_responses.regexp : # this file replace hard-coded error message by french one # 550 5.1.1 <f...@domain.tld>: Recipient address rejected: User unknown /^550 5.1.1 (<[^>]*>):/ $1: Adresse destinataire invalide. The result for unknown recipient : rcpt to:<fkldk...@example.com> 554 5.7.1 <fkldkfdl@example>: Adresse destinataire invalide. Pour assistance, appelez-le 800-555-0101. > So we need a canonical multiline representation before we can even > think about filtering SMTP server replies. It's probably going to > be embedded \r\n sequences, with smtpd_chat_reply() implementing > the filter-then-footer or footer-then-filter, and then splitting > the multiline text into separate lines, before doing output and > appending to the session history. I've no opinion about that, I think that the change don't break anything (replacing everything starting after the first SMTP error code and its following SMTP extended status code) Below an extract of the proposed code : src/global/smtp_reply_footer.[ch] are renamed into src/global/smtp_reply_filter.[ch] with 2 public functions smtp_reply_filter() and smtp_reply_footer() and 95% of the common code in internal function smtp_reply_alter. diff --git a/src/smtpd/smtpd_chat.c b/src/smtpd/smtpd_chat.c index 63795b8..af0f69f 100644 --- a/src/smtpd/smtpd_chat.c +++ b/src/smtpd/smtpd_chat.c @@ -102,7 +102,7 @@ #include <maps.h> #include <post_mail.h> #include <mail_error.h> -#include <smtp_reply_footer.h> +#include <smtp_reply_filter.h> /* Application-specific. */ @@ -111,8 +111,9 @@ #include "smtpd_chat.h" /* - * Reject footer. + * Reject replacement and footer. */ +static MAPS *smtpd_rej_flt_maps; static MAPS *smtpd_rej_ftr_maps; #define STR vstring_str @@ -128,12 +129,16 @@ void smtpd_chat_pre_jail_init(void) msg_panic("smtpd_chat_pre_jail_init: multiple calls"); /* - * SMTP server reject footer. + * SMTP server reject replacement and footer. */ if (*var_smtpd_rej_ftr_maps) smtpd_rej_ftr_maps = maps_create(VAR_SMTPD_REJ_FTR_MAPS, var_smtpd_rej_ftr_maps, DICT_FLAG_LOCK); + if (*var_smtpd_rej_flt_maps) + smtpd_rej_flt_maps = maps_create(VAR_SMTPD_REJ_FLT_MAPS, + var_smtpd_rej_flt_maps, + DICT_FLAG_LOCK); } /* smtp_chat_reset - reset SMTP transaction log */ @@ -205,7 +210,8 @@ void vsmtpd_chat_reply(SMTPD_STATE *state, const char *format, va_list ap) char *cp; char *next; char *end; - const char *footer; + const char *footer = 0; + const char *replacement; /* * Slow down clients that make errors. Sleep-on-anything slows down @@ -216,12 +222,19 @@ void vsmtpd_chat_reply(SMTPD_STATE *state, const char *format, va_list ap) vstring_vsprintf(state->buffer, format, ap); - if ((*(cp = STR(state->buffer)) == '4' || *cp == '5') - && ((smtpd_rej_ftr_maps != 0 + if (*(cp = STR(state->buffer)) == '4' || *cp == '5') { + if (smtpd_rej_flt_maps != 0 + && (replacement = maps_find(smtpd_rej_flt_maps, cp, 0)) != 0) + smtp_reply_filter(state->buffer, 0, replacement, STR(smtpd_expand_filter), + smtpd_expand_lookup, (void *) state); + else if (smtpd_rej_ftr_maps != 0 && (footer = maps_find(smtpd_rej_ftr_maps, cp, 0)) != 0) - || *(footer = var_smtpd_rej_footer) != 0)) - smtp_reply_footer(state->buffer, 0, footer, STR(smtpd_expand_filter), - smtpd_expand_lookup, (void *) state); + smtp_reply_footer(state->buffer, 0, footer, STR(smtpd_expand_filter), + smtpd_expand_lookup, (void *) state); + if (footer == 0 && *(footer = var_smtpd_rej_footer) != 0) + smtp_reply_footer(state->buffer, 0, footer, STR(smtpd_expand_filter), + smtpd_expand_lookup, (void *) state); + } diff --git a/src/global/mail_params.h b/src/global/mail_params.h index 1f4c207..2fe0d0d 100644 --- a/src/global/mail_params.h +++ b/src/global/mail_params.h @@ -4009,6 +4009,10 @@ extern char *var_smtpd_rej_footer; #define DEF_SMTPD_REJ_FTR_MAPS "" extern char *var_smtpd_rej_ftr_maps; +#define VAR_SMTPD_REJ_FLT_MAPS "smtpd_reject_filter_maps" +#define DEF_SMTPD_REJ_FLT_MAPS "" +extern char *var_smtpd_rej_flt_maps; + Sébastien