### Confiugrazione per Exim4 ### Realizzata da Kurgan (kurgan at kurgan dot org) ### versione del 30/11/2024 (Waiting for WW3) ### Compatibile Debian 12 ### Exim versione 4.96 o superiore (se non fanno qualche altro casino in Exim. comincio a odiarli). ### NON COMPATIBILE CON EXIM PRECEDENTI (E PROBABILMENTE ANCHE CON I SUCCESSIVI) ## ## MODIFICARE QUESTE IMPOSTAZIONI PER LA VOSTRA INSTALLAZIONE ## # Indirizzo mail del postmaster per tutti i domini gestiti dal server. # NON USARE un utente che sia "postmaster@ # altrimenti si crea un loop. POSTMASTER=postmaster@ilvostrodominio.tld # dove si trovano i files delle mailbox MAIL=/var/vmail # dove si trova la configurazione di exim4 EXIM4=/etc/exim4 # Dove si trovano le chiavi per DKIM DKIM_PATH = EXIM4/dkim # dove si trovano i files di configurazione degli utenti dei domini virtuali VIRTUALS=/etc/vmail # white e black list degli host da cui accettare connessioni SMTP # Gli indirizzi in whitelist saltano TUTTI I CONTROLLI. Fate attenzione. WHITELIST=EXIM4/white.list BLACKLIST=EXIM4/black.list # whitelist dedicata SOLO al greylisting. Se si usa il greylisting # (vedi sotto) allora i netblock in questa lista non sono soggetti # al greylisting. Serve per non avere ritardi mostruosi sulle email # provenienti da sistemi che hanno decine di server SMTP e li ruotano, # tipo i soliti maledetti google e microsoft. # vedi: https://kb.kurgan.org/LinuxDebian/GreyListd NOGREYLIST=EXIM4/nogrey.list # gli alias per i soli utenti di sistema della macchina SYS_ALIASES=/etc/aliases # Il livello di spam oltre il quale spamassassin rifiuta lo spam a livello smtp # in qualsiasi caso (moltiplicato per 10!) (metterlo a 65534 e` come dire # che lo spam riconosciuto come tale per contenuto non viene mai rifiutato # a livello SMTP ma viene sempre accettato e marcato) SPAM_SCORE_DENY=100 # Il livello di spam oltre il quale marco il messaggio come spam pero` lo accetto # comunque (lo rifiuto pero` se il livello supera "SPAM_SCORE_DENY" indicato sopra) # La marcatura setta acl_m5 a 1 e consente poi di filtrare il messaggio in un filtro SPAM_SCORE_MARK=50 # Voglio che il check del mittente setti un warning o rifiuti la mail in caso # di mittente inesistente? (usare "warn", "refuse" o "none" per disattivarlo) # il check del mittente e` considerato pratica erronea, anche se funziona, # quindi e` meglio disattivarlo per essere dei "buoni cittadini di internet" SPAM_CHECK_SENDER_ADDRESS=none # Voglio verificare che il DOMINIO del mittente esita? A differenza del check # precedente, questo non effettua nessuna connessione al mail server del mittente # ma si basa solo sul DNS. Questo check non è "pratica non gradita" e quindi # lo posso usare senza problemi. # (usare "warn", "refuse" o "none" per disattivarlo) SPAM_CHECK_SENDER_DOMAIN=refuse # Configurazione delle blacklist per INDIRIZZO IP # Voglio che il check delle RBL setti un warning o rifiuti la mail in caso # il cui l'ip del mittente sia in una RBL? (usare "warn" o "refuse" o "none") SPAM_CHECK_RBL=refuse # Configurazione delle blacklist per INDIRIZZO IP # Quali RBL uso per il check precedente (barracudacentral vuole una registrazione ma funziona lo stesso a quanto pare) # per spamhaus questa nuova configurazione che comprende "!&0.255.255.0" ha lo scopo di ignorare # le risposte che contengono qualsiasi bit settato a 1 nel secondo e terzo gruppo. Di fatto accetta solo 127.0.0.XXX # Il motivo è che spamhaus quando decide che sei cattivo e usi il servizio a sbafo ti risponde semmpre 127.255.255.x # e in quel caso è meglio che lo spam passi piuttosto che bloccare tutto indistintamente. # SPAM_RBL_DNSLIST=zen.spamhaus.org : b.barracudacentral.org SPAM_RBL_DNSLIST=zen.spamhaus.org!&0.255.255.0 : b.barracudacentral.org # Configurazione delle blacklist per DOMINIO DEL MITTENTE (MAIL FROM) # Uso della RBL "DBL" di Spamhaus che si basa sui nomi di dominio e non sugli # indirizzi IP: (usare "warn", "refuse" o "none" per disattivarlo) SPAM_CHECK_DOMAIN=refuse # Configurazione delle blacklist per DOMINIO DEL MITTENTE (MAIL FROM) # Elenco delle RBL che uso per il controllo del dominio del mittente: # Notare che qui devo indicare ogni lista con la stringa "/$sender_address_domain" in coda. # Se ho diverse entry, le separo con un ":", ad esempio come segue: # SPAM_DBL_LIST=lista1/$sender_address_domain : lista2/$sender_address_domain # Vedi immediatamente sopra per il motivo del "!&0.255.0.0" aggiunto. In questo caso le risposte corrette sono # 127.0.1.X e gli errori sono sempre 127.255.255.X. SPAM_DBL_DNSLIST=dbl.spamhaus.org!&0.255.0.0/$sender_address_domain # Abilita la funzionalita` di greylisting usando greylistd. (usare "enabled" o "disabled") # Richiede che graylistd sia installato e configurato. Se non usate Debian, # controllate i permessi e il path del socket di graylistd. GREYLISTING=disabled # Scelta del trasporto da usare per il delivery locale agli utenti dei domini virtuali. # Se si vogliono usare i filtri sieve, occorre usare il delivery che passa per Dovecot LDA # Altrimenti si puo` usare il delivery interno di exim. # Le scelte possibili sono: # - virtual_user_delivery per quello interno di Exim # - virtual_user_dovecot_delivery per l' LDA di Dovecot con il supporto per Sieve # vedasi https://kb.kurgan.org/LinuxDebian/Dovecot-Sieve # VIRTUAL_DELIVERY = virtual_user_delivery VIRTUAL_DELIVERY = virtual_user_dovecot_delivery # Rate limit: per limitare il rischio di spam da parte di un account compromesso # vengono applicati dei rate limit al numero di email inviate per periodo di tempo, # a mezzo delle ACL "ratelimit". Qui sono hardcoded i default, che possono poi essere # modificati (per gli utenti autenticati) nel file di definizione degli utenti. # Per gli utenti autenticati: 40 email ogni 5 minuti RATELIMIT_LIMIT=40 RATELIMIT_TIME=5m # Per gli host che possono fare relay e non sono utenti autenticati. (Se sono autenticati # si applica la regola precedente in ogni caso). Se serve che un host superi questi valori # mettere l'host in whitelist. RATELIMIT_HOST_LIMIT=40 RATELIMIT_HOST_TIME=5m # Per l'allarme in caso di superamento del rate limit: indirizzo email a cui mandare un allarme RATELIMIT_ALARM_RECEIVER=indirizzo@email.tld # Variabile interna per definire il numero di campi separati da ":" nel file degli utenti # La versione "minimale" prevede 3 campi: username:password:parametri (opzionali) e # quindi il numero di ":" per arrivare ai parametri opzionali e` 2. # Se uso la modifica per le quote, dovecot mi obbliga a 8 campi, di cui sono usati solo # il primo, il secondo, e l'ottavo. In questo caso il numero di ":" diventa 7. # Questo parametro non va modificato se non si sa cosa si sta facendo. # Usare "2" per un file utenti cosi` fatto: # username:password:parametri opzionali # Usare "7" per un file utenti cosi` fatto: # username:password::::::parametri opzionali USERFILE_FIELDS=2 # # Disabilitare il supporto per ipv6 e` suggerito per riuscire # a mandare email a gmail, almeno per il momento. # Se mandi da ipv6 sei molto più mal visto. Occorre avere SPF, DKIM, DMARC, e RDNS anche per v6. # E comunque se la tua /64 va in blacklist sei fregato. Siccome molti provider di VPS non ti danno una /64 # ma solo un inidirizzo unico (una /128) non hai controllo sullo schifo prodotto dai tuoi vicini e quindi sarai # sempre in blacklist in v6. Morale: v6 crea sempre e solo problemi. Non usarlo per la mail. # disable_ipv6=true # Porte sulle quali ascolta l' SMTP. # Uso la 25 e la 587 (submit) e la 465 per smtps. # daemon_smtp_ports=25 : 587 : 465 tls_on_connect_ports = 465 # Se il vostro mail server e` dietro ad un NAT e` meglio inserire qui l' IP pubblico # del NAT, in modo da evitare che il mail server si mandi la mail da solo creando un loop. # questo problema si verifica tipicamente sull' MX secondario quando il primario e` down. # #hosts_treat_as_local = 1.2.3.4 # hostname della macchina e dominio locale # Il dominio locale idealmente non va usato per gli utenti # ma solo per servizio. Notare: il dominio locale è "host.dominio.tld" e non # dominio.tld, quindi va benissimo avere "mail.test.com" per servire le email # degli utenti del dominio "test.com" (che non e` uguale a "mail.test.com) # entrambi questi parametri ha senso che sian impostati al valore dell'hostname della macchina. # primary_hostname = hostname.ilvostrodominio.tld qualify_domain = hostname.ilvostrodominio.tld # domini per i quali faccio relay ma non sono locali (lasciare vuoto, ovvero non scrivere nulla # dopo il carattere "=", per non fare relay per nessun dominio a parte i locali) # esempio: domainlist relay_to_domains = dominio1.com : dominio2.it domainlist relay_to_domains = # host per i quali faccio relay (i miei client in LAN, volendo, o altri ip pubblici "fidati") hostlist relay_from_hosts = 127.0.0.1/32 : ::::1 # se questo file e` presente, exim blocca il delivery contestuale alla ricezione. # lo uso come "stop" in caso di allarme sul rate limit. In realta` non e` # uno stop quanto un delay, perche` ad ogni queue run comunque la mail esce. # se volessi un vero stop dovrei fermare exim. queue_only_file = /tmp/exim_queue_only # Configurazione dello scanner antivirus. Indica che scanner uso # e come contattarlo. Qui uso clamd (daemon di clamav) su socket locale. av_scanner = clamd:/var/run/clamav/clamd.ctl # Se spamd usa il socket e non la porta tcp, questa riga va scommentata. Se # volete usare la porta tcp di default su localhost potete commentare questa riga. spamd_address = /var/run/spamd.ctl # trusted_users contiene anche www-data se si usa una webmail che ne ha bisogno. # altrimenti si puo` anche togliere never_users = root trusted_users = mail : www-data # Disattivo le richieste ident, tanto quasi nessuno le onora. # rfc1413_hosts = * rfc1413_query_timeout = 0s # limiti sul file system per non ingrippare la macchina, e sulle dimensioni delle mail # e dei bounce check_spool_space = 100M return_size_limit = 10k message_size_limit = 100M # limiti sulle sessioni smtp. smtp_accept_max_per_connection = 100 smtp_accept_queue = 150 # configurazioni dei retry delle mail fallite e dell'eliminazione di quelle che non si # riescono a consegnare ignore_bounce_errors_after = 2d timeout_frozen_after = 7d auto_thaw = 12h # Logging verboso # log_selector = +address_rewrite +all_parents +delivery_size +received_recipients +received_sender +subject # logging molto verboso (da usarsi al posto di quella di prima) log_selector = +all -arguments # Configurazione SSL server (per smtps o STARTTLS) # dove si trovano i certificati SSL SSL_CERT_PATH = /etc/letsencrypt # Quale certificato uso per default se non c'e` SNI (hostname nella richiesta di connessione) # verrà composto un nome file tipo SSL_CERT_PATH/SSL_CERT_DEFAULT.cert per il certificato e # .key per la chiave. # Usare l'hostname principale del vostro mail server (mail.pippo.com per esempio) SSL_CERT_DEFAULT=hotstname.dominio.tld # scommentare tutte le righe per attivare SSL dopo aver generato i cert validi necessari #tls_certificate = ${if exists{SSL_CERT_PATH/${lc:$tls_sni}.cert} {SSL_CERT_PATH/${lc:$tls_sni}.cert}{SSL_CERT_PATH/SSL_CERT_DEFAULT.cert}} #tls_privatekey = ${if exists{SSL_CERT_PATH/${lc:$tls_sni}.key} {SSL_CERT_PATH/${lc:$tls_sni}.key}{SSL_CERT_PATH/SSL_CERT_DEFAULT.key}} #tls_advertise_hosts = * #tls_try_verify_hosts = * # siccome ci sono host remoti che non rispettano gli standard, mi piego # a non rispettarli nemmeno io, consentendo l'invio di mail a un MX # indicato nel DNS con l' ip e non con l'hostname. allow_mx_to_ip = true # Facoltativo: non consente auth sulla 25 (ma sulle altre porte si) a meno che la connessione non sia da localhost # Questa config potrebbe servire se vogliamo esporre la 25 ma non consentire tentativi # di auth sulla medesima, senza esporre la 587 e la 465 che invece supporta auth auth_advertise_hosts = ${if eq {$interface_port}{25} {127.0.0.1 : ::::1}{*}} ################################################################## ################################################################## ## Fine della parte di configurazione che va modificata ## ## per installare Exim. Da qui in poi dovrebbe andare bene ## ## cosi` come e`. ## ################################################################## ################################################################## # Tento di nascondere che MTA uso, magari aiuta contro eventuali # attacchi zero-day. smtp_banner="ESMTP server ready" # Exim 4.86.2-2 e successivi, introducono questi due parametri. Se non li valorizzo # (anche vuoti) Exim scrive warning dappertutto. Questa configurazione funziona anche # con l'environment piallato totalmente, comunuqe ci mettiamo una cosa sensata. # (non tiene nulla dell'environment del chiamante, e ci mette il path standard) add_environment = <; PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # add_environment = <; PATH=/bin:/usr/bin keep_environment = # Configurazione delle ACL acl_smtp_rcpt = acl_check_rcpt acl_smtp_data = acl_check_contents acl_smtp_mime = acl_check_mime # I virtuali sono definiti come nomi di files in una directory. Il dominio e` locale # se esiste nella directory VIRTUALS un file che si chiama come il dominio. # Qui non occorre specificare il nome della macchina, che viene preso gia` # in considerazione (nei posti giusti) usando quello indicato prima in # "$primary_hostname". Lo stesso vale per "localhost". domainlist local_domains = dsearch;VIRTUALS/users ###################################################################### # ACL CONFIGURATION # # Specifies access control lists for incoming SMTP mail # ###################################################################### # NOTA: un "accept" o un "deny" che matchano le condizioni # provocano l'accettazione o il rifiuto della mail immediatamente, # quindi tutte le condizioni che seguono in ordine di apparizione # vengono totalmente ignorate. begin acl # Questa ACL viene verificata al momento in cui il remoto mi manda il comando "RCPT TO" acl_check_rcpt: # Deny if the local part contains @ or % or / or | or !. These are rarely # found in genuine local parts, but are often tried by people looking to # circumvent relaying restrictions. deny local_parts = ^.*[@%!/|] # salvo in due variabili domain e local_part del destinatario, mi serviranno # nella acl successiva per decidere se fare o meno il controllo dello spam. # per farlo uso una acl "warn" alla quale dico di settare due variabili senza # fare alcuna altra azione. # UNTAINT: Dovendo usare acl_m1 in seguito per fare dei lookup su file, devo # renderla non tainted. Il trucco e` validare il dominio contro la lista # local_domains, e settare acl_m1 a $domain_data # Nota: se il dominio non e` locale o relay_to non ho bisogno di queste variabili, # non le uso in nessuna acl nel caso in cui il dominio non sia locale) # Quindi se non le setto (per domini non locali) non succede niente. # Nota bene: acl_m0 che viene da local_part rimante TAINTED warn domains = +local_domains : +relay_to_domains : $primary_hostname : localhost : lsearch;VIRTUALS/domain_aliases set acl_m0 = $local_part set acl_m1 = $domain_data # Whitelist / Blacklist accept hosts = ${if exists{WHITELIST}{WHITELIST}{}} set acl_c0 = no_spam_check deny hosts = ${if exists{BLACKLIST}{BLACKLIST}{}} # Rate limt per gli utenti autenticati: si applica solo agli utenti # autenticati, da qualsiasi host provengano (conta lo username, # non l'host di provenienza) # Legge, se ci sono, due parametri ratelimit_limit e ratelimit_time # dal file degli utenti e applica questi limiti Se non ci sono usa # i valori hard-coded all'inizio del file di configurazione. # la mostruosa stringa qui sotto si traduce di fatto in una chiamata # a ratelimit cosi` fatta: # ratelimit = limite / tempo / strict / $authenticated_id. # La complessita` sta nel fatto di leggere i valori per limite e tempo # dal file degli utenti per ogni utente e gestire il fallback al default # in assenza di questi valori. # Questa ACL blocca l'invio di ulteriore mail fino a che non si scende # sotto il rate limit impostato, inoltre manda una mail usando # lo script indicato nella riga "continue" ad un indirizzo codificato # all'inizio del file di configurazione (RATELIMIT_ALARM_RECEIVER). # Lo script puo` anche creare un file che inibisce il delivery delle email, # file che andra` cancellato a mano dopo essere intervenuti sul # problema. Questo file pero` non impedisce il delivery ogni tot minuti # che fa exim (vedi /etc/default/exim4) e quindi non impedisce l'eventuale # delivery dello spam ma lo ritarda solo di un poco. # UNTAINT: setto e uso acl_m6 che e` UNTAINTED partendo da authenticated_id # e confrontandolo con i domini virtuali. deny authenticated = * set acl_m6 = ${lookup {${domain:$authenticated_id}} dsearch,filter=file {VIRTUALS/users}} ratelimit = ${extract{ratelimit_limit} {${extract{USERFILE_FIELDS}{:} {${lookup {${local_part:$authenticated_id}} lsearch {VIRTUALS/users/$acl_m6}}} }}{$value}{RATELIMIT_LIMIT} } / ${extract{ratelimit_time} {${extract{USERFILE_FIELDS}{:} {${lookup {${local_part:$authenticated_id}} lsearch {VIRTUALS/users/$acl_m6}}} }}{$value}{RATELIMIT_TIME} } / strict / $authenticated_id log_message = RATELIMIT AUTH: $authenticated_id $sender_host_address - $sender_rate/$sender_rate_period (max $sender_rate_limit) message = Utente bloccato per eccessivo invio di email. Rivolgesri all'amministratore del sistema continue = ${run{/bin/bash -c "EXIM4/ratelimitalert.sh RATELIMIT_ALARM_RECEIVER $authenticated_id $sender_host_address $sender_rate $sender_rate_period $sender_rate_limit"}} # Rate limt per gli host nella LAN: si applica agli host che possono fare relay # e non usano autenticazione. Se invece usano l'autenticazione, allora questa # non si applica e si applica la precedente. # Se occorre che un host non sia limitato da questa regola, va messo in whitelist. # Se dovesse servire in futuro rendero` questa regola configurabile per ogni host # in modo diverso, ma per ora non ne ho voglia. deny hosts = +relay_from_hosts !authenticated = * ratelimit = RATELIMIT_HOST_LIMIT / RATELIMIT_HOST_TIME / strict / $sender_host_address log_message = RATELIMIT HOST: $sender_host_address - $sender_rate/$sender_rate_period (max $sender_rate_limit) message = Host bloccato per eccessivo invio di email. Rivolgesri all'amministratore del sistema continue = ${run{/bin/bash -c "EXIM4/ratelimitalert.sh RATELIMIT_ALARM_RECEIVER '' $sender_host_address $sender_rate $sender_rate_period $sender_rate_limit"}} # Accept if the source is local SMTP (i.e. not over TCP/IP). We do this by # testing for an empty sending host field. # Qui dovro` ragionare sul rate limit. # la riga control=submission aggiunge headers se mancano nel messaggio (data e id) # ed ha senso metterla perché molti programmi non mettono tutti gli header correttamente. accept hosts = : control = submission/sender_retain # Se la mail viene dagli host dai quali accetto il relay (tipicamente la mia LAN) # la accetto e setto una variabile per evitare di fare il check dello spam # sui messaggi che vengono dalla mia rete. accept hosts = +relay_from_hosts set acl_c0 = no_spam_check control = submission/sender_retain # Accept mail to postmaster and other administrative addresses in any local domain, # regardless of the source, and without verifying the sender. accept local_parts = postmaster : bayes : revoke domains = +local_domains : +relay_to_domains : $primary_hostname : localhost : lsearch;VIRTUALS/domain_aliases # Se il destinatario e` listato nel file VIRTUALS/allowed_recipients allora # lo accetto comunque, ignorando tutti i controlli sul mittente. accept recipients = ${if exists{VIRTUALS/allowed_recipients}{VIRTUALS/allowed_recipients}{}} set acl_c0 = no_spam_check # Se la mail viene da un client autenticato, la accetto comunque. # Inoltre imposto una variabile che usero` per saltare la scansione antispam della mail # proveniente da una connessione autenticata, che ritengo sicura. accept authenticated = * set acl_c0 = no_spam_check control = submission/sender_retain # Rifiuta se non c'e' l'HELO deny message = HELO/EHLO required by SMTP RFC condition = ${if eq{$sender_helo_name}{}{yes}{no}} # Rifiuta se l'IP in HELO e' uguale al mio... deny message = My IP detected in HELO condition = ${if eq{$sender_helo_name}{$interface_address}{yes}{no}} # Rifiuta se l'hostname usato in HELO e' il mio deny message = Forged hostname detected in HELO !authenticated = * condition = ${if match_domain{$sender_helo_name}{+local_domains}{yes}{no}} # Solo un destinatario se il mittente e' nullo deny message = Only one recipient accepted for NULL sender senders = : condition = ${if >{$rcpt_count}{1} {1}} # Verifica del reverse DNS. Richiede che il record PTR per l'ip del mittente coincida con almeno uno # degli ip del record A. Questa funzione è un test quindi scrivo nel log ma non blocco la mail. # non so se ha senso tenerla, renderla bloccante, o cosa. # se il DNS non risponde lascio passare. warn !verify = reverse_host_lookup/defer_ok log_message = RDNS test failed, PTR $sender_host_address and A $sender_host_name do not match. # Blacklist per indirizzo IP del mittente: # RBL Check (se non e` nella lista degli host da cui faccio relay, ovvero la mia LAN, # allora controllo presso i vari provider di RBL e poi rejecto con un messaggio personalizzabile) deny hosts = ! +relay_from_hosts condition = ${if eq {SPAM_CHECK_RBL} {refuse} {true}{false}} dnslists = SPAM_RBL_DNSLIST log_message = RBL check: IP address $sender_host_address found in black list at $dnslist_domain with result $dnslist_value message = rejected because $sender_host_address is in a black list at $dnslist_domain # Blacklist per indirizzo IP del mittente: # Altro tipo di RBL check, come prima ma la mail viene accettata comunque, con un # warning in un header e l'impostazione della variabile acl_m5, utile se si vuole # usare il router che salva lo spam in un folder imap separato. warn message = X-Warning: $sender_host_address is in a black list at $dnslist_domain condition = ${if eq {SPAM_CHECK_RBL} {warn} {true}{false}} hosts = ! +relay_from_hosts log_message = RBL check: IP address $sender_host_address found in black list at $dnslist_domain with result $dnslist_value dnslists = SPAM_RBL_DNSLIST set acl_m5 = 1 # Blacklist per DOMINIO del mittente: # RBL Check (se non e` nella lista degli host da cui faccio relay, ovvero la mia LAN, # allora controllo presso i vari provider di RBL e poi rejecto con un messaggio personalizzabile) deny hosts = ! +relay_from_hosts condition = ${if eq {SPAM_CHECK_DOMAIN} {refuse} {true}{false}} dnslists = SPAM_DBL_DNSLIST log_message = RBL check: domain $sender_address_domain found in black list at $dnslist_domain with result $dnslist_value message = rejected because the domain $sender_address_domain is in a black list at $dnslist_domain # Blacklist per DOMINIO del mittente: # Altro tipo di RBL check, come prima ma la mail viene accettata comunque, con un # warning in un header e l'impostazione della variabile acl_m5, utile se si vuole # usare il router che salva lo spam in un folder imap separato. warn message = X-Warning: domain $sender_address_domain is in a black list at $dnslist_domain condition = ${if eq {SPAM_CHECK_DOMAIN} {warn} {true}{false}} hosts = ! +relay_from_hosts log_message = RBL check: domain $sender_address_domain found in black list at $dnslist_domain with result $dnslist_value dnslists = SPAM_DBL_DNSLIST set acl_m5 = 1 # Verifico se il dominio del mittente esiste verificando semplicemente se ha un record DNS # Se il domnio non esiste, rifiuto la mail. Nota: non verifico se esiste l'indirizzo email # ma solo il dominio del mittente. Questa pratica è "safe" e la posso usare senza patemi. deny condition = ${if eq {SPAM_CHECK_SENDER_DOMAIN} {refuse} {true}{false}} !verify = sender # Variante del controllo precedente che imposta un header se il dominio del mittente non esiste warn condition = ${if eq {SPAM_CHECK_SENDER_DOMAIN} {warn} {true}{false}} !verify = sender message = X-Warning: sender domain verify failed: $acl_verify_message hosts = ! +relay_from_hosts log_message = sender domain verify failed: $acl_verify_message set acl_m5 = 1 # Verifico se il mittente esiste facendo una chiamata al suo mail server e fingendo di # volergli mandare una mail. Se il mittente non esiste, rifiuto la mail. Se il suo mail server # non risponde, la accetto lo stesso. Questa pratica non è considerata civile quindi meglio # non usarla. deny condition = ${if eq {SPAM_CHECK_SENDER_ADDRESS} {refuse} {true}{false}} !verify = sender/callout=10s,connect=5s/defer_ok # Variante del controllo precedente che imposta un header se il mittente non esiste (2010-01-13) # imposta anche la variabile acl_m5 per indicare che un controllo antispam ha dato esito positivo # Questa pratica non è considerata civile quindi meglio non usarla. warn condition = ${if eq {SPAM_CHECK_SENDER_ADDRESS} {warn} {true}{false}} !verify = sender/callout=10s,connect=5s/defer_ok message = X-Warning: sender address verify failed: $acl_verify_message hosts = ! +relay_from_hosts log_message = sender address verify failed: $acl_verify_message set acl_m5 = 1 # Controllo del record SPF del mittente, in test a novembre 2024 # vedi https://www.exim.org/exim-html-current/doc/html/spec_html/ch-dkim_spf_srs_and_dmarc.html # Se il mittente ha un record SPF ed è impostato con un "-", quindi per # dire ai riceventi di non accettare mail da quel dominio, allora io non accetto mail da quel # dominio a meno che non passi il controllo SPF deny spf = fail : softfail message = SPF validation failed: \ $sender_host_address is not allowed to send mail from ${if def:sender_address_domain {$sender_address_domain}{$sender_helo_name}} log_message = SPF validation failed: \ ${if eq{$spf_result}{softfail} { (softfail)}{}}: $sender_host_address is not allowed to send mail from ${if def:sender_address_domain {$sender_address_domain}{$sender_helo_name}} log_message = SPF Header comment: {$spf_header_comment} deny spf = permerror message = SPF validation failed: syntax error in SPF record(s) for ${if def:sender_address_domain {$sender_address_domain}{$sender_helo_name}} log_message = SPF validation failed (permerror): syntax error in SPF record(s) for ${if def:sender_address_domain {$sender_address_domain}{$sender_helo_name}} defer spf = temperror message = temporary error during SPF validation, please try again later log_message = SPF validation failed temporarily, message deferred warn spf = none : neutral log_message = SPF validation none/neutral # implementazione delle greylist a mezzo del demone greylistd. # Se la mail non e` stata rifiutata prima, arriva qui e viene verificata la greylist prima # di venire eventualmente accettata dalle ACL che seguono. # notare che non considero il singolo host, ma la net /24 a cui esso appartiene. # questo e` un rilassamento del controllo per evitare di ritardare all'infinito mail che vengono # da sistemi che hanno diversi server smtpche lavorano in parallelo. # Se l'host si trova nella lista NOGREYLIST allora il controllo viene saltato e la mail accettata # immediatamente. defer message = Sender is greylisted. Please try again later. !authenticated = * condition = ${if eq {GREYLISTING} {enabled} {true}{false}} !hosts = ${if exists{NOGREYLIST}{net-iplsearch;NOGREYLIST}{}} condition = ${if eq {grey}\ {${readsocket{/var/run/greylistd/socket}\ {${mask:$sender_host_address/24} \ $sender_address \ $local_part@$domain}\ {5s}{}{}}}\ {true}{false}} log_message = Greylisted $sender_host_address $sender_address $local_part@$domain # Accept if the address is in a local domain, but only if the recipient can # be verified. Otherwise deny. The "endpass" line is the border between # passing on to the next ACL statement (if tests above it fail) or denying # access (if tests below it fail). accept domains = +local_domains : $primary_hostname : localhost : lsearch;VIRTUALS/domain_aliases endpass message = unknown user verify = recipient # Accetto la mail se sono un MX secondario, ma tento di verificarla presso il primario. # Se il primario non risponde, la accetto (defer_ok), mentre se risponde verifico se # il destinatario esiste o meno. Se non esiste, la rifiuto. Questo evita di affogare # il secondario nello spam che il primario ha rifiutato. accept domains = +relay_to_domains endpass message = unrouteable address or unknown user verify = recipient/callout=5s/defer_ok # If control reaches this point, the domain is neither in +local_domains # nor in +relay_to_domains. # Reaching the end of the ACL causes a "deny", but we might as well give # an explicit message. deny message = relay not permitted # Questa ACL viene verificata dopo aver ricevuto il body (DATA), quindi di fatto subito prima della # fine della connessione SMTP. acl_check_contents: # check virus. Lascio che il messaggio passi se il virus scanner non funziona (defer_ok) # I contenuti mime del messaggio sono gia` stati decodificati nella acl "acl_check_mime". # DISATTIVAZIONE: il controllo antivirus e` sempre attivo a meno che nel file degli utenti # del dominio non sia specificato "virus=off" fra i paramentri dopo la password. # Se il messaggio e` mandato dai miei utenti (acl_c0 e` impostata a "no_spam_check") allora # non eseguo il controllo AV deny message = This message contains a virus ($malware_name) and has been rejected condition = ${if !eq {$acl_c0} {no_spam_check} } condition = ${if or{ {!exists{VIRTUALS/users/$acl_m1}} {!eq {${extract{virus} {${extract{USERFILE_FIELDS}{:} {${lookup {$acl_m0} lsearch {VIRTUALS/users/$acl_m1}}} }} }} {off}}} {true} {false} } malware = */defer_ok # Check spam: Se il messaggio non e` stato mandato dai miei utenti, e # se non e` troppo grosso per scannarlo, lo scanno e mi segno i punteggi # dentro delle variabili warn condition = ${if !eq {$acl_c0} {no_spam_check} } spam = mail:true/defer_ok logwrite = SpamScore $spam_score set acl_m2 = $spam_score_int set acl_m3 = $spam_report set acl_m4 = [SPAM]($spam_score) $rh_Subject # Check spam: se a livello di sistema e` impostata una soglia di "spammosita`" # oltre la quale lo spam viene rifiutato, lo rifiuto a livello smtp deny condition = ${if !eq {$acl_c0} {no_spam_check} } condition = ${if > {$spam_score_int}{SPAM_SCORE_DENY} {true}{false}} log_message = Message refused by system configuration (spam score $spam_score_int is too high) message = This message is considered to be spam based on its contents # Check spam: se a livello di sistema e` impostata una soglia di spammosita` per il marking, # marco il messaggio con un header e setto la acl_m5 a 1 per indicare che un controllo # antispam ha dato esito positivo (2010-01-15) warn condition = ${if !eq {$acl_c0} {no_spam_check} } condition = ${if > {$spam_score_int}{SPAM_SCORE_MARK} {true}{false}} log_message = Message marked as spam by system configuration (spam score $spam_score_int is too high) set acl_m5 = 1 # Check spam: se il destinatario ha impostato il parametro spam_smtp_deny, # leggo il punteggio e decido se rifiutare la mail (in base al punteggio) # Se spam_smtp_deny non e` impostato, salto questo controllo deny condition = ${if !eq {$acl_c0} {no_spam_check} } condition = ${if exists{VIRTUALS/users/$acl_m1} {true}{false} } condition = ${if !eq {} {${extract{spam_smtp_deny} {${extract{USERFILE_FIELDS}{:} {${lookup {$acl_m0} lsearch {VIRTUALS/users/$acl_m1}}} }} }} } condition = ${if > {$spam_score_int} {${extract{spam_smtp_deny} {${extract{USERFILE_FIELDS}{:} {${lookup {$acl_m0} lsearch {VIRTUALS/users/$acl_m1}}} }} }} } log_message = Messagre refused by recipient (user) configuration (spam score too high) message = This message is considered to be spam based on its contents # Check spam: come sopra, pero` nel file degli alias e non nel file # degli utenti. Teoricamente dovrei verificare se esite un alias # con lo stesso indirizzo di un utente, e nel caso applicare solo il # check dell'alias e non quello dell'utente, al momento li # applico entrambi, col risultato che il piu` restrittivo decide la sorte # del messaggio. deny condition = ${if !eq {$acl_c0} {no_spam_check} } condition = ${if exists{VIRTUALS/aliases/$acl_m1} {true}{false} } condition = ${if !eq {} {${extract{spam_smtp_deny} {${extract{2}{:} {${lookup {$acl_m0} lsearch {VIRTUALS/aliases/$acl_m1}}} }} }} } condition = ${if > {$spam_score_int} {${extract{spam_smtp_deny} {${extract{2}{:} {${lookup {$acl_m0} lsearch {VIRTUALS/aliases/$acl_m1}}} }} }} } log_message = Messagre refused by recipient (alias) configuration (spam score too high) message = This message is considered to be spam based on its contents # Check spam: come sopra, pero` nel file dei domain alias. # in questo caso pero` e` possibile indicare solo un valore # per tutti gli utenti del dominio aliasato deny condition = ${if !eq {$acl_c0} {no_spam_check} } condition = ${if exists{VIRTUALS/domain_aliases} {true}{false} } condition = ${if !eq {} {${extract{spam_smtp_deny} {${extract{2}{:} {${lookup {$acl_m1} lsearch {VIRTUALS/domain_aliases}}} }} }} } condition = ${if > {$spam_score_int} {${extract{spam_smtp_deny} {${extract{2}{:} {${lookup {$acl_m1} lsearch {VIRTUALS/domain_aliases}}} }} }} } log_message = Messagre refused by recipient (domain alias) configuration (spam score too high) message = This message is considered to be spam based on its contents # Alla fine accetto tutto quello che e` passato fino a qui. accept # Questa ACL si applica ai contenuti MIME. In pratica qui non faccio nessun # controllo sul contenuto, ma mi limito a decodificarlo in modo da poter # poi eseguire il controllo antivirus sui contenuti decodificati. acl_check_mime: warn decode = default accept ###################################################################### # ROUTERS CONFIGURATION # # Specifies how addresses are handled # ###################################################################### # THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT! # # An address is passed to each router in turn until it is accepted. # ###################################################################### begin routers # This router routes addresses that are not in local domains by doing a DNS # lookup on the domain name. These are sent via SMTP. # Any domain that resolves to 0.0.0.0 or to a loopback interface address # (127.0.0.0/8) is treated as if it had no DNS entry. # If the DNS lookup fails, no further routers are tried because of # the no_more setting, and consequently the address is unrouteable. # TAINT OK dnslookup: driver = dnslookup #ipv4_only = true # se un remoto ha v4 e v6, usa v4. Se ha solo v6, fallisce il router #ipv4_prefer = true # se un remoto ha v4 e v6, usa v4. Se ha solo v6, usa v6 domains = ! +local_domains : ! $primary_hostname : ! localhost : ! lsearch;VIRTUALS/domain_aliases transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more # gestione autoreply # Se esiste un file VIRTUALS/autoreply/domain/user allora fa un autoreply per questo utente # usando come testo della risposta il contenuto del file # TAINT OK autoreply: driver = accept #domains = +local_domains domains = dsearch;VIRTUALS/autoreply condition = ${if exists{VIRTUALS/autoreply/$domain_data/$local_part} {true}{false} } # TAINT il dsearch detainta local_part local_parts = ${lookup {$local_part} dsearch,ret=key{VIRTUALS/autoreply/$domain_data} } no_verify no_expn unseen transport = autoreply senders = ! ^.*-request@.*:\ ! ^bounce-.*@.*:\ ! ^.*-bounce@.*:\ ! ^owner-.*@.*:\ ! ^postmaster@.*:\ ! ^abuse@.*:\ ! ^webmaster@.*:\ ! ^listmaster@.*:\ ! ^mailer-daemon@.*:\ ! ^root@.* # gestione dei files .forward per gli utenti locali della macchina # TAINT OK userforward: driver = redirect check_local_user condition = ${if exists{$home/.forward} {true}{false} } domains = ${primary_hostname} : localhost file = $home/.forward no_verify no_expn check_ancestor # allow_filter file_transport = address_file pipe_transport = address_pipe reply_transport = address_reply # alias di sistema presi da /etc/aliases, solo per l'hostname locale # TAINT OK system_aliases: driver = redirect allow_fail allow_defer domains = ${primary_hostname} : localhost data = ${lookup {$local_part} lsearch{SYS_ALIASES} } file_transport = address_file pipe_transport = address_pipe # delivery della mail per gli utenti locali della macchina localuser: driver = accept domains = ${primary_hostname} : localhost check_local_user transport = local_delivery # alias di sistema presi da /etc/aliases, solo per l'hostname locale # Questa volta cerco con l' asterisco, in modo che se alla fine del file aliases metto una voce # che dice "*:indirizzo", un qualsiasi indirizzo che non sia stato trovato prima (ne` fra gli alias # ne` fra gli utenti) venga diretto all'indirizzo indicato dopo l'asterisco. # questo sistema bruttino di fare due volte la ricerca degli alias serve per consentire di avere # un ordine preciso: prima gli alias (Senza asterisco) poi gli utenti, e per finire l'alias con # l'asterisco (se c'e`)a # TAINT OK system_aliases_wildcard: driver = redirect allow_fail allow_defer domains = ${primary_hostname} : localhost data = ${lookup {$local_part} lsearch*{SYS_ALIASES} } file_transport = address_file pipe_transport = address_pipe # Redirect di tutte le mail indirizzate ai vari postmaster, sia # dei domini locali (virtuali), sia a quello della macchina # Queste vanno tutte a qualcuno che sappia cosa farne. domain_postmaster: driver = redirect local_parts = postmaster domains = +local_domains : ${primary_hostname} : localhost check_ancestor retry_use_local_part data = POSTMASTER ##### ATTENZIONE: questo pezzo e` incompleto e non va usato se non viene prima sistemato ##### ## Istruiamo spamassassin. Le mail indirizzate a bayes e revoke vanno mandate a ## un trasporto speciale che addestra il filtro bayesiano e riporta a razor #bayes_report: # driver = accept # local_parts = bayes : revoke # domains = +local_domains # transport = bayes_update # gli indirizzi real-email@domain non passano per l'espansione degli alias # TAINT OK real_virtual_user: driver = accept local_part_prefix = real- domains = +local_domains # TAINT - popoliamo local_part_data local_parts = ${lookup {$local_part} lsearch,ret=key{VIRTUALS/users/$domain_data} } condition = ${lookup {$local_part} lsearch{VIRTUALS/users/$domain_data} } retry_use_local_part transport = VIRTUAL_DELIVERY # alias virtuali, redirect ad altri indirizzi e/o pipe verso comandi # TAINT OK virtual_aliases: driver = redirect allow_defer allow_fail domains = +local_domains condition = ${if exists{VIRTUALS/aliases/$domain_data} {true}{false} } pipe_transport = address_pipe file_transport = address_file data = ${extract{1}{:} {${lookup {$local_part} lsearch{VIRTUALS/aliases/${domain_data}} } }} user=${extract{pipe_user} {${extract{2}{:}{${lookup {$local_part} lsearch{VIRTUALS/aliases/${domain_data}} }}}} {$value} {Debian-exim}} group=${extract{pipe_group} {${extract{2}{:}{${lookup {$local_part} lsearch{VIRTUALS/aliases/${domain_data}} }}}} {$value} {Debian-exim}} # Prima del delivery finale agli utenti virtuali applico eventuali # regole per lo spam definite nel file VIRTUALS/users/$domain # per l'utente in questione. (i prossimi due router) # Questo router mette lo spam nel gufo se cosi` e` # richiesto dalla configurazione utente. Attenzione che # qui si perdono i messaggi se si sbaglia configurazione virtual_spam_owl: driver = redirect domains = +local_domains no_verify # TAINT - popoliamo local_part_data local_parts = ${lookup {$local_part} lsearch,ret=key{VIRTUALS/users/$domain_data} } condition = ${if exists{VIRTUALS/users/$domain_data} {true}{false} } condition = ${if > {$spam_score_int} {${extract{spam_blackhole} {${extract{USERFILE_FIELDS}{:} {${lookup {$local_part} lsearch {VIRTUALS/users/$domain_data}}} }}{$value}{65535} }} } data=:blackhole: # Questo router modifica il subject se richiesto # nella configurazione dell'utente. Per velocita` # faccio in modo di non ripassare tutti i router da capo # ma di passare direttamente al successivo (redirect_router) virtual_spam_add_subject: driver = redirect domains = +local_domains no_verify # TAINT - popoliamo local_part_data local_parts = ${lookup {$local_part} lsearch,ret=key{VIRTUALS/users/$domain_data} } condition = ${if exists{VIRTUALS/users/$domain_data} {true}{false} } condition = ${if > {$spam_score_int} {${extract{spam_subject} {${extract{USERFILE_FIELDS}{:} {${lookup {$local_part} lsearch {VIRTUALS/users/$domain_data}}} }}{$value}{65535} }} } headers_remove = Subject headers_add = Subject: $acl_m4 data = $local_part_data@$domain_data redirect_router = virtual_filter # Delivery dello spam in una cartella IMAP apposta (2010-01-15) # Questo, se l'utente ha il parametro spam_folder settato e la variabile acl_m5 e` uguale a 1 # (quindi la mail in questione ha fatto scattare almeno uno dei controlli antispam) # salva la mail in un folder che ha il nome indicato nel parametro spam_folder # (piu` esattamente chiama un trasporto apposta che provvedera` all'uopo) virtual_spam_folder: driver=accept domains = +local_domains # TAINT - popoliamo local_part_data local_parts = ${lookup {$local_part} lsearch,ret=key{VIRTUALS/users/$domain_data} } condition = ${if exists{VIRTUALS/users/$domain_data} {true}{false} } condition = ${if and{ { !eq{}{${lookup {$local_part} lsearch{VIRTUALS/users/$domain_data}}}} {={$acl_m5}{1}} {={1}{ ${extract{spam_folder} { ${extract{USERFILE_FIELDS}{:} {${lookup {$local_part} lsearch {VIRTUALS/users/$domain_data}}} }}{1}{0}} }} } } headers_remove = X-Spam-Score:X-Spam-Report headers_add = X-Spam-Score: $acl_m2\nX-Spam-Report: $acl_m3\nX-Spam-Boolean: $acl_m5\n transport = virtual_user_spam_delivery # Filtri per gli utenti dei domini virtuali. # Questo router applica un filtro alle mail in transito per l'utente # se esiste un file VIRTUALS/filters/$domain/$local_part # Questo sistema non e` sicuro se i filtri possono essere impostati da qualcuno che # ha cattive intenzioni. Idealmente i files dei filtri dovrebbero essere creati solo # dal sysadmin su richiesta degli utenti. virtual_filter: user=mail group=mail driver = redirect domains = +local_domains # TAINT - popoliamo local_part_data local_parts = ${lookup {$local_part} lsearch,ret=key{VIRTUALS/users/$domain_data} } condition = ${if exists{VIRTUALS/filters/$domain_data/$local_part} {true}{false} } file = VIRTUALS/filters/$domain_data/$local_part_data headers_remove = X-Spam-Score:X-Spam-Report headers_add = X-Spam-Score: $acl_m2\nX-Spam-Report: $acl_m3\nX-Spam-Boolean: $acl_m5\n no_verify allow_filter allow_freeze directory_transport = address_directory file_transport = address_file pipe_transport = address_pipe reply_transport = autoreply # Delivery agli utenti dei domini virtuali # TAINT: la riga local_parts serve a popolare local_part_data # in modo che poi il trasporto abbia le variabili untainted da usare # TAINT OK virtual_user: driver = accept domains = +local_domains condition = ${if exists{VIRTUALS/users/$domain_data} {true}{false} } local_parts = ${lookup {$local_part} lsearch,ret=key{VIRTUALS/users/$domain_data} } headers_remove = X-Spam-Score:X-Spam-Report headers_add = X-Spam-Score: $acl_m2\nX-Spam-Report: $acl_m3\nX-Spam-Boolean: $acl_m5\n retry_use_local_part transport = VIRTUAL_DELIVERY # Questo router cerca un indirizzo del tipo "user-ggmmaaaa@domain.tld" e se lo trova lo ridirige a # user@domain.tld senza il "-ggmmaaaa". Serve a fornire ad ogni utente un indirizzo mail "temporaneo" # valido solo per la data odierna, utile per iscriversi a quei servizi che poi magari ti spammano # a morte, perche` da domani questo non e` piu` valido. # TAINT: testato OK auto_daily_alias: driver = redirect domains = +local_domains check_ancestor condition = ${if eq {${substr{-9}{10}{$local_part}}} {-${substr{6}{2}{$tod_logfile}}${substr{4}{2}{$tod_logfile}}${substr{0}{4}{$tod_logfile}}} {true}{false}} data = ${substr{-9}{$local_part}}@$domain # alias virtuali, redirect ad altri indirizzi e/o pipe verso comandi # questa volta anche con l'asterisco, come per gli aliases locali # TAINT dovrebbe essere OK come virtual_aliases virtual_aliases_wildcard: driver = redirect allow_defer allow_fail domains = +local_domains condition = ${if exists{VIRTUALS/aliases/$domain_data} {true}{false} } pipe_transport = address_pipe file_transport = address_file data = ${extract{1}{:} {${lookup {$local_part} lsearch*{VIRTUALS/aliases/${domain_data}} } }} user=${extract{pipe_user} {${extract{2}{:}{${lookup {$local_part} lsearch{VIRTUALS/aliases/${domain_data}} }}}} {$value} {Debian-exim}} group=${extract{pipe_group} {${extract{2}{:}{${lookup {$local_part} lsearch{VIRTUALS/aliases/${domain_data}} }}}} {$value} {Debian-exim}} # alias dei domini. Se esiste un file che si chiama VIRTUALS/domain_aliases # questo consente di ridirigere tutta la mail per un dominio su un'altro. # la sintassi del file domain_aliases e` "dominio_origine:dominio_destinazione[:variabili]" # (una coppia per riga). In questo modo quando riceviamo una mail per # utente@dominio_origine, prima viene verificato se esiste l'utente nel # dominio originale. Se l'utente non esiste, o se proprio non esiste il file # degli utenti del dominio originale, allora la mail viene ridiretta a # utente@dominio_destinazione. domain_aliases: driver = redirect condition = ${if and{ {exists{VIRTUALS/domain_aliases}} {!eq {${lookup {$domain} lsearch{VIRTUALS/domain_aliases}}} {}}}{true}{false}} data = ${quote:$local_part}@${extract{1}{:} {${lookup {$domain} lsearch{VIRTUALS/domain_aliases}}}} ###################################################################### # TRANSPORTS CONFIGURATION # ###################################################################### # ORDER DOES NOT MATTER # # Only one appropriate transport is called for each delivery. # ###################################################################### begin transports # Delivery via SMTP all' MX del dominio remoto remote_smtp: driver = smtp dkim_canon = relaxed dkim_selector = dkim dkim_domain = ${lc:$sender_address_domain} # TAINT facendo un lookup dsearch il risultato è non tainted dkim_private_key = ${lookup {${lc:$sender_address_domain}-private.pem} dsearch,ret=full {DKIM_PATH}} # opzioni varie che non uso ma le tengo qui per ricordarmi se devo fare modifiche speciali per qualcuno # fallback_hosts = your.provider.smtp.server # hosts_avoid_esmtp = * # interface = 1.2.3.4 # Delivery locale per gli utenti fisici della macchina. (files in /var/mail) local_delivery: driver = appendfile file = /var/mail/$local_part_data group=mail delivery_date_add envelope_to_add return_path_add # Pipe ad un programma, per i vari files di forward address_pipe: driver = pipe return_output # Scrittura su un file, per i vari files di forward address_file: driver = appendfile delivery_date_add envelope_to_add return_path_add # Scrittura su una maildir, per i vari files di forward address_directory: driver=appendfile delivery_date_add envelope_to_add return_path_add maildir_format # Reply a mezzo email, per i vari files di forward. Questo NON va usato per vacation # perche` non ha protezioni tipo once o simili. address_reply: driver = autoreply # Insegnamento a spamassassin # Mai testato e mai usato. Al momento lo commento e lo tengo buono per il futuro. # Come sistema di insegnamento a spamassassin, usiamo quello via IMAP. #spam_update: # driver = pipe # user = mail # group = mail # return_output # command = spamassassin if{ eq {$local_part_data}{revoke} {-k}{-r}} # Delivery locale agli utenti virtuali (il trasporto fondamentale) # Questa e` la versione che NON USA Dovecot LDA e quindi NON funziona con SIEVE. # TAINT: questo richiede domain_data e local_part_data, che se non ho fatto errori # sono settati dai router che possono richiamare questo trasporto. virtual_user_delivery: driver = appendfile directory = MAIL/$domain_data/$local_part_data maildir_format user = mail group = mail mode = 0600 directory_mode = 0700 # Delivery locale agli utenti virtuali con Dovecot LDA e supporto SIEVE # TAINT: in Debian 12 Exim 4.96 mi ha fregato e ho dovuto modificare anche questo pezzo per gestire le variabili tainted, maledizione # Le modifiche rispetto a debian 11 sono tali che questa configurazione potrebbe presentare anomalie, va verificata e colladutata a fondo. # La configurazione "return_fail_output" e il "-e" nella command line di dovecot mandano l'errore di dovevot come delivery failure al mittente # in caso in cui ci siano errori permanenti che tornano dal processo dovecot-lda (tipicamente il 77 che infatti non e` un temp_error) virtual_user_dovecot_delivery: driver = pipe command = /usr/lib/dovecot/dovecot-lda -e -d $local_part_data@$domain_data message_prefix = message_suffix = delivery_date_add # questa riga aggiunge un header "Envelope-to:" che poi Dovecot legge (e` specificato nella config di dovecot) # e serve perche` non posso piu usare "-a $original_local_part@$original_domain" in command line envelope_to_add return_path_add log_output user = mail return_fail_output temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78 # Delivery locale agli utenti virtuali della mail che e` considerata spam # Questo viene chiamato se si decide di accettare lo spam anziche` rimbalzarlo # e fa delivery in un folder imap apposito, specificato nella configurazione # dell'utente alla voce "spam_folder". Viene chiamato dal router "virtual_spam_folder". # TAINT: dovrebbe essere OK, i valori sono popolati dal router che lo chiama virtual_user_spam_delivery: driver = appendfile directory = MAIL/$domain_data/$local_part_data/.${extract{spam_folder} { ${extract{USERFILE_FIELDS}{:} {${lookup {$local_part_data} lsearch {VIRTUALS/users/$domain_data}}} }}{$value}{}} # directory = MAIL/$domain/$local_part/.testspam maildir_format user = mail group = Debian-exim mode = 0600 directory_mode = 0700 # Trasporto di replay con funzione di limitazione con file once. # funziona per il router autoreplay oppure se chiamato in un filtro. # imposta il subject a un valore standard, e il testo al contenuto del file di autoreply oppure # ad un valore standard se questo file non esiste. I valori possono essere overridati nel filtro. # TAINT: OK autoreply: driver = autoreply to = ${sender_address} from = "${local_part}@${domain}" subject = "Autoreply from: ${local_part}@${domain}" text = ${if exists{VIRTUALS/autoreply/$domain_data/$local_part_data}{${readfile{VIRTUALS/autoreply/$domain_data/$local_part_data}{\n}}}{"This autoreply text should always be overridden"}} user = mail group = mail once = MAIL/$domain_data/${local_part_data}_autoreply.once once_file_size = 10k once_repeat = 1d ###################################################################### # RETRY CONFIGURATION # ###################################################################### begin retry # Regle di retry. # Se ho un errore 4xx (segno di una greylist) allora riprovo spesso # Se ho errori diversi, riprovo in modo meno insistente # ATTENZIONE: perche` questi retry cosi` veloci (2 minuti) funzionino # occorre che Exim esegua il "queue run" spesso. Se lo fa solo ogni 30 # minuti allora ovviamente la mail partira` ogni 30 minuti e non piu` # spesso. # Domain Error Retries # ------ ----- ------- * rcpt_4xx F,1h,2m; F,23h,30m; G,3d,1h,1.1 * mail_4xx F,1h,2m; F,23h,30m; G,3d,1h,1.1 * data_4xx F,1h,2m; F,23h,30m; G,3d,1h,1.1 * * F,2h,15m; F,23h,1h; G,3d,1h,1.1 ###################################################################### # REWRITE CONFIGURATION # ###################################################################### # There are no rewriting specifications in this default configuration file. begin rewrite ###################################################################### # AUTHENTICATION CONFIGURATION # ###################################################################### begin authenticators ### ### Autenticazione su file di testo ### #cram: # driver = cram_md5 # public_name = CRAM-MD5 # server_secret = ${lookup{$auth1}lsearch{EXIM4/passwd.smtp}{$value}fail} # server_set_id = $1 #plain: # driver = plaintext # public_name = PLAIN # server_prompts = : # server_condition = "\ # ${if and {{!eq{$2}{}}{!eq{$3}{}} \ # {eq{$3}{${extract{1}{:} \ # {${lookup{$2}lsearch{EXIM4/passwd.smtp}{$value}}}}}}}{1}{0}}" # server_set_id = $2 #login: # driver = plaintext # public_name = LOGIN # server_prompts = "Username:: : Password::" # server_condition = "\ # ${if and {{!eq{$1}{}}{!eq{$2}{}} \ # {eq{$2}{${extract{1}{:} \ # {${lookup{$1}lsearch{EXIM4/passwd.smtp}{$value}}}}}}}{1}{0}}" # server_set_id = $1 ### ### Autenticazione su Dovecot ### # questo sistema richiede che Dovecot sia configurato per fornire autenticazione sul socket # definito qui in "server_socket" e che supporti tutti i metodi di autenticazione definiti # qui in alla voce "public_name". # NTLM ho smesso di usarlo in Dovecot per cui è commentato anche qui. dovecot_cram: driver = dovecot public_name = CRAM-MD5 server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 dovecot_plain: driver = dovecot public_name = PLAIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 dovecot_login: driver = dovecot public_name = LOGIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 #dovecot_ntlm: # driver = dovecot # public_name = NTLM # server_socket = /var/run/dovecot/auth-client # server_set_id = $auth1 ###################################################################### # CONFIGURATION FOR local_scan() # ###################################################################### # If you have built Exim to include a local_scan() function that contains # tables for private options, you can define those options here. Remember to # uncomment the "begin" line. It is commented by default because it provokes # an error with Exim binaries that are not built with LOCAL_SCAN_HAS_OPTIONS # set in the Local/Makefile. # begin local_scan # End of Exim configuration file