Troubleshooting your mail server

General troubleshooting tips

  • Run “postfix check” to make Postfix look for obvious configuration errors. If it returns no output then no problem was found.
  • Read your /var/log/mail.log and look for warnings and errors.

Postfix keeps unwanted emails in the queue

Check that you do not keep soft_bounce enabled. If “postconf soft_bounce” shows “yes” then run “postconf soft_bounce=no”.

I get “Permission denied” from Dovecot in the mail.log file

You have the permissions wrong. Run:

chown -R vmail:vmail /var/vmail

Postfix says: “Mail loops back to myself”

Postfix tried to send an email to the internet because it did not feel responsible for the recipient’s domain. However DNS records pointed it back to itself. So either your DNS record for a certain domain is wrong (unlikely) or your Postfix refuses to receive email for the given domain (very likely). Check that the recipient’s domain is listed in the “virtual_domains” table in the MySQL database. And verify that your CF files are working correctly

37 thoughts on “Troubleshooting your mail server”

  1. Hello. First let me say that your guides are the best and they are very much appreciated. I have used the squeeze guide and it has been working perfectly for the past few years. Now I decided to follow this guide and everything works fine except the fact that when I login to Roundcube, the email is username@localhost. And when the emails leave, they leave as username@localhost.

    Any thoughts?

    1. I figured it out and in case someone needs it, just add a new variable in the $config array of roundcube in the file /etc/roundcube/ like this:
      $config[‘username_domain’] = array(‘servername’=>’’,’’=>’’,’localhost’=>’’);

  2. Hallo Christoph,

    this wonderful guide helped me to build a personal mail server from scratch. Everything is working like a charm and mails can be received and sent using various clients. The only thing missing now is making the MX-record of my domain point to the new server, so that it becomes the primary mail host.

    Before I do so, I’d like to ask you why both – gmail and hotmail – consider mails being sent via this new host as SPAM? Could it be caused by the mismatch in the domain’s mx-record which currently does not point to the new server? I don’t see no other cause, the headers are clean otherwise.

    Viele Grüße und Frohes Neues!


      1. hi,
        i confirm , after design and apply the spf record, the problems stopped , now i can receive the e-mails on my gmail.

        thanks Hannes for your tips.

  3. Christoph Haas

    @Christoph: thanks for the feedback. Nice to hear everything worked well and the time was well-invested. The problem you are facing with GMail and Hotmail is not uncommon. Such large ISPs usually have their own black lists and score IP addresses. A well-known scoring service is I wouldn’t give them money – I don’t like their business model. But you can at least enter your IP address and find out if it’s ocnsidered neutral, good or bad.

    My strategy for introducing a new mail relay is to slowly warm it up. If you send too many emails per time unit and the ISPs never received emails from that gateway then they will be suspicious and quickly throttle the amount of email they take from you.

  4. Hi Christoph, thank you very much for this how-to! So far, everything is working fine except one thing: When I tell sieve to forward a certain message, I get

    postfix/sendmail[18905]: fatal: open /etc/postfix/ Permission denied

    It seems like sendmail implementation is part of postfix, but then I don’t know why it can’t access the file. The permissions are:

    /etc # ls -l | grep postfix
    drwxr-x— 1 root postfix 712 7. Jan 22:55 postfix

    /etc/postfix # ls -l grep
    -rw-r—– 1 root postfix 28020 7. Jan 04:45

    Do you have any idea what could be wrong? It works fine when “others” have read access to the file, but that is not what I want, is it? I added the users dovecot and vmail to the postfix group, but that didn’t change anything. Can I figure out as which user the process is running?


    1. Christoph Haas

      Both the directory /etc/postfix and the must be others-accessible. I wonder what broke it.

      1. Thank you very much! I didn’t know that this is okay and even necessary. Now it forwards happily 😉 It’s very likely that I broke it myself in a burst of over-cautiosness when you told us to secure the mysql-* files, so I guess I have to check some more file permissions now :/

  5. Hello,
    thanks for the great tutorials,
    Hovewer I have a little problem with mailing lists:
    My assumptions:
    1. I created alias: ->,,

    2. I want to restrict acces to lsit to let writing messages to it only by:

    I tried to do this in this way which doesn’t work properly :
    smtpd_recipient_restrictions =

    check_sender_access hash:/etc/postfix/access,

    FILE /etc/postfix/access: managers_sender_list

    FILE managers_sender_list:

    I checked it on but I think this is not what I’m looking for.
    Am I wrong ? How to implement these assumptions properly ?

    1. I tried simple way:
      Fake account + Filters (managesieve) in RC.
      Works great for small no of redirections.
      If you want to use many addresses, you can edit /accountdir/sieve/managesieve.sieve and paste the list in proper format.
      There is one more thing: where to set the limit of max redirections.
      I tried in:
      sieve_max_redirects = 100
      Doesn’t work.

      1. That’s work:
        1. Fake account + Filters (managesieve) in RC.
        2. edit:
        sieve_max_redirects = 100
        sieve_max_actions = 200

  6. Hi Christoph,
    I’ll repeat what others say – thank you for such a great tutorial! It rocks! I’m just finishing configuration of mail server on AWS t2.micro (free but limited hosting offer from Amazon) and wondering which ports should be opened on firewall to allow communication with mail clients and other mail servers. I consider 25 for transporting between MTA, 587 for submitting and receiving email to and from user, 443 for Roundcube and PhpMyAdmin (although here I consider using some uncommon port) and 22 for SSH. I’m not going to use POP so 110 is not needed. Do you think anything is missing? Regards, Piotr.

    1. Hi Pjotr,

      I would consider not opening a port for PhpMyAdmin, but instead using port redirection over SSH and then access it locally on your workstation. I always have to look up the syntax, and I am afraid I’ll lead you on the wrong path if I just write down some pseudo-forwarding-rule, so I leave that to you.

  7. How do I have to configure Thunderbird? I’m on a domain and Thunderbird cannot autoconfigure itself.

    Do I have to use IMAP or IMAPS? Port number? Password: plain text or encoded?
    SMTP port is 25? And password?

    Thank you!

  8. Just wondering. When I set up icedove with and the setting that was auto detected for both was “normal password”. I know that the server is setup up to encrypt this communication anyway but I was just wondering why “encrypted password” setting fails to work?

  9. Davide Marchi

    Hi friends,
    I would like to point out this trick, if you does not intend to use IPV6 on your email server and want to delivery email to google server. So because I found myself in this situation.

    If you receive from google server this message:

    Undelivered Mail Returned to Sender
    : host[2a00:1450:400c:c0a::1b]
    said: 550-5.7.1 [2a02:c205:2008:934::1] Our system has detected that this
    message does 550-5.7.1 not meet IPv6 sending guidelines regarding PTR
    records and 550-5.7.1 authentication. Please review 550-5.7.1 for more information 550
    5.7.1 . xs6si28642072wjc.244 – gsmtp (in reply to end of DATA command)

    Just add on Postfix


    and restart Postfix

    1. Francesco Piraneo G.

      Hi Davide,
      thank you very much for this hint! It solved me a headhace!

      @Christoph, why don’t include this configuration change in your guide, maybe with a small side note?

      Thank you again guys! 😉

      1. Christoph Haas

        I considered adding that. However Google says that the forward and reverse DNS records for IPv6 (AAAA and PTR) need to match. We should rather ensure that. Disabling IPv6 seems very wrong and is no long-term solution. If we are using IPv6 to connect to the internet we should rather do it right. Don’t you agree?

  10. A couple days ago someone noticed that their emails to me were bouncing. While troubleshooting I found the message:

    Feb 28 06:30:53 email postfix/cleanup[6200]: warning: 70A492127F: write queue file: No space left on device

    With further investigation I found that my root drive was full. The `df -i` command showed /dev/vda1 (/) to have 100% in the IUse column. After further troubleshooting without much luck I run the command again and get the following output:

    Filesystem Inodes IUsed IFree IUse% Mounted on
    /dev/vda1 187680 59966 127714 32% /
    udev 60970 315 60655 1% /dev
    tmpfs 63288 478 62810 1% /run
    tmpfs 63288 1 63287 1% /dev/shm
    tmpfs 63288 8 63280 1% /run/lock
    tmpfs 63288 13 63275 1% /sys/fs/cgroup
    /dev/mapper/vg1-mail 997472 141 997331 1% /var/vmail
    /dev/mapper/vg1-tmp 65536 21 65515 1% /tmp

    So somehow the problem resolved itself. Which is sometimes good, but now I have to live with the fear that it will just happen again. Any idea why this would happen?


    1. Christoph Haas

      @Tom: You could install “ncdu” and run “ncdu -x /” to find which directories use most of the space. Sometimes it is log file. Sometimes it is leftovers from package installations that you can clean out by running “apt-get clean”. On Ubuntu it’s typically leftover Kernel updates that can be cleaned out by running “apt-get autoremove”.

      1. Thanks for your help! ncdu was very helpful in identifying the bigger directories. Turns out that I was accidentally using `df -i` instead of `df -l` which was why it looked like I was only using 30%. Running clean and autoremove, along with removing some log files and locales cleared up a good bit of space. I should be good for now. Thanks!

  11. IPv6 get bounced by gmail:

    Diagnostic-Code: smtp; 550-5.7.1 [2001:981:52a5:1:e49b:b257:57eb:c4df] Our
    system has detected that 550-5.7.1 this message does not meet IPv6 sending
    guidelines regarding PTR 550-5.7.1 records and authentication.

    What I understand Christoph is my rdns record is not set. Which is correct while my emailserver is IPv4 natted behind my router. I tried `proxy_interfaces` with no result (I hoped postfix would use modem WAN interface IPv6 address..)

    For now `inet_protocols = ipv4` works.

    Have you got the time to elaborate a little bit more about IPv6?

    Kind regards, Marc

  12. I have followed along you tutorial, done everything, everything is working fine, I can send and receive emails on my server, also I can send email to any other server like gmail. However I don’t receive mail from gmail and outlook etc.
    smtp; The recipient server did not accept our requests to connect. Learn more at
    above is the error that I get when I try to send mail from gamil to my server.
    Any help?

    1. Christoph Haas

      Hi Davide. The servers should be able to have a secure connection between them. Either have the on the same network or make sure there is a VPN they can use. Then you could either just make the backup server use the primary database. Or you could use MySQL replication and run a MySQL slave on the backup MX. The second approach is slightly more complex if you haven’t used replication before – but it has the advantage that the backup server is completely independent from the first server.

  13. Davide Marchi

    I am very grateful for your reply Christoph,
    Undoubtedly the MySQL replication solution will be better.
    And so just duplicate the database and no need to edit configuration files (I’m just talking about synchronizing domains, v-users and alias) to prevent that the mx backup become a backscatter mail server.
    However in general I think adding a page with some documentation on how to create a backup server can be very instructive for your users 😉

    Thanks again for this guide!

    1. Davide Marchi

      I’ve finally setup a working MX email backup server, here, If you think to publish my experience.

      Basically as first thing: the backup server does not have to recognize as local, domains and addresses.

      “” the.backed-up.domain.tld (primary domain) (on DNS MX 10)
      “” the backup MX (secondary domain) (on DNS MX 20)

      1) never list in mydomains/myhostname the primary server domain.
      2) never list in virtual_alias_domains the primary server domain. I’ve commented it.
      3) never list in mailbox_domains o in virtual_mailbox_domains the primary domain. I’ve commented it.
      4) do not list in virtual_alias_maps the primary domain. I’ve commented it.
      5) this is useless: smtpd_sender_login_maps. I’ve commented it.
      6) myorigin = $myhostname
      7) mydestination =,, localhost
      8) always list in relay_domains every domains (virtual too)

      to do so via mysql add in the following files and their configurations:

      relay_domains = mysql:/etc/postfix/

      then create a file called: “/etc/postfix/” with content:

      user = mailuser
      password = your-password
      hosts =
      dbname = mailserver
      query = SELECT name FROM virtual_domains WHERE name=’%s’

      (all the query content are fine for workaround database structure)

      9) then add in

      relay_recipient_maps = mysql:/etc/postfix/

      create file “/etc/postfix/” with content:

      user = mailuser
      password = your-password
      hosts =
      dbname = mailserver
      query = SELECT email FROM virtual_users WHERE email = ‘%s’

      10) to ensure that aliases are also accepted (is it correct?):

      add in too:

      relay_recipient_maps = mysql:/etc/postfix/

      At this point (including relay_recipient_maps content) it will be:
      relay_recipient_maps = mysql:/etc/postfix/,mysql:/etc/postfix/

      create file:


      whose content must be:

      user = mailuser
      password = your-password
      hosts =
      dbname = mailserver
      query = SELECT source FROM virtual_aliases WHERE source = ‘%s’

      // I hope (if this is right, for me it is), this scheme may be of help to others. //

      Thanks to all

  14. One of the best tutorials I have ever seen!

    I do have one problem with it. I’m able to send email as whoever I want, even after adding smtpd_sender_login_maps=mysql:/etc/postfix/ to the submission service.

    Any idea on what the problem might be?

    postconf -q user@domain.tld mysql:/etc/postfix/ seems to work just fine, giving me user@domain.tld as a reply, and nothing if it doesn’t exist. The query is executed when a user sends a mail, but it never stops/blocks anything.

    Could I get a postconf -nf and postconf -Mf so I/others can compare the config when troubleshooting?

    Anyway, thank you for a fantastic guide, I’ve learned a lot from this. 🙂

    1. Christoph Haas

      Hi Alex. Glad you like the guide. Could you just quickly check that “postconf smtpd_sender_login_maps” prints what we would expect?

      1. It’s probably just me being stupid. I see now that I’m not using postfix 2.11, but 3.1, so that’s probably the problem considering how well written this guide is.

        Guess I’ll have to wait for your 3.1.4 guide, I’m really looking forward to it. 🙂

        I added the postfix config if you’re interested, but I don’t wanna waste your time. Anyway, thank you so much for this guide. I really mean it when I say that this is one of the best guides I have ever seen. Have a nice weekend! 🙂

        # postconf smtpd_sender_login_maps
        smtpd_sender_login_maps = mysql:/etc/postfix/

        All postfix config:

        I can see in the sql query log that the query in /etc/postfix/ is executed each time a client sends mail, but it never blocks anything.

Leave a Reply

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

Scroll to Top