From 0418e5b461938d307c354a1a0805f880dca3148a Mon Sep 17 00:00:00 2001 From: Rimas Kudelis Date: Tue, 23 Jan 2024 11:08:18 +0200 Subject: [PATCH 1/8] Rewrite all SQL queries in 250_vexim_virtual_domains - Use `INNER JOIN ON` instead of "comma-joins" with `WHERE` conditions - Fix #276: prevent non-members from posting to private groups when they are members of other groups - modify `virtual_dom_groups` query to not assume that usernames and email addresses match --- .../router/250_vexim_virtual_domains | 191 +++++++++++------- 1 file changed, 119 insertions(+), 72 deletions(-) diff --git a/docs/debian-conf.d/router/250_vexim_virtual_domains b/docs/debian-conf.d/router/250_vexim_virtual_domains index c55863c7..cde5f808 100644 --- a/docs/debian-conf.d/router/250_vexim_virtual_domains +++ b/docs/debian-conf.d/router/250_vexim_virtual_domains @@ -5,12 +5,18 @@ virtual_vacation: driver = accept domains = +local_domains - condition = ${if and { {!match {$h_precedence:}{(?i)junk|bulk|list}} \ - {eq {${lookup mysql{select users.on_vacation from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_vacation = '1' \ - and users.domain_id=domains.domain_id}}}{1} }} {yes}{no} } + condition = ${if and { \ + {!match {$h_precedence:}{(?i)junk|bulk|list}} \ + {eq \ + {1} \ + {${lookup mysql{ \ + SELECT u.on_vacation \ + FROM users u \ + INNER JOIN domains d ON (d.domain_id = u.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }}} \ + }} {yes}{no}} no_verify no_expn unseen @@ -20,46 +26,67 @@ virtual_forward: driver = redirect domains = +local_domains check_ancestor - unseen = ${if eq {${lookup mysql{select unseen from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_forward = '1' \ - and users.domain_id=domains.domain_id}}}{1} {yes}{no}} - data = ${lookup mysql{select forward from users,domains \ - where localpart='${quote_mysql:$local_part}' \ - and domain='${quote_mysql:$domain}' \ - and users.domain_id=domains.domain_id \ - and on_forward = '1'}} + unseen = ${if eq \ + {1} \ + {${lookup mysql{ \ + SELECT u.unseen \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.on_forward = '1' \ + }}} {yes}{no}} + data = ${lookup mysql{ \ + SELECT u.forward \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + and u.on_forward = '1' \ + }} # We explicitly make this condition NOT forward mailing list mail! - condition = ${if and { {!match {$h_precedence:}{(?i)junk}} \ - {eq {${lookup mysql{select users.on_forward from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_forward = '1' \ - and users.domain_id=domains.domain_id}}}{1} }} {yes}{no} } + condition = ${if and { \ + {!match {$h_precedence:}{(?i)junk}} \ + {eq \ + {1} \ + {${lookup mysql{ \ + SELECT u.on_forward \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.on_forward = '1' \ + }}} \ + }} {yes}{no} } virtual_domains: driver = redirect domains = +local_domains address_data = ${lookup mysql{\ - select smtp, users.sa_tag*10 AS sa_tag, users.on_spamassassin AND domains.spamassassin AS on_spamassassin, \ - users.uid AS uid, users.gid AS gid, quota \ - from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and domains.enabled = '1' \ - and users.enabled = '1' \ - and users.domain_id = domains.domain_id}{$value}fail} + SELECT \ + u.smtp, \ + u.sa_tag * 10 AS sa_tag, \ + u.on_spamassassin AND d.spamassassin AS on_spamassassin, \ + u.uid AS uid, \ + u.gid AS gid, \ + quota \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND d.enabled = '1' \ + AND u.enabled = '1' \ + }{$value}fail} allow_fail data = ${extract{smtp}{$address_data}} headers_add = ${if and { \ - {match{$domain}{$original_domain}} \ - {match{$local_part}{$original_local_part}} \ - {>={$spam_score_int}{${extract{sa_tag}{$address_data}}}} \ - {eq{1}{${extract{on_spamassassin}{$address_data}}}} \ - } {X-Spam-Flag: YES\nX-Spam-Score: $acl_m_spam_score\nVEXIM_SPAM_REPORT_HEADER_NAME: $acl_m_spam_report}{} } - # using local_part_suffixes enables possibility to use user-"something" localparts - # which could cause you trouble if you're creating email-adresses with dashes in between. + {match{$domain}{$original_domain}} \ + {match{$local_part}{$original_local_part}} \ + {>={$spam_score_int}{${extract{sa_tag}{$address_data}}}} \ + {eq{1}{${extract{on_spamassassin}{$address_data}}}} \ + } {X-Spam-Flag: YES\nX-Spam-Score: $acl_m_spam_score\nVEXIM_SPAM_REPORT_HEADER_NAME: $acl_m_spam_report}{} } + # using local_part_suffixes enables possibility to use user+"something" localparts + # which could cause you trouble if you're creating email addresses with plus signs in them. .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional @@ -71,8 +98,8 @@ virtual_domains: # A group is a list of users # -# if a group is flaged public -# then anyone on the internet can write to it +# If a group is marked public +# then anyone on the Internet can write to it # else only members can write to it # # If not public non member sender will receive a "550 Unknown user" message @@ -80,34 +107,47 @@ virtual_dom_groups: driver = redirect domains = +local_domains allow_fail - senders = ${if eq{Y}{${lookup mysql{select g.is_public \ - from groups g, domains d \ - where d.enabled = '1' and d.domain = '${quote_mysql:$domain}' and \ - d.domain_id = g.domain_id and g.enabled = '1' and \ - g.name = '${quote_mysql:$local_part}'}}} \ - {$sender_address} \ - {${lookup mysql{select concat_ws('@', u.localpart, d.domain) \ - from domains d, groups g, group_contents c, users u \ - where d.enabled = '1' and d.domain = '${quote_mysql:$domain}' and \ - d.domain_id = g.domain_id and g.name = '${quote_mysql:$local_part}' and \ - g.enabled = '1' and \ - g.is_public = 'N' and c.member_id = u.user_id and \ - d.domain_id = u.domain_id and u.enabled = '1' \ - and u.username = '${quote_mysql:$sender_address}' limit 1}}}} + senders = ${if eq \ + {Y} \ + {${lookup mysql{ \ + SELECT g.is_public \ + FROM domains d \ + INNER JOIN groups g ON (g.domain_id = d.domain_id) \ + WHERE d.domain = '${quote_mysql:$domain}' \ + AND g.name = '${quote_mysql:$local_part}' \ + AND d.enabled = '1' \ + AND g.enabled = '1' \ + }}} \ + {$sender_address} \ + {${lookup mysql{ \ + SELECT CONCAT_WS('@', u.localpart, d.domain) AS sender \ + FROM domains d \ + INNER JOIN groups g ON (g.domain_id = d.domain_id) \ + INNER JOIN group_contents c ON (c.group_id = g.id) \ + INNER JOIN users u ON (u.user_id = c.member_id AND u.domain_id = d.domain_id) \ + WHERE d.domain = '${quote_mysql:$domain}' \ + AND g.name = '${quote_mysql:$local_part}' \ + AND g.is_public = 'N' \ + AND d.enabled = '1' \ + AND g.enabled = '1' \ + AND u.enabled = '1' \ + HAVING sender = '${quote_mysql:$sender_address}' \ + LIMIT 1 \ + }}}} data = ${lookup mysql{ \ - select concat_ws('@', u.localpart, d.domain) \ - from domains d, groups g, group_contents c, users u \ - where d.enabled = '1' and \ - d.domain = '${quote_mysql:$domain}' and \ - d.domain_id = g.domain_id and \ - g.enabled = '1' and \ - g.id = c.group_id and \ - c.member_id = u.user_id and \ - d.domain_id = u.domain_id and \ - u.enabled = '1' and \ - g.name = '${quote_mysql:$local_part}'} } - # using local_part_suffixes enables possibility to use user-"something" localparts - # which could cause you trouble if you're creating email-adresses with dashes in between. + SELECT CONCAT_WS('@', u.localpart, d.domain) \ + FROM domains d \ + INNER JOIN groups g ON (g.domain_id = d.domain_id) \ + INNER JOIN group_contents c ON (c.group_id = g.id) \ + INNER JOIN users u ON (u.user_id = c.member_id AND u.domain_id = d.domain_id) \ + WHERE d.domain = '${quote_mysql:$domain}' \ + AND g.name = '${quote_mysql:$local_part}' \ + AND d.enabled = '1' \ + AND g.enabled = '1' \ + AND u.enabled = '1' \ + }} + # using local_part_suffixes enables possibility to use user+"something" localparts + # which could cause you trouble if you're creating email addresses with plus signs in them. .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional @@ -120,9 +160,13 @@ virtual_domains_catchall: driver = redirect domains = +local_domains allow_fail - data = ${lookup mysql{select smtp from users,domains where localpart = '*' \ - and domain = '${quote_mysql:$domain}' \ - and users.domain_id = domains.domain_id}} + data = ${lookup mysql{ \ + SELECT u.smtp \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE localpart = '*' \ + AND domain = '${quote_mysql:$domain}' \ + }} retry_use_local_part file_transport = virtual_delivery reply_transport = address_reply @@ -132,7 +176,10 @@ virtual_domain_alias: driver = redirect domains = +local_domains allow_fail - data = ${lookup mysql{select concat('${quote_mysql:$local_part}@', domain) \ - from domains,domainalias where domainalias.alias = '${quote_mysql:$domain}' \ - and domainalias.domain_id = domains.domain_id}} + data = ${lookup mysql{ \ + SELECT CONCAT('${quote_mysql:$local_part}@', d.domain) \ + FROM domains d \ + INNER JOIN domainalias a ON (a.domain_id = d.domain_id) \ + WHERE a.alias = '${quote_mysql:$domain}' \ + }} retry_use_local_part From 111f9ec36a95990e517631b737c3c720d017af97 Mon Sep 17 00:00:00 2001 From: Rimas Kudelis Date: Tue, 23 Jan 2024 12:21:17 +0200 Subject: [PATCH 2/8] Port changes in 0418e5b to the configure file --- docs/configure | 194 +++++++++++++++++++++++++++++++------------------ 1 file changed, 124 insertions(+), 70 deletions(-) diff --git a/docs/configure b/docs/configure index 4f6b6ac5..d88ae2c6 100644 --- a/docs/configure +++ b/docs/configure @@ -747,12 +747,19 @@ ditch_hdrsubject: virtual_vacation: driver = accept - condition = ${if and { {!match {$h_precedence:}{(?i)junk|bulk|list}} \ - {eq {${lookup mysql{select users.on_vacation from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_vacation = '1' \ - and users.domain_id=domains.domain_id}}}{1} }} {yes}{no} } + domains = +local_domains + condition = ${if and { \ + {!match {$h_precedence:}{(?i)junk|bulk|list}} \ + {eq \ + {1} \ + {${lookup mysql{ \ + SELECT u.on_vacation \ + FROM users u \ + INNER JOIN domains d ON (d.domain_id = u.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }}} \ + }} {yes}{no}} no_verify no_expn unseen @@ -760,47 +767,69 @@ virtual_vacation: virtual_forward: driver = redirect + domains = +local_domains check_ancestor - unseen = ${if eq {${lookup mysql{select unseen from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_forward = '1' \ - and users.domain_id=domains.domain_id}}}{1} {yes}{no}} - data = ${lookup mysql{select forward from users,domains \ - where localpart='${quote_mysql:$local_part}' \ - and domain='${quote_mysql:$domain}' \ - and users.domain_id=domains.domain_id \ - and on_forward = '1'}} + unseen = ${if eq \ + {1} \ + {${lookup mysql{ \ + SELECT u.unseen \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.on_forward = '1' \ + }}} {yes}{no}} + data = ${lookup mysql{ \ + SELECT u.forward \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + and u.on_forward = '1' \ + }} # We explicitly make this condition NOT forward mailing list mail! - condition = ${if and { {!match {$h_precedence:}{(?i)junk}} \ - {eq {${lookup mysql{select users.on_forward from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_forward = '1' \ - and users.domain_id=domains.domain_id}}}{1} }} {yes}{no} } + condition = ${if and { \ + {!match {$h_precedence:}{(?i)junk}} \ + {eq \ + {1} \ + {${lookup mysql{ \ + SELECT u.on_forward \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.on_forward = '1' \ + }}} \ + }} {yes}{no} } virtual_domains: driver = redirect domains = +local_domains address_data = ${lookup mysql{\ - select smtp, users.sa_tag*10 AS sa_tag, users.on_spamassassin AND domains.spamassassin AS on_spamassassin, \ - users.uid AS uid, users.gid AS gid, quota \ - from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and domains.enabled = '1' \ - and users.enabled = '1' \ - and users.domain_id = domains.domain_id}{$value}fail} + SELECT \ + u.smtp, \ + u.sa_tag * 10 AS sa_tag, \ + u.on_spamassassin AND d.spamassassin AS on_spamassassin, \ + u.uid AS uid, \ + u.gid AS gid, \ + quota \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND d.enabled = '1' \ + AND u.enabled = '1' \ + }{$value}fail} allow_fail data = ${extract{smtp}{$address_data}} headers_add = ${if and { \ - {match{$domain}{$original_domain}} \ - {match{$local_part}{$original_local_part}} \ - {>={$spam_score_int}{${extract{sa_tag}{$address_data}}}} \ - {eq{1}{${extract{on_spamassassin}{$address_data}}}} \ - } {X-Spam-Flag: YES\nX-Spam-Score: $acl_m_spam_score\nVEXIM_SPAM_REPORT_HEADER_NAME: $acl_m_spam_report}{} } - # using local_part_suffixes enables possibility to use user-"something" localparts - # which could cause you trouble if you're creating email-adresses with dashes in between. + {match{$domain}{$original_domain}} \ + {match{$local_part}{$original_local_part}} \ + {>={$spam_score_int}{${extract{sa_tag}{$address_data}}}} \ + {eq{1}{${extract{on_spamassassin}{$address_data}}}} \ + } {X-Spam-Flag: YES\nX-Spam-Score: $acl_m_spam_score\nVEXIM_SPAM_REPORT_HEADER_NAME: $acl_m_spam_report}{} } + # using local_part_suffixes enables possibility to use user+"something" localparts + # which could cause you trouble if you're creating email addresses with plus signs in them. .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional @@ -812,40 +841,56 @@ virtual_domains: # A group is a list of users # -# if a group is flaged public -# then anyone on the internet can write to it +# If a group is marked public +# then anyone on the Internet can write to it # else only members can write to it # # If not public non member sender will receive a "550 Unknown user" message virtual_dom_groups: driver = redirect + domains = +local_domains allow_fail - senders = ${if eq{Y}{${lookup mysql{select g.is_public \ - from groups g, domains d \ - where d.enabled = '1' and d.domain = '${quote_mysql:$domain}' and \ - d.domain_id = g.domain_id and g.enabled = '1' and \ - g.name = '${quote_mysql:$local_part}'}}} \ - {$sender_address} \ - {${lookup mysql{select concat_ws('@', u.localpart, d.domain) \ - from domains d, groups g, group_contents c, users u \ - where d.enabled = '1' and d.domain = '${quote_mysql:$domain}' and \ - d.domain_id = g.domain_id and g.name = '${quote_mysql:$local_part}' and \ - g.enabled = '1' and \ - g.is_public = 'N' and c.member_id = u.user_id and \ - d.domain_id = u.domain_id and u.enabled = '1' \ - and u.username = '${quote_mysql:$sender_address}' }}}} + senders = ${if eq \ + {Y} \ + {${lookup mysql{ \ + SELECT g.is_public \ + FROM domains d \ + INNER JOIN groups g ON (g.domain_id = d.domain_id) \ + WHERE d.domain = '${quote_mysql:$domain}' \ + AND g.name = '${quote_mysql:$local_part}' \ + AND d.enabled = '1' \ + AND g.enabled = '1' \ + }}} \ + {$sender_address} \ + {${lookup mysql{ \ + SELECT CONCAT_WS('@', u.localpart, d.domain) AS sender \ + FROM domains d \ + INNER JOIN groups g ON (g.domain_id = d.domain_id) \ + INNER JOIN group_contents c ON (c.group_id = g.id) \ + INNER JOIN users u ON (u.user_id = c.member_id AND u.domain_id = d.domain_id) \ + WHERE d.domain = '${quote_mysql:$domain}' \ + AND g.name = '${quote_mysql:$local_part}' \ + AND g.is_public = 'N' \ + AND d.enabled = '1' \ + AND g.enabled = '1' \ + AND u.enabled = '1' \ + HAVING sender = '${quote_mysql:$sender_address}' \ + LIMIT 1 \ + }}}} data = ${lookup mysql{ \ - select concat_ws('@', u.localpart, d.domain) \ - from domains d, groups g, group_contents c, users u \ - where d.enabled = '1' and \ - d.domain = '${quote_mysql:$domain}' and \ - d.domain_id = g.domain_id and \ - g.enabled = '1' and \ - g.id = c.group_id and \ - c.member_id = u.user_id and \ - d.domain_id = u.domain_id and \ - u.enabled = '1' and \ - g.name = '${quote_mysql:$local_part}'} } + SELECT CONCAT_WS('@', u.localpart, d.domain) \ + FROM domains d \ + INNER JOIN groups g ON (g.domain_id = d.domain_id) \ + INNER JOIN group_contents c ON (c.group_id = g.id) \ + INNER JOIN users u ON (u.user_id = c.member_id AND u.domain_id = d.domain_id) \ + WHERE d.domain = '${quote_mysql:$domain}' \ + AND g.name = '${quote_mysql:$local_part}' \ + AND d.enabled = '1' \ + AND g.enabled = '1' \ + AND u.enabled = '1' \ + }} + # using local_part_suffixes enables possibility to use user+"something" localparts + # which could cause you trouble if you're creating email addresses with plus signs in them. .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional @@ -856,10 +901,15 @@ virtual_dom_groups: virtual_domains_catchall: driver = redirect + domains = +local_domains allow_fail - data = ${lookup mysql{select smtp from users,domains where localpart = '*' \ - and domain = '${quote_mysql:$domain}' \ - and users.domain_id = domains.domain_id}} + data = ${lookup mysql{ \ + SELECT u.smtp \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE localpart = '*' \ + AND domain = '${quote_mysql:$domain}' \ + }} retry_use_local_part file_transport = virtual_delivery reply_transport = address_reply @@ -867,10 +917,14 @@ virtual_domains_catchall: virtual_domain_alias: driver = redirect + domains = +local_domains allow_fail - data = ${lookup mysql{select concat('${quote_mysql:$local_part}@', domain) \ - from domains,domainalias where domainalias.alias = '${quote_mysql:$domain}' \ - and domainalias.domain_id = domains.domain_id}} + data = ${lookup mysql{ \ + SELECT CONCAT('${quote_mysql:$local_part}@', d.domain) \ + FROM domains d \ + INNER JOIN domainalias a ON (a.domain_id = d.domain_id) \ + WHERE a.alias = '${quote_mysql:$domain}' \ + }} retry_use_local_part From 8ed91a125c95b3e75243a2684d5ae2839cc986f6 Mon Sep 17 00:00:00 2001 From: Rimas Kudelis Date: Tue, 23 Jan 2024 12:21:56 +0200 Subject: [PATCH 3/8] Reformat authenticator config --- docs/configure | 94 ++++++++++--------- .../auth/30_vexim_authenticators | 79 ++++++++-------- 2 files changed, 92 insertions(+), 81 deletions(-) diff --git a/docs/configure b/docs/configure index d88ae2c6..35a5db30 100644 --- a/docs/configure +++ b/docs/configure @@ -1189,36 +1189,42 @@ begin rewrite begin authenticators plain_virtual_exim: - driver = plaintext - public_name = PLAIN - server_condition = ${if crypteq{$auth3}{${lookup mysql{ \ - SELECT crypt FROM users \ - WHERE username = '${quote_mysql:$auth2}' \ - AND enabled = 1 \ - }}}{1}{0}} - server_set_id = $auth2 - server_advertise_condition = ${if or{\ - {!eq{$tls_cipher}{}}\ - {match_ip {$sender_host_address}{@[]}}\ - }\ - {*}{}} + driver = plaintext + public_name = PLAIN + server_condition = ${if crypteq \ + {$auth3} \ + {${lookup mysql{ \ + SELECT crypt FROM users \ + WHERE username = '${quote_mysql:$auth2}' \ + AND enabled = 1 \ + }}} \ + {1}{0}} + server_set_id = $auth2 + server_advertise_condition = ${if or{ \ + {!eq{$tls_cipher}{}} \ + {match_ip {$sender_host_address}{@[]}} \ + } \ + {*}{}} login_virtual_exim: - driver = plaintext - public_name = LOGIN - server_prompts = "Username:: : Password::" - server_condition = ${if crypteq{$auth2}{${lookup mysql{ \ - SELECT crypt FROM users \ - WHERE username = '${quote_mysql:$auth1}' \ - AND enabled = 1 \ - }}}{1}{0}} - server_set_id = $auth1 - server_advertise_condition = ${if or{\ - {!eq{$tls_cipher}{}}\ - {match_ip {$sender_host_address}{@[]}}\ - }\ - {*}{}} + driver = plaintext + public_name = LOGIN + server_prompts = "Username:: : Password::" + server_condition = ${if crypteq \ + {$auth2} \ + {${lookup mysql{ \ + SELECT crypt FROM users \ + WHERE username = '${quote_mysql:$auth1}' \ + AND enabled = 1 \ + }}} \ + {1}{0}} + server_set_id = $auth1 + server_advertise_condition = ${if or{ \ + {!eq{$tls_cipher}{}} \ + {match_ip {$sender_host_address}{@[]}} \ + } \ + {*}{}} # You can use the authenticator of your IMAP server (Courier or Dovecot) to authenticate # users in Exim. To do that, comment out the lines above after begin authenticators, @@ -1242,10 +1248,10 @@ login_virtual_exim: # {yes} \ # fail} # server_set_id = $auth2 -# server_advertise_condition = ${if or{\ -# {!eq{$tls_cipher}{}}\ -# {match_ip {$sender_host_address}{@[]}}\ -# }\ +# server_advertise_condition = ${if or{ \ +# {!eq{$tls_cipher}{}} \ +# {match_ip {$sender_host_address}{@[]}} \ +# } \ # {*}{}} # # login_courier_authdaemon: @@ -1259,24 +1265,24 @@ login_virtual_exim: # {yes} \ # fail} # server_set_id = $auth1 -# server_advertise_condition = ${if or{\ -# {!eq{$tls_cipher}{}}\ -# {match_ip {$sender_host_address}{@[]}}\ -# }\ +# server_advertise_condition = ${if or{ \ +# {!eq{$tls_cipher}{}} \ +# {match_ip {$sender_host_address}{@[]}} \ +# } \ # {*}{}} # Authenticate against Dovecot SASL -# Based on: http://wiki2.dovecot.org/HowTo/EximAndDovecotSASL +# Based on: https://doc.dovecot.org/configuration_manual/howto/exim_and_dovecot_sasl/ # # login_dovecot_sasl: # driver = dovecot # public_name = LOGIN # server_socket = /var/run/dovecot/auth-client # server_set_id = $auth1 -# server_advertise_condition = ${if or{\ -# {!eq{$tls_cipher}{}}\ -# {match_ip {$sender_host_address}{@[]}}\ -# }\ +# server_advertise_condition = ${if or{ \ +# {!eq{$tls_cipher}{}} \ +# {match_ip {$sender_host_address}{@[]}} \ +# } \ # {*}{}} # # plain_dovecot_sasl: @@ -1284,10 +1290,10 @@ login_virtual_exim: # public_name = PLAIN # server_socket = /var/run/dovecot/auth-client # server_set_id = $auth1 -# server_advertise_condition = ${if or{\ -# {!eq{$tls_cipher}{}}\ -# {match_ip {$sender_host_address}{@[]}}\ -# }\ +# server_advertise_condition = ${if or{ \ +# {!eq{$tls_cipher}{}} \ +# {match_ip {$sender_host_address}{@[]}} \ +# } \ # {*}{}} diff --git a/docs/debian-conf.d/auth/30_vexim_authenticators b/docs/debian-conf.d/auth/30_vexim_authenticators index af0c212e..84bbdbbe 100644 --- a/docs/debian-conf.d/auth/30_vexim_authenticators +++ b/docs/debian-conf.d/auth/30_vexim_authenticators @@ -3,54 +3,59 @@ ########################### plain_virtual_exim: - driver = plaintext - public_name = PLAIN - server_condition = ${if crypteq{$auth3}{${lookup mysql{ \ - SELECT crypt FROM users \ - WHERE username = '${quote_mysql:$auth2}' \ - AND enabled = 1 \ - }}}{1}{0}} - server_set_id = $auth2 - server_advertise_condition = ${if or{\ - {!eq{$tls_cipher}{}}\ - {match_ip {$sender_host_address}{@[]}}\ - }\ - {*}{}} + driver = plaintext + public_name = PLAIN + server_condition = ${if crypteq \ + {$auth3} \ + {${lookup mysql{ \ + SELECT crypt FROM users \ + WHERE username = '${quote_mysql:$auth2}' \ + AND enabled = 1 \ + }}} \ + {1}{0}} + server_set_id = $auth2 + server_advertise_condition = ${if or{ \ + {!eq{$tls_cipher}{}} \ + {match_ip {$sender_host_address}{@[]}} \ + } \ + {*}{}} login_virtual_exim: - driver = plaintext - public_name = LOGIN - server_prompts = "Username:: : Password::" - - server_condition = ${if crypteq{$auth2}{${lookup mysql{ \ - SELECT crypt FROM users \ - WHERE username = '${quote_mysql:$auth1}' \ - AND enabled = 1 \ - }}}{1}{0}} - server_set_id = $auth1 - server_advertise_condition = ${if or{\ - {!eq{$tls_cipher}{}}\ - {match_ip {$sender_host_address}{@[]}}\ - }\ - {*}{}} + driver = plaintext + public_name = LOGIN + server_prompts = "Username:: : Password::" + server_condition = ${if crypteq \ + {$auth2} \ + {${lookup mysql{ \ + SELECT crypt FROM users \ + WHERE username = '${quote_mysql:$auth1}' \ + AND enabled = 1 \ + }}} \ + {1}{0}} + server_set_id = $auth1 + server_advertise_condition = ${if or{ \ + {!eq{$tls_cipher}{}} \ + {match_ip {$sender_host_address}{@[]}} \ + } \ + {*}{}} # You can use the authenticator of your IMAP server (Dovecot or Courier) to authenticate # users in Exim. To do that, comment out the lines above and uncomment either the Dovecot # section below or the Courier section in 30_exim4-config_examples file. # Authenticate against Dovecot SASL -# Based on: http://wiki2.dovecot.org/HowTo/EximAndDovecotSASL +# Based on: https://doc.dovecot.org/configuration_manual/howto/exim_and_dovecot_sasl/ # # login_dovecot_sasl: # driver = dovecot # public_name = LOGIN # server_socket = /var/run/dovecot/auth-client # server_set_id = $auth1 -# server_advertise_condition = ${if or{\ -# {!eq{$tls_cipher}{}}\ -# {match_ip {$sender_host_address}{@[]}}\ -# }\ +# server_advertise_condition = ${if or{ \ +# {!eq{$tls_cipher}{}} \ +# {match_ip {$sender_host_address}{@[]}} \ +# } \ # {*}{}} # # plain_dovecot_sasl: @@ -58,8 +63,8 @@ login_virtual_exim: # public_name = PLAIN # server_socket = /var/run/dovecot/auth-client # server_set_id = $auth1 -# server_advertise_condition = ${if or{\ -# {!eq{$tls_cipher}{}}\ -# {match_ip {$sender_host_address}{@[]}}\ -# }\ +# server_advertise_condition = ${if or{ \ +# {!eq{$tls_cipher}{}} \ +# {match_ip {$sender_host_address}{@[]}} \ +# } \ # {*}{}} From d82a6974e44292e40787adbf6e87f1b1f15fbf75 Mon Sep 17 00:00:00 2001 From: Rimas Kudelis Date: Tue, 23 Jan 2024 15:53:03 +0200 Subject: [PATCH 4/8] Reformat SQL queries in ditch routers --- docs/configure | 328 ++++++++------ .../router/249_vexim_ditch_routers | 422 ++++++++++-------- 2 files changed, 449 insertions(+), 301 deletions(-) diff --git a/docs/configure b/docs/configure index 35a5db30..7d50610f 100644 --- a/docs/configure +++ b/docs/configure @@ -545,60 +545,85 @@ mailman_router: # This router fails messages to accounts of type "fail", for which a suggested new email address is specified. ditch_551_fails: - driver = redirect - allow_fail - condition = ${if eq {${lookup mysql{select count(*) from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.type = 'fail' \ - and users.smtp != ':fail:' \ - and users.domain_id=domains.domain_id}}}{1} {yes}{no}} - data = :fail: 551 User not local; please try <\ - ${lookup mysql{select users.smtp from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.type = 'fail' \ - and users.smtp != ':fail:' \ - and users.domain_id=domains.domain_id}}> - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + condition = ${if eq \ + {1} \ + {${lookup mysql{ \ + SELECT COUNT(*) \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.type = 'fail' \ + AND u.smtp != ':fail:' \ + }}} \ + {yes}{no}} + data = :fail: 551 User not local; please try <\ + ${lookup mysql{ \ + SELECT u.smtp \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.type = 'fail' \ + AND u.smtp != ':fail:' \ + }}> + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part # This router fails messages to the remaining accounts of type "fail". ditch_550_fails: - driver = redirect - allow_fail - condition = ${if eq {${lookup mysql{select count(*) from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.type = 'fail' \ - and users.smtp = ':fail:' \ - and users.domain_id=domains.domain_id}}}{1} {yes}{no}} - data = :fail: Unrouteable address - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + condition = ${if eq \ + {1} \ + {${lookup mysql{ \ + SELECT COUNT(*) \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.type = 'fail' \ + AND u.smtp = ':fail:' \ + }}} \ + {yes}{no}} + data = :fail: Unrouteable address + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part ditch_maxmsgsize: driver = redirect allow_fail - condition = ${if >{$message_size}{${lookup mysql{select users.maxmsgsize from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.maxmsgsize > 0 \ - and users.domain_id=domains.domain_id }{${value}K}fail}} {yes}{no}} + condition = ${if > \ + {$message_size} \ + {${lookup mysql{ \ + SELECT u.maxmsgsize \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.maxmsgsize > 0 \ + }{${value}K}fail} \ + } + {yes}{no}} data = :fail:\n\Your message is too big.\n \ - Your message was rejected because the user $local_part@$domain\n \ - does not accept messages larger than \ - ${lookup mysql{select users.maxmsgsize from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.maxmsgsize > 0 \ - and users.domain_id=domains.domain_id}{${value}K}fail} Kb. + Your message was rejected because the user $local_part@$domain\n \ + does not accept messages larger than \ + ${lookup mysql{ \ + SELECT u.maxmsgsize \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + and u.maxmsgsize > 0 \ + }{${value}K}fail} Kb. .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional @@ -610,13 +635,21 @@ ditch_malware: driver = redirect allow_fail data = :blackhole: - condition = ${if and { {match {$h_X-ACL-Warn:}{.*malware.*}} \ - {eq {${lookup mysql{select users.on_avscan from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_avscan = '1' \ - and domains.avscan = '1' \ - and users.domain_id=domains.domain_id}}}{1} }} {yes}{no} } + condition = ${if and { \ + {match {$h_X-ACL-Warn:}{.*malware.*}} \ + {eq \ + {1} \ + {${lookup mysql{ \ + SELECT u.on_avscan \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.on_avscan = '1' \ + AND d.avscan = '1' \ + }}} \ + }} \ + {yes}{no}} .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional @@ -628,66 +661,89 @@ ditch_malware: # Eventually got this working with Philip Hazel and Codiac's help. # spam drop router ditch_spam_drop: - driver = redirect - allow_fail - data = :blackhole: - condition = ${if >={$spam_score_int}{${lookup mysql{select users.sa_refuse * 10 from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_spamassassin = '1' \ - and domains.spamassassin = '1' \ - and users.spam_drop = '1' \ - and users.domain_id=domains.domain_id \ - and users.sa_refuse > 0 }{$value}fail}} {yes}{no}} - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + data = :blackhole: + condition = ${if >= \ + {$spam_score_int} \ + {${lookup mysql{ \ + SELECT u.sa_refuse * 10 \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + and d.spamassassin = '1' \ + and u.on_spamassassin = '1' \ + and u.spam_drop = '1' \ + and u.sa_refuse > 0 \ + }{$value}fail} \ + } \ + {yes}{no}} + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part ditch_spam: - driver = redirect - allow_fail - file_transport = virtual_ditch_spam_transport - data = ${lookup mysql{select concat(smtp,'/.Spam') \ - from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and domains.enabled = '1' \ - and users.enabled = '1' \ - and users.domain_id = domains.domain_id}} - condition = ${if >={$spam_score_int}{${lookup mysql{select \ - users.sa_refuse * 10 from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_spamassassin = '1' \ - and domains.spamassassin = '1' \ - and users.spam_drop = '0' \ - and users.on_forward = '0' \ - and users.type = 'local' \ - and users.domain_id=domains.domain_id \ - and users.sa_refuse > 0 }{$value}fail}} {yes}{no}} - headers_add = ${if and { \ - {match{$domain}{$original_domain}} \ - {match{$local_part}{$original_local_part}} \ - } {X-Spam-Flag: YES\nX-Spam-Score: $acl_m_spam_score\nVEXIM_SPAM_REPORT_HEADER_NAME: $acl_m_spam_report}{} } - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + file_transport = virtual_ditch_spam_transport + data = ${lookup mysql{ \ + SELECT CONCAT(u.smtp , '/.Spam') \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + and d.enabled = '1' \ + and u.enabled = '1' \ + }} + condition = ${if >= \ + {$spam_score_int} \ + {${lookup mysql{ \ + SELECT u.sa_refuse * 10 \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.on_spamassassin = '1' \ + AND d.spamassassin = '1' \ + AND u.spam_drop = '0' \ + AND u.on_forward = '0' \ + AND u.type = 'local' \ + AND u.sa_refuse > 0 \ + }{$value}fail} \ + } \ + {yes}{no}} + headers_add = ${if \ + and { \ + {match{$domain}{$original_domain}} \ + {match{$local_part}{$original_local_part}} \ + } \ + {X-Spam-Flag: YES\nX-Spam-Score: $acl_m_spam_score\nVEXIM_SPAM_REPORT_HEADER_NAME: $acl_m_spam_report}{}} + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part ditch_hdrmailer: driver = redirect allow_fail data = :blackhole: - condition = ${if eq {${lookup mysql{select count(*) from blocklists,users,domains \ - where blocklists.blockhdr = 'x-mailer' \ - and blocklists.blockval = '${quote_mysql:$h_x-mailer:}' \ - and users.localpart = '${quote_mysql:$local_part}' \ - and domains.domain = '${quote_mysql:$domain}' \ - and domains.domain_id=blocklists.domain_id \ - and users.user_id=blocklists.user_id}}}{1} {yes}{no}} + condition = ${if eq \ + {1} \ + {${lookup mysql{\ + SELECT COUNT(*) \ + FROM blocklists b \ + INNER JOIN users u ON (u.user_id = b.user_id) \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE b.blockhdr = 'x-mailer' \ + AND b.blockval = '${quote_mysql:$h_x-mailer:}' \ + AND u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }}} \ + {yes}{no}} .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional @@ -698,13 +754,19 @@ ditch_hdrto: driver = redirect allow_fail data = :blackhole: - condition = ${if eq {${lookup mysql{select count(*) from blocklists,users,domains \ - where blocklists.blockhdr = 'to' \ - and blocklists.blockval = '${quote_mysql:$h_to:}' \ - and users.localpart = '${quote_mysql:$local_part}' \ - and domains.domain = '${quote_mysql:$domain}' \ - and domains.domain_id=blocklists.domain_id \ - and users.user_id=blocklists.user_id}}}{1} {yes}{no}} + condition = ${if eq \ + {1} \ + {${lookup mysql{ \ + SELECT COUNT(*) \ + FROM blocklists b \ + INNER JOIN users u ON (b.user_id = u.user_id) \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE b.blockhdr = 'to' \ + AND b.blockval = '${quote_mysql:$h_to:}' \ + AND u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }}} \ + {yes}{no}} .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional @@ -715,13 +777,19 @@ ditch_hdrfrom: driver = redirect allow_fail data = :blackhole: - condition = ${if eq {${lookup mysql{select count(*) from blocklists,users,domains \ - where blocklists.blockhdr = 'from' \ - and blocklists.blockval = '${quote_mysql:$h_from:}' \ - and users.localpart = '${quote_mysql:$local_part}' \ - and domains.domain = '${quote_mysql:$domain}' \ - and domains.domain_id=blocklists.domain_id \ - and users.user_id=blocklists.user_id}}}{1} {yes}{no}} + condition = ${if eq \ + {1} + {${lookup mysql{ \ + SELECT COUNT(*) \ + FROM blocklists b \ + INNER JOIN users u ON (b.user_id = u.user_id) \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE b.blockhdr = 'from' \ + AND b.blockval = '${quote_mysql:$h_from:}' \ + AND u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }}} \ + {yes}{no}} .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional @@ -732,13 +800,19 @@ ditch_hdrsubject: driver = redirect allow_fail data = :blackhole: - condition = ${if eq {${lookup mysql{select count(*) from blocklists,users,domains \ - where blocklists.blockhdr = 'subject' \ - and blocklists.blockval = '${quote_mysql:$h_subject:}' \ - and users.localpart = '${quote_mysql:$local_part}' \ - and domains.domain = '${quote_mysql:$domain}' \ - and domains.domain_id=blocklists.domain_id \ - and users.user_id=blocklists.user_id}}}{1} {yes}{no}} + condition = ${if eq { \ + {1} + ${lookup mysql{ \ + SELECT COUNT(*) \ + FROM blocklists b \ + INNER JOIN users u ON (b.user_id = u.user_id) \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE b.blockhdr = 'subject' \ + and b.blockval = '${quote_mysql:$h_subject:}' \ + and u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + }}} \ + {yes}{no}} .ifdef VEXIM_LOCALPART_SUFFIX local_part_suffix = VEXIM_LOCALPART_SUFFIX local_part_suffix_optional diff --git a/docs/debian-conf.d/router/249_vexim_ditch_routers b/docs/debian-conf.d/router/249_vexim_ditch_routers index 10bc7b8e..0d810624 100644 --- a/docs/debian-conf.d/router/249_vexim_ditch_routers +++ b/docs/debian-conf.d/router/249_vexim_ditch_routers @@ -4,82 +4,115 @@ # This router fails messages to accounts of type "fail", for which a suggested new email address is specified. ditch_551_fails: - driver = redirect - allow_fail - condition = ${if eq {${lookup mysql{select count(*) from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.type = 'fail' \ - and users.smtp != ':fail:' \ - and users.domain_id=domains.domain_id}}}{1} {yes}{no}} - data = :fail: 551 User not local; please try <\ - ${lookup mysql{select users.smtp from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.type = 'fail' \ - and users.smtp != ':fail:' \ - and users.domain_id=domains.domain_id}}> - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + condition = ${if eq \ + {1} \ + {${lookup mysql{ \ + SELECT COUNT(*) \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.type = 'fail' \ + AND u.smtp != ':fail:' \ + }}} \ + {yes}{no}} + data = :fail: 551 User not local; please try <\ + ${lookup mysql{ \ + SELECT u.smtp \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.type = 'fail' \ + AND u.smtp != ':fail:' \ + }}> + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part # This router fails messages to the remaining accounts of type "fail". ditch_550_fails: - driver = redirect - allow_fail - condition = ${if eq {${lookup mysql{select count(*) from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.type = 'fail' \ - and users.smtp = ':fail:' \ - and users.domain_id=domains.domain_id}}}{1} {yes}{no}} - data = :fail: Unrouteable address - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + condition = ${if eq \ + {1} \ + {${lookup mysql{ \ + SELECT COUNT(*) \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.type = 'fail' \ + AND u.smtp = ':fail:' \ + }}} \ + {yes}{no}} + data = :fail: Unrouteable address + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part ditch_maxmsgsize: - driver = redirect - allow_fail - condition = ${if >{$message_size}{${lookup mysql{select users.maxmsgsize from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.maxmsgsize > 0 \ - and users.domain_id=domains.domain_id }{${value}K}fail}} {yes}{no}} - data = :fail:\n\Your message is too big.\n \ - Your message was rejected because the user $local_part@$domain\n \ - does not accept messages larger than \ - ${lookup mysql{select users.maxmsgsize from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.maxmsgsize > 0 \ - and users.domain_id=domains.domain_id}{${value}K}fail} Kb. - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + condition = ${if > \ + {$message_size} \ + {${lookup mysql{ \ + SELECT u.maxmsgsize \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.maxmsgsize > 0 \ + }{${value}K}fail} \ + } + {yes}{no}} + data = :fail:\n\Your message is too big.\n \ + Your message was rejected because the user $local_part@$domain\n \ + does not accept messages larger than \ + ${lookup mysql{ \ + SELECT u.maxmsgsize \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + and u.maxmsgsize > 0 \ + }{${value}K}fail} Kb. + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part # malware drop router ditch_malware: - driver = redirect - allow_fail - data = :blackhole: - condition = ${if and { {match {$h_X-ACL-Warn:}{.*malware.*}} \ - {eq {${lookup mysql{select users.on_avscan from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_avscan = '1' \ - and domains.avscan = '1' \ - and users.domain_id=domains.domain_id}}}{1} }} {yes}{no} } - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif + driver = redirect + allow_fail + data = :blackhole: + condition = ${if and { \ + {match {$h_X-ACL-Warn:}{.*malware.*}} \ + {eq \ + {1} \ + {${lookup mysql{ \ + SELECT u.on_avscan \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.on_avscan = '1' \ + AND d.avscan = '1' \ + }}} \ + }} \ + {yes}{no}} + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif # This router caused me so much s*** it's untrue. # If your db lookup returns 'no data', then $spam_in_score is @@ -87,119 +120,160 @@ ditch_malware: # Eventually got this working with Philip Hazel and Codiac's help. # spam drop router ditch_spam_drop: - driver = redirect - allow_fail - data = :blackhole: - condition = ${if >={$spam_score_int}{${lookup mysql{select users.sa_refuse * 10 from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_spamassassin = '1' \ - and domains.spamassassin = '1' \ - and users.spam_drop = '1' \ - and users.domain_id=domains.domain_id \ - and users.sa_refuse > 0 }{$value}fail}} {yes}{no}} - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + data = :blackhole: + condition = ${if >= \ + {$spam_score_int} \ + {${lookup mysql{ \ + SELECT u.sa_refuse * 10 \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + and d.spamassassin = '1' \ + and u.on_spamassassin = '1' \ + and u.spam_drop = '1' \ + and u.sa_refuse > 0 \ + }{$value}fail} \ + } \ + {yes}{no}} + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part ditch_spam: - driver = redirect - allow_fail - file_transport = virtual_ditch_spam_transport - data = ${lookup mysql{select concat(smtp,'/.Spam') \ - from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and domains.enabled = '1' \ - and users.enabled = '1' \ - and users.domain_id = domains.domain_id}} - condition = ${if >={$spam_score_int}{${lookup mysql{select \ - users.sa_refuse * 10 from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.on_spamassassin = '1' \ - and domains.spamassassin = '1' \ - and users.spam_drop = '0' \ - and users.on_forward = '0' \ - and users.type = 'local' \ - and users.domain_id=domains.domain_id \ - and users.sa_refuse > 0 }{$value}fail}} {yes}{no}} - headers_add = ${if and { \ - {match{$domain}{$original_domain}} \ - {match{$local_part}{$original_local_part}} \ - } {X-Spam-Flag: YES\nX-Spam-Score: $acl_m_spam_score\nVEXIM_SPAM_REPORT_HEADER_NAME: $acl_m_spam_report}{} } - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + file_transport = virtual_ditch_spam_transport + data = ${lookup mysql{ \ + SELECT CONCAT(u.smtp , '/.Spam') \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + and d.enabled = '1' \ + and u.enabled = '1' \ + }} + condition = ${if >= \ + {$spam_score_int} \ + {${lookup mysql{ \ + SELECT u.sa_refuse * 10 \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + AND u.on_spamassassin = '1' \ + AND d.spamassassin = '1' \ + AND u.spam_drop = '0' \ + AND u.on_forward = '0' \ + AND u.type = 'local' \ + AND u.sa_refuse > 0 \ + }{$value}fail} \ + } \ + {yes}{no}} + headers_add = ${if \ + and { \ + {match{$domain}{$original_domain}} \ + {match{$local_part}{$original_local_part}} \ + } \ + {X-Spam-Flag: YES\nX-Spam-Score: $acl_m_spam_score\nVEXIM_SPAM_REPORT_HEADER_NAME: $acl_m_spam_report}{}} + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part ditch_hdrmailer: - driver = redirect - allow_fail - data = :blackhole: - condition = ${if eq {${lookup mysql{select count(*) from blocklists,users,domains \ - where blocklists.blockhdr = 'x-mailer' \ - and blocklists.blockval = '${quote_mysql:$h_x-mailer:}' \ - and users.localpart = '${quote_mysql:$local_part}' \ - and domains.domain = '${quote_mysql:$domain}' \ - and domains.domain_id=blocklists.domain_id \ - and users.user_id=blocklists.user_id}}}{1} {yes}{no}} - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + data = :blackhole: + condition = ${if eq \ + {1} \ + {${lookup mysql{\ + SELECT COUNT(*) \ + FROM blocklists b \ + INNER JOIN users u ON (u.user_id = b.user_id) \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE b.blockhdr = 'x-mailer' \ + AND b.blockval = '${quote_mysql:$h_x-mailer:}' \ + AND u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }}} \ + {yes}{no}} + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part ditch_hdrto: - driver = redirect - allow_fail - data = :blackhole: - condition = ${if eq {${lookup mysql{select count(*) from blocklists,users,domains \ - where blocklists.blockhdr = 'to' \ - and blocklists.blockval = '${quote_mysql:$h_to:}' \ - and users.localpart = '${quote_mysql:$local_part}' \ - and domains.domain = '${quote_mysql:$domain}' \ - and domains.domain_id=blocklists.domain_id \ - and users.user_id=blocklists.user_id}}}{1} {yes}{no}} - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + data = :blackhole: + condition = ${if eq \ + {1} \ + {${lookup mysql{ \ + SELECT COUNT(*) \ + FROM blocklists b \ + INNER JOIN users u ON (b.user_id = u.user_id) \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE b.blockhdr = 'to' \ + AND b.blockval = '${quote_mysql:$h_to:}' \ + AND u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }}} \ + {yes}{no}} + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part ditch_hdrfrom: - driver = redirect - allow_fail - data = :blackhole: - condition = ${if eq {${lookup mysql{select count(*) from blocklists,users,domains \ - where blocklists.blockhdr = 'from' \ - and blocklists.blockval = '${quote_mysql:$h_from:}' \ - and users.localpart = '${quote_mysql:$local_part}' \ - and domains.domain = '${quote_mysql:$domain}' \ - and domains.domain_id=blocklists.domain_id \ - and users.user_id=blocklists.user_id}}}{1} {yes}{no}} - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + data = :blackhole: + condition = ${if eq \ + {1} + {${lookup mysql{ \ + SELECT COUNT(*) \ + FROM blocklists b \ + INNER JOIN users u ON (b.user_id = u.user_id) \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE b.blockhdr = 'from' \ + AND b.blockval = '${quote_mysql:$h_from:}' \ + AND u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }}} \ + {yes}{no}} + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part ditch_hdrsubject: - driver = redirect - allow_fail - data = :blackhole: - condition = ${if eq {${lookup mysql{select count(*) from blocklists,users,domains \ - where blocklists.blockhdr = 'subject' \ - and blocklists.blockval = '${quote_mysql:$h_subject:}' \ - and users.localpart = '${quote_mysql:$local_part}' \ - and domains.domain = '${quote_mysql:$domain}' \ - and domains.domain_id=blocklists.domain_id \ - and users.user_id=blocklists.user_id}}}{1} {yes}{no}} - .ifdef VEXIM_LOCALPART_SUFFIX - local_part_suffix = VEXIM_LOCALPART_SUFFIX - local_part_suffix_optional - .endif - retry_use_local_part + driver = redirect + allow_fail + data = :blackhole: + condition = ${if eq { \ + {1} + ${lookup mysql{ \ + SELECT COUNT(*) \ + FROM blocklists b \ + INNER JOIN users u ON (b.user_id = u.user_id) \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE b.blockhdr = 'subject' \ + and b.blockval = '${quote_mysql:$h_subject:}' \ + and u.localpart = '${quote_mysql:$local_part}' \ + and d.domain = '${quote_mysql:$domain}' \ + }}} \ + {yes}{no}} + .ifdef VEXIM_LOCALPART_SUFFIX + local_part_suffix = VEXIM_LOCALPART_SUFFIX + local_part_suffix_optional + .endif + retry_use_local_part From 8d96e1e648a5428ea28b7ec6f67d9d5fe478af2a Mon Sep 17 00:00:00 2001 From: Rimas Kudelis Date: Tue, 23 Jan 2024 16:12:32 +0200 Subject: [PATCH 5/8] Reformat SQL queries in transports --- docs/configure | 43 +++++++++++-------- .../30_vexim_virtual_ditch_spam_transport | 22 ++++++---- .../30_vexim_virtual_vacation_delivery | 21 +++++---- 3 files changed, 52 insertions(+), 34 deletions(-) diff --git a/docs/configure b/docs/configure index 7d50610f..302a3ccd 100644 --- a/docs/configure +++ b/docs/configure @@ -1133,15 +1133,18 @@ virtual_delivery: Please take note of this and remove unwanted mail from your mailbox.\n" virtual_vacation_delivery: - driver = autoreply - from = "${local_part}@${domain}" - to = ${sender_address} - subject = "Autoreply from ${local_part}@${domain}" - headers = "Content-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: quoted-printable" - text = ${lookup mysql{select vacation from users,domains \ - where domain='${quote_mysql:$domain}' \ - and localpart='${quote_mysql:$local_part}' \ - and users.domain_id=domains.domain_id}} + driver = autoreply + from = "${local_part}@${domain}" + to = ${sender_address} + subject = "Autoreply from ${local_part}@${domain}" + headers = "Content-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: quoted-printable" + text = ${lookup mysql{ \ + SELECT u.vacation \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE d.domain='${quote_mysql:$domain}' \ + AND u.localpart='${quote_mysql:$local_part}' \ + }} virtual_ditch_spam_transport: driver = appendfile @@ -1150,14 +1153,20 @@ virtual_ditch_spam_transport: mode = 0600 maildir_format = true create_directory = true - user = ${lookup mysql{select users.uid from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.domain_id = domains.domain_id}} - group = ${lookup mysql{select users.gid from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.domain_id = domains.domain_id}} + user = ${lookup mysql{ \ + SELECT u.uid \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }} + group = ${lookup mysql{ \ + SELECT u.gid \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }} maildir_use_size_file = false diff --git a/docs/debian-conf.d/transport/30_vexim_virtual_ditch_spam_transport b/docs/debian-conf.d/transport/30_vexim_virtual_ditch_spam_transport index 47b5c7df..d158890e 100644 --- a/docs/debian-conf.d/transport/30_vexim_virtual_ditch_spam_transport +++ b/docs/debian-conf.d/transport/30_vexim_virtual_ditch_spam_transport @@ -9,12 +9,18 @@ virtual_ditch_spam_transport: mode = 0600 maildir_format = true create_directory = true - user = ${lookup mysql{select users.uid from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.domain_id = domains.domain_id}} - group = ${lookup mysql{select users.gid from users,domains \ - where localpart = '${quote_mysql:$local_part}' \ - and domain = '${quote_mysql:$domain}' \ - and users.domain_id = domains.domain_id}} + user = ${lookup mysql{ \ + SELECT u.uid \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }} + group = ${lookup mysql{ \ + SELECT u.gid \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE u.localpart = '${quote_mysql:$local_part}' \ + AND d.domain = '${quote_mysql:$domain}' \ + }} maildir_use_size_file = false diff --git a/docs/debian-conf.d/transport/30_vexim_virtual_vacation_delivery b/docs/debian-conf.d/transport/30_vexim_virtual_vacation_delivery index b1d8ec32..05ef058a 100644 --- a/docs/debian-conf.d/transport/30_vexim_virtual_vacation_delivery +++ b/docs/debian-conf.d/transport/30_vexim_virtual_vacation_delivery @@ -3,12 +3,15 @@ ####################################### virtual_vacation_delivery: - driver = autoreply - from = "${local_part}@${domain}" - to = ${sender_address} - subject = "Autoreply from ${local_part}@${domain}" - headers = "Content-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: quoted-printable" - text = ${lookup mysql{select vacation from users,domains \ - where domain='${quote_mysql:$domain}' \ - and localpart='${quote_mysql:$local_part}' \ - and users.domain_id=domains.domain_id}} + driver = autoreply + from = "${local_part}@${domain}" + to = ${sender_address} + subject = "Autoreply from ${local_part}@${domain}" + headers = "Content-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: quoted-printable" + text = ${lookup mysql{ \ + SELECT u.vacation \ + FROM users u \ + INNER JOIN domains d ON (u.domain_id = d.domain_id) \ + WHERE d.domain='${quote_mysql:$domain}' \ + AND u.localpart='${quote_mysql:$local_part}' \ + }} From 979fc29c1e852c99263bd0d99980427489366b22 Mon Sep 17 00:00:00 2001 From: Rimas Kudelis Date: Tue, 23 Jan 2024 16:13:15 +0200 Subject: [PATCH 6/8] Reformat SQL query in vexim-acl-check-rcpt --- docs/vexim-acl-check-rcpt.conf | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/vexim-acl-check-rcpt.conf b/docs/vexim-acl-check-rcpt.conf index 70ba05ea..955624ba 100644 --- a/docs/vexim-acl-check-rcpt.conf +++ b/docs/vexim-acl-check-rcpt.conf @@ -47,9 +47,15 @@ # deny hosts = ! +relay_from_hosts -# condition = ${if eq {${lookup mysql{select count(*) from domains \ -# where domain = '${quote_mysql:$domain}' \ -# and spamassassin='1'}}}{1} {yes}{no}} +# condition = ${if eq \ +# {1} \ +# {${lookup mysql{ \ +# SELECT COUNT(*) \ +# FROM domains \ +# WHERE domain = '${quote_mysql:$domain}' \ +# AND spamassassin='1' \ +# }}} \ +# {yes}{no}} # !acl = spf_rcpt_acl From 468e653a9b6032876dc7f5eafab414a3e66d17c8 Mon Sep 17 00:00:00 2001 From: Rimas Kudelis Date: Tue, 23 Jan 2024 16:46:14 +0200 Subject: [PATCH 7/8] Add missing backslashes --- docs/debian-conf.d/router/249_vexim_ditch_routers | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/debian-conf.d/router/249_vexim_ditch_routers b/docs/debian-conf.d/router/249_vexim_ditch_routers index 0d810624..a89d688d 100644 --- a/docs/debian-conf.d/router/249_vexim_ditch_routers +++ b/docs/debian-conf.d/router/249_vexim_ditch_routers @@ -70,7 +70,7 @@ ditch_maxmsgsize: AND d.domain = '${quote_mysql:$domain}' \ AND u.maxmsgsize > 0 \ }{${value}K}fail} \ - } + } \ {yes}{no}} data = :fail:\n\Your message is too big.\n \ Your message was rejected because the user $local_part@$domain\n \ @@ -237,7 +237,7 @@ ditch_hdrfrom: allow_fail data = :blackhole: condition = ${if eq \ - {1} + {1} \ {${lookup mysql{ \ SELECT COUNT(*) \ FROM blocklists b \ @@ -260,7 +260,7 @@ ditch_hdrsubject: allow_fail data = :blackhole: condition = ${if eq { \ - {1} + {1} \ ${lookup mysql{ \ SELECT COUNT(*) \ FROM blocklists b \ From 2969c679d7ffbf6b6a8a1126abf4d24412507a9f Mon Sep 17 00:00:00 2001 From: Rimas Kudelis Date: Tue, 23 Jan 2024 23:05:00 +0200 Subject: [PATCH 8/8] Fix curly brace position in condition --- docs/debian-conf.d/router/249_vexim_ditch_routers | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/debian-conf.d/router/249_vexim_ditch_routers b/docs/debian-conf.d/router/249_vexim_ditch_routers index a89d688d..03758bcd 100644 --- a/docs/debian-conf.d/router/249_vexim_ditch_routers +++ b/docs/debian-conf.d/router/249_vexim_ditch_routers @@ -259,9 +259,9 @@ ditch_hdrsubject: driver = redirect allow_fail data = :blackhole: - condition = ${if eq { \ + condition = ${if eq \ {1} \ - ${lookup mysql{ \ + {${lookup mysql{ \ SELECT COUNT(*) \ FROM blocklists b \ INNER JOIN users u ON (b.user_id = u.user_id) \