Installing and Configuring Postfix

General Information

Postfix is an attempt to provide an alternative to the widely-used Sendmail program. Postfix attempts to be fast, easy to administer, and (hopefully) secure, while at the same time being sendmail-compatible enough to not upset your users.


Installation Is simple and easy.. So let’s get started.

# cd /usr/ports/mail/postfix
# make install clean

Now, to avoid any confusion with other applications that use postfix were going to make a quick symbolic link.

# ln -s /usr/local/etc/postfix /etc/postfix


Now lets configure this puppy. Thanks to elmore at for providing the configuration we will be using here. Let’s start off by going into your postfix directory and editing with your favorite editor.

# cd /usr/local/etc/postfix
# vi

The first thing you’re going to modify is the following line:

myhostname =

This line will set the mail server host name of your box. This cannot be any arbitrary name; it MUST be a fully qualified domain name!!

The next line to modify is:

mydomain =

Again this sets the default domain of the box, this must be a Fully Qualified Domain Name Here!

The next line to look at is the following line:

myorigin = $mydomain

Make sure this variable is set correctly! “$mydomain” is a valid global variable for the file so you should be good with that!

The next line to modify is the following:

mydestination = $myhostname, localhost.$mydomain $mydomain virtualdomain1 virtual domain2

Obviously this example assumes you’ll be setting up virtual domains. It also assumes you’ll be setting up sendmail style virtual domains. I know the file says to use the virtual file instead I don’t do that, I specify here, sendmail-style, you may not want to do that and that’s fine with me just understand in this how-to we’ll be setting up sendmail-style virtual domains.

Moving on, the next line I modify is the following:

home_mailbox = Maildir/

DO NOT uncomment this line if you do not intend to use imap. If you are using pop or traditional /var/mail spool to deliver mail this is not needed and will undoubtedly mess up your mail delivery. If you are using courier-imap this line needs to be uncommented!

Moving right along the next line I modify is the:

relay_domains = $mydestination,

This will only allow messages to be accepted where the final destination domain is on this box. It also allows delivery over the loopback interface.

Now, modify the following:

mynetworks =,

This only allows mail to be sent out to the Internet from the specified IPs! This can be an entire subnet or just one box you decide.

This brings us to the next lines to modify:

local_destination_concurrency_limit = 2
default_destination_concurrency_limit = 10

These lines limit the amount of concurrent connections to a domain. Good to have especially if you have a user that is forwarding mail out of his home via the use of a .forward file.

I actually insert the next lines into the file. They are for the canonical maps, you’ll need these if the following are true:

  1. You have virtual domains
  2. You have virtual usernames like mapped back to

If you’re using one of the above add it in. If not, don’t worry about it.

sender_canonical_maps = hash:/etc/postfix/canonical
recipient_canonical_maps = hash:/etc/postfix/canonical-receive

We’ll be going over canonical tables in more depth in a little while. For now what you need to know is that on table modifies the incoming mail and one will modify outgoing mail.

The following lines I also add, you may or may not want to add these. It depends on how true you want to be to to the rfc and how strict you want to be on other hosts trying to send mail to you. These lines will lay down the framework for cutting down on your spam!

smtpd_client_restrictions = reject_rbl_client, \
check_client_access hash:/etc/postfix/client_access, reject_unauth_pipelining

smtpd_recipient_restrictions = regexp:/etc/postfix/regexp_access, \
check_recipient_access hash:/etc/postfix/access, permit_mynetworks,reject_unknown_recipient_domain, \
reject_unknown_hostname, reject_rbl_client, reject_unauth_pipelining, reject

smtpd_sender_restrictions = regexp:/etc/postfix/sender_checks.regexp, \
check_sender_access hash:/etc/postfix/sender_access, reject_unknown_sender_domain, \
reject_non_fqdn_sender, reject_rbl_client, reject_unauth_pipelining

(That should be 3 lines, thought i would mention that so avoid future frustrations)

The first section specifies rejection if a client is not in an access list. An access list is a list I use which details the exact usernames on the box. This list is a necessity if you are running virtual domains, if you don’t use it userid1@virtualdomain1 can receive an e-mail to userid1@virtualdomain2 and so on and so forth. This is the most efficient way I know to block this! It is also a good practice to do even if you aren’t running virtual domains (opinion). It also specifies a lookup to the rbl list (a real time black hole list for open-relay mail servers). It also does not allow unauthorized pipelining, not exactly sure why that’s needed but it is. If you know, let me know!

The second section does much of the same but is it for outside connections — people trying to send mail in. It specifies a regular expression file which sorts through the headers and looks for junk, the access list, it rejects mail from computers that don’t have a fqdn it also reject is it can’t get the computer hostname through nslookup, it also rejects via the rbl list and the pipelining again.

The next section is a lot more of the same. Nothing really new to explain here.

The next line I add is my rbl line, defining what list to use. I personally use the ordb list that can be found at

maps_rbl_domains =

The next things added are the following body and header checks. They specify lookup files to run against all incoming and outgoing messages!

header_checks = regexp:/etc/postfix/header_checks
body_checks = regexp:/etc/postfix/body_checks

The final things I add are a couple of reject codes and a message size limit self-explanatory, here they are!

unknown_hostname_reject_code = 554
unknown_client_reject_code = 450
message_size_limit = 5000000

Now after the SMTP helo is sent, the client needs to tell Postfix who the e-mail is from (MAIL FROM) and where to sent to (RCPT TO). This communication is supposed to follow RFC-821. Some spam software is not strict about its conformance so we can block spam based on this fact.

strict_rfc821_envelopes = yes

With this done, we are now through with the file. Save it and let’s move on with our next section to configure the rest of postfix! A keynote here: once you finish editing files you need to cap it. Don’t forget to do this whenever you edit your postfix configuration files.

# postmap

The Access file

This file is the definitive list as that decides who to accept incoming mail from the Internet for. If you defined it earlier in the file it must be defined here. Basic syntax is one user per line followed by an OK so edit /etc/postfix/access now

userid1@domain1 OK
userid2@domain1 OK
userid3@domain2 OK

etc. etc. Now for a little postfix sorcery, don’t specify an account if you don’t want them to have the ability to receive Internet mail. For instance, if you only want the ability for someone to mail local accounts (accounts only contained on your box), leave them out of here. Also, if you are running lots of Virtual domains, you may want to specify system account for each domain, like:

webmaster@domain1 OK
webmaster@domain2 OK
postmaster@domain1 OK
postmaster@domain2 OK

Remember if the specific e-mail you want to receive mail from is not listed in this file it will bounce. Once you’ve entered in all your info save that file. From here you must make that file into a hashed db, also after any updates you make to this file in the future you must recompile that hashed db to include your new accounts. Do this by typing the following:

# postmap access

Also to avoid any delay you should always reload postfix, but don’t do that now because we haven’t turned postfix on yet! It can be done like this:

# postfix reload


The next files we’ll look at are, /usr/local/etc/postfix/canonical and /usr/local/etc/postfix/canonical-receive. Again, if you’re not using canonical tables specified in your file, you don’t need to worry about it here.


The canonical file as defined in this how-to will remap a users e-mail from the default domain to the appropriate virtual domain, if this is the case you need to specify all users except those in the default domain of the box here! Also, if you are mapping a local account to use another name like userid1 -> then you need to specify that here. Syntax is: userid@domain userid@virtualdomain, or, userid@domain this file handles mail outgoing only! Edit /etc/postfix/canonical now

userid@defaultdomain userid@virtualdomain
userid2@defaultdomain userid2@virtualdomain




This file is used for incoming mail to clean up so that the virtual addresses don’t get remapped to the default domain. All users should have an entry here including system accounts unless they are on the default domain of the box alone, and not using virtual usernames. With that let’s edit /usr/local/etc/postfix/canonical-receive now.

userid1@defaultdomain userid1@defaultdomain
userid1@virtualdomain userid1@virtualdomain
userid2@virtualdomain userid2@virtualdomain
postmast@virtualdomain userid2@virtualdomain
webmaster@defaultdomain webmaster@defaultdomain
webmastr@virtualdomain userid2@virtualdomain

Or for virtual usernames userid@domain

Got it? Good, it’s not that difficult now is it? Again, once you’re done with these files you’ll need to make a hashed db out of them using the postmap command and you’ll need to reload postfix. You remember how to do that right? Good! You’re on your way.


The next file we’ll be looking at is the /usr/local/etc/postfix client_access file. This file will specify a list of exceptions and specific denials of mail servers. For instance, your friend, God bless him, has a mail server but is pretty clueless when it comes to dns. He hasn’t configured his dns to reverse lookup properly. Well, you could bypass that here. Also, you have some evil spammer that keeps sending you mail and the rbl list isn’t blocking him, you could add a specific block here. Syntax of this file is function where x is an ip address and function is either OK or REJECT. OK REJECT

After making this file, do you know what you need to do? That’s right. You must make a hashed db out of this file as well! Ok that’s, done let’s move on!


This file /usr/local/etc/postfix/sender_access is where you can specify specific e-mail addresses or domain to block — usually bogus spam addresses. Syntax is function where the function is a reject code. 550 No Spam Accepted 550 What kind of bogus address is that?

etc. etc. This file further solidifies your box and your place as an anti-spam ninja! (-For you McDonald!) You’ll need to make this file a hashed db as well once you’re done with it!


The next file we’ll be looking at is /usr/local/etc/postfix/body_checks. This file is either a regex file or a pcre file (if you compiled postfix with pcre support). I mainly use this file to block troublesome attachments I have no use for anyways. The following blocks certain types of attachments. Self-explanatory.

/^(.*)name="(.*). (com|vbs|vbe|js|jse|exe|bat|cmd|vxd|scr|hlp|swf|mpeg|mpg|mov|mp3|avi|pif|mpe|shs|ini)"$/ REJECT

This will help out with viruses among other things. You won’t have to worry about vbs scripts and that sort of stupid thing from now on. This file just needs to be in place. There is NO need to make it a hashed db; although, after making changes DO reload postfix!


The next file we’ll take a look at is /usr/local/etc/postfix/header_checks. This file does exactly as it says — it checks mail headers. Again, either regex or pcre. I will give a couple of examples here that I use:

# This will block 8 non ascii characters in a row, which shouldn't be in the
# header anyway according to the RFC... Japan and Chinese spammers...
/[^[:print:]]{8}/ REJECT

# Pegasus uses "Comments: ..." not "Comment: ...". spammers got it wrong.
/^Comment: Authenticated sender is/ REJECT

These are just a couple of examples. My files are actually really large for this. You can spend a lot of time doing this! Try to avoid going crazy as it can be fairly obsessive! Again no hashed db needed, just reload postfix when you finish altering.


The next file to look at is /usr/local/etc/postfix/regexp_access. This file pretty much does some more of the same — kicking spammers where it hurts! Here is an example I have in mine.

/[%!@].*[%!@]/ 550 Sender specified routing is not supported here.

There, you see, not too bad huh. Ok, again reload postfix when your done and let’s move on.


Lets edit /etc/aliases

The aliases file is very limited with the configuration we have specified here. It does need some things filled in. Standard system aliases should be placed here: aliases for root, postmaster, abuse, etc. etc. Also if you are running majordomo you’ll specify your outgoing secrets here. If you’re forwarding mail to another domain and not using a .forward file in your home, specify that here as well. Other than that you should be good to go. After editing the aliases file you should run the command newaliases to tell the system there’s new content in that file.

# newaliases

Starting Postfix

Ok now our configuration is complete, let’s start up postfix! Run the following:

# postfix start

It should start-up error free! Now, be sure to send a couple of emails to yourself through yahoo or something and watch your maillog to ensure everything goes smoothly.

References And Source Of Article: ScreamingElectron

Speak Your Mind