вівторок, 28 грудня 2010 р.

Email Service for Development Needs

What's this all about?

This article covers the setup of email delivery service, suited for non-production use (like development). The important for production aspects like spam and virus checking, compatibility with legacy clients and security were intentionally not covered, though you can use this article for bootstrap setup and add all that features on top of it.

Required skills

You should feel yourself easy with Linux and Google, understand what email is (i hope you do, if not leave me your address, I'll send you a postcard), understand what IMAP, SASL, SMTP is for, being a geek in system administration  is not required.

Needed software

We will need software. Let's setup some. We will need to install exim(heavyweight version which comes with SASL support), Cyrus SASL, Cyrus IMAP and their admin tools.
grim@kepler:~$ sudo apt-get install exim4 exim4-daemon-heavy
grim@kepler:~$ sudo apt-get install sasl2-bin libsasl2-2 libsasl2-modules
grim@kepler:~$ sudo apt-get install cyrus-imapd-2.2 cyrus-admin-2.2 cyrus-clients-2.2

Basic configuration

When you're done with installation, you'll get all that preconfigured with defaults, which you want to change to suit your site.

You will find that saslauthd is disabled by default. To enable it, edit /etc/default/saslauthd and set START=yes, it's already there, you need to change the options. Also add sasldb to list of authentication mechanisms, that saslauthd daemon will use.

grim@kepler:~$ sudo vim /etc/default/saslauthd
MECHANISMS="sasldb pam"

Restart the service after that:

grim@kepler:~$ sudo /etc/init.d/saslauthd restart

Also, you will need to do basic configuration of exim MTA. This is where dpkg steps in:

grim@kepler:~$ sudo dpkg-reconfigure --priority=low exim4-config

I'll be using modular configuration in this article, so make sure you'll choose to split your configuration into small files when asked.

Binding it together

Now we're done with saslauthd and basic things, let's bind it together. First of all we need to let our MTA to use SASL. By default only users from group sasl can use SASL, so Debian-exim user, under which exim runs must be added to sasl group.

After that I'm going to create test1 user with ChangeMe1 password and finally check that exim can authenticate with SASL.

grim@kepler:~$ sudo adduser Debian-exim sasl
grim@kepler:~$ sudo saslpasswd2 -c -f /etc/sasldb2 test1
Again (for verification):

grim@kepler:~$ sudo -u Debian-exim testsaslauthd -u test1 -p ChangeMe1
0: OK "Success."

Cool! Now we're safe with OS-level stuff and can proceed with exim and Cyrus configuration, to make mail delivery actually happen.

Making delivery actually happen - Configuring exim MTA

Here we have three things to tune. First is authenticators (not quite necessary), second is router and third is transport (these two are the must).


To enable authentication of users through SASL, you will just need to uncomment the readily available authenticators, available in /etc/exim4/conf.d/auth/30_exim4-config_examples. Edit that file with editor of your taste, find and uncomment the below lines:

# Authenticate against local passwords using sasl2-bin
# Requires exim_uid to be a member of sasl group, see README.Debian.gz
  driver = plaintext
  public_name = PLAIN
  server_condition = ${if saslauthd{{$auth2}{$auth3}}{1}{0}}
  server_set_id = $auth2
  server_prompts = :
  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}

  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"
  # don't send system passwords over unencrypted connections
  server_condition = ${if saslauthd{{$auth1}{$auth2}}{1}{0}}
  server_set_id = $auth1
  server_advertise_condition = ${if eq{$tls_cipher}{}{}{*}}

Note that configuring TLS is out of the scope of the current article. Maybe I'll find some time to go in depth of TLS later, but for now add the guarding macro  definition to /etc/exim4/conf.d/main/00_localmacros file.


Router and transport

Unfortunately I didn't found on the Net any readily available solutions for building mail delivery system based on SASL user database. So I've cleaned off the rust from my Perl skills and wrote the plugin for exim that can check if the user is present in sasl db. 

Download it here and put it /etc/exim4/ folder. After that's done, add the following option to your /etc/exim4/conf.d/main/00_localmacros file:

perl_startup = do '/etc/exim4/exim.pm'

The module can be tested from command line like this:

grim@kepler:~$ sudo perl -Mexim -e "check_sasldb_user test1"
Debug output is enabled
Checking sasldb for given user: test1
  test1@kepler: userPassword
User found

Now, when script is in place and confirmed to be working we should proceed with router and transport setup.

Create the file for router called /etc/exim4/conf.d/router/910_sasldb_user and put the below router definition there.

  debug_print = "R: sasldb_user for $local_part@$domain"
  condition = ${perl{check_sasldb_user}}
  driver = accept
  domains = +local_domains
  local_parts = ! root
  transport = cyrus_delivery
  cannot_route_message = Unknown user

Create the file for transport called /etc/exim4/conf.d/transport/30_cyrus_imapd and put the below transport definition there

  driver = pipe
  command = /usr/sbin/cyrdeliver $local_part
  user = cyrus
  group = mail
  message_prefix =
  message_suffix =

After all these changes we are ready to update exim configuration and restart it.

grim@kepler:~$ sudo update-exim4.conf
grim@kepler:~$ sudo /etc/init.d/exim4 restart

To check if that worked, you can test the delivery using -bt option like this:

grim@kepler:/etc/exim4$ exim -bt test1
R: system_aliases for test1@kepler.linuxgears.org
R: sasldb_user for test1@kepler.linuxgears.org
  router = sasldb_user, transport = cyrus_delivery

Making delivery actually happen - Configuring Cyrus IMAP

Again we need to make sure cyrus user is in sasl group, so /etc/sasldb2 is readable by Cyrus apps.

grim@kepler:~$ sudo adduser cyrus sasl

Then make sure that the user cyrus is in the admins: line in /etc/imapd.conf.

# Uncomment the following and add the space-separated users who
# have admin rights for all services.
admins: cyrus

Restart cyrus with

grim@kepler:/etc/exim4$ sudo /etc/init.d/cyrus2.2 restart

One last thing is setting up the password for cyrus user. Use saslpasswd2 tool, just like above for test1 user:

grim@kepler:/etc/exim4$ sudo saslpasswd2 -c cyrus

Now you can adminsiter imap mailboxes. Run cyradm to connect to cyrus daemon:

cyradm -u cyrus localhost
Enter the password when asked and create a mailbox for your first user.

localhost> cm user.test1
localhost> quit


Finally test the availability of your service through direct SMTP session to the host.

grim@blackbox:~$ telnet kepler 25
Connected to kepler.linuxgears.org.
Escape character is '^]'.
220 kepler ESMTP Exim 4.71 Sun, 26 Dec 2010 22:51:08 +0200
EHLO snuke
250-kepler Hello 77-52-53-233.dialup.umc.net.ua []
250-SIZE 52428800
250 HELP
MAIL FROM: <oleksiy.khilkevich@gmail.com>
250 OK
RCPT TO: <test1@kepler.linuxgears.org>
250 Accepted
354 Enter message, ending with "." on a line by itself
From: Oleksiy
To: Test1

250 OK id=1PWxad-0002LE-Jfa
Connection closed by foreign host.

And you may want to test your IMAP server works
 with imtest

grim@blackbox:~$ imtest -a test1 -w ChangeMe1 localhost
S: * OK kepler Cyrus IMAP4 v2.2.13-Debian-2.2.13-19 server ready
S: C01 OK Completed
S: + bm9uY2U9InNjcjFvYkZkYnc5b05aeDNBcVJOKzNRaTVDY0NEVjBJOE1MYmFtVGwwdW89IixyZWFsbT0ia2VwbGVyIixxb3A9ImF1dGgsYXV0aC1pbnQsYXV0aC1jb25mIixjaXBoZXI9InJjNC00MCxyYzQtNTYscmM0LGRlcywzZGVzIixtYXhidWY9NDA5NixjaGFyc2V0PXV0Zi04LGFsZ29yaXRobT1tZDUtc2Vzcw==
C: dXNlcm5hbWU9InRlc3QxIixyZWFsbT0ia2VwbGVyIixub25jZT0ic2NyMW9iRmRidzlvTlp4M0FxUk4rM1FpNUNjQ0RWMEk4TUxiYW1UbDB1bz0iLGNub25jZT0iUnBPVGliTXBCNjU2ek10d0tycmhnNDJQRm1HN01KQ3FuOXVOUVVjYTRvVT0iLG5jPTAwMDAwMDAxLHFvcD1hdXRoLWNvbmYsY2lwaGVyPXJjNCxtYXhidWY9MTAyNCxkaWdlc3QtdXJpPSJpbWFwL2xvY2FsaG9zdCIscmVzcG9uc2U9MTFmODhmNTkxMzQ4MWUxOTMyMzgwN2RjZTQxNDlhYmU=
S: + cnNwYXV0aD1kMDc4YjM2MDc1NDRkNTJmYjZiYTBlNmQwMWJhYjliNg==
S: A01 OK Success (privacy protection)

Security strength factor: 128
Connection closed.

Now you can tell it is working.

Webmail setup

Now, when we have the delivery chain configured, the next thing is to install some webmail system, so you can view the incoming messages easy way.

If you are just as poor as me, you'll probably have only one dedicated server available, and if you are just as itchy for experiments as me, you'd probably already have some services on it, like web server and app server. If that is the case, the ports 80 and 8080 are most probably to be busy or will be busy in the near future. In addition to that, I didn't want to mess with other sites, I wanted this all thing to be kind of separate, so I could easily change it or switch it on/off without much impact.

That's why we're gonna setup separate Apache virtual host on port 81.

For webmail software I've chosen RoundCube (http://roundcube.net/) which is quite nice and easy to deploy and what's more important can work with SQLite as a backend DB.

First we'll install all dependencies RC requires:

grim@kepler:~$ sudo apt-get install apache2 libapache2-mod-php5 sqlite php5-sqlite php5-mcrypt php5-intl

Next is to create new Apache virtual host. To do that add below lines to /etc/apache2/ports.conf

NameVirtualHost *:81
Listen 81

Next go to /etc/apache2/sites-available and copy file called default to default-81.

grim@kepler:~$ cd /etc/apache2/sites-available/
grim@kepler:/etc/apache2/sites-available$ sudo cp default default-81

Edit the file, and change the virtual host configuration to refer to the port 81.
You may also want to change DocumentRoot and some other options. As for me I've left most of the file intact and changed below lines: 

<VirtualHost *:81>
    DocumentRoot /srv/www-81
    <Directory /srv/www-81/>
    ErrorLog /var/log/apache2/error-default-81.log
    CustomLog /var/log/apache2/access-default-81.log combined

Now we are ok to enable the virtual host. Do it with command:

grim@kepler:~$ sudo a2ensite default-81

Check the configuration for errors and restart the web server.

grim@kepler:~$ apache2ctl -S
apache2: Could not reliably determine the server's fully qualified domain name, using for ServerName
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:81                   is a NameVirtualHost
         default server (/etc/apache2/sites-enabled/default-81:1)
         port 81 namevhost (/etc/apache2/sites-enabled/default-81:1)
*:80                   is a NameVirtualHost
         default server (/etc/apache2/sites-enabled/000-default:1)
         port 80 namevhost (/etc/apache2/sites-enabled/000-default:1)
Syntax OK
grim@kepler:~$ sudo /etc/init.d/apache2 graceful

You can try access the site at port 81(for my case that'd be http://kepler:81/)

I'll not be covering installation of RoundCube here, as there is already really self-explanatory article at http://wiki.kartbuilding.net/index.php/Roundcube, if you'll find any problems with adapting it for your installation, feel free to ask for help.

So as a final goal you should have http://<your-host>:81/roundcube/ showing the RC login page.

Great, now I've done all this long, so what do I have?

Now you have the working mail service, were you can easily add/remove users, send/receive emails on behalf of them and watch that emails through web interface.


I didn't covered the Cyrus IMAP and SASL usage in this install. If you find troubles using it, feel free to ask in comments, or send me the mail.


[1] https://help.ubuntu.com/8.04/serverguide/C/exim4.html
[2] http://www.exim.org/exim-html-current/doc/html/spec_html/ch12.html
[3] http://flakey.info/mailserver/
[4] http://www.exim.org/docs.html

Немає коментарів:

Дописати коментар