Let’s do Postfix slowly and properly – Part 2: Address manipulation

Tweaking a local postfix setup with aliases, .forward and more.

In the last post in my Postfix series I went through the basics of configuring Postfix to accept mail. This second part will be a somewhat short addendum in which I cover a few extra settings related to how Postfix finds the right user to deliver mail to.

Postfix has an impressive amount of settings that can manipulate where email ends up. I’m only going to cover two and then quickly list some of the others.


In the last part, one of the four initial configuration parameters was myorigin but I never actually made use of it. It’s not going to be massively useful going forward but I think it’s helpful in understanding the sort of system, that we’re dealing with.

I’ll start up a telnet sessions as before, i.e.

telnet localhost 25

I greet Postfix with a HELO [name of machine I’m calling from] and enter the MAIL FROM and RCPT TO commands as follows:

MAIL FROM:<alice>        
250 2.1.0 Ok
RCPT TO:<bob>
250 2.1.5 Ok
354 End data with <CR><LF>.<CR><LF>
This is an email without domains in the from or to fields.
250 2.0.0 Ok: queued as 4B3A6D4091B
221 2.0.0 Bye
Connection closed by foreign host.

The point is that we’re not assigning domain names to the usernames. It’s just alice and bob. Postfix will see to it that each is assigned whatever domain name I have set in myorigin, the value of $mydomain. It delivers the mail to itself, seeing as it is the final destination for mails headed to $mydomain.

It’s a neat trick if you are hosting an email system where most or a lot of email is in-house. But that’s not where I am  headed so why bother with this? The point to understand is that although my setup is local, it isn’t local in the sense that Postfix automatically understands that a username without a domain name is a local user. I first need to assign a domain name to the domain-less user (using the myorigin setting), then realize that that domain is here, and then deliver the mail to a local user.


Aliases are well, aliases. Mail addressed to an alias will be delivered to the user who has that alias listed in an alias file. This can be useful for a number of scenarios. Say you want to confirm that you are the legitimate owner of a domain name, you will often be required to certify that you are in control of the postmaster@[domain name] account. If you don’t want to have a permanent user named ‘postmaster’, a quick ‘postmaster’ alias for your standard user is an effective way to achieve that. Or if you need a throwaway email address to create an account on a web site, a quickly created (and equally quickly deleted) alias will suffice.

A final benefit of aliases is that they provide a superior way of filtering and sorting email. With webmail and the like your only options for sorting and filtering are a) using multiple accounts or b) filtering by sender. With aliases I get the best of both worlds: a single account/login and the ability to supply different addresses for different purposes. So I tell facebook, twitter etc. that my address is social@mydomain.tld, alias the address to my main account and now I can filter by a single recipient rather than a long list of senders.

Let’s try the postmaster trick. There are two alias settings in main.cf: alias_maps and alias_database. It seems that the former is a complete listing of all the alias databases Postfix should check. The latter then is a subset of the former: The databases that Postfix needs to ‘rebuild’ whenever new aliases are added. This rebuilding takes the form af creating a file with the same name as the source, only with a .db suffix. What this means for me, the user, is that if I use a simple textfile to maintain my list of aliases, this file should be listed in alias_maps and again in alias_database. Whenever you use databases you tell Postfix what type it is in the format [type]:[database] where database can be a file, a MySQL table etc. depending on type. I will stick with the default, ‘hash’. The database file is listed without the ‘.db’ suffix:

# aliases
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

If you edit the /etc/aliases file you will likely find a setting for postmaster (usually to root). If you stick with this, you will not see any mail for postmaster. Postfix assumes the identity of the user to which it is delivering mail (check the ownership of the mail files in /var/mail to see this) but it will not do so for root for safety reasons. Imagine I found a way to make Postfix run a script that I sent in an email and then imagine that I wrote to the root user, saying rm -rf /. So instead I set postmaster to be an alias for my standard username:

# See man 5 aliases for format
postmaster:    alice

Now that I have added new aliases, I need to rebuild the aliases database. I do this simply by running the command newaliases and checking that the /etc/aliases.db file gets updated.

Then I use telnet to send an email to postmaster. I can use the full name with domain or I can just use the myorigin auto-completion trick.  Here’s the effect as seen in the log: An email addressed to postmaster gets delivered to alice.

Oct 18 16:23:33 ACORP postfix/local[9435]: 09849D44799: to=<alice@ACORP>, orig_to=<postmaster@ACORP>, relay=local, delay=1.4, delays=0.4/0/0/1, dsn=2.0.0, status=sent (delivered to command: procmail -a "$EXTENSION")

To check, I simply see if alice has new mail:

cat /var/mail/alice 


Forward files are a very simple way of changing where mail ends up. In all it’s simple glory it’s a text file called .forward in a system user’s home directory. Any local mail addressed to the user is forwarded to the local/virtual address in the text file. This makes for a very easy way to forward system notices to local users to say, a virtual email address that I am more likely to see in the course of the day:

[~] cat .forward

How does it differ from aliases? In effect, it doesn’t but any user can write a .forward file whereas only the system administrator can edit the aliases file. So from the perspective of a non-root user, .forward files have a certain appeal.

Of course, for forwarding out of the local machine to work I have to have a working relay, i.e. a way to pass on email, from my local machine, a topic for later posts.

Other rewrite settings

There are far more ways to rewrite addresses in Postfix than is likely to be useful for a home setup. Just for good measure I will run through a few of them:

  • Listed in the canonical_maps setting are a special sort of aliases where one sort of address is used internally, say a shortened form, and another is used externally, say the complete name spelled out with periods in between names.
  • ‘Masquerading’ refers to hiding specific hostnames from the address, so that your email address isn’t bob@mailserver5.acorp.com but just bob@acorp.com.
  • ‘Relocated’ users are another form of aliases but instead of silently redirecting the mail, it is rejected with information about the new address.
  • Finally Postfix has settings that can be used to catch mail to unknown users (instead of the default behaviour which is to reject it outright)

You may or may not be familiar with some of these tricks from a corporate or other workplace setting. I’m not going to use or detail any of these as they mostly will not be relevant to the standard selfhosted setup. But it’s good to know roughly what they mean if you see settings related to them.

So, now I have a basic system where email recipients still correspond to local users but with a few twists and options to redirect mail. It’s not much but it works. The next step is to make my SMTP server accessible from the outside. Keep in mind though, that changing the hostname from an internal one to one that makes sense on the internet (e.g. “brokkr.net”) will not change that it is a local system in the Postfix sense that all addressees (except aliases and the like) must be shell accounts.

Russian post © Jonathan Cosens Photography, Unsplash license.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.