using procmail with mdbox in dovecot (deliver or dovecot-lda)

By thomas, 2 August, 2012

When using an mdbox or maildir mailbox, you need to use the dovecot-lda to deliver the message and not allow procmail to do this directly. I had a few issues getting this to work properly, here are the details of getting it going.

The first issue is that my procmail transport in exim needed to set user to the local_part and do initgroups to get the uid and gid of the localuser, then run procmail as that user/group. Here is that transport:

driver = pipe
command = /usr/bin/procmail -d $local_part
check_string = "From "
escape_string = ">From "
user = $local_part

The check_string and escape_string parts are from the manual, they just work around a bug in procmail where it would make a mistake if it saw a line starting with From.

Next I had to get deliver to do the right thing, in my case that meant taking off the group and user parts of the lda in dovecot.conf, so I made a separate dovecot-lda.conf with those settings commented out, the lda part of my config is also included.

#mail_privileged_group = mail
#mail_gid =12

protocol lda {
mail_plugins = $mail_plugins sieve
lda_mailbox_autocreate = yes
lda_mailbox_autosubscribe = yes
log_path = /var/log/dovecot/deliver-errors.log
info_log_path = /var/log/dovecot/deliver.log

The postmaster_address is needed so that if there are errors with submission via lda, the errors will be delivered to this address, similarly we add log lines. We use sieve here so we append sieve to the plugins line. The next two lines are important, lda_mailbox_autocreate and lda_mailbox_autosubscribe. If the call to deliver names a mailbox that doesn't exist yet, deliver will create it. Without this line the mail fails if the box doesn't exist. The autosubscribe is there so that the box shows up in the users list after creation.

With a new config file, I wrote a small script that calls dovecot-lda with the appropriate config file.


exec /usr/libexec/dovecot/dovecot-lda -c /etc/dovecot/dovecot-lda.conf $@

I wasn't kidding about small...that's all it needs to do. I store this in /usr/bin/deliver and make sure it's selinux type is procmail_exec_t

[thomas@example: ~] $ ls -Z /usr/bin/deliver
-rwxr-xr-x. root root system_u:object_r:procmail_exec_t:s0 /usr/bin/deliver

With these settings in place, you can make a procmailrc that calls /usr/bin/deliver

:0 c
* ^From example@*
| $DELIVER -d $LOGNAME -m Example

:0 w

In the above, any email from example@someplace will be delivered via dovecot to the Example mailbox, the rest of the mail will be delivered to the Inbox.

I also needed to make some selinux adjustments to allow procmail to run the dovecot-lda command as well as use the sendmail command (which is just exim). Here is my selinux policy for that part.


require {
type dovecot_deliver_exec_t;
type dovecot_t;
type dovecot_var_run_t;
type exim_t;
type exim_log_t;
type exim_spool_t;
type procmail_t;
type procmail_exec_t;
type sendmail_t;
type var_lib_t;

allow procmail_t dovecot_deliver_exec_t:file { open read execute execute_no_trans getattr };
allow procmail_t dovecot_t:unix_stream_socket connectto;
allow procmail_t procmail_exec_t:lnk_file read;
allow procmail_t dovecot_var_run_t:dir search;
allow procmail_t dovecot_var_run_t:sock_file write;

allow procmail_t exim_spool_t:file { read write };

allow procmail_t sendmail_t:process { siginh rlimitinh noatsecure };
allow procmail_t var_lib_t:file read;

allow sendmail_t exim_log_t:dir search;
allow sendmail_t exim_log_t:file open;

allow sendmail_t exim_spool_t:dir { write search read remove_name open getattr add_name };

allow sendmail_t exim_spool_t:file { rename setattr read lock create write getattr open append };
allow sendmail_t exim_t:process { siginh rlimitinh noatsecure };

'cause enforcing is the only way to run...