# - prefix: name (default: "")
# prefix to the name of the greylist database
# - lookup_by_host: boolean (default: false)
-# perform lookup per host instead of domain.
+# perform lookup per host. The default behaviour is to remove the last number of the IP
+# to match a domain. This behaviour is disabled if a part of the IP is contained in the
+# hostname (look like a dialup ip from a provider). With this flag on, the "domain"
+# matching is always disable.
+# - no_sender: boolean (default: false)
+# do not use the sender address. Default behaviour is to greylist using the tuple
+# (client_address, sender, recipient). With this flag on, the sender is not used.
+# - no_recipient: boolean (default: false)
+# same as no_sender but with recipient.
# - delay: number (default: 300)
# number of seconds the client must wait before retrial.
# - retry_window: (default: 2 * 24 * 3600)
# - if the client is greylisted, returns greylist
# - if a error occured (not currently possible), returns error
# State:
-# this filter is a recipient filter and works in RCPT state only
-# (smtpd_recipient_restrictions).
+# this filter is a recipient filter and works in RCPT state onl if no_recipient
+# is not specified (smtpd_recipient_restrictions). If no_sender is not given, this
+# requires a sender name, and so must be called after MAIL TO.
# Perform greylisting
greylist {
typedef struct greylist_config_t {
unsigned lookup_by_host : 1;
+ unsigned no_sender : 1;
+ unsigned no_recipient : 1;
int delay;
int retry_window;
int client_awl;
} greylist_config_t;
#define GREYLIST_INIT { .lookup_by_host = false, \
+ .no_sender = false, \
+ .no_recipient = false, \
.delay = 300, \
.retry_window = 2 * 24 * 3600, \
.client_awl = 5, \
*/
klen = snprintf(key, sizeof(key), "%s/%s/%s",
c_net(config, c_addr, c_name, cnet, sizeof(cnet)),
- sender_normalize(sender, sbuf, sizeof(sbuf)), rcpt);
+ config->no_sender ? "" : sender_normalize(sender, sbuf, sizeof(sbuf)),
+ config->no_recipient ? "" : rcpt);
klen = MIN(klen, ssizeof(key) - 1);
res = tcbdbget3(config->obj_db, key, klen, &len);
FILTER_PARAM_PARSE_STRING(PATH, path);
FILTER_PARAM_PARSE_STRING(PREFIX, prefix);
FILTER_PARAM_PARSE_BOOLEAN(LOOKUP_BY_HOST, config->lookup_by_host);
+ FILTER_PARAM_PARSE_BOOLEAN(NO_SENDER, config->no_sender);
+ FILTER_PARAM_PARSE_BOOLEAN(NO_RECIPIENT, config->no_recipient);
FILTER_PARAM_PARSE_INT(RETRY_WINDOW, config->retry_window);
FILTER_PARAM_PARSE_INT(CLIENT_AWL, config->client_awl);
FILTER_PARAM_PARSE_INT(DELAY, config->delay);
filter_context_t *context)
{
const greylist_config_t *config = filter->data;
- if (query->state != SMTP_RCPT) {
- warn("greylisting only works as smtpd_recipient_restrictions");
+ if (!config->no_recipient && query->state != SMTP_RCPT) {
+ warn("greylisting on recipient only works as smtpd_recipient_restrictions");
+ return HTK_ABORT;
+ }
+ if (!config->no_sender && query->state < SMTP_MAIL) {
+ warn("greylisting on sender must be performed after (or at) MAIL TO");
return HTK_ABORT;
}
/* Parameters.
*/
(void)filter_param_register(type, "lookup_by_host");
+ (void)filter_param_register(type, "no_sender");
+ (void)filter_param_register(type, "no_recipient");
(void)filter_param_register(type, "delay");
(void)filter_param_register(type, "retry_window");
(void)filter_param_register(type, "client_awl");