mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-19 05:58:34 +02:00
476 lines
13 KiB
ReStructuredText
476 lines
13 KiB
ReStructuredText
###################
|
|
Dovecot and Postfix
|
|
###################
|
|
|
|
.. _dovecot:
|
|
|
|
*******
|
|
Dovecot
|
|
*******
|
|
|
|
Modoboa works better with Dovecot 2.0 so the following documentation
|
|
is suitable for this combination.
|
|
|
|
In this section, we assume dovecot's configuration resides in
|
|
:file:`/etc/dovecot`, all pathes will be relative to this directory.
|
|
|
|
Mailboxes
|
|
=========
|
|
|
|
First, edit the :file:`conf.d/10-mail.conf` and set the ``mail_location``
|
|
variable::
|
|
|
|
# maildir
|
|
mail_location = maildir:~/.maildir
|
|
|
|
Then, edit the ``inbox`` namespace and add the following lines::
|
|
|
|
inbox = yes
|
|
|
|
mailbox Drafts {
|
|
auto = create
|
|
special_use = \Drafts
|
|
}
|
|
mailbox Junk {
|
|
auto = create
|
|
special_use = \Junk
|
|
}
|
|
mailbox Sent {
|
|
auto = create
|
|
special_use = \Sent
|
|
}
|
|
mailbox Trash {
|
|
auto = create
|
|
special_use = \Trash
|
|
}
|
|
|
|
It ensures all the special mailboxes will be automaticaly created for
|
|
new accounts.
|
|
|
|
.. _fs_operations:
|
|
|
|
Operations on the file system
|
|
-----------------------------
|
|
|
|
Three operation types are considered:
|
|
|
|
#. Mailbox creation
|
|
#. Mailbox renaming
|
|
#. Mailbox deletion
|
|
|
|
The first one is managed by Dovecot. The last two ones may be managed
|
|
by Modoboa if it can access the file system where the mailboxes are
|
|
stored (see :ref:`admin-params` to activate this feature).
|
|
|
|
Those operations are treated asynchronously by a cron script. For
|
|
example, when you rename an e-mail address through the web UI, the
|
|
associated mailbox on the file system is not modified
|
|
directly. Instead of that, a *rename* order is created for this
|
|
mailbox. The mailbox will be considered unavailable until the order is
|
|
not executed (see :ref:`Postfix configuration <postfix_config>`).
|
|
|
|
Edit the crontab of the user who owns the mailboxes on the file system::
|
|
|
|
$ crontab -u <user> -e
|
|
|
|
And add the following line inside::
|
|
|
|
* * * * * python <modoboa_site>/manage.py handle_mailbox_operations
|
|
|
|
.. warning::
|
|
|
|
The cron script must be executed by the system user owning the mailboxes.
|
|
|
|
.. warning::
|
|
|
|
The user running the cron script must have access to the
|
|
:file:`settings.py` file of the modoboa instance.
|
|
|
|
The result of each order is recorded into Modoboa's log. Go to
|
|
*Modoboa > Logs* to consult them.
|
|
|
|
.. _dovecot_authentication:
|
|
|
|
Authentication
|
|
==============
|
|
|
|
To make the authentication work, edit the :file:`conf.d/10-auth.conf` and
|
|
uncomment the following line at the end::
|
|
|
|
#!include auth-system.conf.ext
|
|
!include auth-sql.conf.ext
|
|
#!include auth-ldap.conf.ext
|
|
#!include auth-passwdfile.conf.ext
|
|
#!include auth-checkpassword.conf.ext
|
|
#!include auth-vpopmail.conf.ext
|
|
#!include auth-static.conf.ext
|
|
|
|
|
|
Then, edit the :file:`conf.d/auth-sql.conf.ext` file and add the following
|
|
content inside::
|
|
|
|
passdb sql {
|
|
driver = sql
|
|
# Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
|
|
args = /etc/dovecot/dovecot-sql.conf.ext
|
|
}
|
|
|
|
userdb sql {
|
|
driver = sql
|
|
args = /etc/dovecot/dovecot-sql.conf.ext
|
|
}
|
|
|
|
Make sure to activate only one backend (per type) inside your configuration
|
|
(just comment the other ones).
|
|
|
|
Edit the :file:`dovecot-sql.conf.ext` and modify the configuration according
|
|
to your database engine.
|
|
|
|
.. _dovecot_mysql_queries:
|
|
|
|
MySQL users
|
|
-----------
|
|
|
|
::
|
|
|
|
driver = mysql
|
|
|
|
connect = host=<mysqld socket> dbname=<database> user=<user> password=<password>
|
|
|
|
default_pass_scheme = CRYPT
|
|
|
|
password_query = SELECT email AS user, password FROM core_user WHERE email='%u' and is_active=1
|
|
|
|
user_query = SELECT '<mailboxes storage directory>/%d/%n' AS home, <uid> as uid, <gid> as gid, concat('*:bytes=', 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'
|
|
|
|
iterate_query = SELECT email AS username FROM core_user
|
|
|
|
.. _dovecot_pg_queries:
|
|
|
|
PostgreSQL users
|
|
----------------
|
|
|
|
::
|
|
|
|
driver = pgsql
|
|
|
|
connect = host=<postgres socket> dbname=<database> user=<user> password=<password>
|
|
|
|
default_pass_scheme = CRYPT
|
|
|
|
password_query = SELECT email AS user, password FROM core_user WHERE email='%u' and is_active
|
|
|
|
user_query = SELECT '<mailboxes storage directory>/%d/%n' AS home, <uid> as uid, <gid> as gid, '*:bytes=' || 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'
|
|
|
|
iterate_query = SELECT email AS username FROM core_user
|
|
|
|
SQLite users
|
|
------------
|
|
|
|
::
|
|
|
|
driver = sqlite
|
|
|
|
connect = <path to the sqlite db file>
|
|
|
|
default_pass_scheme = CRYPT
|
|
|
|
password_query = SELECT email AS user, password FROM core_user WHERE email='%u' and is_active=1
|
|
|
|
user_query = SELECT '<mailboxes storage directory>/%d/%n' AS home, <uid> as uid, <gid> as gid, ('*:bytes=' || 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'
|
|
|
|
iterate_query = SELECT email AS username FROM core_user
|
|
|
|
.. note::
|
|
|
|
Replace values between ``<>`` with yours.
|
|
|
|
LDA
|
|
===
|
|
|
|
The LDA is activated by default but you must define a *postmaster*
|
|
address. Open the :file:`conf.d/15-lda.conf` file modify the following line::
|
|
|
|
postmaster_address = postmaster@<domain>
|
|
|
|
.. _dovecot_quota:
|
|
|
|
Quota
|
|
=====
|
|
|
|
Modoboa lets adminstrators define per-domain and/or per-account limits
|
|
(quota). It also lists the current quota usage of each account. Those
|
|
features require Dovecot to be configured in a specific way.
|
|
|
|
Inside :file:`conf.d/10-mail.conf`, add the ``quota`` plugin to the default
|
|
activated ones::
|
|
|
|
mail_plugins = quota
|
|
|
|
Inside :file:`conf.d/10-master.conf`, update the ``dict`` service to set
|
|
proper permissions::
|
|
|
|
service dict {
|
|
# If dict proxy is used, mail processes should have access to its socket.
|
|
# For example: mode=0660, group=vmail and global mail_access_groups=vmail
|
|
unix_listener dict {
|
|
mode = 0600
|
|
user = <user owning mailboxes>
|
|
#group =
|
|
}
|
|
}
|
|
|
|
Inside :file:`conf.d/20-imap.conf`, activate the ``imap_quota`` plugin::
|
|
|
|
protocol imap {
|
|
# ...
|
|
|
|
mail_plugins = $mail_plugins imap_quota
|
|
|
|
# ...
|
|
}
|
|
|
|
Inside :file:`dovecot.conf`, activate the quota SQL dictionary backend::
|
|
|
|
dict {
|
|
quota = <driver>:/etc/dovecot/dovecot-dict-sql.conf.ext
|
|
}
|
|
|
|
Inside :file:`conf.d/90-quota.conf`, activate the *quota dictionary* backend::
|
|
|
|
plugin {
|
|
quota = dict:User quota::proxy::quota
|
|
}
|
|
|
|
It will tell Dovecot to keep quota usage in the SQL dictionary.
|
|
|
|
Finally, edit the :file:`dovecot-dict-sql.conf.ext` file and put the
|
|
following content inside::
|
|
|
|
connect = host=<db host> dbname=<db name> user=<db user> password=<password>
|
|
# SQLite users
|
|
# connect = /path/to/the/database.db
|
|
|
|
map {
|
|
pattern = priv/quota/storage
|
|
table = admin_quota
|
|
username_field = username
|
|
value_field = bytes
|
|
}
|
|
map {
|
|
pattern = priv/quota/messages
|
|
table = admin_quota
|
|
username_field = username
|
|
value_field = messages
|
|
}
|
|
|
|
*PostgreSQL* users
|
|
------------------
|
|
|
|
Database schema update
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The ``admin_quota`` table is created by Django but unfortunately it
|
|
doesn't support ``DEFAULT`` constraints (it only simulates them when the
|
|
ORM is used). As PostgreSQL is a bit strict about constraint
|
|
violations, you must execute the following query manually::
|
|
|
|
db=> ALTER TABLE admin_quota ALTER COLUMN bytes SET DEFAULT 0;
|
|
db=> ALTER TABLE admin_quota ALTER COLUMN messages SET DEFAULT 0;
|
|
|
|
Trigger
|
|
^^^^^^^
|
|
|
|
As indicated on `Dovecot's wiki
|
|
<http://wiki2.dovecot.org/Quota/Dict>`_, you need a trigger to
|
|
properly update the quota. Unfortunately, the provided example won't
|
|
work for Modoboa. You should use the following one instead:
|
|
|
|
.. sourcecode:: sql
|
|
|
|
CREATE OR REPLACE FUNCTION merge_quota() RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
IF NEW.messages < 0 OR NEW.messages IS NULL THEN
|
|
-- ugly kludge: we came here from this function, really do try to insert
|
|
IF NEW.messages IS NULL THEN
|
|
NEW.messages = 0;
|
|
ELSE
|
|
NEW.messages = -NEW.messages;
|
|
END IF;
|
|
return NEW;
|
|
END IF;
|
|
|
|
LOOP
|
|
UPDATE admin_quota SET bytes = bytes + NEW.bytes,
|
|
messages = messages + NEW.messages
|
|
WHERE username = NEW.username;
|
|
IF found THEN
|
|
RETURN NULL;
|
|
END IF;
|
|
|
|
BEGIN
|
|
IF NEW.messages = 0 THEN
|
|
RETURN NEW;
|
|
ELSE
|
|
NEW.messages = - NEW.messages;
|
|
return NEW;
|
|
END IF;
|
|
EXCEPTION WHEN unique_violation THEN
|
|
-- someone just inserted the record, update it
|
|
END;
|
|
END LOOP;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE OR REPLACE FUNCTION set_mboxid() RETURNS TRIGGER AS $$
|
|
DECLARE
|
|
mboxid INTEGER;
|
|
BEGIN
|
|
SELECT admin_mailbox.id INTO STRICT mboxid FROM admin_mailbox INNER JOIN core_user ON admin_mailbox.user_id=core_user.id WHERE core_user.username=NEW.username;
|
|
UPDATE admin_quota SET mbox_id = mboxid
|
|
WHERE username = NEW.username;
|
|
RETURN NULL;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS mergequota ON admin_quota;
|
|
CREATE TRIGGER mergequota BEFORE INSERT ON admin_quota
|
|
FOR EACH ROW EXECUTE PROCEDURE merge_quota();
|
|
|
|
DROP TRIGGER IF EXISTS setmboxid ON admin_quota;
|
|
CREATE TRIGGER setmboxid AFTER INSERT ON admin_quota
|
|
FOR EACH ROW EXECUTE PROCEDURE set_mboxid();
|
|
|
|
Copy this example into a file (for example: :file:`quota-trigger.sql`) on
|
|
server running postgres and execute the following commands::
|
|
|
|
$ su - postgres
|
|
$ psql < /path/to/quota-trigger.sql
|
|
$ exit
|
|
|
|
Forcing recalculation
|
|
---------------------
|
|
|
|
For existing installations, *Dovecot* (> 2) offers a command to
|
|
recalculate the current quota usages. For example, if you want to
|
|
update all usages, run the following command::
|
|
|
|
$ doveadm quota recalc -A
|
|
|
|
Be carefull, it can take a while to execute.
|
|
|
|
ManageSieve/Sieve
|
|
=================
|
|
|
|
Modoboa lets users define filtering rules from the web interface. To
|
|
do so, it requires *ManageSieve* to be activated on your server.
|
|
|
|
Inside :file:`conf.d/20-managesieve.conf`, make sure the following lines are
|
|
uncommented::
|
|
|
|
protocols = $protocols sieve
|
|
|
|
service managesieve-login {
|
|
# ...
|
|
}
|
|
|
|
service managesieve {
|
|
# ...
|
|
}
|
|
|
|
protocol sieve {
|
|
# ...
|
|
}
|
|
|
|
Messages filtering using Sieve is done by the LDA.
|
|
|
|
Inside :file:`conf.d/15-lda.conf`, activate the ``sieve`` plugin like this::
|
|
|
|
protocol lda {
|
|
# Space separated list of plugins to load (default is global mail_plugins).
|
|
mail_plugins = $mail_plugins sieve
|
|
}
|
|
|
|
Finally, configure the ``sieve`` plugin by editing the
|
|
:file:`conf.d/90-sieve.conf` file. Put the follwing caontent inside::
|
|
|
|
plugin {
|
|
# Location of the active script. When ManageSieve is used this is actually
|
|
# a symlink pointing to the active script in the sieve storage directory.
|
|
sieve = ~/.dovecot.sieve
|
|
|
|
#
|
|
# The path to the directory where the personal Sieve scripts are stored. For
|
|
# ManageSieve this is where the uploaded scripts are stored.
|
|
sieve_dir = ~/sieve
|
|
}
|
|
|
|
Restart Dovecot.
|
|
|
|
.. _postfix:
|
|
|
|
*******
|
|
Postfix
|
|
*******
|
|
|
|
This section gives an example about building a simple virtual hosting
|
|
configuration with *Postfix*. Refer to the `official documentation
|
|
<http://www.postfix.org/VIRTUAL_README.html>`_ for more explanation.
|
|
|
|
Map files
|
|
=========
|
|
|
|
You first need to create configuration files (or map files) that will
|
|
be used by Postfix to lookup into Modoboa tables.
|
|
|
|
To automaticaly generate the requested map files and store them in a
|
|
directory, run the following command::
|
|
|
|
$ modoboa-admin.py postfix_maps --dbtype <mysql|postgres|sqlite> mapfiles
|
|
|
|
:file:`mapfiles` is the directory where the files will be
|
|
stored. Answer the few questions and you're done.
|
|
|
|
.. _postfix_config:
|
|
|
|
Configuration
|
|
=============
|
|
|
|
Use the following configuration in the :file:`/etc/postfix/main.cf` file
|
|
(this is just one possible configuration)::
|
|
|
|
# Stuff before
|
|
virtual_transport = dovecot
|
|
dovecot_destination_recipient_limit = 1
|
|
|
|
virtual_minimum_uid = <vmail user id>
|
|
virtual_gid_maps = static:<vmail group id>
|
|
virtual_uid_maps = static:<vmail user id>
|
|
virtual_mailbox_base = /var/vmail
|
|
|
|
relay_domains =
|
|
virtual_mailbox_domains = <driver>:/etc/postfix/sql-domains.cf
|
|
virtual_alias_domains = <driver>:/etc/postfix/sql-domain-aliases.cf
|
|
virtual_mailbox_maps = <driver>:/etc/postfix/sql-mailboxes.cf
|
|
virtual_alias_maps = <driver>:/etc/postfix/sql-aliases.cf,
|
|
<driver>:/etc/postfix/sql-domain-aliases-mailboxes.cf,
|
|
<driver>:/etc/postfix/sql-catchall-aliases.cf
|
|
|
|
smtpd_recipient_restrictions =
|
|
...
|
|
check_recipient_access <driver>:/etc/postfix/sql-maintain.cf
|
|
permit_mynetworks
|
|
...
|
|
|
|
# Stuff after
|
|
|
|
Replace ``<driver>`` by the name of the database you use.
|
|
|
|
Then, edit the :file:`/etc/postfix/master.cf` file and add the following
|
|
definition at the end::
|
|
|
|
dovecot unix - n n - - pipe
|
|
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}
|
|
|
|
Restart Postfix.
|