Testing IMAP and setting up Roundcube webmail

Testing IMAP access

You have already finished the configuration of Dovecot so fetching emails using the IMAP protocol will already work. Let’s give it a try using a simple but powerful IMAP client: mutt.

mutt -f imaps://john@example.org@webmail.example.org

The connection URL may look a little confusing because of the two “@” characters. Usually mutt expects imaps://user@server. And as we use the email address as the “user” part you get this look. You should get prompted for the password which is “summersun”. If you get any certificate warnings then check if you used the correct server name to connect to and if you finished the certificate/LetsEncrypt part earlier in this guide.

After logging in you will see an empty inbox:

Very good – so IMAP works.

Enabling Roundcube

Not everyone is a hardcore user who uses an application like Thunderbird, Evolution, kmail or A**le Mail to manage their emails. It surprises how many users are happy with a web interface to their emails. Okay, if you like. So let’s provide a webmail interface. A very (if not the most) common software for that purpose is Roundcube.

When you installed the Roundcube package at the very beginning of this guide it created a /etc/apache2/conf-available/roundcube.conf file that was linked to /etc/apache2/conf-enabled/. So the general Apache configuration is already ready. All you have to do is link your virtual host for webmail to the directory that contains the Roundcube installation.

The configuration file suggests this Apache configuration line:

Alias /roundcube /var/lib/roundcube

That would make RoundCube accessible under https://webmail.example.org/roundcube. However I would rather omit the “/roundcube”. That is easily done by changing the DocumentRoot in your /etc/apache2/sites-enabled/webmail.example.org-https.conf file to:

DocumentRoot /var/lib/roundcube

Reload the Apache configuration…

service apache2 reload

…and you can now access the webmail interface at https://webmail.example.org/

You could already log in by entering “localhost” as a server. But let’s improve the configuration a litte. The “Server” is always “localhost”. So edit the /etc/roundcube/config.inc.php file and set:

$config['default_host'] = 'localhost';

Now when you reload the login form the “Server” field should be gone.

Try to login using our example user “john@example.org” with his password “summersun”. That will create an IMAP connection to “localhost” (on the server) and show you John’s emails:

The inbox is still empty but you logged in successfully. Nice.

Set up HTTP to HTTPS redirection

For those users who forget to type “https” instead of “http” let us also set up an automatic redirection so that they will be forwarded to the secure URL. Edit the /etc/apache2/sites-enabled/webmail.example.org-http.conf file and insert this anywhere within the VirtualHost section:

 RewriteEngine On
 RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/.*
 RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=301]

Experienced sysadmins may wonder why I didn’t just use the simpler form of a redirection like…

# Don't use this!
Redirect permanent / https://webmail.example.org/

The reason is that directing all requests from HTTP to HTTPS would break LetsEncrypt’s auto-renewal. If a certificate is due for renewal the “certbot” will put a file into the .well-known/acme-challenge subdirectory of your virtual hosts’s DocumentRoot to verify your server. If you redirected those requests to the HTTPS vhost then LetsEncrypt’s verification would fail. Use the RewriteCond(ition) we can exclude that path from the redirection.

Also make sure that the redirection module is enabled in Apache:

a2enmod rewrite

To make your change work:

service apache2 reload

Now when you open http://webmail.example.org/ in your browser you should get redirected to the HTTPS URL automatically.

HTTP? HTTPS? Redirections? Confused?

Let’s reiterate how the two virtual hosts are supposed to work:

  • HTTP (/etc/apache2/sites-enabled/webmail.example.org-http.conf)
    /.well-known/acme-challenge/ -> serve from /var/www/webmail.example.org for verification of Let’s Encrypt challenges
    anything else -> redirect to HTTPS so that users always use Roundcube in a safe manner
  • HTTPS (/etc/apache2/sites-enabled/webmail.example.org-https.conf)
    / -> serve Roundcube from /var/lib/roundcube

I hope that makes things a bit clearer. Pay attention to the names of the two different configuration files.


Further down in /etc/roundcube/config.inc.php there is a list of plugins that Roundcube loads. Add at least the “managesieve” and “password” plugins so that the setting looks like this:

$config['plugins'] = array(	 	 

There are for more plugins available. Take a look at the /var/lib/roundcube/plugins/ directory. You can add any of them. Custom configuration of the plugins goes into the /etc/roundcube/plugins/* directories.

Next an optional setting. The default session lifetime in Roundcube is 10 minutes. That means if a user is not using the webmail interface for more than 10 minutes they will be logged out. I found that annoying and increased that timeout to one hour. To do that at the end of the config file add:

$config['session_lifetime'] = 60;

And if you would like to change the default logo of Roundcube that can be done by setting:

$config['skin_logo'] = './ispmail-logo.png';
ISPmail logo for Roundcube

You just need to copy that image file by that name to /var/lib/roundcube/ispmail-logo.png. The logo should be 177×49 pixels large. Feel free to take this nifty ISPmail logo I crafted. 🙂
If the logo appears to be broken then make sure that the permissions are correct:

chmod a+r /var/lib/roundcube/ispmail-logo.png

When you reload the login form in the browser it will then look like this instead:

Configuring the managesieve plugin

The “managesieve” plugin will allow your users to manage automatic rules to manage their email. These rules are stored on the server and will be run automatically. You need to configure this plugin though. A default configuration can be found at /usr/share/roundcube/plugins/managesieve/config.inc.php.dist on your system. Copy it to the location where Roundcube will look for it:

cp /usr/share/roundcube/plugins/managesieve/config.inc.php.dist \

No further changes are required.

Configuring the password plugin

If you want to allow your users to change their passwords then use the password plugin. Copy the default configuration file /usr/share/roundcube/plugins/password/config.inc.php to the right place:

cp /usr/share/roundcube/plugins/password/config.inc.php.dist \

The configuration file at /etc/roundcube/plugins/password/config.inc.php requires a couple of changes though. We need to tell it how our database works and what to do when a user wants to change their password. The first setting deals with the minimal length of the password. I recommend to enforce at least 10 characters. In fact the complexity of the password is not that important. Consider XKCD as food for thought on password security. So set:

$config['password_minimum_length'] = 10;

We should allow the user to use the old password as the new password. It may sound stupid but as we are upgrading the password scheme from the weak unsalted MD5 to the better SHA2 algorithm we should allow that:

$config['password_force_save'] = true;

Next the password plugin needs to know how to access your database:

$config['password_db_dsn'] = 'mysql://mailadmin:ChangeMe@localhost/mailserver';

Replace “ChangeMe” by the randomly generated password you created earlier for the “mailadmin” database user.
Now tell the plugin how to actually write the new password hash into the database:

$config['password_query'] = "UPDATE virtual_users SET password=CONCAT('{SHA256-CRYPT}', ENCRYPT (%p, CONCAT('$5$', SUBSTRING(SHA(RAND()), -16)))) WHERE email=%u;";

Whoa, that looks weird, doesn’t it? That SQL query generates a password hash from these parts:

  • The string “{SHA256-CRYPT}”. It tells Dovecot explicitly that this password is a salted SHA256 hash. You may have different kinds of encrypted passwords in your database so this makes it clear.
  • The actual encrypted password that is generated using your operating system’s crypt() function (MariaDB calls it when you use the ENCRYPT SQL function) using…
    • The new plaintext password (Roundcube replaces “%p” by it).
    • “$5$” – that stands for using the SHA-256 algorithm. Check “man crypt” to see which algorithms are supported by crypt().
    • And SUBSTRING(SHA(RAND()), -16) is used as a salt. A salt is just some additional randomness that makes it much much harder to reverse-engineer the actual password from the encrypted string.
  • And of course we just want to change the password of the current email user. So “WHERE email=%u” makes sure we choose the right row in the database. Roundcube replaces “%u” with the user name – which is the same as the email address in our case.

(I used to recommend just using “dovecot pw -s SHA256-CRYPT” to generate passwords. You can do that, too. But in fact MySQL is capable of generating salted SHA256 hashes without calling any shell command. Thanks for the hint, Martin.)

19 thoughts on “Testing IMAP and setting up Roundcube webmail

  • 2018-01-21 at 22:42

    Changing the DocumentRoot to /var/lib/roundcube results in 403 – forbidden
    /etc/apache2/sites-enabled/webmail.workaround.org-https.conf should have been probably example.org

    • 2018-01-22 at 22:50

      the 403 forbidden was caused by the apache being installed later than roundcube so some hooks weren’t activated during the installation dpkg-reconfigure fixed it but some of the configurations were re-written so the /etc/roundcube/config.inc.php needs to be revisited

  • 2018-01-22 at 17:29

    Module RewriteEngine was not available by default.

    Rewrite module can be enabled by entering command “a2enmod rewrite” followed by “systemctl restart apache2” to reload apache2.

    • 2018-01-22 at 22:51

      also in my case there was a mod enabled by default that was conflicting with rewrite so it had to be disabled with a2dismod

      • 2018-01-23 at 08:07

        Thanks for the hint. I have added “a2enmod rewrite” to the documentation.

        What was the other mod that caused a conflict?

        • 2018-01-25 at 14:41

          Thx. I’m not seeing any conflicting mods, so I think all is fine. Install on fresh system works flawlessly.

    • 2018-01-23 at 21:30

      It’s a bit hidden in the details. There are two virtual hosts. One for HTTP and one for HTTPS. Basically they work like this:

      / -> redirect to HTTPS
      /.well-known/acme-challenge/ -> serve from /var/www/webmail.example.org

      / -> serve Roundcube from /var/lib/roundcube

      Let me know if that doesn’t work for you. I admit that you have to follow the article very closely because sometimes I refer to /etc/apache2/sites-enabled/foo-http.conf and at other times to …/foo-https.conf

      • 2018-01-23 at 22:54

        Ah, clever! I was wondering why the DocumentRoot was only changed in the https file. Thanks for clarifying.

  • 2018-01-23 at 21:01

    The “managesieve” plugin doesn’t work out of the box in roundcube (Error log says: PHP Fatal error: Uncaught Error: Class ‘Net_Sieve’ not found in /usr/share/roundcube/plugins/managesieve/lib/Roundcube/rcube_sieve.php:65).

    It looks like there is an missing dependency as you can read here: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=798307
    So you have to install the package “php-net-sieve” manual: “apt-get install php-net-sieve”

    After that it worked for me. Perhaps you could add this somewhere in the tutorial.

    • 2018-01-23 at 21:19

      Thanks for the hint. I’m surprised that the bug was closed in 2015 but still existed at the point of release in 2017. But I have verified it and you are right. It’s added to the “apt install roundcube…” statement on the page about installing packages.

  • 2018-01-28 at 09:40

    Apparently now you could simplify the password update task, by modifying:
    $config[‘password_algorithm’] = ‘sha256-crypt’;
    $config[‘password_algorithm_prefix’] = ‘{SHA256-CRYPT}’;
    $config[‘password_dovecotpw’] = ‘/usr/local/sbin/doveadm pw’; // for dovecot-2.x – i don’t know if really needed
    $config[‘password_query’] = ‘UPDATE virtual_users SET password = %P WHERE email = %u;’;

    As you can see, it simplifies a lot the query needed to update the password. As a matter of fact, in my case, your example did not work at all, it just gave an error in log:
    PHP Parse error: syntax error, unexpected ”, ENCRYPT (%p, CONCAT(” (T_CONSTANT_ENCAPSED_STRING)

    • 2018-02-22 at 20:02

      I ended up back here while googling the solution to that same error. I did manage to finally get it done your way, but I had to use back ticks for all the quotes; for reasons I don’t understand.

  • 2018-02-04 at 16:12

    The “managesieve” password will allow your users to manage automatic rules to manage their email.

    I suppose you wanted to say “The “managesieve” plugin…” ?

    • 2018-02-04 at 16:16

      I knew it was something with “p”. 🙂 Thanks for the hint.

  • 2018-02-06 at 17:40

    Hi Christoph. Can you also include the rspamd webinterface in sites available? I think it is very usefull to fight spam.

  • 2018-02-20 at 11:23

    Since /usr/share/roundcube/plugins/password/config.inc.php contains the password for mailadmin but everyone can read it, shouldn’t it be readable by root and postfix, too, like mysql-*.cf flies?

  • 2018-04-17 at 15:39

    Should the $config[‘des_key’] be changed? The comments in /etc/roundcube/config.inc.php suggest so…

  • 2018-06-09 at 01:13

    If it helps anyone, I had trouble with performing the test in Mutt, it would never get to the password prompt, it would just fail to connect spit out “GPGME: CMS protocol not available”.
    Installing the gpgsm package resolved that.
    Also I found that Cloudflare caused major headaches with SSL certificates, it tripped me up as I could access https traffic within the network, but when accessing https://webmail.example.org it just forwarded me to http://webmail.example.org and gave me a file listing of test.txt.
    Pausing the website on Cloudflare ‘resolved’ that – for the time being at least.


Leave a Reply

Your email address will not be published. Required fields are marked *