Mercurial > dnsbl
diff src/dnsbl.cpp @ 192:8f4a9a37d4d9
delay autowhitelisting to avoid out of office reply bots
author | carl |
---|---|
date | Sun, 11 Nov 2007 12:49:25 -0800 |
parents | 2a67d31099c3 |
children | 3ea79ef741a0 |
line wrap: on
line diff
--- a/src/dnsbl.cpp Sat Nov 10 16:20:51 2007 -0800 +++ b/src/dnsbl.cpp Sun Nov 11 12:49:25 2007 -0800 @@ -257,6 +257,7 @@ want_spamassassin = false; want_dccgrey = false; want_dccbulk = false; + is_bulk_precedence = false; content_context = NULL; memory = NULL; scanner = NULL; @@ -285,6 +286,7 @@ if (queueid) free(queueid); if (authenticated) free(authenticated); if (client_name) free(client_name); + delayer.clear(); discard(env_to); if (memory) delete memory; if (scanner) delete scanner; @@ -302,6 +304,7 @@ want_spamassassin = false; want_dccgrey = false; want_dccbulk = false; + is_bulk_precedence = false; content_context = NULL; memory = NULL; scanner = NULL; @@ -950,17 +953,22 @@ // wrapper if the mail client did not, but the current version does not do // that. So the <> wrapper is now optional. It may have mixed case, just // as the mail client sent it. We dup the string and convert the duplicate -// to lower case. +// to lower case. Some clients enclose the entire address in single quotes, +// so we strip those as well. // char *to_lower_string(char *email); char *to_lower_string(char *email) { int n = strlen(email); - if (*email == '<') { + if (email[0] == '<') { // assume it also ends with > n -= 2; if (n < 1) return strdup(email); // return "<>" email++; } + if ((email[0] == '\'') && (email[n-1] == '\'') && (n > 2)) { + n -= 2; + email++; + } char *key = strdup(email); key[n] = '\0'; for (int i=0; i<n; i++) key[i] = tolower(key[i]); @@ -1110,14 +1118,15 @@ // if needed to ensure we can accept replies loto = to_lower_string(rcptaddr); WHITELISTERP w = con2.find_autowhite(loto, priv.mailaddr); + // check if local part is too big + const int max_local_size = 30; + char *p = strchr(loto, '@'); + int len = (p) ? p-loto : max_local_size; + if (len >= max_local_size) w = NULL; // too big, pretend we don't have a whitelister + // record it if we have a whitelister if (w) { - if (debug_syslog > 1) { - char buf[maxlen]; - char msg[maxlen]; - snprintf(msg, sizeof(msg), "whitelist reply from <%s> in context %s", loto, con2.get_full_name(buf,maxlen)); - my_syslog(&priv, msg); - } - w->sent(loto); // don't free it, the whitelister takes ownership of the string + DELAYWHITEP dwp = new DELAYWHITE(loto, w, &con2); + priv.delayer.push_back(dwp); } else { free(loto); @@ -1154,6 +1163,10 @@ sfsistat mlfi_header(SMFICTX* ctx, char* headerf, char* headerv) { mlfiPriv &priv = *MLFIPRIV; + // detect precedence:bulk for avoiding autowhitelisting + if ((strcasecmp(headerf, "precedence") == 0) && + (strcasecmp(headerv, "bulk") == 0)) priv.is_bulk_precedence = true; + // other headers are only needed for content filtering if (priv.authenticated) return SMFIS_CONTINUE; if (priv.only_whites) return SMFIS_CONTINUE; if (priv.want_spamassassin) priv.assassin->mlfi_header(headerf, headerv); @@ -1164,6 +1177,25 @@ sfsistat mlfi_eoh(SMFICTX* ctx) { mlfiPriv &priv = *MLFIPRIV; + // delayed autowhitelisting + while (!priv.delayer.empty()) { + DELAYWHITEP dwp = priv.delayer.front(); + if (!priv.is_bulk_precedence) { + char *loto = dwp->get_loto(); + WHITELISTERP w = dwp->get_w(); + CONTEXTP con2 = dwp->get_con(); + if (debug_syslog > 1) { + char buf[maxlen]; + char msg[maxlen]; + snprintf(msg, sizeof(msg), "whitelist reply from <%s> in context %s", loto, con2->get_full_name(buf,maxlen)); + my_syslog(&priv, msg); + } + w->sent(loto); // don't free it, the whitelister takes ownership of the string + } + delete dwp; + priv.delayer.pop_front(); + } + // content filtering if (priv.authenticated) return SMFIS_CONTINUE; if (priv.only_whites) return SMFIS_CONTINUE; if (priv.want_spamassassin) priv.assassin->mlfi_eoh();