Raspberry Pi Email Server Part 2: Dovecot

Dovecot Logo

This is the second part of a five part tutorial that will show you how to install a full featured email server on your Raspberry Pi. This tutorial covers Dovecot, which provides SASL authentication and IMAP capabilities. The parts are:

The Introduction & Contents Page (read first)
Raspberry Pi Email Server Part 1: Postfix
Raspberry Pi Email Server Part 2: Dovecot
Raspberry Pi Email Server Part 3: Squirrelmail
Raspberry Pi Email Server Part 4: Spam Detection with Spamassassin
Raspberry Pi Email Server Part 5: Spam Sorting with LMTP & Sieve

Fixing the errors that appeared during dovecot installation

In part 1, when you installed Dovecot I mentioned that you might see some errors like this:

Creating config file /etc/dovecot/conf.d/20-imap.conf with new version
[....] Restarting IMAP/POP3 mail server: dovecotError: socket() failed: Address family not supported by protocol
Error: service(imap-login): listen(::, 143) failed: Address family not supported by protocol
Error: socket() failed: Address family not supported by protocol
Error: service(imap-login): listen(::, 993) failed: Address family not supported by protocol
Fatal: Failed to start listeners
 failed!
invoke-rc.d: initscript dovecot, action "restart" failed.
dpkg: error processing dovecot-imapd (--configure):
 subprocess installed post-installation script returned error exit status 1
Setting up dovecot-ldap (1:2.1.7-7) ...

These errors are caused by the lack of IPv6 support, which I mentioned in the previous tutorial. To remove the errors, open the main dovecot configuration file (/etc/dovecot/dovecot.conf) and find this line:

listen = *, ::

And change it to:

listen = *

The * means “all IPv4 addresses”, the :: means “all IPv6 addresses”. Now restart Dovecot, and you shouldn’t get any errors:

sudo service dovecot restart

Note: since I wrote this tutorial, there have been a few small changes to the default configuration file - you may find that the line is commented (with a # at the start of the line). If so, remember to uncomment it when you make your changes!

Tell Dovecot where your Mailbox is

Open /etc/dovecot/conf.d/10-mail.conf and find this line:

mail_location = mbox:~/mail:INBOX=/var/mail/%u

Change it to this:

mail_location = maildir:~/Maildir

Instruct Postfix to use Dovecot SASL

Now we need to tell Postfix that we would like to use Dovecot for SASL authentication. Open /etc/postfix/main.cf and add these lines:

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

Now tell Dovecot to listen for SASL authentication requests from Postfix. Open /etc/dovecot/conf.d/10-master.conf and comment out the current block that begins with service auth (place a # at the start of each line). Replace it with this:

service auth {
        unix_listener /var/spool/postfix/private/auth {
                mode = 0660
                user = postfix
                group = postfix
        }
}

Now you want to enable plain text logins. Do it by adding these two lines to /etc/dovecot/conf.d/10-auth.conf. Make sure they are not already present in the file, or your settings may be overwritten with the default ones if the default is declared later in the file than the lines you add. If the parameters are already present, you can either modify the existing lines or comment them out and add these new ones:

disable_plaintext_auth = no
auth_mechanisms = plain login

Note that although the logins are in plain text, we will be setting Postfix up later so that it only allows you to use plaintext logins from within SSL/TLS. This means that your login and password will sent in an encrypted session - you wouldn't see them in plain text if you used a packet sniffer, for example. For now, we’re allowing unencrypted plain text logins so that we can test logging in with Telnet. Since the connection is local (from the Pi to the Pi), your password isn’t being sent over any insecure networks so this is fine.

Testing SASL

Creating a new user for testing purposes is a good idea. Let’s call this temporary user testmail and give it the password test1234 Use this command to add the user, and follow the prompts including setting a password.

sudo adduser testmail

Now restart Postfix and Dovecot:

sudo service postfix restart
sudo service dovecot restart

We’re now going to try and send an email after authenticating with SASL. The server is expecting to see a base64 encoded version of your username and password, so we have to convert it first. There are three ways of doing this, so I've given examples below using the testmail username and test1234 password:

#Method No.1
echo -ne '\000testmail\000test1234' | openssl base64

#Method No.2
perl -MMIME::Base64 -e 'print encode_base64("\0testmail\0test1234");'

#Method No.3
printf '\0%s\0%s' 'testmail' 'test1234' | openssl base64

I have discovered that if your password starts with a number, methods 1 and 2 don’t work. Assuming the username and password are testmail and test1234, the commands produce this:

AHRlc3RtYWlsAHRlc3QxMjM0

WARNING: If you’re having problems with authentication and you paste examples to forums or mailing lists, be aware that it is really easy to convert this back into your username and password (hence the creation of a test user). If you're using your real username and password to test, redact it before posting!

Now, still logged into the Pi via SSH, you can telnet port 25 to test whether or not SASL is working. There’s only one extra step, which is the AUTH PLAIN command that comes after ehlo but before mail from. For testing, the permit_mynetworks parameter should be commented out under your postfix smtpd_recipient_restrictions block in /etc/postfix/main.cf. If you’re following on from Raspberry Pi Email Server Part 1: Postfix then this should already be the case. If you have to change it, remember to reload postfix (sudo service postfix reload) after you change the value. Here’s an example:

telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 samhobbs ESMTP Postfix (Debian/GNU)
ehlo facebook.com
250-samhobbs
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH PLAIN AHRlc3RtYWlsAHRlc3QxMjM0
235 2.7.0 Authentication successful
mail from:testmail
250 2.1.0 Ok
rcpt to:me@externalemail.com
250 2.1.5 Ok
data
354 End data with .
Subject: This is my first email that has been authenticated with Dovecot SASL
Woop woop
.
250 2.0.0 Ok: queued as B87133F768
quit
221 2.0.0 Bye
Connection closed by foreign host.

Now try again but enter the username/password incorrectly (base64 encode something random) – you should get an error message and the email won’t send. If everything went to plan, then SASL is working properly!

You can now uncomment permit_mynetworks again.

Separating Incoming email (unauthenticated) from Outgoing Email (SASL authenticated)

It’s probably a good idea to have a dedicated port for sending outgoing email…here’s why: Port 25 doesn’t require (but does offer) SSL/TLS encryption. If you mess up configuring your mail client you could end up letting it authenticate with SASL over insecure connections. Using a different port that only accepts SSL/TLS connections removes the risk that a poorly configured email client could be sending your password unencrypted over dodgy networks. There are two ports you can use for this:

  1. 465: SMTP over SSL
  2. 587: Email submission

587 is the “official” port for email clients (like K9 mail, Thunderbird and Outlook) to use when submitting messages to the Mail Submission Agent (your email server) – the submission may be encrypted or unencrypted depending on the server configuration. 465 was a port that was assigned for SMTP with SSL/TLS before the STARTTLS protocol was introduced, back in the days when you chose your port and that decided on the type of connection you were going to get (encrypted or unencrypted).

STARTTLS changed things because it allows you to connect with an unencrypted connection (like the one you get with Telnet), and then upgrade to an encrypted connection without changing port… so when STARTTLS was introduced, SMTPS on port 465 was removed from the standard because you could do the same thing with a single port (25).

However, I think there is some value in specifying a port for submission that only accepts SSL/TLS encrypted connections, and won’t work if the connection isn’t encrypted. This means that if you misconfigure your email client it just won’t work, instead of working and sending your password in an unencrypted format. So, anyway… Here’s how to set up Postfix to listen on port 465 for encrypted connections. The first step is telling Postfix to listen on port 465, so open /etc/postfix/master.cf and uncomment the line:

smtps     inet  n       -       -       -       -       smtpd

Now restart Postfix:

sudo service postfix restart

Test whether Postfix is listening on port 465:

telnet localhost 465
Trying 127.0.0.1...                                                                           
Connected to localhost.                                                                       
Escape character is '^]'.
220 samhobbs.co.uk ESMTP Postfix (Debian/GNU)
ehlo samhobbs.co.uk
250-samhobbs
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
quit
221 2.0.0 Bye
Connection closed by foreign host.

OK, so now it’s listening on the right port, but it’s allowing unencrypted connections. Here’s how you force TLS on port 465: open /etc/postfix/master.cf and find the line you uncommented earlier. Below it are some options, you want to edit them so that they look like this (i.e. uncomment lines 2 and 3):

smtps     inet  n       -       -       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes

Line 3 is forcing TLS on port 465, and line 2 means that connections to port 465 have a different label in the logs, which can be useful for debugging.

sudo service postfix restart

Now try connecting with Telnet again… you should be able to establish a connection, but not receive any prompts from the server:

telnet localhost 465                                            
Trying 127.0.0.1...                                                                           
Connected to localhost.
Escape character is '^]'.
exit
exit
Connection closed by foreign host.

Now try openssl:

openssl s_client -connect localhost:465 -quiet
depth=0 CN = samhobbs
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = samhobbs
verify return:1
220 samhobbs.co.uk ESMTP Postfix (Debian/GNU)
quit
221 2.0.0 Bye

Good: we are able to start a TLS encrypted connection. We got some errors because the certificate is self-signed (it's not signed by a certificate that is in the trusted root store on the server) but this is OK because we're just using the certificate for testing for now. When you come back later to set up a proper certificate, you can use this command to verify it. The -CApath option tells openssl where the trusted certificates are stored on your system:

openssl s_client -connect localhost:465 -quiet -CApath /etc/ssl/certs

Successful validation looks something like this:

sam@samhobbs:~$ openssl s_client -connect localhost:465 -quiet -CApath /etc/ssl/certs
depth=3 C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root
verify return:1                                                                              
depth=2 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority
verify return:1                                                                              
depth=1 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Domain Validation Secure Server CA
verify return:1                                                                              
depth=0 OU = Domain Control Validated, OU = PositiveSSL, CN = samhobbs.co.uk                 
verify return:1                                                                              
220 samhobbs.co.uk ESMTP Postfix (Ubuntu)                                                    
quit                                                                                         
221 2.0.0 Bye

There are a couple more changes we want to make here: first, tell Postfix to only advertise SASL authentication over encrypted connections (so that you don’t accidentally send your password in the clear). Open /etc/postfix/main.cf and add this line:

smtpd_tls_auth_only = yes
sudo service postfix reload

Now connect to port 25 and you shouldn’t see AUTH advertised:

telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 samhobbs.co.uk ESMTP Postfix (Debian/GNU)
ehlo samhobbs.co.uk
250-samhobbs.co.uk
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN

Lastly, we want to override the smtp_recipient_restrictions for port 465 so that it doesn't accept incoming messages from unauthenticated users.

At first, I didn't make this change and I noticed that some spam emails were coming in on port 465 and bypassing my spam filter, which I configured to scan all incoming email on port 25, but not 465 because I only expected it to be used for outgoing email. We can do this by overriding the smtp_recipient_restrictions list for port 465 in /etc/postfix/master.cf. Open master.cf and find the smtps line. Add a new recipient restrictions list option like this:

smtps     inet  n       -       -       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject

Now reload postfix:

sudo service postfix reload

Perfect! Postfix configuration is now complete.

Testing IMAP

There are two main protocols for fetching mail: POP and IMAP. The main difference between them is what they do with emails when they collect them: a POP client will fetch email from your server and remove it from the server when it’s done. This is inconvenient if you want to connect with two or more devices (like a phone and a computer) and have complete copies of all your emails on both. IMAP, on the other hand, makes a copy of the emails on the server and leaves the originals there. For this reason, I think IMAP is much more useful than POP and I didn’t even bother to set up POP on my server. We can now test the IMAP server with Telnet in a similar way to SMTP & SASL testing earlier. This time, we’ll be using port 143, the standard port for IMAP. The stages are:

  1. establish a connection with telnet localhost 143
  2. log in with a login "USERNAME" "PASSWORD"" (not base64 encoded this time)
  3. select inbox to see messages inside b select inbox
  4. logout with c logout

In case you're wondering, the "a b c" thing is done because a client can send multiple commands to the server at once, and they might not come back in the same order depending on what they are. So, the responses have the same letter as the commands they are responding to so that the client doesn't get muddled.

Here’s an example, using the testmail user we created earlier:

telnet localhost 143
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS AUTH=PLAIN AUTH=LOGIN] Dovecot ready.
a login "testmail" "test1234"
a OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE] Logged in
b select inbox
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permitted.
* 1 EXISTS
* 0 RECENT
* OK [UNSEEN 1] First unseen.
* OK [UIDVALIDITY 1385217480] UIDs valid
* OK [UIDNEXT 2] Predicted next UID
* OK [NOMODSEQ] No permanent modsequences
b OK [READ-WRITE] Select completed.
c logout
* BYE Logging out
c OK Logout completed.
Connection closed by foreign host.

Adding TLS support

Now that we know IMAP is working, we need to enable IMAPS (imap with SSL/TLS). The standard port for this is 993.

Many other tutorials that were written for older versions of dovecot will tell you to do this in different ways that won’t work, I tried 3 different methods before I ended up with a working one.

First, edit /etc/dovecot/conf.d/10-master.conf, find the “service imap-login” block and uncomment the port and SSL lines so that it looks like this:

service imap-login {
  inet_listener imap {
    port = 143
  } 
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

Edit 14/10/2015: the default dovecot configuration files changed recently after Jessie became the new stable distribution of Debian, which caused some users problems; TLS on port 993 used to be enabled by default but now it isn't. We need to re-enable it.

In /etc/dovecot/conf.d/10-ssl.conf, find ssl = no and change it to:

ssl = yes

There have been some security vulnerabilities discovered in older versions of the SSL protocol in recent times. SSLv2 is disabled by default, but it doesn't harm to explicitly disable it again. SSLv3 is vulnerable to an attack called POODLE, so we will disable it too. In the same file, find the ssl_protocols parameter line, uncomment it and add !SSLv3 to the end, like this:

ssl_protocols = !SSLv2 !SSLv3

Edit 02/09/2017: if you're using Debian Stretch or later, or one of its derivatives, then you will need to edit that line to match the following. The SSLv2 option is no longer recognised as an option for ssl_protocols because it has been removed entirely:

ssl_protocols = !SSLv3

For some bizarre reason, the Dovecot package for Raspberry Pi (and possibly newer versions of Ubuntu) does not create a self-signed certificate during installation like it used to. So, we have to create one manually. If you look in /usr/share/dovecot/ you will find the script that used to be used to generate the certificate; we can use it ourselves to simplify the process.

The script is located at /usr/share/dovecot/mkcert.sh and looks like this:

#!/bin/sh

# Generates a self-signed certificate.
# Edit dovecot-openssl.cnf before running this.

OPENSSL=${OPENSSL-openssl}
SSLDIR=${SSLDIR-/etc/ssl}
OPENSSLCONFIG=${OPENSSLCONFIG-dovecot-openssl.cnf}

CERTDIR=/etc/dovecot
KEYDIR=/etc/dovecot/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 -days 365 || exit 2
chmod 0600 $KEYFILE
echo 
$OPENSSL x509 -subject -fingerprint -noout -in $CERTFILE || exit 2

If you were going to use this certificate for any significant length of time, it would be worth editing the parameters in the config file it uses (/usr/share/dovecot/dovecot-openssl.cnf) to set the proper common name and contact details on the certificate. However, I suggest you leave the defaults as they are, use this certificate just for testing, and then come back later and generate a new cert when everything is working (more on that later).

You must be in the same folder as the configuration file when you run the script, or it will not find the config and the certificate generation will fail. The following two commands will change to the right folder and then execute the script:

cd /usr/share/dovecot
sudo ./mkcert.sh

You should see a message "writing new private key to '/etc/dovecot/private/dovecot.pem'" and then some details about the certificate.

Next, find the following two lines in /etc/dovecot/conf.d/10-ssl.conf and uncomment them:

#ssl_cert = </etc/dovecot/dovecot.pem
#ssl_key = </etc/dovecot/private/dovecot.pem

Now reload dovecot to apply the changes:

sudo service dovecot reload

Since IMAPS is a connection over SSL/TLS, we can’t use Telnet to test it. Instead, we use openssl to create a secure connection. There are two versions of the command, one will show you LOADS of information about the certificate used to encrypt the connection, and the other will suppress this info. I recommend trying the long version out of interest, but both will work the same for the test:

For full information:

openssl s_client -connect localhost:993

For minimal information:

openssl s_client -connect localhost:993 -quiet

I won’t print the output of the first command, because it’s ridiculously long. Here’s an example of the second, including a login test:

admin@samhobbs /etc/dovecot/conf.d $ openssl s_client -connect localhost:993 -quiet
depth=0 O = Dovecot mail server, OU = samhobbs, CN = samhobbs, emailAddress = root@samhobbs.co.uk
verify error:num=18:self signed certificate
verify return:1
depth=0 O = Dovecot mail server, OU = samhobbs, CN = samhobbs, emailAddress = root@samhobbs.co.uk
verify return:1
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN] Dovecot ready.
a login "testmail" "test1234"
a OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE] Logged in
b logout
* BYE Logging out
b OK Logout completed.
Connection closed by foreign host.

Good stuff: SSL/TLS is working on port 993, and you can log in successfully.

Note that by default Dovecot uses a “snakeoil” self-signed certificate. SSL/TLS certificates are used for two purposes: encryption and verification. The “snakeoil” certificate will encrypt your content but it won’t verify that you’re talking to your server – you could be talking to someone imitating your server (anyone can create a self-signed certificate claiming to be any website).

If you’d like to get your certificate signed without forking out loads of money to a cert signing authority, I’d recommend CAcert. I've written a tutorial explaining how to generate your own cert and get it signed here. If you opt for a commercial certificate, you can use the CAcert tutorial to generate the certificate and then this tutorial will explain the differences in the installation/configuration of commercial certificates once you have it signed.

If you're testing a proper certificate, use this command to tell openssl where the trusted root certificates are stored:

openssl s_client -connect localhost:993 -quiet -CApath /etc/ssl/certs

Tidying up and enabling WAN access

Before opening the ports on your router to the world, it’s a good idea to delete that test user because the password is so easy to guess.

sudo userdel testmail

Also, if you still use the "pi" login, for goodness' sake change the password from "raspberry"! You can do this using the passwd command when logged in as pi:

passwd

Or you can achieve the same thing when logged in as another user by using sudo to gain root privileges:

sudo passwd pi

Now you can open a few ports on your router’s firewall. Make sure your Pi has a static LAN IP address and then forward these ports from WAN to its LAN IP address:

  • Port 25 for SMTP (used for receiving emails)
  • Port 465 for secure SMTP (used for sending emails after SASL authentication)
  • Port 993 for IMAPS (used to receive emails on your phone/tablet/computer)

Here’s an example on my router, running OpenWrt:

openwrt-port-forwards-raspberry-pi-email-server.png

Setting up IMAP Email Clients

I’m now going to run through setting up IMAP email clients quickly, using K9 Mail on Android and Thunderbird on GNU/Linux as examples. The setup for Thunderbird on Windows and Mac OSX should be very similar.

The basics are this:

  • Select an IMAP connection
  • Your login is your username only (omit @yourdomain.com), and you password is…your password!
  • For incoming emails: select use SSL/TLS always and the program should automatically select port 993
  • For outgoing emails: select SSL/TLS always. The program may suggest port 587, but you want port 465

K9 Mail

Open K9 Mail and select add new account. Type in your account information (you@yourdomain.com and password) and then select manual setup. Select IMAP and then enter your information as follows…

Incoming email:

K9 Incoming Email Settings

Outgoing email:

K9 Outgoing Email Settings

Thunderbird

Open Thunderbird, and then click Account Actions –> Add Mail Account.

Fill in your password and email address, which is your username followed by your fully qualified domain name (FQDN), i.e. username@yourdomain.com:

Thunderbird Step 1: Mail Account Setup

Thunderbird will try to auto-detect settings and fail. Don’t worry, this is normal. Select “manual config”:

 Thunderbird Step 2: TB will try to autodetect settings, and fail. Select “Manual Config"

Now edit the settings as appropriate. I had to remove a period (.) from in front of my “server hostname”, and edit the SSL and Authentication settings. If you select “SSL/TLS” for both incoming and outgoing, ports 993 and 465 are automatically selected:

Thunderbird Step 3: Edit the settings so that they match these (but change them to match your username and domain name!)

Now try emailing yourself from your external email address, and see if your email gets through. If you are having problems, be sure to check you’ve set up an MX record as well as a DNS A record.

Stuck in spam filters?

A few people have contacted me recently to say that their email server is working fine but their emails are getting sent to Gmail's spam folder.

If you are experiencing problems like this (or even if you're not), try setting up an SPF and/or PTR record as explained in my DNS basics tutorial.

You might also want to check if your domain name or IP address are on any blacklists. There's a handy website called MX toolbox that lets you do this (choose blacklist check from the dropdown menu).

Almost done…

Good news! If you’ve reached this far and everything is working, then you’re almost done. The next step (Webmail with Squirrelmail) is optional but by far the easiest of the three steps.

If you’ve hit a rut, please post a comment and I’ll try and help you out.

If not… continue to Raspberry Pi Email Server Part 3: Squirrelmail

Type: 

Comments

Hi Sam - well after un-installing and reinstalling Postfix and Dovecot all seemed to be going well. The first issue I struck was that Dovecot was now reinstalled in /usr/share/dovecot. There was nothing in the /etc/dovecot directory! But that didn't seem to matter - I just referred to that directory to edit the configuration files. The next strange issue was that telnet seemed to stop working at some point after creating the new test user. It would open and immediately close ('connection closed by foreign host') or would sit and not allow any commands and then close automatically after some minute or so. Not to worry - I'll press on! (I actually reinstalled telnet, but still the same). Then, after making the ssl changes, telnet started working correctly again and connected - with no prompts - to port 465 as suggested! Finally, after setting up IMAP (although I NEVER was able to telnet into port 143?) and following the instructions for creating a certificate, (and confirming it and the private keys are there as expected) I hit a brick wall. I've carefully un-commented all as suggested in the 10-ssl.conf file and try to login with 'openssl s_client' etc but get 'connection refused - errno=111'. I've restarted dovecot and postfix; I've restarted my Pi....nothing works. I've double checked all the config files (although I do think I found the previous problem - there are TWO instances of authentication mechanisms in auth.conf and if you add 'login' to the first- as suggested, it presumably gets overwritten by the second further down that doesn't have the login parameter) but cannot see any errors. I do notice in the 10-ssl.conf file that there is a comment:

"Included doc/mkcert.sh can be used to easily generate self-signed certificate, just make sure to update the domains in dovecot-openssl.cnf"

but no instructions to do so? Is that OK?

Again, any help gratefully received!

Many thanks - Mike

Mike,

There is something seriously wrong if you don't have an /etc/dovecot directory. Normally /usr/share is for default configuration files, you should not be editing those.

Sam

One further issue - I notice my apt-get says it is selecting dovecot-core instead of dovecot-common? Is that significant?

Thanks

Mike

Hi Sam - Further investigation.......

This is what is in the dovecot-openssl.cnf file and looking at the Dovecot wiki (and actually at your tutorial, if you read the top of the script copy it says "Edit dovecot-openssl.cnf before running this."), it says this MUST be modified or the certificate will NOT work.

[ req_distinguished_name ]
organizationName = Dovecot mail server
organizationalUnitName = @commonName@
commonName = @commonName@
emailAddress = @emailAddress@

[ v3_req ]
basicConstraints = CA:FALSE

I have tried changing some of the parameters but nothing works. In addition, if I delete the certificate and private keys, I get the same error message, so it looks like the certificate(s) that I've been producing just do not work! So, I guess my question is - what do I change in this file and to what? Any information gratefully received! Thanks Sam!

Mike

Mike,

The tutorial also says why you don't need to edit that config file just below the script:

If you were going to use this certificate for any significant length of time, it would be worth editing the parameters in the config file it uses (/usr/share/dovecot/dovecot-openssl.cnf) to set the proper common name and contact details on the certificate. However, I suggest you leave the defaults as they are, use this certificate just for testing, and then come back later and generate a new cert when everything is working (more on that later).

We're just generating a self-signed certificate for testing, just to prove that we can get TLS working. After setting up initially and proving that it works (with the commandline tests in the tutorial), you're supposed to either get a certificate signed by CAcert or a paid certificate authority, so that you can connect to it with a normal client and the certificate will be accepted. Even if you edit that config file so that the certificate has the name of your domain on it, an email client (like thunderbird) would not accept the certificate because it hasn't been signed by a CA that is trusted by your operating system.

If you want to read more about this, you can see my CAcert tutorial and this tutorial on how to use commercial certificates.

Really though, I would focus on finding out why you don't have any files in the /etc/dovecot directory. Something is seriously wrong there.

Sam

Sorry Sam - seems I've been a bit of a goose!! Uninstalling Postfix and Dovecot didn't. Well, not entirely. Then re-installing also didn't! But after a lot of file cleaning and directory deletion and using just about every 'clear' option of apt-get, before re-installing again, it seems I'm back in action. Dovecot is where it is supposed to be; every test so far (to the end of section 2) has worked as expected and I have a working email server! Emails go back and forth just as expected. Of course, Thunderbird is complaining about the 'shonky' certificate, but I'll tackle that later. You probably want to make an amendment to the tutorial (part 2) where you say:

"..add the following lines to 10-auth.conf"
disable_plaintext_auth = no
auth_mechanisms = plain login

In my default config file, both lines were present and not commented out. However, they aren't listed together and if you don't notice that the auth_mechanisms line is there and add another, it gets 'overwritten' by the later line which only has the plain option set. I think that was certainly one of my early problems. Maybe you should note that '...the lines may be present and if so, make sure that 'login' is added as an option and they are commented out' rather than a blanket '...add the following'. But it's a small point and you have been most generous with your time and effort. It's much appreciated! Kind regards - Mike

Mike,

Thanks! That's great feedback, I'll add a note - there are a few small changes in the default config files for Postfix / Dovecot between Wheezy and Jessie, I think this might be one of them . The differences are very difficult for me to spot, so it takes someone like you to notice and take the time to report it.

Really happy you got it all working!

Sam

Hi Sam - Glad to say that the email server works very well - but there are a couple of glitches that I wonder if you can assist with?. I have a number of email addresses that I use for different purposes. I suppose you could group them in three 'bins' There are Gmail address. These work exceptionally well with my personal email server set-up. I can send and receive emails either way with or without attachments. Fantastic, and absolutely no problems.

Then I have email addresses with my ISP - iinet (the second largest in Australia). I can send emails to my home server from them, but - generally - cannot receive emails sent from my home address to them. I say generally, as a couple of times, they have 'go through'. However, there is no consistency and it could not be used as the basis of a reliable system. I've check the mail.log in /var/log and these lines of text seem typical (with obvious details removed!)

Jan 19 10:49:07 raspberrypi2 postfix/smtp[3690]: 5DF8963411: to=,
relay=as-av.iinet.net.au[xxx.0.178.180]:25, delay=9779, delays=9779/0.06/0.02/0, dsn=4.0.0, status=deferred
(host as-av.iinet.net.au[xxx.0.178.180] refused to talk to me: 554-icp-osb-irony-in6.iinet.net.au
554 Your access to this mail system from xxx.59.180.28 has been rejected due to the sending MTA's
poor reputation. If you believe that this failure is in error, please contact the intended
recipient via alternate means.)

I should add that I have a dynamic IP address on my FTTP internet access and use DDNS to translate to my email address - which for most purposes, doesn't seem to be a problem. (Getting a static IP is an expensive option here in Australia where internet access is, by world standards, VERY expensive. I couldn't justify it especially as I am now retired!)

The third 'bin' consists of a few other 'webmail' address. I've only tried a live.com.au address - the Microsoft provided one. Again, I can send email from it to my home server, but not from home to live.com.au. A different message appears in the log:

Jan 19 10:23:15 raspberrypi2 postfix/smtp[3269]: A62B465F4D: to=,
relay=mx2.hotmail.com[207.46.8.199]:25, delay=1.2, delays=0.32/0.03/0.62/0.2, dsn=5.0.0,
status=bounced (host mx2.hotmail.com[207.46.8.199] said: 550 DY-001 (BAY004-MC6F6) Unfortunately,
messages from xxx.59.180.28 weren't sent. Please contact your Internet service provider. You can
tell them that Hotmail does not relay dynamically-assigned IP ranges. You can also refer your
provider to http://mail.live.com/mail/troubleshooting.aspx#errors. (in reply to MAIL FROM command))

As a result of this, I checked at http://www.spamhaus.org and get "xxx.59.176.0/20 is listed on the Policy Block List (PBL)". I also read on the same page:

Important: If you are using any normal email software (such as Outlook, Entourage, Thunderbird, Apple Mail, etc.) and you are being blocked by this Spamhaus PBL listing when you try to send email, the reason is simply that you need to turn on "SMTP Authentication" in your email program settings.

So - am I sending 'unauthenticated' emails? is this the problem? Is it a dynamic vs static IP issue? I suppose, in other words - HELP!

I realise I can stick with a combination of Gmail and my shiny, new mail server - it works! But - if I want to 'advertise' my home address, it really has to be watertight or else it's pretty useless.

Thanks so much for your assistance (which I hope might help other people!)

Mike

Unfortunately, this is just a problem with the reputation of the IP address you have been dynamically assigned - other people who have had that IP in the past have sent spam (or have had compromised machines on their network sending spam).

You can't do anything about it apart from get a static IP address, unfortunately - other dynamic IP addresses are likely to have the same problem.

Ignore that SMTP authentication thing you found, it's not relevant to your case (it's for people sending email on port 25 straight from their email client, authenticating with their ISP's email servers).

Sam

Thanks so much for your help; assistance and fantastic patience, Sam. It goes without saying that it's people like you who make the 'net what it is - a continuous source of pleasure and wonderment! I've solved all my addressing problems by relaying my email through my ISP mail server, as you suggested. This involved adding a few lines in my postfix main.cf config file. I found good instructions at:

https://www.howtoforge.com/postfix_relaying_through_another_mailserver

However, these mods alone wouldn't work until I realised I was probably trying to authenticate to my ISP mail server on port 25 - and I could see from the mail log that it was refusing my request. Then I found a snippet at:

https://simon.heimlicher.com/articles/2010/08/29/smtp-smarthost

that explained what additional steps I needed to take - adding port 587 to the mail server name (mail.iinet.net.au:587) in the sasl_passwd file, as well as adding two extra line in the config file so that I was using STARTTLS to authenticate (which my ISP demands). And it works. All of it! I can now send and receive emails from any address I try - Gmail; Hotmail; ISP mail etc

One interesting aside is that as soon as that relay authentication worked, all the messages I'd been - unsuccessfully! - trying to send from my "forbidden" IP address suddenly started flooding into my in-box! Ah well, it at least shows it works!

Hopefully, if others are having similar problems with dynamic addresses, they might find these tips useful as well.

Kind regards - and thanks again.

Mike

You're welcome :) That's great, thank you for posting how got it working too.

This is one of the things that's very difficult for me to help people with because every ISP is different, and I haven't had to set it up myself!

Sam

Thanks for the great tutorial, but I'm stuck at the Testing SASL part. I type in "AUTH PLAIN" followed by the long string of text and it get the error "503 5.5.1 Error: authentication not enabled." I looked in the 10-master and 10-auth files to see if I typed everything right, and it looks fine.

The only thing that I think could be a problem is that when I go to restart dovecot a few steps earlier, it fails due to "unknown setting: unix_listener". Does this effect the testing of SASL?

The unix_listener parameter should be set inside the service auth { block, I think you've probably not commented out the entirety of the old block or put unix_listener on its own (not inside the block).

Sam

Thanks Sam! It looks like I typed "stmpd" rather than "smtpd" in main.cf, so now I'm back on track.

Now I'm having trouble with Testing IMAP. I saw in the comments to double check the "Tell Dovecot where your Mailbox is" section and I noticed that, after following those instructions, I now have "mail_location = maildir:~/Maildir" written twice in the 10-mail.conf file, and both are commented out. Do I need both, and should I uncomment one? It seems every combination fails to change anything.

You only need one of the lines, so comment one and keep one.

What are the symptoms now? Any errors when restarting, and what happens. when you test?

Sam

Thanks! I was editing the wrong line, one that was already commented out.

A few steps down the line and I'm not sure what to do again. I created a new file at /usr/share/dovecot/mkcert.sh, copying and pasting in what you have in the tutorial (I had no mkcert file before). However, when I do "cd/usr/share/dovecot" and "sudo ./mkcert.sh", I get a response saying command not found.

Do I need to edit dovecot-openssl.cnf?

You only need to use the mkcert script if you don't already have a cert. Check main.cf for the cert file locations, and see if they exist?

Sam

I looked in main.cf but couldn't find any other cert info.

When I go through the steps and get to "openssl s_client..... -qiuet", I get a response of "write:errno=104"
When I go through the steps and leave out "-quiet", I get the same error, followed by "no peer certificate available", "no client certificate CA names sent", "SSL Handshake has read 0 bytes and written 298 bytes", "New none, cipher none, secure renegotiation is not supported, compression none, expansion none"

Mike

Are you certain you don't have any lines like this?

smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key

If you don't, then add them. If you do, update them so that the paths point to real certificates and keyfiles.

Sam

I found those two lines in the file. Here's where I am now:

Here's the error I get:
root@raspberrypi:/etc/postfix# cd /usr/share/dovecot
root@raspberrypi:/usr/share/dovecot# sudo ./mkcert.sh
sudo: ./mkcert.sh: command not found

I got this error after creating a new file called mkcert.sh at /usr/share/dovecot/, then reloading dovecot. I erased all
the data from that file and tried again, with the same result.

When I reload dovecot, I noticed this error:
root@raspberrypi:/usr/share/dovecot# sudo service dovecot reload
doveconf: Fatal: Error in configuration file /etc/dovecot/conf.d/10-ssl.conf line 43: Expecting '='
[ ok ] Reloading IMAP/POP3 mail server: dovecot.

I went into 10-ssl.conf to find line 43 and found this area:
SSL protocols to use
ssl_protocols = !SSLv2 !SSLv3

I'm not sure where exactly it wants the "=", but maybe this is the problem that's holding me back?

Thank you so much for all the help! I'm nearly done setting this thing up!

The hash worked just as you said, but now I'm in Thunderbird and it can't connect with my username and password. Thinking back to when I set up the testmail user, I realized I never created a regular user for myself, so I went back through those steps to create one, but Thunderbird still doesn't recognize it.

Am I possibly missing something with my domain name? currently, my regular domain name (bought from godaddy) basically points to a Wordpress folder on my Pi. I don't know if I need to somehow more directly link it to the Pi or what. In main.cf, I have it as "myhostname: website.com". Should it be www.website.com, or some other way, or just like that?

Or is there an entirely different issue with the username and password?

Just your domain name (without the www.) is fine, it should be the part of the email address after the @ symbol.

Have a look in the logs (/var/log/mail.err) to see if it's an internal error? It's possible that the Maildir wasn't created properly, or doesn't have the right permissions, or something like that.

Sam

Mail.err is completley blank, so no problems there. When I restart postfix, however, I noticed tons of warnings, like this:

[....] Starting Postfix Mail Transport Agent: postfixpostconf: warning: /etc/postfix/main.cf: unused parameter: stmpd_helo_restriction=permit_mynetworks, permit_sasl_authenticated, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_helo_hostname

There's probably 50+ more of these ina row before it finally says "ok". Maybe that's the problem?

Mike,

The parameter is smtpd_helo_restrictions not smtpd_helo_restriction, fix that typo and see what happens.

I would expect to see those startup messages in mail.err too, one reason it might be blank is if you're using binary logging with systemd - the journald queries to get messages from postfix look something like this:

sudo journalctl -u postfix

Sam

I updated the "helo_restrictions" line, but still no luck.

I went back to make sure I created a new user (the name and password I want to use for my email) and I did create it. I went back to "openssl s_client -connect localhost:993 -quiet" and tried logging in, but I get "authentication failed".

I also get "command not found" when I do "sudo journalctl -u postfix"

Mike

I can't think of anything else that is obviously wrong, I think we need to find your mail log first and check for messages in there. Can you have a rummage and see if you can find it?

Sam

Still nothing in var/log/mail.err

I started going through all the steps again, staring with the beginning of the postfix tutorial. I found one area where I wrote "stmpd" instead of "smtpd", so I fixed that.

Now I'm back to testing SASL with no luck, getting an "authentication not enabled" error. The old "service auth" is commented out, the new one is written exactly as it's written in the tutorial. I reloaded postfix, and triple checked that all the appropriate lines are spelled "smtpd". I also tried both commenting and uncommenting the "mynetworks" line in one of the files.

Pages

Add new comment