mailserver setup

mysza

New version based on Debian 7.2 and with the latest Modoboa… watch this space. If you wan’t to help out testing the new guide, leave a comment below.

First off, this guide like 90% complete. If you follow it, please report back if something is wrong etc.

When I first started writing, I ran through the steps a couple of times installing everything from scratch, but after a while, I got tired of re installing just to try stuff out, so some things may gone wrong along the way.

These are mostly my own notes setting up modoboa. When completed, you’ll have postfix, dovecot and modoboa running with nginx.

I won’t go into detail how to configure the various modoboa extensions, this is covered in modoboas documentation.

I’m using a minimal install of Debian Squeeze for this. So, some packages may already be installed if you don’t us the same dist. The steps described here also should work on Ubuntu, but I haven’t verified that.

Replace <fqdn> with your fully qualified domain name. For example: mail.domain.com. <domain> with your domain. For example: example.com.

This guide assumes you’ll run mailserver, mysql and modoboa on the same host. If you plan to grow, it might be a good idea to separate these.

Content

Install packages

I’d start with installing netselect-apt to find your fastest mirror. This is optional (works only in Debian).

apt-get install netselect-apt
cd /etc/apt/
netselect-apt
apt-get update

then we’ll install the needed packages. We won’t use the Debian packaged version of amavisd-new but the latest from source. That’s why we install all the perl modules and archive packages

apt-get install sudo gcc libxslt-dev python-pip postfix-mysql nginx \
python-dev python-rrdtool python-mysqldb mysql-server dovecot-imapd \
dovecot-pop3d pwgen spamassassin vim ca-certificates dkim-filter \
libarchive-zip-perl libconvert-tnef-perl libconvert-uulib-perl \
libmime-tools-perl libcrypt-openssl-rsa-perl libnet-cidr-perl \
libevent-1.4-2 libnet-server-perl pax libnfsidmap2 libmail-dkim-perl \
libberkeleydb-perl librpcsecgss3 libio-multiplex-perl libgssglue1 portmap \
libunix-syslog-perl libcrypt-openssl-bignum-perl ncompress nomarch \
arc arj zoo tnef cabextract clamav clamav-daemon bzip2 unrar-free xdms \
p7zip p7zip-full unzip orange ripole lzop rpm2cpio lrzip

If you’re using Ubuntu, replace package dkim-filter with opendkim. I won’t go into detail how to enable dkim in this guide anyway.

amavisd-new setup

These instructions pretty much come from the INSTALL file from amavisd-new.

Create user group amavis:amavis and set to home dir /var/amavis

useradd amavis -d /var/amavis
mkdir -p /var/amavis/tmp /var/amavis/var /var/amavis/db /var/amavis/home
chown -R amavis:amavis /var/amavis
chmod -R 750 /var/amavis

Download and unpack amavisd-new.

cd /usr/local/src
wget http://www.amavis.org/amavisd-new-2.8.0.tar.gz -O - | tar zxf -
cd amavisd-new-2.8.0

install amavis

cp amavisd /usr/local/sbin/
chown root /usr/local/sbin/amavisd
chmod 755 /usr/local/sbin/amavisd

copy configfile

cp amavisd.conf /etc/
chown root:amavis /etc/amavisd.conf
chmod 640 /etc/amavisd.conf

create a directory to be used by amavisd-new as a quarantine area

mkdir /var/virusmails
chown amavis:amavis /var/virusmails
chmod 750 /var/virusmails

edit /etc/amavisd.conf and change, enable or uncomment, the following settings:

$daemon_user = 'amavis';
$daemon_group = 'amavis';

$mydomain = 'example.com';

$MYHOME = '/var/amavis';
$TEMPBASE = "$MYHOME/tmp";
$db_home = "$MYHOME/db";

$helpers_home = "$MYHOME/home";
$pid_file = "/var/run/amavis/amavisd.pid";
$lock_file = "/var/run/amavis/amavisd.lock";

$unix_socketname = "/var/run/amavis/amavisd.sock";

$myhostname = '<fdqn>';

since we’re doing the ”uncluttered” setup, for some extra security, also change ownerships:

chown root /var/amavis
chown -R amavis:amavis /var/amavis/home
chmod 750 /var/amavis /var/amavis/home

Create init script for amavisd

Create a new file, /etc/init.d/amavisd, containing:

#!/bin/sh
# /etc/init.d/amavisd

### BEGIN INIT INFO
# Provides: amavis 
# Required-Start:    $local_fs $remote_fs $network $syslog $time
# Required-Stop:     $local_fs $remote_fs $network $syslog 
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start amavis at boot time
# Description:       Enable amavis service
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
PIDFILE=/var/run/amavis/amavisd.pid
SOCKET=/var/run/amavis/amavisd.sock

case "$1" in
  start)
    if [ -f "$PIDFILE" ]; then
      echo "Already running"
    else
      echo "Starting amavisd"
      /usr/local/sbin/amavisd -u amavis
    fi
    ;;
  stop)
    if [ -f "$PIDFILE" ]; then
      echo "Stopping amavisd"
      kill `cat $PIDFILE`
    else
      echo "Not running"
    fi
    ;;
  restart)
    echo "Restarting amavisd"
    $0 stop
    sleep 1
    $0 start
    ;;
  reload)
    echo "Reloading amavisd"
    kill -HUP `cat /var/amavis/amavisd.pid`
    ;;
  *)
    echo "Usage: /etc/init.d/amavisd {start|stop}"
    exit 1
    ;;
esac

exit 0

also create the directory /var/run/amavis.

mkdir /var/run/amavis
chown amavis:amavis /var/run/amavis
chmod 700 /var/run/amavis

and finally set executable bit and enable the service:

chmod +x /etc/init.d/amavisd
update-rc.d amavisd defaults

and start the service:

service amavisd start

Configure clamav

Add the clamav user to the amavis group

make sure the following lines are enabled in /etc/amavisd.conf (note the change from .sock to .ctl).

['ClamAV-clamd',
  \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd.ctl"],
  qr/\bOK$/m, qr/\bFOUND$/m,
  qr/^.*?: (?!Infected Archive)(.*) FOUND$/m ],

and make sure

AllowSupplementaryGroups true

is set in /etc/clamav/clamd.conf. This is the default setting (at least in Debian squeeze).

gpasswd -a clamav

and finally start clamd-daemon

service clamav-daemon start

Make /tmp a bit more secure

Add the following line to /etc/fstab. As per recommendation in amavisd-new install instructions.

tmpfs             /tmp          tmpfs      noexec,nosuid,nodev    0 0

After that, create a new file /etc/apt/apt.conf.d/50extracttemplates. Apt uses /tmp per default running installation scripts and if we add noexec to /tmp, this will make sure this doesn’t happen.

APT
{
  ExtractTemplates
  {
    TempDir "/var/tmp";
  };
};

Create users

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/vmail -m
chown -R vmail:vmail /var/vmail
chmod u+w /var/vmail

Install modoboa with pip

pip install modoboa

This will download, compile and install modoboa and what’s needed to run the whole shebang.

Create databases and user

mysql -u root -p
create database modoboa;
create database amavis;
grant all privileges on modoboa.* to 'modoboa'@'localhost'
identified by 'somepassword';
grant all privileges on amavis.* to 'amavis'@'localhost'
identified by 'someotherpassword';
flush privileges;

Create amavis tables

I’ve removed (some) comments to save pixels. Please refer to the amavis documentation for the whole thing. It’s pure SQL so you can cut and paste. If you get errors. Take one query at the time.

use amavis;
CREATE TABLE users (
  id         int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,  -- unique id
  priority   integer      NOT NULL DEFAULT '7',  -- sort field, 0 is low prior.
  policy_id  integer unsigned NOT NULL DEFAULT '1',  -- JOINs with policy.id
  email      varbinary(255) NOT NULL UNIQUE,
  fullname   varchar(255) DEFAULT NULL    -- not used by amavisd-new
  -- local   char(1)      -- Y/N  (optional field, see note further down)
);

CREATE TABLE mailaddr (
  id         int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
  priority   integer      NOT NULL DEFAULT '7',  -- 0 is low priority
  email      varbinary(255) NOT NULL UNIQUE
);

CREATE TABLE wblist (
  rid        integer unsigned NOT NULL,  -- recipient: users.id
  sid        integer unsigned NOT NULL,  -- sender: mailaddr.id
  wb         varchar(10)  NOT NULL,  -- W or Y / B or N / space=neutral / score
  PRIMARY KEY (rid,sid)
);

CREATE TABLE policy (
  id  int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
                                    -- 'id' this is the _only_ required field
  policy_name      varchar(32),     -- not used by amavisd-new, a comment

  virus_lover           char(1) default NULL,     -- Y/N
  spam_lover            char(1) default NULL,     -- Y/N
  unchecked_lover       char(1) default NULL,     -- Y/N
  banned_files_lover    char(1) default NULL,     -- Y/N
  bad_header_lover      char(1) default NULL,     -- Y/N

  bypass_virus_checks   char(1) default NULL,     -- Y/N
  bypass_spam_checks    char(1) default NULL,     -- Y/N
  bypass_banned_checks  char(1) default NULL,     -- Y/N
  bypass_header_checks  char(1) default NULL,     -- Y/N

  spam_modifies_subj    char(1) default NULL,     -- Y/N

  virus_quarantine_to      varchar(64) default NULL,
  spam_quarantine_to       varchar(64) default NULL,
  banned_quarantine_to     varchar(64) default NULL,
  unchecked_quarantine_to  varchar(64) default NULL,
  bad_header_quarantine_to varchar(64) default NULL,
  clean_quarantine_to      varchar(64) default NULL,
  archive_quarantine_to    varchar(64) default NULL,

  spam_tag_level  float default NULL, -- higher score inserts spam info headers
  spam_tag2_level float default NULL, -- inserts 'declared spam' header fields
  spam_tag3_level float default NULL, -- inserts 'blatant spam' header fields
  spam_kill_level float default NULL, -- higher score triggers evasive actions
                                      -- e.g. reject/drop, quarantine, ...
                                     -- (subject to final_spam_destiny setting)
  spam_dsn_cutoff_level        float default NULL,
  spam_quarantine_cutoff_level float default NULL,

  addr_extension_virus      varchar(64) default NULL,
  addr_extension_spam       varchar(64) default NULL,
  addr_extension_banned     varchar(64) default NULL,
  addr_extension_bad_header varchar(64) default NULL,

  warnvirusrecip      char(1)     default NULL, -- Y/N
  warnbannedrecip     char(1)     default NULL, -- Y/N
  warnbadhrecip       char(1)     default NULL, -- Y/N
  newvirus_admin      varchar(64) default NULL,
  virus_admin         varchar(64) default NULL,
  banned_admin        varchar(64) default NULL,
  bad_header_admin    varchar(64) default NULL,
  spam_admin          varchar(64) default NULL,
  spam_subject_tag    varchar(64) default NULL,
  spam_subject_tag2   varchar(64) default NULL,
  spam_subject_tag3   varchar(64) default NULL,
  message_size_limit  integer     default NULL, -- max size in bytes, 0 disable
  banned_rulenames    varchar(64) default NULL, -- comma-separated list of ...
        -- names mapped through %banned_rules to actual banned_filename tables
  disclaimer_options  varchar(64) default NULL,
  forward_method      varchar(64) default NULL,
  sa_userconf         varchar(64) default NULL,
  sa_username         varchar(64) default NULL
);

CREATE TABLE maddr (
  partition_tag integer      DEFAULT 0, -- see $partition_tag
  id         bigint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
  email      varbinary(255)  NOT NULL,  -- full mail address
  domain     varchar(255)    NOT NULL,  -- only domain part of the email address
                                        -- with subdomain fields in reverse
  CONSTRAINT part_email UNIQUE (partition_tag,email)
) ENGINE=InnoDB;

CREATE TABLE msgs (
  partition_tag integer     DEFAULT 0,   -- see $partition_tag
  mail_id     varbinary(16) NOT NULL,    -- long-term unique mail id, dflt 12 ch
  secret_id   varbinary(16) DEFAULT '',  -- authorizes release of mail_id, 12 ch
  am_id       varchar(20)   NOT NULL,    -- id used in the log
  time_num    integer unsigned NOT NULL, -- rx_time: seconds since Unix epoch
  time_iso    char(16)      NOT NULL,    -- rx_time: ISO8601 UTC ascii time
  sid         bigint unsigned NOT NULL,  -- sender: maddr.id
  policy      varchar(255)  DEFAULT '',  -- policy bank path (like macro %p)
  client_addr varchar(255)  DEFAULT '',  -- SMTP client IP address (IPv4 or v6)
  size        integer unsigned NOT NULL, -- message size in bytes
  originating char(1) DEFAULT ' ' NOT NULL,  -- sender from inside or auth'd
  content     char(1),                   -- content type: V/B/U/S/Y/M/H/O/T/C
    -- virus/banned/unchecked/spam(kill)/spammy(tag2)/
    -- /bad-mime/bad-header/oversized/mta-err/clean
    -- is NULL on partially processed mail
    -- (prior to 2.7.0 the CC_SPAMMY was logged as 's', now 'Y' is used;
    -- to avoid a need for case-insenstivity in queries)
  quar_type  char(1),                   -- quarantined as: ' '/F/Z/B/Q/M/L
                                        --  none/file/zipfile/bsmtp/sql/
                                        --  /mailbox(smtp)/mailbox(lmtp)
  quar_loc   varbinary(255) DEFAULT '', -- quarantine location (e.g. file)
  dsn_sent   char(1),                   -- was DSN sent? Y/N/q (q=quenched)
  spam_level float,                     -- SA spam level (no boosts)
  message_id varchar(255)  DEFAULT '',  -- mail Message-ID header field
  from_addr  varchar(255)  CHARACTER SET utf8 COLLATE utf8_bin  DEFAULT '',
                                        -- mail From header field,    UTF8
  subject    varchar(255)  CHARACTER SET utf8 COLLATE utf8_bin  DEFAULT '',
                                        -- mail Subject header field, UTF8
  host       varchar(255)  NOT NULL,    -- hostname where amavisd is running
  PRIMARY KEY (partition_tag,mail_id)
-- FOREIGN KEY (sid) REFERENCES maddr(id) ON DELETE RESTRICT
) ENGINE=InnoDB;
CREATE INDEX msgs_idx_sid      ON msgs (sid);
CREATE INDEX msgs_idx_mess_id  ON msgs (message_id); -- useful with pen pals
CREATE INDEX msgs_idx_time_num ON msgs (time_num);
-- alternatively when purging based on time_iso (instead of msgs_idx_time_num):
-- CREATE INDEX msgs_idx_time_iso ON msgs (time_iso);

CREATE TABLE msgrcpt (
  partition_tag integer    DEFAULT 0,    -- see $partition_tag
  mail_id    varbinary(16) NOT NULL,     -- (must allow duplicates)
  rseqnum    integer  DEFAULT 0   NOT NULL, -- recip's enumeration within msg
  rid        bigint unsigned NOT NULL,   -- recipient: maddr.id (dupl. allowed)
  is_local   char(1)  DEFAULT ' ' NOT NULL, -- recip is: Y=local, N=foreign
  content    char(1)  DEFAULT ' ' NOT NULL, -- content type V/B/U/S/Y/M/H/O/T/C
  ds         char(1)  NOT NULL,          -- delivery status: P/R/B/D/T
                                         -- pass/reject/bounce/discard/tempfail
  rs         char(1)  NOT NULL,          -- release status: initialized to ' '
  bl         char(1)  DEFAULT ' ',       -- sender blacklisted by this recip
  wl         char(1)  DEFAULT ' ',       -- sender whitelisted by this recip
  bspam_level float,                     -- per-recipient (total) spam level
  smtp_resp  varchar(255)  DEFAULT '',   -- SMTP response given to MTA
  PRIMARY KEY (partition_tag,mail_id,rseqnum)
-- FOREIGN KEY (rid)     REFERENCES maddr(id)     ON DELETE RESTRICT,
-- FOREIGN KEY (mail_id) REFERENCES msgs(mail_id) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE INDEX msgrcpt_idx_mail_id  ON msgrcpt (mail_id);
CREATE INDEX msgrcpt_idx_rid      ON msgrcpt (rid);

CREATE TABLE quarantine (
  partition_tag integer    DEFAULT 0,    -- see $partition_tag
  mail_id    varbinary(16) NOT NULL,     -- long-term unique mail id
  chunk_ind  integer unsigned NOT NULL,  -- chunk number, starting with 1
  mail_text  blob          NOT NULL,     -- store mail as chunks of octets
  PRIMARY KEY (partition_tag,mail_id,chunk_ind)
-- FOREIGN KEY (mail_id) REFERENCES msgs(mail_id) ON DELETE CASCADE
) ENGINE=InnoDB;

Deploy modoboa

mkdir /var/www && cd /var/www
modoboa-admin.py deploy --syncdb --collectstatic --with-amavis mailadmin
cd mailadmin
python manage.py collectstatic
python manage.py syncdb --migrate --noinput
python manage.py loaddata initial_users.json

Configure postfix

Use the modoboa-admin.py script to create these files automatically.

modoboa-admin.py postfix_maps --dbtype mysql /etc/postfix/maps

Answer the questions with the values you used earlier. The database is the modoboa database.

Fix permissions. Since these files contain your database passwords and it’s only postfix that need to read them.

chown root:postfix /etc/postfix/maps/sql-*
chmod 640 /etc/postfix/maps/sql-*

configure postfix

postconf -e mailbox_transport=virtual
postconf -e maildrop_destination_recipient_limit=1
postconf -e virtual_minimum_uid=5000
postconf -e virtual_gid_maps=static:5000
postconf -e virtual_uid_maps=static:5000
postconf -e virtual_mailbox_base=/var/vmail
postconf -e relay_domains=
postconf -e virtual_mailbox_domains=mysql:/etc/postfix/maps/sql-domains.cf
postconf -e virtual_alias_domains=mysql:/etc/postfix/maps/sql-domain-aliases.cf
postconf -e virtual_mailbox_maps=mysql:/etc/postfix/maps/sql-mailboxes.cf
postconf -e virtual_alias_maps=mysql:/etc/postfix/maps/sql-aliases.cf,mysql:/etc/postfix/maps/sql-domain-aliases-mailboxes.cf,mysql:/etc/postfix/maps/sql-email2email.cf,mysql:/etc/postfix/maps/sql-catchall-aliases.cf
postconf -e virtual_transport=dovecot
postconf -e dovecot_destination_recipient_limit=1

add definition to /etc/postfix/master.cf

dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}

and then restart postfix

service postfix restart

configure nginx

Now we’ll install Green Unicorn and configure nginx. I know, there is a package included with Debian, don’t use that, use easy_install as described here to get the latest version instead.

Green Unicorn

easy_install -U gunicorn

create a gunicorn config file /var/www/mailadmin/gunicorn.conf.py

backlog = 2048
bind = "unix:/var/run/gunicorn/modoboa.sock"
pidfile = "/var/run/gunicorn/modoboa.pid"
daemon = True
debug = False
workers = 2
logfile = "/var/log/gunicorn/modoboa.log"
loglevel = "info"

Now, gunicorn won’t run without /var/run/gunicorn, let’s create it.

mkdir /var/run/gunicorn

then create a init script, /etc/init.d/modoboa:

#!/bin/sh
# /etc/init.d/modoboa

### BEGIN INIT INFO
# Provides: modoboa
# Required-Start:    $local_fs $remote_fs $network $syslog $time
# Required-Stop:     $local_fs $remote_fs $network $syslog 
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start modoboa at boot time
# Description:       Enable modoboa service
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MODOBOA_ROOT=/var/www/mailadmin
LOGFILE=/var/log/modoboa.log
PIDFILE=/var/run/gunicorn/modoboa.pid
SOCKET=/var/run/gunicorn/modoboa.sock

case "$1" in
  start)
    if [ -f "$PIDFILE" ]; then
      echo "Already running"
    else
      echo "Starting modoboa"
      cd $MODOBOA_ROOT
      gunicorn_django --error-log $LOGFILE -c gunicorn.conf.py
    fi
    ;;
  stop)
    if [ -f "$PIDFILE" ]; then
      echo "Stopping modoboa"
      kill -QUIT `cat /var/run/gunicorn/modoboa.pid`
    else
      echo "Not running"
    fi
    ;;
  restart)
    echo "Restarting modoboa"
    $0 stop
    sleep 1
    $0 start
    ;;
  reload)
    echo "Reloading modoboa"
    kill -HUP `cat /var/run/gunicorn/modoboa.pid`
    ;;
  *)
    echo "Usage: /etc/init.d/modoboa {start|stop}"
    exit 1
    ;;
esac

exit 0

set executable bit and enable the service:

chmod +x /etc/init.d/modoboa
update-rc.d modoboa defaults

and finally start it

service modoboa start

nginx

now create a config file for nginx

vi /etc/nginx/sites-available/modoboa

change as it suits you:

upstream modoboa {
        server  unix:/var/run/gunicorn/modoboa.sock fail_timeout=0;
}

server {
        listen 443;
        server_name <fqdn>;
        root /var/www/mailadmin/mailadmin/;

        ssl on;
        ssl_certificate /etc/ssl/<fqdn>.pem;
        ssl_certificate_key /etc/ssl/<fqdn>.key;

        # if you're serve other stuff; it might be good to use separate logfile
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        location /sitestatic/ {
                autoindex on;
        }

        location /media/ {
                autoindex on;
        }

        location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_set_header X-Forwarded-Protocol ssl;
                proxy_pass http://modoboa;
        }
}

change path to your cert and key accordingly. you can read here how to enable ssl and generate a self signed cert/key pair. You can use the same cert/key for dovecot below if you have the same fdqn on web- and mailserver.

Now enable the site and restart nginx. Make sure the certificates excist, otherwise nginx won’t start.

ln -s /etc/nginx/sites-available/modoboa /etc/nginx/sites-enabled/modoboa
service nginx restart

You shold now be able to login using the default username: admin and password: password at https://<fqdn>. First thing you do is to change the password! First time you save modoboa settings, some tables are creted. Do that and then run the following snippets.

Change MAILDIR_ROOT

Change default maildir root from .maildir/ to just /. I think it’s prettier, and I already used this on a server I migrated from. This is optional.

echo "update modoboa.lib_parameter set value = '/' where name = 'admin.MAILDIR_ROOT';" | mysql -u root -p

Create a SECRET_KEY

echo "update modoboa.lib_parameter set value = '`pwgen -N 1 -s 32`' where name = 'auth.SECRET_KEY';" | mysql -u root -p

Change NOTIFICATIONS_SENDER

echo "update modoboa.lib_parameter set value = 'admin@domain.com' where name = 'amavis.NOTIFICATIONS_SENDER';" | mysql -u root -p

Configure dovecot

I won’t go into detail here. I’ll just paste an example config file. NOT COMPLETE YET!

# if you, like me, have mail stored on nfs use these settings so index files doesn't get corrupted (according to dovecot manual)
mmap_disable = yes
dotlock_use_excl = no
mail_nfs_storage = yes
mail_nfs_index = yes

login_processes_count=16 
login_max_processes_count=256
mail_max_userip_connections=20
protocols = imap imaps pop3 pop3s managesieve
disable_plaintext_auth=no
log_timestamp = "%Y-%m-%d %H:%M:%S"
# certificates
ssl_ca_file = /etc/ssl/certs/ca-certificates.crt 
ssl_cert_file = /etc/ssl/mail.crt
ssl_key_file = /etc/ssl/mail.key

# needed for fail2ban to work
auth_verbose=yes

log_path = /var/log/dovecot.log 
info_log_path = /var/log/dovecot-info.log
mail_location = maildir:/var/vmail/%d/%n

namespace private {
	separator=.
	inbox = yes
}

mail_privileged_group = mail

protocol pop3 {
	pop3_uidl_format = %08Xu%08Xv
}

protocol imap {
	mail_plugins = quota imap_quota
}

plugin {
	sieve_global_path = /var/vmail/globalsieverc
	sieve_dir=/var/vmail/%d/%n/sieve
	sieve=/var/vmail/%d/%n/.dovecot.sieve
	quota = maildir:User quota
	quota_rule = *:storage=100M
	quota_rule2 = Trash:storage=50M
}

protocol managesieve {
	login_executable = /usr/lib/dovecot/managesieve-login
	mail_executable = /usr/lib/dovecot/managesieve
	managesieve_max_line_length = 65536
	managesieve_logout_format = bytes=%i/%o
	#managesieve_implementation_string = Cyrus timsieved v2.2.13
}

protocol lda {
	postmaster_address = admin@dalnix.se
	auth_socket_path = /var/run/dovecot/auth-master
	mail_plugins = sieve
	log_path = /var/log/dovecot-deliver-errors.log
	info_log_path = /var/log/dovecot-deliver.log
}

auth default {
	mechanisms = plain login
	passdb sql {
		args = /etc/dovecot/dovecot-sql.conf
	}
	userdb sql {
		args = /etc/dovecot/dovecot-sql.conf
	}
	user = root
	socket listen {
		master {
			path = /var/run/dovecot/auth-master
			mode = 0600
			user = vmail
		}
		client {
			path = /var/spool/postfix/private/auth
			mode = 0660
			user = postfix
		}
	}
}

now create /etc/dovecot/dovecot-sql.conf.

driver = mysql
connect = host=localhost dbname=modoboa user=modoboa password=somepassword
default_pass_scheme = CRYPT
password_query = SELECT email AS user, password FROM auth_user WHERE email='%u' and is_active=1
user_query = SELECT concat('/', dom.name, '/', mb.path) AS home, uid, gid, concat('*:storage=', mb.quota, 'M') AS quota_rule FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.address='%n' AND dom.name='%d'

and then restart dovecot

service dovecot restart

Troubleshooting

Relay access denied

If you get lines like these in your /etc/mail.log.

Mar 15 18:59:19 mail postfix/smtpd[4012]: NOQUEUE: reject: RCPT from mail-qe0-f48.google.com[209.85.128.48]: 454 4.7.1 <joe@example.com>: Relay access denied; from=<mrbad@gmail.com> to=<joe@example.com> proto=ESMTP helo=<mail-qe0-f48.google.com>

Make sure the domain/account is actually enabled in modoboa. I had some trouble figuring this out after doing an import of alot of domains and all apparantly got imported without beeing enabled (my bad).

5 svar på ”mailserver setup”

  1. Hi,

    Am unable to launch the gunucorn server. Any help will be much appreciated.

    Bellow is the /var/log/modoboa.log output.

    http://pastebin.com/NJ0M1VyG

    ValueError: Unable to configure handler ’modoboa’: Cannot resolve ’modoboa.lib.logutils.SQLHandler’: cannot import name connection

    1. Hi, I’m sorry but I can’t help you. I’m not really a pyhon guru. Plus this guide is quite old and probably won’t work for Modoboa 1.0.

      You’ll get better help asking in the #modoboa irc channel on Freenode etc.

  2. Hi

    You should mention that you need to specify ALLOWED_HOSTS in settings.py for the django app to get it up and running with nginx.

    Regards
    Paul

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *