[Wheezy] Exim4 + Courier mit MySQL-Backend

[Wheezy] Exim4 + Courier mit MySQL-Backend

Version 1.00

Author: Ilya Beliaev

In diesem Tutorial handelt es sich um die Installation eines Mailservers mit Exim4, Courier und einem vollen MySQL-Backend für virtuelle Benutzer.
Voraussetzung für diese Installation ist ein Debian Wheezy Server.

1.0 Pakete installieren

Wichtige Pakete installieren:

apt-get install exim4-daemon-heavy libsasl2-modules-sql courier-pop courier-imap courier-authlib-mysql maildrop mysql-server php5 php5-mysql

Notiz:
MySQL Root Kennwort sorgfälltig wählen!

2.0 Weitere Datenbank/DB-User für virtuelle Benutzer anlegen

mysql -u root -p

Root Passwort eintippen….

CREATE USER 'maildb'@'maildb' IDENTIFIED BY '{password}';
GRANT USAGE ON * . * TO 'maildb'@'maildb' IDENTIFIED BY '{password}' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
CREATE DATABASE IF NOT EXISTS `maildb` ;
GRANT ALL PRIVILEGES ON `maildb` . * TO 'maildb'@'maildb';

Hier bitte die Variable gegen ein richtiges Passwort für den Benutzer maildb ersetzen und diese gut merken. Diesen Benutzer werden wir benötigen um unserem Mailserver mitzuteilen mit welchen Logindaten er auf die Datenbank „maildb“ zugreien darf.

2.1 Anlegen der nötigen Tabellen

USE maildb;

CREATE TABLE IF NOT EXISTS `domains` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `domain` varchar(255) NOT NULL DEFAULT '',
  `aliasdomain` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `domain` (`domain`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(255) NOT NULL DEFAULT '',
  `username` varchar(255) NOT NULL DEFAULT '',
  `password` varchar(128) NOT NULL DEFAULT '',
  `uid` int(11) NOT NULL DEFAULT '2000',
  `gid` int(11) NOT NULL DEFAULT '2000',
  `homedir` varchar(255) NOT NULL DEFAULT '/home/mailusers/',
  `maildir` varchar(255) NOT NULL DEFAULT '',
  `domainid` int(11) unsigned NOT NULL DEFAULT '0',
  `quota` bigint(13) NOT NULL DEFAULT '0',
  `pop3` tinyint(1) NOT NULL DEFAULT '1',
  `imap` tinyint(1) NOT NULL DEFAULT '1',
  FOREIGN KEY (domainid) REFERENCES domains(id)
    ON UPDATE CASCADE
	ON DELETE CASCADE,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `virtual` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(255) NOT NULL DEFAULT '',
  `email_full` varchar(255) NOT NULL DEFAULT '',
  `destination` text NOT NULL,
  `domainid` int(11) unsigned NOT NULL DEFAULT '0',
  `popaccountid` int(11) unsigned NOT NULL DEFAULT '0',
  `iscatchall` tinyint(1) unsigned NOT NULL DEFAULT '0',
   FOREIGN KEY (domainid) REFERENCES domains(id)
    ON UPDATE CASCADE
	ON DELETE CASCADE,
   FOREIGN KEY (popaccountid) REFERENCES users(id)
    ON UPDATE CASCADE
	ON DELETE CASCADE,
  PRIMARY KEY (`id`),
  KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

3.0 Re-Konfiguration von Exim4

Als erstes sollten wir die Standardkonfiguration vom Exim4 ändern. Dazu konfigurieren wir mittels DPKG das Paket um.

Re-Konfiguration von Exm4:

dpkg-reconfigure exim4-config

Konfiguration:

General type of mail configuation:
internet site; mail is sent and received directly using smtp

System mail name:
ihredomain.tld

IP-addresses to listen on for incoming SMTP connections:
0.0.0.0

Other destinations for which mail is accepted:
Ihre statische IP-Adresse

Domains to relay mail for:
Keine Angabe

Machines to relay mail for:
Keine Angabe

Keep number of DNS-queries minimal:
no

Delivery method for local mail:
Maildir format in home directory

Split configuration into small files?:
yes

Root and postmaster mail recipient:
Keine Angabe

3.1 Verzeichnisse anlegen

Als nächstes legen wir uns das erste Verzeichnis an. example.tld ist ihre Domain sowie „user“ ihr gewünschter Username.

mkdir /home/mailusers/example.tld/user/
maildirmake /home/mailusers/example.tld/user/Maildir

3.2 User anlegen

Hier legen wir uns den Systembenutzer für den Zugriff auf die Emails an und weisen ihm das Verzeichnis

/home/mailusers

zu.

groupadd -g 2000 vmail
useradd -u 2000 -s /bin/false -d /bin/null -g vmail vmail
chown -R 2000:2000 /home/mailusers

3.3 Exim4 auf MySQL umstellen

Als nächstes müssen wir einige Konfigurationen an den Konfigdateien von Exim4 vornehmen:

cd /etc/exim4/conf.d/

nano auth/30_exim4-config

Inhalt einsetzen und als neue Datei speichern:

plain_server:
  driver = plaintext
  public_name = PLAIN
  server_condition = "${if and {
                        {!eq{$2}{}}
                        {!eq{$3}{}}
                        {crypteq{$3}{${lookup mysql{PHPDEV_AUTH_LOGIN}{$value}fail}}}
                        } {yes}{no}}"
  server_set_id = $2
  server_prompts = :
#   .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
#   server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}
#   .endif

login_server:
  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"
  server_condition = "${if and {
                        {!eq{$1}{}}
                        {!eq{$2}{}}
                        {crypteq{$2}{${lookup mysql{PHPDEV_AUTH_LOGIN}{$value}fail}}}
                        } {yes}{no}}"
  server_set_id = $1
#   .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
#   server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}
#   .endif

nano main/10_exim4-config_options

Inhalt einfügen und speichern:

hide mysql_servers = 127.0.0.1/maildb/maildb/{password}

PHPDEV_LOCAL_DOMAIN	= SELECT domain FROM domains WHERE domain = '${quote_mysql:$domain}'

PHPDEV_MAILALIAS		= SELECT REPLACE(destination,' ',',') FROM virtual WHERE
				(( email = '${quote_mysql:$local_part}@${quote_mysql:$domain}' )
				OR ( email = '@${quote_mysql:$domain}' AND iscatchall > 0 ))
				AND destination <> '' AND destination <> ' ' ORDER BY iscatchall ASC LIMIT 1

PHPDEV_MAILUSER		= SELECT CONCAT(homedir,maildir) FROM users WHERE
				email = '${quote_mysql:$local_part}@${quote_mysql:$domain}'

PHPDEV_PARENT_DOMAIN	= SELECT parent.domain FROM `domains` AS parent INNER JOIN domains AS alias
				ON alias.domain = '${quote_mysql:$domain}' AND parent.id = alias.aliasdomain

PHPDEV_AUTH_PLAIN	= SELECT password FROM users WHERE username = '${quote_mysql:$2}'

PHPDEV_AUTH_LOGIN	= SELECT password FROM users WHERE username = '${quote_mysql:$1}'

domainlist phpdev_domain = mysql;PHPDEV_LOCAL_DOMAIN

Hier sollten Sie {password} gegen das Passwort des Datenbankbenutzers „maildb“ ersetzen.

nano router/180_exim4-config

Inhalt einfügen und speichern:

phpdev_mailalias:
  debug_print = "R: phpdev_mailalias for $local_part@$domain"
  driver = redirect
  domains = +phpdev_domain
  data = ${lookup mysql {PHPDEV_MAILALIAS}{$value}fail}

phpdev_mailuser:
  debug_print = "R: phpdev_mailuser for $local_part@$domain"
  driver = redirect
  domains = +phpdev_domain
  data = ${lookup mysql {PHPDEV_MAILUSER}{$value}fail}
  directory_transport = maildir_phpdev
  no_more

nano transport/30_exim4-config

Inhalt einfügen und speichern:

maildir_phpdev:
  debug_print = "T: maildir_phpdev for $local_part@$domain"
  driver = appendfile
  create_directory
  delivery_date_add
  envelope_to_add
  return_path_add
  maildir_format
  directory_mode = 0770
  mode = 0660
  mode_fail_narrower = false
  user = 2000
  group = 2000

nano acl/30_exim4-config_check_rcpt

Inhalt ersetzen gegen:

### acl/30_exim4-config_check_rcpt
#################################

acl_check_rcpt:
  accept
    hosts = :

  warn
    hosts = +relay_from_hosts
    control = submission/sender_retain

  .ifdef CHECK_RCPT_LOCAL_LOCALPARTS
  deny
    domains = +local_domains:+phpdev_domain
    local_parts = CHECK_RCPT_LOCAL_LOCALPARTS
    message = restricted characters in address
  .endif

  .ifdef CHECK_RCPT_REMOTE_LOCALPARTS
  deny
    domains = !+local_domains
    local_parts = CHECK_RCPT_REMOTE_LOCALPARTS
    message = restricted characters in address
  .endif

  accept
    .ifndef CHECK_RCPT_POSTMASTER
    local_parts = postmaster
    .else
    local_parts = CHECK_RCPT_POSTMASTER
    .endif
    domains = +local_domains:+phpdev_domain

  deny
    message = sender envelope address $sender_address is locally blacklisted here. If you think this is wrong, get in touch with postmaster
    !acl = acl_local_deny_exceptions
    senders = ${if exists{CONFDIR/local_sender_blacklist}
                   {CONFDIR/local_sender_blacklist}
                   {}}

  deny
    message = sender IP address $sender_host_address is locally blacklisted here. If you think this is wrong, get in touch with postmaster
    !acl = acl_local_deny_exceptions
    hosts = ${if exists{CONFDIR/local_host_blacklist}
                 {CONFDIR/local_host_blacklist}
                 {}}

  .ifdef CHECK_RCPT_VERIFY_SENDER
  deny
    message = Sender verification failed
    !acl = acl_local_deny_exceptions
    !verify = sender
  .endif

  deny
    !acl = acl_local_deny_exceptions
    senders = ${if exists{CONFDIR/local_sender_callout}
                         {CONFDIR/local_sender_callout}
                   {}}
    !verify = sender/callout

  deny
    !acl = acl_local_deny_exceptions
    recipients = ${if exists{CONFDIR/local_rcpt_callout}
                            {CONFDIR/local_rcpt_callout}
                      {}}
    !verify = recipient/callout

  .ifdef CHECK_RCPT_REVERSE_DNS
  warn
    message = X-Host-Lookup-Failed: Reverse DNS lookup failed for $sender_host_address (${if eq{$host_lookup_failed}{1}{failed}{deferred}})
     condition = ${if and{{def:sender_host_address}{!def:sender_host_name}}
                      {yes}{no}}
  .endif

  .ifdef CHECK_RCPT_IP_DNSBLS
  warn
    message = X-Warning: $sender_host_address is listed at $dnslist_domain ($dnslist_value: $dnslist_text)
    log_message = $sender_host_address is listed at $dnslist_domain ($dnslist_value: $dnslist_text)
    dnslists = CHECK_RCPT_IP_DNSBLS
  .endif

  .ifdef CHECK_RCPT_DOMAIN_DNSBLS
  warn
    message = X-Warning: $sender_address_domain is listed at $dnslist_domain ($dnslist_value: $dnslist_text)
    log_message = $sender_address_domain is listed at $dnslist_domain ($dnslist_value: $dnslist_text)
    !senders = ${if exists{CONFDIR/local_domain_dnsbl_whitelist}
                    {CONFDIR/local_domain_dnsbl_whitelist}
                    {}}
    dnslists = CHECK_RCPT_DOMAIN_DNSBLS/$sender_address_domain
  .endif

  .ifdef CHECK_RCPT_LOCAL_ACL_FILE
  .include CHECK_RCPT_LOCAL_ACL_FILE
  .endif

  accept
    domains = +local_domains:+phpdev_domain
    endpass
    message = unknown user
    verify = recipient

  accept
    domains = +relay_to_domains
    endpass
    .ifdef CHECK_RCPT_GIVE_UNKNOWN_USER
    message = ${if eq{$acl_verify_message}{Unrouteable address}{unknown user}{$acl_verify_message}}
    .else
    message = unrouteable address
    .endif
    verify = recipient

  ############
  # If control reaches this point, the domain is neither in +local_domains
  # nor in +relay_to_domains.
  ############

  accept
    hosts = +relay_from_hosts

  accept
    authenticated = *

  deny
    message = relay not permitted

Jetzt zu fast guter letzt noch den chmod für die Konfigurationen ändern und Exim4 neustarten.

chmod o-rx /var/lib/exim4
chmod o-rx /etc/exim4/conf.d/main/10_exim4-config_options
/etc/init.d/exim4 restart

4.0 Konfiguration von POP und IMAP (Courier)

nano /etc/courier/authdaemonrc

Inhalt ersetzen gegen:

##VERSION: $Id: authdaemonrc.in,v 1.8 2001/10/07 02:16:22 mrsam Exp $
#
# Copyright 2000-2001 Double Precision, Inc.  See COPYING for
# distribution information.
#
# authdaemonrc created from authdaemonrc.dist by sysconftool
#
# Do not alter lines that begin with ##, they are used when upgrading
# this configuration.
#
# This file configures authdaemond, the resident authentication daemon.
#
# Comments in this file are ignored.  Although this file is intended to
# be sourced as a shell script, authdaemond parses it manually, so
# the acceptable syntax is a bit limited.  Multiline variable contents,
# with the  continuation character, are not allowed.  Everything must
# fit on one line.  Do not use any additional whitespace for indentation,
# or anything else.

##NAME: authmodulelist:0
#
# The authentication modules that are linked into authdaemond.  The
# default list is installed.  You may selectively disable modules simply
# by removing them from the following list.  The available modules you
# can use are: authcustom authcram authuserdb authldap authmysql authpam

authmodulelist="authmysql"

##NAME: authmodulelistorig:1
#
# This setting is used by Courier's webadmin module, and should be left
# alone

authmodulelistorig="authcustom authcram authuserdb authldap authmysql authpam"

##NAME: daemons:0
#
# The number of daemon processes that are started.  authdaemon is typically
# installed where authentication modules are relatively expensive: such
# as authldap, or authmysql, so it's better to have a number of them running.
# PLEASE NOTE:  Some platforms may experience a problem if there's more than
# one daemon.  Specifically, SystemV derived platforms that use TLI with
# socket emulation.  I'm suspicious of TLI's ability to handle multiple
# processes accepting connections on the same filesystem domain socket.
#
# You may need to increase daemons if as your system load increases.  Symptoms
# include sporadic authentication failures.  If you start getting
# authentication failures, increase daemons.  However, the default of 5
# SHOULD be sufficient.  Bumping up daemon count is only a short-term
# solution.  The permanent solution is to add more resources: RAM, faster
# disks, faster CPUs...

daemons=5

##NAME: version:0
#
# When you have multiple versions of authdaemond.* installed, authdaemond
# just picks the first one it finds.  Set "version" to override that.
# For example:  version=authdaemond.plain

version=""

##NAME: authdaemonvar:0
#
# authdaemonvar is here, but is not used directly by authdaemond.  It's
# used by various configuration and build scripts, so don't touch it!

authdaemonvar=/var/run/courier/authdaemon

nano /etc/courier/authmysqlrc

Inhalt ersetzen gegen:

MYSQL_SERVER 127.0.0.1
MYSQL_USERNAME maildb
MYSQL_PASSWORD {password}
MYSQL_PORT 3306
MYSQL_DATABASE maildb
MYSQL_USER_TABLE users
MYSQL_CRYPT_PWFIELD password
MYSQL_UID_FIELD uid
MYSQL_GID_FIELD gid
MYSQL_LOGIN_FIELD username
MYSQL_HOME_FIELD homedir
MYSQL_MAILDIR_FIELD maildir
MYSQL_QUOTA_FIELD (quota*1024*1024)
MYSQL_AUXOPTIONS_FIELD CONCAT("allowimap=",imap,",allowpop3=",pop3)

Auch hier sollten sie den Platzhalter „{password}“ gegen Ihr Passwort des Datenbankbenutzers „maildb“ ändern. Als nächstes müssen sie Courier neustarten um die Konfigurationen zu übernehmen.

/etc/init.d/courier-authdaemon restart
/etc/init.d/courier-pop restart

Sollten Sie jetzt noch das Interesse daran haben das Anlegen von Konten zu erleichtern können Sie mein Konfigurationsscript nutzen:

http://blog.php-dev.info/downloads/create_mail.7z

Nicht vergessen die Verbindungsdaten zum DBMS zu ändern!

Oder hier eine Komplette Konfiguration:

http://blog.php-dev.info/downloads/email.7z

Das könnte Dich auch interessieren …