doc:appunti:linux:sa:postfix_spamassassin_clamav_dovecot
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
doc:appunti:linux:sa:postfix_spamassassin_clamav_dovecot [2021/02/22 18:23] – [Quota] niccolo | doc:appunti:linux:sa:postfix_spamassassin_clamav_dovecot [2023/02/24 16:18] – [Sanitizer/ClamAV Filter] niccolo | ||
---|---|---|---|
Line 64: | Line 64: | ||
< | < | ||
- | !include auth-system.conf.ext | + | # Order matters: we use passwdfile first because it is most likely used |
+ | # and because system autentication (PAM) does a 2-seconds delay on fail. | ||
!include auth-passwdfile.conf.ext | !include auth-passwdfile.conf.ext | ||
+ | !include auth-system.conf.ext | ||
</ | </ | ||
Line 207: | Line 209: | ||
* **clamdscan** | * **clamdscan** | ||
* **clamav-freshclam** | * **clamav-freshclam** | ||
+ | * **libclamunrar9** (non-free package to scan inside RAR archives) | ||
Periodic download (update) of viruses database is performed by the **clamav-freshclam.service**, | Periodic download (update) of viruses database is performed by the **clamav-freshclam.service**, | ||
Line 249: | Line 252: | ||
mailbox_command = / | mailbox_command = / | ||
</ | </ | ||
+ | |||
+ | ==== Error stats-writer Broken pipe ==== | ||
+ | |||
+ | **WARNING**: | ||
+ | |||
+ | < | ||
+ | postfix/ | ||
+ | status=bounced (Command died with status 134: | ||
+ | "/ | ||
+ | Command output: lda(lica-marilena): | ||
+ | Error: net_connect_unix(/ | ||
+ | Permission denied Aborted Unable to flush stdout: Broken pipe ) | ||
+ | </ | ||
+ | |||
+ | It seems that the quickest and simplest solution is to make the socket **0666 mode** (which will risk the stats service to be abused). Add the following snippet to **/ | ||
+ | |||
+ | < | ||
+ | service stats { | ||
+ | unix_listener stats-writer { | ||
+ | mode = 0666 | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | See the following posts about the problem: | ||
+ | |||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | ==== Error Command output: Aborted ==== | ||
+ | |||
+ | Another subtle error with Dovecot LDA can be reported generically into the Postfix log as: | ||
+ | |||
+ | < | ||
+ | postfix/ | ||
+ | status=bounced (Command died with status 134: | ||
+ | "/ | ||
+ | Command output: Aborted ) | ||
+ | </ | ||
+ | |||
+ | To get some hints about the problem you can enable logging in Dovecot LDA; you can add the following in **/ | ||
+ | |||
+ | < | ||
+ | protocol lda { | ||
+ | ... | ||
+ | log_path = / | ||
+ | info_log_path = / | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | and create the log files with suitable permissions (in my case the LDA is executed with user's privileges, so I made it world-writable). | ||
+ | |||
+ | < | ||
+ | lda(username)< | ||
+ | exec:/ | ||
+ | Execution timed out (> 10000 msecs) | ||
+ | lda(username)< | ||
+ | exec:/ | ||
+ | Forcibly terminated with signal 15 | ||
+ | lda(username)< | ||
+ | output stream (temp iostream in / | ||
+ | for (program client seekable output)) is missing error handling | ||
+ | lda(username)< | ||
+ | Raw backtrace: / | ||
+ | </ | ||
+ | |||
+ | There was a problem with **the filter program responding too slowly**. It is possible to change the **exec timeout**, in this case for the **filter** extension, just add the following in **/ | ||
+ | |||
+ | < | ||
+ | plugin { | ||
+ | ... | ||
+ | # Change the default timeout (10 seconds) for the filter extension. | ||
+ | sieve_filter_exec_timeout = 20s | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Error Unable to flush stdout ==== | ||
+ | |||
+ | FIXME This error message has an unwknown origin. | ||
+ | |||
+ | < | ||
+ | postfix/ | ||
+ | status=bounced (Command died with status 134: | ||
+ | "/ | ||
+ | Command output: Aborted Unable to flush stdout: Broken pipe ) | ||
+ | </ | ||
===== Sieve filtering ===== | ===== Sieve filtering ===== | ||
Line 358: | Line 447: | ||
terminated with non-zero exit code 127 | terminated with non-zero exit code 127 | ||
</ | </ | ||
+ | |||
+ | FIXME How to handle errors in filter external commands? The default action is to send a **non-delivery notification**, | ||
==== Multiple Sieve Scripts ==== | ==== Multiple Sieve Scripts ==== | ||
Line 401: | Line 492: | ||
The files (with the .sieve extension) will be searched into the proper directory. | The files (with the .sieve extension) will be searched into the proper directory. | ||
+ | |||
+ | ==== Using Sieve to decode winmail.dat attachments ==== | ||
+ | |||
+ | Microsoft Outlook uses the infamous **winmail.dat** attachment to forward emails: it is the proprietary **TNEF** format. In this article you can find a recipe to filter that attachments using a Sieve filter: **[[sieve_filtering_tnef]]**. | ||
+ | |||
===== Roundcube with MySQL ===== | ===== Roundcube with MySQL ===== | ||
Line 690: | Line 786: | ||
See **[[https:// | See **[[https:// | ||
- | If Dovecot is started via **Systemd**, | + | If Dovecot is started via **Systemd**, |
< | < | ||
Line 725: | Line 821: | ||
</ | </ | ||
- | The Dovecot plugin will return mailbox full when user will reach the filesystem quota **soft limit**. You may want to set the **hard limit** a bit above the soft one, so that the system can still write mailbox indexes, Spamassassin stats, etc. | + | The Dovecot plugin will return mailbox full when user will reach the **filesystem quota soft limit**. You may want to set the **hard limit** a bit above the soft one, so that the system can still write mailbox indexes, Spamassassin stats, etc. |
==== Enable Filesystem Quota ==== | ==== Enable Filesystem Quota ==== | ||
Line 769: | Line 865: | ||
</ | </ | ||
+ | **NOTICE**: The Dovecot' | ||
- | ==== Dovecot | + | ==== Dovecot |
We enable a service that will be checked by Postfix when accepting mail via SMTP. Into **/ | We enable a service that will be checked by Postfix when accepting mail via SMTP. Into **/ | ||
Line 794: | Line 891: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | The Postfix quota-status service may uses also a **quota_over_flag** provided by the **userdb** backend. We don't have such a field into the userdb, neverthless we have to configure the parameters **quota_over_flag_value** and **quota_over_script**, | ||
+ | |||
+ | < | ||
+ | # === WARNING === | ||
+ | # Both " | ||
+ | # required, otherwise the Postfix quota-status check will always | ||
+ | # return DUNNO (i.e. user is under quota). This is because | ||
+ | # without those two parameters the quota check is skipped | ||
+ | # completely, as seen in the mail_debug = yes log: | ||
+ | # Debug: quota: quota_over_flag check: quota_over_script unset - skipping | ||
+ | # | ||
+ | # Actually we don't have a " | ||
+ | # when quota-status service is called by Postfix, the value | ||
+ | # quota_over_flag=0(*dummy*) is assumed due the config values | ||
+ | # below. Current quota status for the user is then checked by | ||
+ | # querying the filesystem and it will be 1 for overquota, 0 | ||
+ | # otherwise. | ||
+ | # | ||
+ | # As a side effect, the quota-warning script is executed at | ||
+ | # every check if the user is overquota because 0 mismatches 1. | ||
+ | plugin { | ||
+ | quota_over_flag_value = FALSE | ||
+ | quota_over_flag = " | ||
+ | quota_over_script = quota-warning mismatch %u | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | We have to define also a **quota-warning service**, which basically is a script called when the user crosses some quota barriers, we can use it to send warning messages. The script needs to be run as root, because we want it to be able to switch to the final user (this is required by our system which uses Maildir and user's filters). The **/ | ||
+ | |||
+ | < | ||
+ | service quota-warning { | ||
+ | executable = script / | ||
+ | user = root | ||
+ | unix_listener quota-warning { | ||
+ | user = dovecot | ||
+ | group = dovecot | ||
+ | mode = 0666 | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | To have the script executed when crossing some quota limits, add the following: | ||
+ | |||
+ | < | ||
+ | plugin { | ||
+ | quota_warning = storage=90%% quota-warning 90 %u | ||
+ | quota_warning2 = storage=75%% quota-warning 75 %u | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | So, all after all, here it is the script executed when an user is crossing some quota levels and when the fake **quota_over_flag** does not match the actual quota status (i.e. it is called when the user is over quota, and we just do nothing in that case!): | ||
+ | |||
+ | **/ | ||
+ | |||
+ | <code bash> | ||
+ | #!/bin/sh | ||
+ | ARG1=$1 | ||
+ | USER=$2 | ||
+ | DATE=" | ||
+ | |||
+ | # ==== WARGNING ==== | ||
+ | # * The user is set by Dovecot " | ||
+ | # configuration is: uid=0(root) gid=0(root) groups=0(root) | ||
+ | # * Working directory is / | ||
+ | # * /tmp directory is / | ||
+ | |||
+ | # Do nothing if called on Dovecot quota_over_flag_value mismatch. | ||
+ | test " | ||
+ | |||
+ | # Send the warning message. | ||
+ | #cat << EOF | / | ||
+ | cat << EOF | / | ||
+ | From: postmaster@supermail.texnet.it | ||
+ | Subject: Attenzione: mailbox quasi piena | ||
+ | Date: $DATE | ||
+ | Content-Type: | ||
+ | Content-Transfer-Encoding: | ||
+ | |||
+ | La tua mailbox è quasi piena; lo spazio occupato ha superato il ${ARG1}%. | ||
+ | Eliminare i messaggi non più necessari ed eventualmente svuotare il cestino. | ||
+ | EOF | ||
+ | </ | ||
+ | |||
+ | ==== Troubleshoting Postfix quota-status service ==== | ||
After reloading **dovecot.service**, | After reloading **dovecot.service**, | ||
Line 800: | Line 982: | ||
telnet localhost 12340 | telnet localhost 12340 | ||
- | request=smtpd_access_policy | ||
- | protocol_state=RCPT | ||
- | protocol_name=SMTP | ||
- | sender=foo@bar.tld | ||
recipient=user@domain.org | recipient=user@domain.org | ||
- | client_address=1.2.3.4 | + | size=10000000 |
- | client_name=another.domain.tld | + | |
- | size=123000 | + | |
action=554 5.2.2 Quota exceeded (mailbox for user is full) | action=554 5.2.2 Quota exceeded (mailbox for user is full) | ||
</ | </ | ||
+ | |||
+ | The **554 Quota exceeded error** should be returned when the **actual user's quota** plus the announced **size** will exceed the filesystem **soft quota** plus the **quota_grace** percentage. | ||
+ | |||
+ | Another way to check the service using a single command line is using **netcat**: | ||
+ | |||
+ | < | ||
+ | printf " | ||
+ | </ | ||
In Postfix configuration **/ | In Postfix configuration **/ |
doc/appunti/linux/sa/postfix_spamassassin_clamav_dovecot.txt · Last modified: 2023/10/30 11:09 by niccolo