I've set up my mail server using a guide from Digital Ocean, followed by another guide. So, now if I send mail to torvin@mydomain, it works.

Now I'm trying to set up a catch-all address for all undelivered mail. Things I've tried so far:

1) Replaced

local_recipient_maps = proxy:pgsql:/etc/postfix/pgsql-boxes.cf $alias_maps

line with this:

local_recipient_maps =
luser_relay = torvin

The result I see in the logs:

postfix/lmtp[32692]: D5AD540085: to=, relay=mail.mydomain[private/dovecot-lmtp], delay=0.21, delays=0.17/0.01/0.01/0.02, dsn=5.1.1, status=bounced (host mail.mydomain[private/dovecot-lmtp] said: 550 5.1.1 User doesn't exist: thisisjustatest@mydomain (in reply to RCPT TO command))

2) Instead replaced

alias_maps = hash:/etc/aliases proxy:pgsql:/etc/postfix/pgsql-aliases.cf


alias_maps = hash:/etc/aliases pcre:/etc/aliases_pcre proxy:pgsql:/etc/postfix/pgsql-aliases.cf

And created /etc/aliases_pcre with the following content:

/.*/    torvin

Result is the endless loop of:

to=, relay=local, delay=0.01, delays=0/0/0/0, dsn=5.4.6, status=bounced (mail forwarding loop for torvin@mydomain)

3) Instead tried

virtual_alias_maps = pcre:/etc/aliases_pcre

Now all my mail goes to torvin, and never gets delivered to any other existing users in the system.

Please help!

2 Answers 2


This is because /.*/ also includes torvin. I assume your proxy:pgsql: has information on this user, but pcre:/etc/aliases_pcre is looked before that. In this case, the easiest solution would be to reorder them. Also, a simple hash: database line @example.com [email protected] would do the same as your /.*/ PCRE approach.

Technical implementation aside, having such a catch-all on a domain with multiple users is a bad idea. There would not be ANY actual messages that would need attention. What you'd get is:

  • Spam for non-existent common addresses like [email protected]. This is the most common.
  • Messages destined to someone else. Picture someone trying to send confidential information to Jane Smith on <[email protected]>, but forgets the dot <[email protected]> or mistypes it like <[email protected]>. Normally, the sender would receive a notification that the user doesn't exist, double check the email address and resend the message. With a catch-all, this doesn't happen. Instead, there's this torvin guy in an awkward and most likely illegal situation.

Both should be treated with a SMTP connection-stage rejection.

  • I tried reordering and got the same mail forwarding loop problem. Then I tried @mydomain torvin@mydomain and got postalias: warning: /etc/aliases, line 18: name must be local. I suspect this syntax is supported in virtual_alias_maps, but then I will get the problem #3. Any ideas? Also, thank you for your concern, I understand that my setup is quite unusual and your argument is valid in the general case!
    – torvin
    Dec 10, 2018 at 21:22
  • 1
    a) As you already have proxy:pgsql: you could edit the SQL query to answer with torvin when there's no match in the database. b) If you use hash:, remember to postmap. Dec 11, 2018 at 5:03
  • Thanks for your reply! a) I don't think it's a SQL query, /etc/postfix/pgsql-aliases.cf looks like a config file of some sort, but I have no idea how to find documentation for it. And I don't think I can trick it into returning something in case of a miss... b) Sorry, but I literally have no idea what that means. I read the man page for postmap but I don't understand how and if it is applicable in my situation (LMTP etc). postfix is just horrifying...
    – torvin
    Dec 11, 2018 at 9:59
  • a) Don't have overly complicated configuration you don't understand. If your users aren't listed in the database, remove such configuration. If that part was relevant, it's certainly possible to modify the SQL query. b) You have hash:/etc/aliases, so you already need to to postmap /etc/aliases every time you make a change to that file. The hash: database for virtual aliases works the same way. Dec 11, 2018 at 10:02
  • a) yes, I want to keep users in the DB, because I don't want to create system users for mailboxes. but what I'm saying is, /etc/postfix/pgsql-aliases.cf doesn't have any SQL query, so there is no way to modify it. b) I used newaliases instead... is that wrong?..
    – torvin
    Dec 13, 2018 at 10:14

When using Postfix with Dovecot LMTP, the catchall function is not supported natively like Postfix's luser_relay or Cryus's lmtp_catchall_mailbox.

The acceptable way to implement it is to use Postfix's virtual_alias_maps = hash:/etc/postfix/virtual_alias .

If there is only one mailbox:

@example.com    [email protected]

If there are more than one mailbox, list all mailbox in /etc/postfix/virtual_alias to alias to itself also:

[email protected]    [email protected]
[email protected]   [email protected]
@example.com    [email protected]

This method is mentioned in the book "Postfix The Definitive Guide".


alias_maps and luser_relay are layers within the Postfix local delivery agent(LDA). Checkout https://www.postfix.org/postconf.5.html#mailbox_transport. aliases > .forward files > mailbox_transport > mailbox_command > home_mailbox > mail_spool_directory > fallback_transport > luser_relay.

You can totally replace the Postfix local delivery agent if you are using lmtp. local_transport = lmtp:unix:private/dovecot-lmtp. And put all your alias in virtual_alias virtual_alias_maps = proxy:pgsql:/etc/postfix/pgsql-aliases.cf

The virtual alias rewrites recipient addresses for all local, all virtual, and all remote mail destinations. https://www.postfix.org/virtual.5.html I think local alias is redundant, and is still here for compatibility only.

local_recipient_maps could be ignore because of the smtpd_reject_unlisted_recipient rule.

An address is considered "unknown" when 1) it does not match a virtual(5) alias or canonical(5) mapping, and 2) the address is not valid for its address class.

A catchall row exist in the virtual_alias mean every address will be accepted.

  • After 4 years you solved my problem! Thank you, it worked!
    – torvin
    Oct 25, 2022 at 7:34
  • I tested more and it didn't work completely... I have aliases alias_maps = hash:/etc/aliases proxy:pgsql:/etc/postfix/pgsql-aliases.cf - those stopped working. how do I make them work together?
    – torvin
    Oct 26, 2022 at 3:15
  • lol, you still learning mail server after 4 years!! I wrote this comment for people finding the catchall function like me. Check my updated comment.
    – Waiho
    Oct 26, 2022 at 4:37
  • not really learning. I just want to configure it once and forget about it. are you saying I should move my aliases into virtual_alias file instead? I also have no idea about what local transport is and whether I need to change anything in it
    – torvin
    Oct 28, 2022 at 23:42
  • Yes. Put all mailbox and alias in the virtual_alias source, no matter it is a file or postgresql. The format of mailbox is alias to itself, torvin@mydomain torvin@mydomain. Put the catchall row @mydomain torvin@mydomain to your virtual_alias source also. Change local_transport to the lmtp path that you are using currently.
    – Waiho
    Oct 29, 2022 at 12:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .