Benutzer-Werkzeuge

Webseiten-Werkzeuge


freebsd:postfix_dovecot_virtual

Postfix with Dovecot2 and Virtualdomain with Mysql

Reference:

We use the following folder structure:

/usr/local/vmail/%d/%u/mail/
                 ^  ^  ^
                 |  |  |- Directory were emails are stored in maildir format
                 |  |- the username part of the email address
                 |- the domain
/usr/local/vmail/%d/%u/sieve/
                       ^- Folder to store sieve filters
/usr/local/etc/dovecot
               ^- Hold configuration files for dovecot
               dovecot/sieve
                        ^- Directory for global sieve scripts for all users
                        
/usr/local/etc/postfix
               ^- Hold configuration files for postfix                        

We will use Postfix, Dovecot2 with virtual domains managed by ViMbAdmin and everything stored on a mysql database. As password scheme BLF-CRYPT is used, see http://wiki2.dovecot.org/Authentication/PasswordSchemes.

Base System

I will start from a plain installation. Make sure your system is up to date:

portsnap fetch
portsnap update
freebsd-update fetch
freebsd-update install
reboot

Install MYSQL

cd /usr/ports/databases/mysql56-server/
make install clean
echo 'mysql_enable="YES"' >> /etc/rc.conf
service mysql-server start
mysql_secure_installation

Install amavisd-new

cd /usr/ports/security/amavisd-new
make install clean
sysrc amavisd_enable="YES"

Install clamav and clamsmtp

pkg install clamsmtp
pkg install clamav
sysrc clamsmtpd_enable="YES"
sysrc clamav_clamd_enable="YES"
sysrc clamav_freshclam_enable="YES"

Install mailman

cd /usr/ports/mail/mailman/
make install clean
(select DOCS, NLS, POSTFIX)

Install Apache/PHP

cd /usr/ports/databases/db6/
make install clean
cd /usr/ports/www/apache24/
make install clean
sysrc apache24_enable="YES"
sysrc apache24ssl_enable="YES"
sysrc apache24_http_accept_enable="YES"
cd /usr/ports/lang/php5-extensions
# select: MCRYPT, MYSQL, MYSQLI, PDO_MYSQL, IMAP, GETTEXT, JSON
make install clean
cd /usr/ports/databases/pecl-memcached
make install clean
cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini
cd /usr/ports/devel/php-composer
make install clean

Make sure correct timezone is set in php.ini:

/usr/local/etc/php.ini
date.timezone = "Europe/Berlin"

Install Dovecot

cd /usr/ports/mail/dovecot2
#(select MYSQL)
make install clean
sysrc dovecot_enable="YES"

Copy standard config files:

cp -a /usr/local/share/doc/dovecot/example-config/ /usr/local/etc/dovecot/
cd /usr/ports/mail/dovecot2-pigeonhole/
make install clean

Install Postfix

cd /usr/ports/mail/postfix
#(select MYSQL, SPF, TLS, DOVECOT2)
make install clean
sysrc sendmail_enable="NO"
sysrc sendmail_submit_enable="NO"
sysrc sendmail_outbound_enable="NO"
sysrc sendmail_msp_queue_enable="NO"
sysrc postfix_enable="YES"
 
sysrc -f /etc/periodic.conf daily_clean_hoststat_enable="NO"
sysrc -f /etc/periodic.conf daily_status_mail_rejects_enable="NO"
sysrc -f /etc/periodic.conf daily_status_include_submit_mailq="NO"
sysrc -f /etc/periodic.conf daily_submit_queuerun="NO"

Installing Postfix SPF

cd /usr/ports/mail/postfix-policyd-spf-perl
make install clean

Install ViMbAdmin

Create several accounts in the mysql database, we give the users only the rights they require, e.g. for dovecot and postfix user select permissions are enough. The account vimbadmin needs more rights to edit data (make sure the replace password! pwgen -s 20 is be a good start). Make sure that every user has an own password!

mysql -u root -p
create database vimbadmin;
grant all privileges on vimbadmin.* to 'vimbadmin'@'localhost' identified by 'password';
grant select on vimbadmin.* to 'dovecot'@'localhost' identified by 'password';
grant select on vimbadmin.* to 'postfix'@'localhost' identified by 'password';
exit

Install ViMbAdmin (follow the instruction https://github.com/opensolutions/ViMbAdmin/wiki/Installation):

mkdir -p /usr/local/www
cd /usr/local/www
git clone https://github.com/idefix6/ViMbAdmin.git
# git clone https://github.com/opensolutions/ViMbAdmin.git
cd ViMbAdmin
composer install --dev
chown -R www var/
cd public
cp .htaccess.dist .htaccess
cd ..

Make sure you change the following options (replace values with correct values for your domains):

/usr/local/www/ViMbAdmin/application/configs/application.ini
resources.doctrine2.connection.options.password = 'password'
 
defaults.mailbox.uid = 5000
defaults.mailbox.gid = 5000
 
defaults.mailbox.maildir = "maildir:/usr/local/vmail/%d/%u/mail:LAYOUT=fs"
defaults.mailbox.homedir = "/usr/local/vmail/%d/%u"
defaults.mailbox.min_password_length = 20
 
defaults.mailbox.password_scheme = "dovecot:BLF-CRYPT"
 
defaults.mailbox.dovecot_pw_binary = "/usr/local/bin/doveadm pw"
 
server.smtp.host    = "smtp-host-name"
 
server.pop3.host  = "pop3-hostname"
 
server.imap.host  = "imap-hostname"
 
server.webmail.host  = "https://webmail-hostname"
 
identity.orgname  = "Lostinspace"
identity.name  = "Lostinspace Support Team"
identity.email = "admins@hostname"
 
identity.autobot.name  = "ViMbAdmin Autobot"
identity.autobot.email = "autobot@hostname"
identity.mailer.name   = "ViMbAdmin Autobot"
identity.mailer.email  = "do-not-reply@hostname"
 
identity.siteurl = "https://link-to-vimbadmin-website/vimbadmin/"
 
server.email.name = "ViMbAdmin Administrator"
server.email.address = "support@example.com"

; If you have to authenticate on your mailserver to send email you want to set:
resources.mailer.smtphost = "localhost"
resources.mailer.username = "<user>"
resources.mailer.password = "<password>"
resources.mailer.auth     = "login"
resources.mailer.ssl      = "tls"
resources.mailer.port     = "587"
./bin/doctrine2-cli.php orm:schema-tool:create

Add the config section to the virtual host configuration file you want to add vimbadmin available:

/usr/local/etc/apache24/Includes/webmail.hostname.conf
...
Alias /vimbadmin "/usr/local/www/ViMbAdmin/public/"
<Directory "/usr/local/www/ViMbAdmin/public/">
    Options FollowSymLinks
    AllowOverride None
 
    Require all granted
 
    SetEnv APPLICATION_ENV production
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} -s [OR]
    RewriteCond %{REQUEST_FILENAME} -l [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^.*$ - [NC,L]
    RewriteRule ^.*$ /vimbadmin/index.php [NC,L]
 
</Directory>
...

Now access the website:

https://hostname/vimbadmin/

and follow the instructions there.

Create user and group that store the emails:

pw groupadd vmail -g 5000
pw useradd vmail -u 5000 -g vmail -s /usr/sbin/nologin -d /nonexistent -c "Virtual Mail Owner"
mkdir -p /usr/local/vmail
chown vmail /usr/local/vmail
chgrp vmail /usr/local/vmail
chmod 770 /usr/local/vmail

Configure Dovecot

Now we configure dovecot, set the config files based on this diff.:

diff -ur /usr/local/share/doc/dovecot/example-config/conf.d/10-auth.conf ./conf.d/10-auth.conf
--- /usr/local/share/doc/dovecot/example-config/conf.d/10-auth.conf     2014-08-19 20:38:20.043506000 +0200
+++ ./conf.d/10-auth.conf       2014-08-19 20:06:07.528052364 +0200
@@ -119,7 +119,7 @@
 #!include auth-deny.conf.ext
 #!include auth-master.conf.ext
 
-!include auth-system.conf.ext
+#!include auth-system.conf.ext
 #!include auth-sql.conf.ext
 #!include auth-ldap.conf.ext
 #!include auth-passwdfile.conf.ext
diff -ur /usr/local/share/doc/dovecot/example-config/conf.d/10-ssl.conf ./conf.d/10-ssl.conf
--- /usr/local/share/doc/dovecot/example-config/conf.d/10-ssl.conf      2014-08-19 20:38:20.044506000 +0200
+++ ./conf.d/10-ssl.conf        2014-08-19 22:27:15.827087484 +0200
@@ -9,8 +9,8 @@
 # dropping root privileges, so keep the key file unreadable by anyone but
 # root. Included doc/mkcert.sh can be used to easily generate self-signed
 # certificate, just make sure to update the domains in dovecot-openssl.cnf
-ssl_cert = </etc/ssl/certs/dovecot.pem
-ssl_key = </etc/ssl/private/dovecot.pem
+#ssl_cert = </etc/ssl/certs/dovecot.pem
+#ssl_key = </etc/ssl/private/dovecot.pem
 
 # If key file is password protected, give the password here. Alternatively
 # give it when starting dovecot with -p parameter. Since this file is often
diff -ur /usr/local/share/doc/dovecot/example-config/dovecot-sql.conf.ext ./dovecot-sql.conf.ext
--- /usr/local/share/doc/dovecot/example-config/dovecot-sql.conf.ext    2014-08-19 20:38:20.064506000 +0200
+++ ./dovecot-sql.conf.ext      2014-08-19 22:33:01.703040984 +0200
@@ -29,7 +29,7 @@
 # );
 
 # Database driver: mysql, pgsql, sqlite
-#driver =
+driver = mysql
 
 # Database connection string. This is driver-specific setting.
 #
@@ -68,14 +68,14 @@
 #   connect = host=sql.example.com dbname=virtual user=virtual password=blarg
 #   connect = /etc/dovecot/authdb.sqlite
 #
-#connect =
+connect = host=localhost dbname=vimbadmin user=dovecot password=<password>
 
 # Default password scheme.
 #
 # List of supported schemes is in
 # http://wiki2.dovecot.org/Authentication/PasswordSchemes
 #
-#default_pass_scheme = MD5
+default_pass_scheme = BLF-CRYPT
 
 # passdb query to retrieve the password. It can return fields:
 #   password - The user's password. This field must be returned.
@@ -137,5 +137,12 @@
 #    home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \
 #  FROM users WHERE userid = '%u'
 
+password_query = SELECT username as user, password as password, \
+        homedir AS userdb_home, maildir AS userdb_mail, \
+        concat('*:bytes=', quota) as userdb_quota_rule, uid as userdb_uid, gid as userdb_gid \
+    FROM mailbox \
+        WHERE username = '%Lu' AND active = '1' \
+            AND ( access_restriction = 'ALL' OR LOCATE( '%Us', access_restriction ) > 0 )
+
+user_query = SELECT homedir AS home, maildir AS mail, \
+        concat('*:bytes=', quota) as quota_rule, uid, gid \
+    FROM mailbox WHERE username = '%u'
 
 # Query to get a list of all usernames.
- #iterate_query = SELECT username AS user FROM users
+ iterate_query = SELECT username AS user FROM mailbox

Now create a new config file that hold all settings:

/usr/local/etc/dovecot/local.conf
service auth {
  unix_listener auth-userdb {
    mode = 0666
    user = vmail
    group = vmail
  }
 
  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
 
  # Auth process is run as this user.
  #user = $default_internal_user
  user=root
}
 
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0660
    group = postfix
    user = postfix
  }
  user = vmail
}
 
# ***** Configure location for mailbox
mail_location = maildir:/usr/local/vmail/%d/%u
 
# ***** Authenticate against sql database *****
auth_mechanisms = plain login
passdb {
  driver = sql
  args = /usr/local/etc/dovecot/dovecot-sql.conf.ext
}
userdb {
  driver = prefetch
}
userdb {
  driver = sql
  args = /usr/local/etc/dovecot/dovecot-sql.conf.ext
}
 
 
# ***** use uid and gid for vmail
mail_uid = 5000
mail_gid = 5000
mail_privileged_group = 5000
mail_access_groups = 5000
first_valid_uid = 5000
last_valid_uid = 5000
first_valid_gid = 5000
last_valid_gid = 5000
 
maildir_copy_with_hardlinks = yes
 
# ***** Modules we use *****
mail_plugins = $mail_plugins
 
 
# **** SSL config *****
ssl = yes
ssl_cert = </usr/local/etc/apache24/ssl_keys/newcert.pem
ssl_key = </usr/local/etc/apache24/ssl_keys/req.pem
ssl_protocols = !SSLv2 !SSLv3
ssl_cipher_list = EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA
ssl_require_crl = no
ssl_prefer_server_ciphers = yes
ssl_dh_parameters_length = 2048
 
 
 
# **** Configure IMAP *****
protocol imap {
  # Space separated list of plugins to load (default is global mail_plugins).
  mail_plugins = $mail_plugins quota imap_quota
}
 
 
# ***** Configure POP3 *****
protocol pop3 {
  # Space separated list of plugins to load (default is global mail_plugins).
  mail_plugins = $mail_plugins quota
}
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
 
 
# ***** LDA Config *****
postmaster_address = postmaster@%d
hostname = anny.lostinspace.de
quota_full_tempfail = yes
recipient_delimiter = +
lda_mailbox_autocreate = yes
lda_mailbox_autosubscribe = yes
 
protocol lda {
  mail_plugins = $mail_plugins sieve quota
}
 
 
# ***** LMTP Config *****
protocol lmtp {
    postmaster_address = postmaster@%d
    mail_plugins = quota sieve
}
 
# ***** Plugin Configuration *****
plugin {
# autocreate plugin
# This plugin allows administrator to specify mailboxes that must always
# exist for all users. They can optionally also be subscribed. The
# mailboxes are created and subscribed always after user logs in.
# Namespaces are fully supported, so namespace prefixes need to be used
# where necessary.
  autocreate = Sent
  autocreate2 = Drafts
  autocreate3 = Junk
  autocreate4 = Trash
  #autocreate5 = ..etc..
  autosubscribe = Sent
  autosubscribe2 = Drafts
  autosubscribe3 = Junk
  autosubscribe4 = Trash
  #autosubscribe5 = ..etc
 
  sieve = ~/.sieve/dovecot.sieve
  sieve_dir = ~/sieve
  sieve_extensions = +notify +imapflags +spamtest +spamtestplus +relational +comparator-i;ascii-numeric
  sieve_before = /usr/local/etc/dovecot/sieve/
 
# ***** Quota Configuration *****
  quota = maildir:User quota
}
 
 
# ***** Configure Sieve *****
protocols = $protocols sieve
service managesieve-login {
  inet_listener sieve {
    port = 4190
  }
}
service managesieve {
}
 
protocol sieve {
}
 
##
## Mailbox definitions
##
 
# NOTE: Assumes "namespace inbox" has been defined in 10-mail.conf.
namespace inbox {
 
  #mailbox name {
    # auto=create will automatically create this mailbox.
    # auto=subscribe will both create and subscribe to the mailbox.
    #auto = no
 
    # Space separated list of IMAP SPECIAL-USE attributes as specified by
    # RFC 6154: \All \Archive \Drafts \Flagged \Junk \Sent \Trash
    #special_use =
  #}
 
  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    special_use = \Drafts
  }
  mailbox Junk {
    special_use = \Junk
  }
  mailbox Trash {
    special_use = \Trash
  }
 
  # For \Sent mailboxes there are two widely used names. We'll mark both of
  # them as \Sent. User typically deletes one of them if duplicates are created.
  mailbox Sent {
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
 
  # If you have a virtual "All messages" mailbox:
  #mailbox virtual/All {
  #  special_use = \All
  #}
 
  # If you have a virtual "Flagged" mailbox:
  #mailbox virtual/Flagged {
  #  special_use = \Flagged
  #}
}
 
# ***** Logging *****
auth_verbose = yes
auth_debug_passwords = yes
mail_debug = yes

To use the sieve plugin in Thunderbird use this here: https://github.com/thsmi/sieve/blob/master/nightly/README.md

Configure Sieve

As we configured the folder /usr/local/etc/dovecot/sieve to hold standard scripts for all users:

mkdir -p /usr/local/etc/dovecot/sieve
chown vmail:vmail /usr/local/etc/dovecot/sieve

Now create a new file with content:

/usr/local/dovecot/etc/dovecot/sieve/move-spam.sieve
require ["fileinto"];
if anyof (header :contains "X-Spam-Flag" "YES")
{
 fileinto "Junk";
}
/* Other messages get filed into INBOX */

Compile all rules:

cd /usr/local/etc/dovecot/sieve
sievec .
chown vmail .
chown vmail *
chgrp vmail .
chgrp vmail *

Migrate mbox to Maildir

We have to migrate a mbox to Maildir. The inbox is on: /var/mail/<user>. The other folders are /usr/home/<user>/mail.

Make sure the dovecot user can read/write to the folders (make sure you remember the permission to undo it):

chgrp vmail /var/mail
chmod g+w /var/mail
chgrp vmail /var/mail/<user>
chgrp -R vmail /usr/home/<user>/mail

Now we convert it:

dsync -v -u <newdovecotuser> mirror mbox:/usr/home/<user>/mail/:INBOX=/var/mail/<user>

Restore permissions on the old folder/files or remove them if migration was successfully finished.

Configure Mailman

/usr/local/mailman/Mailman/mm_cfg.py
MTA = 'Postfix'
POSTFIX_STYLE_VIRTUAL_DOMAINS = ['domain1.de', 'domain2.org' ]
SMTPHOST = 'full-smtp-host-name-to-connect'

Create required files:

cd /usr/local/mailman
bin/genaliases
chown mailman:mailman data/aliases*
chmod g+w data/aliases*
chown mailman:mailman data/virtual-mailman*
chmod g+w data/virtual-mailman*

Configure clamav

Copy standard configuration files and modify them:

cp clamd.conf.sample clamd.conf
cp freshclam.conf.sample freshclam.conf
cp clamsmtpd.conf.sample clamsmtpd.conf
/usr/local/etc/freshclam.conf
--- freshclam.conf.sample       2016-03-19 10:55:28.000000000 +0100
+++ freshclam.conf      2016-03-19 11:27:09.857817239 +0100
@@ -71,6 +71,7 @@
 # code. See http://www.iana.org/cctld/cctld-whois.htm for the full list.
 # You can use db.XY.ipv6.clamav.net for IPv6 connections.
 #DatabaseMirror db.XY.clamav.net
+DatabaseMirror db.de.clamav.net
/usr/local/etc/clamsmtpd.conf
--- clamsmtpd.conf.sample       2016-04-02 04:13:28.000000000 +0200
+++ clamsmtpd.conf      2016-04-02 12:46:37.399587985 +0200
@@ -8,7 +8,7 @@
 
 # The address to send scanned mail to.
 # This option is required unless TransparentProxy is enabled
-OutAddress: 10026
+OutAddress: 10029
 
 
 
@@ -26,13 +26,13 @@
 #XClient: off
 
 # Address to listen on (defaults to all local addresses on port 10025)
-#Listen: 0.0.0.0:10025
+Listen: 127.0.0.1:10028
 
 # The address clamd is listening on
-#ClamAddress: /var/run/clamav/clamd.sock
+ClamAddress: /var/run/clamav/clamd.sock
 
 # A header to add to all scanned email
-#Header: X-Virus-Scanned: ClamAV using ClamSMTP
+Header: X-Virus-Scanned: ClamAV using ClamSMTP
 
 # Directory for temporary files
 #TempDirectory: /tmp
@@ -47,7 +47,7 @@
 #TransparentProxy: off
 
 # User to switch to
-#User: clamav
+User: clamav
 
 # Virus actions: There's an option to run a script every time a virus is found.
 # !IMPORTANT! This can open a hole in your server's security big enough to drive

Configure Postfix

Create SSL related files:

cd /etc/mail/certs
cd /usr/local/etc/apache24/ssl_keys
openssl gendh -out dh_512.pem -2 512
openssl gendh -out dh_1024.pem -2 1024
openssl gendh -out dh_2048.pem -2 2048
openssl gendh -out dh_4096.pem -2 4096

Add the following lines to main.cf

/usr/local/etc/postfix/main.cf
# enable TLS
tls_append_default_CA = yes
smtpd_tls_received_header = yes
smtpd_tls_key_file = /usr/local/etc/apache24/ssl_keys/req.pem
smtpd_tls_cert_file = /usr/local/etc/apache24/ssl_keys/newcert.pem
#smtp_tls_CAfile= /etc/mail/certs/newcert.pem
#smtp_tls_CApath = /etc/mail/certs/
smtpd_tls_loglevel = 1
 
# enable smtp auth as Server
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions =
        reject_unknown_sender_domain,
        reject_unknown_recipient_domain,
        reject_unauth_pipelining,
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_invalid_hostname,
        reject_non_fqdn_sender,
        reject_non_fqdn_recipient,
        reject_unauth_destination,
        reject_unknown_reverse_client_hostname,
        reject_unknown_client,
        reject_unknown_hostname,
        check_client_access hash:/usr/local/etc/postfix/client_checks,
        check_sender_access hash:/usr/local/etc/postfix/sender_checks,
        reject_non_fqdn_hostname,
        check_policy_service unix:private/spf-policy,
        reject_rbl_client zen.spamhaus.org
 
smtpd_helo_restrictions =
        permit_mynetworks,
#       check_helo_access hash:/etc/postfix/ehlo_whitelist,
        reject_non_fqdn_hostname,
        reject_invalid_hostname
 
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
broken_sasl_auth_clients = yes
 
smtpd_helo_required = yes
strict_rfc821_envelopes = yes
disable_vrfy_command = yes
smtpd_delay_reject = yes
 
smtpd_sender_restrictions =
        permit_mynetworks,
        reject_unknown_sender_domain
#       check_sender_access hash:/etc/postfix/sender_access,
 
smtpd_data_restrictions =
        reject_unauth_pipelining
 
smtpd_client_restrictions =
        permit_sasl_authenticated,
        reject_rbl_client zen.spamhaus.org
#       check_client_access hash:/etc/postfix/client_access,
 
# enable ipv6 and ipv4
inet_protocols = all
 
# limit message size to 100MB
message_size_limit = 104857600
mailbox_size_limit = 512000000
 
# increase timeouts to prevent queue write file errors
#smtpd_timeout=600s
smtpd_proxy_timeout=600s
 
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated      defer_unauth_destination
 
# Virtual Domain Configuration
virtual_alias_maps = mysql:/usr/local/etc/postfix/mysql/virtual_alias_maps.cf,
                     hash:/usr/local/mailman/data/virtual-mailman
virtual_gid_maps = static:5000
virtual_mailbox_base = /usr/local/vmail
virtual_mailbox_domains = mysql:/usr/local/etc/postfix/mysql/virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/usr/local/etc/postfix/mysql/virtual_mailbox_maps.cf
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
#dovecot_destination_recipient_limit = 1
virtual_transport = lmtp:unix:private/dovecot-lmtp
 
home_mailbox = Maildir/
smtpd_sasl_authenticated_header = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
 
# Mailman
alias_maps = hash:/etc/mail/aliases,
             hash:/etc/mail/aliases.own,
             hash:/usr/local/mailman/data/aliases
 
# SPF
spf-policy_time_limit = 3600
 
# optimize SSL configuration
smtpd_tls_security_level = may
smtpd_tls_mandatory_protocols = !SSLv2 !SSLv3
smtpd_tls_protocols = !SSLv2 !SSLv3
smtpd_tls_dh1024_param_file = /usr/local/etc/apache24/ssl_keys/dh_2048.pem
smtpd_tls_dh512_param_file = /usr/local/etc/apache24/ssl_keys/dh_512.pem
smtpd_tls_eecdh_grade = strong
tls_preempt_cipherlist = yes
smtpd_tls_loglevel = 1
 
smtp_dns_support_level = dnssec
smtp_tls_security_level=dane
smtp_tls_mandatory_protocols = !SSLv2 !SSLv3
smtp_tls_protocols = !SSLv2, !SSLv3
smtp_tls_mandatory_ciphers = high
smtp_tls_loglevel = 1

Edit master.cf to have this:

/usr/local/etc/postfix/master.cf
smtp      inet  n       -       n       -       -       smtpd
smtpd     pass  -       -       n       -       -       smtpd
        -o content_filter=smtp-amavis:[127.0.0.1]:10024
submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
# options for amavis
smtp-amavis             unix    -               -               n               -               2               lmtp
    -o lmtp_data_done_timeout=1200
    -o lmtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
 
#  -o content_filter=lmtp:unix:/var/run/dspam.sock
# reinject mail from amavisd
[localhost]:10025 inet  n -       n       -       -        smtpd
  -o content_filter=clamav:[127.0.0.1]:10028
  -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
  -o smtpd_helo_restrictions=
  -o smtpd_client_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks=localhost
  -o smtpd_authorized_xforward_hosts=localhost
 
# SPF check
spf-policy      unix    -       n       n       -       0       spawn
  user=nobody argv=/usr/local/libexec/postfix-policyd-spf-perl
 
# AV scan filter (used by content_filter)
clamav     unix  -       -       n       -       16      smtp
    -o smtp_send_xforward_command=yes
    -o smtp_enforce_tls=no
    -o smtp_tls_security_level=none
# For injecting mail back into postfix from the clamav filter
127.0.0.1:10029 inet  n -       n       -       16      smtpd
    -o content_filter=
    -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
    -o smtpd_helo_restrictions=
    -o smtpd_client_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o mynetworks_style=host
    -o smtpd_authorized_xforward_hosts=localhost
    -o smtp_enforce_tls=no
    -o smtp_tls_security_level=none

Create SQL related configuration:

mkdir -p /usr/local/etc/postfix/mysql

Create the following files:

/usr/local/etc/postfix/mysql/virtual_alias_maps.cf
user = postfix
password = <password>
hosts = 127.0.0.1
dbname = vimbadmin
query = SELECT goto FROM alias WHERE address = '%s' AND active = '1'
/usr/local/etc/postfix/mysql/virtual_domains_maps.cf
user = postfix
password = <password>
hosts = 127.0.0.1
dbname = vimbadmin
query = SELECT domain FROM domain WHERE domain = '%s' AND backupmx = '0' AND active = '1'
/usr/local/etc/postfix/mysql/virtual_mailbox_maps.cf
user = postfix
password = <password>
hosts = 127.0.0.1
dbname = vimbadmin
table = mailbox
select_field = maildir
where_field = username
/usr/local/etc/postfix/mysql/virtual_transport_maps.cf
user = postfix
password = <password>
hosts = 127.0.0.1
dbname = vimbadmin
table = domain
select_field = transport
where_field = domain
additional_conditions = and backupmx = '0' and active = '1'

If you would like to block domain add the following lines:

/usr/local/etc/postfix/client_checks
IP/HOSTNAME    REJECT User unkown

To block senders:

/usr/local/etc/postfix/sender_checks
email    REJECT User unkown

Create the map with:

cd /usr/local/etc/postfix
postmap client_checks
postmap sender_checks

Make sure you build you alias databases

cd /etc/mail
postalias aliases
postalias aliases.own
...

Install and Configure SRS

SRS is sender Rewriting Scheme daemon which is required if you forward mails and to not break SPF.

cd /usr/ports/mail/postsrsd
make install clean
sysrc postsrsd_enable="YES"
sysrc postsrsd_flags=" -4"

Add to main.cf file from postfix:

/usr/local/etc/postfix/main.cf
# Sender Rewriting
sender_canonical_maps = tcp:127.0.0.1:10001
sender_canonical_classes = envelope_sender
recipient_canonical_maps = tcp:127.0.0.1:10002
recipient_canonical_classes= envelope_recipient

Start it with:

/usr/local/etc/rc.d/postsrsd restart
/usr/local/etc/rc.d/postfix restart

WARNING! Make sure you include all domains you host to the ignore list for postsrsd. If not that could break SPF setup and will in worst case cause that all emails are bounced and not accepted by remote mail servers!

/etc/rc.conf
postsrsd_exclude_domains="domain1.de,domain2.net,domain3.de"

Maybe you have to apply this patch to fix a bug: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=199797

Postscreen

Reference:

Postscreen is used to block spammers as early as possible using some checks including rbl lists.

Add the following lines in main.cf:

/usr/local/etc/postfix/main.cf
## Postscreen setup
postscreen_access_list = permit_mynetworks,cidr:/usr/local/etc/postfix/postscreen_access.cidr
postscreen_blacklist_action = drop
# DNS Blackhole Lists
postscreen_dnsbl_threshold = 8
postscreen_dnsbl_sites =
        b.barracudacentral.org=127.0.0.2*7
        dnsbl.inps.de=127.0.0.2*7
        bl.mailspike.net=127.0.0.2*5
        bl.mailspike.net=127.0.0.[10;11;12]*4
        dnsbl.sorbs.net=127.0.0.10*8
        dnsbl.sorbs.net=127.0.0.5*6
        dnsbl.sorbs.net=127.0.0.7*3
        dnsbl.sorbs.net=127.0.0.8*2
        dnsbl.sorbs.net=127.0.0.6*2
        dnsbl.sorbs.net=127.0.0.9*2
        zen.spamhaus.org=127.0.0.[10..11]*8
        zen.spamhaus.org=127.0.0.[4..7]*6
        zen.spamhaus.org=127.0.0.3*4
        zen.spamhaus.org=127.0.0.2*3
        bl.spamcop.net*2
        hostkarma.junkemailfilter.com=127.0.0.2*3
        hostkarma.junkemailfilter.com=127.0.0.4*1
        hostkarma.junkemailfilter.com=127.0.1.2*1
        dnsbl-1.uceprotect.net*2
        dnsbl-2.uceprotect.net*2
        dnsbl-3.uceprotect.net*3
        wl.mailspike.net=127.0.0.[18;19;20]*-2
        list.dnswl.org=127.0.[0..255].0*-3
        list.dnswl.org=127.0.[0..255].1*-4
        list.dnswl.org=127.0.[0..255].[2..255]*-6
        hostkarma.junkemailfilter.com=127.0.0.1*-2
postscreen_dnsbl_action = enforce
 
# Pregreeting
postscreen_greet_action = enforce
 
# Additional Postscreen Tests
postscreen_pipelining_enable = no
postscreen_non_smtp_command_enable = no
postscreen_non_smtp_command_action = drop
postscreen_bare_newline_enable = no

In master.cf remove the smtp line and add/change the following:

/usr/local/etc/postfix/master.cf
smtp      inet  n       -       n       -       1       postscreen
smtpd     pass  -       -       n       -       -       smtpd
        -o content_filter=smtp-amavis:[127.0.0.1]:10024
dnsblog   unix  -       -       n       -       0       dnsblog
tlsproxy  unix  -       -       n       -       0       tlsproxy

Create the file:

/usr/local/etc/postfix/postscreen_access.cidr
# Rules are evaluated in the order as specified.
127.0.0.1       permit
::1             permit

You must restart postfix if you have change the postscreen_access.cidr!

OpenDKIM (WIP)

References:

cd /usr/ports/mail/opendkim
make install clean
sysrc milteropendkim_enable="YES"
mkdir -p /var/db/opendkim
chown mailnull /var/db/opendkim/

Generate key for domain fechner.net

cd /var/db/opendkim
opendkim-genkey -r -D /var/db/opendkim -d fechner.net
mv default.private fechner.net.dkim.private
mv default.txt fechner.net.dkim.txt

Copy the public key to your DNS server:

cp fechner.net.dkim.txt /usr/local/etc/namedb/master/fechner.net/
chown bind /usr/local/etc/namedb/master/fechner.net/fechner.net.dkim.txt
chmod 644 /usr/local/etc/namedb/master/fechner.net/fechner.net.dkim.txt

Make sure your DNS zone includes:

; include dkim public key
$INCLUDE /usr/local/etc/namedb/master/fechner.net/fechner.net.dkim.txt
_adsp._domainkey        IN TXT "dkim=unknown"

Increase your serial and reload the zone. Make sure your zone is correct with:

host -t TXT default._domainkey.fechner.net
dig +norec @localhost -t TXT default._domainkey.fechner.net

Now we configure what key is used for what domain:

/usr/local/etc/mail/DkimSigningTable
# format:
#  $pattern     $keyname
*@fechner.net   fechner.net
/usr/local/etc/mail/DkimKeyTable
# format
#  $keyname     $domain:$selector:$keypath
fechner.net     fechner.net:default:/var/db/opendkim/fechner.net.dkim.private

The last part is the configuration file:

/usr/local/etc/mail/opendkim.conf
--- opendkim.conf.sample        2015-04-29 12:06:58.290800000 +0200
+++ opendkim.conf       2015-04-29 15:56:05.735861987 +0200
@@ -116,7 +116,7 @@
 ##  operation.  Thus, cores will be dumped here and configuration files
 ##  are read relative to this location.
 
-# BaseDirectory                /var/run/opendkim
+BaseDirectory          /var/db/opendkim
 
 ##  BodyLengthDB dataset
 ##     default (none)
@@ -175,7 +175,7 @@
 ##  Specify for which domain(s) signing should be done.  No default; must
 ##  be specified for signing.
 
-Domain                 example.com
+Domain                 anny.lostinspace.de
 
 ##  DomainKeysCompat { yes | no }
 ##     default "no"
@@ -261,7 +261,7 @@
 ##  a base64-encoded DER format private key, or a path to a file containing
 ##  one of those.
 
-# KeyTable             dataset
+KeyTable               /usr/local/etc/mail/DkimKeyTable
 
 ##  LocalADSP dataset
 ##     default (none)
@@ -290,7 +290,7 @@
 ##  in the amount of log data generated for each message, so it should be
 ##  limited to debugging use and not enabled for general operation.
 
-# LogWhy               no
+LogWhy         Yes
 
 ##  MacroList macro[=value][,...]
 ##
@@ -659,7 +659,7 @@
 ##  is set, all possible lookup keys will be attempted which may result
 ##  in multiple signatures being applied.
 
-# SigningTable         filename
+SigningTable           refile:/usr/local/etc/mail/DkimSigningTable
 
 ##  SingleAuthResult { yes | no}
 ##     default "no"
@@ -687,7 +687,7 @@
 ##  inet:port                  to listen on all interfaces
 ##  local:/path/to/socket      to listen on a UNIX domain socket
 
-Socket                 inet:port@localhost
+Socket                 inet:8891@localhost
 
 ##  SoftwareHeader { yes | no }
 ##     default "no"
@@ -746,7 +746,7 @@
 ##
 ##  Log success activity to syslog?
 
-# SyslogSuccess                No
+SyslogSuccess          Yes
 
 ##  TemporaryDirectory path
 ##     default /tmp

Now start the milter with:

/usr/local/etc/rc.d/milter-opendkim start

Check the /var/log/maillog for possible error messages, if you found no error message we can continue setting up postfix:

/usr/local/etc/postfix/main.cf
# OpenDKIM
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891

To test it write an email to check-auth@verifier.port25.com

OpenDmarc (WIP)

A first comment: I do NOT recommend to use DMARC. It breaks most of the existing mailing list and you will get problem from a lot mail servers, that are not configured 100% correctly. DMARC will cause a lot of false-positives. I decided to not use it for any domain I manage. Depending on your needs, this could be different.

References:

cd /usr/ports/mail/opendmarc
make install clean

Configuration:

cp /usr/local/etc/mail/opendmarc.conf.sample opendmarc.conf

Modify the configuration like this:

/usr/local/etc/mail/opendmarc.conf
--- opendmarc.conf.sample       2015-04-29 11:17:12.018006000 +0200
+++ opendmarc.conf      2015-04-30 05:35:34.395463225 +0200
@@ -90,7 +90,7 @@
 ##  Requests addition of the specified email address to the envelope of
 ##  any message that fails the DMARC evaluation.
 #
-# CopyFailuresTo postmaster@localhost
+CopyFailuresTo postmaster@fechner.net
 
 ##  DNSTimeout (integer)
 ##     default 5
@@ -118,7 +118,7 @@
 ##  purported sender of the message has requested such reports.  Reports are
 ##  formatted per RFC6591.
 #
-# FailureReports false
+FailureReports true
 
 ##  FailureReportsBcc (string)
 ##     default (none)
@@ -129,7 +129,7 @@
 ##  If no request is made, they address(es) are used in a To: field.  There
 ##  is no default.
 #
-# FailureReportsBcc postmaster@example.coom
+FailureReportsBcc postmaster@fechner.net
 
 ##  FailureReportsOnNone { true | false }
 ##     default "false"
@@ -273,7 +273,7 @@
 ##  either in the configuration file or on the command line.  If an IP
 ##  address is used, it must be enclosed in square brackets.
 #
-# Socket inet:8893@localhost
+Socket inet:8893@localhost
 
 ##  SoftwareHeader { true | false }
 ##     default "false"
@@ -283,7 +283,7 @@
 ##  delivery.  The product's name, version, and the job ID are included in
 ##  the header field's contents.
 #
-# SoftwareHeader false
+SoftwareHeader true
 
 ##  SPFIgnoreResults { true | false }
 ##     default "false"
@@ -312,7 +312,7 @@
 ##
 ##  Log via calls to syslog(3) any interesting activity.
 #
-# Syslog false
+Syslog true
 
 ##  SyslogFacility facility-name
 ##     default "mail"
@@ -343,7 +343,7 @@
 ##  specific file mode on creation regardless of the process umask.  See
 ##  umask(2) for more information.
 #
-# UMask 077
+UMask 0002
 
 ##  UserID user[:group]
 ##     default (none)
sysrc opendmarc_enable="YES"
touch /var/run/opendmarc.pid
chown mailnull:mailnull /var/run/opendmarc.pid
/usr/local/etc/rc.d/opendmarc start

In postfix add:

/usr/local/etc/postfix/main.cf
# OpenDKIM (port 8891), OpenDMARC (port 8893)
milter_default_action = accept
smtpd_milters = inet:localhost:8891, inet:localhost:8893
non_smtpd_milters = inet:localhost:8891, inet:localhost:8893

Restart postfix:

service postfix restart

The last step would be to add a dmarc TXT record to your DNS zone. You can use therefore:

A record could look like:

_dmarc                  IN TXT "v=DMARC1; p=none; sp=none; rua=mailto:postmaster@fechner.net; ruf=mailto:postmaster@fechner.net; rf=afrf; pct=100; ri=86400"

To test the setup you can send an email to mentioned addresses here: http://dmarc.org/resources/deployment-tools/

Antispam Plugin for Dovecot

cd /usr/ports/mail/dovecot2-antispam-plugin
make install clean
/usr/local/etc/dovecot/local.conf
# antispam plugin
protocol imap {
    mail_plugins = $mail_plugins antispam
}

SOLR integration in dovecot

Make sure dovecot is compiled with solr support.

Make sure solr is running.

Create a new core for solr:

su -m solr -c "/usr/local/solr/bin/solr create_core -c dovecot"

Make sure we switch result from json to xml by editing:

/var/db/solr/dovecot/conf/solrconfig.xml
  <!-- The following response writers are implicitly configured unless
       overridden...
    -->
     <queryResponseWriter name="xml"
                          default="true"
                          class="solr.XMLResponseWriter" />
  <!--

Copy the dovecot schema.xml configuration:

rm /var/db/solr/dovecot/conf/managed-schema

Create the schema file:

/var/db/solr/dovecot/conf/schema.xml
<?xml version="1.0" encoding="UTF-8" ?>
 
<!--
For fts-solr:
 
This is the Solr schema file, place it into solr/conf/schema.xml. You may
want to modify the tokenizers and filters.
-->
<schema name="dovecot" version="1.5">
    <!-- IMAP has 32bit unsigned ints but java ints are signed, so use longs -->
    <fieldType name="string" class="solr.StrField" />
    <fieldType name="long" class="solr.TrieLongField" />
 
    <fieldType name="text" class="solr.TextField" positionIncrementGap="100">
      <analyzer type="index">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.EnglishPossessiveFilterFactory"/>
        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
        <filter class="solr.EnglishMinimalStemFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.EnglishPossessiveFilterFactory"/>
        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
        <filter class="solr.EnglishMinimalStemFilterFactory"/>
      </analyzer>
    </fieldType>
 
    <!-- boolean type: "true" or "false" -->
    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
    <fieldType name="booleans" class="solr.BoolField" sortMissingLast="true" multiValued="true"/>
 
    <!--
      Numeric field types that index values using KD-trees.
      Point fields don't support FieldCache, so they must have docValues="true" if needed for sorting, faceting, functions, etc.
    -->
    <fieldType name="pint" class="solr.IntPointField" docValues="true"/>
    <fieldType name="pfloat" class="solr.FloatPointField" docValues="true"/>
    <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
    <fieldType name="pdouble" class="solr.DoublePointField" docValues="true"/>
 
    <fieldType name="pints" class="solr.IntPointField" docValues="true" multiValued="true"/>
    <fieldType name="pfloats" class="solr.FloatPointField" docValues="true" multiValued="true"/>
    <fieldType name="plongs" class="solr.LongPointField" docValues="true" multiValued="true"/>
    <fieldType name="pdoubles" class="solr.DoublePointField" docValues="true" multiValued="true"/>
 
 
    <!-- The format for this date field is of the form 1995-12-31T23:59:59Z, and
         is a more restricted form of the canonical representation of dateTime
         http://www.w3.org/TR/xmlschema-2/#dateTime
         The trailing "Z" designates UTC time and is mandatory.
         Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
         All other components are mandatory.
 
         Expressions can also be used to denote calculations that should be
         performed relative to "NOW" to determine the value, ie...
 
               NOW/HOUR
                  ... Round to the start of the current hour
               NOW-1DAY
                  ... Exactly 1 day prior to now
               NOW/DAY+6MONTHS+3DAYS
                  ... 6 months and 3 days in the future from the start of
                      the current day
 
      -->
    <!-- KD-tree versions of date fields -->
    <fieldType name="pdate" class="solr.DatePointField" docValues="true"/>
    <fieldType name="pdates" class="solr.DatePointField" docValues="true" multiValued="true"/>
 
    <!--Binary data type. The data should be sent/retrieved in as Base64 encoded Strings -->
    <fieldType name="binary" class="solr.BinaryField"/>
 
 
    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" multiValued="true">
      <analyzer type="index">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
        <!-- in this example, we will only use synonyms at query time
        <filter class="solr.SynonymGraphFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
        <filter class="solr.FlattenGraphFilterFactory"/>
        -->
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.StandardTokenizerFactory"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
        <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
        <filter class="solr.LowerCaseFilterFactory"/>
      </analyzer>
    </fieldType>
   <field name="id" type="string" indexed="true" stored="true" required="true" />
   <field name="uid" type="long" indexed="true" stored="true" required="true" />
   <field name="box" type="string" indexed="true" stored="true" required="true" />
   <field name="_text_" type="text_general" indexed="true" stored="false" multiValued="true"/>
   <field name="user" type="string" indexed="true" stored="true" required="true" />
 
   <field name="hdr" type="text" indexed="true" stored="false" />
   <field name="body" type="text" indexed="true" stored="false" />
 
   <field name="from" type="text" indexed="true" stored="false" />
   <field name="to" type="text" indexed="true" stored="false" />
   <field name="cc" type="text" indexed="true" stored="false" />
   <field name="bcc" type="text" indexed="true" stored="false" />
   <field name="subject" type="text" indexed="true" stored="false" />
 
   <!-- Used by Solr internally: -->
   <field name="_version_" type="long" indexed="true" stored="true"/>
 
 <uniqueKey>id</uniqueKey>
</schema>

Now restart solr and check the logfile:

tail -F /var/log/solr/solr.log
service solr restart

You should not see an error message but something like this:

2017-10-12 15:57:07.584 INFO  (searcherExecutor-7-thread-1-processing-x:dovecot) [   x:dovecot] o.a.s.c.SolrCore [dovecot] Registered new searcher Searcher@2ed6c198[dovecot] main{ExitableDirectoryReader(UninvertingDirectoryReader())}

Now we can configure dovecot.

/usr/local/etc/dovecot/conf.d/10-mail.conf
mail_plugins = $mail_plugins fts fts_solr
/usr/local/etc/dovecot/conf.d/90-plugin.conf
plugin {
    fts_autoindex = yes
    fts = solr
    fts_solr = url=http://127.0.0.1:8983/solr/dovecot/
}

Restart dovecot:

service dovecot restart

Keep the tail on the solr log file running and execute:

doveadm index -u idefix inbox

Now after some seconds you should see that solr is is indexing emails.

We would like to add some maintenance tasks for solr:

/etc/crontab
# Optimize solr dovecot storage
2               2               *               *               *               root    curl "http://127.0.0.1:8983/solr/dovecot/update?optimize=true"
5               */1             *               *               *               root    curl "http://127.0.0.1:8983/solr/dovecot/update?commit=true"

That's it, have fun ;)

freebsd/postfix_dovecot_virtual.txt · Zuletzt geändert: 2017/10/12 18:07 (Externe Bearbeitung)