Courier-IMAP

For a general introduction and configuration settings for some popular IMAP clients, go and read imap/README(.html).

In this document:

INSTALLATION

To compile and install the Courier-IMAP server:

 
$ ./configure [ options, see below ]
$ make
$ make check       # Note - this creates /tmp/courier-imap-check
                   # Note - the --enable-workarounds-for-imap-client-bugs
                   # option to configure will result in make check FAILING.
$ make install     # Or, make install-strip, to strip the executables

NOTE: The configure script can take 5-10 minutes to finish, on slow machines. It may appear that the configure script is constantly looping, but that's an illusion. Courier-IMAP is built from highly recyclable code modules, each with its own configuration script. There will be about a dozen separate configuration scripts that will be recursively invoked.

You should try make install-strip first. Use make install if make install-strip fails due to a buggy install program.

The configure script accepts certain options, but the defaults should be fine in most cases. make install puts everything into /usr/lib/courier-imap. If the directory /etc/pam.d exists, make install will create /etc/pam.d/imap, obliterating any existing file of that name. If you have some other IMAP server installed, this means that you will want to save your existing PAM imap configuration first.

"make check" performs some internal sanity checks. NOTE: this creates a temporary directory /tmp/courier-imap-check. If it already exists due to a previous Courier-IMAP install, you should remove it in advance. If make check fails, something is wrong, and Courier-IMAP will probably not work for you.

After installation, you will want to review /usr/lib/courier-imap/lib/imapd.config and make any changes you deem necessary, including:

./configure should automatically detect if you use vchkpw, and compile and install the authvchkpw authentication module.

After running make install or make install-strip you will then have to modify your system's startup scripts to run Courier-IMAP when your system boots.

Use the following command to start the Courier-IMAP server:

 
$ /usr/lib/courier-imap/libexec/imapd.rc start

This assumes that Courier-IMAP is installed in /usr/lib/courier-imap. Use the following command to stop Courier-IMAP:

 
$ /usr/lib/courier-imap/libexec/imapd.rc stop

You will have to add these commands to your system startup/shutdown scripts.

IMAP over SSL

Courier-IMAP supports IMAP over SSL. To add SSL support you have to install OpenSSL and stunnel separately, before installing Courier-IMAP. Download stunnel from http://mike.daewoo.com.pl/computer/stunnel/. Download OpenSSL from http://www.openssl.org/. Follow the instruction in each package to install it and configure it. SSL support in Courier-IMAP has been tested with stunnel 3.8 and OpenSSL 0.9.5.

The /usr/lib/courier-imap/lib/imapd-ssl.config configuration file sets some additional options for SSL and stunnel, which you may need to adjust. Consult that configuration file for additional information. Then, you also have to run the /usr/lib/courier-imap/libexec/imapd-ssl.rc script from your system startup and shutdown scripts, just like the /usr/lib/courier-imap/libexec/imapd.rc script. You may accept both SSL and non-SSL connections by running both scripts.

Note that SSL requires a valid, signed, X.509 certificate to be installed where stunnel expects to find it. You can generate your own self-signed certificate with OpenSSL, but IMAP clients will display a warning message the first time they connect to the server. To prevent the warning message, you will need to pay big buck$ to have your certificate signed by a certificate authority. The gory details of setting up SSL is beyond the scope of this document, and you should consult both then OpenSSL and stunnel documentation for more information.

System-V style startup

If your system uses System-V style startup scripts, here's a sample script you can install in /etc/rc.d/init.d:

 
#!/bin/sh
#
# courier-IMAP - IMAP server
#
#

case "$1" in
start)
        cd /
        . /usr/lib/courier-imap/etc/imapd.config
        case x$IMAPDSTART in
        x[yY]*)
                echo -n "Starting Courier-IMAP server:"
                /usr/lib/courier-imap/libexec/imapd.rc start
                ;;
        esac

        . /usr/lib/courier-imap/etc/imapd-ssl.config
        case x$IMAPDSSLSTART in
        x[yY]*)
                test -x $STUNNEL && \
                        /usr/lib/courier-imap/imapd-ssl.rc start
                ;;
        esac

        echo " imaplogin"
        ;;
stop)
        echo -n "Stopping Courier-IMAP server:"
        /usr/lib/courier-imap/libexec/imapd.rc stop
        /usr/lib/courier-imap/libexec/imapd-ssl.rc stop
        echo " imaplogin"
        ;;
restart)
        $0 stop
        $0 start
        ;;
esac
exit 0

Then, create a soft link to /etc/rc.d/init.d from the run-level subdirectories underneath /etc/rc.d.

Options to configure:

Installation directories

Unless the options --prefix, --bindir, or --mandir are specified, everything will be installed in the directory /usr/lib/courier-imap.

Use the --prefix option to specify a different directory. This directory will contain the following subdirectories:

Having everything installed underneath one directory allows its contents to be easily backed up, before a newer version of courier-imap is installed. Reverting to a previous version is as simple as restoring from backup.

Because some binaries in bin and sbin may be executed from the command line, it will be necessary to change your systemwide global startup script to add this directory to the default PATH. Additionally, it will also be necessary to modify the configuration of the man(1) command so that it can find Courier-IMAP's manual pages in this directory:

        PATH="/usr/lib/courier-imap/bin:$PATH"
        if test -w /etc
        then
                PATH="/usr/lib/courier-imap/sbin:$PATH"
        fi
        export PATH
        MANPATH="/usr/lib/courier-imap/man:$MANPATH"
        export MANPATH

As an alternative, you may use the --bindir and --mandir options in order to install binaries to /usr/local/bin and the manual pages to /usr/local/man, which should already be searched by default:

        ./configure --bindir=/usr/local/bin --mandir=/usr/local/man

USING USERDB

userdb is a way to implement many virtual mailboxes - many mailboxes that do not have to have a separate system userid allocated for each one, and there is no system login associated with each mailbox. userdb uses a database for mapping virtual addresses to physical maildirs. It should be scalable to thousands of mailboxes. It can also be used to replace linear searches of /etc/passwd with a database lookup, see pw2userdb(8).

This is a rough overview of using userdb. For additional information, read makeuserdb(8), and userdb(8). All the scripts will be installed in /usr/lib/courier-imap, so look for them there.

Courier-IMAP can use the userdb database simply by the virtue of installing the authuserdb authentication module, which happens by default. The tricky part is creating the database. Hopefully, it's only tricky once, and the second time it won't be so tricky any more. The userdb configuration is extremely flexible, and there are many ways of actually setting up the database.

The best way to describe how userdb works is to try to create one virtual mail account, let's call it vmail.

Simple userdb setup.

This approach should be used if you do not have many virtual mailboxes. It's very simple, but quickly becomes cumbersome if you administer many virtual mailboxes.

Create an empty /etc/userdb.

 
# cp /dev/null /etc/userdb
# chmod 700 /etc/userdb

/etc/userdb must have 700 permissions.

Now, run the script pw2userdb. This script converts the contents of your /etc/passwd to the /etc/userdb format (including the contents of /etc/shadow, this is why permissions on /etc/userdb must be 700). This script is usually used where you want to convert a very large /etc/passwd to /etc/userdb. userdb applications can now use a fast userdb database instead of a linear scan of /etc/passwd in order to look up system accounts. However, you probably don't want to do use this feature right now, so what you simply want to do is take the output of pw2userdb, and find the entry for the vmail account that you created earlier. Look for a line that starts with 'vmail' followed by tab, followed by familiar fields from /etc/passwd. Save the output of pw2userdb in a temporary file, edit it, and remove everything except the line containing vmail, and the very next line, which is a special entry that maps vmail's userid back to the vmail record.

Here's what you might find in the output of pw2userdb:

 
vmail   uid=1012|gid=1012|home=/home/vmail|systempw=*
1012=   vmail

The actual numerical values and the home directory location may vary. Save these two lines as /etc/userdb, and set the permissions on /etc/userdb to 700:

 
$ chmod 700 /etc/userdb

This is a one time step only, and Courier-IMAP does not really need it. However, there are other applications that use /etc/userdb which may require it.

Now, with that out of the way, let's really create a virtual account. In this example we'll create a virtual mailbox for 'john@example.com'.

 
# su vmail
$ cd $HOME
$ maildirmake Maildir-john-example
$ exit
#

You may need to specify a full path to your maildirmake program. The end result is that you created $HOME/Maildir-john-example in vmail's account.

The next step is to configure your mail server to deliver mail for john@example.com directly into the maildir ~vmail/Maildir-john-example. How that's done depends on the mail server that you use.

Now, let's connect the dots here, and create an entry in /etc/userdb for john@example.com:

 
# userdb "john@example.com" set home=/home/vmail \
                                mail=/home/vmail/Maildir-john-example \
                                uid=UUU gid=GGG

This command runs a Perl script named userdb , which is installed, by default in /usr/lib/courier-imap/sbin. Replace UUU and GGG with the userid and groupid of the vmail account. If you now look in /etc/userdb, you will see that a new record for john@example.com has been appended to the end of the file.

We're not finished yet. We need to set the IMAP password for this mailbox:

 
# userdbpw | userdb "john@example.com" set imappw

If you are running Red Hat Linux 6.0, or higher, you can specify the -md5 option to userdbpw, in order to use an MD5 password hash, instead of crypt. Specify "systempw" instead of "imappw" if you would like to use the same password with any other application that uses . The imappw field is only checked by Courier-IMAP. If not defined, systempw is used instead.

Finally, compile the database:

 
# makeuserdb

This command creates the actual database, /etc/userdb.dat and /etc/userdbshadow.dat from the plain text file /etc/userdb. Courier-IMAP will now start accepting logins to this mailbox. Adding and removing mailboxes can be done while Courier-IMAP is running.

Courier-IMAP reads /etc/userdb.dat and /etc/userdbshadow.dat only. The plain text source, /etc/userdb is not read by Courier-IMAP itself. Changes take effect only when makeuserdb runs.

Large virtual domain farm.

The previous approach uses a single flat file, /etc/userdb. This might be a bit cumbersome if you have thousands of virtual mailboxes in many domains. Here's an alternative approach that can scale to thousands of domains and mailboxes.

Instead of creating /etc/userdb file, make it a subdirectory:

 
# mkdir /etc/userdb
# chmod 700 /etc/userdb

Now, create /etc/userdb/default, containing pw2userdb's output for the vmail account, as previously described.

This time, you probably want to create all mailboxes for the same domain in a separate subdirectory:

 
# su vmail
$ cd $HOME
$ mkdir -p domains/example-com
$ maildirmake domains/example-com/john
$ exit

The idea is that all the maildirs for @example.com will be stored in ~vmail/domains/example-com. All maildirs for domain.org will be stored in ~vmail/domains/domain.org. The actual layout and naming conventions are entirely up to you to define.

Now, configure your mail server to deliver mail for john@example.com into this maildir.

Here's how configure /etc/userdb.

 
$ userdb "example-com/john@example.com" set home=/home/vmail \
                                mail=/home/vmail/domains/example-com/john \
                                uid=UUU gid=GGG

This creates the file /etc/userdb/example-com (the first parameter to the userdb command), and appends a record named "john@example.com". You will store all userdb entries for @example.com in the file /etc/userdb/example-com. All entries for @domain.org will be maintained in /etc/userdb/domain-org, and so on.

 
$ userdbpw | userdb "example-com/john@example.com" set imappw

This sets the IMAP access password for this account. Finally:

 
$ makeuserdb

USING VCHKPW/VPOPMAIL

It is possible to convert vpopmail/vchkpw single userid authentication passwd files to /etc/userdb using the vchkpw2userdb script. See vchkpw2userdb(8) for more information.

USING SHARED FOLDERS

Courier-IMAP supports shared folders. See the file README.sharedfolders.html for information on how to set up shared folders.

CRAM-MD5 AUTHENTICATION

CRAM-MD5 authentication allows IMAP clients to authenticate themselves without sending the password in clear-text over the network. Courier-IMAP now supports CRAM-MD5 by default, but is not enabled for reasons explained below. CRAM-MD5 support is implemented by the authcram module, with one exception - authldap should be able to support CRAM-MD5 authentication if the LDAP server is used to store clear-text passwords.

To use CRAM-MD5 it is necessary to use an IMAP client that support CRAM-MD5 authentication, of course. That's the easy part.

The problem is that it is not possible to use the system password when logging in using CRAM-MD5. That's because CRAM-MD5 requires the knowledge of the actual password, in the clear, in order to calculate authentication tokens (even though that the password itself is not sent in the clear over the network).

So, implementation of CRAM-MD5 should be attempted once you are comfortable and understand how Courier-IMAP works in general. Here's an overview of this procedure:

Enabling CRAM-MD5 authentication

Because of these unfortunate complexities, CRAM-MD5 authentication is disabled after installation. CRAM-MD5 authentication is implemented by the authcram authentication module, which will be compiled and installed, however, Courier-IMAP will not advertise the fact that it supports CRAM-MD5. CRAM-MD5 authentication is also supported directly by the authldap module if it is configured to validate clear-text passwords in the LDAP database, however this feature has not been thoroughly tested. You do not need authcram if all you install is authldap (but you do need authcram if you install any other authentication module besides authldap, and you intend to use CRAM-MD5 authentication).

When you're ready to use CRAM-MD5, edit imapd.config and add the "AUTH=CRAM-MD5" keyword to the IMAP_CAPABILITY environment variable, then restart Courier-IMAP. There are instructions in imapd.config to that effect.

If you do not intend to ever use CRAM-MD5 authentication, you can either specify --without-authcram option to the configure script, or simply edit imapd.config and remove authcram from the AUTHMODULES setting.

AUTHENTICATION MODULES - GENERAL NOTES

Authentication modules are responsible for taking the entered userid and password, validating them, then locating the corresponding Maildir for the userid.

There are several authentication modules available. Each authentication module implements a separate way of authenticating logins, and not all authentication modules can be used by everyone. Some authentication modules can be used only on systems that have certain libraries or software installed separately.

The configure script will attempt to pick a default set of authentication modules to install, but the --with-module and --without-module options to the configure can always specify whether a given authentication "module" should be explicitly included or excluded. Multiple --with and --without options are, of course, allowed (each one specifying a different authentication module). As explained later, it will not be necessary, in most cases, to explicitly specify the disposition of each one of the following authentication modules, and most people will find it sufficient to let the configure script decide which one of the following authentication modules are required:

It is possible to include more than one authentication module. For example, if you select both authuserdb and authpam, each login will first be authenticated against /etc/userdb. If Courier-IMAP cannot find the account in /etc/userdb, it will then attempt to authenticate using the PAM library.

If neither --with nor --without is specified for any one of these modules, the configure script will try to figure out whether or not to the given authentication module should be used. Therefore, in most situations, it will not be necessary for you to explicitly specify what to do with each authentication module. For most people, letting configure figure it out will be sufficient.

configure will use the following logic to determine which authentication modules need to be included by default:

Confirming selected authentication options

You can find out what authentication modules were actually used, but you must first run make successfully. Running make compiles the authinfo program in the authlib subdirectory. This program tells you what authentication modules were compiled.

LDAP AUTHENTICATION MODULE

This module attempts to authenticate against an LDAP server. This option installs a sample configuration file, which is /usr/lib/courier-imap/etc/authldaprc by default. You will need to edit this file in order to configure LDAP authentication. This configuration file defines the location of your LDAP server, as well as the names of attributes used to perform LDAP authentication. See the comments in the sample configuration file, and the authldap(8) manual page, for more information.

AUTHENTICATION INTERNALS

Feel free to stop reading now, if all you want to do is install Courier-IMAP, without hacking it even further.

It is possible to use other forms of authentication with Courier-IMAP. To do that, you have to write your own authentication modules.

The easiest way to do that would probably be to take an existing authentication module, and clone it. Some documentation is available in the authlib subdirectory.

For example, take a look at authpwd.c, which implements the /etc/passwd authentication. You will have to write a function that works something like that. The authentication function validates the userid/password, and sets the current userid, groupid, and current directory to the ones specified by the account, and calls some authentication library functions that do the rest of the work. Additionally, you will need to write a "pre-authentication" function, that does the same thing, but it receives only the userid, and assumes that the password is valid. This functionality is not actually used by Courier-IMAP, but it is required to be implemented within the authlib library framework, because authlib is used by other applications where this functionality is required. For authpwd.c, the corresponding function is implemented in preauthpwd.c.

Start by cloning and re-implementing these two functions. Then, you need to create a two-line stub function that inserts the call to your function into a template for a stand-alone authentication module. Take a look at modauthpwd.c for an example.

You will note that all authentication modules in authlib follow this template, which consists of three files: authfunc.c, preauthfunc.c, and modauthfunc.c

After writing these functions, you need to add some code to configure.in in order to enable or disable your authentication module at compile time. The easiest way to do that is to simply copy the code that does that for one of the existing functions, and simply substitute the name of your own authentication function and source files (don't forget to append to the STATIC_LIST variable). Then, finally, add your code to Makefile.am. If you study Makefile.am, you will observe that all authentication modules follow the same pattern:

The reason that the dependency file is required is that some application link directly with libauth.a, instead of running a stand-alone authentication module -- like Courier-IMAP does -- and those applications need to know what external libraries they must to link with.

A successful authentication involves initialization of a couple of environment variables: AUTHADDR - this environment variable should be set to the E-mail address that the mailbox actually represents (if it's a local physical address, you can leave out the domain, but otherwise it must be a real E-mail address); AUTHFULLNAME - the name of the breathing organism that reads this mailbox. That's taken care of automatically, if you reuse some of my code. There's no room in this brief README for the gory details, read the code and figure it out.

Also note how dynamic memory allocation is handled. Also, you must avoid using stdio calls. Some authlib applications use the Fast-CGI library, which implements an incompatible set of stdio function calls.