jeudi 5 avril 2012

IMAP with Dovecot2, and Sendmail

In the previous post, we configured SPF, DKIM and Spams filtering for Sendmail.

Most Engineering People know that a mail service is running at least two types of services :

  • SMTP, through which you can send mails
  • And one or more services from which you can retrieve mails you received
    • POP3, which enables you to retrieve your mail locally. There's no inside mailboxes, everything is in one place and you can't store mail from other mailboxes
    • IMAP, which enables you to read your mail locally but stores them on the server. Depending on imap service, you can create mailboxes (sub-folders) and store whatever mails you want inside it.
So POP3 is more simple than IMAP, but IMAP is really better if you don't want your mails to be stored locally, or not to lose your mails history if you install a new computer and don't want to migrate manually all your mails.
Not every company can afford to install IMAP service, and in most case a company considers you should only access your mails from work, they are related to work, you don't need to read them from outside etc etc.

Well, here is not the case, we first want to get out of Google Mail, even if we know we'll lose some features. We'll see here how to :

I had first installed dovecot 1, and configured it. It was working, but since the version 2 is out, I upgraded my configuration file. Also keep in mind that we're going to use SSL to connect to imap service, so don't bother much about the plain login authentication mechanisms.

To install dovecot2 on FreeBSD :

# cd /usr/ports/mail/dovecot2
# make config

We only need these two :

[*] KQUEUE    kqueue(2) support
[*] SSL       SSL support

Start the install :

# setenv BATCH 1
# make install clean
# unsetenv BATCH

Once it's installed, you need to configure dovecot. First I list here files :

# ll /usr/local/etc/dovecot
total 58
-r--r--r--  1 root  wheel    122 Mar  4 12:36 README
drwxr-xr-x  2 root  wheel    512 Mar  6 22:35 conf.d
-r--r--r--  1 root  wheel  52331 Mar  4 12:32 dovecot-1.conf
-r--r--r--  1 root  wheel   1125 Apr  4 09:27 dovecot.conf
# ll /usr/local/etc/dovecot/conf.d
total 4
-r--r--r--  1 root  wheel  2461 Apr  4 09:29 20-managesieve.conf

Since we want to request IMAP with SSL, we need to create a key and and certificate.
Let's decide we put our key and certificate in a folder : /usr/local/certs/dovecot
We're using an openssl .cnf file to help us create informations, and a script which will set environment to help us create the files.

# cat /usr/local/certs/dovecot/dovecot.cnf
HOME= .
RANDFILE = $ENV::HOME/.rnd

[ req ]
default_bits = 1024
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type

[ req_dn ]
countryName = Country Name (2 letter code)
countryName_default             = NO
countryName_min                 = 2
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Some-State

localityName                    = Locality Name (eg, city)

0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = FooBar Inc.

organizationalUnitName          = Organizational Unit Name (eg, section)
#organizationalUnitName_default =

0.commonName                    = Common Name (FQDN of your server)

1.commonName                    = Common Name (default)
1.commonName_value              = localhost

[ cert_type ]
nsCertType = server

And :

# cat mkcert.sh 
#!/bin/sh

OPENSSL=openssl
SSLDIR=/usr/local/certs/dovecot
OPENSSLCONFIG=/usr/local/certs/dovecot/dovecot.cnf

CERTDIR=$SSLDIR/certs
KEYDIR=$SSLDIR/private

CERTFILE=$CERTDIR/dovecot.pem
KEYFILE=$KEYDIR/dovecot.pem

if [ ! -d $CERTDIR ]; then
  echo "$SSLDIR/certs directory doesn't exist"
  exit 1
fi

if [ ! -d $KEYDIR ]; then
  echo "$SSLDIR/private directory doesn't exist"
  exit 1
fi

if [ -f $CERTFILE ]; then
  echo "$CERTFILE already exists, won't overwrite"
  exit 1
fi

if [ -f $KEYFILE ]; then
  echo "$KEYFILE already exists, won't overwrite"
  exit 1
fi

$OPENSSL req -new -x509 -nodes -config $OPENSSLCONFIG -out $CERTFILE -keyout $KEYFILE || exit 2
chmod 0600 $KEYFILE
echo 
$OPENSSL x509 -subject -fingerprint -noout -in $CERTFILE || exit 2

Created the 2 files ? ok, create "certs" and "private" folders :

# cd /usr/local/certs/dovecot
# mkdir certs
# mkdir private

Then run the mkcert.sh :

# sh mkcert.sh

Here is what you could answer when running this script :

Country Name (2 letter code) [NO]:FR
State or Province Name (full name) [Some-State]:France
Locality Name (eg, city) []:Paris
Organization Name (eg, company) [FooBar Inc.]:host.com
Organizational Unit Name (eg, section) []:
Common Name (FQDN of your server) []:imap.host.com

it should generate 2 dovecot.pem files :

# ll {certs,private}/*.pem
-rw-r--r--  1 root  wheel  904 Apr  4 17:00 certs/dovecot.pem
-rw-------  1 root  wheel  887 Apr  4 17:00 private/dovecot.pem

And we are happy with that.
Now let's take a look at our pre-configured dovecot.conf. There is only what's needed in there. 

# cat /usr/local/etc/dovecot/dovecot.conf
# Listen on each interface
listen = *

# Use plain and login mechanisms, through ssl it's ok
auth_mechanisms = plain login
auth_username_format = %Lu
disable_plaintext_auth = no
first_valid_gid = 1000
first_valid_uid = 1000
# Maildir mailbox format
mail_location = maildir:~/Maildir
mail_privileged_group = mail
mbox_read_locks = flock
mbox_write_locks = dotlock flock
# We're using pam, combined with passwd (NSS)
passdb {
  args = session=yes dovecot
  driver = pam
}
protocols = imap
service auth {
  unix_listener auth-client {
    mode = 0660
  }
  unix_listener auth-master {
    mode = 0600
  }
  user = root
}
service imap-login {
  inet_listener imap {
    port = 0
  }
}
# We want SSL and we tell where the key and certificate are
ssl = yes
ssl_cert = </usr/local/certs/dovecot/certs/dovecot.pem
ssl_key = </usr/local/certs/dovecot/private/dovecot.pem


# we're using /etc/passwd
userdb {
  args = blocking=no
  driver = passwd
}
verbose_proctitle = yes
protocol imap {
  imap_idle_notify_interval = 600
  imap_client_workarounds = delay-newmail  tb-extra-mailbox-sep
}
protocol pop3 {
  pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
  pop3_uidl_format = %08Xu%08Xv
}
# it will enable sendmail to send mail in the inbox
protocol lda {
  sendmail_path = /usr/sbin/sendmail
  mail_plugins = sieve
}

!include conf.d/*.conf



Here is the only conf.d/ file, 20-managesieve.conf (defaults mostly) :

# cat /usr/local/etc/dovecot/conf.d/20-managesieve.conf

protocols = $protocols sieve


service managesieve-login {
}


service managesieve {
}


protocol sieve {
}


plugin {
  sieve = ~/.dovecot.sieve
  sieve_dir = ~/sieve
}

And the last file not to forget is /usr/local/etc/pam.d/dovecot, which contains :

# cat /usr/local/etc/pam.d/dovecot

auth required pam_unix.so no_warn try_first_pass
account required pam_unix.so

Let's enable dovecot to start in /etc/rc.conf, add this to yours :

dovecot_enable="YES"

I think we're done here with dovecot configuration, so you can try to start it and check your processes for dovecot :

# /usr/local/etc/rc.d/dovecot start

# ps auxwwww | grep dovecot
root     37748   0.0  0.1  19948   2472  ??  Is  10:37AM 0:00.01 /usr/local/sbin/dovecot -c /usr/local/etc/dovecot/dovecot.conf
dovecot  37749   0.0  0.1  19948   2184  ??  I   10:37AM 0:00.00 anvil: [7 connections] (anvil)
root     37750   0.0  0.1  19952   2148  ??  I   10:37AM 0:00.00 dovecot/log
root     37752   0.0  0.1  28160   5088  ??  I   10:37AM 0:00.01 dovecot/config
root     37800   0.0  0.1  26048   3140  ??  I   10:43AM 0:00.00 dovecot/ssl-params
root     37852   0.0  0.0  16424   1496   0  S+  10:46AM 0:00.00 grep dovecot

It's very tempting from there to connect to your mail box with IMAP and SSL, but let's finish our installation with the configuration of Sendmail.


2. Configure Sendmail, to move your mails inside your IMAP Inbox


Here are the line to add to your /etc/mail/mail.host.com.mc (I don't show every lines of the conf) :

# cat /etc/mail/mail.host.com.mc
...
FEATURE(virtusertable, `hash -o /etc/mail/virtusertable')
FEATURE(`local_procmail', `/usr/local/libexec/dovecot/dovecot-lda',`/usr/local/libexec/dovecot/dovecot-lda -d $u')
...
MODIFY_MAILER_FLAGS(`LOCAL', `-f')
MAILER(local)
MAILER(smtp)
MAILER(procmail)

These three lines tell sendmail to use the Dovecot LDA System, so that users mails are move inside the Inbox mailbox instead of just staying in /var/mail/username. (see http://wiki2.dovecot.org/LDA/Sendmail).

Let's restart sendmail to use these changes :

# cd /etc/mail
# make all install restart

If you had already mails in /var/mail, you could migrate them following this Wiki page http://wiki2.dovecot.org/Migration/MailFormat. If you can use the dsync tool, it's nice. If not, then follow steps with the perl script.