Hi,
I got this simple test Sieve config:
############################################# # Sieve Filter # Generated by Ingo (http://www.horde.org/apps/ingo/) (11/01/2019, 10:46:06 PM)
# Forwards if true { redirect "krustev@krustev.net"; } # Forward Keep Action if true { keep; stop; } #############################################
Which used to work fine with:
# 2.2.27 (c0f36b0): /etc/dovecot/dovecot.conf # Pigeonhole version 0.4.16 (fed8554) # OS: Linux 4.9.0-8-amd64 x86_64 Debian 9.11
Then I've tried migrating to:
# 2.3.4.1 (f79e8e7e4): /etc/dovecot/dovecot.conf # Pigeonhole version 0.5.4 () # OS: Linux 4.19.0-6-amd64 x86_64 Debian 10.1
And started getting the following errors:
# cat .dovecot.sieve.log sieve: info: started log at Nov 01 22:55:50. error: msgid=4221584.AlbrL4BjWX@home: failed to redirect message to krustev@krustev.net: Failed to execute sendmail (temporary failure).
A google search lead me to:
https://bugs.archlinux.org/task/56933
which blames systemd service changes:
NoNewPrivileges=true
, however I'm not running dovecot via systemd but use DJB's daemontools for service supervision .
The page above suggested to change from:
sendmail_path = /usr/sbin/sendmail
to
submission_host = localhost
in "conf.d/15-lda.conf", which worked fine. But since I don't have other problems with "sendmail" execution I've decided to debug this further.
I have dovecot integrated with Qmail:
# apt-cache policy qmail qmail: Installed: 1.06-6+b1 Candidate: 1.06-6+b1 Version table: *** 1.06-6+b1 900 900 http://deb.debian.org/debian buster/main amd64 Packages
so sendmail's implementation comes from Qmail:
# ls -al which sendmail
lrwxrwxrwx 1 root root 14 Feb 23 2015 /usr/sbin/sendmail -> qmail-sendmail
I've strace-d the qmail-lspawn process which executes dovecot's LDA, which processes the Sieve rules and executes "sendmail". The sendmail process executes and returns successfully, the mail is delivered, however the Sieve code does not wait for the child process correctly and tries to kill the already exited process after 30 seconds timeout.
Here are the problematic Sieve syscalls:
22:55:15.283482 execve("/usr/lib/dovecot/deliver", ["/usr/lib/dovecot/deliver", "-e", "-a", "tester@krustev.net"], 0x5620b4330c40 /* 61 vars */) = 0 ... 22:55:15.286845 pipe([5, 6]) = 0 22:55:15.286870 fcntl(5, F_GETFL) = 0 (flags O_RDONLY) 22:55:15.286889 fcntl(5, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 22:55:15.286909 fcntl(6, F_GETFL) = 0x1 (flags O_WRONLY) 22:55:15.286928 fcntl(6, F_SETFL, O_WRONLY|O_NONBLOCK) = 0 22:55:15.286947 fcntl(5, F_GETFD) = 0 22:55:15.286966 fcntl(5, F_SETFD, FD_CLOEXEC) = 0 22:55:15.286985 fcntl(6, F_GETFD) = 0 22:55:15.287003 fcntl(6, F_SETFD, FD_CLOEXEC) = 0 22:55:15.287024 epoll_create(128) = 7 22:55:15.287043 fcntl(7, F_GETFD) = 0 22:55:15.287062 fcntl(7, F_SETFD, FD_CLOEXEC) = 0 22:55:15.287084 epoll_ctl(7, EPOLL_CTL_ADD, 5, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP, {u32=47201248, u64=94699781110752}}) = 0 ... 22:55:15.294625 epoll_ctl(7, EPOLL_CTL_DEL, 5, 0x7ffd59156b8c) = 0 22:55:15.294647 epoll_create(128) = 12 22:55:15.294668 fcntl(12, F_GETFD) = 0 22:55:15.294687 fcntl(12, F_SETFD, FD_CLOEXEC) = 0 22:55:15.294708 epoll_ctl(12, EPOLL_CTL_ADD, 5, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP, {u32=47455536, u64=94699781365040}}) = 0
Dovecot/Sieve will wait for this pipe FD 5 later, but no event will arrive.
22:55:15.294740 rt_sigaction(SIGCHLD, {sa_handler=0x7f15404b3640, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7f1540229840}, NULL, 8) = 0 22:55:15.294763 pipe([13, 14]) = 0 22:55:15.294788 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f15401ec2d0) = 6929
The sendmail child process with PID 6929 is forked here.
22:55:15.294928 close(13) = 0 22:55:15.294969 fcntl(14, F_GETFL) = 0x1 (flags O_WRONLY) 22:55:15.295006 fcntl(14, F_SETFL, O_WRONLY|O_NONBLOCK) = 0 22:55:15.295039 lseek(14, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) 22:55:15.295065 getsockname(14, 0x7ffd59156a40, [28]) = -1 ENOTSOCK (Socket operation on non-socket) 22:55:15.295109 write(14, "EDITTED LONG MESSAGE DATA\n", 1461) = 1461 22:55:15.295150 close(14) = 0 22:55:15.295175 wait4(6929, 0x562102d4fee4, WNOHANG, NULL) = 0 22:55:15.295211 epoll_wait(12, [], 1, 30000) = 0
Here's where the 30 second's timeout is requested and waited.
22:55:45.325580 kill(6929, SIGTERM) = 0 22:55:45.325769 epoll_wait(12, [], 1, 5000) = 0 22:55:50.331108 kill(6929, SIGKILL) = 0 22:55:50.332867 wait4(6929, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 6929 22:55:50.333020 epoll_ctl(12, EPOLL_CTL_DEL, 5, 0x7ffd59156b6c) = 0 22:55:50.333060 epoll_ctl(7, EPOLL_CTL_ADD, 5, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP, {u32=47201248, u64=94699781110752}}) = 0 22:55:50.333097 close(12) = 0 22:55:50.333240 sendto(9, "<19>Nov 1 22:55:50 dovecot: lda(krustev)<6926><IlpXEdO3vF0OGwAA4EGeoA>: Error: sieve: msgid=4221584.AlbrL4BjWX@home: failed to redirect message to krustev@krustev.net: Failed to execute sendmail (temporary failure)", 220, MSG_NOSIGNAL, NULL, 0) = 220 22:55:50.333321 openat(AT_FDCWD, "/home/krustev/mail/domains/krustev.net/tester/.dovecot.sieve.log", O_WRONLY|O_CREAT|O_APPEND, 0600) = 12 22:55:50.333557 fstat(12, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 22:55:50.333613 lseek(12, 0, SEEK_CUR) = 0 22:55:50.333643 fstat(12, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 22:55:50.333678 stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=127, ...}) = 0 22:55:50.333726 write(12, "sieve: info: started log at Nov 01 22:55:50.\n", 45) = 45 22:55:50.333788 write(12, "error: msgid=4221584.AlbrL4BjWX@home: failed to redirect message to krustev@krustev.net: Failed to execute sendmail (temporary failure).\n", 141) = 141 22:55:50.333857 sendto(9, "<19>Nov 1 22:55:50 dovecot: lda(krustev)<6926><IlpXEdO3vF0OGwAA4EGeoA>: Error: sieve: Execution of script /home/krustev/mail/domains/krustev.net/tester/.dovecot.sieve was aborted due to temporary failure (user logfile /home/krustev/mail/domains/krustev.net/tester/.dovecot.sieve.log may reveal additional details)", 317, MSG_NOSIGNAL, NULL, 0) = 317 22:55:50.333941 close(10) = 0 22:55:50.333996 close(12) = 0 22:55:50.334057 lstat("/home/krustev/mail/domains/krustev.net/tester/.dovecot.lda-dupes.lock", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 22:55:50.334095 unlink("/home/krustev/mail/domains/krustev.net/tester/.dovecot.lda-dupes.lock") = 0 22:55:50.334188 close(11) = 0 22:55:50.334245 write(2, "Execution of Sieve filters was aborted due to temporary failure\n", 64) = 64 22:55:50.334418 munmap(0x7f15401bc000, 103680) = 0 22:55:50.334481 munmap(0x7f15403b3000, 32800) = 0 22:55:50.334516 munmap(0x7f15400fb000, 788352) = 0 22:55:50.334610 epoll_ctl(7, EPOLL_CTL_DEL, 8, 0x7ffd5915706c) = 0 22:55:50.334640 close(8) = 0 22:55:50.334685 epoll_ctl(7, EPOLL_CTL_DEL, 5, 0x7ffd5915706c) = 0 22:55:50.334738 close(5) = 0 22:55:50.334785 close(6) = 0 22:55:50.334813 close(7) = 0 22:55:50.334841 close(4) = 0 22:55:50.334881 exit_group(75) = ? 22:55:50.335077 +++ exited with 75 +++
Here's the interesting part of sendmail's (PID 6929) execution with timestamps: .. 22:55:15.295268 execve("/usr/sbin/sendmail", ["/usr/sbin/sendmail", "-i", "-f", "tester@krustev.net", "--", "krustev@krustev.net"], NULL) = 0 ... 22:55:15.296024 chdir("/var/lib/qmail") = 0 22:55:15.296055 execve("bin/qmail-inject", ["bin/qmail-inject", "-a", "-f", "tester@krustev.net", "--", "krustev@krustev.net"], 0x55741b1890e0 /* 2 vars */) = 0 ... 22:55:15.297264 vfork() = 6930 .. 22:55:15.297930 wait4(6930, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 6930 22:55:15.305391 exit_group(0) = ? 22:55:15.305472 +++ exited with 0 +++
The PID 6930 is a call to the setuid qmail-queue, which also executes and returns normally.
With all the above stated - It seems that the problem is in the "epoll" calls. Either it is not set-up correctly or dovecot-LDA does not receive the information it waits for.
I've tried to make my way trough Dovecot's source code but have concluded that someone more familiar should be able to spot the problem much quicker than me.
Let me know if you need some additional information. Sorry for the long mail.
Dovecot config follows:
# 2.3.4.1 (f79e8e7e4): /etc/dovecot/dovecot.conf # Pigeonhole version 0.5.4 () # OS: Linux 4.19.0-6-amd64 x86_64 Debian 10.1 # Hostname: pinko.livehostserver.com auth_mechanisms = plain login disable_plaintext_auth = no lda_mailbox_autocreate = yes lda_mailbox_autosubscribe = yes log_path = /dev/stderr log_timestamp = mail_plugins = " quota" managesieve_notify_capability = mailto managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date index ihave duplicate mime foreverypart extracttext namespace inbox { inbox = yes location = mailbox Archive { special_use = \Archive } mailbox Archives { special_use = \Archive } mailbox "Deleted Items" { special_use = \Trash } mailbox "Deleted Messages" { special_use = \Trash } mailbox Drafts { auto = subscribe special_use = \Drafts } mailbox Junk { auto = subscribe special_use = \Junk } mailbox "Junk E-mail" { special_use = \Junk } mailbox Sent { auto = subscribe special_use = \Sent } mailbox "Sent Items" { special_use = \Sent } mailbox "Sent Mail" { special_use = \Sent } mailbox "Sent Messages" { special_use = \Sent } mailbox Spam { special_use = \Junk } mailbox Trash { auto = subscribe special_use = \Trash } mailbox sent-mail { special_use = \Sent } prefix = } passdb { args = /usr/local/sbin/vchkpw-dovecot driver = checkpassword } plugin { antispam_allow_append_to_spam = yes antispam_backend = pipe antispam_pipe_program = /bin/sh antispam_pipe_program_notspam_args = -c;HOME=$PWD exec nice sa-learn --ham antispam_pipe_program_spam_args = -c;HOME=$PWD exec nice sa-learn --spam antispam_pipe_tmpdir = /tmp antispam_spam_pattern_ignorecase = spam;junk;junk * antispam_trash_pattern_ignorecase = trash;Deleted * quota = maildir:User quota sieve = ~/.dovecot.sieve sieve_dir = ~/sieve sieve_redirect_envelope_from = recipient } protocols = " imap sieve pop3" service anvil { client_limit = 1536 } service auth { client_limit = 1536 } service imap-login { process_limit = 512 } service managesieve-login { inet_listener sieve { port = 4190 } process_min_avail = 1 service_count = 1 } service managesieve { process_limit = 50 } service pop3-login { process_limit = 512 } service stats { client_limit = 1024 unix_listener stats-writer { mode = 0666 } } ssl_ca =
Best regards
Delian