Sie sind auf Seite 1von 485

Postfix Basic Configuration

Introduction
Postfix has several hundred configuration parameters that are controlled via the main.cf file. Fortunately, all parameters have sensible default values. In many cases, you need to configure only two or three parameters before you can start to play with the mail system. Here's a quick introduction to the syntax: Postfix configuration files The text below assumes that you already have Postfix installed on the system, either by compiling the source code yourself (as described in the INSTALL file) or by installing an already compiled version. This document covers basic Postfix configuration. Information about how to configure Postfix for specific applications such as mailhub, firewall or dial-up client can be found in the STANDARD_CONFIGURATION_README file. But don't go there until you already have covered the material presented below. The first parameters of interest specify the machine's identity and role in the network. What domain name to use in outbound mail What domains to receive mail for What clients to relay mail from What destinations to relay mail to What delivery method: direct or indirect The default values for many other configuration parameters are derived from just these. The next parameter of interest controls the amount of mail sent to the local postmaster: What trouble to report to the postmaster Be sure to set the following correctly if you're behind a proxy or network address translator, and you are running a backup MX host for some other domain: Proxy/NAT external network addresses Postfix daemon processes run in the background, and log problems and normal activity to the syslog daemon. Here are a few things that you need to be aware of: What you need to know about Postfix logging If your machine has unusual security requirements you may want to run Postfix daemon processes inside a chroot environment. Running Postfix daemon processes chrooted If you run Postfix on a virtual network interface, or if your machine runs other mailers on virtual interfaces, you'll have to look at the other parameters listed here as well:

My own hostname My own domain name My own network addresses

Postfix configuration files


By default, Postfix configuration files are in /etc/postfix. The two most important files are main.cf and master.cf; these files must be owned by root. Giving someone else write permission to main.cf or master.cf (or to their parent directories) means giving root privileges to that person. In /etc/postfix/main.cf you will have to set up a minimal number of configuration parameters. Postfix configuration parameters resemble shell variables, with two important differences: the first one is that Postfix does not know about quotes like the UNIX shell does. You specify a configuration parameter as:
/etc/postfix/main.cf: parameter = value

and you use it by putting a "$" character in front of its name:


/etc/postfix/main.cf: other_parameter = $parameter

You can use $parameter before it is given a value (that is the second main difference with UNIX shell variables). The Postfix configuration language uses lazy evaluation, and does not look at a parameter value until it is needed at runtime. Postfix uses database files for access control, address rewriting and other purposes. The DATABASE_README file gives an introduction to how Postfix works with Berkeley DB, LDAP or SQL and other types. Here is a common example of how Postfix invokes a database:
/etc/postfix/main.cf: virtual_alias_maps = hash:/etc/postfix/virtual

Whenever you make a change to the main.cf or master.cf file, execute the following command as root in order to refresh a running mail system:
# postfix reload

What domain name to use in outbound mail


The myorigin parameter specifies the domain that appears in mail that is posted on this machine. The default is to use the local machine name, $myhostname, which defaults to the name of the machine. Unless you are running a really small site, you probably want to change that into $mydomain, which defaults to the parent domain of the machine name. For the sake of consistency between sender and recipient addresses, myorigin also specifies the domain name that is appended to an unqualified recipient address. Examples (specify only one of the following):
/etc/postfix/main.cf: myorigin = $myhostname (default: send mail as "user@$myhostname") myorigin = $mydomain (probably desirable: "user@$mydomain")

What domains to receive mail for


The mydestination parameter specifies what domains this machine will deliver locally, instead of forwarding to another machine. The default is to receive mail for the machine itself. See the VIRTUAL_README file for how to configure Postfix for hosted domains. You can specify zero or more domain names, "/file/name" patterns and/or "type:table" lookup tables (such as hash:, btree:, nis:, ldap:, or mysql:), separated by whitespace and/or commas. A "/file/name" pattern is replaced by its contents; "type:table" requests that a table lookup is done and merely tests for existence: the lookup result is ignored. IMPORTANT: If your machine is a mail server for its entire domain, you must list $mydomain as well. Example 1: default setting.
/etc/postfix/main.cf: mydestination = $myhostname localhost.$mydomain localhost

Example 2: domain-wide mail server.


/etc/postfix/main.cf: mydestination = $myhostname localhost.$mydomain localhost $mydomain

Example 3: host with multiple DNS A records.


/etc/postfix/main.cf: mydestination = $myhostname localhost.$mydomain localhost www.$mydomain ftp.$mydomain

Caution: in order to avoid mail delivery loops, you must list all hostnames of the machine, including $myhostname, and localhost.$mydomain.

What clients to relay mail from


By default, Postfix will forward mail from clients in authorized network blocks to any destination. Authorized networks are defined with the mynetworks configuration parameter. The default is to authorize all clients in the IP subnetworks that the local machine is attached to. IMPORTANT: If your machine is connected to a wide area network then your default mynetworks setting may be too friendly. Examples (specify only one of the following):
/etc/postfix/main.cf: mynetworks_style = subnet (default: authorize subnetworks) mynetworks_style = host (safe: authorize local machine only) mynetworks = 127.0.0.0/8 (safe: authorize local machine only) mynetworks = 127.0.0.0/8 168.100.189.2/32 (authorize local machine)

You can specify the trusted networks in the main.cf file, or you can let Postfix do the work for you. The default is to let Postfix do the work. The result depends on the mynetworks_style parameter value. Specify "mynetworks_style = host" when Postfix should forward mail from only the local machine. Specify "mynetworks_style = subnet" (the default) when Postfix should forward mail from

SMTP clients in the same IP subnetworks as the local machine. On Linux, this works correctly only with interfaces specified with the "ifconfig" command. Specify "mynetworks_style = class" when Postfix should forward mail from SMTP clients in the same IP class A/B/C networks as the local machine. Don't do this with a dialup site - it would cause Postfix to "trust" your entire provider's network. Instead, specify an explicit mynetworks list by hand, as described below. Alternatively, you can specify the mynetworks list by hand, in which case Postfix ignores the mynetworks_style setting. To specify the list of trusted networks by hand, specify network blocks in CIDR (network/mask) notation, for example:
/etc/postfix/main.cf: mynetworks = 168.100.189.0/28, 127.0.0.0/8

You can also specify the absolute pathname of a pattern file instead of listing the patterns in the main.cf file.

What destinations to relay mail to


By default, Postfix will forward mail from strangers (clients outside authorized networks) to authorized remote destinations only. Authorized remote destinations are defined with the relay_domains configuration parameter. The default is to authorize all domains (and subdomains) of the domains listed with the mydestination parameter. Examples (specify only one of the following):
/etc/postfix/main.cf: relay_domains = $mydestination (default) relay_domains = (safe: never forward mail from strangers) relay_domains = $mydomain (forward mail to my domain and subdomains)

What delivery method: direct or indirect


By default, Postfix tries to deliver mail directly to the Internet. Depending on your local conditions this may not be possible or desirable. For example, your system may be turned off outside office hours, it may be behind a firewall, or it may be connected via a provider who does not allow direct mail to the Internet. In those cases you need to configure Postfix to deliver mail indirectly via a relay host. Examples (specify only one of the following):
/etc/postfix/main.cf: relayhost = Internet) relayhost = $mydomain relayhost = [mail.$mydomain] relayhost = [mail.isp.tld] (default: direct delivery to (deliver via local mailhub) (deliver via local mailhub) (deliver via provider mailhub)

The form enclosed with [] eliminates DNS MX lookups. Don't worry if you don't know what that means. Just be sure to specify the [] around the mailhub hostname that your ISP gave to you, otherwise mail may be mis-delivered. The STANDARD_CONFIGURATION_README file has more hints and tips for firewalled and/or dial-up networks.

What trouble to report to the postmaster


You should set up a postmaster alias in the aliases(5) table that directs mail to a human person. The postmaster address is required to exist, so that people can report mail delivery problems. While you're updating the aliases(5) table, be sure to direct mail for the super-user to a human person too.
/etc/aliases: postmaster: you root: you

Execute the command "newaliases" after changing the aliases file. Instead of /etc/aliases, your alias file may be located elsewhere. Use the command "postconf alias_maps" to find out. The Postfix system reports problems to the postmaster alias. You may not be interested in all types of trouble reports, so this reporting mechanism is configurable. The default is to report only serious problems (resource, software) to postmaster: Default setting:
/etc/postfix/main.cf: notify_classes = resource, software

The meaning of the classes is as follows: bounce Inform the postmaster of undeliverable mail. Either send the postmaster a copy of undeliverable mail that is returned to the sender, or send a transcript of the SMTP session when Postfix rejected mail. For privacy reasons, the postmaster copy of undeliverable mail is truncated after the original message headers. This implies "2bounce" (see below). See also the luser_relay feature. The notification is sent to the address specified with the bounce_notice_recipient configuration parameter (default: postmaster). 2bounce When Postfix is unable to return undeliverable mail to the sender, send it to the postmaster instead (without truncating the message after the primary headers). The notification is sent to the address specified with the 2bounce_notice_recipient configuration parameter (default: postmaster). delay Inform the postmaster of delayed mail. In this case, the postmaster receives message headers only. The notification is sent to the address specified with the delay_notice_recipient configuration parameter (default: postmaster). policy Inform the postmaster of client requests that were rejected because of (UCE) policy restrictions. The postmaster receives a transcript of the SMTP session. The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). protocol

Inform the postmaster of protocol errors (client or server side) or attempts by a client to execute unimplemented commands. The postmaster receives a transcript of the SMTP session. The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). resource Inform the postmaster of mail not delivered due to resource problems (for example, queue file write errors). The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). software Inform the postmaster of mail not delivered due to software problems. The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster).

Proxy/NAT external network addresses


Some mail servers are connected to the Internet via a network address translator (NAT) or proxy. This means that systems on the Internet connect to the address of the NAT or proxy, instead of connecting to the network address of the mail server. The NAT or proxy forwards the connection to the network address of the mail server, but Postfix does not know this. If you run a Postfix server behind a proxy or NAT, you need to configure the proxy_interfaces parameter and specify all the external proxy or NAT addresses that Postfix receives mail on. You may specify symbolic hostnames instead of network addresses. IMPORTANT: You must specify your proxy/NAT external addresses when your system is a backup MX host for other domains, otherwise mail delivery loops will happen when the primary MX host is down. Example: host behind NAT box running a backup MX host.
/etc/postfix/main.cf: proxy_interfaces = 1.2.3.4 (the proxy/NAT external network address)

What you need to know about Postfix logging


Postfix daemon processes run in the background, and log problems and normal activity to the syslog daemon. The syslogd process sorts events by class and severity, and appends them to logfiles. The logging classes, levels and logfile names are usually specified in /etc/syslog.conf. At the very least you need something like:
/etc/syslog.conf: mail.err mail.debug /dev/console /var/log/maillog

After changing the syslog.conf file, send a "HUP" signal to the syslogd process. IMPORTANT: many syslogd implementations will not create files. You must create files before (re)starting syslogd. IMPORTANT: on Linux you need to put a "-" character before the pathname, e.g., -/var/log/maillog,

otherwise the syslogd process will use more system resources than Postfix. Hopefully, the number of problems will be small, but it is a good idea to run every night before the syslog files are rotated:
# postfix check # egrep '(reject|warning|error|fatal|panic):' /some/log/file

The first line (postfix check) causes Postfix to report file permission/ownership discrepancies. The second line looks for problem reports from the mail software, and reports how effective the relay and junk mail access blocks are. This may produce a lot of output. You will want to apply some postprocessing to eliminate uninteresting information. The DEBUG_README document describes the meaning of the "warning" etc. labels in Postfix logging.

Running Postfix daemon processes chrooted


Postfix daemon processes can be configured (via the master.cf file) to run in a chroot jail. The processes run at a fixed low privilege and with file system access limited to the Postfix queue directories (/var/spool/postfix). This provides a significant barrier against intrusion. The barrier is not impenetrable (chroot limits file system access only), but every little bit helps. With the exception of Postfix daemons that deliver mail locally and/or that execute non-Postfix commands, every Postfix daemon can run chrooted. Sites with high security requirements should consider to chroot all daemons that talk to the network: the smtp(8) and smtpd(8) processes, and perhaps also the lmtp(8) client. The author's own porcupine.org mail server runs all daemons chrooted that can be chrooted. The default /etc/postfix/master.cf file specifies that no Postfix daemon runs chrooted. In order to enable chroot operation, edit the file /etc/postfix/master.cf, and follow instructions in the file. When you're finished, execute "postfix reload" to make the change effective. Note that a chrooted daemon resolves all filenames relative to the Postfix queue directory (/var/spool/postfix). For successful use of a chroot jail, most UNIX systems require you to bring in some files or device nodes. The examples/chroot-setup directory in the source code distribution has a collection of scripts that help you set up Postfix chroot environments on different operating systems. Additionally, you almost certainly need to configure syslogd so that it listens on a socket inside the Postfix queue directory. Examples of syslogd command line options that achieve this for specific systems: FreeBSD: syslogd -l /var/spool/postfix/var/run/log Linux, OpenBSD: syslogd -a /var/spool/postfix/dev/log

My own hostname
The myhostname parameter specifies the fully-qualified domain name of the machine running the Postfix system. $myhostname appears as the default value in many other Postfix configuration parameters. By default, myhostname is set to the local machine name. If your local machine name is not in fully-qualified domain name form, or if you run Postfix on a virtual interface, you will have to specify the fully-qualified domain name that the mail system should use.

Alternatively, if you specify mydomain in main.cf, then Postfix will use its value to generate a fully-qualified default value for the myhostname parameter. Examples (specify only one of the following):
/etc/postfix/main.cf: myhostname = host.local.domain (machine name is not FQDN) myhostname = host.virtual.domain (virtual interface) myhostname = virtual.domain (virtual interface)

My own domain name


The mydomain parameter specifies the parent domain of $myhostname. By default, it is derived from $myhostname by stripping off the first part (unless the result would be a top-level domain). Conversely, if you specify mydomain in main.cf, then Postfix will use its value to generate a fullyqualified default value for the myhostname parameter. Examples (specify only one of the following):
/etc/postfix/main.cf: mydomain = local.domain mydomain = virtual.domain (virtual interface)

My own network addresses


The inet_interfaces parameter specifies all network interface addresses that the Postfix system should listen on; mail addressed to "user@[network address]" will be delivered locally, as if it is addressed to a domain listed in $mydestination. You can override the inet_interfaces setting in the Postfix master.cf file by prepending an IP address to a server name. The default is to listen on all active interfaces. If you run mailers on virtual interfaces, you will have to specify what interfaces to listen on. IMPORTANT: If you run MTAs on virtual interfaces you must specify explicit inet_interfaces values for the MTA that receives mail for the machine itself: this MTA should never listen on the virtual interfaces or you would have a mailer loop when a virtual MTA is down. Example: default setting.
/etc/postfix/main.cf: inet_interfaces = all

Example: host running one or more virtual mailers. For each Postfix instance, specify only one of the following.
/etc/postfix/main.cf: inet_interfaces = virtual.host.tld (virtual Postfix) inet_interfaces = $myhostname localhost... (non-virtual Postfix)

Note: you need to stop and start Postfix after changing this parameter.

Postfix Small/Home Office Hints and Tips


Overview
This document combines hints and tips for "small office/home office" applications into one document so that they are easier to find. The text describes the mail sending side only. If your machine does not receive mail directly (i.e. it does not have its own Internet domain name and its own fixed IP address), then you will need a solution such as "fetchmail", which is outside the scope of the Postfix documentation. Selected topics from the STANDARD_CONFIGURATION_README document: Postfix on a stand-alone Internet host Postfix on hosts without a real Internet hostname Selected topics from the SASL_README document: Enabling SASL authentication in the Postfix SMTP client Configuring Sender-Dependent SASL authentication See the SASL_README and STANDARD_CONFIGURATION_README documents for further information on these topics.

Postfix on a stand-alone Internet host


Postfix should work out of the box without change on a stand-alone machine that has direct Internet access. At least, that is how Postfix installs when you download the Postfix source code via http://www.postfix.org/. You can use the command "postconf -n" to find out what settings are overruled by your main.cf. Besides a few pathname settings, few parameters should be set on a stand-alone box, beyond what is covered in the BASIC_CONFIGURATION_README document:
/etc/postfix/main.cf: # Optional: send mail as user@domainname instead of user@hostname. #myorigin = $mydomain # Optional: specify NAT/proxy external address. #proxy_interfaces = 1.2.3.4 # Alternative 1: don't relay mail from other hosts. mynetworks_style = host relay_domains = # Alternative 2: relay mail from local clients only. # mynetworks = 192.168.1.0/28 # relay_domains =

See also the section "Postfix on hosts without a real Internet hostname" if this is applicable to your

configuration.

Postfix on hosts without a real Internet hostname


This section is for hosts that don't have their own Internet hostname. Typically these are systems that get a dynamic IP address via DHCP or via dialup. Postfix will let you send and receive mail just fine between accounts on a machine with a fantasy name. However, you cannot use a fantasy hostname in your email address when sending mail into the Internet, because no-one would be able to reply to your mail. In fact, more and more sites refuse mail addresses with non-existent domain names. Note: the following information is Postfix version dependent. To find out what Postfix version you have, execute the command "postconf mail_version".

Solution 1: Postfix version 2.2 and later


Postfix 2.2 uses the generic(5) address mapping to replace local fantasy email addresses by valid Internet addresses. This mapping happens ONLY when mail leaves the machine; not when you send mail between users on the same machine. The following example presents additional configuration. You need to combine this with basic configuration information as discussed the first half of this document.
1 /etc/postfix/main.cf: 2 smtp_generic_maps = hash:/etc/postfix/generic 3 4 /etc/postfix/generic: 5 his@localdomain.local hisaccount@hisisp.example 6 her@localdomain.local heraccount@herisp.example 7 @localdomain.local hisaccount+local@hisisp.example

When mail is sent to a remote host via SMTP: Line 5 replaces his@localdomain.local by his ISP mail address, Line 6 replaces her@localdomain.local by her ISP mail address, and Line 7 replaces other local addresses by his ISP account, with an address extension of +local (this example assumes that the ISP supports "+" style address extensions). Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what lookup tables Postfix supports, use the command "postconf -m". Execute the command "postmap /etc/postfix/generic" whenever you change the generic table.

Solution 2: Postfix version 2.1 and earlier


The solution with older Postfix systems is to use valid Internet addresses where possible, and to let Postfix map valid Internet addresses to local fantasy addresses. With this, you can send mail to the Internet and to local fantasy addresses, including mail to local fantasy addresses that don't have a valid Internet address of their own. The following example presents additional configuration. You need to combine this with basic configuration information as discussed the first half of this document.
1 /etc/postfix/main.cf: 2 myhostname = hostname.localdomain 3 mydomain = localdomain

4 5 canonical_maps = hash:/etc/postfix/canonical 6 7 virtual_alias_maps = hash:/etc/postfix/virtual 8 9 /etc/postfix/canonical: 10 your-login-name your-account@your-isp.com 11 12 /etc/postfix/virtual: 13 your-account@your-isp.com your-login-name

Translation: Lines 2-3: Substitute your fantasy hostname here. Do not use a domain name that is already in use by real organizations on the Internet. See RFC 2606 for examples of domain names that are guaranteed not to be owned by anyone. Lines 5, 9, 10: This provides the mapping from "your-login-name@hostname.localdomain" to "your-account@your-isp.com". This part is required. Lines 7, 12, 13: Deliver mail for "your-account@your-isp.com" locally, instead of sending it to the ISP. This part is not required but is convenient. Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what lookup tables Postfix supports, use the command "postconf -m". Execute the command "postmap /etc/postfix/canonical" whenever you change the canonical table. Execute the command "postmap /etc/postfix/virtual" whenever you change the virtual table.

Enabling SASL authentication in the Postfix SMTP/LMTP client


This section shows a typical scenario where the Postfix SMTP client sends all messages via a mail gateway server that requires SASL authentication. Trouble solving tips: If your SASL logins fail with "SASL authentication failure: No worthy mechs found" in the mail logfile, then see the section "Postfix SMTP/LMTP client policy - SASL mechanism properties". For a solution to a more obscure class of SASL authentication failures, see "Postfix SMTP/LMTP client policy - SASL mechanism names". To make the example more readable we introduce it in two parts. The first part takes care of the basic configuration, while the second part sets up the username/password information.
/etc/postfix/main.cf: smtp_sasl_auth_enable = yes relayhost = [mail.isp.example] # Alternative form: # relayhost = [mail.isp.example]:submission smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd

The smtp_sasl_auth_enable setting enables client-side authentication. We will configure the client's username and password information in the second part of the example.

The relayhost setting forces the Postfix SMTP to send all remote messages to the specified mail server instead of trying to deliver them directly to their destination. In the relayhost setting, the "[" and "]" prevent the Postfix SMTP client from looking up MX (mail exchanger) records for the enclosed name. The relayhost destination may also specify a non-default TCP port. For example, the alternative form [mail.isp.example]:submission tells Postfix to connect to TCP network port 587, which is reserved for email client applications. The Postfix SMTP client is compatible with SMTP servers that use the non-standard "AUTH=method...." syntax in response to the EHLO command; this requires no additional Postfix client configuration. The Postfix SMTP client does not support the obsolete "wrappermode" protocol, which uses TCP port 465 on the SMTP server. See TLS_README for a solution that uses the stunnel command. With the smtp_sasl_password_maps parameter, we configure the Postfix SMTP client to send username and password information to the mail gateway server. As discussed in the next section, the Postfix SMTP client supports multiple ISP accounts. For this reason the username and password are stored in a table that contains one username/password combination for each mail gateway server.
/etc/postfix/sasl_passwd: # destination credentials [mail.isp.example] username:password # Alternative form: # [mail.isp.example]:submission username:password

Important Keep the SASL client password file in /etc/postfix, and make the file read+write only for root to protect the username/password combinations against other users. The Postfix SMTP client will still be able to read the SASL client passwords. It opens the file as user root before it drops privileges, and before entering an optional chroot jail. Use the postmap command whenever you change the /etc/postfix/sasl_passwd file. If you specify the "[" and "]" in the relayhost destination, then you must use the same form in the smtp_sasl_password_maps file. If you specify a non-default TCP Port (such as ":submission" or ":587") in the relayhost destination, then you must use the same form in the smtp_sasl_password_maps file.

Configuring Sender-Dependent SASL authentication


Postfix supports different ISP accounts for different sender addresses (version 2.3 and later). This can be useful when one person uses the same machine for work and for personal use, or when people with different ISP accounts share the same Postfix server. To make this possible, Postfix supports per-sender SASL passwords and per-sender relay hosts. In the example below, the Postfix SMTP client will search the SASL password file by sender address before it searches that same file by destination. Likewise, the Postfix trivial-rewrite(8) daemon will search the per-sender relayhost file, and use the default relayhost setting only as a final resort.

/etc/postfix/main.cf: smtp_sender_dependent_authentication = yes sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd relayhost = [mail.isp.example] # Alternative form: # relayhost = [mail.isp.example]:submission /etc/postfix/sasl_passwd: # Per-sender authentication; see also /etc/postfix/sender_relay. user1@example.com username2:password2 user2@example.net username2:password2 # Login information for the default relayhost. [mail.isp.example] username:password # Alternative form: # [mail.isp.example]:submission username:password /etc/postfix/sender_relay: # Per-sender provider; see also /etc/postfix/sasl_passwd. user1@example.com [mail.example.com]:submission user2@example.net [mail.example.net]

If you are creative, then you can try to combine the two tables into one single MySQL database, and configure different Postfix queries to extract the appropriate information. Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what lookup tables Postfix supports, use the command "postconf -m". Execute the command "postmap /etc/postfix/sasl_passwd" whenever you change the sasl_passwd table. Execute the command "postmap /etc/postfix/sender_relay" whenever you change the sender_relay table.

Postfix Standard Configuration Examples


Purpose of this document
This document presents a number of typical Postfix configurations. This document should be reviewed after you have followed the basic configuration steps as described in the BASIC_CONFIGURATION_README document. In particular, do not proceed here if you don't already have Postfix working for local mail submission and for local mail delivery. The first part of this document presents standard configurations that each solve one specific problem. Postfix on a stand-alone Internet host Postfix on a null client Postfix on a local network Postfix email firewall/gateway

The second part of this document presents additional configurations for hosts in specific environments. Delivering some but not all accounts locally Running Postfix behind a firewall Configuring Postfix as primary or backup MX host for a remote site Postfix on a dialup machine Postfix on hosts without a real Internet hostname

Postfix on a stand-alone Internet host


Postfix should work out of the box without change on a stand-alone machine that has direct Internet access. At least, that is how Postfix installs when you download the Postfix source code via http://www.postfix.org/. You can use the command "postconf -n" to find out what settings are overruled by your main.cf. Besides a few pathname settings, few parameters should be set on a stand-alone box, beyond what is covered in the BASIC_CONFIGURATION_README document:
/etc/postfix/main.cf: # Optional: send mail as user@domainname instead of user@hostname. #myorigin = $mydomain # Optional: specify NAT/proxy external address. #proxy_interfaces = 1.2.3.4 # Alternative 1: don't relay mail from other hosts. mynetworks_style = host relay_domains = # Alternative 2: relay mail from local clients only.

# mynetworks = 192.168.1.0/28 # relay_domains =

See also the section "Postfix on hosts without a real Internet hostname" if this is applicable to your configuration.

Postfix on a null client


A null client is a machine that can only send mail. It receives no mail from the network, and it does not deliver any mail locally. A null client typically uses POP, IMAP or NFS for mailbox access. In this example we assume that the Internet domain name is "example.com" and that the machine is named "nullclient.example.com". As usual, the examples show only parameters that are not left at their default settings.
1 /etc/postfix/main.cf: 2 myorigin = $mydomain 3 relayhost = $mydomain 4 inet_interfaces = loopback-only 5 local_transport = error:local delivery is disabled 6 7 /etc/postfix/master.cf: 8 Comment out the local delivery agent entry

Translation: Line 2: Send mail as "user@example.com" (instead of "user@nullclient.example.com"), so that nothing ever has a reason to send mail to "user@nullclient.example.com". Line 3: Forward all mail to the mail server that is responsible for the "example.com" domain. This prevents mail from getting stuck on the null client if it is turned off while some remote destination is unreachable. Line 4: Do not accept mail from the network. Lines 5-8: Disable local mail delivery. All mail goes to the mail server as specified in line 3.

Postfix on a local network


This section describes a local area network environment of one main server and multiple other systems that send and receive email. As usual we assume that the Internet domain name is "example.com". All systems are configured to send mail as "user@example.com", and all systems receive mail for "user@hostname.example.com". The main server also receives mail for "user@example.com". We call this machine by the name of mailhost.example.com. A drawback of sending mail as "user@example.com" is that mail for "root" and other system accounts is also sent to the central mailhost. See the section "Delivering some but not all accounts locally" below for possible solutions. As usual, the examples show only parameters that are not left at their default settings. First we present the non-mailhost configuration, because it is the simpler one. This machine sends mail as "user@example.com" and is final destination for "user@hostname.example.com".
1 /etc/postfix/main.cf: 2 myorigin = $mydomain 3 mynetworks = 127.0.0.0/8 10.0.0.0/24 4 relay_domains = 5 # Optional: forward all non-local mail to mailhost 6 #relayhost = $mydomain

Translation: Line 2: Send mail as "user@example.com". Line 3: Specify the trusted networks. Line 4: This host does not relay mail from untrusted networks. Line 6: This is needed if no direct Internet access is available. See also below, "Postfix behind a firewall". Next we present the mailhost configuration. This machine sends mail as "user@example.com" and is final destination for "user@hostname.example.com" as well as "user@example.com".
1 DNS: 2 example.com IN MX 10 mailhost.example.com. 3 4 /etc/postfix/main.cf: 5 myorigin = $mydomain 6 mydestination = $myhostname localhost.$mydomain localhost $mydomain 7 mynetworks = 127.0.0.0/8 10.0.0.0/24 8 relay_domains = 9 # Optional: forward all non-local mail to firewall 10 #relayhost = [firewall.example.com]

Translation: Line 2: Send mail for the domain "example.com" to the machine mailhost.example.com. Remember to specify the "." at the end of the line. Line 5: Send mail as "user@example.com". Line 6: This host is the final mail destination for the "example.com" domain, in addition to the names of the machine itself. Line 7: Specify the trusted networks. Line 8: This host does not relay mail from untrusted networks. Line 10: This is needed only when the mailhost has to forward non-local mail via a mail server on a firewall. The [] forces Postfix to do no MX record lookups. In an environment like this, users access their mailbox in one or more of the following ways: Mailbox access via NFS or equivalent. Mailbox access via POP or IMAP. Mailbox on the user's preferred machine. In the latter case, each user has an alias on the mailhost that forwards mail to her preferred machine:
/etc/aliases: joe: joe@joes.preferred.machine jane: jane@janes.preferred.machine

On some systems the alias database is not in /etc/aliases. To find out the location for your system, execute the command "postconf alias_maps". Execute the command "newaliases" whenever you change the aliases file.

Postfix email firewall/gateway


The idea is to set up a Postfix email firewall/gateway that forwards mail for "example.com" to an inside gateway machine but rejects mail for "anything.example.com". There is only one problem: with "relay_domains = example.com", the firewall normally also accepts mail for "anything.example.com". That would not be right. Note: this example requires Postfix version 2.0 and later. To find out what Postfix version you have, execute the command "postconf mail_version". The solution is presented in multiple parts. This first part gets rid of local mail delivery on the firewall, making the firewall harder to break.
1 /etc/postfix/main.cf: 2 myorigin = example.com 3 mydestination = 4 local_recipient_maps = 5 local_transport = error:local mail delivery is disabled 6 7 /etc/postfix/master.cf: 8 Comment out the local delivery agent

Translation: Line 2: Send mail from this machine as "user@example.com", so that no reason exists to send mail to "user@firewall.example.com". Lines 3-8: Disable local mail delivery on the firewall machine. For the sake of technical correctness the firewall must be able to receive mail for postmaster@[firewall ip address]. Reportedly, some things actually expect this ability to exist. The second part of the solution therefore adds support for postmaster@[firewall ip address], and as a bonus we do abuse@[firewall ip address] as well. All the mail to these two accounts is forwarded to an inside address.
1 /etc/postfix/main.cf: 2 virtual_alias_maps = hash:/etc/postfix/virtual 3 4 /etc/postfix/virtual: 5 postmaster postmaster@example.com 6 abuse abuse@example.com

Translation: Because mydestination is empty (see the previous example), only address literals matching $inet_interfaces or $proxy_interfaces are deemed local. So "localpart@[a.d.d.r]" can be matched as simply "localpart" in canonical(5) and virtual(5). This avoids the need to specify firewall IP addresses into Postfix configuration files. The last part of the solution does the email forwarding, which is the real purpose of the firewall email function.
1 /etc/postfix/main.cf: 2 mynetworks = 127.0.0.0/8 12.34.56.0/24 3 relay_domains = example.com 4 parent_domain_matches_subdomains = 5 debug_peer_list smtpd_access_maps 6 smtpd_recipient_restrictions = 7 permit_mynetworks reject_unauth_destination 8 9 relay_recipient_maps = hash:/etc/postfix/relay_recipients

10 transport_maps = hash:/etc/postfix/transport 11 12 /etc/postfix/relay_recipients: 13 user1@example.com x 14 user2@example.com x 15 . . . 16 17 /etc/postfix/transport: 18 example.com smtp:[inside-gateway.example.com]

Translation: Lines 1-7: Accept mail from local systems in $mynetworks, and accept mail from outside for "user@example.com" but not for "user@anything.example.com". The magic is in lines 4-5. Lines 9, 12-14: Define the list of valid addresses in the "example.com" domain that can receive mail from the Internet. This prevents the mail queue from filling up with undeliverable MAILER-DAEMON messages. If you can't maintain a list of valid recipients then you must specify "relay_recipient_maps =" (that is, an empty value), or you must specify an "@example.com x" wild-card in the relay_recipients table. Lines 10, 17-18: Route mail for "example.com" to the inside gateway machine. The [] forces Postfix to do no MX lookup. Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what lookup tables Postfix supports, use the command "postconf -m". Execute the command "postmap /etc/postfix/relay_recipients" whenever you change the relay_recipients table. Execute the command "postmap /etc/postfix/transport" whenever you change the transport table. In some installations, there may be separate instances of Postfix processing inbound and outbound mail on a multi-homed firewall. The inbound Postfix instance has an SMTP server listening on the external firewall interface, and the outbound Postfix instance has an SMTP server listening on the internal interface. In such a configuration is it is tempting to configure $inet_interfaces in each instance with just the corresponding interface address. In most cases, using inet_interfaces in this way will not work, because as documented in the $inet_interfaces reference manual, the smtp(8) delivery agent will also use the specified interface address as the source address for outbound connections and will be unable to reach hosts on "the other side" of the firewall. The symptoms are that the firewall is unable to connect to hosts that are in fact up. See the inet_interfaces parameter documentation for suggested work-arounds.

Delivering some but not all accounts locally


A drawback of sending mail as "user@example.com" (instead of "user@hostname.example.com") is that mail for "root" and other system accounts is also sent to the central mailhost. In order to deliver such accounts locally, you can set up virtual aliases as follows:
1 /etc/postfix/main.cf: 2 virtual_alias_maps = hash:/etc/postfix/virtual 3 4 /etc/postfix/virtual: 5 root root@localhost 6 . . .

Translation: Line 5: As described in the virtual(5) manual page, the bare name "root" matches

"root@site" when "site" is equal to $myorigin, when "site" is listed in $mydestination, or when it matches $inet_interfaces or $proxy_interfaces. Execute the command "postmap /etc/postfix/virtual" after editing the file.

Running Postfix behind a firewall


The simplest way to set up Postfix on a host behind a firewalled network is to send all mail to a gateway host, and to let that mail host take care of internal and external forwarding. Examples of that are shown in the local area network section above. A more sophisticated approach is to send only external mail to the gateway host, and to send intranet mail directly. Note: this example requires Postfix version 2.0 and later. To find out what Postfix version you have, execute the command "postconf mail_version". The following example presents additional configuration. You need to combine this with basic configuration information as discussed the first half of this document.
1 /etc/postfix/main.cf: 2 transport_maps = hash:/etc/postfix/transport 3 relayhost = 4 # Optional for a machine that isn't "always on" 5 #fallback_relay = [gateway.example.com] 6 7 /etc/postfix/transport: 8 # Internal delivery. 9 example.com : 10 .example.com : 11 # External delivery. 12 * smtp:[gateway.example.com]

Translation: Lines 2, 7-12: Request that intranet mail is delivered directly, and that external mail is given to a gateway. Obviously, this example assumes that the organization uses DNS MX records internally. The [] forces Postfix to do no MX lookup. Line 3: IMPORTANT: do not specify a relayhost in main.cf. Line 5: This prevents mail from being stuck in the queue when the machine is turned off. Postfix tries to deliver mail directly, and gives undeliverable mail to a gateway. Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what lookup tables Postfix supports, use the command "postconf -m". Execute the command "postmap /etc/postfix/transport" whenever you edit the transport table.

Configuring Postfix as primary or backup MX host for a remote site


This section presents additional configuration. You need to combine this with basic configuration information as discussed the first half of this document. When your system is SECONDARY MX host for a remote site this is all you need:
1 DNS: 2 the.backed-up.domain.tld your.machine.tld. 3 4 /etc/postfix/main.cf: IN MX 100

5 relay_domains = . . . the.backed-up.domain.tld 6 smtpd_recipient_restrictions = 7 permit_mynetworks reject_unauth_destination 8 9 # You must specify your NAT/proxy external address. 10 #proxy_interfaces = 1.2.3.4 11 12 relay_recipient_maps = hash:/etc/postfix/relay_recipients 13 14 /etc/postfix/relay_recipients: 15 user1@the.backed-up.domain.tld x 16 user2@the.backed-up.domain.tld x 17 . . .

When your system is PRIMARY MX host for a remote site you need the above, plus:
18 /etc/postfix/main.cf: 19 transport_maps = hash:/etc/postfix/transport 20 21 /etc/postfix/transport: 22 the.backed-up.domain.tld relay:[their.mail.host.tld]

Important notes: Do not list the.backed-up.domain.tld in mydestination. Do not list the.backed-up.domain.tld in virtual_alias_domains. Do not list the.backed-up.domain.tld in virtual_mailbox_domains. Lines 1-7: Forward mail from the Internet for "the.backed-up.domain.tld" to the primary MX host for that domain. Line 10: This is a must if Postfix receives mail via a NAT relay or proxy that presents a different IP address to the world than the local machine. Lines 12-16: Define the list of valid addresses in the "the.backed-up.domain.tld" domain. This prevents your mail queue from filling up with undeliverable MAILER-DAEMON messages. If you can't maintain a list of valid recipients then you must specify "relay_recipient_maps =" (that is, an empty value), or you must specify an "@the.backedup.domain.tld x" wild-card in the relay_recipients table. Line 22: The [] forces Postfix to do no MX lookup. Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what lookup tables Postfix supports, use the command "postconf -m". Execute the command "postmap /etc/postfix/transport" whenever you change the transport table. NOTE for Postfix < 2.2: Do not use the fallback_relay feature when relaying mail for a backup or primary MX domain. Mail would loop between the Postfix MX host and the fallback_relay host when the final destination is unavailable. In main.cf specify "relay_transport = relay", In master.cf specify "-o fallback_relay =" at the end of the relay entry. In transport maps, specify "relay:nexthop..." as the right-hand side for backup or primary MX domain entries. These are default settings in Postfix version 2.2 and later.

Postfix on a dialup machine


This section applies to dialup connections that are down most of the time. For dialup connections that are up 24x7, see the local area network section above. This section presents additional configuration. You need to combine this with basic configuration information as discussed the first half of this document. If you do not have your own hostname and IP address (usually with dialup, cable TV or DSL connections) then you should also study the section on "Postfix on hosts without a real Internet hostname". Route all outgoing mail to your network provider. If your machine is disconnected most of the time, there isn't a lot of opportunity for Postfix to deliver mail to hard-to-reach corners of the Internet. It's better to give the mail to a machine that is connected all the time. In the example below, the [] prevents Postfix from trying to look up DNS MX records.
/etc/postfix/main.cf: relayhost = [smtprelay.someprovider.com]

Disable spontaneous SMTP mail delivery (if using on-demand dialup IP only). Normally, Postfix attempts to deliver outbound mail at its convenience. If your machine uses on-demand dialup IP, this causes your system to place a telephone call whenever you submit new mail, and whenever Postfix retries to deliver delayed mail. To prevent such telephone calls from being placed, disable spontaneous SMTP mail deliveries.
/etc/postfix/main.cf: defer_transports = smtp (Only for on-demand dialup IP hosts)

Disable SMTP client DNS lookups (dialup LAN only).


/etc/postfix/main.cf: disable_dns_lookups = yes (Only for on-demand dialup IP hosts)

Flush the mail queue whenever the Internet link is established. Put the following command into your PPP or SLIP dialup scripts:
/usr/sbin/sendmail -q (whenever the Internet link is up)

The exact location of the Postfix sendmail command is system-specific. Use the command "postconf sendmail_path" to find out where the Postfix sendmail command is located on your machine. In order to find out if the mail queue is flushed, use something like:
#!/bin/sh # Start mail deliveries. /usr/sbin/sendmail -q # Allow deliveries to start. sleep 10 # Loop until all messages have been tried at least once. while mailq | grep '^[^ ]*\*' >/dev/null do sleep 10 done

If you have disabled spontaneous SMTP mail delivery, you also need to run the "sendmail -q" command every now and then while the dialup link is up, so that newly-posted mail is flushed from the queue.

Postfix on hosts without a real Internet hostname


This section is for hosts that don't have their own Internet hostname. Typically these are systems that get a dynamic IP address via DHCP or via dialup. Postfix will let you send and receive mail just fine between accounts on a machine with a fantasy name. However, you cannot use a fantasy hostname in your email address when sending mail into the Internet, because no-one would be able to reply to your mail. In fact, more and more sites refuse mail addresses with non-existent domain names. Note: the following information is Postfix version dependent. To find out what Postfix version you have, execute the command "postconf mail_version".

Solution 1: Postfix version 2.2 and later


Postfix 2.2 uses the generic(5) address mapping to replace local fantasy email addresses by valid Internet addresses. This mapping happens ONLY when mail leaves the machine; not when you send mail between users on the same machine. The following example presents additional configuration. You need to combine this with basic configuration information as discussed the first half of this document.
1 /etc/postfix/main.cf: 2 smtp_generic_maps = hash:/etc/postfix/generic 3 4 /etc/postfix/generic: 5 his@localdomain.local hisaccount@hisisp.example 6 her@localdomain.local heraccount@herisp.example 7 @localdomain.local hisaccount+local@hisisp.example

When mail is sent to a remote host via SMTP: Line 5 replaces his@localdomain.local by his ISP mail address, Line 6 replaces her@localdomain.local by her ISP mail address, and Line 7 replaces other local addresses by his ISP account, with an address extension of +local (this example assumes that the ISP supports "+" style address extensions). Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what lookup tables Postfix supports, use the command "postconf -m". Execute the command "postmap /etc/postfix/generic" whenever you change the generic table.

Solution 2: Postfix version 2.1 and earlier


The solution with older Postfix systems is to use valid Internet addresses where possible, and to let Postfix map valid Internet addresses to local fantasy addresses. With this, you can send mail to the Internet and to local fantasy addresses, including mail to local fantasy addresses that don't have a valid Internet address of their own. The following example presents additional configuration. You need to combine this with basic configuration information as discussed the first half of this document.
1 /etc/postfix/main.cf:

2 myhostname = hostname.localdomain 3 mydomain = localdomain 4 5 canonical_maps = hash:/etc/postfix/canonical 6 7 virtual_alias_maps = hash:/etc/postfix/virtual 8 9 /etc/postfix/canonical: 10 your-login-name your-account@your-isp.com 11 12 /etc/postfix/virtual: 13 your-account@your-isp.com your-login-name

Translation: Lines 2-3: Substitute your fantasy hostname here. Do not use a domain name that is already in use by real organizations on the Internet. See RFC 2606 for examples of domain names that are guaranteed not to be owned by anyone. Lines 5, 9, 10: This provides the mapping from "your-login-name@hostname.localdomain" to "your-account@your-isp.com". This part is required. Lines 7, 12, 13: Deliver mail for "your-account@your-isp.com" locally, instead of sending it to the ISP. This part is not required but is convenient. Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what lookup tables Postfix supports, use the command "postconf -m". Execute the command "postmap /etc/postfix/canonical" whenever you change the canonical table. Execute the command "postmap /etc/postfix/virtual" whenever you change the virtual table.

Postfix Address Rewriting


Postfix address rewriting purpose
Address rewriting is at the heart of the Postfix mail system. Postfix rewrites addresses for many different purposes. Some are merely cosmetic, and some are necessary to deliver correctly formatted mail to the correct destination. Examples of address rewriting in Postfix are: Transform an incomplete address into a complete address. For example, transform "username" into "username@example.com", or transform "username@hostname" into "username@hostname.example.com". Replace an address by an equivalent address. For example, replace "username@example.com" by "firstname.lastname@example.com" when sending mail, and do the reverse transformation when receiving mail. Replace an internal address by an external address. For example, replace "username@localdomain.local" by "isp-account@isp.example" when sending mail from a home computer to the Internet. Replace an address by multiple addresses. For example, replace the address of an alias by the addresses listed under that alias. Determine how and where to deliver mail for a specific address. For example, deliver mail for "username@example.com" with the smtp(8) delivery agent, to the hosts that are listed in the DNS as the mail servers for the domain "example.com". Although Postfix currently has no address rewriting language, it can do surprisingly powerful address manipulation via table lookup. Postfix typically uses lookup tables with fixed strings to map one address to one or multiple addresses, and typically uses regular expressions to map multiple addresses to one or multiple addresses. Fixed-string lookup tables may be in the form of local files, or in the form of NIS, LDAP or SQL databases. The DATABASE_README document gives an introduction to Postfix lookup tables. Topics covered in this document: To rewrite message headers or not, or to label as invalid Postfix address rewriting overview Address rewriting when mail is received Rewrite addresses to standard form Canonical address mapping Address masquerading Automatic BCC recipients Virtual aliasing Address rewriting when mail is delivered Resolve address to destination Mail transport switch Relocated users table Address rewriting with remote delivery

Generic mapping for outgoing SMTP mail Address rewriting with local delivery Local alias database Local per-user .forward files Local catch-all address Debugging your address manipulations

To rewrite message headers or not, or to label as invalid


Postfix versions 2.1 and earlier always rewrite message header addresses, and append Postfix's own domain information to addresses that Postfix considers incomplete. While rewriting message header addresses is OK for mail with a local origin, it is undesirable for remote mail: Message header address rewriting is frowned upon by mail standards, Appending Postfix's own domain produces incorrect results with some incomplete addresses, Appending Postfix's own domain sometimes creates the appearance that spam is sent by local users. Postfix versions 2.2 give you the option to either not rewrite message headers from remote SMTP clients at all, or to label incomplete addresses in such message headers as invalid. Here is how it works: Postfix always rewrites message headers from local SMTP clients and from the Postfix sendmail command, and appends its own domain to incomplete addresses. The local_header_rewrite_clients parameter controls what SMTP clients Postfix considers local (by default, only local network interface addresses). Postfix never rewrites message header addresses from remote SMTP clients when the remote_header_rewrite_domain parameter value is empty (the default setting). Otherwise, Postfix rewrites message headers from remote SMTP clients, and appends the remote_header_rewrite_domain value to incomplete addresses. This feature can be used to append a reserved domain such as "domain.invalid", so that incomplete addresses cannot be mistaken for local addresses.

Postfix address rewriting overview


The figure below zooms in on those parts of Postfix that are most involved with address rewriting activity. See the OVERVIEW document for an overview of the complete Postfix architecture. Names followed by a number are Postfix daemon programs, while unnumbered names represent Postfix queues or internal sources of mail messages. trivialrewrite(8) (std form) ^ | | v ^ | | v active smtp(8) -> qmgr(8) -< lmtp(8) local(8) trivialrewrite(8 ) (resolve)

smtpd(8) qmqpd(8) >- cleanup(8) -> incoming -> pickup(8) ^ ^ | |

bounces forwarding deferred notices The table below summarizes all Postfix address manipulations. If you're reading this document for the first time, skip forward to "Address rewriting when mail is received". Once you've finished reading the remainder of this document, the table will help you to quickly find what you need. Address manipulation Rewrite addresses to standard form Scope all mail Daemon Global turn-on control Selective turn-off control append_at_myorigin, local_header_rewrite_client trivialappend_dot_mydomain, s, rewrite(8 swap_bangpath, remote_header_rewrite_do ) allow_percent_hack main cleanup( canonical_maps 8) receive_override_options, local_header_rewrite_client s, remote_header_rewrite_do main receive_override_options, local_header_rewrite_client s, remote_header_rewrite_do main receive_override_options receive_override_options none

Canonical address mapping

all mail

Address masquerading

all mail

cleanup( masquerade_domains 8)

Automatic BCC recipients Virtual aliasing Resolve address to destination Mail transport switch

always_bcc, cleanup( new mail sender_bcc_maps, 8) recipient_bcc_maps all mail all mail cleanup( virtual_alias_maps 8) trivialrewrite(8 none ) trivialrewrite(8 transport_maps ) trivialrewrite(8 relocated_maps )

all mail

none

Relocated users table

all mail

none

Generic mapping table Local alias database

outgoing SMTP smtp(8) smtp_generic_maps mail local mail local(8) alias_maps only

none none none none

Local per-user .forward local mail local(8) forward_path files only Local catch-all address local mail local(8) luser_relay only

Address rewriting when mail is received


The cleanup(8) server receives mail from outside of Postfix as well as mail from internal sources such as forwarded mail, undeliverable mail that is bounced to the sender, and postmaster notifications about problems with the mail system. The cleanup(8) server transforms the sender, recipients and message content into a standard form before writing it to an incoming queue file. The server cleans up sender and recipient addresses in message headers and in the envelope, adds missing message headers such as From: or Date: that are required by mail standards, and removes message headers such as Bcc: that should not be present. The cleanup(8) server delegates the more complex address manipulations to the trivial-rewrite(8) server as described later in this document. Address manipulations at this stage are: Rewrite addresses to standard form Canonical address mapping Address masquerading Automatic BCC recipients Virtual aliasing

Rewrite addresses to standard form


Before the cleanup(8) daemon runs an address through any address mapping lookup table, it first rewrites the address to the standard "user@fully.qualified.domain" form, by sending the address to the trivial-rewrite(8) daemon. The purpose of rewriting to standard form is to reduce the number of entries needed in lookup tables. The Postfix trivial-rewrite(8) daemon implements the following hard-coded address manipulations: Rewrite "@hosta,@hostb:user@site" to "user@site" In case you wonder what this is, the address form above is called a route address, and specifies that mail for "user@site" be delivered via "hosta" and "hostb". Usage of this form has been deprecated for a long time. Postfix has no ability to handle route addresses, other than to strip off the route part. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a nonempty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Rewrite "site!user" to "user@site" This feature is controlled by the boolean swap_bangpath parameter (default: yes). The purpose is to rewrite UUCP-style addresses to domain style. This is useful only when you receive mail via UUCP, but it probably does not hurt otherwise. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a nonempty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all".

Rewrite "user%domain" to "user@domain" This feature is controlled by the boolean allow_percent_hack parameter (default: yes). Typically, this is used in order to deal with monstrosities such as "user %domain@otherdomain". NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a nonempty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Rewrite "user" to "user@$myorigin" This feature is controlled by the boolean append_at_myorigin parameter (default: yes). You should never turn off this feature, because a lot of Postfix components expect that all addresses have the form "user@domain". NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter; otherwise they append the domain name specified with the remote_header_rewrite_domain configuration parameter, if one is specified. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". If your machine is not the main machine for $myorigin and you wish to have some users delivered locally without going via that main machine, make an entry in the virtual alias table that redirects "user@$myorigin" to "user@$myhostname". See also the "delivering some users locally" section in the STANDARD_CONFIGURATION_README document. Rewrite "user@host" to "user@host.$mydomain" This feature is controlled by the boolean append_dot_mydomain parameter (default: yes). The purpose is to get consistent treatment of different forms of the same hostname. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter; otherwise they append the domain name specified with the remote_header_rewrite_domain configuration parameter, if one is specified. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Some will argue that rewriting "host" to "host.domain" is bad. That is why it can be turned off. Others like the convenience of having Postfix's own domain appended automatically. Rewrite "user@site." to "user@site" (without the trailing dot). A single trailing dot is silently removed. However, an address that ends in multiple dots will be rejected as an invalid address.

NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a nonempty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all".

Canonical address mapping


The cleanup(8) daemon uses the canonical(5) tables to rewrite addresses in message envelopes and in message headers. By default all header and envelope addresses are rewritten; this is controlled with the canonical_classes configuration parameter. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a non-empty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Address rewriting is done for local and remote addresses. The mapping is useful to replace login names by "Firstname.Lastname" style addresses, or to clean up invalid domains in mail addresses produced by legacy mail systems. Canonical mapping is disabled by default. To enable, edit the canonical_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or commas. Example:
/etc/postfix/main.cf: canonical_maps = hash:/etc/postfix/canonical /etc/postfix/canonical: wietse Wietse.Venema

For static mappings as shown above, lookup tables such as hash:, ldap:, mysql: or pgsql: are sufficient. For dynamic mappings you can use regular expression tables. This requires that you become intimately familiar with the ideas expressed in regexp_table(5), pcre_table(5) and canonical(5). In addition to the canonical maps which are applied to both sender and recipient addresses, you can specify canonical maps that are applied only to sender addresses or to recipient addresses. Example:
/etc/postfix/main.cf: sender_canonical_maps = hash:/etc/postfix/sender_canonical recipient_canonical_maps = hash:/etc/postfix/recipient_canonical

The sender and recipient canonical maps are applied before the common canonical maps. The sender_canonical_classes and recipient_canonical_classes parameters control what addresses are subject to sender_canonical_maps and recipient_canonical_maps mappings, respectively. Sender-specific rewriting is useful when you want to rewrite ugly sender addresses to pretty ones, and still want to be able to send mail to the those ugly address without creating a mailer loop. Canonical mapping can be turned off selectively for mail received by smtpd(8), qmqpd(8), or pickup(8), by overriding main.cf settings in the master.cf file. This feature is available in Postfix version 2.1 and later. Example:
/etc/postfix/master.cf:

127.0.0.1:10026 inet n n -o receive_override_options=no_address_mappings

smtpd

Note: do not specify whitespace around the "=" here.

Address masquerading
Address masquerading is a method to hide hosts inside a domain behind their mail gateway, and to make it appear as if the mail comes from the gateway itself, instead of from individual machines. NOTE: Postfix versions 2.2 and later rewrite message headers from remote SMTP clients only if the client matches the local_header_rewrite_clients parameter, or if the remote_header_rewrite_domain configuration parameter specifies a non-empty value. To get the behavior before Postfix 2.2, specify "local_header_rewrite_clients = static:all". Address masquerading is disabled by default, and is implemented by the cleanup(8) server. To enable, edit the masquerade_domains parameter in the main.cf file and specify one or more domain names separated by whitespace or commas. When Postfix tries to masquerade a domain, it processes the list from left to right, and processing stops at the first match. Example:
/etc/postfix/main.cf: masquerade_domains = foo.example.com example.com

strips "any.thing.foo.example.com" to "foo.example.com", but strips "any.thing.else.example.com" to "example.com". A domain name prefixed with "!" means do not masquerade this domain or its subdomains:
/etc/postfix/main.cf: masquerade_domains = !foo.example.com example.com

does not change "any.thing.foo.example.com" and "foo.example.com", but strips "any.thing.else.example.com" to "example.com". The masquerade_exceptions configuration parameter specifies what user names should not be subjected to address masquerading. Specify one or more user names separated by whitespace or commas. Example:
/etc/postfix/main.cf: masquerade_exceptions = root

By default, Postfix makes no exceptions. Subtle point: by default, address masquerading is applied only to message headers and to envelope sender addresses, but not to envelope recipients. This allows you to use address masquerading on a mail gateway machine, while still being able to forward mail from outside to users on individual machines. In order to subject envelope recipient addresses to masquerading, too, specify (Postfix version 1.1 and later):
/etc/postfix/main.cf: masquerade_classes = envelope_sender, envelope_recipient, header_sender, header_recipient

If you rewrite the envelope recipient like this, Postfix will no longer be able to send mail to individual machines.

Address masquerading can be turned off selectively for mail received by smtpd(8), qmqpd(8), or pickup(8), by overriding main.cf settings in the master.cf file. This feature is available in Postfix version 2.1 and later. Example:
/etc/postfix/master.cf: 127.0.0.1:10026 inet n n -o receive_override_options=no_address_mappings smtpd

Note: do not specify whitespace around the "=" here.

Automatic BCC recipients


After applying the canonical and masquerade mappings, the cleanup(8) daemon can generate optional BCC (blind carbon-copy) recipients. Postfix provides three mechanisms: always_bcc = address Deliver a copy of all mail to the specified address. In Postfix versions before 2.1, this feature is implemented by smtpd(8), qmqpd(8), or pickup(8). sender_bcc_maps = type:table Search the specified "type:table" lookup table with the envelope sender address for an automatic BCC address. This feature is available in Postfix 2.1 and later. recipient_bcc_maps = type:table Search the specified "type:table" lookup table with the envelope recipient address for an automatic BCC address. This feature is available in Postfix 2.1 and later. Note: automatic BCC recipients are produced only for new mail. To avoid mailer loops, automatic BCC recipients are not generated for mail that Postfix forwards internally, nor for mail that Postfix generates itself. Automatic BCC recipients (including always_bcc) can be turned off selectively for mail received by smtpd(8), qmqpd(8), or pickup(8), by overriding main.cf settings in the master.cf file. This feature is available in Postfix version 2.1 and later. Example:
/etc/postfix/master.cf: 127.0.0.1:10026 inet n n -o receive_override_options=no_address_mappings smtpd

Note: do not specify whitespace around the "=" here.

Virtual aliasing
Before writing the recipients to the queue file, the cleanup(8) daemon uses the optional virtual(5) alias tables to redirect mail for recipients. The mapping affects only envelope recipient addresses; it has no effect on message headers or envelope sender addresses. Virtual alias lookups are useful to redirect mail for virtual alias domains to real user mailboxes, and to redirect mail for domains that no longer exist. Virtual alias lookups can also be used to transform " Firstname.Lastname " back into UNIX login names, although it seems that local aliases may be a more appropriate vehicle. See the VIRTUAL_README document for an overview of methods to host virtual domains with

Postfix. Virtual aliasing is disabled by default. To enable, edit the virtual_alias_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or commas. Example:
/etc/postfix/main.cf: virtual_alias_maps = hash:/etc/postfix/virtual /etc/postfix/virtual: Wietse.Venema wietse

Addresses found in virtual alias maps are subjected to another iteration of virtual aliasing, but are not subjected to canonical mapping, in order to avoid loops. For static mappings as shown above, lookup tables such as hash:, ldap:, mysql: or pgsql: are sufficient. For dynamic mappings you can use regular expression tables. This requires that you become intimately familiar with the ideas expressed in regexp_table(5), pcre_table(5) and virtual(5). Virtual aliasing can be turned off selectively for mail received by smtpd(8), qmqpd(8), or pickup(8), by overriding main.cf settings in the master.cf file. This feature is available in Postfix version 2.1 and later. Example:
/etc/postfix/master.cf: 127.0.0.1:10026 inet n n -o receive_override_options=no_address_mappings smtpd

Note: do not specify whitespace around the "=" here. At this point the message is ready to be stored into the Postfix incoming queue.

Address rewriting when mail is delivered


The Postfix queue manager sorts mail according to its destination and gives it to Postfix delivery agents such as local(8), smtp(8), or lmtp(8). Just like the cleanup(8) server, the Postfix queue manager delegates the more complex address manipulations to the trivial-rewrite(8) server. Address manipulations at this stage are: Resolve address to destination Mail transport switch Relocated users table Each Postfix delivery agent tries to deliver the mail to its destination, while encapsulating the sender, recipients, and message content according to the rules of the SMTP, LMTP, etc. protocol. When mail cannot be delivered, it is either returned to the sender or moved to the deferred queue and tried again later. Address manipulations when mail is delivered via the smtp(8) delivery agent: Generic mapping for outgoing SMTP mail Address manipulations when mail is delivered via the local(8) delivery agent: Local alias database Local per-user .forward files Local catch-all address

The remainder of this document presents each address manipulation step in more detail, with specific examples or with pointers to documentation with examples.

Resolve address to destination


The Postfix qmgr(8) queue manager selects new mail from the incoming queue or old mail from the deferred queue, and asks the trivial-rewrite(8) address rewriting and resolving daemon where it should be delivered. As of version 2.0, Postfix distinguishes four major address classes. Each class has its own list of domain names, and each class has its own default delivery method, as shown in the table below. See the ADDRESS_CLASS_README document for the fine details. Postfix versions before 2.0 only distinguish between local delivery and everything else. Destination domain list $mydestination, $inet_interfaces, $proxy_interfaces $virtual_mailbox_domains $relay_domains none Default delivery method $local_transport $virtual_transport $relay_transport $default_transport Availability Postfix 1.0 Postfix 2.0 Postfix 2.0 Postfix 1.0

Mail transport switch


Once the trivial-rewrite(8) daemon has determined a default delivery method it searches the optional transport(5) table for information that overrides the message destination and/or delivery method. Typical use of the transport(5) table is to send mail to a system that is not connected to the Internet, or to use a special SMTP client configuration for destinations that have special requirements. See, for example, the STANDARD_CONFIGURATION_README and UUCP_README documents, and the examples in the transport(5) manual page. Transport table lookups are disabled by default. To enable, edit the transport_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or commas. Example:
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport

Relocated users table


Next, the trivial-rewrite(8) address rewriting and resolving daemon runs each recipient through the relocated(5) database. This table provides information on how to reach users that no longer have an account, or what to do with mail for entire domains that no longer exist. When mail is sent to an address that is listed in this table, the message is returned to the sender with an informative message. The relocated(5) database is searched after transport(5) table lookups, in anticipation of transport(5) tables that can replace one recipient address by a different one. Lookups of relocated users are disabled by default. To enable, edit the relocated_maps parameter in the main.cf file and specify one or more lookup tables, separated by whitespace or commas. Example:
/etc/postfix/main.cf:

relocated_maps = hash:/etc/postfix/relocated /etc/postfix/relocated: username@example.com otheruser@elsewhere.tld

As of Postfix version 2, mail for a relocated user will be rejected by the SMTP server with the reason "user has moved to otheruser@elsewhere.tld". Older Postfix versions will receive the mail first, and then return it to the sender as undeliverable, with the same reason.

Generic mapping for outgoing SMTP mail


Some hosts have no valid Internet domain name, and instead use a name such as localdomain.local. This can be a problem when you want to send mail over the Internet, because many mail servers reject mail addresses with invalid domain names. With the smtp_generic_maps parameter you can specify generic(5) lookup tables that replace local mail addresses by valid Internet addresses when mail leaves the machine via SMTP. The generic(5) mapping replaces envelope and header addresses, and is non-recursive. It does not happen when you send mail between addresses on the local machine. This feature is available in Postfix version 2.2 and later. Example:
/etc/postfix/main.cf: smtp_generic_maps = hash:/etc/postfix/generic /etc/postfix/generic: his@localdomain.local her@localdomain.local @localdomain.local hisaccount+local@hisisp.example hisaccount@hisisp.example heraccount@herisp.example

When mail is sent to a remote host via SMTP, this replaces his@localdomain.local by his ISP mail address, replaces her@localdomain.local by her ISP mail address, and replaces other local addresses by his ISP account, with an address extension of +local (this example assumes that the ISP supports "+" style address extensions).

Local alias database


When mail is to be delivered locally, the local(8) delivery agent runs each local recipient name through the aliases(5) database. The mapping does not affect addresses in message headers. Local aliases are typically used to implement distribution lists, or to direct mail for standard aliases such as postmaster to real people. The table can also be used to map "Firstname.Lastname" addresses to login names. Alias lookups are enabled by default. The default configuration depends on the operating system environment, but it is typically one of the following:
/etc/postfix/main.cf: alias_maps = hash:/etc/aliases alias_maps = dbm:/etc/aliases, nis:mail.aliases

The pathname of the alias database file is controlled with the alias_database configuration parameter. The value is system dependent. Usually it is one of the following:
/etc/postfix/main.cf: alias_database = hash:/etc/aliases (4.4BSD, LINUX) alias_database = dbm:/etc/aliases (4.3BSD, SYSV<4)

alias_database = dbm:/etc/mail/aliases (SYSV4)

An aliases(5) file can specify that mail should be delivered to a local file, or to a command that receives the message in the standard input stream. For security reasons, deliveries to command and file destinations are performed with the rights of the alias database owner. A default userid, default_privs, is used for deliveries to commands or files in "root"-owned aliases.

Local per-user .forward files


With delivery via the local(8) deliver agent, users can control their own mail delivery by specifying destinations in a file called .forward in their home directories. The syntax of these files is the same as with the local aliases(5) file, except that the left-hand side of the alias (lookup key and colon) are not present.

Local catch-all address


When the local(8) delivery agent finds that a message recipient does not exist, the message is normally returned to the sender ("user unknown"). Sometimes it is desirable to forward mail for non-existing recipients to another machine. For this purpose you can specify an alternative destination with the luser_relay configuration parameter. Alternatively, mail for non-existent recipients can be delegated to an entirely different message transport, as specified with the fallback_transport configuration parameter. For details, see the local(8) delivery agent documentation. Note: if you use the luser_relay feature in order to receive mail for non-UNIX accounts, then you must specify:
/etc/postfix/main.cf: local_recipient_maps =

(i.e. empty) in the main.cf file, otherwise the Postfix SMTP server will reject mail for non-UNIX accounts with "User unknown in local recipient table". See the LOCAL_RECIPIENT_README file for more information on this. luser_relay can specify one address. It is subjected to "$name" expansions. Examples: $user@other.host The bare username, without address extension, is prepended to "@other.host". For example, mail for "username+foo" is sent to "username@other.host". $local@other.host The entire original recipient localpart, including address extension, is prepended to "@other.host". For example, mail for "username+foo" is sent to "username+foo@other.host". sysadmin+$user The bare username, without address extension, is appended to "sysadmin". For example, mail for "username+foo" is sent to "sysadmin+username". sysadmin+$local The entire original recipient localpart, including address extension, is appended to

"sysadmin". For example, mail for "username+foo" is sent to "sysadmin+username+foo".

Debugging your address manipulations


Postfix version 2.1 and later can produce mail delivery reports for debugging purposes. These reports not only show sender/recipient addresses after address rewriting and alias expansion or forwarding, they also show information about delivery to mailbox, delivery to non-Postfix command, responses from remote SMTP servers, and so on. Postfix can produce two types of mail delivery reports for debugging: What-if: report what would happen, but do not actually deliver mail. This mode of operation is requested with:
$ /usr/sbin/sendmail -bv address... Mail Delivery Status Report will be mailed to <your login name>.

What happened: deliver mail and report successes and/or failures, including replies from remote SMTP servers. This mode of operation is requested with:
$ /usr/sbin/sendmail -v address... Mail Delivery Status Report will be mailed to <your login name>.

These reports contain information that is generated by Postfix delivery agents. Since these run as daemon processes and do not interact with users directly, the result is sent as mail to the sender of the test message. The format of these reports is practically identical to that of ordinary non-delivery notifications. As an example, below is the delivery report that is produced with the command "sendmail -bv postfix-users@postfix.org". The first part of the report contains human-readable text. In this case, mail would be delivered via mail.cloud9.net, and the SMTP server replies with "250 Ok". Other reports may show delivery to mailbox, or delivery to non-Postfix command.
Content-Description: Notification Content-Type: text/plain This is the mail system at host spike.porcupine.org. Enclosed is the mail delivery report that you requested. The mail system <postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250 2.1.5 Ok

The second part of the report is in machine-readable form, and includes the following information: The envelope sender address (wietse@porcupine.org). The envelope recipient address (postfix-users@postfix.org). If the recipient address was changed by Postfix then Postfix also includes the original recipient address. The delivery status. Some details depend on Postfix version. The example below is for Postfix version 2.3 and later.
Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; spike.porcupine.org

X-Postfix-Queue-ID: 84863BC0E5 X-Postfix-Sender: rfc822; wietse@porcupine.org Arrival-Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) Final-Recipient: rfc822; postfix-users@postfix.org Action: deliverable Status: 2.1.5 Remote-MTA: dns; mail.cloud9.net Diagnostic-Code: smtp; 250 2.1.5 Ok

The third part of the report contains the message that Postfix would have delivered, including From: and To: message headers, so that you can see any effects of address rewriting on those. Mail submitted with "sendmail -bv" has no body content so none is shown in the example below.
Content-Description: Message Content-Type: message/rfc822 Received: by spike.porcupine.org (Postfix, from userid 1001) id 84863BC0E5; Sun, 26 Nov 2006 17:01:01 -0500 (EST) Subject: probe To: postfix-users@postfix.org Message-Id: <20061126220101.84863BC0E5@spike.porcupine.org> Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST) From: wietse@porcupine.org (Wietse Venema)

Postfix Virtual Domain Hosting Howto


Purpose of this document
This document requires Postfix version 2.0 or later. This document gives an overview of how Postfix can be used for hosting multiple Internet domains, both for final delivery on the machine itself and for the purpose of forwarding to destinations elsewhere. The text not only describes delivery mechanisms that are built into Postfix, but also gives pointers for using non-Postfix mail delivery software. The following topics are covered: Canonical versus hosted versus other domains Local files versus network databases As simple as can be: shared domains, UNIX system accounts Postfix virtual ALIAS example: separate domains, UNIX system accounts Postfix virtual MAILBOX example: separate domains, non-UNIX accounts Non-Postfix mailbox store: separate domains, non-UNIX accounts Mail forwarding domains Mailing lists Autoreplies

Canonical versus hosted versus other domains


Most Postfix systems are final destination for only a few domain names. These include the hostnames and [the IP addresses] of the machine that Postfix runs on, and sometimes also include the parent domain of the hostname. The remainder of this document will refer to these domains as the canonical domains. They are usually implemented with the Postfix local domain address class, as defined in the ADDRESS_CLASS_README file. Besides the canonical domains, Postfix can be configured to be final destination for any number of additional domains. These domains are called hosted, because they are not directly associated with the name of the machine itself. Hosted domains are usually implemented with the virtual alias domain address class and/or with the virtual mailbox domain address class, as defined in the ADDRESS_CLASS_README file. But wait! There is more. Postfix can be configured as a backup MX host for other domains. In this case Postfix is not the final destination for those domains. It merely queues the mail when the primary MX host is down, and forwards the mail when the primary MX host becomes available. This function is implemented with the relay domain address class, as defined in the ADDRESS_CLASS_README file. Finally, Postfix can be configured as a transit host for sending mail across the internet. Obviously, Postfix is not final destination for such mail. This function is available only for authorized clients

and/or users, and is implemented by the default domain address class, as defined in the ADDRESS_CLASS_README file.

Local files versus network databases


The examples in this text use table lookups from local files such as DBM or Berkeley DB. These are easy to debug with the postmap command: Example: postmap -q info@example.com hash:/etc/postfix/virtual See the documentation in LDAP_README, MYSQL_README and PGSQL_README for how to replace local files by databases. The reader is strongly advised to make the system work with local files before migrating to network databases, and to use the postmap command to verify that network database lookups produce the exact same results as local file lookup. Example: postmap -q info@example.com ldap:/etc/postfix/virtual.cf

As simple as can be: shared domains, UNIX system accounts


The simplest method to host an additional domain is to add the domain name to the domains listed in the Postfix mydestination configuration parameter, and to add the user names to the UNIX password file. This approach makes no distinction between canonical and hosted domains. Each username can receive mail in every domain. In the examples we will use "example.com" as the domain that is being hosted on the local Postfix machine.
/etc/postfix/main.cf: mydestination = $myhostname localhost.$mydomain ... example.com

The limitations of this approach are: A total lack of separation: mail for info@my.host.name is delivered to the same UNIX system account as mail for info@example.com. With users in the UNIX password file, administration of large numbers of users becomes inconvenient. The examples that follow provide solutions for both limitations.

Postfix virtual ALIAS example: separate domains, UNIX system accounts


With the approach described in this section, every hosted domain can have its own info etc. email address. However, it still uses UNIX system accounts for local mailbox deliveries. With virtual alias domains, each hosted address is aliased to a local UNIX system account or to a remote address. The example below shows how to use this mechanism for the example.com domain.
1 /etc/postfix/main.cf: 2 virtual_alias_domains = example.com ...other hosted domains... 3 virtual_alias_maps = hash:/etc/postfix/virtual

4 5 /etc/postfix/virtual: 6 postmaster@example.com postmaster 7 info@example.com joe 8 sales@example.com jane 9 # Uncomment entry below to implement a catch-all address 10 # @example.com jim 11 ...virtual aliases for more domains...

Notes: Line 2: the virtual_alias_domains setting tells Postfix that example.com is a so-called virtual alias domain. If you omit this setting then Postfix will reject mail (relay access denied) or will not be able to deliver it (mail for example.com loops back to myself). NEVER list a virtual alias domain name as a mydestination domain! Lines 3-8: the /etc/postfix/virtual file contains the virtual aliases. With the example above, mail for postmaster@example.com goes to the local postmaster, while mail for info@example.com goes to the UNIX account joe, and mail for sales@example.com goes to the UNIX account jane. Mail for all other addresses in example.com is rejected with the error message "User unknown". Line 10: the commented out entry (text after #) shows how one would implement a catch-all virtual alias that receives mail for every example.com address not listed in the virtual alias file. This is not without risk. Spammers nowadays try to send mail from (or mail to) every possible name that they can think of. A catch-all mailbox is likely to receive many spam messages, and many bounces for spam messages that were sent in the name of anything@example.com. Execute the command "postmap /etc/postfix/virtual" after changing the virtual file, and execute the command "postfix reload" after changing the main.cf file. Note: virtual aliases can resolve to a local address or to a remote address, or both. They don't have to resolve to UNIX system accounts on your machine. More details about the virtual alias file are given in the virtual(5) manual page, including multiple addresses on the right-hand side. Virtual aliasing solves one problem: it allows each domain to have its own info mail address. But there still is one drawback: each virtual address is aliased to a UNIX system account. As you add more virtual addresses you also add more UNIX system accounts. The next section eliminates this problem.

Postfix virtual MAILBOX example: separate domains, nonUNIX accounts


As a system hosts more and more domains and users, it becomes less desirable to give every user their own UNIX system account. With the Postfix virtual(8) mailbox delivery agent, every recipient address can have its own virtual mailbox. Unlike virtual alias domains, virtual mailbox domains do not need the clumsy translation from each recipient addresses into a different address, and owners of a virtual mailbox address do not need to have a UNIX system account. The Postfix virtual(8) mailbox delivery agent looks up the user mailbox pathname, uid and gid via separate tables that are searched with the recipient's mail address. Maildir style delivery is turned on by terminating the mailbox pathname with "/".

If you find the idea of multiple tables bothersome, remember that you can migrate the information (once it works), to an SQL database. If you take that route, be sure to review the "local files versus databases" section at the top of this document. Here is an example of a virtual mailbox domain "example.com":
1 /etc/postfix/main.cf: 2 virtual_mailbox_domains = example.com ...more domains... 3 virtual_mailbox_base = /var/mail/vhosts 4 virtual_mailbox_maps = hash:/etc/postfix/vmailbox 5 virtual_minimum_uid = 100 6 virtual_uid_maps = static:5000 7 virtual_gid_maps = static:5000 8 virtual_alias_maps = hash:/etc/postfix/virtual 9 10 /etc/postfix/vmailbox: 11 info@example.com example.com/info 12 sales@example.com example.com/sales/ 13 # Comment out the entry below to implement a catch-all. 14 # @example.com example.com/catchall 15 ...virtual mailboxes for more domains... 16 17 /etc/postfix/virtual: 18 postmaster@example.com postmaster

Notes: Line 2: The virtual_mailbox_domains setting tells Postfix that example.com is a so-called virtual mailbox domain. If you omit this setting then Postfix will reject mail (relay access denied) or will not be able to deliver it (mail for example.com loops back to myself). NEVER list a virtual MAILBOX domain name as a mydestination domain! NEVER list a virtual MAILBOX domain name as a virtual ALIAS domain! Line 3: The virtual_mailbox_base parameter specifies a prefix for all virtual mailbox pathnames. This is a safety mechanism in case someone makes a mistake. It prevents mail from being delivered all over the file system. Lines 4, 10-15: The virtual_mailbox_maps parameter specifies the lookup table with mailbox (or maildir) pathnames, indexed by the virtual mail address. In this example, mail for info@example.com goes to the mailbox at /var/mail/vhosts/example.com/info while mail for sales@example.com goes to the maildir located at /var/mail/vhosts/example.com/sales/. Line 5: The virtual_minimum_uid specifies a lower bound on the mailbox or maildir owner's UID. This is a safety mechanism in case someone makes a mistake. It prevents mail from being written to sensitive files. Lines 6, 7: The virtual_uid_maps and virtual_gid_maps parameters specify that all the virtual mailboxes are owned by a fixed uid and gid 5000. If this is not what you want, specify lookup tables that are searched by the recipient's mail address. Line 14: The commented out entry (text after #) shows how one would implement a catchall virtual mailbox address. Be prepared to receive a lot of spam, as well as bounced spam that was sent in the name of anything@example.com. NEVER put a virtual MAILBOX wild-card in the virtual ALIAS file!! Lines 8, 17, 18: As you see, it is possible to mix virtual aliases with virtual mailboxes. We use this feature to redirect mail for example.com's postmaster address to the local postmaster. You can use the same mechanism to redirect an address to a remote address.

Line 18: This example assumes that in main.cf, $myorigin is listed under the mydestination parameter setting. If that is not the case, specify an explicit domain name on the right-hand side of the virtual alias table entries or else mail will go to the wrong domain. Execute the command "postmap /etc/postfix/virtual" after changing the virtual file, execute "postmap /etc/postfix/vmailbox" after changing the vmailbox file, and execute the command "postfix reload" after changing the main.cf file. Note: mail delivery happens with the recipient's UID/GID privileges specified with virtual_uid_maps and virtual_gid_maps. Postfix 2.0 and earlier will not create mailDIRs in worldwritable parent directories; you must create them in advance before you can use them. Postfix may be able to create mailBOX files by itself, depending on parent directory write permissions, but it is safer to create mailBOX files ahead of time. More details about the virtual mailbox delivery agent are given in the virtual(8) manual page.

Non-Postfix mailbox store: separate domains, non-UNIX accounts


This is a variation on the Postfix virtual mailbox example. Again, every hosted address can have its own mailbox. While non-Postfix software is being used for final delivery, some Postfix concepts are still needed in order to glue everything together. For additional background on this glue you may want to take a look at the virtual mailbox domain class as defined in the ADDRESS_CLASS_README file. The text in this section describes what things should look like from Postfix's point of view. See CYRUS_README or MAILDROP_README for specific information about Cyrus or about Courier maildrop. Here is an example for a hosted domain example.com that delivers to a non-Postfix delivery agent:
1 /etc/postfix/main.cf: 2 virtual_transport = ...see below... 3 virtual_mailbox_domains = example.com ...more domains... 4 virtual_mailbox_maps = hash:/etc/postfix/vmailbox 5 virtual_alias_maps = hash:/etc/postfix/virtual 6 7 /etc/postfix/vmailbox: 8 info@example.com whatever 9 sales@example.com whatever 10 # Comment out the entry below to implement a catch-all. 11 # Configure the mailbox store to accept all addresses. 12 # @example.com whatever 13 ...virtual mailboxes for more domains... 14 15 /etc/postfix/virtual: 16 postmaster@example.com postmaster

Notes: Line 2: With delivery to a non-Postfix mailbox store for hosted domains, the virtual_transport parameter usually specifies the Postfix LMTP client, or the name of a master.cf entry that executes non-Postfix software via the pipe delivery agent. Typical examples (use only one):
virtual_transport = lmtp:unix:/path/name (uses UNIX-domain socket) virtual_transport = lmtp:hostname:port (uses TCP socket) virtual_transport = maildrop: (uses pipe(8) to

command)

Postfix comes ready with support for LMTP. And an example maildrop delivery method is already defined in the default Postfix master.cf file. See the MAILDROP_README document for more details. Line 3: The virtual_mailbox_domains setting tells Postfix that example.com is delivered via the virtual_transport that was discussed in the previous paragraph. If you omit this virtual_mailbox_domains setting then Postfix will either reject mail (relay access denied) or will not be able to deliver it (mail for example.com loops back to myself). NEVER list a virtual MAILBOX domain name as a mydestination domain! NEVER list a virtual MAILBOX domain name as a virtual ALIAS domain! Lines 4, 7-13: The virtual_mailbox_maps parameter specifies the lookup table with all valid recipient addresses. The lookup result value is ignored by Postfix. In the above example, info@example.com and sales@example.com are listed as valid addresses; other mail for example.com is rejected with "User unknown" by the Postfix SMTP server. It's left up to the non-Postfix delivery agent to reject non-existent recipients from local submission or from local alias expansion. If you intend to use LDAP, MySQL or PgSQL instead of local files, be sure to review the "local files versus databases" section at the top of this document! Line 12: The commented out entry (text after #) shows how one would inform Postfix of the existence of a catch-all address. Again, the lookup result is ignored by Postfix. NEVER put a virtual MAILBOX wild-card in the virtual ALIAS file!! Note: if you specify a wildcard in virtual_mailbox_maps, then you still need to configure the non-Postfix mailbox store to receive mail for any address in that domain. Lines 5, 15, 16: As you see above, it is possible to mix virtual aliases with virtual mailboxes. We use this feature to redirect mail for example.com's postmaster address to the local postmaster. You can use the same mechanism to redirect any addresses to a local or remote address. Line 16: This example assumes that in main.cf, $myorigin is listed under the mydestination parameter setting. If that is not the case, specify an explicit domain name on the right-hand side of the virtual alias table entries or else mail will go to the wrong domain. Execute the command "postmap /etc/postfix/virtual" after changing the virtual file, execute "postmap /etc/postfix/vmailbox" after changing the vmailbox file, and execute the command "postfix reload" after changing the main.cf file.

Mail forwarding domains


Some providers host domains that have no (or only a few) local mailboxes. The main purpose of these domains is to forward mail elsewhere. The following example shows how to set up example.com as a mail forwarding domain:
1 /etc/postfix/main.cf: 2 virtual_alias_domains = example.com ...other hosted domains... 3 virtual_alias_maps = hash:/etc/postfix/virtual 4 5 /etc/postfix/virtual: 6 postmaster@example.com postmaster 7 joe@example.com joe@somewhere 8 jane@example.com jane@somewhere-else 9 # Uncomment entry below to implement a catch-all address 10 # @example.com jim@yet-another-site

11

...virtual aliases for more domains...

Notes: Line 2: The virtual_alias_domains setting tells Postfix that example.com is a so-called virtual alias domain. If you omit this setting then Postfix will reject mail (relay access denied) or will not be able to deliver it (mail for example.com loops back to myself). NEVER list a virtual alias domain name as a mydestination domain! Lines 3-11: The /etc/postfix/virtual file contains the virtual aliases. With the example above, mail for postmaster@example.com goes to the local postmaster, while mail for joe@example.com goes to the remote address joe@somewhere, and mail for jane@example.com goes to the remote address jane@somewhere-else. Mail for all other addresses in example.com is rejected with the error message "User unknown". Line 10: The commented out entry (text after #) shows how one would implement a catchall virtual alias that receives mail for every example.com address not listed in the virtual alias file. This is not without risk. Spammers nowadays try to send mail from (or mail to) every possible name that they can think of. A catch-all mailbox is likely to receive many spam messages, and many bounces for spam messages that were sent in the name of anything@example.com. Execute the command "postmap /etc/postfix/virtual" after changing the virtual file, and execute the command "postfix reload" after changing the main.cf file. More details about the virtual alias file are given in the virtual(5) manual page, including multiple addresses on the right-hand side.

Mailing lists
The examples that were given above already show how to direct mail for virtual postmaster addresses to a local postmaster. You can use the same method to direct mail for any address to a local or remote address. There is one major limitation: virtual aliases and virtual mailboxes can't directly deliver to mailing list managers such as majordomo. The solution is to set up virtual aliases that direct virtual addresses to the local delivery agent:
/etc/postfix/main.cf: virtual_alias_maps = hash:/etc/postfix/virtual /etc/postfix/virtual: listname-request@example.com listname-request listname@example.com listname owner-listname@example.com owner-listname /etc/aliases: listname: "|/some/where/majordomo/wrapper ..." owner-listname: ... listname-request: ...

This example assumes that in main.cf, $myorigin is listed under the mydestination parameter setting. If that is not the case, specify an explicit domain name on the right-hand side of the virtual alias table entries or else mail will go to the wrong domain. More information about the Postfix local delivery agent can be found in the local(8) manual page. Why does this example use a clumsy virtual alias instead of a more elegant transport mapping? The

reason is that mail for the virtual mailing list would be rejected with "User unknown". In order to make the transport mapping work one would still need a bunch of virtual alias or virtual mailbox table entries. In case of a virtual alias domain, there would need to be one identity mapping from each mailing list address to itself. In case of a virtual mailbox domain, there would need to be a dummy mailbox for each mailing list address.

Autoreplies
In order to set up an autoreply for virtual recipients while still delivering mail as normal, set up a rule in a virtual alias table:
/etc/postfix/main.cf: virtual_alias_maps = hash:/etc/postfix/virtual /etc/postfix/virtual: user@domain.tld user@domain.tld, user@domain.tld@autoreply.mydomain.tld

This delivers mail to the recipient, and sends a copy of the mail to the address that produces automatic replies. The address can be serviced on a different machine, or it can be serviced locally by setting up a transport map entry that pipes all mail for autoreply.mydomain.tld into some script that sends an automatic reply back to the sender. DO NOT list autoreply.mydomain.tld in mydestination!
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport /etc/postfix/transport: autoreply.mydomain.tld autoreply:

/etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= autoreply unix n n pipe flags= user=nobody argv=/path/to/autoreply $sender $mailbox

This invokes /path/to/autoreply with the sender address and the user@domain.tld recipient address on the command line. For more information, see the pipe(8) manual page, and the comments in the Postfix master.cf file.

Postfix SASL Howto


Warning
People who go to the trouble of installing Postfix may have the expectation that Postfix is more secure than some other mailers. The Cyrus SASL library contains a lot of code. With this, Postfix becomes as secure as other mail systems that use the Cyrus SASL library. Dovecot provides an alternative that may be worth considering.

How Postfix uses SASL authentication


SMTP servers need to decide whether an SMTP client is authorized to send mail to remote destinations, or only to destinations that the server itself is responsible for. Usually, SMTP servers allow mail to remote destinations when the client's IP address is in the "same network" as the server's IP address. SMTP clients outside the SMTP server's network need a different way to get "same network" privileges. To address this need, Postfix supports SASL authentication (RFC 4954, formerly RFC 2554). With this a remote SMTP client can authenticate to the Postfix SMTP server, and the Postfix SMTP client can authenticate to a remote SMTP server. Once a client is authenticated, a server can give it "same network" privileges. Postfix does not implement SASL itself, but instead uses existing implementations as building blocks. This means that some SASL-related configuration files will belong to Postfix, while other configuration files belong to the specific SASL implementation that Postfix will use. This document covers both the Postfix and non-Postfix configuration. You can read more about the following topics: Configuring SASL authentication in the Postfix SMTP server Configuring SASL authentication in the Postfix SMTP/LMTP client Building Postfix with SASL support Using Cyrus SASL version 1.5.x Credits

Configuring SASL authentication in the Postfix SMTP server


As mentioned earlier, SASL is implemented separately from Postfix. For this reason, configuring SASL authentication in the Postfix SMTP server involves two different steps: Configuring the SASL implementation to offer a list of mechanisms that are suitable for SASL authentication and, depending on the SASL implementation used, configuring authentication backends that verify the remote SMTP client's authentication data against the system password file or some other database. Configuring the Postfix SMTP server to enable SASL authentication, and to authorize clients to relay mail or to control what envelope sender addresses the client may use. Successful authentication in the Postfix SMTP server requires a functional SASL framework.

Configuring SASL should therefore always be the first step. You can read more about the following topics: Which SASL Implementations are supported? Configuring Dovecot SASL Postfix to Dovecot SASL communication Configuring Cyrus SASL Cyrus SASL configuration file name Cyrus SASL configuration file location Postfix to Cyrus SASL communication Enabling SASL authentication and authorization in the Postfix SMTP server Enabling SASL authentication in the Postfix SMTP server Postfix SMTP Server policy - SASL mechanism properties Enabling SASL authorization in the Postfix SMTP server Additional SMTP Server SASL options Testing SASL authentication in the Postfix SMTP server

Which SASL Implementations are supported?


Currently the Postfix SMTP server supports the Cyrus SASL and Dovecot SASL implementations. Note Before Postfix version 2.3, Postfix had support only for Cyrus SASL. Current Postfix versions have a plug-in architecture that can support multiple SASL implementations. To find out what SASL implementations are compiled into Postfix, use the following commands:
% postconf -a (SASL support in the SMTP server) % postconf -A (SASL support in the SMTP+LMTP client)

These commands are available only with Postfix version 2.3 and later.

Configuring Dovecot SASL


Dovecot is a POP/IMAP server that has its own configuration to authenticate POP/IMAP clients. When the Postfix SMTP server uses Dovecot SASL, it reuses parts of this configuration. Consult the Dovecot documentation for how to configure and operate the Dovecot authentication server. Postfix to Dovecot SASL communication Communication between the Postfix SMTP server and Dovecot SASL happens via a UNIX-domain socket. The socket pathname and the list of mechanisms offered to Postfix need to be specified on the Dovecot server side in dovecot.conf. The following example assumes that the Postfix queue is under /var/spool/postfix/.
1 /etc/dovecot.conf: 2 auth default { 3 mechanisms = plain login 4 passdb pam { 5 } 6 userdb passwd { 7 } 8 socket listen { 9 client {

10 11 12 13 14 15 16

} } }

path = /var/spool/postfix/private/auth mode = 0660 user = postfix group = postfix

Line 3 provides plain and login as mechanisms for the Postfix SMTP server, line 10 places the Dovecot SASL socket in /var/spool/postfix/private/auth, and lines 11-13 limit read+write permissions to user and group postfix only. Proceed with the section "Enabling SASL authentication and authorization in the Postfix SMTP server" to turn on and use SASL in the Postfix SMTP server.

Configuring Cyrus SASL


The Cyrus SASL framework supports a wide variety of applications (POP, IMAP, SMTP, etc.). Different applications may require different configurations. As a consequence each application may have its own configuration file. The first step configuring Cyrus SASL is to determine name and location of a configuration file that describes how the Postfix SMTP server will use the SASL framework. Cyrus SASL configuration file name The name of the configuration file (default: smtpd.conf) is configurable. It is a concatenation from a value that the Postfix SMTP server sends to the Cyrus SASL library, and the suffix .conf, added by Cyrus SASL. The value sent by Postfix is the name of the server component that will use Cyrus SASL. It defaults to smtpd and is configured with one of the following variables:
/etc/postfix/main.cf: # Postfix 2.3 and later smtpd_sasl_path = smtpd # Postfix < 2.3 smtpd_sasl_application_name = smtpd

Cyrus SASL configuration file location The location where Cyrus SASL searches for the named file depends on the Cyrus SASL version and the OS/distribution used. You can read more about the following topics: Cyrus SASL version 2.x searches for the configuration file in /usr/lib/sasl2/. Cyrus SASL version 2.1.22 and newer additionally search in /etc/sasl2/. Some Postfix distributions are modified and look for the Cyrus SASL configuration file in /etc/postfix/sasl/, /var/lib/sasl2/ etc. See the distribution-specific documentation to determine the expected location. Note Cyrus SASL searches /usr/lib/sasl2/ first. If it finds the specified configuration file there, it will not examine other locations.

Postfix to Cyrus SASL communication As the Postfix SMTP server is linked with the Cyrus SASL library libsasl, communication between Postfix and Cyrus SASL takes place by calling functions in the SASL library. The SASL library may use an external password verification service, or an internal plugin to connect to authentication backends and verify the SMTP client's authentication data against the system password file or other databases. The following table shows typical combinations discussed in this document: authentication backend /etc/shadow PAM IMAP server sasldb LDAP Note password verification service / plugin saslauthd saslauthd saslauthd sasldb ldapdb

MySQL, PostgreSQL, SQLite sql

Read the Cyrus SASL documentation for other backends it can use. saslauthd - Cyrus SASL password verification service Communication between the Postfix SMTP server (read: Cyrus SASL's libsasl) and the saslauthd server takes place over a UNIX-domain socket. saslauthd usually establishes the UNIX domain socket in /var/run/saslauthd/ and waits for authentication requests. The Postfix SMTP server must have read+execute permission to this directory or authentication attempts will fail. Important Some distributions require the user postfix to be member of a special group e.g. sasl, otherwise it will not be able to access the saslauthd socket directory. The following example configures the Cyrus SASL library to contact saslauthd as its password verification service:
/etc/sasl2/smtpd.conf: pwcheck_method: saslauthd mech_list: PLAIN LOGIN

Important Do not specify any other mechanisms in mech_list than PLAIN or LOGIN when using saslauthd! It can only handle these two mechanisms, and authentication will fail if clients are allowed to choose other mechanisms. Important Plaintext mechanisms (PLAIN, LOGIN) send credentials unencrypted. This information should be protected by an additional security layer such as a TLS-encrypted SMTP

session (see: TLS_README). Additionally the saslauthd server itself must be configured. It must be told which authentication backend to turn to for password verification. The backend is selected with a saslauthd command-line option and will be shown in the following examples. Note Some distributions use a configuration file to provide saslauthd command line options to set e.g. the authentication backend. Typical locations are /etc/sysconfig/saslauthd or /etc/default/saslauthd. Using saslauthd with /etc/shadow Access to the /etc/shadow system password file requires root privileges. The Postfix SMTP server (and in consequence libsasl linked to the server) runs with the least privilege possible. Direct access to /etc/shadow would not be possible without breaking the Postfix security architecture. The saslauthd socket builds a safe bridge. Postfix, running as limited user postfix, can access the UNIX-domain socket that saslauthd receives commands on; saslauthd, running as privileged user root, has the privileges required to access the shadow file. The saslauthd server verifies passwords against the authentication backend /etc/shadow if started like this:
% saslauthd -a shadow

See section "Testing saslauthd authentication" for test instructions. Using saslauthd with PAM Cyrus SASL can use the PAM framework to authenticate credentials. saslauthd uses the PAM framework when started like this:
% saslauthd -a pam

Note PAM configuration for the Postfix SMTP server is usually given in /etc/pam.d/smtp and is beyond the scope of this document. See section "Testing saslauthd authentication" for test instructions. Using saslauthd with an IMAP server saslauthd can verify the SMTP client credentials by using them to log into an IMAP server. If the login succeeds, SASL authentication also succeeds. saslauthd contacts an IMAP server when started like this:
% saslauthd -a rimap -O imap.example.com

Note The option "-O imap.example.com" specifies the IMAP server saslauthd should contact when it verifies credentials.

Important saslauthd sends IMAP login information unencrypted. Any IMAP session leaving the local host should be protected by an additional security layer such as an SSL tunnel. See section "Testing saslauthd authentication" for test instructions. Testing saslauthd authentication Cyrus SASL provides the testsaslauthd utility to test saslauthd authentication. The username and password are given as command line arguments. The example shows the response when authentication is successful:
% testsaslauthd -u username -p password 0: OK "Success."

Note Sometimes the testsaslauthd program is not distributed with a the Cyrus SASL main package. In that case, it may be distributed with -devel, -dev or -debug packages. Specify an additional "-s smtp" if saslauthd was configured to contact the PAM authentication framework, and specify an additional "-f /path/to/socketdir/mux" if saslauthd establishes the UNIX-domain socket in a non-default location. If authentication succeeds, proceed with the section "Enabling SASL authentication and authorization in the Postfix SMTP server". Cyrus SASL Plugins - auxiliary property plugins Cyrus SASL uses a plugin infrastructure (called auxprop) to expand libsasl's capabilities. Currently Cyrus SASL sources provide three authentication plugins. Plugin sasldb sql Description Accounts are stored stored in a Cyrus SASL Berkeley DB database Accounts are stored in a SQL database

ldapdb Accounts are stored stored in an LDAP database Important These three plugins support shared-secret mechanisms i.e. CRAM-MD5, DIGEST-MD5 and NTLM. These mechanisms send credentials encrypted but their verification process requires the password to be available in plaintext. Consequently passwords cannot (!) be stored in encrypted form. The sasldb plugin The sasldb auxprop plugin authenticates SASL clients against credentials that are stored in a Berkeley DB database. The database schema is specific to Cyrus SASL. The database is usually located at /etc/sasldb2. Note

The sasldb2 file contains passwords in plaintext, and should have read+write access only to user postfix or a group that postfix is member of. The saslpasswd2 command-line utility creates and maintains the database:
% saslpasswd2 -c -u example.com username Password: Again (for verification):

This command creates an account username@example.com. Important users must specify username@example.com as login name, not username. Run the following command to reuse the Postfix mydomain parameter value as the login domain:
% saslpasswd2 -c -u `postconf -h mydomain` username Password: Again (for verification):

Note Run saslpasswd2 without any options for further help on how to use the command. The sasldblistusers2 command lists all existing users in the sasldb database:
% sasldblistusers2 username1@example.com: password1 username2@example.com: password2

Configure libsasl to use sasldb with the following instructions:


/etc/sasl2/smtpd.conf: pwcheck_method: auxprop auxprop_plugin: sasldb mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM

Note In the above example adjust mech_list to the mechanisms that are applicable for your environment. The sql plugin The sql auxprop plugin is a generic SQL plugin. It provides access to credentials stored in a MySQL, PostgreSQL or SQLite database. This plugin requires that SASL client passwords are stored as plaintext. Tip If you must store encrypted passwords, you cannot use the sql auxprop plugin. Instead, see section "Using saslauthd with PAM", and configure PAM to look up the encrypted passwords with, for example, the pam_mysql module. You will not be able to use any of the methods that require access to plaintext passwords, such as the shared-secret methods CRAM-MD5 and DIGEST-MD5.

The following example configures libsasl to use the sql plugin and connects it to a PostgreSQL server:
/etc/sasl2/smtpd.conf: pwcheck_method: auxprop auxprop_plugin: sql mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 NTLM sql_engine: pgsql sql_hostnames: 127.0.0.1, 192.0.2.1 sql_user: username sql_passwd: secret sql_database: dbname sql_select: SELECT password FROM users WHERE user = '%u'@'%r'

Note Set appropriate permissions if smtpd.conf contains a password. The file should be readable by the postfix user. Note In the above example, adjust mech_list to the mechanisms that are applicable for your environment. The sql plugin has the following configuration options: sql_engine Specify mysql to connect to a MySQL server, pgsql for a PostgreSQL server or sqlite for an SQLite database sql_hostnames Specify one or more servers (hostname or hostname:port) separated by commas. Note With MySQL servers, specify localhost to connect over a UNIXdomain socket, and specify 127.0.0.1 to connect over a TCP socket. sql_user The login name to gain access to the database. sql_passwd The password to gain access to the database. sql_database The name of the database to connect to. sql_select

The SELECT statement that should retrieve the plaintext password from a database table. Important Do not enclose the statement in quotes! Use single quotes to escape macros! The sql plugin provides macros to build sql_select statements. They will be replaced with arguments sent from the client. The following macros are available: %u The name of the user whose properties are being selected. %p The name of the property being selected. While this could technically be anything, Cyrus SASL will try userPassword and cmusaslsecretMECHNAME (where MECHNAME is the name of a SASL mechanism). %r The name of the realm to which the user belongs. This could be the KERBEROS realm, the fully-qualified domain name of the computer the SASL application is running on, or the domain after the "@" in a username. The ldapdb plugin The ldapdb auxprop plugin provides access to credentials stored in an LDAP server. This plugin requires that SASL client passwords are stored as plaintext. Tip If you must store encrypted passwords, you cannot use the ldapdb auxprop plugin. Instead, you can use "saslauthd -a ldap" to query the LDAP database directly, with appropriate configuration in saslauthd.conf. This may be documented in a later version of this document. You will not be able to use any of the methods that require access to plaintext passwords, such as the shared-secret methods CRAM-MD5 and DIGEST-MD5. The ldapdb plugin implements proxy authorization. This means that the ldapdb plugin uses its own username and password to authenticate with the LDAP server, before it asks the LDAP server for the remote SMTP client's password. The LDAP server then decides if the ldapdb plugin is authorized to read the remote SMTP client's password. In a nutshell: Configuring ldapdb means authentication and authorization must be configured twice - once in the Postfix SMTP server to authenticate and authorize the remote SMTP client, and once in the LDAP server to authenticate and authorize the ldapdb plugin. This example configures libsasl to use the ldapdb plugin and the plugin to connect to an LDAP server:
/etc/sasl2/smtpd.conf: pwcheck_method: auxprop

auxprop_plugin: ldapdb mech_list: PLAIN LOGIN NTLM CRAM-MD5 DIGEST-MD5 ldapdb_uri: ldap://localhost ldapdb_id: proxyuser ldapdb_pw: password ldapdb_mech: DIGEST-MD5

Important Set appropriate permissions if smtpd.conf contains a password. The file should be readable by the postfix user. Note The shared-secret mechanisms (CRAM-MD5, etc.) require that the SASL client passwords are stored as plaintext. The following is a summary of applicable smtpd.conf file entries: auxprop_plugin Specify ldapdb to enable the plugin. ldapdb_uri Specify either ldapi:// for to connect over a UNIX-domain socket, ldap:// for an unencrypted TCP connection or ldaps:// for an encrypted TCP connection. ldapdb_id The login name to authenticate the ldapdb plugin to the LDAP server (proxy authorization). ldapdb_pw The password (in plaintext) to authenticate the ldapdb plugin to the LDAP server (proxy authorization). ldapdb_mech The mechanism to authenticate the ldapdb plugin to the LDAP server. Note Specify a mechanism here that is supported by the LDAP server. ldapdb_rc (optional) The path to a file containing individual configuration options for the ldapdb LDAP client (libldap). This allows to specify a TLS client certificate which in turn can be used to use the SASL EXTERNAL mechanism.

Note This mechanism supports authentication over an encrypted transport layer, which is recommended if the plugin must connect to an OpenLDAP server on a remote machine. ldapdb_starttls (optional) The TLS policy for connecting to the LDAP server. Specify either try or demand. If the option is try the plugin will attempt to establish a TLSencrypted connection with the LDAP server, and will fallback to an unencrypted connection if TLS fails. If the policy is demand and a TLS-encrypted connection cannot be established, the connection fails immediately. When the ldapdb plugin connects to the OpenLDAP server and successfully authenticates, the OpenLDAP server decides if the plugin user is authorized to read SASL account information. The following configuration gives an example of authorization configuration in the OpenLDAP slapd server:
/etc/openldap/slapd.conf: authz-regexp uid=(.*),cn=.*,cn=auth ldap:///dc=example,dc=com??sub?cn=$1 authz-policy to

Here, the authz-regexp option serves for authentication of the ldapdb user. It maps its login name to a DN in the LDAP directory tree where slapd can look up the SASL account information. The authz-policy options defines the authentication policy. In this case it grants authentication privileges "to" the ldapdb plugin. The last configuration step is to tell the OpenLDAP slapd server where ldapdb may search for usernames matching the one given by the mail client. The example below adds an additional attribute ldapdb user object (here: authzTo because the authz-policy is "to") and configures the scope where the login name "proxyuser" may search:
dn: cn=proxyuser,dc=example,dc=com changetype: modify add: authzTo authzTo: dn.regex:uniqueIdentifier=(.*),ou=people,dc=example,dc=com

Use the ldapmodify or ldapadd command to add the above attribute. Note Read the chapter "Using SASL" in the OpenLDAP Admin Guide for more detailed instructions to set up SASL authentication in OpenLDAP.

Enabling SASL authentication and authorization in the Postfix SMTP server


By default the Postfix SMTP server uses the Cyrus SASL implementation. If the Dovecot SASL implementation should be used, specify an smtpd_sasl_type value of dovecot instead of cyrus:
/etc/postfix/main.cf: smtpd_sasl_type = dovecot

Additionally set the path where the Postfix SMTP server can find the Dovecot SASL socket:
/etc/postfix/main.cf: smtpd_sasl_path = private/auth

Note This example uses a pathname relative to the Postfix queue directory, so that it will work whether or not the Postfix SMTP server runs chrooted. Enabling SASL authentication in the Postfix SMTP server Regardless of the SASL implementation type, enabling SMTP authentication in the Postfix SMTP server always requires setting the smtpd_sasl_auth_enable option:
/etc/postfix/main.cf: smtpd_sasl_auth_enable = yes

After a "postfix reload", SMTP clients will see the additional capability AUTH in an SMTP session, followed by a list of authentication mechanisms the server supports:
% telnet server.example.com 25 ... 220 server.example.com ESMTP Postfix EHLO client.example.com 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-AUTH DIGEST-MD5 PLAIN CRAM-MD5 ...

However not all clients recognize the AUTH capability as defined by the SASL authentication RFC. Some historical implementations expect the server to send an "=" as separator between the AUTH verb and the list of mechanisms that follows it. The broken_sasl_auth_clients configuration option lets Postfix repeat the AUTH statement in a form that these broken clients understand:
/etc/postfix/main.cf: broken_sasl_auth_clients = yes

Note Enable this option for Outlook up to and including version 2003 and Outlook Express up to version 6. This option does not hurt other clients. After "postfix reload", the Postfix SMTP server will propagate the AUTH capability twice - once for compliant and once for broken clients:
% telnet server.example.com 25 ... 220 server.example.com ESMTP Postfix EHLO client.example.com 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-AUTH DIGEST-MD5 PLAIN CRAM-MD5 250-AUTH=DIGEST-MD5 PLAIN CRAM-MD5 ...

Postfix SMTP Server policy - SASL mechanism properties The Postfix SMTP server supports policies that limit the SASL mechanisms that it makes available to clients, based on the properties of those mechanisms. The next two sections give examples of how these policies are used. Property noanonymous noplaintext nodictionary Description Don't use mechanisms that permit anonymous authentication. Don't use mechanisms that transmit unencrypted username and password information. Don't use mechanisms that are vulnerable to dictionary attacks.

forward_secrec Require forward secrecy between sessions (breaking one session does y not break earlier sessions). mutual_auth Use only mechanisms that authenticate both the client and the server to each other.

Unencrypted SMTP session The default policy is to allow any mechanism in the Postfix SMTP server except for those based on anonymous authentication:
/etc/postfix/main.cf: # Specify a list of properties separated by comma or whitespace smtpd_sasl_security_options = noanonymous

Important Always set at least the noanonymous option. Otherwise, the Postfix SMTP server can give strangers the same authorization as a properly-authenticated client. Encrypted SMTP session (TLS) A separate parameter controls Postfix SASL mechanism policy during a TLS-encrypted SMTP session. The default is to copy the settings from the unencrypted session:
/etc/postfix/main.cf: smtpd_sasl_tls_security_options = $smtpd_sasl_security_options

A more sophisticated policy allows plaintext mechanisms, but only over a TLS-encrypted connection:
/etc/postfix/main.cf: smtpd_sasl_security_options = noanonymous, noplaintext smtpd_sasl_tls_security_options = noanonymous

To offer SASL authentication only after a TLS-encrypted session has been established specify this:
/etc/postfix/main.cf: smtpd_tls_auth_only = yes

Enabling SASL authorization in the Postfix SMTP server After the client has authenticated with SASL, the Postfix SMTP server decides what the remote SMTP client will be authorized for. Examples of possible SMTP clients authorizations are:

Send a message to a remote recipient. Use a specific envelope sender in the MAIL FROM command. These permissions are not enabled by default. Mail relay authorization The permit_sasl_authenticated restriction allows SASL-authenticated SMTP clients to send mail to remote destinations. Add it to the list of smtpd_recipient_restrictions as follows:
/etc/postfix/main.cf: smtpd_recipient_restrictions = ... permit_mynetworks permit_sasl_authenticated reject_unauth_destination ...

Envelope sender address authorization By default an SMTP client may specify any envelope sender address in the MAIL FROM command. That is because the Postfix SMTP server only knows the remote SMTP client hostname and IP address, but not the user who controls the remote SMTP client. This changes the moment an SMTP client uses SASL authentication. Now, the Postfix SMTP server knows who the sender is. Given a table of envelope sender addresses and SASL login names, the Postfix SMTP server can decide if the SASL authenticated client is allowed to use a particular envelope sender address:
/etc/postfix/main.cf: smtpd_sender_login_maps = hash:/etc/postfix/controlled_envelope_senders smtpd_recipient_restrictions = ... reject_sender_login_mismatch permit_sasl_authenticated permit_mynetworks reject_unauth_destination ...

The controlled_envelope_senders table specifies the binding between a sender envelope address and the SASL login names that own that address:
/etc/postfix/controlled_envelope_senders # envelope sender owners (SASL login names) john@example.com john@example.com helpdesk@example.com john@example.com, mary@example.com postmaster admin@example.com @example.net barney, fred, john@example.com, mary@example.com

With this, the reject_sender_login_mismatch restriction above will reject the sender address in the MAIL FROM command if smtpd_sender_login_maps does not specify the SMTP client's login name as an owner of that address. See also reject_authenticated_sender_login_mismatch and reject_unauthenticated_sender_login_mismatch for additional control over the

SASL login name and the envelope sender. Additional SMTP Server SASL options Postfix provides a wide range of SASL authentication configuration options. The next section lists a few that are discussed frequently. See postconf(5) for a complete list. Default authentication domain Postfix can append a domain name (or any other string) to a SASL login name that does not have a domain part, e.g. "john" instead of "john@example.com":
/etc/postfix/main.cf: smtpd_sasl_local_domain = example.com

This is useful as a default setting and safety net for misconfigured clients, or during a migration to an authentication method/backend that requires an authentication REALM or domain name, before all SMTP clients are configured to send such information. Hiding SASL authentication from clients or networks Some clients insist on using SASL authentication if it is offered, even when they are not configured to send credentials - and therefore they will always fail and disconnect. Postfix can hide the AUTH capability from these clients/networks:
/etc/postfix/main.cf: smtpd_sasl_exceptions_networks = !192.0.2.171/32, 192.0.2.0/24

Adding the SASL login name to mail headers To report SASL login names in Received: message headers (Postfix version 2.3 and later):
/etc/postfix/main.cf: smtpd_sasl_authenticated_header = yes

Note The SASL login names will be shared with the entire world.

Testing SASL authentication in the Postfix SMTP Server


To test the server side, connect (for example, with telnet) to the Postfix SMTP server port and you should be able to have a conversation as shown below. Information sent by the client (that is, you) is shown in bold font.
% telnet server.example.com 25 ... 220 server.example.com ESMTP Postfix EHLO client.example.com 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-ETRN 250-AUTH DIGEST-MD5 PLAIN CRAM-MD5 250 8BITMIME AUTH PLAIN AHRlc3QAdGVzdHBhc3M= 235 Authentication successful

To test this over a connection that is encrypted with TLS, use openssl s_client instead of telnet:
% openssl s_client -connect server.example.com:25 -starttls smtp ... 220 server.example.com ESMTP Postfix EHLO client.example.com ...see above example for more...

Instead of AHRlc3QAdGVzdHBhc3M=, specify the base64-encoded form of \ 0username\0password (the \0 is a null byte). The example above is for a user named `test' with password `testpass'. Caution When posting logs of the SASL negotiations to public lists, please keep in mind that username/password information is trivial to recover from the base64-encoded form. You can use one of the following commands to generate base64 encoded authentication information:
% gen-auth plain username: username password:

The gen-auth Perl script was written by John Jetmore and can be found at http://jetmore.org/john/code/gen-auth.
% printf '\0username\0password' | mmencode

The mmencode command is part of the metamail software.


% perl -MMIME::Base64 -e \ 'print encode_base64("\0username\0password");'

MIME::Base64 is available from http://www.cpan.org/.

Configuring SASL authentication in the Postfix SMTP/LMTP client


The Postfix SMTP and the LMTP client can authenticate with a remote SMTP server via the Cyrus SASL framework. At this time, the Dovecot SASL implementation does not provide client functionality. Note The examples in this section discuss only the SMTP client. Replace smtp_ with lmtp_ to get the corresponding LMTP client configuration. You can read more about the following topics: Enabling SASL authentication in the Postfix SMTP/LMTP client Configuring sender-dependent SASL authentication Postfix SMTP/LMTP client policy - SASL mechanism properties Postfix SMTP/LMTP client policy - SASL mechanism names

Enabling SASL authentication in the Postfix SMTP/LMTP client


This section shows a typical scenario where the Postfix SMTP client sends all messages via a mail gateway server that requires SASL authentication. Trouble solving tips: If your SASL logins fail with "SASL authentication failure: No worthy mechs found" in the mail logfile, then see the section "Postfix SMTP/LMTP client policy - SASL mechanism properties". For a solution to a more obscure class of SASL authentication failures, see "Postfix SMTP/LMTP client policy - SASL mechanism names". To make the example more readable we introduce it in two parts. The first part takes care of the basic configuration, while the second part sets up the username/password information.
/etc/postfix/main.cf: smtp_sasl_auth_enable = yes relayhost = [mail.isp.example] # Alternative form: # relayhost = [mail.isp.example]:submission smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd

The smtp_sasl_auth_enable setting enables client-side authentication. We will configure the client's username and password information in the second part of the example. The relayhost setting forces the Postfix SMTP to send all remote messages to the specified mail server instead of trying to deliver them directly to their destination. In the relayhost setting, the "[" and "]" prevent the Postfix SMTP client from looking up MX (mail exchanger) records for the enclosed name. The relayhost destination may also specify a non-default TCP port. For example, the alternative form [mail.isp.example]:submission tells Postfix to connect to TCP network port 587, which is reserved for email client applications. The Postfix SMTP client is compatible with SMTP servers that use the non-standard "AUTH=method...." syntax in response to the EHLO command; this requires no additional Postfix client configuration. The Postfix SMTP client does not support the obsolete "wrappermode" protocol, which uses TCP port 465 on the SMTP server. See TLS_README for a solution that uses the stunnel command. With the smtp_sasl_password_maps parameter, we configure the Postfix SMTP client to send username and password information to the mail gateway server. As discussed in the next section, the Postfix SMTP client supports multiple ISP accounts. For this reason the username and password are stored in a table that contains one username/password combination for each mail gateway server.
/etc/postfix/sasl_passwd: # destination credentials [mail.isp.example] username:password # Alternative form: # [mail.isp.example]:submission username:password

Important

Keep the SASL client password file in /etc/postfix, and make the file read+write only for root to protect the username/password combinations against other users. The Postfix SMTP client will still be able to read the SASL client passwords. It opens the file as user root before it drops privileges, and before entering an optional chroot jail. Use the postmap command whenever you change the /etc/postfix/sasl_passwd file. If you specify the "[" and "]" in the relayhost destination, then you must use the same form in the smtp_sasl_password_maps file. If you specify a non-default TCP Port (such as ":submission" or ":587") in the relayhost destination, then you must use the same form in the smtp_sasl_password_maps file.

Configuring Sender-Dependent SASL authentication


Postfix supports different ISP accounts for different sender addresses (version 2.3 and later). This can be useful when one person uses the same machine for work and for personal use, or when people with different ISP accounts share the same Postfix server. To make this possible, Postfix supports per-sender SASL passwords and per-sender relay hosts. In the example below, the Postfix SMTP client will search the SASL password file by sender address before it searches that same file by destination. Likewise, the Postfix trivial-rewrite(8) daemon will search the per-sender relayhost file, and use the default relayhost setting only as a final resort.
/etc/postfix/main.cf: smtp_sender_dependent_authentication = yes sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd relayhost = [mail.isp.example] # Alternative form: # relayhost = [mail.isp.example]:submission /etc/postfix/sasl_passwd: # Per-sender authentication; see also /etc/postfix/sender_relay. user1@example.com username2:password2 user2@example.net username2:password2 # Login information for the default relayhost. [mail.isp.example] username:password # Alternative form: # [mail.isp.example]:submission username:password /etc/postfix/sender_relay: # Per-sender provider; see also /etc/postfix/sasl_passwd. user1@example.com [mail.example.com]:submission user2@example.net [mail.example.net]

If you are creative, then you can try to combine the two tables into one single MySQL database, and configure different Postfix queries to extract the appropriate information. Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what lookup tables Postfix supports, use the command "postconf -m". Execute the command "postmap /etc/postfix/sasl_passwd" whenever you change the sasl_passwd table. Execute the command "postmap /etc/postfix/sender_relay" whenever you change the

sender_relay table.

Postfix SMTP/LMTP client policy - SASL mechanism properties


Just like the Postfix SMTP server, the SMTP client has a policy that determines which SASL mechanisms are acceptable, based on their properties. The next two sections give examples of how these policies are used. Property Description Don't use mechanisms that transmit unencrypted username and password information. Don't use mechanisms that are vulnerable to dictionary attacks. Use only mechanisms that authenticate both the client and the server to each other. noanonymous Don't use mechanisms that permit anonymous authentication. noplaintext nodictionary mutual_auth

Unencrypted SMTP session The default policy is stricter than that of the Postfix SMTP server - plaintext mechanisms are not allowed (nor is any anonymous mechanism):
/etc/postfix/main.cf: smtp_sasl_security_options = noplaintext, noanonymous

This default policy, which allows no plaintext passwords, leads to authentication failures if the remote server only offers plaintext authentication mechanisms (the SMTP server announces "AUTH PLAIN LOGIN"). In such cases the SMTP client will log the following error message:
SASL authentication failure: No worthy mechs found

Note This same error message will also be logged when the libplain.so or liblogin.so modules are not installed in the /usr/lib/sasl2 directory. The insecure approach is to lower the security standards and permit plaintext authentication mechanisms:
/etc/postfix/main.cf: smtp_sasl_security_options = noanonymous

The more secure approach is to protect the plaintext username and password with TLS session encryption. To find out if the remote SMTP server supports TLS, connect to the server and see if it announces STARTTLS support as shown in the example. Information sent by the client (that is, you) is shown in bold font.
% telnet server.example.com 25 ... 220 server.example.com ESMTP Postfix EHLO client.example.com 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-STARTTLS ...

Instead of port 25 (smtp), specify port 587 (submission) where appriopriate. Encrypted SMTP session (TLS) To turn on TLS in the Postfix SMTP client, see TLS_README for configuration details. The smtp_sasl_tls_security_options parameter controls Postfix SASL mechanism policy during a TLS-encrypted SMTP session. The default is to copy the settings from the unencrypted session:
/etc/postfix/main.cf: smtp_sasl_tls_security_options = $smtp_sasl_security_options

A more sophisticated policy allows plaintext mechanisms, but only over a TLS-encrypted connection:
/etc/postfix/main.cf: smtpd_sasl_security_options = noanonymous, noplaintext smtpd_sasl_tls_security_options = noanonymous

Postfix SMTP/LMTP client policy - SASL mechanism names


Given the SASL security options of the previous section, the Cyrus SASL library will choose the most secure authentication mechanism that both the SMTP client and server implement. Unfortunately, that authentication mechanism may fail because the client or server is not configured to use that mechanism. To prevent this, the Postfix SMTP client can filter the names of the authentication mechanisms from the remote SMTP server. Used correctly, the filter hides unwanted mechanisms from the Cyrus SASL library, forcing the library to choose from the mechanisms the Postfix SMTP client filter passes through. The following example filters out everything but the mechanisms PLAIN and LOGIN:
/etc/postfix/main.cf: smtp_sasl_mechanism_filter = plain, login

Note If the remote server does not offer any of the mechanisms on the filter list, authentication will fail. We close this section with an example that passes every mechanism except for GSSAPI and LOGIN:
/etc/postfix/main.cf: smtp_sasl_mechanism_filter = !gssapi, !login, static:all

Building Postfix with SASL support


As mentioned elsewhere, Postfix supports two SASL implementations: Cyrus SASL (SMTP client and server) and Dovecot SASL (SMTP server only). Both implementations can be built into Postfix simultaneously. Building Dovecot SASL support Building Cyrus SASL support

Building Dovecot SASL support


These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Support for the Dovecot version 1 SASL protocol is available in Postfix 2.3 and later. At the time of writing, only server-side SASL support is available, so you can't use it to authenticate the Postfix SMTP client to your network provider's server. Dovecot uses its own daemon process for authentication. This keeps the Postfix build process simple, because there is no need to link extra libraries into Postfix. To generate the necessary Makefiles, execute the following in the Postfix top-level directory:
% make tidy # if you have left-over files from a previous build % make makefiles CCARGS='-DUSE_SASL_AUTH \ -DDEF_SERVER_SASL_TYPE=\"dovecot\"'

After this, proceed with "make" as described in the INSTALL document. Note The -DDEF_SERVER_SASL_TYPE=\"dovecot\" is not necessary; it just makes Postfix configuration a little more convenient because you don't have to specify the SASL plug-in type in the Postfix main.cf file (but this may cause surprises when you switch to a later Postfix version that is built with the default SASL type of sasl). If you also want support for LDAP or TLS (or for Cyrus SASL), you need to merge their CCARGS and AUXLIBS options into the above command line; see the LDAP_README and TLS_README for details.
% make tidy # if you have left-over files from a previous build % make makefiles CCARGS='-DUSE_SASL_AUTH \ -DDEF_SERVER_SASL_TYPE=\"dovecot\" \ ...CCARGS options for LDAP or TLS etc....' \ AUXLIBS='...AUXLIBS options for LDAP or TLS etc....'

Building Cyrus SASL support


Building the Cyrus SASL library Postfix works with cyrus-sasl-1.5.x or cyrus-sasl-2.1.x, which are available from ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/. Important If you install the Cyrus SASL libraries as per the default, you will have to create a symlink /usr/lib/sasl -> /usr/local/lib/sasl for version 1.5.x or /usr/lib/sasl2 -> /usr/local/lib/sasl2 for version 2.1.x. Reportedly, Microsoft Outlook (Express) requires the non-standard LOGIN and/or NTLM authentication mechanism. To enable these authentication mechanisms, build the Cyrus SASL libraries with:
% ./configure --enable-login --enable-ntlm

Building Postfix with Cyrus SASL support These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. The following assumes that the Cyrus SASL include files are in /usr/local/include, and that the Cyrus SASL libraries are in /usr/local/lib. On some systems this generates the necessary Makefile definitions: Cyrus SASL version 2.1.x
% make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ -I/usr/local/include/sasl" AUXLIBS="-L/usr/local/lib -lsasl2"

Cyrus SASL version 1.5.x


% make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ -I/usr/local/include" AUXLIBS="-L/usr/local/lib -lsasl"

On Solaris 2.x you need to specify run-time link information, otherwise the ld.so run-time linker will not find the SASL shared library: Cyrus SASL version 2.1.x
% make tidy # remove left-over files from a previous build % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ -I/usr/local/include/sasl" AUXLIBS="-L/usr/local/lib \ -R/usr/local/lib -lsasl2"

Cyrus SASL version 1.5.x


% make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_SASL_AUTH -DUSE_CYRUS_SASL \ -I/usr/local/include" AUXLIBS="-L/usr/local/lib \ -R/usr/local/lib -lsasl"

Using Cyrus SASL version 1.5.x


Postfix supports Cyrus SASL version 1.x, but you shouldn't use it unless you are forced to. The makers of Cyrus SASL write: This library is being deprecated and applications should transition to using the SASLv2 library (source: Project Cyrus: Downloads). If you still need to set it up, here's a quick rundown: Read the regular section on SMTP server configurations for the Cyrus SASL framework. The differences are: Cyrus SASL version 1.5.x searches for configuration (smtpd.conf) in /usr/lib/sasl/ only. You must place the configuration in that directory. Some systems may have modified Cyrus SASL and put the files into e.g. /var/lib/sasl/. Use the saslpasswd command instead of saslpasswd2 to create users in sasldb.

Use the sasldblistusers command instead of sasldblistusers2 to find users in sasldb. In the smtpd.conf file you can't use mech_list to limit the range of mechanisms offered. Instead, remove their libraries from /usr/lib/sasl/ (and remember remove those files again when a system update re-installs new versions).

Credits
Postfix SASL support was originally implemented by Till Franke of SuSE Rhein/Main AG. Wietse trimmed down the code to only the bare necessities. Support for Cyrus SASL version 2 was contributed by Jason Hoos. Liviu Daia added smtpd_sasl_application_name, separated reject_sender_login_mismatch into reject_authenticated_sender_login_mismatch and reject_unauthenticated_sender_login_mismatch, and revised the docs. Wietse made another iteration through the code to add plug-in support for multiple SASL implementations, and for reasons that have been lost, also changed smtpd_sasl_application_name into smtpd_sasl_path. The Dovecot SMTP server-only plug-in was originally implemented by Timo Sirainen of Procontrol, Finland. Patrick Ben Koetter revised this document for Postfix 2.4 and made much needed updates. Patrick Ben Koetter revised this document again for Postfix 2.7 and made much needed updates.

Postfix IPv6 Support


Introduction
Postfix 2.2 introduces support for the IPv6 (IP version 6) protocol. IPv6 support for older Postfix versions was available as an add-on patch. The section "Compatibility with Postfix <2.2 IPv6 support" below discusses the differences between these implementations. The main feature of interest is that IPv6 uses 128-bit IP addresses instead of the 32-bit addresses used by IPv4. It can therefore accommodate a much larger number of hosts and networks without ugly kluges such as NAT. A side benefit of the much larger address space is that it makes random network scanning impractical. Postfix uses the same SMTP protocol over IPv6 as it already uses over the older IPv4 network, and does AAAA record lookups in the DNS in addition to the older A records. Information about IPv6 can be found at http://www.ipv6.org/. This document provides information on the following topics: Supported platforms Configuration Known limitations Compatibility with Postfix <2.2 IPv6 support IPv6 Support for unsupported platforms Credits

Supported Platforms
Postfix version 2.2 supports IPv4 and IPv6 on the following platforms: AIX 5.1+ Darwin 7.3+ FreeBSD 4+ Linux 2.4+ NetBSD 1.5+ OpenBSD 2+ Solaris 8+ Tru64Unix V5.1+

On other platforms Postfix will simply use IPv4 as it has always done. See below for tips how to port Postfix IPv6 support to other environments.

Configuration
Postfix IPv6 support introduces two new main.cf configuration parameters, and introduces an important change in address syntax notation in match lists such as mynetworks or debug_peer_list. Postfix IPv6 address syntax is a little tricky, because there are a few places where you must enclose

an IPv6 address inside "[]" characters, and a few places where you must not. It is a good idea to use "[]" only in the few places where you have to. Check out the postconf(5) manual whenever you do IPv6 related configuration work with Postfix. Instead of hard-coding 127.0.0.1 and ::1 loopback addresses in master.cf, specify "inet_interfaces = loopback-only" in main.cf. This way you can use the same master.cf file regardless of whether or not Postfix will run on an IPv6-enabled system. The first new parameter is called inet_protocols. This specifies what protocols Postfix will use when it makes or accepts network connections, and also controls what DNS lookups Postfix will use when it makes network connections.
/etc/postfix/main.cf: # You must stop/start Postfix after changing this parameter. inet_protocols = ipv4 (DEFAULT: enable IPv4 only) inet_protocols = all (enable IPv4, and IPv6 if supported) inet_protocols = ipv4, ipv6 (enable both IPv4 and IPv6) inet_protocols = ipv6 (enable IPv6 only)

By default, Postfix uses IPv4 only, because most systems aren't attached to an IPv6 network. On systems with combined IPv4/IPv6 stacks, attempts to deliver mail via IPv6 would always fail with "network unreachable", and those attempts would only slow down Postfix. Linux kernels don't even load IPv6 protocol support by default. Any attempt to use it would fail immediately. Note 1: you must stop and start Postfix after changing the inet_protocols configuration parameter. Note 2: if you see error messages like the following, then you're running Linux and need to turn on IPv6 in the kernel: see http://www.ipv6.org/ for hints and tips. Unlike other systems, Linux does not have a combined stack for IPv4 and IPv6, and IPv6 protocol support is not loaded by default.
postconf: warning: inet_protocols: IPv6 support is disabled: Address family not supported by protocol postconf: warning: inet_protocols: configuring for IPv4 support only

Note 3: on older Linux and Solaris systems, the setting "inet_protocols = ipv6" will not prevent Postfix from accepting IPv4 connections. Postfix will present the client IP addresses in IPv6 format, though. In all other cases, Postfix always presents IPv4 client IP addresses in the traditional dotted quad IPv4 format. The other new parameter is smtp_bind_address6. This sets the local interface address for outgoing IPv6 SMTP connections, just like the smtp_bind_address parameter does for IPv4:
/etc/postfix/main.cf: smtp_bind_address6 = 2001:240:587:0:250:56ff:fe89:1

If you left the value of the mynetworks parameter at its default (i.e. no mynetworks setting in main.cf) Postfix will figure out by itself what its network addresses are. This is what a typical setting looks like:
% postconf mynetworks mynetworks = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [fe80::]/10 [2001:240:587::]/64

If you did specify the mynetworks parameter value in main.cf, you need update the mynetworks value to include the IPv6 networks the system is in. Be sure to specify IPv6 address information inside "[]", like this:
/etc/postfix/main.cf: mynetworks = ...IPv4 networks... [::1]/128 [2001:240:587::]/64 ...

NOTE: when configuring Postfix match lists such as mynetworks or debug_peer_list, you must specify IPv6 address information inside "[]" in the main.cf parameter value and in files specified with a "/file/name" pattern. IPv6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern.

Known Limitations
The order of IPv6/IPv4 outgoing connection attempts is not yet configurable. Currently, IPv6 is tried before IPv4. Postfix currently does not support DNSBL (real-time blackhole list) lookups for IPv6 client IP addresses; currently there are no blacklists that cover the IPv6 address space. IPv6 does not have class A, B, C, etc. networks. With IPv6 networks, the setting "mynetworks_style = class" has the same effect as the setting "mynetworks_style = subnet". On Tru64Unix and AIX, Postfix can't figure out the local subnet mask and always assumes a /128 network. This is a problem only with "mynetworks_style = subnet" and no explicit mynetworks setting in main.cf.

Compatibility with Postfix <2.2 IPv6 support


Postfix version 2.2 IPv6 support is based on the Postfix/IPv6 patch by Dean Strik and others, but differs in a few minor ways. main.cf: The inet_interfaces parameter does not support the notation "ipv6:all" or "ipv4:all". Use the inet_protocols parameter instead. main.cf: Specify "inet_protocols = all" or "inet_protocols = ipv4, ipv6" in order to enable both IPv4 and IPv6 support. main.cf: The inet_protocols parameter also controls what DNS lookups Postfix will attempt to make when delivering or receiving mail. main.cf: Specify "inet_interfaces = loopback-only" to listen on loopback network interfaces only. The lmtp_bind_address and lmtp_bind_address6 features were omitted. The Postfix LMTP client will be absorbed into the SMTP client, so there is no reason to keep adding features to the LMTP client. The SMTP server now requires that IPv6 addresses in SMTP commands are specified as [ipv6:ipv6address], as described in RFC 2821. The IPv6 network address matching code was rewritten from the ground up, and is expected to be closer to the specification. The result may be incompatible with the Postfix/IPv6 patch.

IPv6 Support for unsupported platforms


Getting Postfix IPv6 working on other platforms involves the following steps: Specify how Postfix should find the local network interfaces. Postfix needs this information to avoid mailer loops and to find out if mail for user@[ipaddress] is a local or remote destination. If your system has the getifaddrs() routine then add the following to your platform-specific section in src/util/sys_defs.h:
#ifndef NO_IPV6 # define HAS_IPV6 # define HAVE_GETIFADDRS #endif

Otherwise, if your system has the SIOCGLIF ioctl() command in /usr/include/*/*.h, add the following to your platform-specific section in src/util/sys_defs.h:
#ifndef NO_IPV6 # define HAS_IPV6 # define HAS_SIOCGLIF #endif

Otherwise, Postfix will have to use the old SIOCGIF commands and get along with reduced IPv6 functionality (it won't be able to figure out your IPv6 netmasks, which are needed for "mynetworks_style = subnet". Add this to your platform-specific section in src/util/sys_defs.h:
#ifndef NO_IPV6 # define HAS_IPV6 #endif

Test if Postfix can figure out its interface information. After compiling Postfix in the usual manner, step into the src/util directory and type "make inet_addr_local". Running this file by hand should produce all the interface addresses and network masks, for example:
% make % cd src/util % make inet_addr_local [... some messages ...] % ./inet_addr_local [... some messages ...] ./inet_addr_local: inet_addr_local: configured 2 IPv4 addresses ./inet_addr_local: inet_addr_local: configured 4 IPv6 addresses 168.100.189.2/255.255.255.224 127.0.0.1/255.0.0.0 fe80:1::2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff:: 2001:240:587:0:2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff:: fe80:5::1/ffff:ffff:ffff:ffff:: ::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

The above is for an old FreeBSD machine. Other systems produce slightly different results, but you get the idea. If none of all this produces a usable result, send email to the postfix-users@postfix.org mailing list and we'll try to help you through this.

Credits
The following information is in part based on information that was compiled by Dean Strik. Mark Huizer wrote the original Postfix IPv6 patch. Jun-ichiro 'itojun' Hagino of the KAME project made substantial improvements. Since then, we speak of the KAME patch. The PLD Linux Distribution ported the code to other stacks (notably USAGI). We speak of the PLD patch. A very important feature of the PLD patch was that it can work with Lutz Jaenicke's TLS patch for Postfix. Dean Strik extended IPv6 support to platforms other than KAME and USAGI, updated the patch to keep up with Postfix development, and provided a combined IPv6 + TLS patch. Information about his effort can be found on Dean Strik's Postfix website at http://www.ipnet6.org/postfix/. Wietse Venema took Dean Strik's IPv6 patch, merged it into Postfix 2.2, and took the opportunity to eliminate all IPv4-specific code from Postfix that could be removed. For systems without IPv6 support in the kernel and system libraries, Postfix has a simple compatibility layer, so that it will use IPv4 as before.

Postfix TLS Support


WARNING
By turning on TLS support in Postfix, you not only get the ability to encrypt mail and to authenticate remote SMTP clients or servers. You also turn on thousands and thousands of lines of OpenSSL library code. Assuming that OpenSSL is written as carefully as Wietse's own code, every 1000 lines introduce one additional bug into Postfix.

What Postfix TLS support does for you


Transport Layer Security (TLS, formerly called SSL) provides certificate-based authentication and encrypted sessions. An encrypted session protects the information that is transmitted with SMTP mail or with SASL authentication. This document describes a TLS user interface that was introduced with Postfix version 2.3. Support for an older user interface is documented in TLS_LEGACY_README, which also describes the differences between Postfix and the third-party patch on which Postfix version 2.2 TLS support was based. Topics covered in this document: How Postfix TLS support works Building Postfix with TLS support SMTP Server specific settings SMTP Client specific settings TLS manager specific settings Reporting problems Credits

And last but not least, for the impatient: Getting started, quick and dirty

How Postfix TLS support works


The diagram below shows the main elements of the Postfix TLS architecture and their relationships. Colored boxes with numbered names represent Postfix daemon programs. Other colored boxes represent storage elements. The smtpd(8) server implements the SMTP over TLS server side. The smtp(8) client implements the SMTP over TLS client side. The tlsmgr(8) server maintains the pseudo-random number generator (PRNG) that seeds the TLS engines in the smtpd(8) server and smtp(8) client processes, and maintains the TLS session key cache files. Network-> <---seed-------seed---> ->Network

smtpd(8) <-key/cert-> / / smtpd session key cache

tlsmgr(8) <-key/cert-> | | \ \ PRNG state file smtp session key cache

smtp(8)

Building Postfix with TLS support


These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. To build Postfix with TLS support, first we need to generate the make(1) files with the necessary definitions. This is done by invoking the command "make makefiles" in the Postfix top-level directory and with arguments as shown next. NOTE: Do not use Gnu TLS. It will spontaneously terminate a Postfix daemon process with exit status code 2, instead of allowing Postfix to 1) report the error to the maillog file, and to 2) provide plaintext service where this is appropriate. If the OpenSSL include files (such as ssl.h) are in directory /usr/include/openssl, and the OpenSSL libraries (such as libssl.so and libcrypto.so) are in directory /usr/lib:
% make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_TLS" AUXLIBS="-lssl -lcrypto"

If the OpenSSL include files (such as ssl.h) are in directory /usr/local/include/openssl, and the OpenSSL libraries (such as libssl.so and libcrypto.so) are in directory /usr/local/lib:
% make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_TLS -I/usr/local/include" \ AUXLIBS="-L/usr/local/lib -lssl -lcrypto"

On Solaris, specify the -R option as shown below:


% make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_TLS -I/usr/local/include" \ AUXLIBS="-R/usr/local/lib -L/usr/local/lib -lssl -lcrypto"

If you need to apply other customizations (such as Berkeley DB databases, MySQL, PostgreSQL, LDAP or SASL), see the respective Postfix README documents, and combine their "make makefiles" instructions with the instructions above:
% make tidy # if you have left-over files from a previous build % make makefiles CCARGS="-DUSE_TLS \ (other -D or -I options)" \ AUXLIBS="-lssl -lcrypto \ (other -l options for libraries in /usr/lib) \ (-L/path/name + -l options for other libraries)"

To complete the build process, see the Postfix INSTALL instructions. Postfix has TLS support

turned off by default, so you can start using Postfix as soon as it is installed.

SMTP Server specific settings


Topics covered in this section: Server-side certificate and private key configuration Server-side TLS activity logging Enabling TLS in the Postfix SMTP server Client certificate verification Supporting AUTH over TLS only Server-side TLS session cache Server access control Server-side cipher controls Miscellaneous server controls

Server-side certificate and private key configuration


In order to use TLS, the Postfix SMTP server generally needs a certificate and a private key. Both must be in "PEM" format. The private key must not be encrypted, meaning: the key must be accessible without a password. The certificate and private key may be in the same file, in which case the certificate file should be owned by "root" and not be readable by any other user. If the key is stored separately, this applies to the key file only, and the certificate file may be "world-readable". Public Internet MX hosts without certificates signed by a "reputable" CA must generate, and be prepared to present to most clients, a self-signed or private-CA signed certificate. The remote SMTP client will generally not be able to authenticate the self-signed certificate, but unless the client is running Postfix 2.3 or similar software, it will still insist on a server certificate. For servers that are not public Internet MX hosts, Postfix supports configurations with no certificates. This entails the use of just the anonymous TLS ciphers, which are not supported by typical SMTP clients. Since such clients will not, as a rule, fall back to plain text after a TLS handshake failure, a certificate-less Postfix SMTP server will be unable to receive email from most TLS enabled clients. To avoid accidental configurations with no certificates, Postfix enables certificate-less operation only when the administrator explicitly sets "smtpd_tls_cert_file = none". This ensures that new Postfix SMTP server configurations will not accidentally run with no certificates. RSA, DSA and ECDSA (Postfix 2.6) certificates are supported. Typically you will only have RSA certificates issued by a commercial CA. In addition, the tools supplied with OpenSSL will by default issue RSA certificates. You can configure all three at the same time, in which case the cipher used determines which certificate is presented. For Netscape and OpenSSL clients without special cipher choices, the RSA certificate is preferred. To enable a remote SMTP client to verify the Postfix SMTP server certificate, the issuing CA certificates must be made available to the client. You should include the required certificates in the server certificate file, the server certificate first, then the issuing CA(s) (bottom-up order). Example: the certificate for "server.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". Create the server.pem file with:
% cat server_cert.pem intermediate_CA.pem > server.pem

A Postfix SMTP server certificate supplied here must be usable as SSL server certificate and hence pass the "openssl verify -purpose sslserver ..." test.

A client that trusts the root CA has a local copy of the root CA certificate, so it is not necessary to include the root CA certificate here. Leaving it out of the "server.pem" file reduces the overhead of the TLS exchange. If you want the Postfix SMTP server to accept remote SMTP client certificates issued by these CAs, append the root certificate to $smtpd_tls_CAfile or install it in the $smtpd_tls_CApath directory. RSA key and certificate examples:
/etc/postfix/main.cf: smtpd_tls_cert_file = /etc/postfix/server.pem smtpd_tls_key_file = $smtpd_tls_cert_file

Their DSA counterparts:


/etc/postfix/main.cf: smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem smtpd_tls_dkey_file = $smtpd_tls_dcert_file

Their ECDSA counterparts (Postfix 2.6 + OpenSSL 0.9.9):


/etc/postfix/main.cf: # Most clients will not be ECDSA capable, so you will likely also need # an RSA or DSA certificate and private key. # smtpd_tls_eccert_file = /etc/postfix/server-ecdsa.pem smtpd_tls_eckey_file = $smtpd_tls_eccert_file

TLS without certificates for servers serving exclusively anonymous-cipher capable clients:
/etc/postfix/main.cf: smtpd_tls_cert_file = none

To verify a remote SMTP client certificate, the Postfix SMTP server needs to trust the certificates of the issuing certification authorities. These certificates in "PEM" format can be stored in a single $smtpd_tls_CAfile or in multiple files, one CA per file in the $smtpd_tls_CApath directory. If you use a directory, don't forget to create the necessary "hash" links with:
# $OPENSSL_HOME/bin/c_rehash /path/to/directory

The $smtpd_tls_CAfile contains the CA certificates of one or more trusted CAs. The file is opened (with root privileges) before Postfix enters the optional chroot jail and so need not be accessible from inside the chroot jail. Additional trusted CAs can be specified via the $smtpd_tls_CApath directory, in which case the certificates are read (with $mail_owner privileges) from the files in the directory when the information is needed. Thus, the $smtpd_tls_CApath directory needs to be accessible inside the optional chroot jail. When you configure the Postfix SMTP server to request client certificates, the DNs of certificate authorities in $smtpd_tls_CAfile are sent to the client, in order to allow it to choose an identity signed by a CA you trust. If no $smtpd_tls_CAfile is specified, no preferred CA list is sent, and the client is free to choose an identity signed by any CA. Many clients use a fixed identity regardless of the preferred CA list and you may be able to reduce TLS negotiation overhead by installing client CA certificates mostly or only in $smtpd_tls_CApath. In the latter case you need not specify a $smtpd_tls_CAfile. Note, that unless client certificates are used to allow greater access to TLS authenticated clients, it is best to not ask for client certificates at all, as in addition to increased overhead some clients (notably

in some cases qmail) are unable to complete the TLS handshake when client certificates are requested. Example:
/etc/postfix/main.cf: smtpd_tls_CAfile = /etc/postfix/CAcert.pem smtpd_tls_CApath = /etc/postfix/certs

Server-side TLS activity logging


To get additional information about Postfix SMTP server TLS activity you can increase the log level from 0..4. Each logging level also includes the information that is logged at a lower logging level. 0 Disable logging of TLS activity. 1 Log TLS handshake and certificate information. 2 Log levels during TLS negotiation. 3 Log hexadecimal and ASCII dump of TLS negotiation process 4 Log hexadecimal and ASCII dump of complete transmission after STARTTLS Use log level 3 only in case of problems. Use of log level 4 is strongly discouraged. Example:
/etc/postfix/main.cf: smtpd_tls_loglevel = 0

To include information about the protocol and cipher used as well as the client and issuer CommonName into the "Received:" message header, set the smtpd_tls_received_header variable to true. The default is no, as the information is not necessarily authentic. Only information recorded at the final destination is reliable, since the headers may be changed by intermediate servers. Example:
/etc/postfix/main.cf: smtpd_tls_received_header = yes

Enabling TLS in the Postfix SMTP server


By default, TLS is disabled in the Postfix SMTP server, so no difference to plain Postfix is visible. Explicitly switch it on with "smtpd_tls_security_level = may" (Postfix 2.3 and later) or "smtpd_use_tls = yes" (obsolete but still supported). Example:
/etc/postfix/main.cf: # Postfix 2.3 and later smtpd_tls_security_level = may # Obsolete, but still supported smtpd_use_tls = yes

With this, the Postfix SMTP server announces STARTTLS support to remote SMTP clients, but does not require that clients use TLS encryption. Note: when an unprivileged user invokes "sendmail -bs", STARTTLS is never offered due to insufficient privileges to access the Postfix SMTP server private key. This is intended behavior. You can ENFORCE the use of TLS, so that the Postfix SMTP server announces STARTTLS and

accepts no mail without TLS encryption, by setting "smtpd_tls_security_level = encrypt" (Postfix 2.3 and later) or "smtpd_enforce_tls = yes" (obsolete but still supported). According to RFC 2487 this MUST NOT be applied in case of a publicly-referenced Postfix SMTP server. This option is off by default and should only seldom be used. Example:
/etc/postfix/main.cf: # Postfix 2.3 and later smtpd_tls_security_level = encrypt # Obsolete, but still supported smtpd_enforce_tls = yes

TLS is sometimes used in the non-standard "wrapper" mode where a server always uses TLS, instead of announcing STARTTLS support and waiting for remote SMTP clients to request TLS service. Some clients, namely Outlook [Express] prefer the "wrapper" mode. This is true for OE (Win32 < 5.0 and Win32 >=5.0 when run on a port<>25 and OE (5.01 Mac on all ports). It is strictly discouraged to use this mode from main.cf. If you want to support this service, enable a special port in master.cf and specify "-o smtpd_tls_wrappermode=yes" (note: no space around the "=") as an smtpd(8) command line option. Port 465 (smtps) was once chosen for this feature. Example:
/etc/postfix/master.cf: smtps inet n n smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes

Client certificate verification


To receive a remote SMTP client certificate, the Postfix SMTP server must explicitly ask for one (any contents of $smtpd_tls_CAfile are also sent to the client as a hint for choosing a certificate from a suitable CA). Unfortunately, Netscape clients will either complain if no matching client certificate is available or will offer the user client a list of certificates to choose from. Additionally some MTAs (notably some versions of qmail) are unable to complete TLS negotiation when client certificates are requested, and abort the SMTP session. So this option is "off" by default. You will however need the certificate if you want to use certificate based relaying with, for example, the permit_tls_clientcerts feature. A server that wants client certificates must first present its own certificate. While Postfix 2.3 by default offers anonymous ciphers to remote SMTP clients, these are automatically suppressed when the Postfix SMTP server is configured to ask for client certificates. Example:
/etc/postfix/main.cf: smtpd_tls_ask_ccert = yes # Postfix 2.3 and later smtpd_tls_security_level = may # Obsolete, but still supported smtpd_use_tls = yes

When TLS is enforced you may also decide to REQUIRE a remote SMTP client certificate for all TLS connections, by setting "smtpd_tls_req_ccert = yes". This feature implies "smtpd_tls_ask_ccert = yes". When TLS is not enforced, "smtpd_tls_req_ccert = yes" is ignored and a warning is logged. Example:
/etc/postfix/main.cf: smtpd_tls_req_ccert = yes # Postfix 2.3 and later smtpd_tls_security_level = encrypt

# Obsolete, but still supported smtpd_enforce_tls = yes

The client certificate verification depth is specified with the main.cf smtpd_tls_ccert_verifydepth parameter. The default verification depth is 9 (the OpenSSL default), for compatibility with Postfix versions before 2.5 where smtpd_tls_ccert_verifydepth was ignored. When you configure trust in a root CA, it is not necessary to explicitly trust intermediary CAs signed by the root CA, unless $smtpd_tls_ccert_verifydepth is less than the number of CAs in the certificate chain for the clients of interest. With a verify depth of 1 you can only verify certificates directly signed by a trusted CA, and all trusted intermediary CAs need to be configured explicitly. With a verify depth of 2 you can verify clients signed by a root CA or a direct intermediary CA (so long as the client is correctly configured to supply its intermediate CA certificate). Example:
/etc/postfix/main.cf: smtpd_tls_ccert_verifydepth = 2

Supporting AUTH over TLS only


Sending AUTH data over an unencrypted channel poses a security risk. When TLS layer encryption is required ("smtpd_tls_security_level = encrypt" or the obsolete "smtpd_enforce_tls = yes"), the Postfix SMTP server will announce and accept AUTH only after the TLS layer has been activated with STARTTLS. When TLS layer encryption is optional ("smtpd_tls_security_level = may" or the obsolete "smtpd_enforce_tls = no"), it may however still be useful to only offer AUTH when TLS is active. To maintain compatibility with non-TLS clients, the default is to accept AUTH without encryption. In order to change this behavior, set "smtpd_tls_auth_only = yes". Example:
/etc/postfix/main.cf: smtpd_tls_auth_only = no

Server-side TLS session cache


The Postfix SMTP server and the remote SMTP client negotiate a session, which takes some computer time and network bandwidth. By default, this session information is cached only in the smtpd(8) process actually using this session and is lost when the process terminates. To share the session information between multiple smtpd(8) processes, a persistent session cache can be used. You can specify any database type that can store objects of several kbytes and that supports the sequence operator. DBM databases are not suitable because they can only store small objects. The cache is maintained by the tlsmgr(8) process, so there is no problem with concurrent access. Session caching is highly recommended, because the cost of repeatedly negotiating TLS session keys is high. Example:
/etc/postfix/main.cf: smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache

Note: as of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non-Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. Cached Postfix SMTP server session information expires after a certain amount of time.

Postfix/TLS does not use the OpenSSL default of 300s, but a longer time of 3600sec (=1 hour). RFC 2246 recommends a maximum of 24 hours. Example:
/etc/postfix/main.cf: smtpd_tls_session_cache_timeout = 3600s

When the Postfix SMTP server does not save TLS sessions to an external cache database, clientside session caching is unlikely to be useful. To prevent such wastage, the Postfix SMTP server can be configured to not issue TLS session ids. By default the Postfix SMTP server always issues TLS session ids. This works around known interoperability issues with some MUAs, and prevents possible interoperability issues with other MTAs. Example:
smtpd_tls_always_issue_session_ids = no

Server access control


Postfix TLS support introduces three additional features for Postfix SMTP server access control: permit_tls_clientcerts Allow the remote SMTP client request if the client certificate fingerprint is listed in the client certificate table (see relay_clientcerts discussion below). permit_tls_all_clientcerts Allow the remote SMTP client request if the client certificate passes trust chain verification. Useful with private-label CAs that only issue certificates to trusted clients (and not otherwise). check_ccert_access type:table Use the remote SMTP client certificate fingerprint as the lookup key for the specified access(5) table. The digest algorithm used to construct the client certificate fingerprints is specified with the main.cf smtpd_tls_fingerprint_digest parameter. The default is "md5", for compatibility with Postfix versions < 2.5. The permit_tls_all_clientcerts feature must be used with caution, because it can result in too many access permissions. Use this feature only if a special CA issues the client certificates, and only if this CA is listed as trusted CA. If other CAs are trusted, any owner of a valid client certificate would be authorized. The permit_tls_all_clientcerts feature can be practical for a specially created email relay server. It is however recommended to stay with the permit_tls_clientcerts feature and list all certificates via $relay_clientcerts, as permit_tls_all_clientcerts does not permit any control when a certificate must no longer be used (e.g. an employee leaving). Example:
/etc/postfix/main.cf: smtpd_recipient_restrictions = ... permit_tls_clientcerts

reject_unauth_destination ...

Example: Postfix lookup tables are in the form of (key, value) pairs. Since we only need the key, the value can be chosen freely, e.g. the name of the user or host:
/etc/postfix/main.cf: relay_clientcerts = hash:/etc/postfix/relay_clientcerts /etc/postfix/relay_clientcerts: D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home

Server-side cipher controls


The description below is for Postfix 2.3; for Postfix < 2.3 the smtpd_tls_cipherlist parameter specifies the acceptable ciphers as an explicit OpenSSL cipherlist. The obsolete setting applies even when TLS encryption is not enforced. Use of this control on public MX hosts is strongly discouraged. The Postfix SMTP server supports 5 distinct cipher security levels as specified by the smtpd_tls_mandatory_ciphers configuration parameter, which determines the cipher grade with mandatory TLS encryption. The default value is "medium" which is essentially 128-bit encryption or better. With opportunistic TLS encryption, the minimum accepted cipher grade is typically "export". The corresponding smtpd_tls_ciphers parameter (Postfix 2.6) controls the cipher grade used with opportunistic TLS. By default anonymous ciphers are enabled. They are automatically disabled when remote SMTP client certificates are requested. If clients are expected to always verify the Postfix SMTP server certificate you may want to disable anonymous ciphers by setting "smtpd_tls_mandatory_exclude_ciphers = aNULL" or "smtpd_tls_exclude_ciphers = aNULL", as appropriate. One can't force a remote SMTP client to check the server certificate, so excluding anonymous ciphers is generally unnecessary. The "smtpd_tls_ciphers" configuration parameter (Postfix 2.6) provides control over the minimum cipher grade for opportunistic TLS. With Postfix < 2.6, the minimum opportunistic TLS cipher grade is always "export". With mandatory TLS encryption, the Postfix SMTP server will by default only use SSLv3 or TLSv1. SSLv2 is only used when TLS encryption is optional. The mandatory TLS protocol list is specified via the smtpd_tls_mandatory_protocols configuration parameter. The corresponding smtpd_tls_protocols parameter (Postfix 2.6) controls the SSL/TLS protocols used with opportunistic TLS. For a server that is not a public Internet MX host, Postfix ( 2.3) supports configurations with no server certificates that use only the anonymous ciphers. This is enabled by explicitly setting "smtpd_tls_cert_file = none" and not specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file. Example, MSA that requires TLSv1, not SSLv2 or SSLv3, with high grade ciphers:
/etc/postfix/main.cf: smtpd_tls_cert_file = /etc/postfix/cert.pem smtpd_tls_key_file = /etc/postfix/key.pem smtpd_tls_mandatory_ciphers = high smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5 smtpd_tls_security_level = encrypt smtpd_tls_mandatory_protocols = TLSv1 # Also available with Postfix 2.5: smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3

If you want to take advantage of ciphers with ephemeral Diffie-Hellman (EDH) key exchange (this offers "forward-secrecy"), DH parameters are needed. Instead of using the built-in DH parameters for both 1024-bit (non-export ciphers) and 512-bit (export ciphers), it is better to generate your own parameters, since otherwise it would "pay" for a possible attacker to start a brute force attack against parameters that are used by everybody. Postfix defaults to compiled-in parameters that are shared by all Postfix users who don't generate their own settings. To generate your own set of DH parameters, use:
% openssl gendh -out /etc/postfix/dh_512.pem -2 512 % openssl gendh -out /etc/postfix/dh_1024.pem -2 1024

Support for elliptic curve cryptography is available with Postfix 2.6 and OpenSSL 0.9.9 or later. To enable ephemeral elliptic curve Diffie-Hellman (EECDH) key-exchange, set "smtpd_tls_eecdh_grade = strong" or "smtpd_tls_eecdh_grade = ultra". The "ultra" setting is substantially more CPU intensive, and "strong" is sufficiently secure for most situations. Examples:
/etc/postfix/main.cf: smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem # Postfix 2.6: smtpd_tls_eecdh_grade = strong

Miscellaneous server controls


The smtpd_starttls_timeout parameter limits the time of Postfix SMTP server write and read operations during TLS startup and shutdown handshake procedures. Example:
/etc/postfix/main.cf: smtpd_starttls_timeout = 300s

SMTP Client specific settings


Topics covered in this section: TLS support in the LMTP delivery agent Client-side certificate and private key configuration Client-side TLS activity logging Client-side TLS session cache Client TLS limitations Configuring TLS in the SMTP/LMTP client Per-destination TLS policy Obsolete per-site TLS policy support Closing a DNS loophole with obsolete per-site TLS policies Discovering servers that support TLS Server certificate verification depth Client-side cipher controls Client-side SMTPS support Miscellaneous client controls

TLS support in the LMTP delivery agent


The smtp(8) and lmtp(8) delivery agents are implemented by a single dual-purpose program. Specifically, all the TLS features described below apply equally to SMTP and LMTP, after replacing the "smtp_" prefix of the each parameter name with "lmtp_". The Postfix LMTP delivery agent can communicate with LMTP servers listening on UNIX-domain sockets. When server certificate verification is enabled and the server is listening on a UNIXdomain socket, the $myhostname parameter is used to set the TLS verification nexthop and hostname. Note, opportunistic encryption of LMTP traffic over UNIX-domain sockets is futile. TLS is only useful in this context when it is mandatory, typically to allow at least one of the server or the client to authenticate the other. The "null" cipher grade may be appropriate in this context, when available on both client and server. The "null" ciphers provide authentication without encryption.

Client-side certificate and private key configuration


Do not configure Postfix SMTP client certificates unless you must present client TLS certificates to one or more servers. Client certificates are not usually needed, and can cause problems in configurations that work well without them. The recommended setting is to let the defaults stand:
smtp_tls_cert_file = smtp_tls_dcert_file = smtp_tls_key_file = smtp_tls_dkey_file = # Postfix 2.6 smtp_tls_eccert_file = smtp_tls_eckey_file =

The best way to use the default settings is to comment out the above parameters in main.cf if present. During TLS startup negotiation the Postfix SMTP client may present a certificate to the remote SMTP server. The Netscape client is rather clever here and lets the user select between only those certificates that match CA certificates offered by the remote SMTP server. As the Postfix SMTP client uses the "SSL_connect()" function from the OpenSSL package, this is not possible and we have to choose just one certificate. So for now the default is to use _no_ certificate and key unless one is explicitly specified here. RSA, DSA and ECDSA (Postfix 2.6) certificates are supported. You can configure all three at the same time, in which case the cipher used determines which certificate is presented. It is possible for the Postfix SMTP client to use the same key/certificate pair as the Postfix SMTP server. If a certificate is to be presented, it must be in "PEM" format. The private key must not be encrypted, meaning: it must be accessible without password. Both parts (certificate and private key) may be in the same file. To enable remote SMTP servers to verify the Postfix SMTP client certificate, the issuing CA certificates must be made available to the server. You should include the required certificates in the client certificate file, the client certificate first, then the issuing CA(s) (bottom-up order). Example: the certificate for "client.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". Create the client.pem file with:
% cat client_cert.pem intermediate_CA.pem > client.pem

A Postfix SMTP client certificate supplied here must be usable as SSL client certificate and hence pass the "openssl verify -purpose sslclient ..." test. A server that trusts the root CA has a local copy of the root CA certificate, so it is not necessary to

include the root CA certificate here. Leaving it out of the "client.pem" file reduces the overhead of the TLS exchange. If you want the Postfix SMTP client to accept remote SMTP server certificates issued by these CAs, append the root certificate to $smtp_tls_CAfile or install it in the $smtp_tls_CApath directory. RSA key and certificate examples:
/etc/postfix/main.cf: smtp_tls_cert_file = /etc/postfix/client.pem smtp_tls_key_file = $smtp_tls_cert_file

Their DSA counterparts:


/etc/postfix/main.cf: smtp_tls_dcert_file = /etc/postfix/client-dsa.pem smtp_tls_dkey_file = $smtp_tls_dcert_file

Their ECDSA counterparts (Postfix 2.6 + OpenSSL 0.9.9):


/etc/postfix/main.cf: smtp_tls_eccert_file = /etc/postfix/client-ecdsa.pem smtp_tls_eckey_file = $smtp_tls_eccert_file

To verify a remote SMTP server certificate, the Postfix SMTP client needs to trust the certificates of the issuing certification authorities. These certificates in "pem" format can be stored in a single $smtp_tls_CAfile or in multiple files, one CA per file in the $smtp_tls_CApath directory. If you use a directory, don't forget to create the necessary "hash" links with:
# $OPENSSL_HOME/bin/c_rehash /path/to/directory

The $smtp_tls_CAfile contains the CA certificates of one or more trusted CAs. The file is opened (with root privileges) before Postfix enters the optional chroot jail and so need not be accessible from inside the chroot jail. Additional trusted CAs can be specified via the $smtp_tls_CApath directory, in which case the certificates are read (with $mail_owner privileges) from the files in the directory when the information is needed. Thus, the $smtp_tls_CApath directory needs to be accessible inside the optional chroot jail. The choice between $smtp_tls_CAfile and $smtp_tls_CApath is a space/time tradeoff. If there are many trusted CAs, the cost of preloading them all into memory may not pay off in reduced access time when the certificate is needed. Example:
/etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAcert.pem smtp_tls_CApath = /etc/postfix/certs

Client-side TLS activity logging


To get additional information about Postfix SMTP client TLS activity you can increase the loglevel from 0..4. Each logging level also includes the information that is logged at a lower logging level. 0 1 2 3 Disable logging of TLS activity. Log TLS handshake and certificate information. Log levels during TLS negotiation. Log hexadecimal and ASCII dump of TLS negotiation process

4 Log hexadecimal and ASCII dump of complete transmission after STARTTLS Example:
/etc/postfix/main.cf: smtp_tls_loglevel = 0

Client-side TLS session cache


The remote SMTP server and the Postfix SMTP client negotiate a session, which takes some computer time and network bandwidth. By default, this session information is cached only in the smtp(8) process actually using this session and is lost when the process terminates. To share the session information between multiple smtp(8) processes, a persistent session cache can be used. You can specify any database type that can store objects of several kbytes and that supports the sequence operator. DBM databases are not suitable because they can only store small objects. The cache is maintained by the tlsmgr(8) process, so there is no problem with concurrent access. Session caching is highly recommended, because the cost of repeatedly negotiating TLS session keys is high. Future Postfix SMTP servers may limit the number of sessions that a client is allowed to negotiate per unit time. Example:
/etc/postfix/main.cf: smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache

Note: as of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non-Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. Cached Postfix SMTP client session information expires after a certain amount of time. Postfix/TLS does not use the OpenSSL default of 300s, but a longer time of 3600s (=1 hour). RFC 2246 recommends a maximum of 24 hours. Example:
/etc/postfix/main.cf: smtp_tls_session_cache_timeout = 3600s

Client TLS limitations


The security properties of TLS communication channels are application specific. While the TLS protocol can provide a confidential, tamper-resistant, mutually authenticated channel between client and server, not all of these security features are applicable to every communication. For example, while mutual TLS authentication between browsers and web servers is possible, it is not practical, or even useful, for web-servers that serve the public to verify the identity of every potential user. In practice, most HTTPS transactions are asymmetric: the browser verifies the HTTPS server's identity, but the user remains anonymous. Much of the security policy is up to the client. If the client chooses to not verify the server's name, the server is not aware of this. There are many interesting browser security topics, but we shall not dwell on them here. Rather, our goal is to understand the security features of TLS in conjunction with SMTP. An important SMTP-specific observation is that a public MX host is even more at the mercy of the SMTP client than is an HTTPS server. Not only can it not enforce due care in the client's use of TLS, but it cannot even enforce the use of TLS, because TLS support in SMTP clients is still the exception rather than the rule. One cannot, in practice, limit access to one's MX hosts to just TLS-

enabled clients. Such a policy would result in a vast reduction in one's ability to communicate by email with the world at large. One may be tempted to try enforcing TLS for mail from specific sending organizations, but this, too, runs into obstacles. One such obstacle is that we don't know who is (allegedly) sending mail until we see the "MAIL FROM:" SMTP command, and at that point, if TLS is not already in use, a potentially sensitive sender address (and with SMTP PIPELINING one or more of the recipients) has (have) already been leaked in the clear. Another obstacle is that mail from the sender to the recipient may be forwarded, and the forwarding organization may not have any security arrangements with the final destination. Bounces also need to be protected. These can only be identified by the IP address and HELO name of the connecting client, and it is difficult to keep track of all the potential IP addresses or HELO names of the outbound email servers of the sending organization. Consequently, TLS security for mail delivery to public MX hosts is almost entirely the client's responsibility. The server is largely a passive enabler of TLS security, the rest is up to the client. While the server has a greater opportunity to mandate client security policy when it is a dedicated MSA that only handles outbound mail from trusted clients, below we focus on the client security policy. On the SMTP client, there are further complications. When delivering mail to a given domain, in contrast to HTTPS, one rarely uses the domain name directly as the target host of the SMTP session. More typically, one uses MX lookups - these are usually unauthenticated - to obtain the domain's SMTP server hostname(s). When, as is current practice, the client verifies the insecurely obtained MX hostname, it is subject to a DNS man-in-the-middle attack. If clients instead attempted to verify the recipient domain name, an SMTP server for multiple domains would need to list all its email domain names in its certificate, and generate a new certificate each time a new domain were added. At least some CAs set fairly low limits (20 for one prominent CA) on the number of names that server certificates can contain. This approach is not consistent with current practice and does not scale. It is regrettably the case that TLS secure-channels (fully authenticated and immune to man-in-themiddle attacks) impose constraints on the sending and receiving sites that preclude ubiquitous deployment. One needs to manually configure this type of security for each destination domain, and in many cases implement non-default TLS policy table entries for additional domains hosted at a common secured destination. With Postfix 2.3, we make secure-channel configurations substantially easier to configure, but they will never be the norm. For the generic domain with which you have made no specific security arrangements, this security level is not a good fit. Given that strong authentication is not generally possible, and that verifiable certificates cost time and money, many servers that implement TLS use self-signed certificates or private CAs. This further limits the applicability of verified TLS on the public Internet. Historical note: while the documentation of these issues and many of the related features are new with Postfix 2.3, the issue was well understood before Postfix 1.0, when Lutz Jnicke was designing the first unofficial Postfix TLS patch. See his original post http://www.imc.org/ietf-apps-tls/mailarchive/msg00304.html and the first response http://www.imc.org/ietf-apps-tls/mailarchive/msg00305.html. The problem is not even unique to SMTP or even TLS, similar issues exist for secure connections via aliases for HTTPS and Kerberos. SMTP merely uses indirect naming (via MX records) more frequently.

Configuring TLS in the SMTP/LMTP client


Similar to the Postfix SMTP server, the Postfix SMTP/LMTP client implements multiple TLS security levels. These levels are described in more detail in the sections that follow.

none No TLS. may Opportunistic TLS. encrypt Mandatory TLS encryption. fingerprint Certificate fingerprint verification. verify Mandatory server certificate verification. secure Secure-channel TLS.

No TLS encryption
At the "none" TLS security level, TLS encryption is disabled. This is the default security level. With Postfix 2.3 and later, it can be configured explicitly by setting "smtp_tls_security_level = none". With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_use_tls = no" and "smtp_enforce_tls = no". With either approach, TLS is not used even if supported by the server. For LMTP, use the corresponding "lmtp_" parameters. Per destination settings may override this default setting, in which case TLS is used selectively, only with destinations explicitly configured for TLS. You can disable TLS for a subset of destinations, while leaving it enabled for the rest. With the Postfix 2.3 and later TLS policy table, specify the "none" security level. With the obsolete per-site table, specify the "NONE" keyword.

Opportunistic TLS
At the "may" TLS security level, TLS encryption is opportunistic. The SMTP transaction is encrypted if the STARTTLS ESMTP feature is supported by the server. Otherwise, messages are sent in the clear. With Postfix 2.3 and later, opportunistic TLS can be configured by setting "smtp_tls_security_level = may". Since sending in the clear is acceptable, demanding stronger than default TLS security mostly reduces inter-operability. If you must restrict TLS protocol or cipher selection even with opportunistic TLS, the "smtp_tls_ciphers" and "smtp_tls_protocols" configuration parameters (Postfix 2.6) provide control over the protocols and cipher grade used with opportunistic TLS. With earlier releases the opportunistic TLS cipher grade is always "export" and no protocols are disabled. With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_use_tls = yes" and "smtp_enforce_tls = no". For LMTP use the corresponding "lmtp_" parameters. With opportunistic TLS, mail delivery continues even if the server certificate is untrusted or bears the wrong name. Starting with Postfix 2.3, when the TLS handshake fails for an opportunistic TLS session, rather than give up on mail delivery, the transaction is retried with TLS disabled. Trying an unencrypted connection makes it possible to deliver mail to sites with non-interoperable server TLS implementations. Opportunistic encryption is never used for LMTP over UNIX-domain sockets. The communications channel is already confidential without TLS, so the only potential benefit of TLS is authentication.

Do not configure opportunistic TLS for LMTP deliveries over UNIX-domain sockets. Only configure TLS for LMTP over UNIX-domain sockets at the encrypt security level or higher. Attempts to configure opportunistic encryption of LMTP sessions will be ignored with a warning written to the mail logs. You can enable opportunistic TLS just for selected destinations. With the Postfix 2.3 and later TLS policy table, specify the "may" security level. With the obsolete per-site table, specify the "MAY" keyword. This is the most common security level for TLS protected SMTP sessions, stronger security is not generally available and, if needed, is typically only configured on a per-destination basis. See the section on TLS limitations above. Example:
/etc/postfix/main.cf: smtp_tls_security_level = may

Postfix 2.2 syntax:


/etc/postfix/main.cf: smtp_use_tls = yes smtp_enforce_tls = no

Mandatory TLS encryption


At the "encrypt" TLS security level, messages are sent only over TLS encrypted sessions. The SMTP transaction is aborted unless the STARTTLS ESMTP feature is supported by the remote SMTP server. If no suitable servers are found, the message will be deferred. With Postfix 2.3 and later, mandatory TLS encryption can be configured by setting "smtp_tls_security_level = encrypt". Even though TLS encryption is always used, mail delivery continues even if the server certificate is untrusted or bears the wrong name. At this security level and higher, the smtp_tls_mandatory_protocols and smtp_tls_mandatory_ciphers configuration parameters determine the list of sufficiently secure SSL protocol versions and the minimum cipher strength. If the protocol or cipher requirements are not met, the mail transaction is aborted. The documentation for these parameters includes useful interoperability and security guidelines. With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = no". For LMTP use the corresponding "lmtp_" parameters. Despite the potential for eliminating passive eavesdropping attacks, mandatory TLS encryption is not viable as a default security level for mail delivery to the public Internet. Most MX hosts do not support TLS at all, and some of those that do have broken implementations. On a host that delivers mail to the Internet, you should not configure mandatory TLS encryption as the default security level. You can enable mandatory TLS encryption just for specific destinations. With the Postfix 2.3 and later TLS policy table, specify the "encrypt" security level. With the obsolete per-site table, specify the "MUST_NOPEERMATCH" keyword. While the obsolete approach still works with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 and later should use the new TLS policy settings. Examples: In the example below, traffic to example.com and its sub-domains via the corresponding MX hosts always uses TLS. The protocol version will be "SSLv3" or "TLSv1" (the default setting of smtp_tls_mandatory_protocols excludes "SSLv2"). Only high or medium strength (i.e. 128 bit or

better) ciphers will be used by default for all "encrypt" security level sessions.
/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/postfix/tls_policy: example.com encrypt .example.com encrypt

Postfix 2.2 syntax (no support for sub-domains without resorting to regexp tables). With Postfix 2.3 and later, do not use the obsolete per-site table.
/etc/postfix/main.cf: smtp_tls_per_site = hash:/etc/postfix/tls_per_site /etc/postfix/tls_per_site: example.com MUST_NOPEERMATCH

In the next example, secure message submission is configured via the MSA "[example.net]:587". TLS sessions are encrypted without authentication, because this MSA does not possess an acceptable certificate. This MSA is known to be capable of "TLSv1" and "high" grade ciphers, so these are selected via the policy table. Note: the policy table lookup key is the verbatim next-hop specification from the recipient domain, transport(5) table or relayhost parameter, with any enclosing square brackets and optional port. Take care to be consistent: the suffixes ":smtp" or ":25" or no port suffix result in different policy table lookup keys, even though they are functionally equivalent nexthop specifications. Use at most one of these forms for all destinations. Below, the policy table has multiple keys, just in case the transport table entries are not specified consistently.
/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/services: submission submission 587/tcp msa # mail message

/etc/postfix/tls_policy: [example.net]:587 encrypt protocols=TLSv1 ciphers=high [example.net]:msa encrypt protocols=TLSv1 ciphers=high [example.net]:submission encrypt protocols=TLSv1 ciphers=high

Postfix 2.2 syntax: Note: Avoid policy lookups with the bare hostname (for example, "example.net"). Instead, use the destination (for example, "[example.net]:587"), as the per-site table lookup key (a recipient domain or MX-enabled transport nexthop with no port suffix may look like a bare hostname, but is still a suitable destination). With Postfix 2.3 and later, do not use the obsolete per-site table; use the new policy table instead.
/etc/postfix/main.cf: smtp_tls_per_site = hash:/etc/postfix/tls_per_site /etc/postfix/tls_per_site: [example.net]:587 MUST_NOPEERMATCH

Certificate fingerprint verification


Certificate fingerprint verification is available with Postfix 2.5 and later. At this security level

("smtp_tls_security_level = fingerprint"), no trusted certificate authorities are used or required. The certificate trust chain, expiration date, ... are not checked. Instead, the smtp_tls_fingerprint_cert_match parameter or the "match" attribute in the policy table lists the valid "fingerprints" of the remote SMTP server certificate. If certificate fingerprints are exchanged securely, this is the strongest, and least scalable security level. The administrator needs to securely collect the fingerprints of the X.509 certificates of each peer server, store them into a local file, and update this local file whenever the peer server's public certificate changes. This may be feasible for an SMTP "VPN" connecting a small number of branch offices over the Internet, or for secure connections to a central mail hub. It works poorly if the remote SMTP server is managed by a third party, and its public certificate changes periodically without prior coordination with the verifying site. The digest algorithm used to calculate the fingerprint is selected by the smtp_tls_fingerprint_digest parameter. In the policy table multiple fingerprints can be combined with a "|" delimiter in a single match attribute, or multiple match attributes can be employed. The ":" character is not used as a delimiter as it occurs between each pair of fingerprint (hexadecimal) digits. Example: fingerprint TLS security with an internal mailhub. Two matching fingerprints are listed. The relayhost may be multiple physical hosts behind a load-balancer, each with its own private/public key and self-signed certificate. Alternatively, a single relayhost may be in the process of switching from one set of private/public keys to another, and both keys are trusted just prior to the transition.
relayhost = [mailhub.example.com] smtp_tls_security_level = fingerprint smtp_tls_fingerprint_digest = md5 smtp_tls_fingerprint_cert_match = 3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1 EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35

Example: Certificate fingerprint verification with selected destinations. As in the example above, we show two matching fingerprints:
/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy smtp_tls_fingerprint_digest = md5 /etc/postfix/tls_policy: example.com fingerprint match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1 match=EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35

Mandatory server certificate verification


At the "verify" TLS security level, messages are sent only over TLS encrypted sessions if the remote SMTP server certificate is valid (not expired or revoked, and signed by a trusted certificate authority) and where the server certificate name matches a known pattern. Mandatory server certificate verification can be configured by setting "smtp_tls_security_level = verify". The smtp_tls_verify_cert_match parameter can override the default "hostname" certificate name matching strategy. Fine-tuning the matching strategy is generally only appropriate for securechannel destinations. With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes". For LMTP use the corresponding "lmtp_" parameters.

If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName certificate extension are used to verify the remote SMTP server name. If no DNS names are specified, the certificate CommonName is checked. If you want mandatory encryption without server certificate verification, see above. Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory certificate trust chain and subject name verification is not viable as a default Internet mail delivery policy. Most MX hosts do not support TLS at all, and a significant portion of TLS enabled MTAs use selfsigned certificates, or certificates that are signed by a private certificate authority. On a machine that delivers mail to the Internet, you should not configure mandatory server certificate verification as a default policy. Mandatory server certificate verification as a default security level may be appropriate if you know that you will only connect to servers that support RFC 2487 and that present verifiable server certificates. An example would be a client that sends all email to a central mailhub that offers the necessary STARTTLS support. In such cases, you can often use a secure-channel configuration instead. You can enable mandatory server certificate verification just for specific destinations. With the Postfix 2.3 and later TLS policy table, specify the "verify" security level. With the obsolete per-site table, specify the "MUST" keyword. While the obsolete approach still works with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 and later should use the new TLS policy settings. Example: In this example, the Postfix SMTP client encrypts all traffic to the example.com domain. The peer hostname is verified, but verification is vulnerable to DNS response forgery. Mail transmission to example.com recipients uses "high" grade ciphers.
/etc/postfix/main.cf: indexed = ${default_database_type}:${config_directory}/ smtp_tls_CAfile = ${config_directory}/CAfile.pem smtp_tls_policy_maps = ${indexed}tls_policy /etc/postfix/tls_policy: example.com verify ciphers=high

Postfix 2.2 syntax:


/etc/postfix/main.cf: indexed = ${default_database_type}:${config_directory}/ smtp_tls_CAfile = ${config_directory}/CAfile.pem smtp_tls_per_site = ${indexed}tls_per_site /etc/postfix/tls_per_site: example.com MUST

Secure server certificate verification


At the secure TLS security level, messages are sent only over secure-channel TLS sessions where DNS forgery resistant server certificate verification succeeds. If no suitable servers are found, the message will be deferred. With Postfix 2.3 and later, secure-channels can be configured by setting "smtp_tls_security_level = secure". The smtp_tls_secure_cert_match parameter can override the default "nexthop, dot-nexthop" certificate match strategy. With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its default (backwards compatible) empty value, the appropriate configuration settings are "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes" with additional settings to harden peer certificate verification

against forged DNS data. For LMTP, use the corresponding "lmtp_" parameters. If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName certificate extension are used to verify the remote SMTP server name. If no DNS names are specified, the CommonName is checked. If you want mandatory encryption without server certificate verification, see above. Despite the potential for eliminating "man-in-the-middle" and other attacks, mandatory secure server certificate verification is not viable as a default Internet mail delivery policy. Most MX hosts do not support TLS at all, and a significant portion of TLS enabled MTAs use self-signed certificates, or certificates that are signed by a private certificate authority. On a machine that delivers mail to the Internet, you should not configure secure TLS verification as a default policy. Mandatory secure server certificate verification as a default security level may be appropriate if you know that you will only connect to servers that support RFC 2487 and that present verifiable server certificates. An example would be a client that sends all email to a central mailhub that offers the necessary STARTTLS support. You can enable secure TLS verification just for specific destinations. With the Postfix 2.3 and later TLS policy table, specify the "secure" security level. With the obsolete per-site table, specify the "MUST" keyword and harden the certificate verification against DNS forgery. While the obsolete approach still works with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 and later should use the new TLS policy settings. Examples: Secure-channel TLS without transport(5) table overrides: The Postfix SMTP client will encrypt all traffic and verify the destination name immune from forged DNS responses. MX lookups are still used to find the hostnames of the SMTP servers for example.com, but these hostnames are not used when checking the names in the server certificate(s). Rather, the requirement is that the MX hosts for example.com have trusted certificates with a subject name of example.com or a sub-domain, see the documentation for the smtp_tls_secure_cert_match parameter. The related domains example.co.uk and example.co.jp are hosted on the same MX hosts as the primary example.com domain, and traffic to these is secured by verifying the primary example.com domain in the server certificates. This frees the server administrator from needing the CA to sign certificates that list all the secondary domains. The downside is that clients that want secure channels to the secondary domains need explicit TLS policy table entries. Note, there are two ways to handle related domains. The first is to use the default routing for each domain, but add policy table entries to override the expected certificate subject name. The second is to override the next-hop in the transport table, and use a single policy table entry for the common nexthop. We choose the first approach, because it works better when domain ownership changes. With the second approach we securely deliver mail to the wrong destination, with the first approach, authentication fails and mail stays in the local queue, the first approach is more appropriate in most cases.
/etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAfile.pem smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/postfix/transport: /etc/postfix/tls_policy: example.com secure example.co.uk secure match=example.com:.example.com example.co.jp secure match=example.com:.example.com

Secure-channel TLS with transport(5) table overrides: In this case traffic to example.com and its related domains is sent to a single logical gateway (to avoid a single point of failure, its name may resolve to one or more load-balancer addresses, or to the combined addresses of multiple physical hosts). All the physical hosts reachable via the gateway's IP addresses have the logical gateway name listed in their certificates. This securechannel configuration can also be implemented via a hardened variant of the MUST policy in the obsolete per-site table. As stated above, this approach has the potential to mis-deliver email if the related domains change hands.
/etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAfile.pem transport_maps = hash:/etc/postfix/transport smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/postfix/transport: example.com smtp:[tls.example.com] example.co.uk smtp:[tls.example.com] example.co.jp smtp:[tls.example.com] /etc/postfix/tls_policy: [tls.example.com] secure match=tls.example.com

Postfix 2.2.9 and later syntax: Note: Avoid policy lookups with the bare hostname (for example, "tls.example.com"). Instead, use the destination (for example, "[tls.example.com]") as the per-site table lookup key (a recipient domain or MX-enabled transport nexthop with no port suffix may look like a bare hostname, but is still a suitable destination). With Postfix 2.3 and later, do not use the obsolete per-site table; use the new policy table instead.
/etc/postfix/main.cf: smtp_cname_overrides_servername = no smtp_tls_CAfile = /etc/postfix/CAfile.pem transport_maps = hash:/etc/postfix/transport smtp_tls_per_site = hash:/etc/postfix/tls_per_site /etc/postfix/transport: example.com smtp:[tls.example.com] example.co.uk smtp:[tls.example.com] example.co.jp smtp:[tls.example.com] /etc/postfix/tls_per_site: [tls.example.com] MUST

TLS policy table


The current TLS policy table was introduced with Postfix 2.3. For earlier releases, read the description of the obsolete Postfix 2.2 per-site table. A small fraction of servers offer STARTTLS but the negotiation consistently fails. With Postfix 2.3, so long as encryption is not enforced, the delivery is immediately retried with TLS disabled. You no longer need to explicitly disable TLS for the problem destinations. As soon as their TLS software or configuration is repaired, encryption will be used. The new policy table is specified via the smtp_tls_policy_maps parameter. This lists optional lookup tables with the Postfix SMTP client TLS security policy by next-hop destination. When $smtp_tls_policy_maps is not empty, the obsolete smtp_tls_per_site parameter is ignored (a warning is written to the logs if both parameter values are non-empty).

The TLS policy table is indexed by the full next-hop destination, which is either the recipient domain, or the verbatim next-hop specified in the transport table, $local_transport, $virtual_transport, $relay_transport or $default_transport. This includes any enclosing square brackets and any non-default destination server port suffix. The LMTP socket type prefix (inet: or unix:) is not included in the lookup key. Only the next-hop domain, or $myhostname with LMTP over UNIX-domain sockets, is used as the nexthop name for certificate verification. The port and any enclosing square brackets are used in the table lookup key, but are not used for server name verification. When the lookup key is a domain name without enclosing square brackets or any :port suffix (typically the recipient domain), and the full domain is not found in the table, just as with the transport(5) table, the parent domain starting with a leading "." is matched recursively. This allows one to specify a security policy for a recipient domain and all its sub-domains. The lookup result is a security level, followed by an optional list of whitespace and/or comma separated name=value attributes that override related main.cf settings. The TLS security levels are described above. Below, we describe the corresponding table syntax: none No TLS. No additional attributes are supported at this level. may Opportunistic TLS. The optional "ciphers", "exclude" and "protocols" attributes (available for opportunistic TLS with Postfix 2.6) override the "smtp_tls_ciphers", "smtp_tls_exclude_ciphers" and "smtp_tls_protocols" configuration parameters. encrypt Mandatory encryption. Mail is delivered only if the remote SMTP server offers STARTTLS and the TLS handshake succeeds. At this level and higher, the optional "protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute overrides the main.cf smtp_tls_mandatory_ciphers parameter, and the optional "exclude" attribute (Postfix 2.6) overrides the main.cf smtp_tls_mandatory_exclude_ciphers parameter. fingerprint Certificate fingerprint verification. Available with Postfix 2.5 and later. At this security level, there are no trusted certificate authorities. The certificate trust chain, expiration date, ... are not checked. Instead, the optional match attribute, or else the main.cf smtp_tls_fingerprint_cert_match parameter, lists the valid fingerprints of the server certificate. The digest algorithm used to calculate fingerprints is selected by the smtp_tls_fingerprint_digest parameter. Multiple fingerprints can be combined with a "|" delimiter in a single match attribute, or multiple match attributes can be employed. The ":" character is not used as a delimiter as it occurs between each pair of fingerprint (hexadecimal) digits. verify Mandatory server certificate verification. Mail is delivered only if the TLS handshake succeeds, if the remote SMTP server certificate can be validated (not expired or revoked, and signed by a trusted certificate authority), and if the server certificate name matches the optional "match" attribute (or the main.cf smtp_tls_verify_cert_match parameter value when no optional "match" attribute is specified). secure Secure certificate verification. Mail is delivered only if the TLS handshake succeeds, if the remote SMTP server certificate can be validated (not expired or revoked, and signed by a trusted certificate authority), and if the server certificate name matches the optional "match" attribute (or the main.cf smtp_tls_secure_cert_match parameter value when no optional "match" attribute is specified).

Notes: The "match" attribute is especially useful to verify TLS certificates for domains that are hosted on a shared server. In that case, specify "match" rules for the shared server's name. While secure verification can also be achieved with manual routing overrides in Postfix transport(5) tables, that approach can deliver mail to the wrong host when domains are assigned to new gateway hosts. The "match" attribute approach avoids the problems of manual routing overrides; mail is deferred if verification of a new MX host fails. When a policy table entry specifies multiple match patterns, multiple match strategies, or multiple protocols, these must be separated by colons. The "exclude" attribute (Postfix 2.6) is used to disable ciphers that cause handshake failures with a specific mandatory TLS destination, without disabling the ciphers for all mandatory destinations. Alternatively, you can exclude ciphers that cause issues with multiple remote servers in main.cf, and selectively enable them on a per-destination basis in the policy table by setting a shorter or empty exclusion list. The per-destination "exclude" list preempts both the opportunistic and mandatory security level exclusions, so that all excluded ciphers can be enabled for known-good destinations. For non-mandatory TLS destinations that exhibit cipher-specific problems, Postfix will fall back to plain-text delivery. If plain-text is not acceptable make TLS mandatory and exclude the problem ciphers. Example:
/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy # Postfix 2.5 and later smtp_tls_fingerprint_digest = md5 /etc/postfix/tls_policy: example.edu none example.mil may example.gov encrypt protocols=SSLv3:TLSv1 ciphers=high example.com verify match=hostname:dot-nexthop protocols=SSLv3:TLSv1 ciphers=high example.net secure .example.net secure match=.example.net:example.net [mail.example.org]:587 secure match=nexthop # Postfix 2.5 and later [thumb.example.org] fingerprint match=EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35 match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1 # Postfix 2.6 and later example.info may protocols=!SSLv2 ciphers=medium exclude=3DES

Note: The "hostname" strategy if listed in a non-default setting of smtp_tls_secure_cert_match or in the "match" attribute in the policy table can render the "secure" level vulnerable to DNS forgery. Do not use the "hostname" strategy for secure-channel configurations in environments where DNS security is not assured.

Obsolete per-site TLS policy support


This section describes an obsolete per-site TLS policy mechanism. Unlike the Postfix 2.3 policy table mechanism, this uses as a policy lookup key a potentially untrusted server hostname, and lacks control over what names can appear in server certificates. Because of this, the obsolete mechanism is typically vulnerable to false DNS hostname information in MX or CNAME records. These

attacks can be eliminated only with great difficulty. The new policy table makes secure-channel configurations easier and provides more control over the cipher and protocol selection for sessions with mandatory encryption. Avoid policy lookups with the bare hostname. Instead, use the full destination nexthop (enclosed in [] with a possible ":port" suffix) as the per-site table lookup key (a recipient domain or MX-enabled transport nexthop with no port suffix may look like a bare hostname, but is still a suitable destination). With Postfix 2.3 and later, use of the obsolete approach documented here is strongly discouraged: use the new policy table instead. Starting with Postfix 2.3, the underlying TLS enforcement levels are common to the obsolete persite table and the new policy table. The main.cf smtp_tls_mandatory_ciphers and smtp_tls_mandatory_protocols parameters control the TLS ciphers and protocols for mandatory encryption regardless of which table is used. The smtp_tls_verify_cert_match parameter determines the match strategy for the obsolete "MUST" keyword in the same way as for the "verify" level in the new policy. With Postfix < 2.3, the obsolete smtp_tls_cipherlist parameter is also applied for opportunistic TLS sessions, and should be used with care, or not at all. Setting cipherlist restrictions that are incompatible with a remote SMTP server render that server unreachable, TLS handshakes are always attempted and always fail. When smtp_tls_policy_maps is empty (default) and smtp_tls_per_site is not empty, the per-site table is searched for a policy that matches the following information: remote SMTP server hostname This is simply the DNS name of the server that the Postfix SMTP client connects to; this name may be obtained from other DNS lookups, such as MX lookups or CNAME lookups. Use of the hostname lookup key is discouraged; always use the next-hop destination instead. next-hop destination This is normally the domain portion of the recipient address, but it may be overridden by information from the transport(5) table, from the relayhost parameter setting, or from the relay_transport setting. When it is not the recipient domain, the next-hop destination can have the Postfix-specific form "[name]", "[name]:port", "name" or "name:port". This is the recommended lookup key for per-site policy lookups (and incidentally for SASL password lookups). When both the hostname lookup and the next-hop lookup succeed, the host policy does not automatically override the next-hop policy. Instead, precedence is given to either the more specific or the more secure per-site policy as described below. The smtp_tls_per_site table uses a simple "name whitespace value" format. Specify host names or next-hop destinations on the left-hand side; no wildcards are allowed. On the right hand side specify one of the following keywords: NONE No TLS. This overrides a less specific "MAY" lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername settings. MAY

Opportunistic TLS. This has less precedence than a more specific result (including "NONE") from the alternate host or next-hop lookup key, and has less precedence than the more specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername = yes". MUST_NOPEERMATCH Mandatory TLS encryption. This overrides a less secure "NONE" or a less specific "MAY" lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. MUST Mandatory server certificate verification. This overrides a less secure "NONE" and "MUST_NOPEERMATCH" or a less specific "MAY" lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. The precedences between global (main.cf) and per-site TLS policies can be summarized as follows: When neither the remote SMTP server hostname nor the next-hop destination are found in the smtp_tls_per_site table, the policy is based on smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername. Note: "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes" imply "smtp_use_tls = yes". When both hostname and next-hop destination lookups produce a result, the more specific per-site policy (NONE, MUST, etc) overrides the less specific one (MAY), and the more secure per-site policy (MUST, etc) overrides the less secure one (NONE). After the per-site policy lookups are combined, the result generally overrides the global policy. The exception is the less specific "MAY" per-site policy, which is overruled by the more specific global "smtp_enforce_tls = yes" with server certificate verification as specified with the smtp_tls_enforce_peername parameter.

Closing a DNS loophole with obsolete per-site TLS policies


For a general discussion of TLS security for SMTP see TLS limitations above. What follows applies only to Postfix 2.2.9 and subsequent Postfix 2.2 patch levels. Do not use this approach with Postfix 2.3 and later; instead see the instructions under secure server certificate verification. As long as no secure DNS lookup mechanism is available, false hostnames in MX or CNAME responses can change Postfix's notion of the server hostname that is used for TLS policy lookup and server certificate verification. Even with a perfect match between the server hostname and the server certificate, there is no guarantee that Postfix is connected to the right server. To avoid this loophole, take all of the following steps: 1. Use a dedicated message delivery transport (for example, "securetls") as illustrated below. 2. Eliminate MX lookups. Specify local transport(5) table entries for sensitive domains with explicit securetls:[mailhost] or securetls:[mailhost]:port destinations (you can assure security of this table unlike DNS). This prevents false hostname information in DNS MX records from changing Postfix's notion of the server hostname that is used for TLS policy lookup and server certificate verification. The "securetls" transport is configured to enforce TLS with peername verification, and to disable the SMTP connection cache which could

interfere with enforcement of smtp_tls_per_site policies. 3. Disallow CNAME hostname overrides. In main.cf, specify "smtp_cname_overrides_servername = no". This prevents false hostname information in DNS CNAME records from changing the server hostname that Postfix uses for TLS policy lookup and server certificate verification. This feature requires Postfix 2.2.9 or later. The default value is "no" starting with Postfix 2.3. Example: We give the non-default "securetls" transport an explicit master.cf process limit, so that we don't raise its process limit when raising $default_process_limit. The total process limit for *all* transports should stay somewhat under 1024 (the typical select() file descriptor limit); otherwise transports may be throttled under steady high load, compounding congestion. It is not uncommon at high volume sites to set the default process limit to 500 or more. We also default the "securetls" transport TLS security level to MUST, obviating the need for persite table entries for secure-channel destinations.
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport /etc/postfix/transport: example.com securetls:[tls.example.com] /etc/postfix/master.cf: securetls unix n -o smtp_enforce_tls=yes -o smtp_tls_enforce_peername=yes 100 smtp

Discovering servers that support TLS


As we decide on a "per site" basis whether or not to use TLS, it would be good to have a list of sites that offered "STARTTLS". We can collect it ourselves with this option. If the smtp_tls_note_starttls_offer feature is enabled and a server offers STARTTLS while TLS is not already enabled for that server, the Postfix SMTP client logs a line as follows:
postfix/smtp[pid]: Host offered STARTTLS: [hostname.example.com]

Example:
/etc/postfix/main.cf: smtp_tls_note_starttls_offer = yes

Server certificate verification depth


The server certificate verification depth is specified with the main.cf smtp_tls_scert_verifydepth parameter. The default verification depth is 9 (the OpenSSL default), for compatibility with Postfix versions before 2.5 where smtp_tls_scert_verifydepth was ignored. When you configure trust in a root CA, it is not necessary to explicitly trust intermediary CAs signed by the root CA, unless $smtp_tls_scert_verifydepth is less than the number of CAs in the certificate chain for the servers of interest. With a verify depth of 1 you can only verify certificates directly signed by a trusted CA, and all trusted intermediary CAs need to be configured explicitly. With a verify depth of 2 you can verify servers signed by a root CA or a direct intermediary CA (so long as the server is correctly configured to supply its intermediate CA certificate). Example:

/etc/postfix/main.cf: smtp_tls_scert_verifydepth = 2

Client-side cipher controls


The Postfix SMTP client supports 5 distinct cipher security levels as specified by the smtp_tls_mandatory_ciphers configuration parameter. This setting controls the minimum acceptable SMTP client TLS cipher grade for use with mandatory TLS encryption. The default value "medium" is suitable for most destinations with which you may want to enforce TLS, and is beyond the reach of today's cryptanalytic methods. See smtp_tls_policy_maps for information on how to configure ciphers on a per-destination basis. By default anonymous ciphers are allowed, and automatically disabled when remote SMTP server certificates are verified. If you want to disable anonymous ciphers even at the "encrypt" security level, set "smtp_tls_mandatory_exclude_ciphers = aNULL"; and to disable anonymous ciphers even with opportunistic TLS, set "smtp_tls_exclude_ciphers = aNULL". There is generally no need to take these measures. Anonymous ciphers save bandwidth and TLS session cache space, if certificates are ignored, there is little point in requesting them. The "smtp_tls_ciphers" configuration parameter (Postfix 2.6) provides control over the minimum cipher grade for opportunistic TLS. With Postfix < 2.6, the minimum opportunistic TLS cipher grade is always "export". With mandatory TLS encryption, the Postfix SMTP client will by default only use SSLv3 or TLSv1. SSLv2 is only used when TLS encryption is optional. The mandatory TLS protocol list is specified via the smtp_tls_mandatory_protocols configuration parameter. The corresponding smtp_tls_protocols parameter (Postfix 2.6) controls the SSL/TLS protocols used with opportunistic TLS. Example:
/etc/postfix/main.cf: smtp_tls_mandatory_ciphers = medium smtp_tls_mandatory_exclude_ciphers = RC4, MD5 smtp_tls_exclude_ciphers = aNULL smtp_tls_mandatory_protocols = SSLv3, TLSv1 # Also available with Postfix 2.5: smtp_tls_mandatory_protocols = !SSLv2 # Also available with Postfix 2.6: smtp_tls_ciphers = export smtp_tls_protocols = !SSLv2

Client-side SMTPS support


Although the Postfix SMTP client by itself doesn't support TLS wrapper mode, it is relatively easy to forward a connection through the stunnel program if Postfix needs to deliver mail to some legacy system that doesn't support STARTTLS. Use one of the following two examples, to send only some remote mail, or to send all remote mail, to an SMTPS server. Sending all remote mail to an SMTPS server The first example uses SMTPS to send all remote mail to a provider's mail server called "mail.example.com". A minimal stunnel.conf file is sufficient to set up a tunnel from local port 11125 to the remote destination "mail.example.com" and port "smtps". Postfix will later use this tunnel to connect to the remote server.

/path/to/stunnel.conf: [smtp-tls-wrapper] accept = 11125 client = yes connect = mail.example.com:smtps

To test this tunnel, use:


$ telnet localhost 11125

This should produce the greeting from the remote SMTP server at mail.example.com. On the Postfix side, the relayhost feature sends all remote mail through the local stunnel listener on port 11125:
/etc/postfix/main.cf: relayhost = [127.0.0.1]:11125

Use "postfix reload" to make the change effective. Sending only mail for a specific destination via SMTPS The second example will use SMTPS to send only mail for "example.com" via SMTPS. It uses the same stunnel configuration file as the first example, so it won't be repeated here. This time, the Postfix side uses a transport map to direct only mail for "example.com" through the tunnel:
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport /etc/postfix/transport: example.com relay:[127.0.0.1]:11125

Use "postmap hash:/etc/postfix/transport" and "postfix reload" to make the change effective.

Miscellaneous client controls


The smtp_starttls_timeout parameter limits the time of Postfix SMTP client write and read operations during TLS startup and shutdown handshake procedures. In case of problems the Postfix SMTP client tries the next network address on the mail exchanger list, and defers delivery if no alternative server is available. Example:
/etc/postfix/main.cf: smtp_starttls_timeout = 300s

TLS manager specific settings


The security of cryptographic software such as TLS depends critically on the ability to generate unpredictable numbers for keys and other information. To this end, the tlsmgr(8) process maintains a Pseudo Random Number Generator (PRNG) pool. This is queried by the smtp(8) and smtpd(8) processes when they initialize. By default, these daemons request 32 bytes, the equivalent to 256 bits. This is more than sufficient to generate a 128bit (or 168bit) session key. Example:
/etc/postfix/main.cf:

tls_daemon_random_bytes = 32

In order to feed its in-memory PRNG pool, the tlsmgr(8) reads entropy from an external source, both at startup and during run-time. Specify a good entropy source, like EGD or /dev/urandom; be sure to only use non-blocking sources (on OpenBSD, use /dev/arandom when tlsmgr(8) complains about /dev/urandom timeout errors). If the entropy source is not a regular file, you must prepend the source type to the source name: "dev:" for a device special file, or "egd:" for a source with EGD compatible socket interface. Examples (specify only one in main.cf):
/etc/postfix/main.cf: tls_random_source = dev:/dev/urandom tls_random_source = egd:/var/run/egd-pool

By default, tlsmgr(8) reads 32 bytes from the external entropy source at each seeding event. This amount (256bits) is more than sufficient for generating a 128bit symmetric key. With EGD and device entropy sources, the tlsmgr(8) limits the amount of data read at each step to 255 bytes. If you specify a regular file as entropy source, a larger amount of data can be read. Example:
/etc/postfix/main.cf: tls_random_bytes = 32

In order to update its in-memory PRNG pool, the tlsmgr(8) queries the external entropy source again after a pseudo-random amount of time. The time is calculated using the PRNG, and is between 0 and the maximal time specified with tls_random_reseed_period. The default maximal time interval is 1 hour. Example:
/etc/postfix/main.cf: tls_random_reseed_period = 3600s

The tlsmgr(8) process saves the PRNG state to a persistent exchange file at regular times and when the process terminates, so that it can recover the PRNG state the next time it starts up. This file is created when it does not exist. Examples:
/etc/postfix/main.cf: tls_random_exchange_name = /var/lib/postfix/prng_exch tls_random_prng_update_period = 3600s

As of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non-Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. If you wish to continue using a pre-existing PRNG state file, move it to the data_directory and change the ownership to the account specified with the mail_owner parameter. With earlier Postfix versions the default file location is under the Postfix configuration directory, which is not the proper place for information that is modified by Postfix.

Getting started, quick and dirty


The following steps will get you started quickly. Because you sign your own Postfix public key certificate, you get TLS encryption but no TLS authentication. This is sufficient for testing, and for exchanging email with sites that you have no trust relationship with. For real authentication, your

Postfix public key certificate needs to be signed by a recognized Certificate Authority, and Postfix needs to be configured with a list of public key certificates of Certificate Authorities, so that Postfix can verify the public key certificates of remote hosts. In the examples below, user input is shown in bold font, and a "#" prompt indicates a super-user shell. Become your own Certificate Authority, so that you can sign your own public keys. This example uses the CA.pl script that ships with OpenSSL. By default, OpenSSL installs this as /usr/local/ssl/misc/CA.pl, but your mileage may vary. The script creates a private key in ./demoCA/private/cakey.pem and a public key in ./demoCA/cacert.pem.
% /usr/local/ssl/misc/CA.pl -newca CA certificate filename (or enter to create) Making CA certificate ... Using configuration from /etc/ssl/openssl.cnf Generating a 1024 bit RSA private key ....................++++++ .....++++++ writing new private key to './demoCA/private/cakey.pem' Enter PEM pass phrase:whatever

Create an unpassworded private key for host foo.porcupine.org and create an unsigned public key certificate.
% openssl req -new -nodes -keyout foo-key.pem -out foo-req.pem -days 365 Using configuration from /etc/ssl/openssl.cnf Generating a 1024 bit RSA private key ........................................++++++ ....++++++ writing new private key to 'foo-key.pem' ----You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:New York Locality Name (eg, city) []:Westchester Organization Name (eg, company) [Internet Widgits Pty Ltd]:Porcupine Organizational Unit Name (eg, section) []: Common Name (eg, YOUR name) []:foo.porcupine.org Email Address []:wietse@porcupine.org Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:whatever An optional company name []:

Sign the public key certificate for host foo.porcupine.org with the Certification Authority private key that we created a few steps ago.

% openssl ca -out foo-cert.pem -infiles foo-req.pem Using configuration from /etc/ssl/openssl.cnf Enter PEM pass phrase:whatever Check that the request matches the signature Signature ok The Subjects Distinguished Name is as follows countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'New York' localityName :PRINTABLE:'Westchester' organizationName :PRINTABLE:'Porcupine' commonName :PRINTABLE:'foo.porcupine.org' emailAddress :IA5STRING:'wietse@porcupine.org' Certificate is to be certified until Nov 21 19:40:56 2005 GMT (365 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated

Install the host private key, the host public key certificate, and the Certification Authority certificate files. This requires super-user privileges.
# cp demoCA/cacert.pem foo-key.pem foo-cert.pem /etc/postfix # chmod 644 /etc/postfix/foo-cert.pem /etc/postfix/cacert.pem # chmod 400 /etc/postfix/foo-key.pem

Configure Postfix, by adding the following to /etc/postfix/main.cf . It is generally best to not configure client certificates, unless there are servers which authenticate your mail submission via client certificates. Often servers that perform TLS client authentication will issue the required certificates signed by their own CA. If you configure the client certificate and key incorrectly, you will be unable to send mail to sites that request client certificate, but don't require them from all clients.
/etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/cacert.pem smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_tls_session_cache smtp_tls_security_level = may smtpd_tls_CAfile = /etc/postfix/cacert.pem smtpd_tls_cert_file = /etc/postfix/foo-cert.pem smtpd_tls_key_file = /etc/postfix/foo-key.pem smtpd_tls_received_header = yes smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_session_cache tls_random_source = dev:/dev/urandom # Postfix 2.3 and later smtpd_tls_security_level = may # Obsolete, but still supported smtpd_use_tls = yes

Reporting problems
Problems are preferably reported via <postfix-users@postfix.org>. See http://www.postfix.org/lists.html for subscription information. When reporting a problem, please be thorough in the report. Patches, when possible, are greatly appreciated too.

Credits
TLS support for Postfix was originally developed by Lutz Jnicke at Cottbus Technical University. Wietse Venema adopted the code, did some restructuring, and compiled this part of the documentation from Lutz's documents. Victor Duchovni was instrumental with the re-implementation of the smtp_tls_per_site code in terms of enforcement levels, which simplified the implementation greatly. Victor Duchovni implemented the fingerprint security level, added more sanity checks, and separated TLS connection management from security policy enforcement. The latter change simplified the code that verifies certificate signatures, certificate names, and certificate fingerprints.

Managing multiple Postfix instances on a single host


Overview
This document is a guide to managing multiple Postfix instances on a single host using the postmulti(1) instance manager. Multi-instance support is available with Postfix version 2.6 and later. See the postfix-wrapper(5) manual page for background on the instance management framework, and on how to deploy a custom instance manager. Topics covered in this document: Why multiple Postfix instances Null-client instances versus service instances Multi-instance walk-through Components of a Postfix system The default Postfix instance Instance groups Multi-instance configuration parameters Using the postmulti(1) command Credits

Why multiple Postfix instances


Postfix is a general-purpose mail system that can be configured to serve a variety of needs. Examples of Postfix applications are: Local mail submission for shell users and system processes. Incoming (MX host) email from the Internet. Outbound mail relay for a corporate network. Authenticated submission for roaming users. Before/after content-filter mail. A single Postfix configuration can provide many or all of these services, but a complex interplay of settings may be required, for example with master.cf options overriding main.cf settings. In this document we take the view that multiple Postfix instances may be a simpler way to configure a multi-function Postfix system. With multiple Postfix instances, each instance has its own directories for configuration, queue and data files, but it shares all Postfix program and documentation files with other instances. Since there is no single right way to configure your system, we recommend that you choose what makes you most comfortable. If different Postfix services don't involve incompatible main.cf or master.cf settings, and if they can be combined together without complex tricks, then a single monolithic configuration may be the simplest approach.

The purpose of multi-instance support in Postfix is not to force you to create multiple Postfix instances, but rather to give you a choice. Multiple instances give you the freedom to tune each Postfix instance to a single task that it does well and to combine instances into complete systems. With the introduction of the postmulti(1) utility and the reduction of the per-instance configuration footprint of a secondary Postfix instance to just a main.cf and master.cf file (other files are now in shared locations), we hope that multiple instances will be easier to use than ever before.

Null-client instances versus service instances


In the multi-instance approach to configuring Postfix, the first simplification is with the default local-submission Postfix instance. Most UNIX systems require support for email submission with the sendmail(1) command so that system processes such as cron jobs can send status reports, and so that system users can send email with command-line utilities. Such email can be handled with a null-client Postfix configuration that forwards all mail to a central mail hub. The null client will typically either not run an SMTP listener at all (master_service_disable = inet), or it will listen only on the loopback interface (inet_interfaces = loopback-only). When implementing specialized servers for inbound Internet email, outbound MTAs, internal mail hubs, and so on, we recommend using a null client for local submission and creating single-function secondary Postfix instances to serve the specialized needs. Note: usually, you need to use different "myhostname" settings when you run multiple instances on the same host. Otherwise, there will be false "mail loops back to myself" alarms when one instance tries to send mail into another instance. Typically, the nullclient instance will use the system's hostname, and other instances will use their own dedicated "myhostname" settings. Different names are not needed when instances send mail to each other with a protocol other than SMTP, or with SMTP over a TCP port other than 25 as is usual with SMTP-based content filters.

Multi-instance walk-through
Before discussing the fine details of multi-instance operation we first show the steps for creating a border mail server. This server has with a null-client Postfix instance for local submission, an input Postfix instance to receive mail from the Internet, plus an advanced SMTP content-filter and an output Postfix instance to deliver filtered email to its internal destination.

Setting up the null-client Postfix instance


On a border mail hub, while mail from the Internet requires a great deal of scrutiny, locally submitted messages are typically limited to mail from cron jobs and other system services. In this regard the border MTA is not different from other Unix hosts in your environment. For this reason, it will submit locally-generated email to the internal mail hub. We start the construction of the border mail server with the default instance, which will be a local-submission null client:
/etc/postfix/main.cf: # We are mta1.example.com # myhostname = mta1.example.com mydomain = example.com # Flat user-account namespace in example.com: # # user@example.com not user@host.example.com

# myorigin = $mydomain # Postfix 2.6+, disable inet services, specifically disable smtpd(8) # master_service_disable = inet # No local delivery: # mydestination = local_transport = error:5.1.1 Mailbox unavailable alias_database = alias_maps = local_recipient_maps = # Send everything to the internal mailhub # relayhost = [mailhub.example.com] # Indexed table macro: # (use "hash", ... when cdb is not available) # default_database_type = cdb indexed = ${default_database_type}:${config_directory}/ # Expose origin host of mail from "root", ... # smtp_generic_maps = ${indexed}generic # Send messages addressed to "root", ... to the MTA support team # virtual_alias_maps = ${indexed}virtual /etc/postfix/generic: # The smarthost supports "+" addressing (recipient_delimiter = +). # Mail from "root" exposes the origin host, without replies # and bounces going back to the same host. # # On clustered MTAs this file is typically machine-built from # a template file. The build process expands the template into # "mtaadmin+root=mta1" # root mtaadmin+root=mta1 /etc/postfix/virtual: # Caretaker aliases: # root mtaadmin postmaster root

You would typically also add a Makefile, to automatically run postmap(1) commands when source files change. This Makefile also creates a "generic" database when none exists.
/etc/postfix/Makefile: MTAADMIN=mtaadmin all: virtual.cdb generic.cdb generic: Makefile @echo Creating $@ @rm -f $@.tmp

@printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` > $@.tmp @mv $@.tmp generic

%.cdb: % postmap cdb:$<

Construct the "virtual" and "generic" databases (the latter is created by running "make"), then start and test the null-client:
# cd /etc/postfix; make # postfix start # sendmail -i -f root -t <<EOF From: root To: root Subject: test testing EOF

The test message should be delivered the members of the "mtaadmin" address group (or whatever address group you choose) with the following headers:
From: mtaadmin+root=mta1@example.com To: mtadmin+root=mta1@example.com Subject: test

Setting up the "output" Postfix instance


With the null-client instance out of the way, we can create the MTA "output" instance that will deliver filtered mail to the inside network. We add the "output" instance first, because the output instance needs to be up and running before the input instance can be fully tested, and when the system boots, the "output" instance must start before the input instance. We will put the output and input instances into a single instance group named "mta". Just once, when adding the first secondary instance, enable multi-instance support in the default (null-client) instance:
# postmulti -e init

Then create the output instance:


# postmulti -I postfix-out -G mta -e create

The instance configuration directory defaults to /etc/postfix-out, more precisely, the "postfix-out" subdirectory of the parent directory of the default-instance configuration directory. The new instance will be created in a "disabled" state:
/etc/postfix-out/main.cf # # ... "stock" main.cf settings ... # multi_instance_name = postfix-out queue_directory = /var/spool/postfix-out data_directory = /var/lib/postfix-out # multi_instance_enable = no master_service_disable = inet authorized_submit_users =

This instance has a "stock" master.cf file, and its queue and data directories, also named "postfixout", will be located in the same parent directories as the corresponding directories of the default instance (e.g., /var/spool/postfix-out and /var/lib/postfix-out). While this instance is immediately safe to start, it is not yet usefully configured. It needs to be customized to fit the role of a post-filter re-injection SMTP service. Typical additions include:
/etc/postfix-out/master.cf: # Replace default "smtp inet" entry with one listening on port 10026. 127.0.0.1:10026 inet n n smtpd /etc/postfix-out/main.cf # ... # Comment out if you don't use IPv6 internally # inet_protocols = ipv4 inet_interfaces = loopback-only mynetworks_style = host smtpd_authorized_xforward_hosts = $mynetworks # Don't anvil(8) control the re-injection port. # smtpd_client_connection_count_limit = 0 smtpd_client_event_limit_exceptions = $mynetworks # Best practice when inet_interfaces is set, as this is not a # "secondary IP personality" configuration. # smtp_bind_address = 0.0.0.0 # All header rewriting happens upstream # local_header_rewrite_clients = # No local delivery on border gateway # mydestination = alias_maps = alias_database = local_recipient_maps = local_transport = error:5.1.1 Mailbox unavailable # May need a recipient_delimiter for per-user transport lookups: # recipient_delimiter = + # Only one (unrestricted client) # With multiple instances, rarely need "-o param=value" overrides # in master.cf, each instance gets its own main.cf file. # smtpd_recipient_restrictions = permit_mynetworks, reject # Tolerate occasional high latency in the # smtpd_timeout = 1200s content filter.

# Best when empty, with all parent domain matches explicit. # parent_domain_matches_subdomains =

# Use the "relay" transport for inbound mail, and the default # "smtp" transport for outbound mail (bounces, ...). The latter # won't starve the former of delivery agent slots. # relay_domains = example.com, .example.com # With xforward, match the input instance setting, if you # want "yes", set both to "yes". # smtpd_client_port_logging = no # # # # Transport settings ... Message size limit Concurrency tuning for "relay" and "smtp" transport ...

With the "output" configuration in place, enable and start the instance:
1 # postmulti -i postfix-out -x postconf -e \ 2 "master_service_disable =" "authorized_submit_users = root" 3 # postmulti -i postfix-out -e enable 4 # postmulti -i postfix-out -p start

This uses the postmulti(1) command to invoke postconf(1) in the context (MAIL_CONFIG=/etc/postfix-out) of the output instance. Lines 1-2: With "authorized_submit_users = root", the superuser can test the postix-out instance with "postmulti -i postfix-out -x sendmail -bv recipient...", but otherwise local submission remains disabled. Lines 1-2: With "master_service_disable =", the "inet" listeners are re-enabled. Line 3: The output instance is enabled for multi-instance start/stop. Line 4: The output instance is started. Test the output instance by submitting probe messages via "sendmail -bv" and "telnet". For production systems, in-depth configuration tests should be done on a lab system. The simple tests just suggested will only confirm successful deployment of a configuration that should already be known good.

Setting up the content-filter proxy


With the output instance ready, deploy your content-filter proxy. Most proxies will need their own /etc/rc* start/stop script. Some proxies, however, are started on demand by the Postfix spawn(8) service, in which case you need to add the relevant spawn(8) entry to the output instance master.cf file. Configure the proxy to listen on 127.0.0.1:10025 and to re-inject filtered email to 127.0.0.1:10026. Start the proxy service if necessary, then test the proxy via "telnet" or automated SMTP injectors. The proxy should support the following ESMTP features: DSN, 8BITMIME, and XFORWARD. In addition, the proxy should support multiple mail deliveries within an SMTP session.

Setting up the input Postfix instance


The input Postfix instance receives mail from the network and sends it through the content filter. Now we create the input instance, also part of the "mta" instance group:
# postmulti -I postfix-in -G mta -e create

The new instance configuration directory defaults to /etc/postfix-in, more precisely, the "postfix-in" subdirectory of the parent directory of the default-instance configuration directory. The new instance will be created in a "disabled" state:
/etc/postfix-in/main.cf # # ... "stock" main.cf settings ... # multi_instance_name = postfix-in queue_directory = /var/spool/postfix-in data_directory = /var/lib/postfix-in # multi_instance_enable = no master_service_disable = inet authorized_submit_users =

As before, make appropriate changes to main.cf and master.cf to make the instance production ready. Consider setting "soft_bounce = yes" during the first few hours of deployment, so you can iron-out any unexpected "kinks". Manual testing can start with:
/etc/postfix-in/main.cf # Accept only local traffic, but allow impersonation: inet_interfaces = 127.0.0.1 smtpd_authorized_xclient_hosts = 127.0.0.1

This allows you to use the Postfix-specific XCLIENT SMTP command to safely simulate connections from remote systems before any remote systems are able to connect. If the test results look good, revert the above settings to the required production values. Typical settings in the prefilter input instance include:
/etc/postfix-in/main.cf # # ... # # No local delivery on border gateway # mydestination = alias_maps = alias_database = local_recipient_maps = local_transport = error:5.1.1 Mailbox unavailable # Don't rewrite remote headers # local_header_rewrite_clients = # All recipients of not yet filtered email go to the same filter together. # # With multiple instances, the content-filter is specified # via transport settings not the "content_filter" transport # switch override! Here the filter listens on local port 10025. # # If you need to route some users or recipient domains directly to the # output instance bypassing the filter, just define a transport table # with suitable entries. #

default_transport = smtp:[127.0.0.1]:10025 relay_transport = $default_transport virtual_transport = $default_transport transport_maps = # Pass original client log information through the filter. # smtp_send_xforward_command = yes # Avoid splitting the envelope and scanning messages multiple times. # Match the re-injection server's recipient limit. # smtp_destination_recipient_limit = 1000 # Tolerate occasional high latency in the content filter. # smtp_data_done_timeout = 1200s # With xforward, match the output instance setting, if you # want "yes", set both to "yes". # smtpd_client_port_logging = no # ... Lots of settings for inbound MX host ...

With the "input" instance configured, enable and start it:


# postmulti -i postfix-in -x postconf -e \ "master_service_disable =" "authorized_submit_users = root" # postmulti -i postfix-in -e enable # postmulti -i postfix-in -p start

That's it. You now have a 3-instance configuration. A null-client sending all locally submitted mail to the internal mail hub and a pair of "mta" instances that receive mail from the Internet, pass it through a content-filter, and then deliver it to the internal destination. Running "postfix start" or "postfix stop" will now start/stop all three Postfix instances. You can use "postfix -c /config/path start" to start just one instance, or use the instance name (or instance group name) via postmulti(1):
# # # # # postmulti postmulti postmulti postmulti ... -i -g -i -i - -p stop mta -p status postfix-out -p flush postfix-in -p reload

This example ends the multi-instance "walk through". The remainder of this document provides background information on Postfix multi-instance support features and options.

Components of a Postfix system


A Postfix system consists of the following components: Shared among all instances: Command-line utilities for administrators and users installed in $command_directory, $sendmail_path, $mailq_path and $newaliases_path. Daemon executables, and run-time support files installed in $daemon_directory.

Bundled documentation, installed in $html_directory, $manpage_directory and $readme_directory. Entries in /etc/passwd and /etc/group for the $mail_owner user and $setgid_group group. The the $mail_owner user provides the mail system with a protected (non-root) execution context. The $setgid_group group is used exclusively to support the setgid postdrop(1) and postqueue(1) utilities (it must not be the primary group or secondary group of any users, including the $mail_owner user). Private to each instance: The main.cf, master.cf (and other optional) configuration files in $config_directory. The maildrop, incoming, active, deferred and hold queues in $queue_directory (which contains additional directories needed by Postfix, and which optionally doubles as a chroot jail for Postfix daemon processes). Various caches (TLS session, address verification, ...) in $data_directory. The Postfix configuration parameters mentioned above are collectively referred to as "installation parameters". Their default values are set when the Postfix software is built from source, and all but one may be optionally set to a non-default value via the main.cf file. The one parameter that (catch22) cannot be set in main.cf is $config_directory, as this defines the location of the main.cf file itself. Though config_directory cannot be set in main.cf, postfix(1) and most of the other command-line Postfix utilities allow you to specify a non-default configuration directory via a command line option (typically -c) or via the MAIL_CONFIG environment variable. In this way, it is possible to have multiple configuration directories on the same machine, and to have multiple running master(8) daemons each with its own configuration files, queue directory and data directory. These multiple running copies of master(8) share the base Postfix software. They do not (and cannot) share their configuration directories, queue directories or data directories. Each combination of configuration directory, together with the queue directory and data directory (specified in the corresponding main.cf file) make up a Postfix instance.

The default Postfix instance


One Postfix instance is special: this is the instance whose configuration directory is the default one compiled into the Postfix utilities. The location of the default configuration directory is typically /etc/postfix, and can be queried via the "postconf -d config_directory" command. We call the instance with this configuration directory the "default instance". The default instance is responsible for local mail submission. The setgid postdrop(1) utility is used by the sendmail(1) local submission program to spool messages into the maildrop sub-directory of the queue directory of the default instance. Even in the rare case when "sendmail -C" is used to submit local mail into a non-default Postfix instance, for security reasons, postdrop(1) will consult the default main.cf file to check the validity of the requested non-default configuration directory. So, while in most other respects, all instances are equal, the default instance is "more equal than others". You may choose to create additional instances, but you must have at least the default instance, with its configuration directory in the default compiled-in location.

Instance groups
The postmulti(1) multi-instance manager supports the notion of an instance "group". Typically, the member instances of an instance group constitute a logical service, and are expected to all be running or all be stopped. In many cases a single Postfix instance will be a complete logical "service". You should define such instances as stand-alone instances that are not members of any instance "group". The null-client instance is an example of a non-group instance. When a logical service consists of multiple Postfix instances, often a pair of pre-filter and post-filter instances with a content filter proxy between them, the related instances should be members of a single instance group (however, the content filter usually has its own start/stop procedure that is separate from any Postfix instance). The default instance main.cf file's $multi_instance_directories configuration parameter lists the configuration directories of all secondary (non-default) instances. Together with the default instance, these secondary instances are managed by the multi-instance manager. Instances are started in the order listed, and stopped in the opposite order. For instances that are members of a service "group", you should arrange to start the service back-to-front, with the output stages started and ready to receive mail before the input stages are started.

Multi-instance configuration parameters


multi_instance_wrapper This default-instance configuration parameter must be set to a suitable multi-instance manager's "wrapper" program that controls the starting, stopping, etc. of a multi-instance Postfix system. To use the postmulti(1) manager described in this document, this parameter should be set with the "postmulti -e init" command. multi_instance_directories This default-instance configuration parameter specifies an optional list of the secondary instances controlled via the multi-instance manager. Instances are listed in their "start" order, with the default instance always started first (if enabled). If $multi_instance_directories is left empty, the postfix(1) command runs with multi-instance support turned off, and none of the multi_instance_ configuration parameters will have any effect. Do not assign a non-empty list of secondary instance configuration directories to multi_instance_directories until you have configured a suitable multi_instance_wrapper setting! This is best accomplished via the "postmulti -e init" command. multi_instance_name Each Postfix instance may be assigned a distinct name (with "postfix -e create/import/assign -I name..."). This name can be used with the postmulti(1) command-line utility to perform tasks on the instance by name (rather than the full pathname of its configuration directory). Choose a name that concisely captures the role of the instance (it must start with "postfix-"). It is an error for two instances to have the same $multi_instance_name. You can leave an instance "nameless" by leaving this parameter at the default empty setting. To avoid confusion in your logs, if you don't assign each secondary instance a non-empty (distinct) $multi_instance_name, you should make sure that the $syslog_name setting is

different for each instance. The $syslog_name parameter defaults to $multi_instance_name when the latter is non-empty. If at all possible, the syslog_name should start with "postfix-", this helps log parsers to identify log entries from secondary Postfix instances. multi_instance_group Each Postfix instance may be assigned an "instance group" name (with "postfix -e create/import/assign -G name..."). The default (empty) value of multi_instance_group parameter indicates a stand-alone instance that is not part of any group. The group name can be used with the postmulti(1) command-line utility to perform a task on the members of a group by name. Choose a single-word group name that concisely captures the role of the group. multi_instance_enable This parameter controls whether a Postfix instance will be started by a Postfix multi-instance manager. The default value is "no". The instance can be started explicitly with "postfix -c /path/to/config/directory"; this is useful for testing. When an instance is disabled, the postfix(1) "start" command is replaced by "check". Some postfix(1) commands (such as "stop", "flush", ...) require a running Postfix instance, and skip instances that are disabled. Other postfix(1) commands (such as "status", "set-permissions", "upgrade-configuration", ...) do not require a running Postfix system, and apply to all instances whether enabled or not. The postmulti(1) utility can be used to create (or destroy) instances. It can also be used to "import" or "deport" existing instances into or from the list of managed instances. When using postmulti(1) to manage instances, the above configuration parameters are managed for you automatically. See below.

Using the postmulti(1) command


Initializing the multi-instance manager Listing managed instances Starting or stopping a multi-instance system Ad-hoc multi-instance operations Creating a new Postfix instance Destroying a Postfix instance Importing an existing Postfix instance Deporting a managed Postfix instance Assigning a new name or group name Enabling/disabling managed instances

Initializing the multi-instance manager


Before postmulti(1) is used for the first time, you must install it as the multi_instance_wrapper for your Postfix system and enable multi-instance operation of the default Postfix instance. You can then proceed to add new or existing instances to the multi-instance configuration. This initial installation is accomplished as follows:

# postmulti -e init

This updates the default instance main.cf file as follows:


# Use postmulti(1) as a postfix-wrapper(5) # multi_instance_wrapper = ${command_directory}/postmulti -p -# Configure the default instance to start when in multi-instance mode # multi_instance_enable = yes

If you prefer, you can make these changes by editing the default main.cf directly, or by using "postconf -e".

Listing managed instances


The list of managed instances consists of the default instance and the additional instances whose configuration directories are listed (in start order) under the multi_instance_directories parameter of the default main.cf configuration file. You can list selected instances, groups of instances or all instances by specifying only the instance matching options with the "-l" option. The "-a" option is assumed if no other instance selection options are specified (this behavior changes with the "-e" option). As a special case, even if it has an explicit name, the default instance can always be selected via "-i -".
# postmulti -l -a # postmulti -l -g a_group # postmulti -l -i an_instance

The output is one line per instance (in "postfix start" order): name mta-in msa-in group enabled config_directory mta msa yes yes yes yes yes /etc/postfix /etc/postfix/mta-out /etc/postfix-mta-in /etc/postfix-msa-out /etc/postfix-msa-in

mta-out mta msa-out msa

test no /etc/postfix-test The first line showing the column headings is not part of the output. When either the instance name or the instance group is not set, it is shown as a "-". When selecting an existing instance via the "-i" option, you can always use the full pathname of its configuration directory instead of the instance (short) name. This is the only way to select a nondefault nameless instance. The default instance can be selected via "-i -", whether it has a name or not. To list instances in reverse start order, include the "-R" option together with the instance selection options.

Starting or stopping a multi-instance system


To start, stop, reload, etc. the complete (already configured as above) multi-instance system just use postfix(1) as you would with a single-instance system. The Postfix multi-instance wrapper

framework insulates Postfix init.d start and package upgrade scripts from the details of multiinstance management! The -p option of postmulti(1) turns on postfix(1) compatibility mode. With this option the remaining arguments are exactly those supported by postfix(1), but commands are applied to all instances or all enabled instances as appropriate. As described above, this switch is required when using postmulti(1) as the multi_instance_wrapper. If you want to specify a subset of instances by name, or group name, or run arbitrary commands (not just "postfix stop/start/etc. in the context (MAIL_CONFIG environment variable setting) of a particular instance or group of instances, then you can use the instance-aware postmulti(1) utility directly.

Ad-hoc multi-instance operations


The postmulti(1) command can be used by the administrator to run arbitrary commands in the context of one or more Postfix instances. The most common use-case is stopping or starting a group of Postfix instances:
# # # # # # postmulti postmulti postmulti postmulti postmulti postmulti -g -g -g -g -g -g mygroup mygroup mygroup mygroup mygroup mygroup -p -p -p -p -p -p start flush reload status stop upgrade-configuration

The -p option is essentially a short-hand for a leading postfix command argument, but with appropriate additional options turned on depending on the first argument. In the case of "start", disabled instances are "checked" (postfix check) rather than simply skipped. The resulting command is executed for each candidate instance with the MAIL_CONFIG environment variable set to the configuration directory of the corresponding Postfix instance. The postmulti(1) utility is able to launch commands other than postfix(1), Use the -x option to ask postmulti to execute an ad-hoc command for all instances, a group of instances, or just one instance. With ad-hoc commands the multi_instance_enable parameter is ignored: the command is unconditionally executed for the instances selected via -a, -g or -i. In addition to MAIL_CONFIG, the following instance parameters are exported into the command environment:
command_directory=$command_directory daemon_directory=$daemon_directory config_directory=$config_directory queue_directory=$queue_directory data_directory=$data_directory multi_instance_name=$multi_instance_name multi_instance_group=$multi_instance_group multi_instance_enable=$multi_instance_enable

The config_directory setting is of course the same as MAIL_CONFIG, and is arguably redundant, but leaving it in is less surprising. If you want to skip disabled instances, just check multi_instance_enable environment variable and exit if it is set to "no". The ability to run ad-hoc commands opens up a wealth of additional possibilities: Specify an instance by name rather than configuration directory when using sendmail(1) to send a verification probe:
$ postmulti -i postfix-myinst -x sendmail -bv test@example.net

Display non-default main.cf settings of all Postfix instances. This uses an inline shell script

to package together multiple shell commands to execute for each instance:


$ postmulti -x sh -c 'echo "-- $MAIL_CONFIG"; postconf -n'

Put all mail in enabled member instances of a group on hold:


# postmulti -g group_name -x \ sh -c 'test $multi_instance_enable = yes && postsuper -h ALL'

Show top 10 domains in the deferred queue of all instances:


# postmulti -x sh -c 'echo "-- $MAIL_CONFIG"; qshape deferred | head -12'

Creating a new Postfix instance


The postmulti(1) command can be used to create additional Postfix instances. New instances are created with local submission and all "inet" services disabled via the following non-default parameter settings in the main.cf file:
authorized_submit_users = master_service_disable = inet

The above settings ensure that new instances are safe to start immediately: they will not conflict with inet listeners in existing Postfix instances. They will also not accept any mail until they are fully configured, at which point you can do away with one or both of the above safety measures. The postmulti(1) command encourages a preferred way of organizing the configuration directories, queue directories and data directories of non-default instances. If the default instance settings are:
config_directory = /conf-path/postfix queue_directory = /queue-path/postfix data_directory = /data-path/postfix

A newly-created instance named postfix-myinst will by default have:


multi_instance_enable = no multi_instance_name = postfix-myinst config_directory = /conf-path/postfix-myinst queue_directory = /queue-path/postfix-myinst data_directory = /data-path/postfix-myinst

You can override any of these defaults when creating the instance, but unless you want to spread instance queue directories over multiple file-systems, use the default naming strategy. It keeps the multiple instances organized in a uniform, predictable fashion. When specifying the instance name later, you can refer to it either as "postfix-myinst", or via the full path of the configuration directory. To create a new instance just use the -e create option:
# postmulti -I postfix-myinst -e create

If the new instance is to belong to a group of related instances that implement a single logical service, assign it to a group:
# postmulti -I postfix-myinst -G mygroup -e create

If you want to override the conventional values of the instance installation parameters, specify their

values on the command-line:


# postmulti [-I postfix-myinst] [-G mygroup] -e create \ "config_directory = /path/to/config_directory" \ "queue_directory = /path/to/queue_directory" \ "data_directory = /path/to/data_directory"

A note on the -I and -G options above. These are always used to assign a name or group name to an instance, while the -i and -g options always select existing instances. By default, the configuration directories of newly managed instances are appended to the instance list. You can use the "-i" or "g" or "-a" options to insert the new instance before the specified instance or group, or at the beginning of the instance list (multi_instance_directories parameter of the default instance). If you do specify a name (use "-I" with a name that is not "-") for the new instance, you may omit any of the 3 instance installation parameters whose instance-name based value is acceptable. Otherwise, all three instance installation parameters are required. You should set the "syslog_name" explicitly in the main.cf file of a "nameless" instance, in order to avoid confusion in the mail logs when multiple instances are in use.

Destroying a Postfix instance


If you no longer need an instance, you can destroy it via:
# postmulti -i postfix-myinst -p stop # postmulti -i postfix-myinst -e disable # postmulti -i postfix-myinst -e destroy

The instance must be stopped, disabled and have no queued messages. This is expected to fully delete a just created instance that has never been used. If the instance is not freshly created, files added after the instance was created will remain in the configuration, queue or data directories, in which case the corresponding directory may not be fully removed and a warning to that effect will be displayed. You can complete the destruction of the instance manually by removing any unwanted remnants of the instance-specific "private" directories.

Importing an existing Postfix instance


If you already have an existing secondary Postfix instance that is not yet managed via postmulti(1), you can "import" it into the list of managed instances. If your instance is already using the default configuration directory naming scheme, just specify the corresponding instance name (the multi_instance_name parameter in its configuration file will be adjusted to match this name if necessary):
# postmulti -I postfix-myinst [-G mygroup] -e import

Otherwise, you must specify the location of its configuration directory:


# postmulti [-I postfix-myinst] [-G mygroup] -e import \ "config_directory = /path/of/config_directory"

When the instance is imported, you can assign a name or a group. As with "create", you can control the placement of the new instance in the start order by using "-i", "-g" or "-a" to prepend before the selected instance or instances. An imported instance is usually not multi-instance "enabled", unless it was part of a multi-instance configuration at an earlier time. If it is fully configured and ready to run, don't forget to enable it and if necessary start it. When other enabled instances are already running, new instances need to be started individually when they are first created or imported.

To find out what instances are running, use:


# postfix status

Deporting a managed Postfix instance


You can "deport" an existing instance from the list of managed instances. This does not destroy the instance, rather the instance just becomes a stand-alone Postfix instance not registered with the multi-instance manager. postmulti(1) will refuse to "deport" an instance that is not stopped and disabled.
# postmulti -i postfix-myinst -p stop # postmulti -i postfix-myinst -e disable # postmulti -i postfix-myinst -e deport

Assigning a new name or group name


You can assign a new name or new group to a managed instance. Use "-" as the new value to assign the instance to no group or make it nameless. To specify a nameless secondary instance use the configuration directory path instead of the old name:
# postmulti -i postfix-old [-I postfix-new] [-G newgroup] -e assign

Enabling/disabling managed instances


You can enable or disable a managed instance. As documented in postfix-wrapper(5), disabled instances are skipped with actions that start, stop or control running Postfix instances.
# postmulti -i postfix-myinst -e enable # postmulti -i postfix-myinst -e disable

Credits
Wietse Venema created Postfix, designed and implemented the multi-instance wrapper framework and provided design feedback that made the postmulti(1) utility much more general and useful than originally envisioned. The postmulti(1) utility was developed by Victor Duchovni of Morgan Stanley, who also wrote the initial version of this document.

Postfix Installation From Source Code


1 - Purpose of this document
If you are using a pre-compiled version of Postfix, you should start with BASIC_CONFIGURATION_README and the general documentation referenced by it. INSTALL is only a bootstrap document to get Postfix up and running from scratch with the minimal number of steps; it should not be considered part of the general documentation. This document describes how to build, install and configure a Postfix system so that it can do one of the following: Send mail only, without changing an existing Sendmail installation. Send and receive mail via a virtual host interface, still without any change to an existing Sendmail installation. Run Postfix instead of Sendmail. Topics covered in this document: 1. Purpose of this document 2. Typographical conventions 3. Documentation 4. Building on a supported system 5. Porting Postfix to an unsupported system 6. Installing the software after successful compilation 7. Configuring Postfix to send mail only 8. Configuring Postfix to send and receive mail via virtual interface 9. Running Postfix instead of Sendmail 10.Mandatory configuration file edits 11.To chroot or not to chroot 12.Care and feeding of the Postfix system

2 - Typographical conventions
In the instructions below, a command written as
# command

should be executed as the superuser. A command written as


% command

should be executed as an unprivileged user.

3 - Documentation
Documentation is available as README files (start with the file README_FILES/AAAREADME), as HTML web pages (point your browser to "html/index.html") and as UNIX-style manual pages. You should view the README files with a pager such as more(1) or less(1), because the files use backspace characters in order to produce bold font. To print a README file without backspace characters, use the col(1) command. For example:
% col -bx <file | lpr

In order to view the manual pages before installing Postfix, point your MANPATH environment variable to the "man" subdirectory; be sure to use an absolute path.
% export MANPATH; MANPATH="`pwd`/man:$MANPATH" % setenv MANPATH "`pwd`/man:$MANPATH"

Of particular interest is the postconf(5) manual page that lists all the 500+ configuration parameters. The HTML version of this text makes it easy to navigate around. All Postfix source files have their own built-in manual page. Tools to extract those embedded manual pages are available in the mantools directory.

4 - Building on a supported system


At some point in time, a version of Postfix was supported on: AIX 3.2.5, 4.1.x, 4.2.0, 4.3.x, 5.2 BSD/OS 2.x, 3.x, 4.x Darwin 1.x FreeBSD 2.x, 3.x, 4.x, 5.x HP-UX 9.x, 10.x, 11.x IRIX 5.x, 6.x Linux Debian 1.3.1, 2.x, 3.x Linux RedHat 3.x (January 2004) - 9.x Linux Slackware 3.x, 4.x, 7.x Linux SuSE 5.x, 6.x, 7.x Linux Ubuntu 4.10..7.04 Mac OS X NEXTSTEP 3.x NetBSD 1.x OPENSTEP 4.x OSF1.V3 - OSF1.V5 (Digital UNIX) Reliant UNIX 5.x Rhapsody 5.x SunOS 4.1.4 (March 2007) SunOS 5.4 - 5.10 (Solaris 2.4..10) Ultrix 4.x (well, that was long ago) or something closely resemblant.

4.1 - Getting started


On Solaris, the "make" command and other utilities for software development are in /usr/ccs/bin, so

you MUST have /usr/ccs/bin in your command search path. If these files do not exist, install the development packages first. See the Solaris FAQ item "Which packages do I need to install to support a C compiler?". If you need to build Postfix for multiple architectures, use the "lndir" command to build a shadow tree with symbolic links to the source files. "lndir" is part of X11R6. If at any time in the build process you get messages like: "make: don't know how to ..." you should be able to recover by running the following command from the Postfix top-level directory:
% make -f Makefile.init makefiles

If you copied the Postfix source code after building it on another machine, it is a good idea to cd into the top-level directory and first do this:
% make tidy

This will get rid of any system dependencies left over from compiling the software elsewhere.

4.2 - What compiler to use


To build with GCC, or with the native compiler if people told me that is better for your system, just cd into the top-level Postfix directory of the source tree and type:
% make

To build with a non-default compiler, you need to specify the name of the compiler. Here are a few examples:
% make makefiles CC=/opt/SUNWspro/bin/cc % make % make makefiles CC="/opt/ansic/bin/cc -Ae" % make % make makefiles CC="purify cc" % make (Solaris) (HP-UX)

and so on. In some cases, optimization is turned off automatically.

4.3 - Building with optional extensions


By default, Postfix builds as a mail system with relatively few bells and whistles. Support for thirdparty databases etc. must be configured when Postfix is compiled. The following documents describe how to build Postfix with support for extensions: Postfix extension Berkeley DB database LDAP database MySQL database PostgreSQL database SASL authentication SQLite database Document DB_README LDAP_README Availability Postfix 1.0 Postfix 1.0 Postfix 1.0 Postfix 1.0

MYSQL_README Postfix 1.0 PGSQL_README Postfix 2.0 SASL_README SQLITE_README Postfix 2.8

Perl compatible regular expression PCRE_README

STARTTLS session encryption TLS_README Postfix 2.2 Note: IP version 6 support is compiled into Postfix on operating systems that have IPv6 support. See the IPV6_README file for details.

4.4 - Overriding built-in parameter default settings


All Postfix configuration parameters can be changed by editing a Postfix configuration file, except for one: the parameter that specifies the location of Postfix configuration files. In order to build Postfix with a configuration directory other than /etc/postfix, use:
% make makefiles CCARGS='-DDEF_CONFIG_DIR=\"/some/where\"' % make

IMPORTANT: Be sure to get the quotes right. These details matter a lot. Parameters whose defaults can be specified in this way are: Macro name DEF_COMMAND_DIR DEF_CONFIG_DIR DEF_DAEMON_DIR DEF_DATA_DIR DEF_MAILQ_PATH DEF_HTML_DIR DEF_MANPAGE_DIR DEF_QUEUE_DIR DEF_README_DIR default value for config_directory daemon_directory data_directory mailq_path html_directory typical default /etc/postfix /usr/libexec/postfix /var/lib/postfix /usr/bin/mailq no /usr/bin/newaliases /var/spool/postfix no command_directory /usr/sbin

manpage_directory /usr/local/man queue_directory readme_directory

DEF_NEWALIAS_PATH newaliases_path

DEF_SENDMAIL_PATH sendmail_path /usr/sbin/sendmail Note: the data_directory parameter (for caches and pseudo-random numbers) was introduced with Postfix version 2.5.

4.5 - Support for thousands of processes


The number of connections that Postfix can manage simultaneously is limited by the number of processes that it can run. This number in turn is limited by the number of files and sockets that a single process can open. For example, the Postfix queue manager has a separate connection to each delivery process, and the anvil(8) server has one connection per smtpd(8) process. Postfix version 2.4 and later have no built-in limits on the number of open files or sockets, when compiled on systems that support one of the following: BSD kqueue(2) (FreeBSD 4.1, NetBSD 2.0, OpenBSD 2.9), Solaris 8 /dev/poll, Linux 2.6 epoll(4). With other Postfix versions or operating systems, the number of file descriptors per process is limited by the value of the FD_SETSIZE macro. If you expect to run more than 1000 mail delivery processes, you may need to override the definition of the FD_SETSIZE macro to make select() work correctly:

% make makefiles CCARGS=-DFD_SETSIZE=2048

Warning: the above has no effect on some Linux versions. Apparently, on these systems the FD_SETSIZE value can be changed only by using undocumented interfaces. Currently, that means including <bits/types.h> directly (which is not allowed) and overriding the __FD_SETSIZE macro. Beware, undocumented interfaces can change at any time and without warning. But wait, there is more: none of this will work unless the operating system is configured to handle thousands of connections. See the TUNING_README guide for examples of how to increase the number of open sockets or files.

4.6 - Compiling Postfix, at last


If the command
% make

is successful, then you can proceed to install Postfix (section 6). If the command produces compiler error messages, it may be time to search the web or to ask the postfix-users@postfix.org mailing list, but be sure to search the mailing list archives first. Some mailing list archives are linked from http://www.postfix.org/.

5 - Porting Postfix to an unsupported system


Each system type that Postfix knows is identified by a unique name. Examples: SUNOS5, FREEBSD4, and so on. When porting Postfix to a new system, the first step is to choose a SYSTEMTYPE name for the new system. You must use a name that includes at least the major version of the operating system (such as SUNOS4 or LINUX2), so that different releases of the same system can be supported without confusion. Add a case statement to the "makedefs" shell script in the source code top-level directory that recognizes the new system reliably, and that emits the right system-specific information. Be sure to make the code robust against user PATH settings; if the system offers multiple UNIX flavors (e.g. BSD and SYSV) be sure to build for the native flavor, instead of the emulated one. Add an "#ifdef SYSTEMTYPE" section to the central util/sys_defs.h include file. You may have to invent new feature macro names. Please choose sensible feature macro names such as HAS_DBM or FIONREAD_IN_SYS_FILIO_H. I strongly recommend against using "#ifdef SYSTEMTYPE" in individual source files. While this may look like the quickest solution, it will create a mess when newer versions of the same SYSTEMTYPE need to be supported. You're likely to end up placing "#ifdef" sections all over the source code again.

6 - Installing the software after successful compilation


This text describes how to install Postfix from source code. See the PACKAGE_README file if you are building a package for distribution to other systems.

6.1 - Save existing Sendmail binaries


IMPORTANT: if you are REPLACING an existing Sendmail installation with Postfix, you may need to keep the old sendmail program running for some time in order to flush the mail queue. Some systems implement a mail switch mechanism where different MTAs (Postfix,

Sendmail, etc.) can be installed at the same time, while only one of them is actually being used. Examples of such switching mechanisms are the FreeBSD mailwrapper(8) or the Linux mail switch. In this case you should try to "flip" the switch to "Postfix" before installing Postfix. If your system has no mail switch mechanism, execute the following commands (your sendmail, newaliases and mailq programs may be in a different place):
# # # # mv /usr/sbin/sendmail /usr/sbin/sendmail.OFF mv /usr/bin/newaliases /usr/bin/newaliases.OFF mv /usr/bin/mailq /usr/bin/mailq.OFF chmod 755 /usr/sbin/sendmail.OFF /usr/bin/newaliases.OFF \ /usr/bin/mailq.OFF

6.2 - Create account and groups


Before you install Postfix for the first time you need to create an account and a group: Create a user account "postfix" with a user id and group id that are not used by any other user account. Preferably, this is an account that no-one can log into. The account does not need an executable login shell, and needs no existing home directory. My password and group file entries look like this:
/etc/passwd: postfix:*:12345:12345:postfix:/no/where:/no/shell /etc/group: postfix:*:12345:

Note: there should be no whitespace before "postfix:". Create a group "postdrop" with a group id that is not used by any other user account. Not even by the postfix user account. My group file entry looks like:
/etc/group: postdrop:*:54321:

Note: there should be no whitespace before "postdrop:".

6.3 - Install Postfix


To install or upgrade Postfix from compiled source code, run one of the following commands as the super-user:
# make install # make upgrade (interactive version, first time install) (non-interactive version, for upgrades)

The interactive version ("make install") asks for pathnames for Postfix data and program files, and stores your preferences in the main.cf file. If you don't want Postfix to overwrite non-Postfix "sendmail", "mailq" and "newaliases" files, specify pathnames that end in ".postfix". The non-interactive version ("make upgrade") needs the /etc/postfix/main.cf file from a previous installation. If the file does not exist, use interactive installation ("make install") instead.

6.4 - Configure Postfix


Proceed to the section on how you wish to run Postfix on your particular machine: Send mail only, without changing an existing Sendmail installation (section 7). Send and receive mail via a virtual host interface, still without any change to an existing Sendmail installation (section 8). Run Postfix instead of Sendmail (section 9).

7 - Configuring Postfix to send mail only


If you are going to use Postfix to send mail only, there is no need to change your existing sendmail setup. Instead, set up your mail user agent so that it calls the Postfix sendmail program directly. Follow the instructions in the "Mandatory configuration file edits" in section 10, and review the "To chroot or not to chroot" text in section 11. You MUST comment out the "smtp inet" entry in /etc/postfix/master.cf, in order to avoid conflicts with the real sendmail. Put a "#" character in front of the line that defines the smtpd service:
/etc/postfix/master.cf: #smtp inet n n smtpd

Start the Postfix system:


# postfix start

or, if you feel nostalgic, use the Postfix sendmail command:


# sendmail -bd -qwhatever

and watch your maillog file for any error messages. The pathname is /var/log/maillog, /var/log/mail, /var/log/syslog, or something else. Typically, the pathname is defined in the /etc/syslog.conf file.
% egrep '(reject|warning|error|fatal|panic):' /some/log/file

Note: the most important error message is logged first. Later messages are not as useful. In order to inspect the mail queue, use one of the following commands:
% mailq % sendmail -bp % postqueue -p

See also the "Care and feeding" section 12 below.

8 - Configuring Postfix to send and receive mail via virtual interface


Alternatively, you can use the Postfix system to send AND receive mail while leaving your Sendmail setup intact, by running Postfix on a virtual interface address. Simply configure your mail user agent to directly invoke the Postfix sendmail program. To create a virtual network interface address, study your system ifconfig manual page. The command syntax could be any of:

# ifconfig le0:1 <address> netmask <mask> up # ifconfig en0 alias <address> netmask 255.255.255.255

In the /etc/postfix/main.cf file, I would specify


/etc/postfix/main.cf: myhostname = virtual.host.tld inet_interfaces = $myhostname mydestination = $myhostname

Follow the instructions in the "Mandatory configuration file edits" in section 10, and review the "To chroot or not to chroot" text in section 11. Start the Postfix system:
# postfix start

or, if you feel nostalgic, use the Postfix sendmail command:


# sendmail -bd -qwhatever

and watch your maillog file for any error messages. The pathname is /var/log/maillog, /var/log/mail, /var/log/syslog, or something else. Typically, the pathname is defined in the /etc/syslog.conf file.
% egrep '(reject|warning|error|fatal|panic):' /some/log/file

Note: the most important error message is logged first. Later messages are not as useful. In order to inspect the mail queue, use one of the following commands:
% mailq % sendmail -bp % postqueue -p

See also the "Care and feeding" section 12 below.

9 - Running Postfix instead of Sendmail


Prior to installing Postfix you should save any existing sendmail program files as described in section 6. Be sure to keep the old sendmail running for at least a couple days to flush any unsent mail. To do so, stop the sendmail daemon and restart it as:
# /usr/sbin/sendmail.OFF -q

Note: this is old sendmail syntax. Newer versions use separate processes for mail submission and for running the queue. After you have visited the "Mandatory configuration file edits" section below, you can start the Postfix system with:
# postfix start

or, if you feel nostalgic, use the Postfix sendmail command:


# sendmail -bd -qwhatever

and watch your maillog file for any error messages. The pathname is /var/log/maillog, /var/log/mail, /var/log/syslog, or something else. Typically, the pathname is defined in the /etc/syslog.conf file.

% egrep '(reject|warning|error|fatal|panic):' /some/log/file

Note: the most important error message is logged first. Later messages are not as useful. In order to inspect the mail queue, use one of the following commands:
% mailq % sendmail -bp % postqueue -p

See also the "Care and feeding" section 12 below.

10 - Mandatory configuration file edits


Note: the material covered in this section is covered in more detail in the BASIC_CONFIGURATION_README document. The information presented below is targeted at experienced system administrators.

10.1 - Postfix configuration files


By default, Postfix configuration files are in /etc/postfix. The two most important files are main.cf and master.cf; these files must be owned by root. Giving someone else write permission to main.cf or master.cf (or to their parent directories) means giving root privileges to that person. In /etc/postfix/main.cf, you will have to set up a minimal number of configuration parameters. Postfix configuration parameters resemble shell variables, with two important differences: the first one is that Postfix does not know about quotes like the UNIX shell does. You specify a configuration parameter as:
/etc/postfix/main.cf: parameter = value

and you use it by putting a "$" character in front of its name:


/etc/postfix/main.cf: other_parameter = $parameter

You can use $parameter before it is given a value (that is the second main difference with UNIX shell variables). The Postfix configuration language uses lazy evaluation, and does not look at a parameter value until it is needed at runtime. Whenever you make a change to the main.cf or master.cf file, execute the following command in order to refresh a running mail system:
# postfix reload

10.2 - Default domain for unqualified addresses


First of all, you must specify what domain will be appended to an unqualified address (i.e. an address without @domain.tld). The "myorigin" parameter defaults to the local hostname, but that is probably OK only for very small sites. Some examples (use only one):
/etc/postfix/main.cf: myorigin = $myhostname (send mail as "user@$myhostname")

myorigin = $mydomain

(send mail as "user@$mydomain")

10.3 - What domains to receive locally


Next you need to specify what mail addresses Postfix should deliver locally. Some examples (use only one):
/etc/postfix/main.cf: mydestination = $myhostname, localhost.$mydomain, localhost mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain mydestination = $myhostname

The first example is appropriate for a workstation, the second is appropriate for the mailserver for an entire domain. The third example should be used when running on a virtual host interface.

10.4 - Proxy/NAT interface addresses


The proxy_interfaces parameter specifies all network addresses that Postfix receives mail on by way of a proxy or network address translation unit. You may specify symbolic hostnames instead of network addresses. IMPORTANT: You must specify your proxy/NAT external addresses when your system is a backup MX host for other domains, otherwise mail delivery loops will happen when the primary MX host is down. Example: host behind NAT box running a backup MX host.
/etc/postfix/main.cf: proxy_interfaces = 1.2.3.4 (the proxy/NAT external network address)

10.5 - What local clients to relay mail from


If your machine is on an open network then you must specify what client IP addresses are authorized to relay their mail through your machine into the Internet. The default setting includes all subnetworks that the machine is attached to. This may give relay permission to too many clients. My own settings are:
/etc/postfix/main.cf: mynetworks = 168.100.189.0/28, 127.0.0.0/8

10.6 - What relay destinations to accept from strangers


If your machine is on an open network then you must also specify whether Postfix will forward mail from strangers. The default setting will forward mail to all domains (and subdomains of) what is listed in $mydestination. This may give relay permission for too many destinations. Recommended settings (use only one):
/etc/postfix/main.cf: relay_domains = (do not forward mail from strangers) relay_domains = $mydomain (my domain and subdomains) relay_domains = $mydomain, other.domain.tld, ...

10.7 - Optional: configure a smart host for remote delivery


If you're behind a firewall, you should set up a relayhost. If you can, specify the organizational domain name so that Postfix can use DNS lookups, and so that it can fall back to a secondary MX host when the primary MX host is down. Otherwise just specify a hard-coded hostname. Some examples (use only one):
/etc/postfix/main.cf: relayhost = $mydomain relayhost = [mail.$mydomain]

The form enclosed with [] eliminates DNS MX lookups. By default, the SMTP client will do DNS lookups even when you specify a relay host. If your machine has no access to a DNS server, turn off SMTP client DNS lookups like this:
/etc/postfix/main.cf: disable_dns_lookups = yes

The STANDARD_CONFIGURATION_README file has more hints and tips for firewalled and/or dial-up networks.

10.8 - Create the aliases database


Postfix uses a Sendmail-compatible aliases(5) table to redirect mail for local(8) recipients. Typically, this information is kept in two files: in a text file /etc/aliases and in an indexed file /etc/aliases.db. The command "postconf alias_maps" will tell you the exact location of the text file. First, be sure to update the text file with aliases for root, postmaster and "postfix" that forward mail to a real person. Postfix has a sample aliases file /etc/postfix/aliases that you can adapt to local conditions.
/etc/aliases: root: you postmaster: root postfix: root bin: root etcetera...

Note: there should be no whitespace before the ":". Finally, build the indexed aliases file with one of the following commands:
# newaliases # sendmail -bi

11 - To chroot or not to chroot


Postfix daemon processes can be configured (via master.cf) to run in a chroot jail. The processes run at a fixed low privilege and with access only to the Postfix queue directories (/var/spool/postfix). This provides a significant barrier against intrusion. The barrier is not impenetrable, but every little bit helps. With the exception of Postfix daemons that deliver mail locally and/or that execute non-Postfix commands, every Postfix daemon can run chrooted. Sites with high security requirements should consider to chroot all daemons that talk to the network: the smtp(8) and smtpd(8) processes, and perhaps also the lmtp(8) client. The author's own porcupine.org mail server runs all daemons chrooted that can be chrooted.

The default /etc/postfix/master.cf file specifies that no Postfix daemon runs chrooted. In order to enable chroot operation, edit the file /etc/postfix/master.cf. Instructions are in the file. Note that a chrooted daemon resolves all filenames relative to the Postfix queue directory (/var/spool/postfix). For successful use of a chroot jail, most UNIX systems require you to bring in some files or device nodes. The examples/chroot-setup directory in the source code distribution has a collection of scripts that help you set up Postfix chroot environments on different operating systems. Additionally, you almost certainly need to configure syslogd so that it listens on a socket inside the Postfix queue directory. Examples for specific systems: FreeBSD:
# mkdir -p /var/spool/postfix/var/run # syslogd -l /var/spool/postfix/var/run/log

Linux, OpenBSD:
# mkdir -p /var/spool/postfix/dev # syslogd -a /var/spool/postfix/dev/log

12 - Care and feeding of the Postfix system


Postfix daemon processes run in the background, and log problems and normal activity to the syslog daemon. The names of logfiles are specified in /etc/syslog.conf. At the very least you need something like:
/etc/syslog.conf: mail.err mail.debug /dev/console /var/log/maillog

IMPORTANT: the syslogd will not create files. You must create them before (re)starting syslogd. IMPORTANT: on Linux you need to put a "-" character before the pathname, e.g., -/var/log/maillog, otherwise the syslogd will use more system resources than Postfix does. Hopefully, the number of problems will be small, but it is a good idea to run every night before the syslog files are rotated:
# postfix check # egrep '(reject|warning|error|fatal|panic):' /some/log/file

The first line (postfix check) causes Postfix to report file permission/ownership discrepancies. The second line looks for problem reports from the mail software, and reports how effective the relay and junk mail access blocks are. This may produce a lot of output. You will want to apply some postprocessing to eliminate uninteresting information. The DEBUG_README document describes the meaning of the "warning" etc. labels in Postfix logging.

Postfix Bottleneck Analysis


Purpose of this document
This document is an introduction to Postfix queue congestion analysis. It explains how the qshape(1) program can help to track down the reason for queue congestion. qshape(1) is bundled with Postfix 2.1 and later source code, under the "auxiliary" directory. This document describes qshape(1) as bundled with Postfix 2.4. This document covers the following topics: Introducing the qshape tool Trouble shooting with qshape Example 1: Healthy queue Example 2: Deferred queue full of dictionary attack bounces Example 3: Congestion in the active queue Example 4: High volume destination backlog Postfix queue directories The "maildrop" queue The "hold" queue The "incoming" queue The "active" queue The "deferred" queue Credits

Introducing the qshape tool


When mail is draining slowly or the queue is unexpectedly large, run qshape(1) as the super-user (root) to help zero in on the problem. The qshape(1) program displays a tabular view of the Postfix queue contents. On the horizontal axis, it displays the queue age with fine granularity for recent messages and (geometrically) less fine granularity for older messages. The vertical axis displays the destination (or with the "-s" switch the sender) domain. Domains with the most messages are listed first. For example, in the output below we see the top 10 lines of the (mostly forged) sender domain distribution for captured spam in the "hold" queue:
$ qshape -s hold | head T TOTAL 486 yahoo.com 14 extremepricecuts.net 13 ms35.hinet.net 12 winnersdaily.net 12 hotmail.com 11 worldnet.fr 6 5 10 20 40 80 160 320 640 1280 1280+ 0 0 1 0 0 2 4 20 40 419 0 0 1 0 0 0 0 1 0 12 0 0 0 0 0 0 0 2 0 11 0 0 0 0 0 0 0 0 1 11 0 0 0 0 0 0 0 2 0 10 0 0 0 0 0 0 0 0 1 10 0 0 0 0 0 0 0 0 0 6

ms41.hinet.net osn.de

6 5

0 0

0 0

0 0

0 0

0 0

0 1

0 0

0 0

0 0

6 4

The "T" column shows the total (in this case sender) count for each domain. The columns with numbers above them, show counts for messages aged fewer than that many minutes, but not younger than the age limit for the previous column. The row labeled "TOTAL" shows the total count for all domains. In this example, there are 14 messages allegedly from yahoo.com, 1 between 10 and 20 minutes old, 1 between 320 and 640 minutes old and 12 older than 1280 minutes (1440 minutes in a day). When the output is a terminal intermediate results showing the top 20 domains (-n option) are displayed after every 1000 messages (-N option) and the final output also shows only the top 20 domains. This makes qshape useful even when the deferred queue is very large and it may otherwise take prohibitively long to read the entire deferred queue. By default, qshape shows statistics for the union of both the incoming and active queues which are the most relevant queues to look at when analyzing performance. One can request an alternate list of queues:
$ qshape deferred $ qshape incoming active deferred

this will show the age distribution of the deferred queue or the union of the incoming active and deferred queues. Command line options control the number of display "buckets", the age limit for the smallest bucket, display of parent domain counts and so on. The "-h" option outputs a summary of the available switches.

Trouble shooting with qshape


Large numbers in the qshape output represent a large number of messages that are destined to (or alleged to come from) a particular domain. It should be possible to tell at a glance which domains dominate the queue sender or recipient counts, approximately when a burst of mail started, and when it stopped. The problem destinations or sender domains appear near the top left corner of the output table. Remember that the active queue can accommodate up to 20000 ($qmgr_message_active_limit) messages. To check whether this limit has been reached, use:
$ qshape -s active

(show sender statistics)

If the total sender count is below 20000 the active queue is not yet saturated, any high volume sender domains show near the top of the output. With oqmgr(8) the active queue is also limited to at most 20000 recipient addresses ($qmgr_message_recipient_limit). To check for exhaustion of this limit use:
$ qshape active

(show recipient statistics)

Having found the high volume domains, it is often useful to search the logs for recent messages pertaining to the domains in question.
# Find deliveries to example.com # $ tail -10000 /var/log/maillog | egrep -i ': to=<.*@example\.com>,' |

less # Find messages from example.com # $ tail -10000 /var/log/maillog | egrep -i ': from=<.*@example\.com>,' | less

You may want to drill in on some specific queue ids:


# Find all messages for a specific queue id. # $ tail -10000 /var/log/maillog | egrep ': 2B2173FF68: '

Also look for queue manager warning messages in the log. These warnings can suggest strategies to reduce congestion.
$ egrep 'qmgr.*(panic|fatal|error|warning):' /var/log/maillog

When all else fails try the Postfix mailing list for help, but please don't forget to include the top 10 or 20 lines of qshape(1) output.

Example 1: Healthy queue


When looking at just the incoming and active queues, under normal conditions (no congestion) the incoming and active queues are nearly empty. Mail leaves the system almost as quickly as it comes in or is deferred without congestion in the active queue.
$ qshape TOTAL meri.uwasa.fi

(show incoming and active queue status)


T 5 5 5 10 20 40 80 160 320 640 1280 1280+ 0 0 0 1 0 0 0 1 1 2 0 0 0 1 0 0 0 1 1 2

If one looks at the two queues separately, the incoming queue is empty or perhaps briefly has one or two messages, while the active queue holds more messages and for a somewhat longer time:
$ qshape incoming TOTAL $ qshape active TOTAL meri.uwasa.fi T 5 5 5 10 20 40 80 160 320 640 1280 1280+ 0 0 0 1 0 0 0 1 1 2 0 0 0 1 0 0 0 1 1 2 T 0 5 10 20 40 80 160 320 640 1280 1280+ 0 0 0 0 0 0 0 0 0 0

Example 2: Deferred queue full of dictionary attack bounces


This is from a server where recipient validation is not yet available for some of the hosted domains. Dictionary attacks on the unvalidated domains result in bounce backscatter. The bounces dominate the queue, but with proper tuning they do not saturate the incoming or active queues. The high volume of deferred mail is not a direct cause for alarm.
$ qshape deferred | head T TOTAL 2234 5 10 20 40 80 160 320 640 1280 1280+ 4 2 5 9 31 57 108 201 464 1353

heyhihellothere.com pleazerzoneprod.com groups.msn.com orion.toppoint.de kali.com.cn meri.uwasa.fi gjr.paknet.com.pk aristotle.algonet.se

207 105 63 49 46 44 43 41

0 0 2 0 0 0 1 0

0 0 1 0 0 0 0 0

1 0 2 0 0 0 0 0

1 0 4 1 0 0 1 0

6 0 4 0 1 1 1 0

6 0 14 2 0 0 3 1

8 0 14 4 2 2 3 2

25 5 14 3 6 8 6 11

68 44 8 16 12 11 12 12

92 56 0 23 25 22 16 15

The domains shown are mostly bulk-mailers and all the volume is the tail end of the time distribution, showing that short term arrival rates are moderate. Larger numbers and lower message ages are more indicative of current trouble. Old mail still going nowhere is largely harmless so long as the active and incoming queues are short. We can also see that the groups.msn.com undeliverables are low rate steady stream rather than a concentrated dictionary attack that is now over.
$ qshape -s deferred | head T TOTAL 2193 MAILER-DAEMON 1709 example.com 263 example.org 209 example.net 6 example.edu 3 example.gov 2 example.mil 1 5 10 20 40 80 160 320 640 1280 1280+ 4 4 5 8 33 56 104 205 465 1309 4 4 5 8 33 55 101 198 452 849 0 0 0 0 0 0 0 0 2 261 0 0 0 0 0 1 3 6 11 188 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1

Looking at the sender distribution, we see that as expected most of the messages are bounces.

Example 3: Congestion in the active queue


This example is taken from a Feb 2004 discussion on the Postfix Users list. Congestion was reported with the active and incoming queues large and not shrinking despite very large delivery agent process limits. The thread is archived at: http://groups.google.com/groups? th=636626c645f5bbde Using an older version of qshape(1) it was quickly determined that all the messages were for just a few destinations:
$ qshape

(show incoming and active queue status)


5 0 0 0 0 10 0 0 0 0 20 1 0 0 0 40 1 0 0 0 80 160 320 320+ 42 94 221 1420 0 0 0 0 0 0 0 0 0 0 2 100

T A TOTAL 11775 9996 user.sourceforge.net 7678 7678 lists.sourceforge.net 2313 2313 gzd.gotdns.com 102 0

The "A" column showed the count of messages in the active queue, and the numbered columns showed totals for the deferred queue. At 10000 messages (Postfix 1.x active queue size limit) the active queue is full. The incoming was growing rapidly. With the trouble destinations clearly identified, the administrator quickly found and fixed the problem. It is substantially harder to glean the same information from the logs. While a careful reading of mailq(1) output should yield similar results, it is much harder to gauge the magnitude of the problem by looking at the queue one message at a time.

Example 4: High volume destination backlog


When a site you send a lot of email to is down or slow, mail messages will rapidly build up in the deferred queue, or worse, in the active queue. The qshape output will show large numbers for the destination domain in all age buckets that overlap the starting time of the problem:
$ qshape deferred | head T 5 10 20 40 80 160 320 640 1280 1280+ TOTAL 5000 200 200 400 800 1600 1000 200 200 200 200 highvolume.com 4000 160 160 320 640 1280 1440 0 0 0 0 ...

Here the "highvolume.com" destination is continuing to accumulate deferred mail. The incoming and active queues are fine, but the deferred queue started growing some time between 1 and 2 hours ago and continues to grow. If the high volume destination is not down, but is instead slow, one might see similar congestion in the active queue. Active queue congestion is a greater cause for alarm; one might need to take measures to ensure that the mail is deferred instead or even add an access(5) rule asking the sender to try again later. If a high volume destination exhibits frequent bursts of consecutive connections refused by all MX hosts or "421 Server busy errors", it is possible for the queue manager to mark the destination as "dead" despite the transient nature of the errors. The destination will be retried again after the expiration of a $minimal_backoff_time timer. If the error bursts are frequent enough it may be that only a small quantity of email is delivered before the destination is again marked "dead". In some cases enabling static (not on demand) connection caching by listing the appropriate nexthop domain in a table included in "smtp_connection_cache_destinations" may help to reduce the error rate, because most messages will re-use existing connections. The MTA that has been observed most frequently to exhibit such bursts of errors is Microsoft Exchange, which refuses connections under load. Some proxy virus scanners in front of the Exchange server propagate the refused connection to the client as a "421" error. Note that it is now possible to configure Postfix to exhibit similarly erratic behavior by misconfiguring the anvil(8) service. Do not use anvil(8) for steady-state rate limiting, its purpose is (unintentional) DoS prevention and the rate limits set should be very generous! If one finds oneself needing to deliver a high volume of mail to a destination that exhibits frequent brief bursts of errors and connection caching does not solve the problem, there is a subtle workaround. Postfix version 2.5 and later: In master.cf set up a dedicated clone of the "smtp" transport for the destination in question. In the example below we will call it "fragile". In master.cf configure a reasonable process limit for the cloned smtp transport (a number in the 10-20 range is typical). IMPORTANT!!! In main.cf configure a large per-destination pseudo-cohort failure limit for the cloned smtp transport.
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport fragile_destination_concurrency_failed_cohort_limit = 100 fragile_destination_concurrency_limit = 20 /etc/postfix/transport:

example.com

fragile: chroot n wakeup maxproc command 20 smtp

/etc/postfix/master.cf: # service type private unpriv fragile unix -

See also the documentation for default_destination_concurrency_failed_cohort_limit and default_destination_concurrency_limit. Earlier Postfix versions: In master.cf set up a dedicated clone of the "smtp" transport for the destination in question. In the example below we will call it "fragile". In master.cf configure a reasonable process limit for the transport (a number in the 10-20 range is typical). IMPORTANT!!! In main.cf configure a very large initial and destination concurrency limit for this transport (say 2000).
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport initial_destination_concurrency = 2000 fragile_destination_concurrency_limit = 2000 /etc/postfix/transport: example.com fragile: /etc/postfix/master.cf: # service type private unpriv fragile unix chroot n wakeup maxproc command 20 smtp

See also the documentation for default_destination_concurrency_limit. The effect of this configuration is that up to 2000 consecutive errors are tolerated without marking the destination dead, while the total concurrency remains reasonable (10-20 processes). This trick is only for a very specialized situation: high volume delivery into a channel with multi-error bursts that is capable of high throughput, but is repeatedly throttled by the bursts of errors. When a destination is unable to handle the load even after the Postfix process limit is reduced to 1, a desperate measure is to insert brief delays between delivery attempts. Postfix version 2.5 and later: In master.cf set up a dedicated clone of the "smtp" transport for the problem destination. In the example below we call it "slow". In main.cf configure a short delay between deliveries to the same destination.
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport slow_destination_rate_delay = 1 slow_destination_concurrency_failed_cohort_limit = 100 /etc/postfix/transport: example.com slow: /etc/postfix/master.cf: # service type private unpriv slow unix chroot n wakeup maxproc command smtp

See also the documentation for default_destination_rate_delay.

This solution forces the Postfix smtp(8) client to wait for $slow_destination_rate_delay seconds between deliveries to the same destination. IMPORTANT!! The large slow_destination_concurrency_failed_cohort_limit value is needed. This prevents Postfix from deferring all mail for the same destination after only one connection or handshake error (the reason for this is that non-zero slow_destination_rate_delay forces a per-destination concurrency of 1). Earlier Postfix versions: In the transport map entry for the problem destination, specify a dead host as the primary nexthop. In the master.cf entry for the transport specify the problem destination as the fallback_relay and specify a small smtp_connect_timeout value.
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport /etc/postfix/transport: example.com slow:[dead.host] /etc/postfix/master.cf: # service type private unpriv chroot wakeup slow unix n -o fallback_relay=problem.example.com -o smtp_connect_timeout=1 -o smtp_connection_cache_on_demand=no maxproc command 1 smtp

This solution forces the Postfix smtp(8) client to wait for $smtp_connect_timeout seconds between deliveries. The connection caching feature is disabled to prevent the client from skipping over the dead host.

Postfix queue directories


The following sections describe Postfix queues: their purpose, what normal behavior looks like, and how to diagnose abnormal behavior.

The "maildrop" queue


Messages that have been submitted via the Postfix sendmail(1) command, but not yet brought into the main Postfix queue by the pickup(8) service, await processing in the "maildrop" queue. Messages can be added to the "maildrop" queue even when the Postfix system is not running. They will begin to be processed once Postfix is started. The "maildrop" queue is drained by the single threaded pickup(8) service scanning the queue directory periodically or when notified of new message arrival by the postdrop(1) program. The postdrop(1) program is a setgid helper that allows the unprivileged Postfix sendmail(1) program to inject mail into the "maildrop" queue and to notify the pickup(8) service of its arrival. All mail that enters the main Postfix queue does so via the cleanup(8) service. The cleanup service is responsible for envelope and header rewriting, header and body regular expression checks, automatic bcc recipient processing, milter content processing, and reliable insertion of the message into the Postfix "incoming" queue. In the absence of excessive CPU consumption in cleanup(8) header or body regular expression checks or other software consuming all available CPU resources, Postfix performance is disk I/O bound. The rate at which the pickup(8) service can inject messages into the queue is largely

determined by disk access times, since the cleanup(8) service must commit the message to stable storage before returning success. The same is true of the postdrop(1) program writing the message to the "maildrop" directory. As the pickup service is single threaded, it can only deliver one message at a time at a rate that does not exceed the reciprocal disk I/O latency (+ CPU if not negligible) of the cleanup service. Congestion in this queue is indicative of an excessive local message submission rate or perhaps excessive CPU consumption in the cleanup(8) service due to excessive body_checks, or (Postfix 2.3) high latency milters. Note, that once the active queue is full, the cleanup service will attempt to slow down message injection by pausing $in_flow_delay for each message. In this case "maildrop" queue congestion may be a consequence of congestion downstream, rather than a problem in its own right. Note, you should not attempt to deliver large volumes of mail via the pickup(8) service. High volume sites should avoid using "simple" content filters that re-inject scanned mail via Postfix sendmail(1) and postdrop(1). A high arrival rate of locally submitted mail may be an indication of an uncaught forwarding loop, or a run-away notification program. Try to keep the volume of local mail injection to a moderate level. The "postsuper -r" command can place selected messages into the "maildrop" queue for reprocessing. This is most useful for resetting any stale content_filter settings. Requeuing a large number of messages using "postsuper -r" can clearly cause a spike in the size of the "maildrop" queue.

The "hold" queue


The administrator can define "smtpd" access(5) policies, or cleanup(8) header/body checks that cause messages to be automatically diverted from normal processing and placed indefinitely in the "hold" queue. Messages placed in the "hold" queue stay there until the administrator intervenes. No periodic delivery attempts are made for messages in the "hold" queue. The postsuper(1) command can be used to manually release messages into the "deferred" queue. Messages can potentially stay in the "hold" queue longer than $maximal_queue_lifetime. If such "old" messages need to be released from the "hold" queue, they should typically be moved into the "maildrop" queue using "postsuper -r", so that the message gets a new timestamp and is given more than one opportunity to be delivered. Messages that are "young" can be moved directly into the "deferred" queue using "postsuper -H". The "hold" queue plays little role in Postfix performance, and monitoring of the "hold" queue is typically more closely motivated by tracking spam and malware, than by performance issues.

The "incoming" queue


All new mail entering the Postfix queue is written by the cleanup(8) service into the "incoming" queue. New queue files are created owned by the "postfix" user with an access bitmask (or mode) of 0600. Once a queue file is ready for further processing the cleanup(8) service changes the queue file mode to 0700 and notifies the queue manager of new mail arrival. The queue manager ignores incomplete queue files whose mode is 0600, as these are still being written by cleanup. The queue manager scans the incoming queue bringing any new mail into the "active" queue if the active queue resource limits have not been exceeded. By default, the active queue accommodates at most 20000 messages. Once the active queue message limit is reached, the queue manager stops scanning the incoming (and deferred, see below) queue.

Under normal conditions the incoming queue is nearly empty (has only mode 0600 files), with the queue manager able to import new messages into the active queue as soon as they become available. The incoming queue grows when the message input rate spikes above the rate at which the queue manager can import messages into the active queue. The main factors slowing down the queue manager are disk I/O and lookup queries to the trivial-rewrite service. If the queue manager is routinely not keeping up, consider not using "slow" lookup services (MySQL, LDAP, ...) for transport lookups or speeding up the hosts that provide the lookup service. If the problem is I/O starvation, consider striping the queue over more disks, faster controllers with a battery write cache, or other hardware improvements. At the very least, make sure that the queue directory is mounted with the "noatime" option if applicable to the underlying filesystem. The in_flow_delay parameter is used to clamp the input rate when the queue manager starts to fall behind. The cleanup(8) service will pause for $in_flow_delay seconds before creating a new queue file if it cannot obtain a "token" from the queue manager. Since the number of cleanup(8) processes is limited in most cases by the SMTP server concurrency, the input rate can exceed the output rate by at most "SMTP connection count" / $in_flow_delay messages per second. With a default process limit of 100, and an in_flow_delay of 1s, the coupling is strong enough to limit a single run-away injector to 1 message per second, but is not strong enough to deflect an excessive input rate from many sources at the same time. If a server is being hammered from multiple directions, consider raising the in_flow_delay to 10 seconds, but only if the incoming queue is growing even while the active queue is not full and the trivial-rewrite service is using a fast transport lookup mechanism.

The "active" queue


The queue manager is a delivery agent scheduler; it works to ensure fast and fair delivery of mail to all destinations within designated resource limits. The active queue is somewhat analogous to an operating system's process run queue. Messages in the active queue are ready to be sent (runnable), but are not necessarily in the process of being sent (running). While most Postfix administrators think of the "active" queue as a directory on disk, the real "active" queue is a set of data structures in the memory of the queue manager process. Messages in the "maildrop", "hold", "incoming" and "deferred" queues (see below) do not occupy memory; they are safely stored on disk waiting for their turn to be processed. The envelope information for messages in the "active" queue is managed in memory, allowing the queue manager to do global scheduling, allocating available delivery agent processes to an appropriate message in the active queue. Within the active queue, (multi-recipient) messages are broken up into groups of recipients that share the same transport/nexthop combination; the group size is capped by the transport's recipient concurrency limit. Multiple recipient groups (from one or more messages) are queued for delivery grouped by transport/nexthop combination. The destination concurrency limit for the transports caps the number of simultaneous delivery attempts for each nexthop. Transports with a recipient concurrency limit of 1 are special: these are grouped by the actual recipient address rather than the nexthop, yielding per-recipient concurrency limits rather than per-domain concurrency limits. Perrecipient limits are appropriate when performing final delivery to mailboxes rather than when relaying to a remote server.

Congestion occurs in the active queue when one or more destinations drain slower than the corresponding message input rate. Input into the active queue comes both from new mail in the "incoming" queue, and retries of mail in the "deferred" queue. Should the "deferred" queue get really large, retries of old mail can dominate the arrival rate of new mail. Systems with more CPU, faster disks and more network bandwidth can deal with larger deferred queues, but as a rule of thumb the deferred queue scales to somewhere between 100,000 and 1,000,000 messages with good performance unlikely above that "limit". Systems with queues this large should typically stop accepting new mail, or put the backlog "on hold" until the underlying issue is fixed (provided that there is enough capacity to handle just the new mail). When a destination is down for some time, the queue manager will mark it dead, and immediately defer all mail for the destination without trying to assign it to a delivery agent. In this case the messages will quickly leave the active queue and end up in the deferred queue (with Postfix < 2.4, this is done directly by the queue manager, with Postfix 2.4 this is done via the "retry" delivery agent). When the destination is instead simply slow, or there is a problem causing an excessive arrival rate the active queue will grow and will become dominated by mail to the congested destination. The only way to reduce congestion is to either reduce the input rate or increase the throughput. Increasing the throughput requires either increasing the concurrency or reducing the latency of deliveries. For high volume sites a key tuning parameter is the number of "smtp" delivery agents allocated to the "smtp" and "relay" transports. High volume sites tend to send to many different destinations, many of which may be down or slow, so a good fraction of the available delivery agents will be blocked waiting for slow sites. Also mail destined across the globe will incur large SMTP command-response latencies, so high message throughput can only be achieved with more concurrent delivery agents. The default "smtp" process limit of 100 is good enough for most sites, and may even need to be lowered for sites with low bandwidth connections (no use increasing concurrency once the network pipe is full). When one finds that the queue is growing on an "idle" system (CPU, disk I/O and network not exhausted) the remaining reason for congestion is insufficient concurrency in the face of a high average latency. If the number of outbound SMTP connections (either ESTABLISHED or SYN_SENT) reaches the process limit, mail is draining slowly and the system and network are not loaded, raise the "smtp" and/or "relay" process limits! When a high volume destination is served by multiple MX hosts with typically low delivery latency, performance can suffer dramatically when one of the MX hosts is unresponsive and SMTP connections to that host timeout. For example, if there are 2 equal weight MX hosts, the SMTP connection timeout is 30 seconds and one of the MX hosts is down, the average SMTP connection will take approximately 15 seconds to complete. With a default per-destination concurrency limit of 20 connections, throughput falls to just over 1 message per second. The best way to avoid bottlenecks when one or more MX hosts is non-responsive is to use connection caching. Connection caching was introduced with Postfix 2.2 and is by default enabled on demand for destinations with a backlog of mail in the active queue. When connection caching is in effect for a particular destination, established connections are re-used to send additional messages, this reduces the number of connections made per message delivery and maintains good throughput even in the face of partial unavailability of the destination's MX hosts. If connection caching is not available (Postfix < 2.2) or does not provide a sufficient latency reduction, especially for the "relay" transport used to forward mail to "your own" domains, consider setting lower than default SMTP connection timeouts (1-5 seconds) and higher than default

destination concurrency limits. This will further reduce latency and provide more concurrency to maintain throughput should latency rise. Setting high concurrency limits to domains that are not your own may be viewed as hostile by the receiving system, and steps may be taken to prevent you from monopolizing the destination system's resources. The defensive measures may substantially reduce your throughput or block access entirely. Do not set aggressive concurrency limits to remote domains without coordinating with the administrators of the target domain. If necessary, dedicate and tune custom transports for selected high volume destinations. The "relay" transport is provided for forwarding mail to domains for which your server is a primary or backup MX host. These can make up a substantial fraction of your email traffic. Use the "relay" and not the "smtp" transport to send email to these domains. Using the "relay" transport allocates a separate delivery agent pool to these destinations and allows separate tuning of timeouts and concurrency limits. Another common cause of congestion is unwarranted flushing of the entire deferred queue. The deferred queue holds messages that are likely to fail to be delivered and are also likely to be slow to fail delivery (time out). As a result the most common reaction to a large deferred queue (flush it!) is more than likely counter-productive, and typically makes the congestion worse. Do not flush the deferred queue unless you expect that most of its content has recently become deliverable (e.g. relayhost back up after an outage)! Note that whenever the queue manager is restarted, there may already be messages in the active queue directory, but the "real" active queue in memory is empty. In order to recover the in-memory state, the queue manager moves all the active queue messages back into the incoming queue, and then uses its normal incoming queue scan to refill the active queue. The process of moving all the messages back and forth, redoing transport table (trivial-rewrite(8) resolve service) lookups, and reimporting the messages back into memory is expensive. At all costs, avoid frequent restarts of the queue manager (e.g. via frequent execution of "postfix reload").

The "deferred" queue


When all the deliverable recipients for a message are delivered, and for some recipients delivery failed for a transient reason (it might succeed later), the message is placed in the deferred queue. The queue manager scans the deferred queue periodically. The scan interval is controlled by the queue_run_delay parameter. While a deferred queue scan is in progress, if an incoming queue scan is also in progress (ideally these are brief since the incoming queue should be short), the queue manager alternates between looking for messages in the "incoming" queue and in the "deferred" queue. This "round-robin" strategy prevents starvation of either the incoming or the deferred queues. Each deferred queue scan only brings a fraction of the deferred queue back into the active queue for a retry. This is because each message in the deferred queue is assigned a "cool-off" time when it is deferred. This is done by time-warping the modification time of the queue file into the future. The queue file is not eligible for a retry if its modification time is not yet reached. The "cool-off" time is at least $minimal_backoff_time and at most $maximal_backoff_time. The next retry time is set by doubling the message's age in the queue, and adjusting up or down to lie within the limits. This means that young messages are initially retried more often than old messages. If a high volume site routinely has large deferred queues, it may be useful to adjust the queue_run_delay, minimal_backoff_time and maximal_backoff_time to provide short enough delays on first failure (Postfix 2.4 has a sensibly low minimal backoff time by default), with perhaps longer delays after multiple failures, to reduce the retransmission rate of old messages and

thereby reduce the quantity of previously deferred mail in the active queue. If you want a really low minimal_backoff_time, you may also want to lower queue_run_delay, but understand that more frequent scans will increase the demand for disk I/O. One common cause of large deferred queues is failure to validate recipients at the SMTP input stage. Since spammers routinely launch dictionary attacks from unrepliable sender addresses, the bounces for invalid recipient addresses clog the deferred queue (and at high volumes proportionally clog the active queue). Recipient validation is strongly recommended through use of the local_recipient_maps and relay_recipient_maps parameters. Even when bounces drain quickly they inundate innocent victims of forgery with unwanted email. To avoid this, do not accept mail for invalid recipients. When a host with lots of deferred mail is down for some time, it is possible for the entire deferred queue to reach its retry time simultaneously. This can lead to a very full active queue once the host comes back up. The phenomenon can repeat approximately every maximal_backoff_time seconds if the messages are again deferred after a brief burst of congestion. Perhaps, a future Postfix release will add a random offset to the retry time (or use a combination of strategies) to reduce the odds of repeated complete deferred queue flushes.

Credits
The qshape(1) program was developed by Victor Duchovni of Morgan Stanley, who also wrote the initial version of this document.

Postfix Stress-Dependent Configuration


Overview
This document describes the symptoms of Postfix SMTP server overload. It presents permanent main.cf changes to avoid overload during normal operation, and temporary main.cf changes to cope with an unexpected burst of mail. This document makes specific suggestions for Postfix 2.5 and later which support stress-adaptive behavior, and for earlier Postfix versions that don't. Topics covered in this document: Symptoms of Postfix SMTP server overload Service more SMTP clients at the same time Spend less time per SMTP client Disconnect suspicious SMTP clients Temporary measures for older Postfix releases Automatic stress-adaptive behavior Detecting support for stress-adaptive behavior Forcing stress-adaptive behavior on or off Other measures to off-load zombies Credits

Symptoms of Postfix SMTP server overload


Under normal conditions, the Postfix SMTP server responds immediately when an SMTP client connects to it; the time to deliver mail is noticeable only with large messages. Performance degrades dramatically when the number of SMTP clients exceeds the number of Postfix SMTP server processes. When an SMTP client connects while all Postfix SMTP server processes are busy, the client must wait until a server process becomes available. SMTP server overload may be caused by a surge of legitimate mail (example: a DNS registrar opens a new zone for registrations), by mistake (mail explosion caused by a forwarding loop) or by malice (worm outbreak, botnet, or other illegitimate activity). Symptoms of Postfix SMTP server overload are: Remote SMTP clients experience a long delay before Postfix sends the "220 hostname.example.com ESMTP Postfix" greeting. NOTE: Broken DNS configurations can also cause lengthy delays before Postfix sends "220 hostname.example.com ...". These delays also exist when Postfix is NOT overloaded. NOTE: To avoid "overload" delays for end-user mail clients, enable the "submission" service entry in master.cf (present since Postfix 2.1), and tell users to connect to this instead of the public SMTP service.

The Postfix SMTP server logs an increased number of "lost connection after CONNECT" events. This happens because remote SMTP clients disconnect before Postfix answers the connection. NOTE: A portscan for open SMTP ports can also result in "lost connection ..." logfile messages. Postfix 2.3 and later logs a warning that all server ports are busy:
Oct 3 20:39:27 spike postfix/master[28905]: warning: service "smtp" (25) has reached its process limit "30": new clients may experience noticeable delays Oct 3 20:39:27 spike postfix/master[28905]: warning: to avoid this condition, increase the process count in master.cf or reduce the service time per client

Legitimate mail that doesn't get through during an episode of Postfix SMTP server overload is not necessarily lost. It should still arrive once the situation returns to normal, as long as the overload condition is temporary.

Service more SMTP clients at the same time


One measure to avoid the "all server processes busy" condition is to service more SMTP clients simultaneously. For this you need to increase the number of Postfix SMTP server processes. This will improve the responsiveness for remote SMTP clients, as long as the server machine has enough hardware and software resources to run the additional processes, and as long as the file system can keep up with the additional load. You increase the number of SMTP server processes either by increasing the default_process_limit in main.cf (line 3 below), or by increasing the SMTP server's "maxproc" field in master.cf (line 10 below). Either way, you need to issue a "postfix reload" command to make the change effective. Process limits above 1000 require Postfix version 2.4 or later, and an operating system that supports kernel-based event filters (BSD kqueue(2), Linux epoll(4), or Solaris /dev/poll). More processes use more memory. You can reduce the Postfix memory footprint by using cdb: lookup tables instead of Berkeley DB's hash: or btree: tables.
1 /etc/postfix/main.cf: 2 # Raise the global process limit, 100 since Postfix 2.0. 3 default_process_limit = 200 4 5 /etc/postfix/master.cf: 6 # ============================================================= 7 # service type private unpriv chroot wakeup maxproc command 8 # ============================================================= 9 # Raise the SMTP service process limit only. 10 smtp inet n n 200 smtpd

NOTE: older versions of the SMTPD_POLICY_README document contain a mistake: they configure a fixed number of policy daemon processes. When you raise the SMTP server's "maxproc" field in master.cf, SMTP server processes will report problems when connecting to policy server processes, because there aren't enough of them. Examples of errors are "connection refused" or "operation timed out". To fix, edit master.cf and specify a zero "maxproc" field in all policy server entries; see line 6 in the example below. Issue a "postfix reload" command to make the change effective.

1 /etc/postfix/master.cf: 2 # ============================================================= 3 # service type private unpriv chroot wakeup maxproc command 4 # ============================================================= 5 # Disable the policy service process limit. 6 policy unix n n 0 spawn 7 user=nobody argv=/some/where/policy-server

Spend less time per SMTP client


When increasing the number of SMTP server processes is not practical, you can improve Postfix server responsiveness by eliminating delays. When Postfix spends less time per SMTP session, the same number of SMTP server processes can service more clients in a given amount of time. Eliminate non-functional RBL lookups (blocklists that are no longer in operation). These lookups can degrade performance. Postfix logs a warning when an RBL server does not respond. Eliminate redundant RBL lookups (people often use multiple Spamhaus RBLs that include each other). To find out whether RBLs include other RBLs, look up the websites that document the RBL's policies. Eliminate header_checks and body_checks, and keep just a few emergency patterns to block the latest worm explosion or backscatter mail. See BACKSCATTER_README for examples of the latter. Group your header_checks and body_checks patterns to avoid unnecessary pattern matching operations:
1 /etc/postfix/header_checks: 2 if /^Subject:/ 3 /^Subject: virus found in mail from you/ reject 4 /^Subject: ..other../ reject 5 endif 6 7 if /^Received:/ 8 /^Received: from (postfix\.org) / reject forged client name in received header: $1 9 /^Received: from ..other../ reject .... 10 endif

Disconnect suspicious SMTP clients


Under conditions of overload you can improve Postfix SMTP server responsiveness by hanging up on suspicious clients, so that other clients get a chance to talk to Postfix. Use "521" SMTP reply codes (Postfix 2.6 and later) or "421" (Postfix 2.3-2.5) to hang up on clients that that match botnet-related RBLs (see next bullet) or that match selected non-RBL restrictions such as SMTP access maps. The Postfix SMTP server will reject mail and disconnect without waiting for the remote SMTP client to send a QUIT command. To hang up connections from blacklisted zombies, you can set specific Postfix SMTP server reject codes for specific RBLs, and for individual responses from specific RBLs. We'll use zen.spamhaus.org as an example; by the time you read this document, details may have changed. Right now, their documents say that a response of 127.0.0.10 or 127.0.0.11 indicates a dynamic client IP address, which means that the machine is probably running a bot of some kind. To give a 521 response instead of the default 554 response, use something

like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /etc/postfix/main.cf: smtpd_client_restrictions = permit_mynetworks reject_rbl_client zen.spamhaus.org=127.0.0.10 reject_rbl_client zen.spamhaus.org=127.0.0.11 reject_rbl_client zen.spamhaus.org rbl_reply_maps = hash:/etc/postfix/rbl_reply_maps /etc/postfix/rbl_reply_maps: # With Postfix 2.3-2.5 use "421" to hang up connections. zen.spamhaus.org=127.0.0.10 521 4.7.1 Service unavailable; $rbl_class [$rbl_what] blocked using $rbl_domain${rbl_reason?; $rbl_reason} zen.spamhaus.org=127.0.0.11 521 4.7.1 Service unavailable; $rbl_class [$rbl_what] blocked using $rbl_domain${rbl_reason?; $rbl_reason}

Although the above example shows three RBL lookups (lines 4-6), Postfix will only do a single DNS query, so it does not affect the performance. With Postfix 2.3-2.5, use reply code 421 (521 will not cause Postfix to disconnect). The down-side of replying with 421 is that it works only for zombies and other malware. If the client is running a real MTA, then it may connect again several times until the mail expires in its queue. When this is a problem, stick with the default 554 reply, and use "smtpd_hard_error_limit = 1" as described below. You can automatically turn on the above overload measure with Postfix 2.5 and later, or with earlier releases that contain the stress-adaptive behavior source code patch from the mirrors listed at http://www.postfix.org/download.html. Simply replace line above 8 with:
8 rbl_reply_maps = ${stress?hash:/etc/postfix/rbl_reply_maps}

More information about automatic stress-adaptive behavior is in section "Automatic stress-adaptive behavior".

Temporary measures for older Postfix releases


See the next section, "Automatic stress-adaptive behavior", if you are running Postfix version 2.5 or later, or if you have applied the source code patch for stress-adaptive behavior from the mirrors listed at http://www.postfix.org/download.html. The following measures can be applied temporarily during overload. They still allow most legitimate clients to connect and send mail, but may affect some legitimate clients. Reduce smtpd_timeout (default: 300s). Experience on the postfix-users list from a variety of sysadmins shows that reducing the "normal" smtpd_timeout to 60s is unlikely to affect legitimate clients. However, it is unlikely to become the Postfix default because it's not RFC compliant. Setting smtpd_timeout to 10s (line 2 below) or even 5s under stress will still allow most legitimate clients to connect and send mail, but may delay mail from some clients. No mail should be lost, as long as this measure is used only temporarily. Reduce smtpd_hard_error_limit (default: 20). Setting this to 1 under stress (line 3 below) helps by disconnecting clients after a single error, giving other clients a chance to connect. However, this may cause significant delays with legitimate mail, such as a mailing list that contains a few no-longer-active user names that didn't bother to unsubscribe. No mail should

be lost, as long as this measure is used only temporarily. Use an smtpd_junk_command_limit of 1 instead of the default 100. This prevents clients from keeping idle connections open by repeatedly sending NOOP or RSET commands.
1 2 3 4 /etc/postfix/main.cf: smtpd_timeout = 10 smtpd_hard_error_limit = 1 smtpd_junk_command_limit = 1

With these measures, no mail should be lost, as long as these measures are used only temporarily. The next section of this document introduces a way to automate this process.

Automatic stress-adaptive behavior


Postfix version 2.5 introduces automatic stress-adaptive behavior. This is also available as a source code patch for Postfix versions 2.4 and 2.3 from the mirrors listed at http://www.postfix.org/download.html. It works as follows. When a "public" network service such as the SMTP server runs into an "all server ports are busy" condition, the Postfix master(8) daemon logs a warning, restarts the service (without interrupting existing network sessions), and runs the service with "-o stress=yes" on the server process command line:
80821 ?? S 0:00.24 smtpd -n smtp -t inet -u -c -o stress=yes

Normally, the Postfix master(8) daemon runs such a service with "-o stress=" on the command line (i.e. with an empty parameter value):
83326 ?? S 0:00.28 smtpd -n smtp -t inet -u -c -o stress=

Services that have local access only never have "-o stress" parameters on the command line. This includes services internal to Postfix such as the queue manager, and services that listen on a loopback interface only, such as after-filter SMTP services. The "stress" parameter value is the key to making main.cf parameter settings stress adaptive. The following settings are the default with Postfix 2.6 and later. With earlier Postfix versions that have stress-adaptive support, append the lines below to the main.cf file and issue a "postfix reload" command:
1 smtpd_timeout = ${stress?10}${stress:300}s 2 smtpd_hard_error_limit = ${stress?1}${stress:20} 3 smtpd_junk_command_limit = ${stress?1}${stress:100}

Translation: Line 1: under conditions of stress, use an smtpd_timeout value of 10 seconds instead of the default 300 seconds. Experience on the postfix-users list from a variety of sysadmins shows that reducing the "normal" smtpd_timeout to 60s is unlikely to affect legitimate clients. However, it is unlikely to become the Postfix default because it's not RFC compliant. Setting smtpd_timeout to 10s (line 2 below) or even 5s under stress will still allow most legitimate clients to connect and send mail, but may delay mail from some clients. No mail should be lost, as long as this measure is used only temporarily. Line 2: under conditions of stress, use an smtpd_hard_error_limit of 1 instead of the default 20. This helps by disconnecting clients after a single error, giving other clients a chance to connect. However, this may cause significant delays with legitimate mail, such as a mailing list that contains a few no-longer-active user names that didn't bother to unsubscribe. No

mail should be lost, as long as this measure is used only temporarily. Line 3: under conditions of stress, use an smtpd_junk_command_limit of 1 instead of the default 100. This prevents clients from keeping idle connections open by repeatedly sending NOOP or RSET commands. The syntax of ${name?value} and ${name:value} is explained at the beginning of the postconf(5) manual page. NOTE: Please keep in mind that the stress-adaptive feature is a fairly desperate measure to keep some legitimate mail flowing under overload conditions. If a site is reaching the SMTP server process limit when there isn't an attack or bot flood occurring, then either the process limit needs to be raised or more hardware needs to be added.

Detecting support for stress-adaptive behavior


To find out if your Postfix installation supports stress-adaptive behavior, use the "ps" command, and look for the smtpd processes. Postfix has stress-adaptive support when you see "-o stress=" or "-o stress=yes" command-line options. Remember that Postfix never enables stress-adaptive behavior on servers that listen on local addresses only. The following example is for FreeBSD or Linux. On Solaris, HP-UX and other System-V flavors, use "ps -ef" instead of "ps ax".
$ ps ax|grep smtpd 83326 ?? S 0:00.28 smtpd -n smtp -t inet -u -c -o stress= 84345 ?? Ss 0:00.11 /usr/bin/perl /usr/libexec/postfix/smtpdpolicy.pl

You can't use postconf(1) to detect stress-adaptive support. The postconf(1) command ignores the existence of the stress parameter in main.cf, because the parameter has no effect there. Commandline "-o parameter" settings always take precedence over main.cf parameter settings. If you configure stress-adaptive behavior in main.cf when it isn't supported, nothing bad will happen. The processes will run as if the stress parameter always has an empty value.

Forcing stress-adaptive behavior on or off


You can manually force stress-adaptive behavior on, by adding a "-o stress=yes" command-line option in master.cf. This can be useful for testing overrides on the SMTP service. Issue "postfix reload" to make the change effective. Note: setting the stress parameter in main.cf has no effect for services that accept remote connections.
1 /etc/postfix/master.cf: 2 # ============================================================= 3 # service type private unpriv chroot wakeup maxproc command 4 # ============================================================= 5 # 6 smtp inet n n smtpd 7 -o stress=yes 8 -o . . .

To permanently force stress-adaptive behavior off with a specific service, specify "-o stress=" on its master.cf command line. This may be desirable for the "submission" service. Issue "postfix reload" to make the change effective. Note: setting the stress parameter in main.cf has no effect for services that accept remote

connections.
1 /etc/postfix/master.cf: 2 # ============================================================= 3 # service type private unpriv chroot wakeup maxproc command 4 # ============================================================= 5 # 6 submission inet n n smtpd 7 -o stress= 8 -o . . .

Other measures to off-load zombies


OpenBSD spamd implements a daemon that handles all connections from "new" clients. Only wellbehaved mail clients are allowed to talk to the mail server. Other clients are tarpitted, and will never get a chance to affect mail server performance. At some point in the future, Postfix may come with a simple front-end daemon that does basic greylisting and pipelining detection to keep zombies and other ratware away from Postfix itself. This would use the "pass" service type which has been available in stable Postfix releases since Postfix 2.5.

Credits
Thanks to the postfix-users mailing list members for sharing early experiences with the stress-adaptive feature. The RBL example and several other paragraphs of text were adapted from postfix-users postings by Noel Jones. Wietse implemented stress-adaptive behavior as the smallest possible patch while he should be working on other things.

Postfix Performance Tuning


Purpose of Postfix performance tuning
The hints and tips in this document help you improve the performance of Postfix systems that already work. If your Postfix system is unable to receive or deliver mail, then you need to solve those problems first, using the DEBUG_README document as guidance. For tuning external content filter performance, first read the respective information in the FILTER_README and SMTPD_PROXY_README documents. Then make sure to avoid latency in the content filter code. As much as possible avoid performing queries against external data sources with a high or highly variable delay. Your content filter will run with a small concurrency to avoid CPU/memory starvation, and if any latency creeps in, content filter throughput will suffer. High volume environments should avoid RBL lookups, complex database queries and so on. Topics on mail receiving performance: General mail receiving performance tips Doing more work with your SMTP server processes Slowing down SMTP clients that make many errors Measures against clients that make too many connections General mail delivery performance tips Tuning the frequency of deferred mail delivery attempts Tuning the number of simultaneous deliveries Tuning the number of recipients per delivery

Topics on mail delivery performance:

Other Postfix performance tuning topics: Tuning the number of Postfix processes Tuning the number of processes on the system Tuning the number of open files or sockets The following tools can be used to measure mail system performance under artificial loads. They are normally not installed with Postfix. smtp-source, SMTP/LMTP message generator smtp-sink, SMTP/LMTP message dump qmqp-source, QMQP message generator qmqp-sink, QMQP message dump

General mail receiving performance tips


Read and understand the maildrop queue, incoming queue, and active queue discussions in the QSHAPE_README document. Run a local name server to reduce slow-down due to DNS lookups. If you run multiple Postfix systems, point each local name server to a shared forwarding server to reduce the

number of lookups across the upstream network link. Eliminate unnecessary LDAP lookups, by specifying a domain filter. This eliminates lookups for addresses in remote domains, and eliminates lookups of partial addresses. See ldap_table(5) for details. When Postfix responds slowly to SMTP clients: Look for obvious signs of trouble as described in the DEBUG_README document, and eliminate those problems first. Turn off your header_checks and body_checks patterns and see if the problem goes away. Turn off chroot operation as described in the DEBUG_README document and see if the problem goes away. If Postfix logs the SMTP client as "unknown" then you have a name service problem: the name server is bad, or the resolv.conf file contains bad information, or some packet filter is blocking the DNS requests or replies. If the number of smtpd(8) processes has reached the process limit as specified in master.cf, new SMTP clients must wait until a process becomes available. Increase the number of processes if memory permits. See the instructions given under "Tuning the number of Postfix processes".

Doing more work with your SMTP server processes


With Postfix versions 2.0 and earlier, the smtpd(8) server pauses before reporting an error to an SMTP client. The idea is called tar pitting. However, these delays also slow down Postfix. When the smtpd(8) server replies slowly, sessions take more time, so that more smtpd(8) server processes are needed to handle the load. When your Postfix smtpd(8) server process limit is reached, new clients must wait until a server process becomes available. This means that all clients experience poor performance. You can speed up the handling of smtpd(8) server error replies by turning off the delay:
/etc/postfix/main.cf: # Not needed with Postfix 2.1 smtpd_error_sleep_time = 0

With the above setting, Postfix 2.0 and earlier can serve more SMTP clients with the same number SMTP server processes. The next section describes how Postfix deals with clients that make a large number of errors.

Slowing down SMTP clients that make many errors


The Postfix smtpd(8) server maintains a per-session error count. The error count is reset when a message is transferred successfully, and is incremented when a client request is unrecognized or unimplemented, when a client request violates access restrictions, or when some other error happens. As the per-session error count increases, the smtpd(8) server changes behavior and begins to insert delays into the responses. The idea is to slow down a run-away client in order to limit resource usage. The behavior is Postfix version dependent. IMPORTANT: These delays slow down Postfix, too. When too much delay is configured, the number of simultaneous SMTP sessions will increase until it reaches the smtpd(8) server process limit, and new SMTP clients must wait until an smtpd(8) server process becomes available.

Postfix version 2.1 and later: When the error count reaches $smtpd_soft_error_limit (default: 10), the Postfix smtpd(8) server delays all non-error and error responses by $smtpd_error_sleep_time seconds (default: 1 second). When the error count reaches $smtpd_hard_error_limit (default: 20) the Postfix smtpd(8) server breaks the connection. Postfix version 2.0 and earlier: When the error count is less than $smtpd_soft_error_limit (default: 10) the Postfix smtpd(8) server delays all error replies by $smtpd_error_sleep_time (1 second with Postfix 2.0, 5 seconds with Postfix 1.1 and earlier). When the error count reaches $smtpd_soft_error_limit, the Postfix smtpd(8) server delays all responses by "error count" seconds or $smtpd_error_sleep_time, whichever is more. When the error count reaches $smtpd_hard_error_limit (default: 20) the Postfix smtpd(8) server breaks the connection.

Measures against clients that make too many connections


Note: these features use the Postfix anvil(8) service, introduced with Postfix version 2.2. The Postfix smtpd(8) server can limit the number of simultaneous connections from the same SMTP client, as well as the connection rate and the rate of certain SMTP commands from the same client. These statistics are maintained by the anvil(8) server (translation: if anvil(8) breaks, then connection limits stop working). IMPORTANT: These limits must not be used to regulate legitimate traffic: mail will suffer grotesque delays if you do so. The limits are designed to protect the smtpd(8) server against abuse by out-of-control clients. smtpd_client_connection_count_limit (default: 50) The maximum number of connections that an SMTP client may make simultaneously. smtpd_client_connection_rate_limit (default: no limit) The maximum number of connections that an SMTP client may make in the time interval specified with anvil_rate_time_unit (default: 60s). smtpd_client_message_rate_limit (default: no limit) The maximum number of message delivery requests that an SMTP client may make in the time interval specified with anvil_rate_time_unit (default: 60s). smtpd_client_recipient_rate_limit (default: no limit) The maximum number of recipient addresses that an SMTP client may specify in the time interval specified with anvil_rate_time_unit (default: 60s). smtpd_client_new_tls_session_rate_limit (default: no limit)

The maximum number of new TLS sessions (without using the TLS session cache) that an SMTP client may negotiate in the time interval specified with anvil_rate_time_unit (default: 60s). smtpd_client_event_limit_exceptions (default: $mynetworks) SMTP clients that are excluded from connection and rate limits specified above.

General mail delivery performance tips


Read and understand the maildrop queue, incoming queue, active queue and deferred queue discussions in the QSHAPE_README document. In case of slow delivery, run the qshape tool as described in the QSHAPE_README document. Submit multiple recipients per message instead of submitting messages with only a few recipients. Submit mail via SMTP instead of /usr/sbin/sendmail. You may have to adjust the smtpd_recipient_limit parameter setting. Don't overwhelm the disk with mail submissions. Optimize the mail submission rate by tuning the number of parallel submissions and/or by tuning the Postfix in_flow_delay parameter setting. Run a local name server to reduce slow-down due to DNS lookups. If you run multiple Postfix systems, point each local name server to a shared forwarding server to reduce the number of lookups across the upstream network link. Reduce the smtp_connect_timeout and smtp_helo_timeout values so that Postfix does not waste lots of time connecting to non-responding remote SMTP servers. Use a dedicated mail delivery transport for problematic destinations, with reduced timeouts and with adjusted concurrency. See "Tuning the number of simultaneous deliveries" below. Use a fallback_relay host for mail that cannot be delivered upon the first attempt. This "graveyard" machine can use shorter retry times for difficult to reach destinations. See "Tuning the frequency of deferred mail delivery attempts" below. Speed up disk updates with a large (64MB) persistent write cache. This allows disk updates to be sorted for optimal access speed without compromising file system integrity when the system crashes. Use a solid-state disk (a persistent RAM disk). This is an expensive solution that should be used in combination with short SMTP timeouts and a fallback_relay "graveyard" machine that delivers mail for problem destinations.

Tuning the number of simultaneous deliveries


Although Postfix can be configured to run 1000 SMTP client processes at the same time, it is rarely desirable that it makes 1000 simultaneous connections to the same remote system. For this reason, Postfix has safety mechanisms in place to avoid this so-called "thundering herd" problem. The Postfix queue manager implements the analog of the TCP slow start flow control strategy: when delivering to a site, send a small number of messages first, then increase the concurrency as

long as all goes well; reduce concurrency in the face of congestion. The initial_destination_concurrency parameter (default: 5) controls how many messages are initially sent to the same destination before adapting delivery concurrency. Of course, this setting is effective only as long as it does not exceed the process limit and the destination concurrency limit for the specific mail transport channel. The default_destination_concurrency_limit parameter (default: 20) controls how many messages may be sent to the same destination simultaneously. You can override this setting for specific message delivery transports by taking the name of the master.cf entry and appending "_destination_concurrency_limit". Examples of transport specific concurrency limits are: The local_destination_concurrency_limit parameter (default: 2) controls how many messages are delivered simultaneously to the same local recipient. The recommended limit is low because delivery to the same mailbox must happen sequentially, so massive parallelism is not useful. Another good reason to limit delivery concurrency to the same recipient: if the recipient has an expensive shell command in her .forward file, or if the recipient is a mailing list manager, you don't want to run too many instances of those processes at the same time. The default smtp_destination_concurrency_limit of 20 seems enough to noticeably load a system without bringing it to its knees. Be careful when changing this to a much larger number. The above default values of the concurrency limits work well in a broad range of situations. Kneejerk changes to these parameters in the face of congestion can actually make problems worse. Specifically, large destination concurrencies should never be the default. They should be used only for transports that deliver mail to a small number of high volume domains. A common situation where high concurrency is called for is on gateways relaying a high volume of mail from between the Internet and an intranet mail environment. Approximately half the mail (assuming equal volumes inbound and outbound) will be destined for the internal mail hubs. Since the internal mail hubs will be receiving all external mail exclusively from the gateway, it is reasonable to configure the gateway to make greater demands on the capacity of the internal SMTP servers. The tuning of the inbound concurrency limits need not be trial and error. A high volume capable mailhub should be able to easily handle 50 or 100 (rather than the default 20) simultaneous connections, especially if the gateway forwards to multiple MX hosts. When all MX hosts are up and accepting connections in a timely fashion, throughput will be high. If any MX host is down and completely unresponsive, the average connection latency rises to at least 1/N * $smtp_connection_timeout, if there are N MX hosts. This limits throughput to at most the destination concurrency * N / $smtp_connection_timeout. For example, with a destination concurrency of 100 and 2 MX hosts, each host will handle up to 50 simultaneous connections. If one MX host is down and the default SMTP connection timeout is 30s, the throughput limit is 100 * 2 / 30 ~= 6 messages per second. This suggests that high volume destinations with good connectivity and multiple MX hosts need a lower connection timeout, values as low as 5s or even 1s can be used to prevent congestion when one or more, but not all MX hosts are down. If necessary, set a higher transport_destination_concurrency_limit (in main.cf since this is a queue manager parameter) and a lower smtp_connection_timeout (with a "-o" override in master.cf since this parameter has no per-transport name) for the relay transport and any transports dedicated for specific high volume destinations.

Tuning the number of recipients per delivery


The default_destination_recipient_limit parameter (default: 50) controls how many recipients a Postfix delivery agent will send with each copy of an email message. You can override this setting for specific Postfix delivery agents. For example, "uucp_destination_recipient_limit = 100" would limit the number of recipients per UUCP delivery to 100. If an email message exceeds the recipient limit for some destination, the Postfix queue manager breaks up the list of recipients into smaller lists. Postfix will attempt to send multiple copies of the message in parallel. IMPORTANT: Be careful when increasing the recipient limit per message delivery; some smtpd(8) servers abort the connection when they run out of memory or when a hard recipient limit is reached, so that the message will never be delivered. The smtpd_recipient_limit parameter (default: 1000) controls how many recipients the Postfix smtpd(8) server will take per delivery. The default limit is more than any reasonable SMTP client would send. The limit exists to protect the local mail system against a run-away client.

Tuning the frequency of deferred mail delivery attempts


When a Postfix delivery agent (smtp(8), local(8), etc.) is unable to deliver a message it may blame the message itself, or it may blame the receiving party. When the delivery agent blames the message, the queue manager gives the queue file a time stamp into the future, so it won't be looked at for a while. By default, the amount of time to cool down is the amount of time that has passed since the message arrived. This results in so-called exponential backoff behavior. When the delivery agent blames the receiving party (for example a local recipient user, or a remote host), the queue manager not only advances the queue file time stamp, but also puts the receiving party on a "dead" list so that it will be skipped for some amount of time. This process is governed by a bunch of little parameters. queue_run_delay (default: 300 seconds; before Postfix 2.4: 1000s) How often the queue manager scans the queue for deferred mail. minimal_backoff_time (default: 300 seconds; before Postfix 2.4: 1000s) The minimal amount of time a message won't be looked at, and the minimal amount of time to stay away from a "dead" destination. maximal_backoff_time (default: 4000 seconds) The maximal amount of time a message won't be looked at after a delivery failure. maximal_queue_lifetime (default: 5 days) How long a message stays in the queue before it is sent back as undeliverable. Specify 0 for mail that should be returned immediately after the first unsuccessful delivery attempt. bounce_queue_lifetime (default: 5 days, available with Postfix version 2.1 and later)

How long a MAILER-DAEMON message stays in the queue before it is considered undeliverable. Specify 0 for mail that should be tried only once. qmgr_message_recipient_limit (default: 20000) The size of many in-memory queue manager data structures. Among others, this parameter limits the size of the short-term, in-memory list of "dead" destinations. Destinations that don't fit the list are not added. IMPORTANT: If you increase the frequency of deferred mail delivery attempts, or if you flush the deferred mail queue frequently, then you may find that Postfix mail delivery performance actually becomes worse. The symptoms are as follows: The active queue becomes saturated with mail that has delivery problems. New mail enters the active queue only when an old message is deferred. This is a slow process that usually requires timing out one or more SMTP connections. All available Postfix delivery agents become occupied trying to connect to unreachable sites etc. New mail has to wait until a delivery agent becomes available. This is a slow process that usually requires timing out one or more SMTP connections. When mail is being deferred frequently, fixing the problem is always better than increasing the frequency of delivery attempts. However, if you can control only the delivery attempt frequency, consider using a dedicated fallback_relay "graveyard" machine for bad destinations, so that these destinations do not ruin the performance of normal mail deliveries.

Tuning the number of Postfix processes


The default_process_limit configuration parameter gives direct control over how many daemon processes Postfix will run. As of Postfix 2.0 the default limit is 100 smtp client processes, 100 smtp server processes, and so on. This may overwhelm systems with little memory, as well as networks with low bandwidth. You can change the global process limit by specifying a non-default default_process_limit in the main.cf file. For example, to run up to 10 smtp client processes, 10 smtp server processes, and so on:
/etc/postfix/main.cf: default_process_limit = 10

You need to execute "postfix reload" to make the change effective. The limits are enforced by the Postfix master(8) daemon which does not automatically read main.cf when it changes. You can override the process limit for specific Postfix daemons by editing the master.cf file. For example, if you do not wish to receive 100 SMTP messages at the same time, but do not want to change the process limits for local mail deliveries, you could specify:
/etc/postfix/master.cf: # ==================================================================== # service type private unpriv chroot wakeup maxproc command + args # (yes) (yes) (yes) (never) (100) # ==================================================================== . . . smtp inet n 10 smtpd . . .

Tuning the number of processes on the system


MacOS X will run out of process slots when you increase Postfix process limits. The following works with OSX 10.4 and OSX 10.5. MacOS X kernel parameters can be specified in /etc/sysctl.conf.
/etc/sysctl.conf: kern.maxproc=2048 kern.maxprocperuid=2048

Unfortunately these can't simply be set on the fly with "sysctl -w". You also have to set the following in /etc/launchd.conf so that the root user after boot will have the right process limit (2048). Otherwise you have to always run ulimit -u 2048 as root, then start a user shell, and then start processes for things to take effect.
/etc/launchd.conf: limit maxproc 2048

Once these are in place, reboot the system. After that, the limits will stay in place.

Tuning the number of open files or sockets


When Postfix opens too many files or sockets, processes will abort with fatal errors, and the system may log "file table full" errors. Depending on your Postfix and operating system versions you may need to recompile Postfix if you need more than 1024 file descriptors per process: No recompilation is needed for Postfix version 2.4 and later, when it was compiled for systems that support BSD kqueue(2) (FreeBSD 4.1, NetBSD 2.0, OpenBSD 2.9), Solaris 8 /dev/poll, or Linux 2.6 epoll(4). Otherwise, Postfix needs to be recompiled to override the default FD_SETSIZE value. Reduce the number of processes as described under "Tuning the number of Postfix processes" above. Fewer processes need fewer open files and sockets. Configure the kernel for more open files and sockets. The details are extremely system dependent and change with the operating system version. Be sure to verify the following information with your system tuning guide: Some FreeBSD kernel parameters can be specified in /boot/loader.conf, and some can be specified in /etc/sysctl.conf or changed with sysctl commands. Which is which depends on the version.
kern.ipc.maxsockets="5000" kern.ipc.nmbclusters="65536" kern.maxproc="2048" kern.maxfiles="16384" kern.maxfilesperproc="16384"

Linux kernel parameters can be specified in /etc/sysctl.conf or changed with sysctl commands:
fs.file-max=16384 kernel.threads-max=2048

Solaris kernel parameters can be specified in /etc/system, as described in the Solaris FAQ entry titled "How can I increase the number of file descriptors per process?"
* set hard limit on file descriptors set rlim_fd_max = 4096 * set soft limit on file descriptors set rlim_fd_cur = 1024

Postfix Debugging Howto


Purpose of this document
This document describes how to debug parts of the Postfix mail system when things do not work according to expectation. The methods vary from making Postfix log a lot of detail, to running some daemon processes under control of a call tracer or debugger. The text assumes that the Postfix main.cf and master.cf configuration files are stored in directory /etc/postfix. You can use the command "postconf config_directory" to find out the actual location of this directory on your machine. Listed in order of increasing invasiveness, the debugging techniques are as follows: Look for obvious signs of trouble Debugging Postfix from inside Try turning off chroot operation in master.cf Verbose logging for specific SMTP connections Record the SMTP session with a network sniffer Making Postfix daemon programs more verbose Manually tracing a Postfix daemon process Automatically tracing a Postfix daemon process Running daemon programs with the interactive ddd debugger Running daemon programs with the interactive gdb debugger Running daemon programs under a non-interactive debugger Unreasonable behavior Reporting problems to postfix-users@postfix.org

Look for obvious signs of trouble


Postfix logs all failed and successful deliveries to a logfile. The file is usually called /var/log/maillog or /var/log/mail; the exact pathname is defined in the /etc/syslog.conf file. When Postfix does not receive or deliver mail, the first order of business is to look for errors that prevent Postfix from working properly:
% egrep '(warning|error|fatal|panic):' /some/log/file | more

Note: the most important message is near the BEGINNING of the output. Error messages that come later are less useful. The nature of each problem is indicated as follows: "panic" indicates a problem in the software itself that only a programmer can fix. Postfix cannot proceed until this is fixed. "fatal" is the result of missing files, incorrect permissions, incorrect configuration file settings that you can fix. Postfix cannot proceed until this is fixed.

"error" reports an error condition. For safety reasons, a Postfix process will terminate when more than 13 of these happen. "warning" indicates a non-fatal error. These are problems that you may not be able to fix (such as a broken DNS server elsewhere on the network) but may also indicate local configuration errors that could become a problem later.

Debugging Postfix from inside


Postfix version 2.1 and later can produce mail delivery reports for debugging purposes. These reports not only show sender/recipient addresses after address rewriting and alias expansion or forwarding, they also show information about delivery to mailbox, delivery to non-Postfix command, responses from remote SMTP servers, and so on. Postfix can produce two types of mail delivery reports for debugging: What-if: report what would happen, but do not actually deliver mail. This mode of operation is requested with:
% /usr/sbin/sendmail -bv address... Mail Delivery Status Report will be mailed to <your login name>.

What happened: deliver mail and report successes and/or failures, including replies from remote SMTP servers. This mode of operation is requested with:
% /usr/sbin/sendmail -v address... Mail Delivery Status Report will be mailed to <your login name>.

These reports contain information that is generated by Postfix delivery agents. Since these run as daemon processes that cannot interact with users directly, the result is sent as mail to the sender of the test message. The format of these reports is practically identical to that of ordinary non-delivery notifications. For a detailed example of a mail delivery status report, see the debugging section at the end of the ADDRESS_REWRITING_README document.

Try turning off chroot operation in master.cf


A common mistake is to turn on chroot operation in the master.cf file without going through all the necessary steps to set up a chroot environment. This causes Postfix daemon processes to fail due to all kinds of missing files. The example below shows an SMTP server that is configured with chroot turned off:
/etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= smtp inet n n smtpd

Inspect master.cf for any processes that have chroot operation not turned off. If you find any, save a copy of the master.cf file, and edit the entries in question. After executing the command "postfix reload", see if the problem has gone away. If turning off chrooted operation made the problem go away, then congratulations. Leaving Postfix running in this way is adequate for most sites. If you prefer chrooted operation, see the Postfix BASIC_CONFIGURATION_README file for information about how to prepare Postfix for

chrooted operation.

Verbose logging for specific SMTP connections


In /etc/postfix/main.cf, list the remote site name or address in the debug_peer_list parameter. For example, in order to make the software log a lot of information to the syslog daemon for connections from or to the loopback interface:
/etc/postfix/main.cf: debug_peer_list = 127.0.0.1

You can specify one or more hosts, domains, addresses or net/masks. To make the change effective immediately, execute the command "postfix reload".

Record the SMTP session with a network sniffer


This example uses tcpdump. In order to record a conversation you need to specify a large enough buffer with the "-s" option or else you will miss some or all of the packet payload.
# tcpdump -w /file/name -s 0 host example.com and port 25

Older tcpdump versions don't support "-s 0"; in that case, use "-s 2000" instead. Run this for a while, stop with Ctrl-C when done. To view the data use a binary viewer, ethereal, or good old less.

Making Postfix daemon programs more verbose


Append one or more "-v" options to selected daemon definitions in /etc/postfix/master.cf and type "postfix reload". This will cause a lot of activity to be logged to the syslog daemon. For example, to make the Postfix SMTP server process more verbose:
/etc/postfix/master.cf: smtp inet n n smtpd -v

To diagnose problems with address rewriting specify a "-v" option for the cleanup(8) and/or trivialrewrite(8) daemon, and to diagnose problems with mail delivery specify a "-v" option for the qmgr(8) or oqmgr(8) queue manager, or for the lmtp(8), local(8), pipe(8), smtp(8), or virtual(8) delivery agent.

Manually tracing a Postfix daemon process


Many systems allow you to inspect a running process with a system call tracer. For example:
# # # # trace -p process-id (SunOS 4) strace -p process-id (Linux and many others) truss -p process-id (Solaris, FreeBSD) ktrace -p process-id (generic 4.4BSD)

Even more informative are traces of system library calls. Examples:


# ltrace -p process-id (Linux, also ported to FreeBSD and BSD/OS) # sotruss -p process-id (Solaris)

See your system documentation for details. Tracing a running process can give valuable information about what a process is attempting to do.

This is as much information as you can get without running an interactive debugger program, as described in a later section.

Automatically tracing a Postfix daemon process


Postfix can attach a call tracer whenever a daemon process starts. Call tracers come in several kinds. 1. System call tracers such as trace, truss, strace, or ktrace. These show the communication between the process and the kernel. 2. Library call tracers such as sotruss and ltrace. These show calls of library routines, and give a better idea of what is going on within the process. Append a -D option to the suspect command in /etc/postfix/master.cf, for example:
/etc/postfix/master.cf: smtp inet n n smtpd -D

Edit the debugger_command definition in /etc/postfix/main.cf so that it invokes the call tracer of your choice, for example:
/etc/postfix/main.cf: debugger_command = PATH=/bin:/usr/bin:/usr/local/bin; (truss -p $process_id 2>&1 | logger -p mail.info) & sleep 5

Type "postfix reload" and watch the logfile.

Running daemon programs with the interactive ddd debugger


If you have X Windows installed on the Postfix machine, then an interactive debugger such as ddd can be convenient. Edit the debugger_command definition in /etc/postfix/main.cf so that it invokes ddd:
/etc/postfix/main.cf: debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon_directory/$process_name $process_id & sleep 5

Be sure that gdb is in the command search path, and export XAUTHORITY so that X access control works, for example:
% setenv XAUTHORITY ~/.Xauthority (csh syntax) $ export XAUTHORITY=$HOME/.Xauthority (sh syntax)

Append a -D option to the suspect daemon definition in /etc/postfix/master.cf, for example:


/etc/postfix/master.cf: smtp inet n n smtpd -D

Stop and start the Postfix system. This is necessary so that Postfix runs with the proper XAUTHORITY and DISPLAY settings. Whenever the suspect daemon process is started, a debugger window pops up and you can watch in detail what happens.

Running daemon programs with the interactive gdb debugger


If you have the screen command installed on the Postfix machine, then you can run an interactive debugger such as gdb as follows. Edit the debugger_command definition in /etc/postfix/main.cf so that it runs gdb inside a detached screen session:
/etc/postfix/main.cf: debugger_command = PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH; HOME=/root; export HOME; screen -e^tt -dmS $process_name gdb $daemon_directory/$process_name $process_id & sleep 2

Be sure that gdb is in the command search path. Append a -D option to the suspect daemon definition in /etc/postfix/master.cf, for example:
/etc/postfix/master.cf: smtp inet n n smtpd -D

Execute the command "postfix reload" and wait until a daemon process is started (you can see this in the maillog file). Then attach to the screen, and debug away:
# HOME=/root screen -r gdb) continue gdb) where

Running daemon programs under a non-interactive debugger


If you do not have X Windows installed on the Postfix machine, or if you are not familiar with interactive debuggers, then you can try to run gdb in non-interactive mode, and have it print a stack trace when the process crashes. Edit the debugger_command definition in /etc/postfix/main.cf so that it invokes the gdb debugger:
/etc/postfix/main.cf: debugger_command = PATH=/bin:/usr/bin:/usr/local/bin; export PATH; (echo cont; echo where; sleep 8640000) | gdb $daemon_directory/$process_name $process_id 2>&1 >$config_directory/$process_name.$process_id.log & sleep 5

Append a -D option to the suspect daemon in /etc/postfix/master.cf, for example:


/etc/postfix/master.cf: smtp inet n n smtpd -D

Type "postfix reload" to make the configuration changes effective. Whenever a suspect daemon process is started, an output file is created, named after the daemon and process ID (for example, smtpd.12345.log). When the process crashes, a stack trace (with output from the "where" command) is written to its logfile.

Unreasonable behavior
Sometimes the behavior exhibited by Postfix just does not match the source code. Why can a

program deviate from the instructions given by its author? There are two possibilities. The compiler has erred. This rarely happens. The hardware has erred. Does the machine have ECC memory? In both cases, the program being executed is not the program that was supposed to be executed, so anything could happen. There is a third possibility: Bugs in system software (kernel or libraries). Hardware-related failures usually do not reproduce in exactly the same way after power cycling and rebooting the system. There's little Postfix can do about bad hardware. Be sure to use hardware that at the very least can detect memory errors. Otherwise, Postfix will just be waiting to be hit by a bit error. Critical systems deserve real hardware. When a compiler makes an error, the problem can be reproduced whenever the resulting program is run. Compiler errors are most likely to happen in the code optimizer. If a problem is reproducible across power cycles and system reboots, it can be worthwhile to rebuild Postfix with optimization disabled, and to see if optimization makes a difference. In order to compile Postfix with optimizations turned off:
% make tidy % make makefiles OPT=

This produces a set of Makefiles that do not request compiler optimization. Once the makefiles are set up, build the software:
% make % su Password: # make install

If the problem goes away, then it is time to ask your vendor for help.

Reporting problems to postfix-users@postfix.org


The people who participate on postfix-users@postfix.org are very helpful, especially if YOU provide them with sufficient information. Remember, these volunteers are willing to help, but their time is limited. When reporting a problem, be sure to include the following information. A summary of the problem. Please do not just send some logging without explanation of what YOU believe is wrong. Complete error messages. Please use cut-and-paste, or use attachments, instead of reciting information from memory. Postfix logging. See the text at the top of the DEBUG_README document to find out where logging is stored. Please do not frustrate the helpers by word wrapping the logging. If the logging is more than a few kbytes of text, consider posting an URL on a web or ftp site. Consider using a test email address so that you don't have to reveal email addresses or passwords of innocent people. If you can't use a test email address, please anonymize email addresses and host names consistently. Replace each letter by "A", each digit by "D" so that the helpers can still

recognize syntactical errors. Output from "postconf -n". Please do not send your main.cf file, or 500+ lines of postconf output. Better, provide output from the postfinger tool. This can be found at http://ftp.wl0.org/SOURCES/postfinger. If the problem is SASL related, consider including the output from the saslfinger tool. This can be found at http://postfix.state-of-mind.de/patrick.koetter/saslfinger/. If the problem is about too much mail in the queue, consider including output from the qshape tool, as described in the QSHAPE_README file. If the problem is protocol related (connections time out, or an SMTP server complains about syntax errors etc.) consider recording a session with tcpdump, as described in the DEBUG_README document.

Postfix Content Inspection


Postfix supports three content inspection methods, ranging from light-weight one-line-at-a-time scanning before mail is queued, to heavy duty machinery that does sophisticated content analysis after mail is queued. Each approach serves a different purpose. before queue, built-in, light-weight This method inspects mail BEFORE it is stored in the queue, and uses Postfix's built-in message header and message body inspection. Although the main purpose is to stop a specific flood of mail from worms or viruses, it is also useful to block a flood of bounced junk email and email notifications from virus detection systems. The built-in regular expressions are not meant to implement general SPAM and virus detection. For that, you should use one of the content inspection methods described below. Details are described in the BUILTIN_FILTER_README and BACKSCATTER_README documents. after queue, external, heavy-weight This method inspects mail AFTER it is stored in the queue, and uses standard protocols such as SMTP or "pipe to command and wait for exit status". After-queue inspection allows you to use content filters of arbitrary complexity without causing timeouts while receiving mail, and without running out of memory resources under a peak load. Details of this approach are in the FILTER_README document. before queue, external, medium-weight The following two methods inspect mail BEFORE it is stored in the queue. The first method uses the SMTP protocol, and is described in the SMTPD_PROXY_README document. This approach is available with Postfix version 2.1 and later. The second method uses the Sendmail 8 Milter protocol, and is described in the MILTER_README document. This approach is available with Postfix version 2.3 and later. Although these approaches appear to be attractive, they have some serious limitations that you need to be aware of. First, content inspection software must finish in a limited amount of time; if content inspection needs too much time then incoming mail deliveries will time out. Second, content inspection software must run in a limited amount of memory; if content inspection needs too much memory then software will crash under a peak load. Before-queue inspection limits the peak load that your system can handle, and limits the sophistication of the content filter that you can use. The more sophisticated content filtering software is not built into Postfix for good reasons: writing an MTA requires different skills than writing a SPAM or virus killer. Postfix encourages the use of external filters and standard protocols because this allows you to choose the best MTA and the best

content inspection software for your purpose. Information about external content inspection software can be found on the Postfix website at http://www.postfix.org/, and on the postfixusers@postfix.org mailing list.

Postfix Backscatter Howto


Overview
This document describes features that require Postfix version 2.0 or later. Topics covered in this document: What is backscatter mail? How do I block backscatter mail to random recipient addresses? How do I block backscatter mail to real recipient addresses? Blocking backscatter mail with forged mail server information Blocking backscatter mail with forged sender information Blocking backscatter mail with other forged information Blocking backscatter mail from virus scanners The examples use Perl Compatible Regular Expressions (Postfix pcre: tables), but also provide a translation to POSIX regular expressions (Postfix regexp: tables). PCRE is preferred primarily because the implementation is often faster.

What is backscatter mail?


When a spammer or worm sends mail with forged sender addresses, innocent sites are flooded with undeliverable mail notifications. This is called backscatter mail. With Postfix, you know that you're a backscatter victim when your logfile goes on and on like this:
Dec 4 04:30:09 hostname postfix/smtpd[58549]: NOQUEUE: reject: RCPT from xxxxxxx[x.x.x.x]: 550 5.1.1 <yyyyyy@your.domain.here>: Recipient address rejected: User unknown; from=<> to=<yyyyyy@your.domain.here> proto=ESMTP helo=<zzzzzz>

What you see are lots of "user unknown" errors with "from=<>". These are error reports from MAILER-DAEMONs elsewhere on the Internet, about email that was sent with a false sender address in your domain.

How do I block backscatter mail to random recipient addresses?


If your machine receives backscatter mail to random addresses, configure Postfix to reject all mail for non-existent recipients as described in the LOCAL_RECIPIENT_README and STANDARD_CONFIGURATION_README documentation. If your machine runs Postfix 2.0 and earlier, disable the "pause before reject" feature in the SMTP server. If your system is under stress then it should not waste time.
/etc/postfix/main.cf: # Not needed with Postfix 2.1 and later. smtpd_error_sleep_time = 0

# Not needed with Postfix 2.4 and later. unknown_local_recipient_reject_code = 550

How do I block backscatter mail to real recipient addresses?


When backscatter mail passes the "unknown recipient" barrier, there still is no need to despair. Many mail systems are kind enough to attach the message headers of the undeliverable mail in the non-delivery notification. These message headers contain information that you can use to recognize and block forged mail.

Blocking backscatter mail with forged mail server information


Although my email address is "wietse@porcupine.org", all my mail systems announce themselves with the SMTP HELO command as "hostname.porcupine.org". Thus, if returned mail has a Received: message header like this:
Received: from porcupine.org ...

Then I know that this is almost certainly forged mail (almost; see next section for the fly in the ointment). Mail that is really sent by my systems looks like this:
Received: from hostname.porcupine.org ...

For the same reason the following message headers are very likely to be the result of forgery:
Received: Received: Received: Received: from from from from host.example.com ([1.2.3.4] helo=porcupine.org) ... [1.2.3.4] (port=12345 helo=porcupine.org) ... host.example.com (HELO porcupine.org) ... host.example.com (EHLO porcupine.org) ...

Some forgeries show up in the way that a mail server reports itself in Received: message headers. Keeping in mind that all my systems have a mail server name of hostname.porcupine.org, the following is definitely a forgery:
Received: by porcupine.org ... Received: from host.example.com ( ... ) by porcupine.org ...

Another frequent sign of forgery is the Message-ID: header. My systems produce a Message-ID: of <stuff@hostname.porcupine.org>. The following are forgeries, especially the first one:
Message-ID: <1cb479435d8eb9.2beb1.qmail@porcupine.org> Message-ID: <yulszqocfzsficvzzju@porcupine.org>

To block such backscatter I use header_checks and body_checks patterns like this:
/etc/postfix/main.cf: header_checks = pcre:/etc/postfix/header_checks body_checks = pcre:/etc/postfix/body_checks /etc/postfix/header_checks: # Do not indent the text between "if" and "endif". if /^Received:/ /^Received: +from +(porcupine\.org) +/ reject forged client name in Received: header: $1 /^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +) (porcupine\.org)\)/ reject forged client name in Received: header: $2 /^Received:.* +by +(porcupine\.org)\b/ reject forged mail server name in Received: header: $1

endif /^Message-ID:.* <!&!/ DUNNO /^Message-ID:.*@(porcupine\.org)/ reject forged domain name in Message-ID: header: $1 /etc/postfix/body_checks: # Do not indent the text between "if" and "endif". if /^[> ]*Received:/ /^[> ]*Received: +from +(porcupine\.org) / reject forged client name in Received: header: $1 /^[> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +) (porcupine\.org)\)/ reject forged client name in Received: header: $2 /^[> ]*Received:.* +by +(porcupine\.org)\b/ reject forged mail server name in Received: header: $1 endif /^[> ]*Message-ID:.* <!&!/ DUNNO /^[> ]*Message-ID:.*@(porcupine\.org)/ reject forged domain name in Message-ID: header: $1

Notes: The example uses pcre: tables mainly for speed; with minor modifications, you can use regexp: tables as explained below. The example is simplified for educational purposes. In reality my patterns list multiple domain names, as "(domain|domain|...)". The "\." matches "." literally. Without the "\", the "." would match any character. The "\(" and "\)" match "(" and ")" literally. Without the "\", the "(" and ")" would be grouping operators. The "\b" is used here to match the end of a word. If you use regexp: tables, specify "[[:>:]]" (on some systems you should specify "\>" instead; for details see your system documentation). The "if /pattern/" and "endif" eliminate unnecessary matching attempts. DO NOT indent lines starting with /pattern/ between the "if" and "endif"! The two "Message-ID:.* <!&!" rules are workarounds for some versions of Outlook express, as described in the caveats section below. Caveats Netscape Messenger (and reportedly, Mozilla) sends a HELO name that is identical to the sender address domain part. If you have such clients then the above patterns would block legitimate email. My network has only one such machine, and to prevent its mail from being blocked I have configured it to send mail as user@hostname.porcupine.org. On the Postfix server, a canonical mapping translates this temporary address into user@porcupine.org.
/etc/postfix/main.cf: canonical_maps = hash:/etc/postfix/canonical /etc/postfix/canonical: @hostname.porcupine.org @porcupine.org

This is of course practical only when you have very few systems that send HELO commands like this, and when you never have to send mail to a user on such a host.

An alternative would be to remove the hostname from "hostname.porcupine.org" with address masquerading, as described in the ADDRESS_REWRITING_README document. Reportedly, Outlook 2003 (perhaps Outlook Express, and other versions as well) present substantially different Message-ID headers depending upon whether or not a DSN is requested (via Options "Request a delivery receipt for this message"). When a DSN is requested, Outlook 2003 uses a Message-ID string that ends in the sender's domain name:
Message-ID: <!&! ...very long string... ==@example.com>

where example.com is the domain name part of the email address specified in Outlook's account settings for the user. Since many users configure their email addresses as username@example.com, messages with DSN turned on will trigger the REJECT action in the previous section. If you have such clients then you can to exclude their Message-ID strings with the two "Message-ID:.* <!&!" patterns that are shown in the previous section. Otherwise you will not be able to use the two backscatter rules to stop forged Message ID strings. Of course this workaround may break the next time Outlook is changed.

Blocking backscatter mail with forged sender information


Like many people I still have a few email addresses in domains that I used in the past. Mail for those addresses is forwarded to my current address. Most of the backscatter mail that I get claims to be sent from these addresses. Such mail is obviously forged and is very easy to stop.
/etc/postfix/main.cf: header_checks = pcre:/etc/postfix/header_checks body_checks = pcre:/etc/postfix/body_checks /etc/postfix/header_checks: /^(From|Return-Path):.*\b(user@domain\.tld)\b/ reject forged sender address in $1: header: $2 /etc/postfix/body_checks: /^[> ]*(From|Return-Path):.*\b(user@domain\.tld)\b/ reject forged sender address in $1: header: $2

Notes: The example uses pcre: tables mainly for speed; with minor modifications, you can use regexp: tables as explained below. The example is simplified for educational purposes. In reality, my patterns list multiple email addresses as "(user1@domain1\.tld|user2@domain2\.tld)". The two "\b" as used in "\b(user@domain\.tld)\b" match the beginning and end of a word, respectively. If you use regexp: tables, specify "[[:<:]] and [[:>:]]" (on some systems you should specify "\< and \>" instead; for details see your system documentation). The "\." matches "." literally. Without the "\", the "." would match any character.

Blocking backscatter mail with other forged information


Another sign of forgery can be found in the IP address that is recorded in Received: headers next to your HELO host or domain name. This information must be used with care, though. Some mail

servers are behind a network address translator and never see the true client IP address.

Blocking backscatter mail from virus scanners


With all the easily recognizable forgeries eliminated, there is one category of backscatter mail that remains, and that is notifications from virus scanner software. Unfortunately, some virus scanning software doesn't know that viruses forge sender addresses. To make matters worse, the software also doesn't know how to report a mail delivery problem, so that we cannot use the above techniques to recognize forgeries. Recognizing virus scanner mail is an error prone process, because there is a lot of variation in report formats. The following is only a small example of message header patterns. For a large collection of header and body patterns that recognize virus notification email, see http://www.dkuug.dk/keld/virus/ or http://www.t29.dk/antiantivirus.txt.
/etc/postfix/header_checks: /^Subject: *Your email contains VIRUSES/ DISCARD virus notification /^Content-Disposition:.*VIRUS1_DETECTED_AND_REMOVED/ DISCARD virus notification /^Content-Disposition:.*VirusWarning.txt/ DISCARD virus notification

Note: these documents haven't been updated since 2004, so they are useful only as a starting point. A plea to virus or spam scanner operators: please do not make the problem worse by sending return mail to forged sender addresses. You're only harassing innocent people. If you must return mail to the purported sender, please return the full message headers, so that the sender can filter out the obvious forgeries.

Postfix Built-in Content Inspection


Built-in content inspection introduction
Postfix supports a built-in filter mechanism that examines message header and message body content, one line at a time, before it is stored in the Postfix queue. The filter is usually implemented with POSIX or PCRE regular expressions, as described in the header_checks(5) manual page. The original purpose of the built-in filter is to stop an outbreak of specific email worms or viruses, and it does this job well. The filter has also helped to block bounced junk email, bounced email from worms or viruses, and notifications from virus detection systems. Information about this secondary application is given in the BACKSCATTER_README document. Because the built-in filter is optimized for stopping specific worms and virus outbreaks, it has limitations that make it NOT suitable for general junk email and virus detection. For that, you should use one of the external content inspection methods that are described in the FILTER_README, SMTPD_PROXY_README and MILTER_README documents. The following diagram gives an over-all picture of how Postfix built-in content inspection works: Postmaster notifications | v Network or Built-in Postfix Delivery Network or -> -> -> -> local users filter queue agents local mailbox | ^ | v Undeliverable mail Forwarded mail The picture makes clear that the filter works while Postfix is receiving new mail. This means that Postfix can reject mail from the network without having to return undeliverable mail to the originator address (which is often spoofed anyway). However, this ability comes at a price: if mail inspection takes too much time, then the remote client will time out, and the client may send the same message repeatedly. Topics covered by this document: What mail is subjected to header/body checks Limitations of Postfix header/body checks Preventing daily mail status reports from being blocked Configuring header/body checks for mail from outside users only Configuring header/body checks for mail to some domains only

What mail is subjected to header/body checks


Postfix header/body checks are implemented by the cleanup(8) server before it injects mail into the incoming queue. The diagram below zooms in on the cleanup(8) server, and shows that this server handles mail from many different sources. In order to keep the diagram readable, the sources of postmaster notifications are not shown, because they can be produced by many Postfix daemon processes. bounce(8) (undeliverable) | v cleanup(8) -> incoming queue

smtpd(8) (network) \ qmqpd(8) -\ (network) -/ pickup(8) / (local)

^ | local(8) (forwarded) For efficiency reasons, only mail that enters from outside of Postfix is inspected with header/body checks. It would be inefficient to filter already filtered mail again, and it would be undesirable to block postmaster notifications. The table below summarizes what mail is and is not subject to header/body checks. Message type Network mail Network mail Local submission Local forwarding Source smtpd(8) Header/body checks? Configurable Undeliverable mail bounce(8) No qmqpd(8) Configurable pickup(8) Configurable local(8) No

Postmaster notice many No How does Postfix decide what mail needs to be filtered? It would be clumsy to make the decision in the cleanup(8) server, as this program receives mail from so many different sources. Instead, header/body checks are requested by the source. Examples of how to turn off header/body checks for mail received with smtpd(8), qmqpd(8) or pickup(8) are given below under "Configuring header/body checks for mail from outside users only" and "Configuring header/body checks for mail to some domains only".

Limitations of Postfix header/body checks


Header/body checks do not decode message headers or message body content. For example, if text in the message body is BASE64 encoded (RFC 2045) then your regular expressions will have to match the BASE64 encoded form. Likewise, message headers with encoded non-ASCII characters (RFC 2047) need to be matched in their encoded form. Header/body checks cannot filter on a combination of message headers or body lines. Header/body checks examine content one message header at a time, or one message body line at a time, and cannot carry a decision over to the next message header or body line. Header/body checks cannot depend on the recipient of a message.

One message can have multiple recipients, and all recipients of a message receive the same treatment. Workarounds have been proposed that involve selectively deferring some recipients of multi-recipient mail, but that results in poor SMTP performance and does not work for non-SMTP mail. Some sources of mail send the headers and content ahead of the recipient information. It would be inefficient to buffer up an entire message before deciding if it needs to be filtered, and it would be clumsy to filter mail and to buffer up all the actions until it is known whether those actions need to be executed. Despite warnings, some people try to use the built-in filter feature for general junk email and/or virus blocking, using hundreds or even thousands of regular expressions. This can result in catastrophic performance failure. The symptoms are as follows: The cleanup(8) processes use up all available CPU time in order to process the regular expressions, and/or they use up all available memory so that the system begins to swap. This slows down all incoming mail deliveries. As Postfix needs more and more time to receive an email message, the number of simultaneous SMTP sessions increases to the point that the SMTP server process limit is reached. While all SMTP server processes are waiting for the cleanup(8) servers to finish, new SMTP clients have to wait until an SMTP server process becomes available. This causes mail deliveries to time out before they have even begun. The remedy for this type of performance problem is simple: don't use header/body checks for general junk email and/or virus blocking, and don't filter mail before it is queued. When performance is a concern, use an external content filter that runs after mail is queued, as described in the FILTER_README document.

Preventing daily mail status reports from being blocked


The following is quoted from Jim Seymour's Pflogsumm FAQ at http://jimsun.linxnet.com/downloads/pflogsumm-faq.txt. Pflogsumm is a program that analyzes Postfix logs, including the logging from rejected mail. If these logs contain text that was rejected by Postfix body_checks patterns, then the logging is also likely to be rejected by those same body_checks patterns. This problem does not exist with header_checks patterns, because those are not applied to the text that is part of the mail status report. You configure Postfix to do body checks, Postfix does its thing, Pflogsumm reports it and Postfix catches the same string in the Pflogsumm report. There are several solutions to this. Wolfgang Zeikat contributed this:
#!/usr/bin/perl use MIME::Lite; ### Create a new message: $msg = MIME::Lite->new( From => 'your@send.er', To => 'your@recipie.nt', # Cc => 'some@other.com, some@more.com', Subject => 'pflogsumm', Date => `date`, Type => 'text/plain',

);

Encoding => 'base64', Path => '/tmp/pflogg',

$msg->send;

Where "/tmp/pflogg" is the output of Pflogsumm. This puts Pflogsumm's output in a base64 MIME attachment. Note by Wietse: if you run this on a machine that is accessible by untrusted users, it is safer to store the Pflogsumm report in a directory that is not world writable. In a follow-up to a thread in the postfix-users mailing list, Ralf Hildebrandt noted: "mpack does the same thing." And it does. Which tool one should use is a matter of preference. Other solutions involve additional body_checks rules that make exceptions for daily mail status reports, but this is not recommended. Such rules slow down all mail and complicate Postfix maintenance.

Configuring header/body checks for mail from outside users only


The following information applies to Postfix 2.1 and later. Earlier Postfix versions do not support the receive_override_options feature. The easiest approach is to configure ONE Postfix instance with multiple SMTP server IP addresses in master.cf: Two SMTP server IP addresses for mail from inside users only, with header/body filtering turned off, and a local mail pickup service with header/body filtering turned off.
/etc/postfix.master.cf: # ================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================== 1.2.3.4:smtp inet n n smtpd -o receive_override_options=no_header_body_checks 127.0.0.1:smtp inet n n smtpd -o receive_override_options=no_header_body_checks pickup fifo n n 60 1 pickup -o receive_override_options=no_header_body_checks

Add some firewall rule to prevent access to 1.2.3.4:smtp from the outside world. One SMTP server address for mail from outside users with header/body filtering turned on via main.cf.
/etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= 1.2.3.5:smtp inet n n smtpd

Configuring header/body checks for mail to some domains only


The following information applies to Postfix 2.1. Earlier Postfix versions do not support the receive_override_options feature. If you are MX service provider and want to apply disable head/body checks for some domains, you can configure ONE Postfix instance with multiple SMTP server IP addresses in master.cf. Each address provides a different service.
/etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= # SMTP service for domains with header/body checks turned on. 1.2.3.4:smtp inet n n smtpd # SMTP service for domains with header/body checks turned off. 1.2.3.5:smtp inet n n smtpd -o receive_override_options=no_header_body_checks

Once this is set up you can configure MX records in the DNS that route each domain to the proper SMTP server instance.

Postfix After-Queue Content Filter


Introduction
This document requires Postfix version 2.1 or later. Normally, Postfix receives mail, stores it in the mail queue and then delivers it. With the external content filter described here, mail is filtered AFTER it is queued. This approach decouples mail receiving processes from mail filtering processes, and gives you maximal control over how many filtering processes you are willing to run in parallel. The after-queue content filter is meant to be used as follows: Network or Postfix Content Postfix Network or -> -> -> -> local users queue filter queue local mailbox This document describes implementations that use a single Postfix instance for everything: receiving, filtering and delivering mail. Applications that use two separate Postfix instances will be covered by a later version of this document. The after-queue content filter is not to be confused with the approaches described in the SMTPD_PROXY_README or MILTER_README documents, where incoming SMTP mail is filtered BEFORE it is stored into the Postfix queue. This document describes two approaches to content filter all email, as well as several options to filter mail selectively: Principles of operation Simple content filter Simple content filter example Simple content filter performance Simple content filter limitations Turning off the simple content filter Advanced content filter Advanced content filter example Advanced content filter performance Turning off the advanced content filter Selective content filtering Filtering mail from outside users only Different filters for different domains FILTER actions in access or header/body tables

Principles of operation
An after-queue content filter receives unfiltered mail from Postfix (as described further below) and can do one of the following:

1. Re-inject the mail back into Postfix, perhaps after changing content and/or destination. 2. Discard or quarantine the mail. 3. Reject the mail (by sending a suitable status code back to Postfix). Postfix will send the mail back to the sender address. NOTE: in this time of mail worms and forged spam, it is a VERY BAD IDEA to send viruses back to the sender address, because the sender address is almost certainly not the originator. It is better to discard known viruses, and to quarantine material that is suspect so that a human can decide what to do with it.

Simple content filter example


The first example is simple to set up, but has major limitations that will be addressed in a second example. Postfix receives unfiltered mail from the network with the smtpd(8) server, and delivers unfiltered mail to a content filter with the Postfix pipe(8) delivery agent. The content filter injects filtered mail back into Postfix with the Postfix sendmail(1) command, so that Postfix can deliver it to the final destination. This means that mail submitted via the Postfix sendmail(1) command cannot be content filtered. In the figure below, names followed by a number represent Postfix commands or daemon programs. See the OVERVIEW document for an introduction to the Postfix architecture. local(8) -> Filtered >- cleanup(8) -> -< smtp(8) -> Filtered pickup(8) pipe(8) | ^ | v maildrop Postfix Postfix Content <<<queue postdrop(1) sendmail(1) filter The content filter can be a simple shell script like this: qmgr(8) Postfix queue
1 #!/bin/sh 2 3 # Simple shell-based filter. It is meant to be invoked as follows: 4 # /path/to/script -f sender recipients... 5 6 # Localize these. The -G option does nothing before Postfix 2.3. 7 INSPECT_DIR=/var/spool/filter 8 SENDMAIL="/usr/sbin/sendmail -G -i" # NEVER NEVER NEVER use "-t" here. 9 10 # Exit codes from <sysexits.h> 11 EX_TEMPFAIL=75 12 EX_UNAVAILABLE=69 13 14 # Clean up when done or when aborting. 15 trap "rm -f in.$$" 0 1 2 3 15 16 17 # Start processing. 18 cd $INSPECT_DIR || { 19 echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; } 20 21 cat >in.$$ || { 22 echo Cannot save mail to file; exit $EX_TEMPFAIL; } 23 24 # Specify your content filter here.

Unfiltered -> smtpd(8)

25 26 27 28 29 30

# filter <in.$$ || { # echo Message content rejected; exit $EX_UNAVAILABLE; } $SENDMAIL "$@" <in.$$ exit $?

Notes: Line 8: The -G option says the filter output is not a local mail submission: don't do silly things like appending the local domain name to addresses in message headers. This option does nothing before Postfix version 2.3. Line 8: The -i option says don't stop reading input when a line contains "." only. Line 8: NEVER NEVER NEVER use the "-t" command-line option here. It will mis-deliver mail, like sending messages from a mailing list back to the mailing list. Line 21: The idea is to first capture the message to file and then run the content through a third-party content filter program. Line 22: If the message cannot be captured to file, mail delivery is deferred by terminating with exit status 75 (EX_TEMPFAIL). Postfix places the message in the deferred mail queue and tries again later. Line 25: You will need to specify a real content filter program here that receives the content on standard input. Line 26: If the content filter program finds a problem, the mail is bounced by terminating with exit status 69 (EX_UNAVAILABLE). Postfix will send the message back to the sender as undeliverable mail. NOTE: in this time of mail worms and spam, it is a BAD IDEA to send known viruses or spam back to the sender, because that address is likely to be forged. It is safer to discard known viruses and to quarantine suspicious content so that it can be inspected by a human being. Line 28: If the content is OK, it is given as input to the Postfix sendmail command, and the exit status of the filter command is whatever exit status the Postfix sendmail command produces. Postfix will deliver the message as usual. Line 30: Postfix returns the exit status of the Postfix sendmail command. I suggest that you first run this script by hand until you are satisfied with the results. Run it with a real message (headers+body) as input:
% /path/to/script -f sender -- recipient... <message-file

Once you're satisfied with the content filtering script: Create a dedicated local user account called "filter". This user handles all potentially dangerous mail content - that is why it should be a separate account. Do not use "nobody", and most certainly do not use "root" or "postfix". Create a directory /var/spool/filter that is accessible only to the "filter" user. This is where the content filtering script is supposed to store its temporary files. Configure Postfix to deliver mail to the content filter with the pipe(8) delivery agent (see the pipe(8) manpage for a description of the command syntax below).
/etc/postfix/master.cf: # =============================================================

# service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= filter unix n n 10 pipe flags=Rq user=filter null_sender= argv=/path/to/script -f ${sender} -- ${recipient}

This runs up to 10 content filters in parallel. Instead of a limit of 10 concurrent processes, use whatever process limit is feasible for your machine. Content inspection software can gobble up a lot of system resources, so you don't want to have too much of it running at the same time. The empty null_sender setting is required with Postfix 2.3 and later. To turn on content filtering for mail arriving via SMTP only, append "-o content_filter=filter:dummy" to the master.cf entry that defines the Postfix SMTP server:
/etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= smtp inet ...other stuff here, do not change... smtpd -o content_filter=filter:dummy

The "-o content_filter" line causes Postfix to add one content filter request record to each incoming mail message, with content "filter:dummy". This record overrides the normal mail routing and causes mail to be given to the content filter instead. The content_filter configuration parameter expects a value of the form transport:destination. The transport name specifies the first field of a mail delivery agent definition in master.cf; the syntax of the next-hop destination is described in the manual page of the corresponding delivery agent. The meaning of an empty next-hop filter destination is version dependent. Postfix 2.7 and later will use the recipient domain; earlier versions will use $myhostname. Specify "default_filter_nexthop = $myhostname" for compatibility with Postfix 2.6 or earlier, or specify a non-empty next-hop filter destination. The content_filter setting has lower precedence than a FILTER action that is specified in an access(5), header_checks(5) or body_checks(5) table. Execute "postfix reload" to complete the change.

Simple content filter performance


With the shell script as shown above you will lose a factor of four in Postfix performance for transit mail that arrives and leaves via SMTP. You will lose another factor in transit performance for each additional temporary file that is created and deleted in the process of content filtering. The performance impact is less for mail that is submitted or delivered locally, because such deliveries are already slower than SMTP transit mail.

Simple content filter limitations


The problem with content filters like the one above is that they are not very robust. The reason is that the software does not talk a well-defined protocol with Postfix. If the filter shell script aborts because the shell runs into some memory allocation problem, the script will not produce a nice exit status as defined in the file /usr/include/sysexits.h. Instead of going to the deferred queue, mail will bounce. The same lack of robustness can happen when the content filtering software itself runs into

a resource problem. The simple content filter method is not suitable for content filter actions that are invoked via header_checks or body_checks patterns. These patterns will be applied again after mail is reinjected with the Postfix sendmail command, resulting in a mail filtering loop. The advanced content filtering method (see below) makes it possible to turn off header_checks or body_checks patterns for filtered mail.

Turning off the simple content filter


To turn off "simple" content filtering: Edit the master.cf file, remove the "-o content_filter=filter:dummy" text from the entry that defines the Postfix SMTP server. Execute "postsuper -r ALL" to remove content filter request records from existing queue files. Execute another "postfix reload".

Advanced content filter example


The second example is more complex, but can give better performance, and is less likely to bounce mail when the machine runs into some resource problem. This content filter receives unfiltered mail with SMTP on localhost port 10025, and sends filtered mail back into Postfix with SMTP on localhost port 10026. For non-SMTP capable content filtering software, Bennett Todd's SMTP proxy implements a nice PERL/SMTP content filtering framework. See: http://bent.latency.net/smtpprox/. In the figure below, names followed by a number represent Postfix commands or daemon programs. See the OVERVIEW document for an introduction to the Postfix architecture. Unfiltered -> smtpd(8) Unfiltered -> pickup(8) >- cleanup(8) -> qmgr(8) Postfix -< queue | v smtp(8) -> Filtered local(8) -> Filtered

^ | smtpd(8) smtp(8) 10026 | ^ | v content filter 10025 The example given here filters all mail, including mail that arrives via SMTP and mail that is locally submitted via the Postfix sendmail command (local submissions enter Postfix via the pickup(8) server; to keep the figure simple we omit local submission details). See examples near the end of this document for how to exclude local users from filtering, or how to configure a destination dependent content filter. You can expect to lose about a factor of two in Postfix performance for mail that arrives and leaves via SMTP, provided that the content filter creates no temporary files. Each temporary file created by the content filter adds another factor to the performance loss.

Advanced content filter: requesting that all mail is filtered


To enable the advanced content filter method for all mail, specify in main.cf:
/etc/postfix/main.cf: content_filter = scan:localhost:10025 receive_override_options = no_address_mappings

The "receive_override_options" line disables address manipulation before the content filter, so that the content filter sees the original mail addresses instead of the result of virtual alias expansion, canonical mapping, automatic bcc, address masquerading, etc. The "content_filter" line causes Postfix to add one content filter request record to each incoming mail message, with content "scan:localhost:10025". The content filter request records are added by the smtpd(8) and pickup(8) servers (and qmqpd(8) if you decide to enable this service). Content filter requests are stored in queue files; this is how Postfix keeps track of what mail needs filtering. When a queue file contains a content filter request, the queue manager will deliver the mail to the specified content filter regardless of its final destination. The content_filter configuration parameter expects a value of the form transport:destination. The transport name specifies the first field of a mail delivery agent definition in master.cf; the syntax of the next-hop destination is described in the manual page of the corresponding delivery agent. The meaning of an empty next-hop filter destination is version dependent. Postfix 2.7 and later will use the recipient domain; earlier versions will use $myhostname. Specify "default_filter_nexthop = $myhostname" for compatibility with Postfix 2.6 or earlier, or specify a non-empty next-hop filter destination. The content_filter setting has lower precedence than a FILTER action that is specified in an access(5), header_checks(5) or body_checks(5) table.

Advanced content filter: sending unfiltered mail to the content filter


In this example, "scan" is an instance of the Postfix SMTP client with slightly different configuration parameters. This is how one would set up the service in the Postfix master.cf file:
/etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= scan unix n 10 smtp -o smtp_send_xforward_command=yes -o disable_mime_output_conversion=yes -o smtp_generic_maps=

This runs up to 10 content filters in parallel. Instead of a limit of 10 concurrent processes, use whatever process limit is feasible for your machine. Content inspection software can gobble up a lot of system resources, so you don't want to have too much of it running at the same time. With "-o smtp_send_xforward_command=yes", the scan transport will try to forward the original client name and IP address through the content filter to the after-filter smtpd process, so that filtered mail is logged with the real client name IP address. See smtp(8) and XFORWARD_README for more information.

The "-o disable_mime_output_conversion=yes" is a workaround that prevents the breaking of domainkeys and other digital signatures. This is needed because some SMTP-based content filters don't announce 8BITMIME support, even though they can handle 8-bit mail. The "-o smtp_generic_maps=" is a workaround that prevents local address rewriting with generic(5) maps. Such rewriting should happen only when mail is sent out to the Internet.

Advanced content filter: running the content filter


The content filter can be set up with the Postfix spawn service, which is the Postfix equivalent of inetd. For example, to instantiate up to 10 content filtering processes on localhost port 10025:
/etc/postfix/master.cf: # =================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # =================================================================== localhost:10025 inet n n n 10 spawn user=filter argv=/path/to/filter localhost 10026

"filter" is a dedicated local user account. The user will never log in, and can be given a "*" password and non-existent shell and home directory. This user handles all potentially dangerous mail content - that is why it should be a separate account. By default, Postfix will terminate a command that runs longer than command_time_limit seconds (default: 1000s). This is a safety measure that prevents filters from running forever. If you want to have your filter listening on port localhost:10025 instead of Postfix, then you must run your filter as a stand-alone program, and must not use the Postfix spawn service.

Advanced filter: injecting mail back into Postfix


The job of the content filter is to either bounce mail with a suitable diagnostic, or to feed the mail back into Postfix through a dedicated listener on port localhost 10026. The simplest content filter just copies SMTP commands and data between its inputs and outputs. If it has a problem, all it has to do is to reply to an input of `.' from Postfix with `550 content rejected', and to disconnect without sending `.' on the connection that injects mail back into Postfix.
/etc/postfix/master.cf: # =================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # =================================================================== localhost:10026 inet n n 10 smtpd -o content_filter= -o receive_override_options=no_unknown_recipient_checks,no_header_body_ch ecks,no_milters -o smtpd_helo_restrictions= -o smtpd_client_restrictions= -o smtpd_sender_restrictions=

-o smtpd_recipient_restrictions=permit_mynetworks,reject -o mynetworks=127.0.0.0/8 -o smtpd_authorized_xforward_hosts=127.0.0.0/8

NOTE: do not use spaces around the "=" or "," characters. NOTE: the SMTP server must not have a smaller process limit than the "filter" master.cf entry. The "-o content_filter=" overrides main.cf settings, and requests no content filtering for mail from the content filter. This is required or else mail will loop. The "-o receive_override_options" overrides main.cf settings to avoid duplicating work that was already done before the content filter. These options are complementary to the options that are specified in main.cf: We specify "no_unknown_recipient_checks" to disable attempts to find out if a recipient is unknown. We specify "no_header_body_checks" to disable header/body checks. We specify "no_milters" to disable Milter applications (this option is available only in Postfix 2.3 and later). We don't specify "no_address_mappings" here. This enables virtual alias expansion, canonical mappings, address masquerading, and other address mappings after the content filter. The main.cf setting of "receive_override_options" disables these mappings before the content filter. These receive override options are either implemented by the SMTP server itself, or they are passed on to the cleanup server. The "-o smtpd_xxx_restrictions" and "-o mynetworks=127.0.0.0/8" override main.cf settings. They turn off junk mail controls that would only waste time here. With "-o smtpd_authorized_xforward_hosts=127.0.0.0/8", the scan transport will try to forward the original client name and IP address to the after-filter smtpd process, so that filtered mail is logged with the real client name and IP address. See XFORWARD_README and smtpd(8).

Advanced content filter performance


With the "sandwich" approach to content filtering described here, it is important to match the filter concurrency to the available CPU, memory and I/O resources. Too few content filter processes and mail accumulates in the active queue even with low traffic volume; too much concurrency and Postfix ends up deferring mail destined for the content filter because processes fail due to insufficient resources. Currently, content filter performance tuning is a process of trial and error; analysis is handicapped because filtered and unfiltered messages share the same queue. As mentioned in the introduction of this document, content filtering with multiple Postfix instances will be covered in a future version.

Turning off the advanced content filter


To turn off "advanced" content filtering: Delete or comment out the two following main.cf lines. The other changes made for advanced content filtering have no effect when content filtering is turned off.

/etc/postfix/main.cf: content_filter = scan:localhost:10025 receive_override_options = no_address_mappings

Execute "postsuper -r ALL" to remove content filter request records from existing queue files. Execute another "postfix reload".

Filtering mail from outside users only


The easiest approach is to configure ONE Postfix instance with multiple SMTP server IP addresses in master.cf: Two SMTP server IP addresses for mail from inside users only, with content filtering turned off.
/etc/postfix.master.cf: # ================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================== 1.2.3.4:smtp inet n n smtpd -o smtpd_client_restrictions=permit_mynetworks,reject 127.0.0.1:smtp inet n n smtpd -o smtpd_client_restrictions=permit_mynetworks,reject

One SMTP server address for mail from outside users with content filtering turned on.
/etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= 1.2.3.5:smtp inet n n smtpd -o content_filter=filter-service:filter-destination -o receive_override_options=no_address_mappings

After this, you can follow the same procedure as outlined in the "advanced" or "simple" content filtering examples above, except that you must not specify "content_filter" or "receive_override_options" in the main.cf file.

Different filters for different domains


If you are an MX service provider and want to apply different content filters for different domains, you can configure ONE Postfix instance with multiple SMTP server IP addresses in master.cf. Each address provides a different content filter service.
/etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= # SMTP service for domains that are filtered with service1:dest1 1.2.3.4:smtp inet n n smtpd -o content_filter=service1:dest1

-o receive_override_options=no_address_mappings # SMTP service for domains that are filtered with service2:dest2 1.2.3.5:smtp inet n n smtpd -o content_filter=service2:dest2 -o receive_override_options=no_address_mappings

After this, you can follow the same procedure as outlined in the "advanced" or "simple" content filtering examples above, except that you must not specify "content_filter" or "receive_override_options" in the main.cf file. Set up MX records in the DNS that route each domain to the proper SMTP server instance.

FILTER actions in access or header/body tables


The above filtering configurations are static. Mail that follows a given path is either always filtered or it is never filtered. As of Postfix 2.0 you can also turn on content filtering on the fly. To turn on content filtering with an access(5) table rule:
/etc/postfix/access: whatever FILTER foo:bar

To turn on content filtering with a header_checks(5) or body_checks(5) table pattern:


/etc/postfix/header_checks: /whatever/ FILTER foo:bar

You can do this in smtpd access maps as well as the cleanup server's header/body_checks. This feature must be used with great care: you must disable all the UCE features in the after-filter smtpd and cleanup daemons or else you will have a content filtering loop. Limitations: FILTER actions from smtpd access maps and header/body_checks take precedence over filters specified with the main.cf content_filter parameter. If a message triggers more than one filter action, only the last one takes effect. The same content filter is applied to all the recipients of a given message.

Postfix Before-Queue Content Filter


WARNING
The before-queue content filtering feature described in this document limits the amount of mail that a site can handle. See the "Pros and Cons" section below for details.

The Postfix before-queue content filter feature


As of version 2.1, the Postfix SMTP server can forward all incoming mail to a content filtering proxy server that inspects all mail BEFORE it is stored in the Postfix mail queue. It is roughly equivalent in capabilities to the approach described in MILTER_README, except that the latter uses a dedicated protocol instead of SMTP. The before-queue content filter is meant to be used as follows: Postfix Before Postfix Postfix smtp - Postfix Internet SMTP queue SMTP cleanup local > > > > > queue < server filter server server virtual The before-queue content filter is not to be confused with the approach described in the FILTER_README document, where mail is filtered AFTER it is stored in the Postfix mail queue. This document describes the following topics: Principles of operation Pros and cons of before-queue content filtering Configuring the Postfix SMTP pass-through proxy feature Configuration parameters How Postfix talks to the before-queue content filter

Principles of operation
As shown in the diagram above, the before-queue filter sits between two Postfix SMTP server processes. The before-filter Postfix SMTP server accepts connections from the Internet and does the usual relay access control, SASL authentication, TLS negotiation, RBL lookups, rejecting non-existent sender or recipient addresses, etc. The before-queue filter receives unfiltered mail content from Postfix and does one of the following: 1. Re-inject the mail back into Postfix via SMTP, perhaps after changing its content and/or destination. 2. Discard or quarantine the mail. 3. Reject the mail by sending a suitable SMTP status code back to Postfix. Postfix

passes the status back to the remote SMTP client. This way, Postfix does not have to send a bounce message. The after-filter Postfix SMTP server receives mail from the content filter. From then on Postfix processes the mail as usual. The before-queue content filter described here works just like the after-queue content filter described in the FILTER_README document. In many cases you can use the same software, within the limitations as discussed in the "Pros and Cons" section below.

Pros and cons of before-queue content filtering


Pro: Postfix can reject mail before the incoming SMTP mail transfer completes, so that Postfix does not have to send rejected mail back to the sender (which is usually forged anyway). Mail that is not accepted remains the responsibility of the remote SMTP client. Con: The remote SMTP client expects an SMTP reply within a deadline. As the system load increases, fewer and fewer CPU cycles remain available to answer within the deadline, and eventually you either have to stop accepting mail or you have to stop filtering mail. It is for this reason that the before-queue content filter limits the amount of mail that a site can handle. Con: Content filtering software can use lots of memory resources. You have to reduce the number of simultaneous content filter processes so that a burst of mail will not drive your system into the ground. With Postfix versions 2.7 and later, SMTP clients will experience an increase in the delay between the time the client sends "end-of-message" and the time the Postfix SMTP server replies (here, the number of before-filter SMTP server processes can be larger than the number of filter processes). With Postfix versions before 2.7, SMTP clients will experience an increase in the delay before they can receive service (here, the number of before-filter SMTP server processes is always equal to the number of filter processes).

Configuring the Postfix SMTP pass-through proxy feature


In the following example, the before-filter Postfix SMTP server gives mail to a content filter that listens on localhost port 10025. The after-filter Postfix SMTP server receives mail from the content filter via localhost port 10026. From then on mail is processed as usual. The content filter itself is not described here. You can use any filter that is SMTP enabled. For nonSMTP capable content filtering software, Bennett Todd's SMTP proxy implements a nice PERL/SMTP content filtering framework. See: http://bent.latency.net/smtpprox/. Postfix Postfix filter on SMTP Postfix Postfix SMTP -> localhost -> server on -> cleanup -> incoming Internet -> server on port 10025 localhost server queue port 25 port 10026 This is configured by editing the master.cf file:
/etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # =============================================================

# # Before-filter SMTP server. Receive mail from the network and # pass it to the content filter on localhost port 10025. # smtp inet n n 20 smtpd -o smtpd_proxy_filter=127.0.0.1:10025 -o smtpd_client_connection_count_limit=10 # Postfix 2.7 and later performance feature. # -o smtpd_proxy_options=speed_adjust # # After-filter SMTP server. Receive mail from the content filter # on localhost port 10026. # 127.0.0.1:10026 inet n n smtpd -o smtpd_authorized_xforward_hosts=127.0.0.0/8 -o smtpd_client_restrictions= -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o smtpd_data_restrictions= -o mynetworks=127.0.0.0/8 -o receive_override_options=no_unknown_recipient_checks

Note: do not specify spaces around the "=" or "," characters. The before-filter SMTP server entry is a modified version of the default Postfix SMTP server entry that is normally configured at the top of the master.cf file: The number of SMTP sessions is reduced from the default 100 to only 20. This prevents a burst of mail from running your system into the ground with too many content filter processes. The "-o smtpd_client_connection_count_limit=10" prevents one SMTP client from using up all 20 SMTP server processes. This limit is not necessary if you receive all mail from a trusted relay host. Note: this setting is available in Postfix version 2.2 and later. Earlier Postfix versions will ignore it. The "-o smtpd_proxy_filter=127.0.0.1:10025" tells the before-filter SMTP server that it should give incoming mail to the content filter that listens on localhost TCP port 10025. The "-o smtpd_proxy_options=speed_adjust" tells the before-filter SMTP server that it should receive an entire email message before it connects to a content filter. This reduces the number of simultaneous filter processes. NOTE 1: When this option is turned on, a content filter must not selectively reject recipients of a multi-recipient message. Rejecting all recipients is OK, as is accepting all recipients. NOTE 2: This feature increases the minimum amount of free queue space by $message_size_limit. The extra space is needed to save the message to a temporary file. Postfix 2.3 supports both TCP and UNIX-domain filters. The above filter could be specified as "inet:127.0.0.1:10025". To specify a UNIX-domain filter, specify "unix:pathname". A relative pathname is interpreted relative to the Postfix queue directory. The after-filter SMTP server is a new master.cf entry: The "127.0.0.1:10026" makes the after-filter SMTP server listen on the localhost address only, without exposing it to the network. NEVER expose the after-filter SMTP server to the Internet :-)

The "-o smtpd_authorized_xforward_hosts=127.0.0.0/8" allows the after-filter SMTP server to receive remote SMTP client information from the before-filter SMTP server, so that the after-filter Postfix daemons log the remote SMTP client information instead of logging localhost[127.0.0.1]. The other after-filter SMTP server settings avoid duplication of work that is already done in the "before filter" SMTP server. By default, the filter has 100 seconds to do its work. If it takes longer then Postfix gives up and reports an error to the remote SMTP client. You can increase this time limit (see configuration parameter section below) but doing so is pointless because you can't control when the remote SMTP client times out.

Configuration parameters
Parameters that control proxying: smtpd_proxy_filter (syntax: host:port): The host and TCP port of the before-queue content filter. When no host or host: is specified here, localhost is assumed. smtpd_proxy_timeout (default: 100s): Timeout for connecting to the before-queue content filter and for sending and receiving commands and data. All proxy errors are logged to the maillog file. For privacy reasons, all the remote SMTP client sees is "451 Error: queue file write error". It would not be right to disclose internal details to strangers. smtpd_proxy_ehlo (default: $myhostname): The hostname to use when sending an EHLO command to the before-queue content filter.

How Postfix talks to the before-queue content filter


The before-filter Postfix SMTP server connects to the content filter, delivers one message, and disconnects. While sending mail into the content filter, Postfix speaks ESMTP but uses no command pipelining. Postfix generates its own EHLO, XFORWARD (for logging the remote client IP address instead of localhost[127.0.0.1]), DATA and QUIT commands, and forwards unmodified copies of all the MAIL FROM and RCPT TO commands that the before-filter Postfix SMTP server didn't reject itself. Postfix sends no other SMTP commands. The content filter should accept the same MAIL FROM and RCPT TO command syntax as the before-filter Postfix SMTP server, and should forward the commands without modification to the after-filter SMTP server. If the content filter or after-filter SMTP server does not support all the ESMTP features that the before-filter Postfix SMTP server supports, then the missing features must be turned off in the before-filter Postfix SMTP server with the smtpd_discard_ehlo_keywords parameter. When the filter rejects content, it should send a negative SMTP response back to the before-filter Postfix SMTP server, and it should abort the connection with the after-filter Postfix SMTP server without completing the SMTP conversation with the after-filter Postfix SMTP server.

Postfix before-queue Milter support


Introduction
Postfix implements support for the Sendmail version 8 Milter (mail filter) protocol. This protocol is used by applications that run outside the MTA to inspect SMTP events (CONNECT, DISCONNECT), SMTP commands (HELO, MAIL FROM, etc.) as well as mail content (headers and body). All this happens before mail is queued. The reason for adding Milter support to Postfix is that there exists a large collection of applications, not only to block unwanted mail, but also to verify authenticity (examples: DomainKeys Identified Mail (DKIM), SenderID+SPF and DomainKeys) or to digitally sign mail (examples: DomainKeys Identified Mail (DKIM), DomainKeys). Having yet another Postfix-specific version of all that software is a poor use of human and system resources. The Milter protocol has evolved over time, and different Postfix versions implement different feature sets. See the workarounds and limitations sections at the end of this document for differences between Postfix and Sendmail implementations. This document provides information on the following topics: How Milter applications plug into Postfix Building Milter applications Running Milter applications Configuring Postfix Workarounds Limitations

How Milter applications plug into Postfix


The Postfix Milter implementation uses two different lists of mail filters: one list of filters for SMTP mail only, and one list of filters for non-SMTP mail. The two lists have different capabilities, which is unfortunate. Avoiding this would require major restructuring of Postfix. The SMTP-only filters handle mail that arrives via the Postfix smtpd(8) server. They are typically used to filter unwanted mail and to sign mail from authorized SMTP clients. You specify SMTP-only Milter applications with the smtpd_milters parameter as described in a later section. Mail that arrives via the Postfix smtpd(8) server is not filtered by the nonSMTP filters that are described next. The non-SMTP filters handle mail that arrives via the Postfix sendmail(1) command-line or via the Postfix qmqpd(8) server. They are typically used to digitally sign mail only. Although non-SMTP filters can be used to filter unwanted mail, they have limitations compared to the SMTP-only filters. You specify non-SMTP Milter applications with the non_smtpd_milters parameter as described in a later section. For those who are familiar with the Postfix architecture, the figure below shows how Milter

applications plug into Postfix. Names followed by a number are Postfix commands or server programs, while unnumbered names inside shaded areas represent Postfix queues. To avoid clutter, the path for local submission is simplified (the OVERVIEW document has a more complete description of the Postfix architecture). SMTP-only filters ^ | | v Network -> Network -> smtpd(8) ^ | | | | | | v cleanup(8) -> incoming non-SMTP filters

Local

->

\ qmqpd(8) -> / pickup(8) : sendmail(1)

Building Milter applications


Milter applications have been written in C, JAVA and Perl, but this document deals with C applications only. For these, you need an object library that implements the Sendmail 8 Milter protocol. Postfix currently does not provide such a library, but Sendmail does. The first option is to use a pre-compiled library. Some systems install the Sendmail libmilter library by default. With other systems, libmilter may be provided by a package (called "sendmail-devel" on some Linux systems). Once libmilter is installed, applications such as dkim-milter and sid-milter build out of the box without requiring any tinkering:
$ gzcat dkim-milter-x.y.z.tar.gz | tar xf $ cd dkim-milter-x.y.z $ make [...lots of output omitted...]

The other option is to build the libmilter library from Sendmail source code:
$ gzcat sendmail-x.y.z.tar.gz | tar xf $ cd sendmail-x.y.z/libmilter $ make [...lots of output omitted...]

After building your own libmilter library, follow the installation instructions in the Milter application source distribution to specify the location of the libmilter include files and object library. Typically, these settings are configured in a file named sidfilter/Makefile.m4 or similar:
APPENDDEF(`confINCDIRS', `-I/some/where/sendmail-x.y.z/include') APPENDDEF(`confLIBDIRS', `-L/some/where/sendmailx.y.z/obj.systemtype/libmilter')

Then build the Milter application.

Running Milter applications


To run a Milter application, see the documentation of the filter for options. A typical command looks like this:
# /some/where/dkim-filter -u userid -p inet:portnumber@localhost ...other options...

Please specify a userid value that isn't used for other applications (not "postfix", not "www", etc.).

Configuring Postfix
Like Sendmail, Postfix has a lot of configuration options that control how it talks to Milter applications. With the initial Postfix Milter protocol implementation, many options are global, that is, they apply to all Milter applications. Future Postfix versions may support per-Milter timeouts, per-Milter error handling, etc. Information in this section: SMTP-Only Milter applications Non-SMTP Milter applications Milter error handling Milter protocol version Milter protocol timeouts Sendmail macro emulation

SMTP-Only Milter applications


The SMTP-only Milter applications handle mail that arrives via the Postfix smtpd(8) server. They are typically used to filter unwanted mail, and to sign mail from authorized SMTP clients. Mail that arrives via the Postfix smtpd(8) server is not filtered by the non-SMTP filters that are described in the next section. NOTE: Do not use the header_checks(5) IGNORE action to remove Postfix's own Received: message header. This causes problems with mail signing filters. Instead, keep Postfix's own Received: message header and use the header_checks(5) REPLACE action to sanitize information. You specify SMTP-only Milter applications (there can be more than one) with the smtpd_milters parameter. Each Milter application is identified by the name of its listening socket; other Milter configuration options will be discussed in later sections. Milter applications are applied in the order as specified, and the first Milter application that rejects a command will override the responses from other Milter applications.
/etc/postfix/main.cf: # Milters for mail that arrives via the smtpd(8) server. # See below for socket address syntax. smtpd_milters = inet:localhost:portnumber ...other filters...

The general syntax for listening sockets is as follows: unix:pathname Connect to the local UNIX-domain server that is bound to the specified pathname. If the smtpd(8) or cleanup(8) process runs chrooted, an absolute pathname is interpreted relative to the Postfix queue directory. inet:host:port

Connect to the specified TCP port on the specified local or remote host. The host and port can be specified in numeric or symbolic form. NOTE: Postfix syntax differs from Milter syntax which has the form inet:port@host.

Non-SMTP Milter applications


The non-SMTP Milter applications handle mail that arrives via the Postfix sendmail(1) commandline or via the Postfix qmqpd(8) server. They are typically used to digitally sign mail. Although nonSMTP filters can be used to filter unwanted mail, there are limitations as discussed later in this section. Mail that arrives via the Postfix smtpd(8) server is not filtered by the non-SMTP filters. NOTE: Do not use the header_checks(5) IGNORE action to remove Postfix's own Received: message header. This causes problems with mail signing filters. Instead, keep Postfix's own Received: message header and use the header_checks(5) REPLACE action to sanitize information. You specify non-SMTP Milter applications with the non_smtpd_milters parameter. This parameter uses the same syntax as the smtpd_milters parameter in the previous section. As with the SMTPonly filters, you can specify more than one Milter application; they are applied in the order as specified, and the first Milter application that rejects a command will override the responses from the other applications.
/etc/postfix/main.cf: # Milters for non-SMTP mail. # See below for socket address syntax. non_smtpd_milters = inet:localhost:portnumber ...other filters...

There's one small complication when using Milter applications for non-SMTP mail: there is no SMTP session. To keep Milter applications happy, the Postfix cleanup(8) server actually has to simulate the SMTP client CONNECT and DISCONNECT events, and the SMTP client EHLO, MAIL FROM, RCPT TO and DATA commands. When new mail arrives via the sendmail(1) command line, the Postfix cleanup(8) server pretends that the mail arrives with ESMTP from "localhost" with IP address "127.0.0.1". The result is very similar to what happens with command line submissions in Sendmail version 8.12 and later, although Sendmail uses a different mechanism to achieve this result. When new mail arrives via the qmqpd(8) server, the Postfix cleanup(8) server pretends that the mail arrives with ESMTP, and uses the QMQPD client hostname and IP address. When old mail is re-injected into the queue with "postsuper -r", the Postfix cleanup(8) server uses the same client information that was used when the mail arrived as new mail. This generally works as expected, with only one exception: non-SMTP filters must not REJECT or TEMPFAIL simulated RCPT TO commands. When a non_smtpd_milters application REJECTs or TEMPFAILs a recipient, Postfix will report a configuration error, and mail will stay in the queue. None of this is a problem for mail filters that digitally sign mail.

Milter error handling


The milter_default_action parameter specifies how Postfix handles Milter application errors. The default action is to respond with a temporary error status, so that the client will try again later. Specify "accept" if you want to receive mail as if the filter does not exist, and "reject" to reject mail with a permanent status. The "quarantine" action is like "accept" but freezes the message in the "hold" queue, and is available with Postfix 2.6 or later.

/etc/postfix/main.cf: # What to do in case of errors? Specify accept, reject, tempfail, # or quarantine (Postfix 2.6 or later). milter_default_action = tempfail

Milter protocol version


As Postfix is not built with the Sendmail libmilter library, you may need to configure the Milter protocol version that Postfix should use. The default version is 6 (before Postfix 2.6 the default version is 2).
/etc/postfix/main.cf: # Postfix 2.6 milter_protocol = 6 # 2.3 Postfix 2.5 milter_protocol = 2

If the Postfix milter_protocol setting specifies a too low version, the libmilter library will log an error message like this:
application name: st_optionneg[xxxxx]: 0xyy does not fulfill action requirements 0xzz

The remedy is to increase the Postfix milter_protocol version number. See, however, the limitations section below for features that aren't supported by Postfix. With Postfix 2.7 and earlier, if the Postfix milter_protocol setting specifies a too high version, the libmilter library simply hangs up without logging a warning, and you see a Postfix warning message like one of the following:
warning: milter error : 0 warning: milter warning: milter header: No such inet:host:port: can't read packet header: Unknown inet:host:port: can't read packet header: Success inet:host:port: can't read SMFIC_DATA reply packet file or directory

The remedy is to lower the Postfix milter_protocol version number. Postfix 2.8 and later will automatically turn off protocol features that the application's libmilter library does not expect.

Milter protocol timeouts


Postfix uses different time limits at different Milter protocol stages. The table shows the timeout settings and the corresponding protocol stages (EOH = end of headers; EOM = end of message). Postfix parameter milter_connect_timeout Time limit 30s CONNECT HELO, MAIL, RCPT, DATA, UNKNOWN Milter protocol stage

milter_command_timeout 30s

milter_content_timeout 300s HEADER, EOH, BODY, EOM Beware: 30s may be too short for Milter applications that do lots of DNS lookups. However, if you increase the above timeouts too much, remote SMTP clients may hang up and mail may be delivered multiple times. This is an inherent problem with before-queue filtering.

Sendmail macro emulation


Postfix emulates a limited number of Sendmail macros, as shown in the table. Some macro values

depend on whether a recipient is rejected (rejected recipients are available on request by the Milter application). Different macros are available at different Milter protocol stages (EOH = end-ofheader, EOM = end-of-message); their availability is not always the same as in Sendmail. See the workarounds section below for solutions. Sendmail macro i j _ {auth_authen} {auth_author} {auth_type} {client_addr} Milter protocol stage DATA, EOH, EOM Always Always Description Queue ID, also Postfix queue file name Value of myhostname The validated client name and address

MAIL, DATA, EOH, EOM SASL login name MAIL, DATA, EOH, EOM SASL sender MAIL, DATA, EOH, EOM SASL login method Always Client IP address Connection concurrency for this client Client hostname When address name lookup or name address verification fails: "unknown" Client TCP port

{client_connecti CONNECT ons} {client_name} {client_port} {client_ptr} Always Always (Postfix 2.5)

Client name from address name CONNECT, HELO, MAIL, lookup DATA When address name lookup fails: "unknown" HELO, MAIL, DATA, EOH, EOM HELO, MAIL, DATA, EOH, EOM HELO, MAIL, DATA, EOH, EOM HELO, MAIL, DATA, EOH, EOM TLS client certificate issuer TLS client certificate subject TLS session key size TLS cipher value of milter_macro_daemon_name Sender address

{cert_issuer} {cert_subject} {cipher_bits} {cipher}

{daemon_name Always } {mail_addr} {mail_host} {mail_mailer} {rcpt_addr} {rcpt_host} MAIL

MAIL (Postfix 2.6, only Sender next-hop destination with smtpd_milters) MAIL (Postfix 2.6, only Sender mail delivery transport with smtpd_milters) RCPT Recipient address With rejected recipient: descriptive text

Recipient next-hop destination RCPT (Postfix 2.6, only With rejected recipient: enhanced status with smtpd_milters) code

{rcpt_mailer} {tls_version}

RCPT (Postfix 2.6, only Recipient mail delivery transport with smtpd_milters) With rejected recipient: "error" HELO, MAIL, DATA, EOH, EOM TLS protocol version

v Always value of milter_macro_v Postfix sends specific sets of macros at different Milter protocol stages. The sets are configured with the parameters as described in the table (EOH = end of headers; EOM = end of message). The protocol version is a number that Postfix sends at the beginning of the Milter protocol handshake. As of Sendmail 8.14.0, Milter applications can specify what macros they want to receive at different Milter protocol stages. An application-specified list takes precedence over a Postfix-specified list. Postfix parameter milter_connect_macros milter_helo_macros milter_mail_macros milter_rcpt_macros milter_data_macros milter_end_of_header_macros milter_end_of_data_macros Milter protocol version Milter protocol stage 2 or higher 2 or higher 2 or higher 2 or higher 4 or higher 6 or higher 2 or higher CONNECT HELO/EHLO MAIL FROM RCPT TO DATA EOH EOM unknown command

milter_unknown_command_macros 3 or higher

Workarounds
To avoid breaking DKIM etc. signatures with an SMTP-based content filter, update the before-filter SMTP client in master.cf, and add a line with "-o disable_mime_output_conversion=yes" (note: no spaces around the "="). For details, see the advanced content filter example.
/etc/postfix/master.cf: # ============================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ============================================================= scan unix n 10 smtp -o smtp_send_xforward_command=yes -o disable_mime_output_conversion=yes -o smtp_generic_maps=

Some Milter applications use the "{if_addr}" macro to recognize local mail; this macro does not exist in Postfix. Workaround: use the "{client_addr}" macro instead. Some Milter applications log a warning that looks like this:
sid-filter[36540]: WARNING: sendmail symbol 'i' not available

And they may insert an ugly message header with "unknown-msgid" like this:
X-SenderID: Sendmail Sender-ID Filter vx.y.z host.example.com <unknown-msgid>

The problem is that Milter applications expect that the queue ID is known before the MTA

accepts the MAIL FROM (sender) command. Postfix does not choose a queue ID, which is used as the queue file name, until after it accepts the first valid RCPT TO (recipient) command. If you experience the ugly header problem, see if a recent version of the Milter application fixes it. For example, current versions of dkim-filter and dk-filter already have code that looks up the Postfix queue ID at a later protocol stage, and sid-filter version 1.0.0 no longer includes the queue ID in the message header. To fix the ugly message header, you will need to add code that looks up the Postfix queue ID at some later point in time. The example below adds the lookup after the end-of-message. Edit the filter source file (typically named xxx-filter/xxx-filter.c or similar). Look up the mlfi_eom() function and add code near the top shown as bold text below:
dfc = cc->cctx_msg; assert(dfc != NULL); /* Determine the job ID for logging. */ if (dfc->mctx_jobid == 0 || strcmp(dfc->mctx_jobid, JOBIDUNKNOWN) == 0) { char *jobid = smfi_getsymval(ctx, "i"); if (jobid != 0) dfc->mctx_jobid = jobid; }

NOTES: Different mail filters use slightly different names for variables. If the above code does not compile, look elsewhere in the mail filter source file for code that looks up the "i" macro value, and copy that code. This change fixes only the ugly message header, but not the WARNING message. Fortunately, many Milters log that message only once.

Limitations
This section lists limitations of the Postfix Milter implementation. Some limitations will be removed as the implementation is extended over time. Of course the usual limitations of beforequeue filtering will always apply. See the CONTENT_INSPECTION_README document for a discussion. The Milter protocol has evolved over time. Therefore, different Postfix versions implement different feature sets. Postfix 2.6 2.5 2.4 2.3 Supported Milter requests All Milter requests of Sendmail 8.14.0 (see notes below). All Milter requests of Sendmail 8.14.0, except: SMFIP_RCPT_REJ (report rejected recipients to the mail filter), SMFIR_CHGFROM (replace sender, with optional ESMTP parameters), SMFIR_ADDRCPT_PAR (add recipient, with optional ESMTP parameters). All Milter requests of Sendmail 8.13.0. All Milter requests of Sendmail 8.13.0, except:

SMFIR_REPLBODY (replace message body). For Milter applications that are written in C, you need to use the Sendmail libmilter library. Postfix has TWO sets of mail filters: filters that are used for SMTP mail only (specified with the smtpd_milters parameter), and filters for non-SMTP mail (specified with the non_smtpd_milters parameter). The non-SMTP filters are primarily for local submissions. When mail is filtered by non_smtpd_milters, the Postfix cleanup(8) server has to simulate SMTP client requests. This works as expected, with only one exception: non_smtpd_milters must not REJECT or TEMPFAIL simulated RCPT TO commands. When this rule is violated, Postfix will report a configuration error, and mail will stay in the queue. Postfix currently does not apply content filters to mail that is forwarded or aliased internally, or to mail that is generated internally such as bounces or Postmaster notifications. This may be a problem when you want to apply a signing Milter to such mail. When you use the before-queue content filter for incoming SMTP mail (see SMTPD_PROXY_README), Milter applications have access only to the SMTP command information; they have no access to the message header or body, and cannot make modifications to the message or to the envelope. Postfix 2.6 ignores the optional ESMTP parameters in requests to replace the sender (SMFIR_CHGFROM) or to append a recipient (SMFIR_ADDRCPT_PAR). Postfix logs a warning message when a Milter application supplies such ESMTP parameters:
warning: queue-id: cleanup_chg_from: ignoring ESMTP arguments "whatever" warning: queue-id: cleanup_add_rcpt: ignoring ESMTP arguments "whatever"

Postfix 2.3 does not implement requests to replace the message body. Milter applications log a warning message when they need this unsupported operation:
st_optionneg[134563840]: 0x3d does not fulfill action requirements 0x1e

The solution is to use Postfix version 2.4 or later. Most Milter configuration options are global. Future Postfix versions may support per-Milter timeouts, per-Milter error handling, etc.

Postfix SMTP relay and access control


Introduction
The Postfix SMTP server receives mail from the network and is exposed to the big bad world of junk email and viruses. This document introduces the built-in and external methods that control what SMTP mail Postfix will accept, what mistakes to avoid, and how to test your configuration. Topics covered in this document: Relay control, junk mail control, and per-user policies Restrictions that apply to all SMTP mail Getting selective with SMTP access restriction lists Delayed evaluation of SMTP access restriction lists Dangerous use of smtpd_recipient_restrictions SMTP access rule testing

Relay control, junk mail control, and per-user policies


In a distant past, the Internet was a friendly environment. Mail servers happily forwarded mail on behalf of anyone towards any destination. On today's Internet, spammers abuse servers that forward mail from arbitrary systems, and abused systems end up on anti-spammer blacklists. See, for example, the information on http://www.mail-abuse.org/ and other websites. By default, Postfix has a moderately restrictive approach to mail relaying. Postfix forwards mail only from clients in trusted networks, or to domains that are configured as authorized relay destinations. For a description of the default policy, see the smtpd_recipient_restrictions parameter in the postconf(5) manual page, and the information that is referenced from there. Most of the Postfix SMTP server access controls are targeted at stopping junk email. Protocol oriented: some SMTP server access controls block mail by being very strict with respect to the SMTP protocol; these catch poorly implemented and/or poorly configured junk email software, as well as email worms that come with their own non-standard SMTP client implementations. Protocol-oriented access controls become less useful over time as spammers and worm writers learn to read RFC documents. Blacklist oriented: some SMTP server access controls query blacklists with known to be bad sites such as open mail relays, open web proxies, and home computers that have been compromised and that are under remote control by criminals. The effectiveness of these blacklists depends on how complete and how up to date they are. Threshold oriented: some SMTP server access controls attempt to raise the bar by either making the client do more work (greylisting) or by asking for a second opinion (SPF and sender/recipient address verification). The greylisting and SPF policies are implemented externally, and are the subject of the SMTPD_POLICY_README document. Sender/recipient address verification is the subject of the

ADDRESS_VERIFICATION_README document. Unfortunately, all junk mail controls have the possibility of falsely rejecting legitimate mail. This can be a problem for sites with many different types of users. For some users it is unacceptable when any junk email slips through, while for other users the world comes to an end when a single legitimate email message is blocked. Because there is no single policy that is "right" for all users, Postfix supports different SMTP access restrictions for different users. This is described in the RESTRICTION_CLASS_README document.

Restrictions that apply to all SMTP mail


Besides the restrictions that can be made configurable per client or per user as described in the next section, Postfix implements a few restrictions that apply to all SMTP mail. The built-in header_checks and body_checks content restrictions, as described in the BUILTIN_FILTER_README document. This happens while Postfix receives mail, before it is stored in the incoming queue. The external before-queue content restrictions, as described in the SMTPD_PROXY_README document. This happens while Postfix receives mail, before it is stored in the incoming queue. Requiring that the client sends the HELO or EHLO command before sending the MAIL FROM or ETRN command. This may cause problems with home-grown applications that send mail. For this reason, the requirement is disabled by default ("smtpd_helo_required = no"). Disallowing illegal syntax in MAIL FROM or RCPT TO commands. This may cause problems with home-grown applications that send mail, and with ancient PC mail clients. For this reason, the requirement is disabled by default ("strict_rfc821_envelopes = no"). Disallowing RFC 822 address syntax (example: "MAIL FROM: the dude <dude@example.com>"). Disallowing addresses that are not enclosed with <> (example: "MAIL FROM: dude@example.com"). Rejecting mail from a non-existent sender address. This form of egress filtering helps to slow down worms and other malware, but may cause problems with home-grown software that sends out mail software with an unreplyable address. For this reason the requirement is disabled by default ("smtpd_reject_unlisted_sender = no"). Rejecting mail for a non-existent recipient address. This form of ingress filtering helps to keep the mail queue free of undeliverable MAILER-DAEMON messages. This requirement is enabled by default ("smtpd_reject_unlisted_recipient = yes").

Getting selective with SMTP access restriction lists


Postfix allows you to specify lists of access restrictions for each stage of the SMTP conversation. Individual restrictions are described in the postconf(5) manual page. Examples of simple restriction lists are:
/etc/postfix/main.cf: # Allow connections from trusted networks only. smtpd_client_restrictions = permit_mynetworks, reject # Don't talk to mail systems that don't know their own hostname.

# With Postfix < 2.3, specify reject_unknown_hostname. smtpd_helo_restrictions = reject_unknown_helo_hostname # Don't accept mail from domains that don't exist. smtpd_sender_restrictions = reject_unknown_sender_domain # Whitelisting: local clients may specify any destination domain. smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination # Block clients that speak too early. smtpd_data_restrictions = reject_unauth_pipelining # Enforce mail volume quota via policy service callouts. smtpd_end_of_data_restrictions = check_policy_service unix:private/policy

Each restriction list is evaluated from left to right until some restriction produces a result of PERMIT, REJECT or DEFER (try again later). The end of the list is equivalent to a PERMIT result. By placing a PERMIT restriction before a REJECT restriction you can make exceptions for specific clients or users. This is called whitelisting; the fourth example above allows mail from local networks but otherwise rejects mail to arbitrary destinations. The table below summarizes the purpose of each SMTP access restriction list. All lists use the exact same syntax; they differ only in the time of evaluation and in the effect of a REJECT or DEFER result. Restriction list name smtpd_client_restrictions smtpd_helo_restrictions smtpd_sender_restrictions smtpd_recipient_restrictions smtpd_data_restrictions smtpd_etrn_restrictions Status Effect of REJECT or DEFER result Optional Reject all client commands Optional Reject HELO/EHLO information Optional Reject MAIL FROM information Required Reject RCPT TO information Optional Reject DATA command Optional Reject ETRN command

smtpd_end_of_data_restrictions Optional Reject END-OF-DATA command

Delayed evaluation of SMTP access restriction lists


Early Postfix versions evaluated SMTP access restrictions lists as early as possible. The client restriction list was evaluated before Postfix sent the "220 $myhostname..." greeting banner to the SMTP client, the helo restriction list was evaluated before Postfix replied to the HELO (EHLO) command, the sender restriction list was evaluated before Postfix replied to the MAIL FROM command, and so on. This approach turned out to be difficult to use. Current Postfix versions postpone the evaluation of client, helo and sender restriction lists until the RCPT TO or ETRN command. This behavior is controlled by the smtpd_delay_reject parameter. Restriction lists are still evaluated in the proper order of (client, helo, etrn) or (client, helo, sender, recipient, data, or end-of-data) restrictions. When a restriction list (example: client) evaluates to REJECT or DEFER the other restriction lists (example: helo, sender, etc.) are skipped. Around the time that smtpd_delay_reject was introduced, Postfix was also changed to support mixed restriction lists that combine information about the client, helo, sender and recipient or etrn command. Benefits of delayed restriction evaluation, and of restriction mixing: Some SMTP clients do not expect a negative reply early in the SMTP session. When the bad

news is postponed until the RCPT TO reply, the client goes away as it is supposed to, instead of hanging around until a timeout happens, or worse, going into an endless connect-rejectconnect loop. Postfix can log more useful information. For example, when Postfix rejects a client name or address and delays the action until the RCPT TO command, it can log the sender and the recipient address. This is more useful than logging only the client hostname and IP address and not knowing whose mail was being blocked. Mixing is needed for complex whitelisting policies. For example, in order to reject local sender addresses in mail from non-local clients, you need to be able to mix restrictions on client information with restrictions on sender information in the same restriction list. Without this ability, many per-user access restrictions would be impossible to express.

Dangerous use of smtpd_recipient_restrictions


By now the reader may wonder why we need smtpd client, helo or sender restrictions, when their evaluation is postponed until the RCPT TO or ETRN command. Some people recommend placing ALL the access restrictions in the smtpd_recipient_restrictions list. Unfortunately, this can result in too permissive access. How is this possible? The purpose of the smtpd_recipient_restrictions feature is to control how Postfix replies to the RCPT TO command. If the restriction list evaluates to REJECT or DEFER, the recipient address is rejected; no surprises here. If the result is PERMIT, then the recipient address is accepted. And this is where surprises can happen. Here is an example that shows when a PERMIT result can result in too much access permission:
1 /etc/postfix/main.cf: 2 smtpd_recipient_restrictions = 3 permit_mynetworks 4 check_helo_access hash:/etc/postfix/helo_access 5 reject_unknown_helo_hostname 6 reject_unauth_destination 7 8 /etc/postfix/helo_access: 9 localhost.localdomain PERMIT

Line 5 rejects mail from hosts that don't specify a proper hostname in the HELO command (with Postfix < 2.3, specify reject_unknown_hostname). Lines 4 and 9 make an exception to allow mail from some machine that announces itself with "HELO localhost.localdomain". The problem with this configuration is that smtpd_recipient_restrictions evaluates to PERMIT for EVERY host that announces itself as "localhost.localdomain", making Postfix an open relay for all such hosts. In order to avoid surprises like these with smtpd_recipient_restrictions, you should place nonrecipient restrictions AFTER the reject_unauth_destination restriction, not before. In the above example, the HELO based restrictions should be placed AFTER reject_unauth_destination, or better, the HELO based restrictions should be placed under smtpd_helo_restrictions where they can do no harm.

SMTP access rule testing


Postfix has several features that aid in SMTP access rule testing: soft_bounce

This is a safety net that changes SMTP server REJECT actions into DEFER (try again later) actions. This keeps mail queued that would otherwise be returned to the sender. Specify "soft_bounce = yes" in the main.cf file to prevent the Postfix SMTP server from rejecting mail permanently, by changing all 5xx SMTP reply codes into 4xx. warn_if_reject This is a different safety net that changes SMTP server REJECT actions into warnings. Instead of rejecting a command, Postfix logs what it would reject. Specify "warn_if_reject" in an SMTP access restriction list, before the restriction that you want to test without actually rejecting mail. XCLIENT With this Postfix 2.1 feature, authorized SMTP clients can impersonate other systems, so that you can do realistic SMTP access rule tests. Examples of how to impersonate other systems for access rule testing are given at the end of the XCLIENT_README document.

Postfix SMTP Access Policy Delegation


Purpose of Postfix SMTP access policy delegation
The Postfix SMTP server has a number of built-in mechanisms to block or accept mail at specific SMTP protocol stages. As of version 2.1, Postfix can delegate policy decisions to an external server that runs outside Postfix. With this policy delegation mechanism, a simple greylist policy can be implemented with only a dozen lines of Perl, as is shown at the end of this document. A complete example can be found in the Postfix source code, in the directory examples/smtpd-policy. Another example of policy delegation is the SPF policy server at http://www.openspf.org/Software. Policy delegation is now the preferred method for adding policies to Postfix. It's much easier to develop a new feature in few lines of Perl, Python, Ruby, or TCL, than trying to do the same in C code. The difference in performance will be unnoticeable except in the most demanding environments. On active systems a policy daemon process is used multiple times, for up to $max_use incoming SMTP connections. This document covers the following topics: Policy protocol description Policy client/server configuration Example: greylist policy server Greylisting mail from frequently forged domains Greylisting all your mail Routine greylist maintenance Example Perl greylist server

Protocol description
The Postfix policy delegation protocol is really simple. The client request is a sequence of name=value attributes separated by newline, and is terminated by an empty line. The server reply is one name=value attribute and it, too, is terminated by an empty line. Here is an example of all the attributes that the Postfix SMTP server sends in a delegated SMTPD access policy request:
Postfix version 2.1 and later: request=smtpd_access_policy protocol_state=RCPT protocol_name=SMTP helo_name=some.domain.tld queue_id=8045F2AB23 sender=foo@bar.tld recipient=bar@foo.tld recipient_count=0

client_address=1.2.3.4 client_name=another.domain.tld reverse_client_name=another.domain.tld instance=123.456.7 Postfix version 2.2 and later: sasl_method=plain sasl_username=you sasl_sender= size=12345 ccert_subject=solaris9.porcupine.org ccert_issuer=Wietse+20Venema ccert_fingerprint=C2:9D:F4:87:71:73:73:D9:18:E7:C2:F3:C1:DA:6E:04 Postfix version 2.3 and later: encryption_protocol=TLSv1/SSLv3 encryption_cipher=DHE-RSA-AES256-SHA encryption_keysize=256 etrn_domain= Postfix version 2.5 and later: stress= [empty line]

Notes: The "request" attribute is required. In this example the request type is "smtpd_access_policy". The order of the attributes does not matter. The policy server should ignore any attributes that it does not care about. When the same attribute name is sent more than once, the server may keep the first value or the last attribute value. When an attribute value is unavailable, the client either does not send the attribute, sends the attribute with an empty value ("name="), or sends a zero value ("name=0") in the case of a numerical attribute. The "recipient" attribute is available in the "RCPT TO" stage. It is also available in the "DATA" and "END-OF-MESSAGE" stages if Postfix accepted only one recipient for the current message. The "recipient_count" attribute (Postfix 2.3 and later) is non-zero only in the "DATA" and "END-OF-MESSAGE" stages. It specifies the number of recipients that Postfix accepted for the current message. The client address is an IPv4 dotted quad in the form 1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6. For a discussion of the differences between reverse and verified client_name information, see the reject_unknown_client_hostname discussion in the postconf(5) document. An attribute name must not contain "=", null or newline, and an attribute value must not contain null or newline. The "instance" attribute value can be used to correlate different requests regarding the same message delivery. These requests are sent over the same policy connection (unless the policy daemon terminates the connection). Once Postfix sends a query with a different instance attribute over that same policy connection, the previous message delivery is either completed or aborted. The "size" attribute value specifies the message size that the client specified in the MAIL FROM command (zero if none was specified). With Postfix 2.2 and later, it specifies the

actual message size when the client sends the END-OF-DATA command. The "sasl_*" attributes (Postfix 2.2 and later) specify information about how the client was authenticated via SASL. These attributes are empty in case of no SASL authentication. The "ccert_*" attributes (Postfix 2.2 and later) specify information about how the client was authenticated via TLS. These attributes are empty in case of no certificate authentication. As of Postfix 2.2.11 these attribute values are encoded as xtext: some characters are represented by +XX, where XX is the two-digit hexadecimal representation of the character value. With Postfix 2.6 and later, the decoded string is an UTF-8 string without non-printable ASCII characters. The "encryption_*" attributes (Postfix 2.3 and later) specify information about how the connection is encrypted. With plaintext connections the protocol and cipher attributes are empty and the keysize is zero. The "etrn_domain" attribute is defined only in the context of the ETRN command, and specifies the ETRN command parameter. The "stress" attribute is either empty or "yes". See the STRESS_README document for further information. The following is specific to SMTPD delegated policy requests: Protocol names are ESMTP or SMTP. Protocol states are CONNECT, EHLO, HELO, MAIL, RCPT, DATA, END-OF-MESSAGE, VRFY or ETRN; these are the SMTP protocol states where the Postfix SMTP server makes an OK/REJECT/HOLD/etc. decision. The policy server replies with any action that is allowed in a Postfix SMTPD access(5) table. Example:
action=defer_if_permit Service temporarily unavailable [empty line]

This causes the Postfix SMTP server to reject the request with a 450 temporary error code and with text "Service temporarily unavailable", if the Postfix SMTP server finds no reason to reject the request permanently. In case of trouble the policy server must not send a reply. Instead the server must log a warning and disconnect. Postfix will retry the request at some later time.

Policy client/server configuration


The Postfix delegated policy client can connect to a TCP socket or to a UNIX-domain socket. Examples:
inet:127.0.0.1:9998 unix:/some/where/policy unix:private/policy

The first example specifies that the policy server listens on a TCP socket at 127.0.0.1 port 9998. The second example specifies an absolute pathname of a UNIX-domain socket. The third example specifies a pathname relative to the Postfix queue directory; use this for policy servers that are spawned by the Postfix master daemon. To create a policy service that listens on a UNIX-domain socket called "policy", and that runs under control of the Postfix spawn(8) daemon, you would use something like this:

1 /etc/postfix/master.cf: 2 policy unix n n 3 user=nobody argv=/some/where/policy-server 4 5 /etc/postfix/main.cf: 6 smtpd_recipient_restrictions = 7 ... 8 reject_unauth_destination 9 check_policy_service unix:private/policy 10 ... 11 policy_time_limit = 3600

spawn

NOTES: Lines 2, 11: the Postfix spawn(8) daemon by default kills its child process after 1000 seconds. This is too short for a policy daemon that may need to run for as long as the SMTP server process that talks to it. The default time limit is overruled in main.cf with an explicit "policy_time_limit" setting. The name of the parameter is the name of the master.cf entry ("policy") concatenated with the "_time_limit" suffix. See spawn(8) for more information about the time limit parameter. Line 2: specify a "0" process limit instead of the default "-", to avoid "connection refused" and other problems when the smtpd process limit exceeds the default_process_limit setting. Lines 8, 9: always specify "check_policy_service" AFTER "reject_unauth_destination" or else your system could become an open relay. Solaris UNIX-domain sockets do not work reliably. Use TCP sockets instead:
1 /etc/postfix/master.cf: 2 127.0.0.1:9998 inet n n n spawn 3 user=nobody argv=/some/where/policy-server 4 5 /etc/postfix/main.cf: 6 smtpd_recipient_restrictions = 7 ... 8 reject_unauth_destination 9 check_policy_service inet:127.0.0.1:9998 10 ... 11 127.0.0.1:9998_time_limit = 3600 0

Other configuration parameters that control the client side of the policy delegation protocol: smtpd_policy_service_max_idle (default: 300s): The amount of time before the Postfix SMTP server closes an unused policy client connection. smtpd_policy_service_max_ttl (default: 1000s): The amount of time before the Postfix SMTP server closes an active policy client connection. smtpd_policy_service_timeout (default: 100s): The time limit to connect to, send to or receive from a policy server.

Example: greylist policy server


Greylisting is a defense against junk email that is described at http://www.greylisting.org/. The idea was discussed on the postfix-users mailing list one year before it was popularized. The file examples/smtpd-policy/greylist.pl in the Postfix source tree implements a simplified greylist policy server. This server stores a time stamp for every (client, sender, recipient) triple. By

default, mail is not accepted until a time stamp is more than 60 seconds old. This stops junk mail with randomly selected sender addresses, and mail that is sent through randomly selected open proxies. It also stops junk mail from spammers that change their IP address frequently. Copy examples/smtpd-policy/greylist.pl to /usr/libexec/postfix or whatever location is appropriate for your system. In the greylist.pl Perl script you need to specify the location of the greylist database file, and how long mail will be delayed before it is accepted. The default settings are:
$database_name="/var/mta/greylist.db"; $greylist_delay=60;

The /var/mta directory (or whatever you choose) should be writable by "nobody", or by whatever username you configure below in master.cf for the policy service. Example:
# mkdir /var/mta # chown nobody /var/mta

Note: DO NOT create the greylist database in a world-writable directory such as /tmp or /var/tmp, and DO NOT create the greylist database in a file system that may run out of space. Postfix can survive "out of space" conditions with the mail queue and with the mailbox store, but it cannot survive a corrupted greylist database. If the file becomes corrupted you may not be able to receive mail at all until you delete the file by hand. The greylist.pl Perl script can be run under control by the Postfix master daemon. For example, to run the script as user "nobody", using a UNIX-domain socket that is accessible by Postfix processes only:
1 /etc/postfix/master.cf: 2 policy unix n n 3 user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl 4 5 /etc/postfix/main.cf: 6 policy_time_limit = 3600 0 spawn

Notes: Line 3: Specify "greylist.pl -v" for verbose logging of each request and reply. Lines 2, 6: the Postfix spawn(8) daemon by default kills its child process after 1000 seconds. This is too short for a policy daemon that may run for as long as an SMTP client is connected to an SMTP server process. The default time limit is overruled in main.cf with an explicit "policy_time_limit" setting. The name of the parameter is the name of the master.cf entry ("policy") concatenated with the "_time_limit" suffix. Line 2: specify a "0" process limit instead of the default "-", to avoid "connection refused" and other problems when the smtpd process limit exceeds the default_process_limit setting. On Solaris you must use inet: style sockets instead of unix: style, as detailed in the "Policy client/server configuration" section above.
1 /etc/postfix/master.cf: 2 127.0.0.1:9998 inet n n spawn 3 user=nobody argv=/usr/bin/perl /usr/libexec/postfix/greylist.pl 4 5 /etc/postfix/main.cf: n 0

127.0.0.1:9998_time_limit = 3600

To invoke this service you would specify "check_policy_service inet:127.0.0.1:9998".

Greylisting mail from frequently forged domains


It is relatively safe to turn on greylisting for specific domains that often appear in forged email. At some point in cyberspace/time a list of frequently forged MAIL FROM domains could be found at http://www.monkeys.com/anti-spam/filtering/sender-domain-validate.in.
1 /etc/postfix/main.cf: 2 smtpd_recipient_restrictions = 3 reject_unlisted_recipient 4 ... 5 reject_unauth_destination 6 check_sender_access hash:/etc/postfix/sender_access 7 ... 8 smtpd_restriction_classes = greylist 9 greylist = check_policy_service unix:private/policy 10 11 /etc/postfix/sender_access: 12 aol.com greylist 13 hotmail.com greylist 14 bigfoot.com greylist 15 ... etcetera ...

NOTES: Line 9: On Solaris you must use inet: style sockets instead of unix: style, as detailed in the "Example: greylist policy server" section above. Line 6: Be sure to specify "check_sender_access" AFTER "reject_unauth_destination" or else your system could become an open mail relay. Line 3: With Postfix 2.0 snapshot releases, "reject_unlisted_recipient" is called "check_recipient_maps". Postfix 2.1 understands both forms. Line 3: The greylist database gets polluted quickly with bogus addresses. It helps if you protect greylist lookups with other restrictions that reject unknown senders and/or recipients.

Greylisting all your mail


If you turn on greylisting for all mail you will almost certainly want to make exceptions for mailing lists that use one-time sender addresses, because such mailing lists can pollute your greylist database relatively quickly.
1 /etc/postfix/main.cf: 2 smtpd_recipient_restrictions = 3 reject_unlisted_recipient 4 ... 5 reject_unauth_destination 6 check_sender_access hash:/etc/postfix/sender_access 7 check_policy_service unix:private/policy 8 ... 9 10 /etc/postfix/sender_access: 11 securityfocus.com OK 12 ...

NOTES: Line 7: On Solaris you must use inet: style sockets instead of unix: style, as detailed in the "Example: greylist policy server" section above. Lines 6-7: Be sure to specify check_sender_access and check_policy_service AFTER reject_unauth_destination or else your system could become an open mail relay. Line 3: The greylist database gets polluted quickly with bogus addresses. It helps if you precede greylist lookups with restrictions that reject unknown senders and/or recipients.

Routine greylist maintenance


The greylist database grows over time, because the greylist server never removes database entries. If left unattended, the greylist database will eventually run your file system out of space. When the status file size exceeds some threshold you can simply rename or remove the file without adverse effects; Postfix automatically creates a new file. In the worst case, new mail will be delayed by an hour or so. To lessen the impact, rename or remove the file in the middle of the night at the beginning of a weekend.

Example Perl greylist server


This is the Perl subroutine that implements the example greylist policy. It is part of a general purpose sample policy server that is distributed with the Postfix source as examples/smtpdpolicy/greylist.pl.
# # greylist status database and greylist time interval. DO NOT create the # greylist status database in a world-writable directory such as /tmp # or /var/tmp. DO NOT create the greylist database in a file system # that can run out of space. # $database_name="/var/mta/greylist.db"; $greylist_delay=60; # # Auto-whitelist threshold. Specify 0 to disable, or the number of # successful "come backs" after which a client is no longer subject # to greylisting. # $auto_whitelist_threshold = 10; # # Demo SMTPD access policy routine. The result is an action just like # it would be specified on the right-hand side of a Postfix access # table. Request attributes are available via the %attr hash. # sub smtpd_access_policy { my($key, $time_stamp, $now); # Open the database on the fly. open_database() unless $database_obj; # Search the auto-whitelist. if ($auto_whitelist_threshold > 0) { $count = read_database($attr{"client_address"}); if ($count > $auto_whitelist_threshold) { return "dunno"; }

} # Lookup the time stamp for this client/sender/recipient. $key = lc $attr{"client_address"}."/".$attr{"sender"}."/".$attr{"recipient"}; $time_stamp = read_database($key); $now = time(); # If new request, add this client/sender/recipient to the database. if ($time_stamp == 0) { $time_stamp = $now; update_database($key, $time_stamp); } # The result can be any action that is allowed in a Postfix access(5) map. # # To label the mail, return ``PREPEND headername: headertext'' # # In case of success, return ``DUNNO'' instead of ``OK'', so that the # check_policy_service restriction can be followed by other restrictions. # # In case of failure, return ``DEFER_IF_PERMIT optional text...'', # so that mail can still be blocked by other access restrictions. # syslog $syslog_priority, "request age %d", $now - $time_stamp if $verbose; if ($now - $time_stamp > $greylist_delay) { # Update the auto-whitelist. if ($auto_whitelist_threshold > 0) { update_database($attr{"client_address"}, $count + 1); } return "dunno"; } else { return "defer_if_permit Service temporarily unavailable"; }

Postfix Address Verification Howto


WARNING
Recipient address verification may cause an increased load on down-stream servers in the case of a dictionary attack or a flood of backscatter bounces. Sender address verification may cause your site to be blacklisted by some providers. See also the "Limitations" section below for more.

What Postfix address verification can do for you


Address verification is a feature that allows the Postfix SMTP server to block a sender (MAIL FROM) or recipient (RCPT TO) address until the address has been verified to be deliverable. The technique has obvious uses to reject junk mail with an unreplyable sender address. The technique is also useful to block mail for undeliverable recipients, for example on a mail relay host that does not have a list of all the valid recipient addresses. This prevents undeliverable junk mail from entering the queue, so that Postfix doesn't have to waste resources trying to send MAILER-DAEMON messages back. This feature is available in Postfix version 2.1 and later. Topics covered in this document: How address verification works Limitations of address verification Recipient address verification Sender address verification for mail from frequently forged domains Sender address verification for all email Address verification database Managing the address verification database Controlling the routing of address verification probes Forced probe routing examples Limitations of forced probe routing

How address verification works


A Postfix MTA verifies a sender or recipient address by probing the nearest MTA for that address, without actually delivering mail. The nearest MTA could be the Postfix MTA itself, or it could be a remote MTA (SMTP interruptus). Probe messages are like normal mail, except that they are never delivered, deferred or bounced; probe messages are always discarded. | v Postfix Postfix < Postfix probe - message > mail Internet - SMTP - verify > queue > server > server

^ probe < Postfix -> Local | status - delivery -> Remote Address v verification database With Postfix address verification turned on, normal mail will suffer only a short delay of up to 6 seconds while an address is being verified for the first time. Once an address status is known, the status is cached and Postfix replies immediately. When verification takes too long the Postfix SMTP server defers the sender or recipient address with a 450 reply. Normal mail clients will connect again after some delay. The address verification delay is configurable with the main.cf address_verify_poll_count and address_verify_poll_delay parameters. See postconf(5) for details.

< -

Limitations of address verification


When verifying a remote address, Postfix probes the nearest MTA for that address, without actually delivering mail to it. If the nearest MTA accepts the address, then Postfix assumes that the address is deliverable. In reality, mail for a remote address can bounce AFTER the nearest MTA accepts the recipient address, or AFTER the nearest MTA accepts the message content. Some sites may blacklist you when you are probing them too often (a probe is an SMTP session that does not deliver mail), or when you are probing them too often for a nonexistent address. This is one reason why you should use sender address verification sparingly, if at all, when your site receives lots of email. Normally, address verification probe messages follow the same path as regular mail. However, some sites send mail to the Internet via an intermediate relayhost; this breaks address verification. See below, section "Controlling the routing of address verification probes", for how to override mail routing and for possible limitations when you have to do this. Postfix assumes that an address is undeliverable when the nearest MTA for the address rejects the probe, regardless of the reason for rejection (client rejected, HELO rejected, MAIL FROM rejected, etc.). Thus, Postfix rejects an address when the nearest MTA for that address rejects mail from your machine for any reason. This is not a limitation, but it is mentioned here just in case people believe that it is a limitation. Unfortunately, some sites do not reject unknown addresses in reply to the RCPT TO command, but report a delivery failure in response to end of DATA after a message is transferred. Postfix address verification does not work with such sites. By default, Postfix probe messages have a sender address "double-bounce@$myorigin" (with Postfix versions before 2.5, the default is "postmaster@$myorigin"). This is SAFE because the Postfix SMTP server does not reject mail for this address. You can change the probe sender address into the null address ("address_verify_sender ="). This is UNSAFE because address probes will fail with mis-configured sites that reject MAIL FROM: <>, while probes from "postmaster@$myorigin" would succeed.

Recipient address verification


As mentioned earlier, recipient address verification is useful to block mail for undeliverable

recipients on a mail relay host that does not have a list of all valid recipient addresses. This can help to prevent the mail queue from filling up with MAILER-DAEMON messages. Recipient address verification is relatively straightforward and there are no surprises. If a recipient probe fails, then Postfix rejects mail for the recipient address. If a recipient probe succeeds, then Postfix accepts mail for the recipient address. However, recipient address verification probes can increase the load on down-stream MTAs when you're being flooded by backscatter bounces, or when some spammer is mounting a dictionary attack. By default, address verification results are saved in a persistent database (Postfix version 2.7 and later; with earlier versions, specify the database in main.cf as described later). The persistent database helps to avoid probing the same address repeatedly.
/etc/postfix/main.cf: smtpd_recipient_restrictions = permit_mynetworks reject_unauth_destination ... reject_unknown_recipient_domain reject_unverified_recipient ... # Postfix 2.6 and later privacy feature. # unverified_recipient_reject_reason = Address lookup failed

The "reject_unknown_recipient_domain" restriction blocks mail for non-existent domains. Putting this before "reject_unverified_recipient" avoids the overhead of generating unnecessary probe messages. The unverified_recipient_reject_code parameter (default 450) specifies the numerical Postfix SMTP server reply code when a recipient address is known to bounce. Change this setting into 550 when you trust Postfix's judgments. The following features are available in Postfix 2.6 and later. The unverified_recipient_defer_code parameter (default 450) specifies the numerical Postfix SMTP server reply code when a recipient address probe fails with some temporary error. Some sites insist on changing this into 250. NOTE: This change turns MX servers into backscatter sources when the load is high. The unverified_recipient_reject_reason parameter (default: empty) specifies fixed text that Postfix will send to remote SMTP clients, instead of sending actual address verification details. Do not specify the SMTP status code or enhanced status code. The unverified_recipient_tempfail_action parameter (default: defer_if_permit) specifies the Postfix SMTP server action when a recipient address verification probe fails with some temporary error.

Sender address verification for mail from frequently forged domains


Only for very small sites, it is relatively safe to turn on sender address verification for specific domains that often appear in forged email.
/etc/postfix/main.cf: smtpd_sender_restrictions = hash:/etc/postfix/sender_access unverified_sender_reject_code = 550 # Postfix 2.6 and later. # unverified_sender_defer_code = 250 # Default setting for Postfix 2.7 and later.

# Note 1: Be sure to read the "Caching" section below! # Note 2: Avoid hash files here. Use btree instead. address_verify_map = btree:/var/lib/postfix/verify /etc/postfix/sender_access: # Don't do this when you handle lots of email. aol.com reject_unverified_sender hotmail.com reject_unverified_sender bigfoot.com reject_unverified_sender ... etcetera ...

At some point in cyberspace/time, a list of frequently forged MAIL FROM domains could be found at http://www.monkeys.com/anti-spam/filtering/sender-domain-validate.in. NOTE: One of the first things you might want to do is to turn on sender address verification for all your own domains.

Sender address verification for all email


Unfortunately, sender address verification cannot simply be turned on for all email - you are likely to lose legitimate mail from mis-configured systems. You almost certainly will have to set up white lists for specific addresses, or even for entire domains. To find out how sender address verification would affect your mail, specify "warn_if_reject reject_unverified_sender" so that you can see what mail would be blocked:
/etc/postfix/main.cf: smtpd_sender_restrictions = permit_mynetworks ... check_sender_access hash:/etc/postfix/sender_access reject_unknown_sender_domain warn_if_reject reject_unverified_sender ... # Postfix 2.6 and later. # unverified_sender_reject_reason = Address verification failed # Default setting for Postfix 2.7 and later. # Note 1: Be sure to read the "Caching" section below! # Note 2: Avoid hash files here. Use btree instead. address_verify_map = btree:/var/lib/postfix/verify

This is also a good way to populate your cache with address verification results before you start to actually reject mail. The sender_access restriction is needed to whitelist domains or addresses that are known to be OK. Although Postfix will not mark a known-to-be-good address as bad after a probe fails, it is better to be safe than sorry. NOTE: You will have to whitelist sites such as securityfocus.com and other sites that operate mailing lists that use a different sender address for each posting (VERP). Such addresses pollute the address verification cache quickly, and generate unnecessary sender verification probes.
/etc/postfix/sender_access securityfocus.com OK ...

The "reject_unknown_sender_domain" restriction blocks mail from non-existent domains. Putting this before "reject_unverified_sender" avoids the overhead of generating unnecessary probe messages.

The unverified_sender_reject_code parameter (default 450) specifies the numerical Postfix server reply code when a sender address is known to bounce. Change this setting into 550 when you trust Postfix's judgments. The following features are available in Postfix 2.6 and later. The unverified_sender_defer_code parameter (default 450) specifies the numerical Postfix SMTP server reply code when a sender address verification probe fails with some temporary error. Specify a valid 2xx or 4xx code. The unverified_sender_reject_reason parameter (default: empty) specifies fixed text that Postfix will send to remote SMTP clients, instead of sending actual addres verification details. Do not specify the SMTP status code or enhanced status code. The unverified_sender_tempfail_action parameter (default: defer_if_permit) specifies the Postfix SMTP server action when a sender address verification probe fails with some temporary error.

Address verification database


To improve performance, the Postfix verify(8) daemon can save address verification results to a persistent database. This is enabled by default with Postfix 2.7 and later. The address_verify_map (NOTE: singular) configuration parameter specifies persistent storage for sender or recipient address verification results. If you specify an empty value, all address verification results are lost after "postfix reload" or "postfix stop".
/etc/postfix/main.cf: # Default setting for Postfix 2.7 and later. # Note: avoid hash files here. Use btree instead. address_verify_map = btree:$data_directory/verify_cache # Default setting for Postfix 2.6 and earlier. # This uses non-persistent storage only. address_verify_map =

NOTE 1: The database file should be stored under a Postfix-owned directory, such as $data_directory. As of version 2.5, Postfix no longer uses root privileges when opening this file. To maintain backwards compatibility, an attempt to open the file under a non-Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. If you wish to continue using a pre-existing database file, change its file ownership to the account specified with the mail_owner parameter, and either move the file to the data_directory, or move it to some other Postfix-owned directory. NOTE 2: Do not put this file in a file system that may run out of space. When the address verification table gets corrupted the world comes to an end and YOU will have to MANUALLY fix things as described in the next section. Meanwhile, you will not receive mail via SMTP. NOTE 3: The verify(8) daemon will create a new database when none exists. It will open or create the file before entering the chroot jail.

Managing the address verification database


The verify(8) manual page describes parameters that control how long address verification results are cached before they need to be refreshed, and how long results can remain "unrefreshed" before they expire. Postfix uses different controls for positive results (address was accepted) and for negative results (address was rejected, or address verification failed for some other reason).

The verify(8) daemon will periodically remove expired entries from the address verification database, and log the number of entries retained and dropped (Postfix versions 2.7 and later). A cleanup run is logged as "partial" when the daemon terminates early because of "postfix reload, "postfix stop", or because the daemon received no requests for $max_idle seconds. Postfix versions 2.6 and earlier do not implement automatic address verification database cleanup. There, the database is managed manually as described next. When the address verification database file becomes too big, or when it becomes corrupted, the solution is to manually rename or delete (NOT: truncate) the file and run "postfix reload". The verify(8) daemon will then create a new database file.

Controlling the routing of address verification probes


By default, Postfix sends address verification probe messages via the same route as regular mail, because that normally produces the most accurate result. It's no good to verify a local address by connecting to your own SMTP port; that just triggers all kinds of mailer loop alarms. The same is true for any destination that your machine is best MX host for: hidden domains, virtual domains, etc. However, some sites have a complex infrastructure where mail is not sent directly to the Internet, but is instead given to an intermediate relayhost. This is a problem for address verification, because remote Internet addresses can be verified only when Postfix can access remote destinations directly. For this reason, Postfix allows you to override the routing parameters when it delivers an address verification probe message. First, the address_verify_relayhost parameter allows you to override the relayhost setting, and the address_verify_transport_maps parameter allows you to override the transport_maps setting. The address_verify_sender_dependent_relayhost_maps parameter does the same for sender-dependent relayhost selection. Second, each address class is given its own address verification version of the message delivery transport, as shown in the table below. Address classes are defined in the ADDRESS_CLASS_README file. Domain list mydestination virtual_alias_domains relay_domains Regular transport local_transport (not applicable) relay_transport Verify transport address_verify_local_transport (not applicable) address_verify_virtual_transport address_verify_relay_transport

virtual_mailbox_domains virtual_transport

(not applicable) default_transport address_verify_default_transport By default, the parameters that control delivery of address probes have the same value as the parameters that control normal mail delivery.

Forced probe routing examples


In a typical scenario one would override the relayhost setting for address verification probes and leave everything else alone:
/etc/postfix/main.cf: relayhost = $mydomain address_verify_relayhost = ...

Sites behind a network address translation box might have to use a different SMTP client that sends the correct hostname information:
/etc/postfix/main.cf: relayhost = $mydomain address_verify_relayhost = address_verify_default_transport = direct_smtp /etc/postfix/master.cf: direct_smtp .. .. .. .. .. .. .. .. .. smtp -o smtp_helo_name=nat.box.tld

Limitations of forced probe routing


Inconsistencies can happen when probe messages don't follow the same path as regular mail. For example, a message can be accepted when it follows the regular route while an otherwise identical probe message is rejected when it follows the forced route. The opposite can happen, too, but is less likely.

Postfix Per-Client/User/etc. Access Control


Postfix restriction classes
The Postfix SMTP server supports access restrictions such as reject_rbl_client or reject_unknown_client_hostname on the right-hand side of SMTP server access(5) tables. This allows you to implement different junk mail restrictions for different clients or users. Having to specify lists of access restrictions for every recipient becomes tedious quickly. Postfix restriction classes allow you to give easy-to-remember names to groups of UCE restrictions (such as "permissive", "restrictive", and so on). The real reason for the existence of Postfix restriction classes is more mundane: you can't specify a lookup table on the right-hand side of a Postfix access table. This is because Postfix needs to open lookup tables ahead of time, but the reader probably does not care about these low-level details. Example:
/etc/postfix/main.cf: smtpd_restriction_classes = restrictive, permissive # With Postfix < 2.3 specify reject_unknown_client. restrictive = reject_unknown_sender_domain reject_unknown_client_hostname ... permissive = permit smtpd_recipient_restrictions = permit_mynetworks reject_unauth_destination check_recipient_access hash:/etc/postfix/recipient_access /etc/postfix/recipient_access: joe@my.domain permissive jane@my.domain restrictive

With this in place, you can use "restrictive" or "permissive" on the right-hand side of your perclient, helo, sender, or recipient SMTPD access tables. The remainder of this document gives examples of how Postfix access restriction classes can be used to: Shield an internal mailing list from outside posters, Prevent external access by internal senders. These questions come up frequently, and the examples hopefully make clear that Postfix restriction classes aren't really the right solution. They should be used for what they were designed to do, different junk mail restrictions for different clients or users.

Protecting internal email distribution lists


We want to implement an internal email distribution list. Something like

all@our.domain.com, which aliases to all employees. My first thought was to use the aliases map, but that would lead to "all" being accessible from the "outside", and this is not desired... :-) Postfix can implement per-address access controls. What follows is based on the SMTP client IP address, and therefore is subject to IP spoofing.
/etc/postfix/main.cf: smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/access ...the usual stuff... /etc/postfix/access: all@my.domain permit_mynetworks,reject all@my.hostname permit_mynetworks,reject

Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what map types Postfix supports, use the command postconf -m. Now, that would be sufficient when your machine receives all Internet mail directly from the Internet. That's unlikely if your network is a bit larger than an office. For example, your backup MX hosts would "launder" the client IP address of mail from the outside so it would appear to come from a trusted machine. In the general case you need two lookup tables: one table that lists destinations that need to be protected, and one table that lists domains that are allowed to send to the protected destinations. What follows is based on the sender SMTP envelope address, and therefore is subject to SMTP sender spoofing.
/etc/postfix/main.cf: smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/protected_destinations ...the usual stuff... smtpd_restriction_classes = insiders_only insiders_only = check_sender_access hash:/etc/postfix/insiders, reject /etc/postfix/protected_destinations: all@my.domain insiders_only all@my.hostname insiders_only /etc/postfix/insiders: my.domain OK another.domain OK

matches my.domain and subdomains matches another.domain and subdomains

Getting past this scheme is relatively easy, because all one has to do is to spoof the SMTP sender address. If the internal list is a low-volume one, perhaps it makes more sense to make it moderated.

Restricting what users can send mail to off-site destinations


How can I configure Postfix in a way that some users can send mail to the internet and other users not. The users with no access should receive a generic bounce message. Please don't discuss whether such access restrictions are necessary, it was not my decision.

Postfix has support for per-user restrictions. The restrictions are implemented by the SMTP server. Thus, users that violate the policy have their mail rejected by the SMTP server. Like this:
554 <user@remote>: Access denied

The implementation uses two lookup tables. One table defines what users are restricted in where they can send mail, and the other table defines what destinations are local. It is left as an exercise for the reader to change this into a scheme where only some users have permission to send mail to off-site destinations, and where most users are restricted. The example assumes DB/DBM files, but this could also be done with LDAP or SQL.
/etc/postfix/main.cf: smtpd_recipient_restrictions = check_sender_access hash:/etc/postfix/restricted_senders ...other stuff... smtpd_restriction_classes = local_only local_only = check_recipient_access hash:/etc/postfix/local_domains, reject /etc/postfix/restricted_senders: foo@domain local_only bar@domain local_only /etc/postfix/local_domains: this.domain OK matches this.domain and subdomains that.domain OK matches that.domain and subdomains

Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what map types Postfix supports, use the command postconf -m. Note: this scheme does not authenticate the user, and therefore it can be bypassed in several ways: By sending mail via a less restrictive mail relay host. By sending mail as someone else who does have permission to send mail to off-site destinations.

Postfix ETRN Howto


Purpose of the Postfix fast ETRN service
The SMTP ETRN command was designed for sites that have intermittent Internet connectivity. With ETRN, a site can tell the mail server of its provider to "Please deliver all my mail now". The SMTP server searches the queue for mail to the customer, and delivers that mail by connecting to the customer's SMTP server. The mail is not delivered via the connection that was used for sending ETRN. As of version 1.0, Postfix has a fast ETRN implementation that does not require Postfix to examine every queue file. Instead, Postfix maintains a record of what queue files contain mail for destinations that are configured for ETRN service. ETRN service is no longer available for domains that aren't configured for the service. This document provides information on the following topics: Using the Postfix fast ETRN service How Postfix fast ETRN works Postfix fast ETRN service limitations Configuring the Postfix fast ETRN service Configuring a domain for ETRN service only Testing the Postfix fast ETRN service

Other documents with information on this subject: flush(8), flush service implementation

Using the Postfix fast ETRN service


The following is an example SMTP session that shows how an SMTP client requests the ETRN service. Client commands are shown in bold font.
220 my.server.tld ESMTP Postfix HELO my.client.tld 250 Ok ETRN some.customer.domain 250 Queuing started QUIT 221 Bye

As mentioned in the introduction, the mail is delivered by connecting to the customer's SMTP server; it is not sent over the connection that was used to send the ETRN command. The Postfix operator can request delivery for a specific customer by using the command "sendmail -qRdestination" and, with Postfix version 1.1 and later, "postqueue -sdestination". Access to this feature is controlled with the authorized_flush_users configuration parameter (Postfix version 2.2 and later).

How Postfix fast ETRN works


When a Postfix delivery agent decides that mail must be delivered later, it sends the destination domain name and the queue file name to the flush(8) daemon which maintains per-destination logfiles with file names of queued mail. These logfiles are kept below $queue_directory/flush. Perdestination logfiles are maintained only for destinations that are listed with the $fast_flush_domains parameter and that have syntactically valid domain names. Postfix Postfix One logfile delivery -(domain, queue ID)-> flush -(queue ID)-> per eligible agent daemon domain When Postfix receives a request to "deliver mail for a domain now", the flush(8) daemon moves all deferred queue files that are listed for that domain to the incoming queue, and requests that the queue manager deliver them. In order to force delivery, the queue manager temporarily ignores the lists of undeliverable destinations: the volatile in-memory list of dead domains, and the list of message delivery transports specified with the defer_transports configuration parameter.

Postfix fast ETRN service limitations


The design of the flush(8) server and of the flush queue introduce a few limitations that should not be an issue unless you want to turn on fast ETRN service for every possible destination. The flush(8) daemon maintains per-destination logfiles with queue file names. When a request to "deliver mail now" arrives, Postfix will attempt to deliver all recipients in the queue files that have mail for the destination in question. This does not perform well with queue files that have recipients in many different domains, such as queue files with outbound mailing list traffic. The flush(8) daemon maintains per-destination logfiles only for destinations listed with $fast_flush_domains. With other destinations you cannot request delivery with "sendmail -qRdestination" or, with Postfix version 1.1 and later, "postqueue -sdestination". Up to and including early versions of Postfix version 2.1, the "fast flush" service may not deliver some messages if the request to "deliver mail now" is received while a deferred queue scan is already in progress. The reason is that the queue manager does not ignore the volatile in-memory list of dead domains, and the list of message delivery transports specified with the defer_transports configuration parameter. Up to and including Postfix version 2.3, the "fast flush" service may not deliver some messages if the request to "deliver mail now" arrives while an incoming queue scan is already in progress.

Configuring the Postfix fast ETRN service


The behavior of the flush(8) daemon is controlled by parameters in the main.cf configuration file. By default, Postfix "fast ETRN" service is available only for destinations that Postfix is willing to relay mail to:
/etc/postfix/main.cf: fast_flush_domains = $relay_domains smtpd_etrn_restrictions = permit_mynetworks, reject

Notes: The relay_domains parameter specifies what destinations Postfix will relay to. For

destinations that are not eligible for the "fast ETRN" service, Postfix replies with an error message. The smtpd_etrn_restrictions parameter limits what clients may execute the ETRN command. By default, any client has permission. To enable "fast ETRN" for some other destination, specify:
/etc/postfix/main.cf: fast_flush_domains = $relay_domains, some.other.domain

To disable "fast ETRN", so that Postfix rejects all ETRN requests and so that it maintains no perdestination logfiles, specify:
/etc/postfix/main.cf: fast_flush_domains =

Configuring a domain for ETRN service only


While an "ETRN" customer is off-line, Postfix will make spontaneous attempts to deliver mail to it. These attempts are separated in time by increasing time intervals, ranging from $minimal_backoff_time to $maximal_backoff_time, and should not be a problem unless a lot of mail is queued. To prevent Postfix from making spontaneous delivery attempts you can configure Postfix to always defer mail for the "ETRN" customer. Mail is delivered only after the ETRN command or with "sendmail -q", with "sendmail -qRdomain", or with "postqueue -sdomain"(Postfix version 1.1 and later only), In the example below we configure an "etrn-only" delivery transport which is simply a duplicate of the "smtp" and "relay" mail delivery transports. The only difference is that mail destined for this delivery transport is deferred as soon as it arrives.
1 /etc/postfix/master.cf: 2 # ============================================================= 3 # service type private unpriv chroot wakeup maxproc command 4 # (yes) (yes) (yes) (never) (100) 5 # ============================================================= 6 smtp unix n smtp 7 relay unix n smtp 8 etrn-only unix n smtp 9 10 /etc/postfix/main.cf: 11 relay_domains = customer.tld ...other domains... 12 defer_transports = etrn-only 13 transport_maps = hash:/etc/postfix/transport 14 15 /etc/postfix/transport: 16 customer.tld etrn-only:[mailhost.customer.tld]

Translation: Line 8: The "etrn-only" mail delivery service is a copy of the "smtp" and "relay" service. Line 11: Don't forget to authorize relaying for this customer, either via relay_domains or with the permit_mx_backup feature. Line 12: The "etrn-only" mail delivery service is configured so that spontaneous mail delivery is disabled.

Lines 13-16: Mail for the customer is given to the "etrn-only" mail delivery service. Line 16: The "[mailhost.customer.tld]" turns off MX record lookups; you must specify this if your Postfix server is the primary MX host for the customer's domain.

Testing the Postfix fast ETRN service


By default, "fast ETRN" service is enabled for all domains that match $relay_domains. If you run Postfix with "fast ETRN" service for the very first time, you need to run "sendmail -q" once in order to populate the per-site deferred mail logfiles. If you omit this step, no harm is done. The logfiles will eventually become populated as Postfix routinely attempts to deliver delayed mail, but that will take a couple hours. After the "sendmail -q" command has completed all delivery attempts (this can take a while), you're ready to test the "fast ETRN" service. To test the "fast ETRN" service, telnet to the Postfix SMTP server from a client that is allowed to execute ETRN commands (by default, that's every client), and type the commands shown in boldface:
220 my.server.tld ESMTP Postfix HELO my.client.tld 250 Ok ETRN some.customer.domain 250 Queuing started

where "some.customer.domain" is the name of a domain that has a non-empty logfile somewhere under $queue_directory/flush. In the maillog file, you should immediately see a couple of logfile records, as evidence that the queue manager has opened queue files:
Oct 2 10:51:19 myhostname postfix/qmgr[51999]: 682E8440A4: from=<whatever>, size=12345, nrcpt=1 (queue active) Oct 2 10:51:19 myhostname postfix/qmgr[51999]: 02249440B7: from=<whatever>, size=4711, nrcpt=1 (queue active)

What happens next depends on whether the destination is reachable. If it's not reachable, the mail queue IDs will be added back to the some.customer.domain logfile under $queue_directory/flush. Repeat the exercise with some other destination that your server is willing to relay to (any domain listed in $relay_domains), but that has no mail queued. The text in bold face stands for the commands that you type:
220 my.server.tld ESMTP Postfix HELO my.client.tld 250 Ok ETRN some.other.customer.domain 250 Queuing started

This time, the "ETRN"" command should trigger NO mail deliveries at all. If this triggers delivery of all mail, then you used the wrong domain name, or "fast ETRN" service is turned off. Finally, repeat the exercise with a destination that your mail server is not willing to relay to. It does not matter if your server has mail queued for that destination.
220 my.server.tld ESMTP Postfix HELO my.client.tld 250 Ok ETRN not.a.customer.domain 459 <not.a.customer.domain>: service unavailable

In this case, Postfix should reject the request as shown above.

Postfix and UUCP


Using UUCP over TCP
Despite a serious lack of sex-appeal, email via UUCP over TCP is a practical option for sites without permanent Internet connections, and for sites without a fixed IP address. For first-hand information, see the following guides: Jim Seymour's guide for using UUCP over TCP at http://jimsun.LinxNet.com/jdp/uucp_over_tcp/index.html, Craig Sanders's guide for SSL-encrypted UUCP over TCP using stunnel at http://taz.net.au/postfix/uucp/. Here's a graphical description of what this document is about: LAN to Local network <---> UUCP <--- UUCP ---> Gateway And here's the table of contents of this document: Setting up a Postfix Internet to UUCP gateway Setting up a Postfix LAN to UUCP gateway Internet to UUCP <---> Internet Gateway

Setting up a Postfix Internet to UUCP gateway


Here is how to set up a machine that sits on the Internet and that forwards mail to a LAN that is connected via UUCP. See the LAN to UUCP gateway section for the other side of the story. You need an rmail program that extracts the sender address from mail that arrives via UUCP, and that feeds the mail into the Postfix sendmail command. Most UNIX systems come with an rmail utility. If you're in a pinch, try the one bundled with the Postfix source code in the auxiliary/rmail directory. Define a pipe(8) based mail delivery transport for delivery via UUCP:
/etc/postfix/master.cf: uucp unix n n pipe flags=F user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)

This runs the uux command to place outgoing mail into the UUCP queue after replacing $nexthop by the next-hop hostname (the receiving UUCP host) and after replacing $recipient by the recipients. The pipe(8) delivery agent executes the uux command without assistance from the shell, so there are no problems with shell meta characters in command-

line parameters. Specify that mail for example.com, should be delivered via UUCP, to a host named uucphost:
/etc/postfix/transport: example.com uucp:uucp-host .example.com uucp:uucp-host

See the transport(5) manual page for more details. Execute the command "postmap /etc/postfix/transport" whenever you change the transport file. Enable transport table lookups:
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport

Specify dbm instead of hash if your system uses dbm files instead of db files. To find out what map types Postfix supports, use the command "postconf -m". Add example.com to the list of domains that your site is willing to relay mail for.
/etc/postfix/main.cf: relay_domains = example.com ...other relay domains...

See the relay_domains configuration parameter description for details. Execute the command "postfix reload" to make the changes effective.

Setting up a Postfix LAN to UUCP gateway


Here is how to relay mail from a LAN via UUCP to the Internet. See the Internet to UUCP gateway section for the other side of the story. You need an rmail program that extracts the sender address from mail that arrives via UUCP, and that feeds the mail into the Postfix sendmail command. Most UNIX systems come with an rmail utility. If you're in a pinch, try the one bundled with the Postfix source code in the auxiliary/rmail directory. Specify that all remote mail must be sent via the uucp mail transport to your UUCP gateway host, say, uucp-gateway:
/etc/postfix/main.cf: relayhost = uucp-gateway default_transport = uucp

Postfix 2.0 and later also allows the following more succinct form:
/etc/postfix/main.cf: default_transport = uucp:uucp-gateway

Define a pipe(8) based message delivery transport for mail delivery via UUCP:
/etc/postfix/master.cf: uucp unix n n pipe flags=F user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)

This runs the uux command to place outgoing mail into the UUCP queue. It substitutes the

next-hop hostname (uucp-gateway, or whatever you specified) and the recipients before executing the command. The uux command is executed without assistance from the shell, so there are no problems with shell meta characters. Execute the command "postfix reload" to make the changes effective.

Postfix Lookup Table Overview


Overview
This document covers the following topics: The Postfix lookup table model Postfix lists versus tables Preparing Postfix for LDAP or SQL lookups Maintaining Postfix lookup table files Updating Berkeley DB files safely Postfix lookup table types

The Postfix lookup table model


Postfix uses lookup tables to store and look up information for access control, address rewriting and even for content filtering. All Postfix lookup tables are specified as "type:table", where "type" is one of the database types described under "Postfix lookup table types" at the end of this document, and where "table" is the lookup table name. The Postfix documentation uses the terms "database" and "lookup table" for the same thing. Examples of lookup tables that appear often in the Postfix documentation:
/etc/postfix/main.cf: alias_maps = hash:/etc/postfix/aliases header_checks = regexp:/etc/postfix/header_checks filtering) transport_maps = hash:/etc/postfix/transport virtual_alias_maps = hash:/etc/postfix/virtual rewriting) (local aliasing) (content (routing table) (address

All Postfix lookup tables store information as (key, value) pairs. This interface may seem simplistic at first, but it turns out to be very powerful. The (key, value) query interface completely hides the complexities of LDAP or SQL from Postfix. This is a good example of connecting complex systems with simple interfaces. Benefits of the Postfix (key, value) query interface: You can implement Postfix lookup tables first with local Berkeley DB files and then switch to LDAP or MySQL without any impact on the Postfix configuration itself, as described under "Preparing Postfix for LDAP or SQL lookups" below. You can use Berkeley DB files with fixed lookup strings for simple address rewriting operations and you can use regular expression tables for the more complicated work. In other words, you don't have to put everything into the same table.

Postfix lists versus tables


Most Postfix lookup tables are used to look up information. Examples are address rewriting (the

lookup string is the old address, and the result is the new address) or access control (the lookup string is the client, sender or recipient, and the result is an action such as "reject"). With some tables, however, Postfix needs to know only if the lookup key exists. The lookup result itself is not used. Examples are the local_recipient_maps that determine what local recipients Postfix accepts in mail from the network, the mydestination parameter that specifies what domains Postfix delivers locally, or the mynetworks parameter that specifies the IP addresses of trusted clients or client networks. Technically, these are lists, not tables. Despite the difference, Postfix lists are described here because they use the same underlying infrastructure as Postfix lookup tables.

Preparing Postfix for LDAP or SQL lookups


LDAP and SQL are complex systems. Trying to set up both Postfix and LDAP or SQL at the same time is definitely not a good idea. You can save yourself a lot of time by implementing Postfix first with local files such as Berkeley DB. Local files have few surprises, and are easy to debug with the postmap(1) command:
% postmap -q info@example.com hash:/etc/postfix/virtual

Once you have local files working properly you can follow the instructions in ldap_table(5), mysql_table(5), pgsql_table(5) or sqlite_table(5) and replace local file lookups with LDAP or SQL lookups. When you do this, you should use the postmap(1) command again, to verify that database lookups still produce the exact same results as local file lookup:
% postmap -q info@example.com ldap:/etc/postfix/virtual.cf

Be sure to exercise all the partial address or parent domain queries that are documented under "table search order" in the relevant manual page: access(5), canonical(5), virtual(5), transport(5), or under the relevant configuration parameter: mynetworks, relay_domains, parent_domain_matches_subdomains.

Maintaining Postfix lookup table files


When you make changes to a database while the mail system is running, it would be desirable if Postfix avoids reading information while that information is being changed. It would also be nice if you can change a database without having to execute "postfix reload", in order to force Postfix to use the new information. Each time you do "postfix reload" Postfix loses a lot of performance. If you change a network database such as LDAP, NIS or SQL, there is no need to execute "postfix reload". The LDAP, NIS or SQL server takes care of read/write access conflicts and gives the new data to Postfix once that data is available. If you change a regexp: or pcre: file then Postfix may or may not pick up the file changes immediately. This is because a Postfix process reads the entire file into memory once and never examines the file again. If the file is used by a short-running process such as smtpd(8), cleanup(8) or local(8), there is no need to execute "postfix reload" after making a change. If the file is being used by a long-running process such as trivial-rewrite(8) on a busy server it may be necessary to execute "postfix reload". If you change a local file based database such as DBM or Berkeley DB, there is no need to execute "postfix reload". Postfix uses file locking to avoid read/write access conflicts, and whenever a Postfix daemon process notices that a file has changed it will terminate before handling the next client request, so that a new process can initialize with the new database.

Updating Berkeley DB files safely


Although Postfix uses file locking to avoid access conflicts while updating Berkeley DB or other local database files, you still have a problem when the update fails because the disk is full or because something else happens. This is because commands such as postmap(1) or postalias(1) overwrite existing files. If the update fails in the middle then you have no usable database, and Postfix will stop working. This is not an issue with the CDB database type available with Postfix 2.2 and later: CDB creates a new file, and renames the file upon successful completion. With multi-file databases such as DBM, there is no simple solution. With Berkeley DB and other "one file" databases, it is possible to add some extra robustness by using "mv" to REPLACE an existing database file instead of overwriting it:
# postmap access.in && mv access.in.db access.db

This converts the input file "access.in" into the output file "access.in.db", and replaces the file "access.db" only when the postmap(1) command was successful. Of course typing such commands becomes boring quickly, and this is why people use "make" instead, as shown below. User input is shown in bold font.
# cat Makefile all: aliases.db access.db virtual.db ...etcetera... # Note 1: commands are specified after a TAB character. # Note 2: use postalias(1) for local aliases, postmap(1) for the rest. aliases.db: aliases.in postalias aliases.in mv aliases.in.db aliases.db access.db: access.in postmap access.in mv access.in.db access.db virtual.db: virtual.in postmap virtual.in mv virtual.in.db virtual.db ...etcetera... # vi access.in ...editing session not shown... # make postmap access.in mv access.in.db access.db #

The "make" command updates only the files that have changed. In case of error, the "make" command will stop and will not invoke the "mv" command, so that Postfix will keep using the existing database file as if nothing happened.

Postfix lookup table types


To find out what database types your Postfix system supports, use the "postconf -m" command. Here is a list of database types that are often supported: btree A sorted, balanced tree structure. This is available only on systems with support for Berkeley DB databases. Database files are created with the postmap(1) or

postalias(1) command. The lookup table name as used in "btree:table" is the database file name without the ".db" suffix. cdb A read-optimized structure with no support for incremental updates. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "cdb:table" is the database file name without the ".cdb" suffix. This feature is available with Postfix 2.2 and later. cidr A table that associates values with Classless Inter-Domain Routing (CIDR) patterns. The table format is described in cidr_table(5). dbm An indexed file type based on hashing. This is available only on systems with support for DBM databases. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "dbm:table" is the database file name without the ".dir" or ".pag" suffix. environ The UNIX process environment array. The lookup key is the variable name. The lookup table name in "environ:table" is ignored. hash An indexed file type based on hashing. This is available only on systems with support for Berkeley DB databases. Database files are created with the postmap(1) or postalias(1) command. The database name as used in "hash:table" is the database file name without the ".db" suffix. internal A non-shared, in-memory hash table. Its content are lost when a process terminates. ldap (read-only) Perform lookups using the LDAP protocol. Configuration details are given in the ldap_table(5). mysql (read-only) Perform MySQL database lookups. Configuration details are given in mysql_table(5). netinfo (read-only) Perform Netinfo database lookups.

nis (read-only) Perform NIS database lookups. nisplus (read-only) Perform NIS+ database lookups. Configuration details are given in nisplus_table(5). pcre (read-only) A lookup table based on Perl Compatible Regular Expressions. The file format is described in pcre_table(5). The lookup table name as used in "pcre:table" is the name of the regular expression file. pgsql (read-only) Perform PostgreSQL database lookups. Configuration details are given in pgsql_table(5). proxy (read-only) Access information via the Postfix proxymap(8) service. The lookup table name syntax is "proxy:type:table". regexp (read-only) A lookup table based on regular expressions. The file format is described in regexp_table(5). The lookup table name as used in "regexp:table" is the name of the regular expression file. sdbm An indexed file type based on hashing. This is available only on systems with support for SDBM databases. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in "sdbm:table" is the database file name without the ".dir" or ".pag" suffix. sqlite (read-only) Perform SQLite database lookups. Configuration details are given in sqlite_table(5). static (read-only) Always returns its lookup table name as lookup result. For example, the lookup table "static:foobar" always returns the string "foobar" as lookup result. tcp Access information through a TCP/IP server. The protocol is described in tcp_table(5). The lookup table name is "tcp:host:port" where "host" specifies a

symbolic hostname or a numeric IP address, and "port" specifies a symbolic service name or a numeric port number. unix (read-only) A limited way to query the UNIX authentication database. The following tables are implemented: unix:passwd.byname The table is the UNIX password database. The key is a login name. The result is a password file entry in passwd(5) format. unix:group.byname The table is the UNIX group database. The key is a group name. The result is a group file entry in group(5) format. Other lookup table types may be available depending on how Postfix was built. With some Postfix distributions the list is dynamically extensible as support for lookup tables is dynamically linked into Postfix.

Postfix CDB Howto


Introduction
CDB (Constant DataBase) is an indexed file format designed by Daniel Bernstein. CDB is optimized exclusively for read access and guarantees that each record will be read in at most two disk accesses. This is achieved by forgoing support for incremental updates: no single-record inserts or deletes are supported. CDB databases can be modified only by rebuilding them completely from scratch, hence the "constant" qualifier in the name. Postfix CDB databases are specified as "cdb:name", where name specifies the CDB file name without the ".cdb" suffix (another suffix, ".tmp", is used temporarily while a CDB file is under construction). CDB databases are maintained with the postmap(1) or postalias(1) command. The DATABASE_README document has general information about Postfix databases. CDB support is available with Postfix 2.2 and later releases. This document describes how to build Postfix with CDB support.

Building Postfix with CDB support


These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Postfix is compatible with two CDB implementations: The original cdb library from Daniel Bernstein, available from http://cr.yp.to/cdb.html, and tinycdb (version 0.5 and later) from Michael Tokarev, available from http://www.corpit.ru/mjt/tinycdb.html. Tinycdb is preferred, since it is a bit faster, has additional useful functionality and is much simpler to use. To build Postfix after you have installed tinycdb, use something like:
% make tidy % CDB=../../../tinycdb-0.5 % make -f Makefile.init makefiles "CCARGS=-DHAS_CDB -I$CDB" \ "AUXLIBS=$CDB/libcdb.a" % make

Alternatively, for the D.J.B. version of CDB:


% make tidy % CDB=../../../cdb-0.75 % make -f Makefile.init makefiles "CCARGS=-DHAS_CDB -I$CDB" \ "AUXLIBS=$CDB/cdb.a $CDB/alloc.a $CDB/buffer.a $CDB/unix.a $CDB/byte.a" % make

After Postfix has been built with cdb support, you can use "cdb" tables wherever you can use read-

only "hash", "btree" or "dbm" tables. However, the "postmap -i" (incremental record insertion) and "postmap -d" (incremental record deletion) command-line options are not available. For the same reason the "cdb" map type cannot be used to store the persistent address verification cache for the verify(8) service, or to store TLS session information for the tlsmgr(8) service.

Postfix Berkeley DB Howto


Introduction
Postfix uses databases of various kinds to store and look up information. Postfix databases are specified as "type:name". Berkeley DB implements the Postfix database type "hash" and "btree". The name of a Postfix Berkeley DB database is the name of the database file without the ".db" suffix. Berkeley DB databases are maintained with the postmap(1) command. Note: Berkeley DB version 4 is not supported by Postfix versions before 2.0. This document describes: 1. How to build Postfix on systems without Berkeley DB library. 2. How to build Postfix on BSD or Linux systems with multiple Berkeley DB versions. 3. How to tweak performance. 4. Missing pthread library trouble.

Building Postfix on systems without Berkeley DB


Some UNIXes ship without Berkeley DB support; for historical reasons these use DBM files instead. A problem with DBM files is that they can store only limited amounts of data. To build Postfix with Berkeley DB support you need to download and install the source code from http://www.oracle.com/database/berkeley-db/. Warning: some Linux system libraries use Berkeley DB, as do some third-party libraries such as SASL. If you compile Postfix with a different Berkeley DB implementation, then every Postfix program will dump core because either the system library, the SASL library, or Postfix itself ends up using the wrong version. The more recent Berkeley DB versions have a compile-time switch, "--with-uniquename", which renames the symbols so that multiple versions of Berkeley DB can co-exist in the same application. Although wasteful, this may be the only way to keep things from falling apart. To build Postfix after you installed the Berkeley DB from source code, use something like:
% make tidy % make makefiles CCARGS="-DHAS_DB -I/usr/local/BerkeleyDB/include" \ AUXLIBS="-L/usr/local/BerkeleyDB/lib -ldb" % make

Solaris needs this:


% make tidy % make makefiles CCARGS="-DHAS_DB -I/usr/local/BerkeleyDB/include" \ AUXLIBS="-R/usr/local/BerkeleyDB/lib -L/usr/local/BerkeleyDB/lib -ldb" % make

The exact pathnames depend on the Berkeley DB version, and on how it was installed.

Warning: the file format produced by Berkeley DB version 1 is not compatible with that of versions 2 and 3 (versions 2 and 3 have the same format). If you switch between DB versions, then you may have to rebuild all your Postfix DB files. Warning: if you use Berkeley DB version 2 or later, do not enable DB 1.85 compatibility mode. Doing so would break fcntl file locking. Warning: if you use Perl to manipulate Postfix's Berkeley DB files, then you need to use the same Berkeley DB version in Perl as in Postfix.

Building Postfix on BSD systems with multiple Berkeley DB versions


Some BSD systems ship with multiple Berkeley DB implementations. Normally, Postfix builds with the default DB version that ships with the system. To build Postfix on BSD systems with a non-default DB version, use a variant of the following commands:
% make tidy % make makefiles CCARGS=-I/usr/include/db3 AUXLIBS=-ldb3 % make

Warning: the file format produced by Berkeley DB version 1 is not compatible with that of versions 2 and 3 (versions 2 and 3 have the same format). If you switch between DB versions, then you may have to rebuild all your Postfix DB files. Warning: if you use Berkeley DB version 2 or later, do not enable DB 1.85 compatibility mode. Doing so would break fcntl file locking. Warning: if you use Perl to manipulate Postfix's Berkeley DB files, then you need to use the same Berkeley DB version in Perl as in Postfix.

Building Postfix on Linux systems with multiple Berkeley DB versions


Some Linux systems ship with multiple Berkeley DB implementations. Normally, Postfix builds with the default DB version that ships with the system. Warning: some Linux system libraries use Berkeley DB. If you compile Postfix with a non-default Berkeley DB implementation, then every Postfix program will dump core because either the system library or Postfix itself ends up using the wrong version. On Linux, you need to edit the makedefs script in order to specify a non-default DB library. The reason is that the location of the default db.h include file changes randomly between vendors and between versions, so that Postfix has to choose the file for you. Warning: the file format produced by Berkeley DB version 1 is not compatible with that of versions 2 and 3 (versions 2 and 3 have the same format). If you switch between DB versions, then you may have to rebuild all your Postfix DB files. Warning: if you use Berkeley DB version 2 or later, do not enable DB 1.85 compatibility mode. Doing so would break fcntl file locking. Warning: if you use Perl to manipulate Postfix's Berkeley DB files, then you need to use the same Berkeley DB version in Perl as in Postfix.

Tweaking performance
Postfix provides two configuration parameters that control how much buffering memory Berkeley DB will use. berkeley_db_create_buffer_size (default: 16 MBytes per table). This setting is used by the commands that maintain Berkeley DB files: postalias(1) and postmap(1). For "hash" files, create performance degrades rapidly unless the memory pool is O(file size). For "btree" files, create performance is good with sorted input even for small memory pools, but with random input degrades rapidly unless the memory pool is O(file size). berkeley_db_read_buffer_size (default: 128 kBytes per table). This setting is used by all other Postfix programs. The buffer size is adequate for reading. If the cache is smaller than the table, random read performance is hardly cache size dependent, except with btree tables, where the cache size must be large enough to contain the entire path from the root node. Empirical evidence shows that 64 kBytes may be sufficient. We double the size to play safe, and to anticipate changes in implementation and bloat.

Missing pthread library trouble


When building Postfix fails with:
undefined undefined undefined undefined reference reference reference reference to to to to `pthread_condattr_setpshared' `pthread_mutexattr_destroy' `pthread_mutexattr_init' `pthread_mutex_trylock'

Add the "-lpthread" library to the "make makefiles" command.


% make makefiles .... AUXLIBS="... -lpthread"

More information is available at http://www.oracle.com/database/berkeley-db/.

Postfix LDAP Howto


LDAP Support in Postfix
Postfix can use an LDAP directory as a source for any of its lookups: aliases(5), virtual(5), canonical(5), etc. This allows you to keep information for your mail service in a replicated network database with fine-grained access controls. By not storing it locally on the mail server, the administrators can maintain it from anywhere, and the users can control whatever bits of it you think appropriate. You can have multiple mail servers using the same information, without the hassle and delay of having to copy it to each. Topics covered in this document: Building Postfix with LDAP support Configuring LDAP lookups Example: aliases Example: virtual domains/addresses Example: expanding LDAP groups Other uses of LDAP lookups Notes and things to think about Feedback Credits

Building Postfix with LDAP support


These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Note 1: Postfix no longer supports the LDAP version 1 interface. Note 2: to use LDAP with Debian GNU/Linux's Postfix, all you need is to install the postfix-ldap package and you're done. There is no need to recompile Postfix. You need to have LDAP libraries and include files installed somewhere on your system, and you need to configure the Postfix Makefiles accordingly. For example, to build the OpenLDAP libraries for use with Postfix (i.e. LDAP client code only), you could use the following command:
% ./configure --without-kerberos --without-cyrus-sasl --without-tls \ --without-threads --disable-slapd --disable-slurpd \ --disable-debug --disable-shared

If you're using the libraries from the UM distribution (http://www.umich.edu/~dirsvcs/ldap/ldap.html) or OpenLDAP (http://www.openldap.org), something like this in the top level of your Postfix source tree should work:
% make tidy % make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \

AUXLIBS="-L/usr/local/lib -lldap -L/usr/local/lib -llber"

On Solaris 2.x you may have to specify run-time link information, otherwise ld.so will not find some of the shared libraries:
% make tidy % make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \ AUXLIBS="-L/usr/local/lib -R/usr/local/lib -lldap \ -L/usr/local/lib -R/usr/local/lib -llber"

The 'make tidy' command is needed only if you have previously built Postfix without LDAP support. Instead of '/usr/local' specify the actual locations of your LDAP include files and libraries. Be sure to not mix LDAP include files and LDAP libraries of different versions!! If your LDAP libraries were built with Kerberos support, you'll also need to include your Kerberos libraries in this line. Note that the KTH Kerberos IV libraries might conflict with Postfix's lib/libdns.a, which defines dns_lookup. If that happens, you'll probably want to link with LDAP libraries that lack Kerberos support just to build Postfix, as it doesn't support Kerberos binds to the LDAP server anyway. Sorry about the bother. If you're using one of the Netscape LDAP SDKs, you'll need to change the AUXLIBS line to point to libldap10.so or libldapssl30.so or whatever you have, and you may need to use the appropriate linker option (e.g. '-R') so the executables can find it at runtime.

Configuring LDAP lookups


In order to use LDAP lookups, define an LDAP source as a table lookup in main.cf, for example:
alias_maps = hash:/etc/aliases, ldap:/etc/postfix/ldap-aliases.cf

The file /etc/postfix/ldap-aliases.cf can specify a great number of parameters, including parameters that enable LDAP SSL and STARTTLS. For a complete description, see the ldap_table(5) manual page.

Example: local(8) aliases


Here's a basic example for using LDAP to look up local(8) aliases. Assume that in main.cf, you have:
alias_maps = hash:/etc/aliases, ldap:/etc/postfix/ldap-aliases.cf

and in ldap:/etc/postfix/ldap-aliases.cf you have:


server_host = ldap.example.com search_base = dc=example, dc=com

Upon receiving mail for a local address "ldapuser" that isn't found in the /etc/aliases database, Postfix will search the LDAP server listening at port 389 on ldap.example.com. It will bind anonymously, search for any directory entries whose mailacceptinggeneralid attribute is "ldapuser", read the "maildrop" attributes of those found, and build a list of their maildrops, which will be treated as RFC822 addresses to which the message will be delivered.

Example: virtual domains/addresses


If you want to keep information for virtual lookups in your directory, it's only a little more

complicated. First, you need to make sure Postfix knows about the virtual domain. An easy way to do that is to add the domain to the mailacceptinggeneralid attribute of some entry in the directory. Next, you'll want to make sure all of your virtual recipient's mailacceptinggeneralid attributes are fully qualified with their virtual domains. Finally, if you want to designate a directory entry as the default user for a virtual domain, just give it an additional mailacceptinggeneralid (or the equivalent in your directory) of "@fake.dom". That's right, no user part. If you don't want a catchall user, omit this step and mail to unknown users in the domain will simply bounce. In summary, you might have a catchall user for a virtual domain that looks like this:
dn: cn=defaultrecipient, dc=fake, dc=dom objectclass: top objectclass: virtualaccount cn: defaultrecipient owner: uid=root, dc=someserver, dc=isp, dc=dom 1 -> mailacceptinggeneralid: fake.dom 2 -> mailacceptinggeneralid: @fake.dom 3 -> maildrop: realuser@real.dom

1: Postfix knows fake.dom is a valid virtual domain when it looks for this and gets something (the maildrop) back. 2: This causes any mail for unknown users in fake.dom to go to this entry ... 3: ... and then to its maildrop. Normal users might simply have one mailacceptinggeneralid and maildrop, e.g. "normaluser@fake.dom" and "normaluser@real.dom".

Example: expanding LDAP groups


LDAP is frequently used to store group member information. There are a number of ways of handling LDAP groups. We will show a few examples in order of increasing complexity, but owing to the number of independent variables, we can only present a tiny portion of the solution space. We show how to: 1. query groups as lists of addresses; 2. query groups as lists of user objects containing addresses; 3. forward special lists unexpanded to a separate list server, for moderation or other processing; 4. handle complex schemas by controlling expansion and by treating leaf nodes specially, using features that are new in Postfix 2.4. The example LDAP entries and implied schema below show two group entries ("agroup" and "bgroup") and four user entries ("auser", "buser", "cuser" and "duser"). The group "agroup" has the users "auser" (1) and "buser" (2) as members via DN references in the multi-valued attribute "memberdn", and direct email addresses of two external users "auser@example.org" (3) and "buser@example.org" (4) stored in the multi-valued attribute "memberaddr". The same is true of "bgroup" and "cuser"/"duser" (6)/(7)/(8)/(9), but "bgroup" also has a "maildrop" attribute of "bgroup@mlm.example.com" (5):
dn: cn=agroup, dc=example, dc=com objectclass: top objectclass: ldapgroup cn: agroup mail: agroup@example.com 1 -> memberdn: uid=auser, dc=example, dc=com

2 -> memberdn: uid=buser, dc=example, dc=com 3 -> memberaddr: auser@example.org 4 -> memberaddr: buser@example.org

5 6 7 8 9

-> -> -> -> ->

dn: cn=bgroup, dc=example, dc=com objectclass: top objectclass: ldapgroup cn: bgroup mail: bgroup@example.com maildrop: bgroup@mlm.example.com memberdn: uid=cuser, dc=example, dc=com memberdn: uid=duser, dc=example, dc=com memberaddr: cuser@example.org memberaddr: duser@example.org

dn: uid=auser, dc=example, dc=com objectclass: top objectclass: ldapuser uid: auser 10 -> mail: auser@example.com 11 -> maildrop: auser@mailhub.example.com

dn: uid=buser, dc=example, dc=com objectclass: top objectclass: ldapuser uid: buser 12 -> mail: buser@example.com 13 -> maildrop: buser@mailhub.example.com

dn: uid=cuser, dc=example, dc=com objectclass: top objectclass: ldapuser uid: cuser 14 -> mail: cuser@example.com

dn: uid=duser, dc=example, dc=com objectclass: top objectclass: ldapuser uid: duser 15 -> mail: duser@example.com

Our first use case ignores the "memberdn" attributes, and assumes that groups hold only direct "memberaddr" strings as in (3), (4), (8) and (9). The goal is to map the group address to the list of constituent "memberaddr" values. This is simple, ignoring the various connection related settings (hosts, ports, bind settings, timeouts, ...) we have:

simple.cf: ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = memberaddr $ postmap -q agroup@example.com ldap:/etc/postfix/simple.cf \ auser@example.org,buser@example.org

We search "dc=example, dc=com". The "mail" attribute is used in the query_filter to locate the right group, the "result_attribute" setting described in ldap_table(5) is used to specify that "memberaddr" values from the matching group are to be returned as a comma separated list. Always check tables using postmap(1) with the "-q" option, before deploying them into production use in main.cf. Our second use case instead expands "memberdn" attributes (1), (2), (6) and (7), follows the DN references and returns the "maildrop" of the referenced user entries. Here we use the "special_result_attribute" setting from ldap_table(5) to designate the "memberdn" attribute as holding DNs of the desired member entries. The "result_attribute" setting selects which attributes are returned from the selected DNs. It is important to choose a result attribute that is not also present in the group object, because result attributes are collected from both the group and the member DNs. In this case we choose "maildrop" and assume for the moment that groups never have a "maildrop" (the "bgroup" "maildrop" attribute is for a different use case). The returned data for "auser" and "buser" is from items (11) and (13) in the example data.
special.cf: ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = maildrop special_result_attribute = memberdn $ postmap -q agroup@example.com ldap:/etc/postfix/special.cf \ auser@mailhub.example.com,buser@mailhub.example.com

Note: if the desired member object result attribute is always also present in the group, you get surprising results: the expansion also returns the address of the group. This is a known limitation of Postfix releases prior to 2.4, and is addressed in the new with Postfix 2.4 "leaf_result_attribute" feature described in ldap_table(5). Our third use case has some groups that are expanded immediately, and other groups that are forwarded to a dedicated mailing list manager host for delayed expansion. This uses two LDAP tables, one for users and forwarded groups and a second for groups that can be expanded immediately. It is assumed that groups that require forwarding are never nested members of groups that are directly expanded.
no_expand.cf: ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = maildrop expand.cf ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = maildrop special_result_attribute = memberdn $ postmap -q auser@example.com \ ldap:/etc/postfix/no_expand.cf ldap:/etc/postfix/expand.cf \ auser@mailhub.example.com $ postmap -q agroup@example.com \ ldap:/etc/postfix/no_expand.cf ldap:/etc/postfix/expand.cf \

auser@mailhub.example.com,buser@mailhub.example.com $ postmap -q bgroup@example.com \ ldap:/etc/postfix/no_expand.cf ldap:/etc/postfix/expand.cf \ bgroup@mlm.example.com

Non-group objects and groups with delayed expansion (those that have a maildrop attribute) are rewritten to a single maildrop value. Groups that don't have a maildrop are expanded as the second use case. This admits a more elegant solution with Postfix 2.4 and later. Our final use case is the same as the third, but this time uses new features in Postfix 2.4. We now are able to use just one LDAP table and no longer need to assume that forwarded groups are never nested inside expanded groups.
fancy.cf: ... search_base = dc=example, dc=com query_filter = mail=%s result_attribute = memberaddr special_result_attribute = memberdn terminal_result_attribute = maildrop leaf_result_attribute = mail $ postmap -q auser@example.com ldap:/etc/postfix/fancy.cf \ auser@mailhub.example.com $ postmap -q cuser@example.com ldap:/etc/postfix/fancy.cf \ cuser@example.com $ postmap -q agroup@example.com ldap:/etc/postfix/fancy.cf \ auser@mailhub.example.com,buser@mailhub.example.com,auser@exam ple.org,buser@example.org $ postmap -q bgroup@example.com ldap:/etc/postfix/fancy.cf \ bgroup@mlm.example.com

Above, delayed expansion is enabled via "terminal_result_attribute", which, if present, is used as the sole result and all other expansion is suppressed. Otherwise, the "leaf_result_attribute" is only returned for leaf objects that don't have a "special_result_attribute" (non-groups), while the "result_attribute" (direct member address of groups) is returned at every level of recursive expansion, not just the leaf nodes. This fancy example illustrates all the features of Postfix 2.4 group expansion.

Other uses of LDAP lookups


Other common uses for LDAP lookups include rewriting senders and recipients with Postfix's canonical lookups, for example in order to make mail leaving your site appear to be coming from "First.Last@example.com" instead of "userid@example.com".

Notes and things to think about


The bits of schema and attribute names used in this document are just examples. There's nothing special about them, other than that some are the defaults in the LDAP configuration parameters. You can use whatever schema you like, and configure Postfix accordingly. You probably want to make sure that mailacceptinggeneralids are unique, and that not just anyone can specify theirs as postmaster or root, say. An entry can have an arbitrary number of mailacceptinggeneralids or maildrops. Maildrops can also be comma-separated lists of addresses. They will all be found and returned by the lookups. For example, you could define an entry intended for use as a mailing list that looks like this (Warning! Schema made up just for this example):

dn: cn=Accounting Staff List, dc=example, dc=com cn: Accounting Staff List o: example.com objectclass: maillist mailacceptinggeneralid: accountingstaff mailacceptinggeneralid: accounting-staff maildrop: mylist-owner maildrop: an-accountant maildrop: some-other-accountant maildrop: this, that, theother

If you use an LDAP map for lookups other than aliases, you may have to make sure the lookup makes sense. In the case of virtual lookups, maildrops other than mail addresses are pretty useless, because Postfix can't know how to set the ownership for program or file delivery. Your query_filter should probably look something like this:
query_filter = (&(mailacceptinggeneralid=%s)(!(|(maildrop="*|*") (maildrop="*:*")(maildrop="*/*"))))

And for that matter, even for aliases, you may not want users able to specify their maildrops as programs, includes, etc. This might be particularly pertinent on a "sealed" server where they don't have local UNIX accounts, but exist only in LDAP and Cyrus. You might allow the fun stuff only for directory entries owned by an administrative account, so that if the object had a program as its maildrop and weren't owned by "cn=root" it wouldn't be returned as a valid local user. This will require some thought on your part to implement safely, considering the ramifications of this type of delivery. You may decide it's not worth the bother to allow any of that nonsense in LDAP lookups, ban it in the query_filter, and keep things like majordomo lists in local alias databases.
query_filter = (&(mailacceptinggeneralid=%s)(!(|(maildrop="*|*") (maildrop="*:*")(maildrop="*/*"))(owner=cn=root, dc=your, dc=com)))

LDAP lookups are slower than local DB or DBM lookups. For most sites they won't be a bottleneck, but it's a good idea to know how to tune your directory service. Multiple LDAP maps share the same LDAP connection if they differ only in their query related parameters: base, scope, query_filter, and so on. To take advantage of this, avoid spurious differences in the definitions of LDAP maps: host selection order, version, bind, tls parameters, ... should be the same for multiple maps whenever possible.

Feedback
If you have questions, send them to postfix-users@postfix.org. Please include relevant information about your Postfix setup: LDAP-related output from postconf, which LDAP libraries you built with, and which directory server you're using. If your question involves your directory contents, please include the applicable bits of some directory entries.

Credits
Manuel Guesdon: Spotted a bug with the timeout attribute. John Hensley: Multiple LDAP sources with more configurable attributes. Carsten Hoeger: Search scope handling. LaMont Jones: Domain restriction, URL and DN searches, multiple result attributes. Mike Mattice: Alias dereferencing control.

Hery Rakotoarisoa: Patches for LDAPv3 updating. Prabhat K Singh: Wrote the initial Postfix LDAP lookups and connection caching. Keith Stevenson: RFC 2254 escaping in queries. Samuel Tardieu: Noticed that searches could include wildcards, prompting the work on RFC 2254 escaping in queries. Spotted a bug in binding. Sami Haahtinen: Referral chasing and v3 support. Victor Duchovni: ldap_bind() timeout. With fixes from LaMont Jones: OpenLDAP cache deprecation. Limits on recursion, expansion and search results size. LDAP connection sharing for maps differing only in the query parameters. Liviu Daia: Support for SSL/STARTTLS. Support for storing map definitions in external files (ldap:/path/ldap.cf) needed to securely store passwords for plain auth. Liviu Daia revised the configuration interface and added the main.cf configuration feature. Liviu Daia with further refinements from Jose Luis Tallon and Victor Duchovni developed the common query, result_format, domain and expansion_limit interface for LDAP, MySQL and PosgreSQL. Gunnar Wrobel provided a first implementation of a feature to limit LDAP search results to leaf nodes only. Victor generalized this into the Postfix 2.4 "leaf_result_attribute" feature.

And of course Wietse.

Postfix MySQL Howto


Introduction
The Postfix mysql map type allows you to hook up Postfix to a MySQL database. This implementation allows for multiple mysql databases: you can use one for a virtual(5) table, one for an access(5) table, and one for an aliases(5) table if you want. You can specify multiple servers for the same database, so that Postfix can switch to a good database server if one goes bad. Busy mail servers using mysql maps will generate lots of concurrent mysql clients, so the mysql server(s) should be run with this fact in mind. You can reduce the number of concurrent mysql clients by using the Postfix proxymap(8) service.

Building Postfix with MySQL support


These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Note: to use mysql with Debian GNU/Linux's Postfix, all you need is to install the postfix-mysql package and you're done. There is no need to recompile Postfix. The Postfix MySQL client utilizes the mysql client library, which can be obtained from: http://www.mysql.com/downloads/ http://sourceforge.net/projects/mysql/ In order to build Postfix with mysql map support, you will need to add -DHAS_MYSQL and -I for the directory containing the mysql headers, and the mysqlclient library (and libm) to AUXLIBS, for example:
make -f Makefile.init makefiles \ 'CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include' \ 'AUXLIBS=-L/usr/local/mysql/lib -lmysqlclient -lz -lm'

On Solaris, use this instead:


make -f Makefile.init makefiles \ 'CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include' \ 'AUXLIBS=-L/usr/local/mysql/lib -R/usr/local/mysql/lib \ -lmysqlclient -lz -lm'

Then, just run 'make'. This requires libz, the compression library. Older mysql implementations build without libz.

Using MySQL tables


Once Postfix is built with mysql support, you can specify a map type in main.cf like this:
alias_maps = mysql:/etc/postfix/mysql-aliases.cf

The file /etc/postfix/mysql-aliases.cf specifies lots of information telling Postfix how to reference the mysql database. For a complete description, see the mysql_table(5) manual page.

Example: local aliases


# # mysql config file for local(8) aliases(5) lookups # # The user name and password to log into the mysql server. user = someone password = some_password # The database name on the servers. dbname = customer_database # For Postfix 2.2 and later The SQL query template. # See mysql_table(5) for details. query = SELECT forw_addr FROM mxaliases WHERE alias='%s' AND status='paid' # For Postfix releases prior to 2.2. See mysql_table(5) for details. select_field = forw_addr table = mxaliases where_field = alias # Don't forget the leading "AND"! additional_conditions = AND status = 'paid'

Additional notes
The MySQL configuration interface setup allows for multiple mysql databases: you can use one for a virtual table, one for an access table, and one for an aliases table if you want. Since sites that have a need for multiple mail exchangers may enjoy the convenience of using a networked mailer database, but do not want to introduce a single point of failure to their system, we've included the ability to have Postfix reference multiple hosts for access to a single mysql map. This will work if sites set up mirrored mysql databases on two or more hosts. Whenever queries fail with an error at one host, the rest of the hosts will be tried in random order. If no mysql server hosts are reachable, then mail will be deferred until at least one of those hosts is reachable.

Credits
The initial version was contributed by Scott Cotton and Joshua Marcus, IC Group, Inc. Liviu Daia revised the configuration interface and added the main.cf configuration feature. Liviu Daia with further refinements from Jose Luis Tallon and Victor Duchovni developed the common query, result_format, domain and expansion_limit interface for LDAP, MySQL and PosgreSQL.

Postfix PCRE Support


PCRE (Perl Compatible Regular Expressions) map support
The optional "pcre" map type allows you to specify regular expressions with the PERL style notation such as \s for space and \S for non-space. The main benefit, however, is that pcre lookups are often faster than regexp lookups. This is because the pcre implementation is often more efficient than the POSIX regular expression implementation that you find on many systems. A description of how to use pcre tables, including examples, is given in the pcre_table(5) manual page. Information about PCRE itself can be found at http://www.pcre.org/.

Building Postfix with PCRE support


These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Note: to use pcre with Debian GNU/Linux's Postfix, all you need is to install the postfix-pcre package and you're done. There is no need to recompile Postfix. In some future, Postfix will have a plug-in interface for adding map types. Until then, you need to compile PCRE support into Postfix. First of all, you need the PCRE library (Perl Compatible Regular Expressions), which can be obtained from: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/. NOTE: pcre versions prior to 2.06 cannot be used. In order to build Postfix with PCRE support you need to add -DHAS_PCRE and a -I for the PCRE include file to CCARGS, and add the path to the PCRE library to AUXLIBS, for example:
make -f Makefile.init makefiles \ "CCARGS=-DHAS_PCRE -I/usr/local/include" \ "AUXLIBS=-L/usr/local/lib -lpcre"

Solaris needs run-time path information too:


make -f Makefile.init makefiles \ "CCARGS=-DHAS_PCRE -I/usr/local/include" \ "AUXLIBS=-L/usr/local/lib -R/usr/local/lib -lpcre"

Things to know
When Postfix searches a pcre: or regexp: lookup table, each pattern is applied to the entire input string. Depending on the application, that string is an entire client hostname, an entire client IP address, or an entire mail address. Thus, no parent domain or parent network search is done, "user@domain" mail addresses are not broken up into their user and domain

constituent parts, and "user+foo" is not broken up into user and foo. Regular expression tables such as pcre: or regexp: are not allowed to do $number substitution in lookup results that can be security sensitive: currently, that restriction applies to the local aliases(5) database or the virtual(8) delivery agent tables.

Postfix PostgreSQL Howto


Introduction
The Postfix pgsql map type allows you to hook up Postfix to a PostgreSQL database. This implementation allows for multiple pgsql databases: you can use one for a virtual(5) table, one for an access(5) table, and one for an aliases(5) table if you want. You can specify multiple servers for the same database, so that Postfix can switch to a good database server if one goes bad. Busy mail servers using pgsql maps will generate lots of concurrent pgsql clients, so the pgsql server(s) should be run with this fact in mind. You can reduce the number of concurrent pgsql clients by using the Postfix proxymap(8) service.

Building Postfix with PostgreSQL support


These instructions assume that you build Postfix from source code as described in the INSTALL document. Some modification may be required if you build Postfix from a vendor-specific source package. Note: to use pgsql with Debian GNU/Linux's Postfix, all you need to do is to install the postfixpgsql package and you're done. There is no need to recompile Postfix. In order to build Postfix with pgsql map support, you specify -DHAS_PGSQL, the directory with the PostgreSQL header files, and the location of the libpq library file. For example:
% make tidy % make -f Makefile.init makefiles \ 'CCARGS=-DHAS_PGSQL -I/usr/local/include/pgsql' \ 'AUXLIBS=-L/usr/local/lib -lpq'

Then just run 'make'.

Configuring PostgreSQL lookup tables


Once Postfix is built with pgsql support, you can specify a map type in main.cf like this:
/etc/postfix/main.cf: alias_maps = pgsql:/etc/postfix/pgsql-aliases.cf

The file /etc/postfix/pgsql-aliases.cf specifies lots of information telling postfix how to reference the pgsql database. For a complete description, see the pgsql_table(5) manual page.

Example: local aliases


# # pgsql config file for local(8) aliases(5) lookups #

# # The hosts that Postfix will try to connect to hosts = host1.some.domain host2.some.domain # The user name and password to log into the pgsql server. user = someone password = some_password # The database name on the servers. dbname = customer_database # Postfix 2.2 and later The SQL query template. See pgsql_table(5). query = SELECT forw_addr FROM mxaliases WHERE alias='%s' AND status='paid' # For Postfix releases prior to 2.2. See pgsql_table(5) for details. select_field = forw_addr table = mxaliases where_field = alias # Don't forget the leading "AND"! additional_conditions = AND status = 'paid'

Using mirrored databases


Sites that have a need for multiple mail exchangers may enjoy the convenience of using a networked mailer database, but do not want to introduce a single point of failure to their system. For this reason we've included the ability to have Postfix reference multiple hosts for access to a single pgsql map. This will work if sites set up mirrored pgsql databases on two or more hosts. Whenever queries fail with an error at one host, the rest of the hosts will be tried in random order. If no pgsql server hosts are reachable, then mail will be deferred until at least one of those hosts is reachable.

Credits
This code is based upon the Postfix mysql map by Scott Cotton and Joshua Marcus, IC Group, Inc. The PostgreSQL changes were done by Aaron Sethman. Updates for Postfix 1.1.x and PostgreSQL 7.1+ and support for calling stored procedures were added by Philip Warner. LaMont Jones was the initial Postfix pgsql maintainer. Liviu Daia revised the configuration interface and added the main.cf configuration feature. Liviu Daia revised the configuration interface and added the main.cf configuration feature. Liviu Daia with further refinements from Jose Luis Tallon and Victor Duchovni developed the common query, result_format, domain and expansion_limit interface for LDAP, MySQL and PosgreSQL. Leandro Santi updated the PostgreSQL client after the PostgreSQL developers made major database API changes in response to SQL injection problems, and made PQexec() handling more robust.

Postfix SQLite Howto


Introduction
The Postfix sqlite map type allows you to hook up Postfix to a SQLite database. This implementation allows for multiple sqlite databases: you can use one for a virtual(5) table, one for an access(5) table, and one for an aliases(5) table if you want.

Building Postfix with SQLite support


The Postfix SQLite client utilizes the sqlite3 library, which can be obtained from: http://www.sqlite.org/ In order to build Postfix with sqlite map support, you will need to add to CCARGS the flags -DHAS_SQLITE and -I with the directory containing the sqlite header files, and you will need to add to AUXLIBS the directory and name of the sqlite3 library, plus the name of the standard POSIX thread library (pthread). For example:
make -f Makefile.init makefiles \ 'CCARGS=-DHAS_SQLITE -I/usr/local/include' \ 'AUXLIBS=-L/usr/local/lib -lsqlite3 -lpthread'

Then, just run 'make'.

Using SQLite tables


Once Postfix is built with sqlite support, you can specify a map type in main.cf like this:
alias_maps = sqlite:/etc/postfix/sqlite-aliases.cf

The file /etc/postfix/sqlite-aliases.cf specifies lots of information telling Postfix how to reference the sqlite database. For a complete description, see the sqlite_table(5) manual page.

Example: local aliases


# # sqlite config file for local(8) aliases(5) lookups # # Path to database dbpath = /some/path/to/sqlite_database # See sqlite_table(5) for details. query = SELECT forw_addr FROM mxaliases WHERE alias='%s' AND status='paid'

Additional notes
The SQLite configuration interface setup allows for multiple sqlite databases: you can use one for a virtual table, one for an access table, and one for an aliases table if you want.

Credits
SQLite support was added with Postfix version 2.8. Implementation by Axel Steiner Documentation by Jesus Garcia Crespo

Postfix VERP Howto


Postfix VERP support
Postfix versions 1.1 and later support variable envelope return path addresses on request. When VERP style delivery is requested, each recipient of a message receives a customized copy of the message, with his/her own recipient address encoded in the envelope sender address. For example, when VERP style delivery is requested, Postfix delivers mail from "ownerlistname@origin" for a recipient "user@domain", with a sender address that encodes the recipient as follows:
owner-listname+user=domain@origin

Thus, undeliverable mail can reveal the undeliverable recipient address without requiring the list owner to parse bounce messages. The VERP concept was popularized by the qmail MTA and by the ezmlm mailing list manager. See http://cr.yp.to/proto/verp.txt for the ideas behind this concept. Topics covered in this document: Postfix VERP configuration parameters Using VERP with majordomo etc. mailing lists VERP support in the Postfix SMTP server VERP support in the Postfix sendmail command VERP support in the Postfix QMQP server

Postfix VERP configuration parameters


With Postfix, the whole process is controlled by four configuration parameters. default_verp_delimiters (default value: +=) What VERP delimiter characters Postfix uses when VERP style delivery is requested but no explicit delimiters are specified. verp_delimiter_filter (default: -+=) What characters Postfix accepts as VERP delimiter characters on the sendmail command line and in SMTP commands. Many characters must not be used as VERP delimiter characters, either because they already have a special meaning in email addresses (such as the @ or the %), because they are used as part of a username or domain name (such as alphanumerics), or because they are non-ASCII or control characters. And who knows, some characters may tickle bugs in vulnerable software, and we would not want that to happen. smtpd_authorized_verp_clients (default value: none)

What SMTP clients are allowed to request VERP style delivery. The Postfix QMQP server uses its own access control mechanism, and local submission (via /usr/sbin/sendmail etc.) is always authorized. To authorize a host, list its name, IP address, subnet (net/mask) or parent .domain. With Postfix versions 1.1 and 2.0, this parameter is called authorized_verp_clients (default: $mynetworks). disable_verp_bounces (default: no) if Postfix sends one bounce report for multi-recipient VERP mail, or one bounce report per recipient. The default, one per recipient, is what ezmlm needs.

Using VERP with majordomo etc. mailing lists


In order to make VERP useful with majordomo etc. mailing lists, you would configure the list manager to submit mail according to one of the following two forms: Postfix 2.3 and later:
% sendmail -XV -f owner-listname other-arguments... % sendmail -XV+= -f owner-listname other-arguments...

Postfix 2.2 and earlier (Postfix 2.3 understands the old syntax for backwards compatibility, but will log a warning that reminds you of the new syntax):
% sendmail -V -f owner-listname other-arguments... % sendmail -V+= -f owner-listname other-arguments...

The first form uses the default main.cf VERP delimiter characters. The second form allows you to explicitly specify the VERP delimiter characters. The example shows the recommended values. This text assumes that you have set up an owner-listname alias that routes undeliverable mail to a real person:
/etc/aliases: owner-listname: yourname+listname

In order to process bounces we are going to make extensive use of address extension tricks. You need to tell Postfix that + is the separator between an address and its optional address extension, that address extensions are appended to .forward file names, and that address extensions are to be discarded when doing alias expansions:
/etc/postfix/main.cf: recipient_delimiter = + forward_path = $home/.forward${recipient_delimiter}${extension}, $home/.forward propagate_unmatched_extensions = canonical, virtual

(the last two parameter settings are default settings). You need to set up a file named .forward+listname with the commands that process all the mail that is sent to the owner-listname address:
~/.forward+listname: "|/some/where/command ..."

With this set up, undeliverable mail for user@domain will be returned to the following address:
owner-listname+user=domain@your.domain

which is processed by the command in your .forward+listname file. The message should contain, among others, a To: header with the encapsulated recipient sender address:
To: owner-listname+user=domain@your.domain

It is left as an exercise for the reader to parse the To: header line and to pull out the user=domain part from the recipient address.

VERP support in the Postfix SMTP server


The Postfix SMTP server implements a command XVERP to enable VERP style delivery. The syntax allows two forms:
MAIL FROM:<sender@domain> XVERP MAIL FROM:<sender@domain> XVERP=+=

The first form uses the default main.cf VERP delimiters, the second form overrides them explicitly. The values shown are the recommended ones.

VERP support in the Postfix sendmail command


The Postfix sendmail command has a -V flag to request VERP style delivery. Specify one of the following two forms: Postfix 2.3 and later:
% sendmail -XV -f owner-listname .... % sendmail -XV+= -f owner-listname ....

Postfix 2.2 and earlier (Postfix 2.3 understands the old syntax for backwards compatibility, but will log a warning that reminds you of the new syntax):
% sendmail -V -f owner-listname .... % sendmail -V+= -f owner-listname ....

The first form uses the default main.cf VERP delimiters, the second form overrides them explicitly. The values shown are the recommended ones.

VERP support in the Postfix QMQP server


When the Postfix QMQP server receives mail with an envelope sender address of the form:
listname-@your.domain-@[]

Postfix generates sender addresses "listname-user=domain@your.domain", using "-=" as the VERP delimiters because qmail/ezmlm expect this. More generally, a sender address of "prefix@origin-@[]" requests VERP style delivery with sender addresses of the form "prefixuser=domain@origin". However, Postfix allows only VERP delimiters that are specified with the verp_delimiter_filter parameter. In particular, the "=" delimiter is required for qmail compatibility (see the qmail addresses(5) manual page for details).

Postfix and Linux


Berkeley DB issues
If you can't compile Postfix because the file "db.h" isn't found, then you MUST install the Berkeley DB development package (name: db???-devel-???) that matches your system library. You can find out what is installed with the rpm command. For example:
$ rpm -qf /usr/lib/libdb.so db4-4.3.29-2

This means that you need to install db4-devel-4.3.29-2 (on some systems, specify "rpm -qf /lib/libdb.so" instead). DO NOT download some Berkeley DB version from the network. Every Postfix program will dump core when it is built with a different Berkeley DB version than the version that is used by the system library routines. See the DB_README file for further information.

Procmail issues
On RedHat Linux 7.1 and later procmail no longer has permission to write the mail spool directory. Workaround:
# chmod 1777 /var/spool/mail

Syslogd performance
LINUX syslogd uses synchronous writes by default. Because of this, syslogd can actually use more system resources than Postfix. To avoid such badness, disable synchronous mail logfile writes by editing /etc/syslog.conf and by prepending a - to the logfile name:
/etc/syslog.conf: mail.* -/var/log/mail.log

Send a "kill -HUP" to the syslogd to make the change effective.

Postfix and NFS


Postfix support status for NFS
What is the status of support for Postfix on NFS? The answer is that Postfix itself is supported when you use NFS, but there is no promise that an NFS-related problem will promptly receive a Postfix workaround, or that a workaround will even be possible. That said, Postfix will in many cases work very well on NFS, because Postfix implements a number of workarounds (see below). Good NFS implementations seldom if ever give problems with Postfix, so Wietse recommends that you spend your money wisely.

Postfix file locking and NFS


For the Postfix mail queue, it does not matter how well NFS file locking works. The reason is that you cannot share Postfix queues among multiple running Postfix instances. You can use NFS to switch a Postfix mail queue from one NFS client to another one, but only one NFS client can access a Postfix mail queue at any particular point in time. For mailbox file sharing with NFS, your options are to use fcntl (kernel locks), dotlock (username.lock files), to use both locking methods simultaneously, or to switch to maildir format. The maildir format uses one file per message and needs no file locking support in Postfix or in other mail software. Many sites that use mailbox format play safe and use both locking methods simultaneously.
/etc/postfix/main.cf: virtual_mailbox_lock = fcntl, dotlock mailbox_delivery_lock = fcntl, dotlock

Postfix NFS workarounds


The list below summarizes the workarounds that exist for running Postfix on NFS as of the middle of 2003. As a reminder, Postfix itself is still supported when it runs on NFS, but there is no promise that an NFS-related problem will promptly receive a Postfix workaround, or that a workaround will even be possible. Problem: when renaming a file, the operation may succeed but report an error anyway[1]. Workaround: when rename(old, new) reports an error, Postfix checks if the new name exists and the old name is gone. If the check succeeds, Postfix assumes that the rename() operation completed normally. Problem: when creating a directory, the operation may succeed but report an error anyway[1]. Workaround: when mkdir(new) reports an EEXIST error, Postfix checks if the new name resolves to a directory. If the check succeeds, Postfix assumes that the mkdir() operation completed normally.

Problem: when creating a hardlink to a file, the operation may succeed but report an error anyway[1]. Workaround: when link(old, new) fails, Postfix compares the device and inode number of the old and new files. When the two files are identical, Postfix assumes that the link() operation completed normally. Problem: when creating a dotlock (username.lock) file, the operation may succeed but report an error anyway[1]. Workaround: in this case, the only safe action is to back off and try again later. Problem: when a file server's "time of day" clock is not synchronized with the client's "time of day" clock, email deliveries are delayed by a minute or more. Workaround: Postfix explicitly sets file time stamps to avoid delays with new mail (Postfix uses "last modified" file time stamps to decide when a queue file is ready for delivery).
[1]

How can an operation succeed and report an error anyway?

Suppose that an NFS server executes a client request successfully, and that the server's reply to the client is lost. After some time the client retransmits the request to the server. Normally, the server remembers that it already completed the request (it keeps a list of recently-completed requests and replies), and simply retransmits the reply. However, when the server has rebooted or when it has been very busy, the server no longer remembers that it already completed the request, and repeats the operation. This causes no problems with file read/write requests (they contain a file offset and can therefore be repeated safely), but fails with non-idempotent operations. For example, when the server executes a retransmitted rename() request, the server reports an ENOENT error because the old name does not exist; and when the server executes a retransmitted link(), mkdir() or create() request, the server reports an EEXIST error because the name already exists. Thus, successful, non-idempotent, NFS operations will report false errors when the server reply is lost, the client retransmits the request, and the server does not remember that it already completed the request.

Postfix + Maildrop Howto


Introduction
This document discusses various options to plug the maildrop delivery agent into Postfix: Direct delivery without the local delivery agent Indirect delivery via the local delivery agent Credits

Direct delivery without the local delivery agent


Postfix can be configured to deliver mail directly to maildrop, without using the local(8) delivery agent as an intermediate. This means that you do not get local aliases(5) expansion or $HOME/.forward file processing. You would typically do this for hosted domains with recipients that don't have UNIX home directories. The following example shows how to use maildrop for some.domain and for someother.domain. The example comes in two parts. Part 1 describes changes to the main.cf file:
1 /etc/postfix/main.cf: 2 maildrop_destination_recipient_limit = 1 3 virtual_mailbox_domains = some.domain someother.domain 4 virtual_transport = maildrop 5 virtual_mailbox_maps = hash:/etc/postfix/virtual_mailbox 6 virtual_alias_maps = hash:/etc/postfix/virtual_alias 7 8 /etc/postfix/virtual_mailbox: 9 user1@some.domain ...text here does not matter... 10 user2@some.domain ...text here does not matter... 11 user3@someother.domain ...text here does not matter... 12 13 /etc/postfix/virtual_alias: 14 postmaster@some.domain postmaster 15 postmaster@someother.domain postmaster

Line 2 is needed so that Postfix will provide one recipient at a time to the maildrop delivery agent. Line 3 informs Postfix that some.domain and someother.domain are so-called virtual mailbox domains. Instead of listing the names in main.cf you can also list them in a file; see the virtual_mailbox_domains documentation for details. Line 4 specifies that mail for some.domain and someother.domain should be delivered by the maildrop delivery agent. Lines 5 and 8-11 specify what recipients the Postfix SMTP server should receive mail for. This prevents the mail queue from becoming clogged with undeliverable messages. Specify an empty value ("virtual_mailbox_maps =") to disable this feature.

Lines 6 and 13-15 redirect mail for postmaster to the local postmaster. RFC 821 requires that every domain has a postmaster address. The vmail userid as used below is the user that maildrop should run as. This would be the owner of the virtual mailboxes if they all have the same owner. If maildrop is suid (see maildrop documentation), then maildrop will change to the appropriate owner to deliver the mail. Note: Do not use the postfix user as the maildrop user. Part 2 describes changes to the master.cf file:
/etc/postfix/master.cf: maildrop unix n n pipe flags=ODRhu user=vmail argv=/path/to/maildrop -d ${recipient}

The pipe(8) manual page gives a detailed description of the above command line arguments, and more. If you want to support user+extension@domain style addresses, use the following instead:
/etc/postfix/master.cf: maildrop unix n n pipe flags=ODRhu user=vmail argv=/path/to/maildrop -d ${user}@${domain} ${extension} ${recipient} ${user} $ {nexthop}

The mail is delivered to ${user}@${domain} (search key for maildrop userdb lookup). The $ {extension} and the other address components are available to maildrop rules as $1, $2, $3, ... and can be omitted from master.cf or ignored by maildrop when not needed. With Postfix 2.4 and earlier, use ${nexthop} instead of ${domain}.

Indirect delivery via the local delivery agent


Postfix can be configured to deliver mail to maildrop via the local delivery agent. This is slightly less efficient than the "direct" approach discussed above, but gives you the convenience of local aliases(5) expansion and $HOME/.forward file processing. You would typically use this for domains that are listed in mydestination and that have users with a UNIX system account. To configure maildrop delivery for all UNIX system accounts:
/etc/postfix/main.cf: mailbox_command = /path/to/maildrop -d ${USER}

Note: ${USER} is spelled in upper case. To enable maildrop delivery for specific users only, you can use the Postfix local(8) delivery agent's mailbox_command_maps feature:
/etc/postfix/main.cf: mailbox_command_maps = hash:/etc/postfix/mailbox_commands /etc/postfix/mailbox_commands: you /path/to/maildrop -d ${USER}

Maildrop delivery for specific users is also possible by invoking it from the user's $HOME/.forward file:
/home/you/.forward: "|/path/to/maildrop -d ${USER}"

Credits
The original text was kindly provided by Russell Mosemann. Victor Duchovni provided tips for supporting user+foo@domain addresses. Tonni Earnshaw contributed text about delivery via the local(8) delivery agent.

Postfix Architecture Overview


Introduction
This document presents an overview of the Postfix architecture, and provides pointers to descriptions of every Postfix command or server program. The text gives the general context in which each command or server program is used, and provides pointers to documents with specific usage examples and background information. Topics covered by this document: How Postfix receives mail How Postfix delivers mail Postfix behind the scenes Postfix support commands

How Postfix receives mail


When a message enters the Postfix mail system, the first stop on the inside is the incoming queue. The figure below shows the main processes that are involved with new mail. Names followed by a number are Postfix commands or server programs, while unnumbered names inside shaded areas represent Postfix queues. trivialrewrite(8) Network -> Network -> smtpd(8) ^ | | v cleanup(8) -> incoming

maildrop ^ | -> sendmail(1) -> Local postdrop(1) Network mail enters Postfix via the smtpd(8) or qmqpd(8) servers. These servers remove the SMTP or QMQP protocol encapsulation, enforce some sanity checks to protect Postfix, and give the sender, recipients and message content to the cleanup(8) server. The smtpd(8) server can be configured to block unwanted mail, as described in the SMTPD_ACCESS_README document. Local submissions are received with the Postfix sendmail(1) compatibility command, and are queued in the maildrop queue by the privileged postdrop(1) command. This arrangement even works while the Postfix mail system is not running. The local pickup(8) server picks up local submissions, enforces some sanity checks to protect Postfix, and gives the sender, recipients and message content to the cleanup(8) server.

\ qmqpd(8) -> / pickup(8) <-

Mail from internal sources is given directly to the cleanup(8) server. These sources are not shown in the figure, and include: mail that is forwarded by the local(8) delivery agent (see next section), messages that are returned to the sender by the bounce(8) server (see secondnext section), and postmaster notifications about problems with Postfix. The cleanup(8) server implements the final processing stage before mail is queued. It adds missing From: and other message headers, and transforms addresses as described in the ADDRESS_REWRITING_README document. Optionally, the cleanup(8) server can be configured to do light-weight content inspection with regular expressions as described in the BUILTIN_FILTER_README document. The cleanup(8) server places the result as a single file into the incoming queue, and notifies the queue manager (see next section) of the arrival of new mail. The trivial-rewrite(8) server rewrites addresses to the standard "user@fully.qualified.domain" form, as described in the ADDRESS_REWRITING_README document. Postfix currently does not implement a rewriting language, but a lot can be done via table lookups and, if need be, regular expressions.

How Postfix delivers mail


Once a message has reached the incoming queue the next step is to deliver it. The figure shows the main components of the Postfix mail delivery apparatus. Names followed by a number are Postfix commands or server programs, while unnumbered names inside shaded areas represent Postfix queues. trivialrewrite(8) ^ | | v smtp(8) -> / lmtp(8) -> Network Network

/ incoming -> active -> qmgr(8) --- local(8) -> File, command \ ^ | | v - virtual(8) -> File \ deferred pipe(8) -> Command The queue manager (the qmgr(8) server process in the figure) is the heart of Postfix mail delivery. It contacts the smtp(8), lmtp(8), local(8), virtual(8), pipe(8), discard(8) or error(8) delivery agents, and sends a delivery request for one or more recipient addresses. The discard(8) and error(8) delivery agents are special: they discard or bounce all mail, and are not shown in the figure above. The queue manager maintains a small active queue with the messages that it has opened for delivery. The active queue acts as a limited window on potentially large incoming or deferred queues. The limited active queue prevents the queue manager from running out of memory under heavy load. The queue manager maintains a separate deferred queue for mail that cannot be delivered, so that a large mail backlog will not slow down normal queue accesses. The queue manager's strategy for delayed mail delivery attempts is described in the QSHAPE_README and TUNING_README documents. The trivial-rewrite(8) server resolves each recipient address according to its local or remote address class, as defined in the ADDRESS_CLASS_README document. Additional

routing information can be specified with the optional transport(5) table. The trivialrewrite(8) server optionally queries the relocated(5) table for recipients whose address has changed; mail for such recipients is returned to the sender with an explanation. The smtp(8) client looks up a list of mail exchangers for the destination host, sorts the list by preference, and tries each server in turn until it finds a server that responds. It then encapsulates the sender, recipient and message content as required by the SMTP protocol; this includes conversion of 8-bit MIME to 7-bit encoding. The lmtp(8) client speaks a protocol similar to SMTP that is optimized for delivery to mailbox servers such as Cyrus. The advantage of this setup is that one Postfix machine can feed multiple mailbox servers over LMTP. The opposite is true as well: one mailbox server can be fed over LMTP by multiple Postfix machines. The local(8) delivery agent understands UNIX-style mailboxes, qmail-compatible maildir files, Sendmail-style system-wide aliases(5) databases, and Sendmail-style per-user .forward files. Multiple local delivery agents can be run in parallel, but parallel delivery to the same user is usually limited. The local(8) delivery agent has hooks for alternative forms of local delivery: you can configure it to deliver to mailbox files in user home directories, you can configure it to delegate mailbox delivery to an external command such as procmail, or you can delegate delivery to a different Postfix delivery agent. The virtual(8) delivery agent is a bare-bones delivery agent that delivers to UNIX-style mailbox or qmail-style maildir files only. This delivery agent can deliver mail for multiple domains, which makes it especially suitable for hosting lots of small domains on a single machine. This is described in the VIRTUAL_README document. The pipe(8) mailer is the outbound interface to other mail processing systems (the Postfix sendmail(1) command being the inbound interface). The interface is UNIX compatible: it provides information on the command line and on the standard input stream, and expects a process exit status code as defined in <sysexits.h>. Examples of delivery via the pipe(8) mailer are in the MAILDROP_README and UUCP_README documents.

Postfix behind the scenes


The previous sections gave an overview of how Postfix server processes send and receive mail. These server processes rely on other server processes that do things behind the scenes. The text below attempts to visualize each service in its own context. As before, names followed by a number are Postfix commands or server programs, while unnumbered names inside shaded areas represent Postfix queues. The resident master(8) server is the supervisor that keeps an eye on the well-being of the Postfix mail system. It is typically started at system boot time with the "postfix start" command, and keeps running until the system goes down. The master(8) server is responsible for starting Postfix server processes to receive and deliver mail, and for restarting servers that terminate prematurely because of some problem. The master(8) server is also responsible for enforcing the server process count limits as specified in the master.cf configuration file. The picture below gives the program hierarchy when Postfix is started up. Only some of the mail handling daemon processes are shown. postfix(1) | |

/ / postsuper(1) / /

postfix-script(1) | | \ \ master(8) | | \ \ postlog(1)

smtpd(8) qmgr(8) local(8) The anvil(8) server implements client connection and request rate limiting for all smtpd(8) servers. The TUNING_README document provides guidance for dealing with misbehaving SMTP clients. The anvil(8) service is available in Postfix version 2.2 and later. <-> smtpd(8) anvil(8) The bounce(8), defer(8) and trace(8) services each maintain their own queue directory trees with per-message logfiles. Postfix uses this information when sending "failed", "delayed" or "success" delivery status notifications to the sender. The trace(8) service also implements support for the Postfix "sendmail -bv" and "sendmail -v" commands which produce reports about how Postfix delivers mail, and is available with Postfix version 2.1 and later. See DEBUG_README for examples. cleanup(8) -> ^ | (Non-) delivery <notice ^ | | v qmgr(8) Postfix -> queue | v bounce(8) defer(8) <trace(8) Delivery agents | v Queue id, recipient, status Network ->

Permessage logfiles The flush(8) servers maintain per-destination logs and implement both ETRN and "sendmail -qRdestination", as described in the ETRN_README document. This moves selected queue files from the deferred queue back to the incoming queue and requests their delivery. The flush(8) service is available with Postfix version 1.0 and later. incoming ^ deferred ^ | smtpd(8) sendmail(1) Destination -> to flush flush(8) <Deferred destination, Delivery agents,

postqueue(1) ^ | | v

queue id

qmgr(8)

Per-destination logs The proxymap(8) servers provide read-only and read-write table lookup service to Postfix processes. This overcomes chroot restrictions, reduces the number of open lookup tables by sharing one open table among multiple processes, and implements single-updater tables. The scache(8) server maintains the connection cache for the Postfix smtp(8) client. When connection caching is enabled for selected destinations, the smtp(8) client does not disconnect immediately after a mail transaction, but gives the connection to the connection cache server which keeps the connection open for a limited amount of time. The smtp(8) client continues with some other mail delivery request. Meanwhile, any smtp(8) process can ask the scache(8) server for that cached connection and reuse it for mail delivery. As a safety measure, Postfix limits the number of times that a connection may be reused. When delivering mail to a destination with multiple mail servers, connection caching can help to skip over a non-responding server, and thus dramatically speed up delivery. SMTP connection caching is available in Postfix version 2.2 and later. More information about this feature is in the CONNECTION_CACHE_README document. smtp(8) --> Internet qmgr(8) | | smtp(8) --> Internet \-| | ^ v | scache(8) The showq(8) servers list the Postfix queue status. This is the queue listing service that does the work for the mailq(1) and postqueue(1) commands. mailq(1) Postfix post- <- showq(8) <queue queue(1) The spawn(8) servers run non-Postfix commands on request, with the client connected via socket or FIFO to the command's standard input, output and error streams. You can find examples of its use in the SMTPD_POLICY_README document. Output < The tlsmgr(8) server runs when TLS (Transport Layer Security, formerly known as SSL) is turned on in the Postfix smtp(8) client or smtpd(8) server. This process has two duties: Maintain the pseudo-random number generator (PRNG) that is used to seed the TLS engines in Postfix smtp(8) client or smtpd(8) server processes. The state of this PRNG is periodically saved to a file, and is read when tlsmgr(8) starts up. Maintain the optional Postfix smtp(8) client or smtpd(8) server caches with TLS session keys. Saved keys can improve performance by reducing the amount of computation at the start of a TLS session. TLS support is available in Postfix version 2.2 and later. Information about the Postfix TLS implementation is in the TLS_README document. Network-> <---seed-----seed---> ->Network /--

smtpd(8) <-session-> / /

tlsmgr(8) <-session-> | | \ \

smtp(8)

smtpd PRNG smtp session state session cache file cache The verify(8) server verifies that a sender or recipient address is deliverable before the smtpd(8) server accepts it. The verify(8) server queries a cache with address verification results. If a result is not found, the verify(8) server injects a probe message into the Postfix queue and processes the status update from a delivery agent or queue manager. This process is described in the ADDRESS_VERIFICATION_README document. The verify(8) service is available with Postfix version 2.1 and later. Postfix < probe | - message > mail Network - smtpd( - verify(8 > 8) ) queue v > > < Postfix -> Local probe < delivery -> status ^ agents Network | Address v verification cache The postscreen(8) server can be put "in front" of Postfix smtpd(8) processes. Its purpose is to accept connections from the network and to decide what SMTP clients are allowed to talk to Postfix. According to the 2008 MessageLabs annual report, 81% of all email was spam, and 90% of that was sent by botnets. While postscreen(8) keeps the zombies away, more smtpd(8) processes remain available for legitimate clients. The postscreen(8) server is still evolving, and is likely to undergo changes that break compatibility with earlier versions. For this reason the postscreen(8) server is not installed with the stable Postfix release. zombie \ zombie other other zombie \ / --- postscreen(8) / \ / smtpd(8)

smtpd(8)

Postfix support commands


The Postfix architecture overview ends with a summary of command-line utilities for day-to-day use of the Postfix mail system. Besides the Sendmail-compatible sendmail(1), mailq(1), and

newaliases(1) commands, the Postfix system comes with it own collection of command-line utilities. For consistency, these are all named postsomething. The postfix(1) command controls the operation of the mail system. It is the interface for starting, stopping, and restarting the mail system, as well as for some other administrative operations. This command is reserved to the super-user. The postalias(1) command maintains Postfix aliases(5) type databases. This is the program that does the work for the newaliases(1) command. The postcat(1) command displays the contents of Postfix queue files. This is a limited, preliminary utility. This program is likely to be superseded by something more powerful that can also edit Postfix queue files. The postconf(1) command displays or updates Postfix main.cf parameters and displays system dependent information about the supported file locking methods, and the supported types of lookup tables. The postdrop(1) command is the mail posting utility that is run by the Postfix sendmail(1) command in order to deposit mail into the maildrop queue directory. The postkick(1) command makes some Postfix internal communication channels available for use in, for example, shell scripts. The postlock(1) command provides Postfix-compatible mailbox locking for use in, for example, shell scripts. The postlog(1) command provides Postfix-compatible logging for shell scripts. The postmap(1) command maintains Postfix lookup tables such as canonical(5), virtual(5) and others. It is a cousin of the UNIX makemap command. The postmulti(1) command repeats the "postfix start" etc. command for each Postfix instance, and supports creation, deletion etc. of Postfix instances. For a tutorial, see MULTI_INSTANCE_README. The postqueue(1) command is the privileged command that is run by Postfix sendmail(1) and mailq(1) in order to flush or list the mail queue. The postsuper(1) command maintains the Postfix queue. It removes old temporary files, and moves queue files into the right directory after a change in the hashing depth of queue directories. This command is run at mail system startup time and when Postfix is restarted.

Postfix Configuration Parameters


Postfix main.cf file format
The Postfix main.cf configuration file specifies a very small subset of all the parameters that control the operation of the Postfix mail system. Parameters not explicitly specified are left at their default values. The general format of the main.cf file is as follows: Each logical line is in the form "parameter = value". Whitespace around the "=" is ignored, as is whitespace at the end of a logical line. Empty lines and whitespace-only lines are ignored, as are lines whose first non-whitespace character is a `#'. A logical line starts with non-whitespace text. A line that starts with whitespace continues a logical line. A parameter value may refer to other parameters. The expressions "$name", "${name}" or "$(name)" are recursively replaced by the value of the named parameter. The expression "${name?value}" expands to "value" when "$name" is non-empty. This form is supported with Postfix version 2.2 and later. The expression "${name:value}" expands to "value" when "$name" is empty. This form is supported with Postfix version 2.2 and later. Specify "$$" to produce a single "$" character. When the same parameter is defined multiple times, only the last instance is remembered. Otherwise, the order of main.cf parameter definitions does not matter. The remainder of this document is a description of all Postfix configuration parameters. Default values are shown after the parameter name in parentheses, and can be looked up with the "postconf -d" command. Note: this is not an invitation to make changes to Postfix configuration parameters. Unnecessary changes are likely to impair the operation of the mail system. 2bounce_notice_recipient (default: postmaster) The recipient of undeliverable mail that cannot be returned to the sender. This feature is enabled with the notify_classes parameter. access_map_defer_code (default: 450) The numerical Postfix SMTP server response code for an access(5) map "defer" action,

including "defer_if_permit" or "defer_if_reject". Prior to Postfix 2.6, the response is hardcoded as "450". Do not change this unless you have a complete understanding of RFC 2821. This feature is available in Postfix 2.6 and later. access_map_reject_code (default: 554) The numerical Postfix SMTP server response code for an access(5) map "reject" action. Do not change this unless you have a complete understanding of RFC 2821. address_verify_cache_cleanup_interval (default: 12h) The amount of time between verify(8) address verification database cleanup runs. This feature requires that the database supports the "delete" and "sequence" operators. Specify a zero interval to disable database cleanup. After each database cleanup run, the verify(8) daemon logs the number of entries that were retained and dropped. A cleanup run is logged as "partial" when the daemon terminates early after "postfix reload", "postfix stop", or no requests for $max_idle seconds. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.7. address_verify_default_transport (default: $default_transport) Overrides the default_transport parameter setting for address verification probes. This feature is available in Postfix 2.1 and later. address_verify_local_transport (default: $local_transport) Overrides the local_transport parameter setting for address verification probes. This feature is available in Postfix 2.1 and later. address_verify_map (default: see "postconf -d" output) Lookup table for persistent address verification status storage. The table is maintained by the verify(8) service, and is opened before the process releases privileges. The lookup table is persistent by default (Postfix 2.7 and later). Specify an empty table name to keep the information in volatile memory which is lost after "postfix reload" or "postfix stop". This is the default with Postfix version 2.6 and earlier. Specify a location in a file system that will not fill up. If the database becomes corrupted, the world comes to an end. To recover delete (NOT: truncate) the file and do "postfix reload". Postfix daemon processes do not use root privileges when opening this file (Postfix 2.5 and

later). The file must therefore be stored under a Postfix-owned directory such as the data_directory. As a migration aid, an attempt to open the file under a non-Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. Examples:
address_verify_map = hash:/var/lib/postfix/verify address_verify_map = btree:/var/lib/postfix/verify

This feature is available in Postfix 2.1 and later. address_verify_negative_cache (default: yes) Enable caching of failed address verification probe results. When this feature is enabled, the cache may pollute quickly with garbage. When this feature is disabled, Postfix will generate an address probe for every lookup. This feature is available in Postfix 2.1 and later. address_verify_negative_expire_time (default: 3d) The time after which a failed probe expires from the address verification cache. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.1 and later. address_verify_negative_refresh_time (default: 3h) The time after which a failed address verification probe needs to be refreshed. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.1 and later. address_verify_poll_count (default: normal: 3, overload: 1) How many times to query the verify(8) service for the completion of an address verification request in progress. By default, the Postfix SMTP server polls the verify(8) service up to three times under nonoverload conditions, and only once when under overload. With Postfix version 2.5 and earlier, the SMTP server always polls the verify(8) service up to three times by default. Specify 1 to implement a crude form of greylisting, that is, always defer the first delivery request for a new address. Examples:
# Postfix 2.6 default address_verify_poll_count = 3 # Poor man's greylisting address_verify_poll_count = 1

This feature is available in Postfix 2.1 and later. address_verify_poll_delay (default: 3s) The delay between queries for the completion of an address verification request in progress. The default polling delay is 3 seconds. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.1 and later. address_verify_positive_expire_time (default: 31d) The time after which a successful probe expires from the address verification cache. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.1 and later. address_verify_positive_refresh_time (default: 7d) The time after which a successful address verification probe needs to be refreshed. The address verification status is not updated when the probe fails (optimistic caching). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.1 and later. address_verify_relay_transport (default: $relay_transport) Overrides the relay_transport parameter setting for address verification probes. This feature is available in Postfix 2.1 and later. address_verify_relayhost (default: $relayhost) Overrides the relayhost parameter setting for address verification probes. This information can be overruled with the transport(5) table. This feature is available in Postfix 2.1 and later. address_verify_sender (default: $double_bounce_sender) The sender address to use in address verification probes; prior to Postfix 2.5 the default was "postmaster". To avoid problems with address probes that are sent in response to address probes, the Postfix SMTP server excludes the probe sender address from all SMTPD access blocks. Specify an empty value (address_verify_sender =) or <> if you want to use the null sender address. Beware, some sites reject mail from <>, even though RFCs require that such addresses be accepted.

Examples:
address_verify_sender = <> address_verify_sender = postmaster@my.domain

This feature is available in Postfix 2.1 and later. address_verify_sender_dependent_default_transport_maps (default: $sender_dependent_default_transport_maps) Overrides the sender_dependent_default_transport_maps parameter setting for address verification probes. This feature is available in Postfix 2.7 and later. address_verify_sender_dependent_relayhost_maps (default: $sender_dependent_relayhost_maps) Overrides the sender_dependent_relayhost_maps parameter setting for address verification probes. This feature is available in Postfix 2.3 and later. address_verify_service_name (default: verify) The name of the verify(8) address verification service. This service maintains the status of sender and/or recipient address verification probes, and generates probes on request by other Postfix processes. address_verify_transport_maps (default: $transport_maps) Overrides the transport_maps parameter setting for address verification probes. This feature is available in Postfix 2.1 and later. address_verify_virtual_transport (default: $virtual_transport) Overrides the virtual_transport parameter setting for address verification probes. This feature is available in Postfix 2.1 and later. alias_database (default: see "postconf -d" output) The alias databases for local(8) delivery that are updated with "newaliases" or with "sendmail -bi". This is a separate configuration parameter because not all the tables specified with $alias_maps have to be local files. Examples:
alias_database = hash:/etc/aliases

alias_database = hash:/etc/mail/aliases

alias_maps (default: see "postconf -d" output) The alias databases that are used for local(8) delivery. See aliases(5) for syntax details. The default list is system dependent. On systems with NIS, the default is to search the local alias database, then the NIS alias database. If you change the alias database, run "postalias /etc/aliases" (or wherever your system stores the mail alias file), or simply run "newaliases" to build the necessary DBM or DB file. The local(8) delivery agent disallows regular expression substitution of $1 etc. in alias_maps, because that would open a security hole. The local(8) delivery agent will silently ignore requests to use the proxymap(8) server within alias_maps. Instead it will open the table directly. Before Postfix version 2.2, the local(8) delivery agent will terminate with a fatal error. Examples:
alias_maps = hash:/etc/aliases, nis:mail.aliases alias_maps = hash:/etc/aliases

allow_mail_to_commands (default: alias, forward) Restrict local(8) mail delivery to external commands. The default is to disallow delivery to "| command" in :include: files (see aliases(5) for the text that defines this terminology). Specify zero or more of: alias, forward or include, in order to allow commands in aliases(5), .forward files or in :include: files, respectively. Example:
allow_mail_to_commands = alias,forward,include

allow_mail_to_files (default: alias, forward) Restrict local(8) mail delivery to external files. The default is to disallow "/file/name" destinations in :include: files (see aliases(5) for the text that defines this terminology). Specify zero or more of: alias, forward or include, in order to allow "/file/name" destinations in aliases(5), .forward files and in :include: files, respectively. Example:
allow_mail_to_files = alias,forward,include

allow_min_user (default: no) Allow a sender or recipient address to have `-' as the first character. By default, this is not allowed, to avoid accidents with software that passes email addresses via the command line. Such software would not be able to distinguish a malicious address from a bona fide

command-line option. Although this can be prevented by inserting a "--" option terminator into the command line, this is difficult to enforce consistently and globally. As of Postfix version 2.5, this feature is implemented by trivial-rewrite(8). With earlier versions this feature was implemented by qmgr(8) and was limited to recipient addresses only. allow_percent_hack (default: yes) Enable the rewriting of the form "user%domain" to "user@domain". This is enabled by default. Note: with Postfix version 2.2, message header address rewriting happens only when one of the following conditions is true: The message is received with the Postfix sendmail(1) command, The message is received from a network client that matches $local_header_rewrite_clients, The message is received from the network, and the remote_header_rewrite_domain parameter specifies a non-empty value. To get the behavior before Postfix version 2.2, specify "local_header_rewrite_clients = static:all". Example:
allow_percent_hack = no

allow_untrusted_routing (default: no) Forward mail with sender-specified routing (user[@%!]remote[@%!]site) from untrusted clients to destinations matching $relay_domains. By default, this feature is turned off. This closes a nasty open relay loophole where a backup MX host can be tricked into forwarding junk mail to a primary MX host which then spams it out to the world. This parameter also controls if non-local addresses with sender-specified routing can match Postfix access tables. By default, such addresses cannot match Postfix access tables, because the address is ambiguous. alternate_config_directories (default: empty) A list of non-default Postfix configuration directories that may be specified with "-c config_directory" on the command line, or via the MAIL_CONFIG environment parameter. This list must be specified in the default Postfix configuration directory, and is used by set-gid Postfix commands such as postqueue(1) and postdrop(1). always_add_missing_headers (default: no) Always add (Resent-) From:, To:, Date: or Message-ID: headers when not present. Postfix 2.6 and later add these headers only when clients match the local_header_rewrite_clients

parameter setting. Earlier Postfix versions always add these headers; this may break DKIM signatures that cover non-existent headers. always_bcc (default: empty) Optional address that receives a "blind carbon copy" of each message that is received by the Postfix mail system. Note: if mail to the BCC address bounces it will be returned to the sender. Note: automatic BCC recipients are produced only for new mail. To avoid mailer loops, automatic BCC recipients are not generated after Postfix forwards mail internally, or after Postfix generates mail itself. anvil_rate_time_unit (default: 60s) The time unit over which client connection rates and other rates are calculated. This feature is implemented by the anvil(8) service which is available in Postfix version 2.2 and later. The default interval is relatively short. Because of the high frequency of updates, the anvil(8) server uses volatile memory only. Thus, information is lost whenever the process terminates. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). anvil_status_update_time (default: 600s) How frequently the anvil(8) connection and rate limiting server logs peak usage information. This feature is available in Postfix 2.2 and later. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). append_at_myorigin (default: yes) With locally submitted mail, append the string "@$myorigin" to mail addresses without domain information. With remotely submitted mail, append the string "@$remote_header_rewrite_domain" instead. Note 1: this feature is enabled by default and must not be turned off. Postfix does not support domain-less addresses. Note 2: with Postfix version 2.2, message header address rewriting happens only when one of the following conditions is true: The message is received with the Postfix sendmail(1) command, The message is received from a network client that matches $local_header_rewrite_clients, The message is received from the network, and the remote_header_rewrite_domain

parameter specifies a non-empty value. To get the behavior before Postfix version 2.2, specify "local_header_rewrite_clients = static:all". append_dot_mydomain (default: yes) With locally submitted mail, append the string ".$mydomain" to addresses that have no ".domain" information. With remotely submitted mail, append the string ". $remote_header_rewrite_domain" instead. Note 1: this feature is enabled by default. If disabled, users will not be able to send mail to "user@partialdomainname" but will have to specify full domain names instead. Note 2: with Postfix version 2.2, message header address rewriting happens only when one of the following conditions is true: The message is received with the Postfix sendmail(1) command, The message is received from a network client that matches $local_header_rewrite_clients, The message is received from the network, and the remote_header_rewrite_domain parameter specifies a non-empty value. To get the behavior before Postfix version 2.2, specify "local_header_rewrite_clients = static:all". application_event_drain_time (default: 100s) How long the postkick(1) command waits for a request to enter the server's input buffer before giving up. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). This feature is available in Postfix 2.1 and later. authorized_flush_users (default: static:anyone) List of users who are authorized to flush the queue. By default, all users are allowed to flush the queue. Access is always granted if the invoking user is the super-user or the $mail_owner user. Otherwise, the real UID of the process is looked up in the system password file, and access is granted only if the corresponding login name is on the access list. The username "unknown" is used for processes whose real UID is not found in the password file. Specify a list of user names, "/file/name" or "type:table" patterns, separated by commas and/or whitespace. The list is matched left to right, and the search stops on the first match. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a name matches a lookup key (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "!pattern" to exclude a name from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later.

This feature is available in Postfix 2.2 and later. authorized_mailq_users (default: static:anyone) List of users who are authorized to view the queue. By default, all users are allowed to view the queue. Access is always granted if the invoking user is the super-user or the $mail_owner user. Otherwise, the real UID of the process is looked up in the system password file, and access is granted only if the corresponding login name is on the access list. The username "unknown" is used for processes whose real UID is not found in the password file. Specify a list of user names, "/file/name" or "type:table" patterns, separated by commas and/or whitespace. The list is matched left to right, and the search stops on the first match. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a name matches a lookup key (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "!pattern" to exclude a user name from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. This feature is available in Postfix 2.2 and later. authorized_submit_users (default: static:anyone) List of users who are authorized to submit mail with the sendmail(1) command (and with the privileged postdrop(1) helper command). By default, all users are allowed to submit mail. Otherwise, the real UID of the process is looked up in the system password file, and access is granted only if the corresponding login name is on the access list. The username "unknown" is used for processes whose real UID is not found in the password file. To deny mail submission access to all users specify an empty list. Specify a list of user names, "/file/name" or "type:table" patterns, separated by commas and/or whitespace. The list is matched left to right, and the search stops on the first match. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a name matches a lookup key (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "!pattern" to exclude a user name from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. Example:
authorized_submit_users = !www, static:all

This feature is available in Postfix 2.2 and later. authorized_verp_clients (default: $mynetworks) What SMTP clients are allowed to specify the XVERP command. This command requests that mail be delivered one recipient at a time with a per recipient return address. By default, only trusted clients are allowed to specify XVERP.

This parameter was introduced with Postfix version 1.1. Postfix version 2.1 renamed this parameter to smtpd_authorized_verp_clients and changed the default to none. Specify a list of network/netmask patterns, separated by commas and/or whitespace. The mask specifies the number of bits in the network part of a host address. You can also specify hostnames or .domain names (the initial dot causes the domain to match any name below it), "/file/name" or "type:table" patterns. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a table entry matches a lookup string (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "! pattern" to exclude an address or network block from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. Note: IP version 6 address information must be specified inside [] in the authorized_verp_clients value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. backwards_bounce_logfile_compatibility (default: yes) Produce additional bounce(8) logfile records that can be read by Postfix versions before 2.0. The current and more extensible "name = value" format is needed in order to implement more sophisticated functionality. This feature is available in Postfix 2.1 and later. berkeley_db_create_buffer_size (default: 16777216) The per-table I/O buffer size for programs that create Berkeley DB hash or btree tables. Specify a byte count. This feature is available in Postfix 2.0 and later. berkeley_db_read_buffer_size (default: 131072) The per-table I/O buffer size for programs that read Berkeley DB hash or btree tables. Specify a byte count. This feature is available in Postfix 2.0 and later. best_mx_transport (default: empty) Where the Postfix SMTP client should deliver mail when it detects a "mail loops back to myself" error condition. This happens when the local MTA is the best SMTP mail exchanger for a destination not listed in $mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, or $virtual_mailbox_domains. By default, the Postfix SMTP client returns such mail as undeliverable. Specify, for example, "best_mx_transport = local" to pass the mail from the Postfix SMTP client to the local(8) delivery agent. You can specify any message delivery "transport" or "transport:nexthop" that is defined in the master.cf file. See the transport(5) manual page for the syntax and meaning of "transport" or "transport:nexthop". However, this feature is expensive because it ties up a Postfix SMTP client process while the

local(8) delivery agent is doing its work. It is more efficient (for Postfix) to list all hosted domains in a table or database. biff (default: yes) Whether or not to use the local biff service. This service sends "new mail" notifications to users who have requested new mail notification with the UNIX command "biff y". For compatibility reasons this feature is on by default. On systems with lots of interactive users, the biff service can be a performance drain. Specify "biff = no" in main.cf to disable. body_checks (default: empty) Optional lookup tables for content inspection as specified in the body_checks(5) manual page. Note: with Postfix versions before 2.0, these rules inspect all content after the primary message headers. body_checks_size_limit (default: 51200) How much text in a message body segment (or attachment, if you prefer to use that term) is subjected to body_checks inspection. The amount of text is limited to avoid scanning huge attachments. This feature is available in Postfix 2.0 and later. bounce_notice_recipient (default: postmaster) The recipient of postmaster notifications with the message headers of mail that Postfix did not deliver and of SMTP conversation transcripts of mail that Postfix did not receive. This feature is enabled with the notify_classes parameter. bounce_queue_lifetime (default: 5d) The maximal time a bounce message is queued before it is considered undeliverable. By default, this is the same as the queue life time for regular mail. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is d (days). Specify 0 when mail delivery should be tried only once. This feature is available in Postfix 2.1 and later. bounce_service_name (default: bounce) The name of the bounce(8) service. This service maintains a record of failed delivery attempts and generates non-delivery notifications. This feature is available in Postfix 2.0 and later. bounce_size_limit (default: 50000)

The maximal amount of original message text that is sent in a non-delivery notification. Specify a byte count. A message is returned as either message/rfc822 (the complete original) or as text/rfc822-headers (the headers only). With Postfix version 2.4 and earlier, a message is always returned as message/rfc822 and is truncated when it exceeds the size limit. Notes: If you increase this limit, then you should increase the mime_nesting_limit value proportionally. Be careful when making changes. Excessively large values will result in the loss of non-delivery notifications, when a bounce message size exceeds a local or remote MTA's message size limit. bounce_template_file (default: empty) Pathname of a configuration file with bounce message templates. These override the built-in templates of delivery status notification (DSN) messages for undeliverable mail, for delayed mail, successful delivery, or delivery verification. The bounce(5) manual page describes how to edit and test template files. Template message body text may contain $name references to Postfix configuration parameters. The result of $name expansion can be previewed with "postconf -b file_name" before the file is placed into the Postfix configuration directory. This feature is available in Postfix 2.3 and later. broken_sasl_auth_clients (default: no) Enable inter-operability with SMTP clients that implement an obsolete version of the AUTH command (RFC 4954). Examples of such clients are MicroSoft Outlook Express version 4 and MicroSoft Exchange version 5.0. Specify "broken_sasl_auth_clients = yes" to have Postfix advertise AUTH support in a nonstandard way. canonical_classes (default: envelope_sender, envelope_recipient, header_sender, header_recipient) What addresses are subject to canonical_maps address mapping. By default, canonical_maps address mapping is applied to envelope sender and recipient addresses, and to header sender and header recipient addresses. Specify one or more of: envelope_sender, envelope_recipient, header_sender, header_recipient This feature is available in Postfix 2.2 and later. canonical_maps (default: empty) Optional address mapping lookup tables for message headers and envelopes. The mapping is applied to both sender and recipient addresses, in both envelopes and in headers, as controlled

with the canonical_classes parameter. This is typically used to clean up dirty addresses from legacy mail systems, or to replace login names by Firstname.Lastname. The table format and lookups are documented in canonical(5). For an overview of Postfix address manipulations see the ADDRESS_REWRITING_README document. If you use this feature, run "postmap /etc/postfix/canonical" to build the necessary DBM or DB file after every change. The changes will become visible after a minute or so. Use "postfix reload" to eliminate the delay. Note: with Postfix version 2.2, message header address mapping happens only when message header address rewriting is enabled: The message is received with the Postfix sendmail(1) command, The message is received from a network client that matches $local_header_rewrite_clients, The message is received from the network, and the remote_header_rewrite_domain parameter specifies a non-empty value. To get the behavior before Postfix version 2.2, specify "local_header_rewrite_clients = static:all". Examples:
canonical_maps = dbm:/etc/postfix/canonical canonical_maps = hash:/etc/postfix/canonical

cleanup_service_name (default: cleanup) The name of the cleanup(8) service. This service rewrites addresses into the standard form, and performs canonical(5) address mapping and virtual(5) aliasing. This feature is available in Postfix 2.0 and later. command_directory (default: see "postconf -d" output) The location of all postfix administrative commands. command_execution_directory (default: empty) The local(8) delivery agent working directory for delivery to external command. Failure to change directory causes the delivery to be deferred. The following $name expansions are done on command_execution_directory before the directory is changed. Expansion happens in the context of the delivery request. The result of $name expansion is filtered with the character set that is specified with the execution_directory_expansion_filter parameter. $user The recipient's username. $shell The recipient's login shell pathname. $home

The recipient's home directory. $recipient The full recipient address. $extension The optional recipient address extension. $domain The recipient domain. $local The entire recipient localpart. $recipient_delimiter The system-wide recipient address extension delimiter. ${name?value} Expands to value when $name is non-empty. ${name:value} Expands to value when $name is empty. Instead of $name you can also specify ${name} or $(name). This feature is available in Postfix 2.2 and later. command_expansion_filter (default: see "postconf -d" output) Restrict the characters that the local(8) delivery agent allows in $name expansions of $mailbox_command and $command_execution_directory. Characters outside the allowed set are replaced by underscores. command_time_limit (default: 1000s) Time limit for delivery to external commands. This limit is used by the local(8) delivery agent, and is the default time limit for delivery by the pipe(8) delivery agent. Note: if you set this time limit to a large value you must update the global ipc_timeout parameter as well. config_directory (default: see "postconf -d" output) The default location of the Postfix main.cf and master.cf configuration files. This can be overruled via the following mechanisms: The MAIL_CONFIG environment variable (daemon processes and commands). The "-c" command-line option (commands only). With Postfix command that run with set-gid privileges, a config_directory override requires either root privileges, or it requires that the directory is listed with the alternate_config_directories parameter in the default main.cf file. connection_cache_protocol_timeout (default: 5s) Time limit for connection cache connect, send or receive operations. The time limit is enforced in the client.

This feature is available in Postfix 2.3 and later. connection_cache_service_name (default: scache) The name of the scache(8) connection cache service. This service maintains a limited pool of cached sessions. This feature is available in Postfix 2.2 and later. connection_cache_status_update_time (default: 600s) How frequently the scache(8) server logs usage statistics with connection cache hit and miss rates for logical destinations and for physical endpoints. connection_cache_ttl_limit (default: 2s) The maximal time-to-live value that the scache(8) connection cache server allows. Requests that specify a larger TTL will be stored with the maximum allowed TTL. The purpose of this additional control is to protect the infrastructure against careless people. The cache TTL is already bounded by $max_idle. content_filter (default: empty) After the message is queued, send the entire message to the specified transport:destination. The transport name specifies the first field of a mail delivery agent definition in master.cf; the syntax of the next-hop destination is described in the manual page of the corresponding delivery agent. More information about external content filters is in the Postfix FILTER_README file. Notes: This setting has lower precedence than a FILTER action that is specified in an access(5), header_checks(5) or body_checks(5) table. The meaning of an empty next-hop filter destination is version dependent. Postfix 2.7 and later will use the recipient domain; earlier versions will use $myhostname. Specify "default_filter_nexthop = $myhostname" for compatibility with Postfix 2.6 or earlier, or specify a content_filter value with an explicit next-hop destination. cyrus_sasl_config_path (default: empty) Search path for Cyrus SASL application configuration files, currently used only to locate the $smtpd_sasl_path.conf file. Specify zero or more directories separated by a colon character, or an empty value to use Cyrus SASL's built-in search path. This feature is available in Postfix 2.5 and later when compiled with Cyrus SASL 2.1.22 or later. daemon_directory (default: see "postconf -d" output) The directory with Postfix support programs and daemon programs. These should not be invoked directly by humans. The directory must be owned by root.

daemon_timeout (default: 18000s) How much time a Postfix daemon process may take to handle a request before it is terminated by a built-in watchdog timer. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). data_directory (default: see "postconf -d" output) The directory with Postfix-writable data files (for example: caches, pseudo-random numbers). This directory must be owned by the mail_owner account, and must not be shared with nonPostfix software. This feature is available in Postfix 2.5 and later. debug_peer_level (default: 2) The increment in verbose logging level when a remote client or server matches a pattern in the debug_peer_list parameter. debug_peer_list (default: empty) Optional list of remote client or server hostname or network address patterns that cause the verbose logging level to increase by the amount specified in $debug_peer_level. Specify domain names, network/netmask patterns, "/file/name" patterns or "type:table" lookup tables. The right-hand side result from "type:table" lookups is ignored. Pattern matching of domain names is controlled by the parent_domain_matches_subdomains parameter. Examples:
debug_peer_list = 127.0.0.1 debug_peer_list = example.com

debugger_command (default: empty) The external command to execute when a Postfix daemon program is invoked with the -D option. Use "command .. & sleep 5" so that the debugger can attach before the process marches on. If you use an X-based debugger, be sure to set up your XAUTHORITY environment variable before starting Postfix. Example:
debugger_command = PATH=/usr/bin:/usr/X11R6/bin ddd $daemon_directory/$process_name $process_id & sleep 5

default_database_type (default: see "postconf -d" output)

The default database type for use in newaliases(1), postalias(1) and postmap(1) commands. On many UNIX systems the default type is either dbm or hash. The default setting is frozen when the Postfix system is built. Examples:
default_database_type = hash default_database_type = dbm

default_delivery_slot_cost (default: 5) How often the Postfix queue manager's scheduler is allowed to preempt delivery of one message with another. Each transport maintains a so-called "available delivery slot counter" for each message. One message can be preempted by another one when the other message can be delivered using no more delivery slots (i.e., invocations of delivery agents) than the current message counter has accumulated (or will eventually accumulate - see about slot loans below). This parameter controls how often is the counter incremented - it happens after each default_delivery_slot_cost recipients have been delivered. The cost of 0 is used to disable the preempting scheduling completely. The minimum value the scheduling algorithm can use is 2 - use it if you want to maximize the message throughput rate. Although there is no maximum, it doesn't make much sense to use values above say 50. The only reason why the value of 2 is not the default is the way this parameter affects the delivery of mailing-list mail. In the worst case, their delivery can take somewhere between (cost+1/cost) and (cost/cost-1) times more than if the preemptive scheduler was disabled. The default value of 5 turns out to provide reasonable message response times while making sure the mailing-list deliveries are not extended by more than 20-25 percent even in the worst case. Use transport_delivery_slot_cost to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. Examples:
default_delivery_slot_cost = 0 default_delivery_slot_cost = 2

default_delivery_slot_discount (default: 50) The default value for transport-specific _delivery_slot_discount settings. This parameter speeds up the moment when a message preemption can happen. Instead of waiting until the full amount of delivery slots required is available, the preemption can happen when transport_delivery_slot_discount percent of the required amount plus transport_delivery_slot_loan still remains to be accumulated. Note that the full amount will still have to be accumulated before another preemption can take place later. Use transport_delivery_slot_discount to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. default_delivery_slot_loan (default: 3)

The default value for transport-specific _delivery_slot_loan settings. This parameter speeds up the moment when a message preemption can happen. Instead of waiting until the full amount of delivery slots required is available, the preemption can happen when transport_delivery_slot_discount percent of the required amount plus transport_delivery_slot_loan still remains to be accumulated. Note that the full amount will still have to be accumulated before another preemption can take place later. Use transport_delivery_slot_loan to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. default_destination_concurrency_failed_cohort_limit (default: 1) How many pseudo-cohorts must suffer connection or handshake failure before a specific destination is considered unavailable (and further delivery is suspended). Specify zero to disable this feature. A destination's pseudo-cohort failure count is reset each time a delivery completes without connection or handshake failure for that specific destination. A pseudo-cohort is the number of deliveries equal to a destination's delivery concurrency. Use transport_destination_concurrency_failed_cohort_limit to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.5. The default setting is compatible with earlier Postfix versions. default_destination_concurrency_limit (default: 20) The default maximal number of parallel deliveries to the same destination. This is the default limit for delivery via the lmtp(8), pipe(8), smtp(8) and virtual(8) delivery agents. With perdestination recipient limit > 1, a destination is a domain, otherwise it is a recipient. Use transport_destination_concurrency_limit to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. default_destination_concurrency_negative_feedback (default: 1) The per-destination amount of delivery concurrency negative feedback, after a delivery completes with a connection or handshake failure. Feedback values are in the range 0..1 inclusive. With negative feedback, concurrency is decremented at the beginning of a sequence of length 1/feedback. This is unlike positive feedback, where concurrency is incremented at the end of a sequence of length 1/feedback. As of Postfix version 2.5, negative feedback cannot reduce delivery concurrency to zero. Instead, a destination is marked dead (further delivery suspended) after the failed pseudocohort count reaches $default_destination_concurrency_failed_cohort_limit (or $transport_destination_concurrency_failed_cohort_limit). To make the scheduler completely immune to connection or handshake failures, specify a zero feedback value and a zero failed pseudo-cohort limit. Specify one of the following forms:

number number / number Constant feedback. The value must be in the range 0..1 inclusive. The default setting of "1" is compatible with Postfix versions before 2.5, where a destination's delivery concurrency is throttled down to zero (and further delivery suspended) after a single failed pseudo-cohort. number / concurrency Variable feedback of "number / (delivery concurrency)". The number must be in the range 0..1 inclusive. With number equal to "1", a destination's delivery concurrency is decremented by 1 after each failed pseudo-cohort. A pseudo-cohort is the number of deliveries equal to a destination's delivery concurrency. Use transport_destination_concurrency_negative_feedback to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.5. The default setting is compatible with earlier Postfix versions. default_destination_concurrency_positive_feedback (default: 1) The per-destination amount of delivery concurrency positive feedback, after a delivery completes without connection or handshake failure. Feedback values are in the range 0..1 inclusive. The concurrency increases until it reaches the per-destination maximal concurrency limit. With positive feedback, concurrency is incremented at the end of a sequence with length 1/feedback. This is unlike negative feedback, where concurrency is decremented at the start of a sequence of length 1/feedback. Specify one of the following forms: number number / number Constant feedback. The value must be in the range 0..1 inclusive. The default setting of "1" is compatible with Postfix versions before 2.5, where a destination's delivery concurrency doubles after each successful pseudo-cohort. number / concurrency Variable feedback of "number / (delivery concurrency)". The number must be in the range 0..1 inclusive. With number equal to "1", a destination's delivery concurrency is incremented by 1 after each successful pseudo-cohort. A pseudo-cohort is the number of deliveries equal to a destination's delivery concurrency. Use transport_destination_concurrency_positive_feedback to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.5 and later. default_destination_rate_delay (default: 0s) The default amount of delay that is inserted between individual deliveries to the same destination; with per-destination recipient limit > 1, a destination is a domain, otherwise it is a recipient.

To enable the delay, specify a non-zero time value (an integral value plus an optional oneletter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). NOTE: the delay is enforced by the queue manager. The delay timer state does not survive "postfix reload" or "postfix stop". Use transport_destination_rate_delay to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. NOTE: with a non-zero _destination_rate_delay, specify a transport_destination_concurrency_failed_cohort_limit of 10 or more to prevent Postfix from deferring all mail for the same destination after only one connection or handshake error. This feature is available in Postfix 2.5 and later. default_destination_recipient_limit (default: 50) The default maximal number of recipients per message delivery. This is the default limit for delivery via the lmtp(8), pipe(8), smtp(8) and virtual(8) delivery agents. Setting this parameter to a value of 1 changes the meaning of the corresponding perdestination concurrency limit from concurrency per domain into concurrency per recipient. Use transport_destination_recipient_limit to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. default_extra_recipient_limit (default: 1000) The default value for the extra per-transport limit imposed on the number of in-memory recipients. This extra recipient space is reserved for the cases when the Postfix queue manager's scheduler preempts one message with another and suddenly needs some extra recipients slots for the chosen message in order to avoid performance degradation. Use transport_extra_recipient_limit to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. default_filter_nexthop (default: empty) When a content_filter or FILTER request specifies no explicit next-hop destination, use $default_filter_nexthop instead; when that value is empty, use the domain in the recipient address. Specify "default_filter_nexthop = $myhostname" for compatibility with Postfix version 2.6 and earlier, or specify an explicit next-hop destination with each content_filter value or FILTER action. This feature is available in Postfix 2.7 and later. default_minimum_delivery_slots (default: 3) How many recipients a message must have in order to invoke the Postfix queue manager's

scheduling algorithm at all. Messages which would never accumulate at least this many delivery slots (subject to slot cost parameter as well) are never preempted. Use transport_minimum_delivery_slots to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. default_privs (default: nobody) The default rights used by the local(8) delivery agent for delivery to external file or command. These rights are used when delivery is requested from an aliases(5) file that is owned by root, or when delivery is done on behalf of root. DO NOT SPECIFY A PRIVILEGED USER OR THE POSTFIX OWNER. default_process_limit (default: 100) The default maximal number of Postfix child processes that provide a given service. This limit can be overruled for specific services in the master.cf file. default_rbl_reply (default: see "postconf -d" output) The default SMTP server response template for a request that is rejected by an RBL-based restriction. This template can be overruled by specific entries in the optional rbl_reply_maps lookup table. This feature is available in Postfix 2.0 and later. The template is subject to exactly one level of $name substitution: $client The client hostname and IP address, formatted as name[address]. $client_address The client IP address. $client_name The client hostname or "unknown". See reject_unknown_client_hostname for more details. $reverse_client_name The client hostname from address->name lookup, or "unknown". See reject_unknown_reverse_client_hostname for more details. $helo_name The hostname given in HELO or EHLO command or empty string. $rbl_class The blacklisted entity type: Client host, Helo command, Sender address, or Recipient address. $rbl_code The numerical SMTP response code, as specified with the maps_rbl_reject_code configuration parameter. Note: The numerical SMTP response code is required, and must appear at the start of the reply. With Postfix version 2.3 and later this information may be followed by an RFC 3463 enhanced status code. $rbl_domain The RBL domain where $rbl_what is blacklisted. $rbl_reason The reason why $rbl_what is blacklisted, or an empty string.

$rbl_what The entity that is blacklisted (an IP address, a hostname, a domain name, or an email address whose domain was blacklisted). $recipient The recipient address or <> in case of the null address. $recipient_domain The recipient domain or empty string. $recipient_name The recipient address localpart or <> in case of null address. $sender The sender address or <> in case of the null address. $sender_domain The sender domain or empty string. $sender_name The sender address localpart or <> in case of the null address. ${name?text} Expands to `text' if $name is not empty. ${name:text} Expands to `text' if $name is empty. Instead of $name you can also specify ${name} or $(name). Note: when an enhanced status code is specified in an RBL reply template, it is subject to modification. The following transformations are needed when the same RBL reply template is used for client, helo, sender, or recipient access restrictions. When rejecting a sender address, the Postfix SMTP server will transform a recipient DSN status (e.g., 4.1.1-4.1.6) into the corresponding sender DSN status, and vice versa. When rejecting non-address information (such as the HELO command argument or the client hostname/address), the Postfix SMTP server will transform a sender or recipient DSN status into a generic non-address DSN status (e.g., 4.0.0). default_recipient_limit (default: 20000) The default per-transport upper limit on the number of in-memory recipients. These limits take priority over the global qmgr_message_recipient_limit after the message has been assigned to the respective transports. See also default_extra_recipient_limit and qmgr_message_recipient_minimum. Use transport_recipient_limit to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. default_recipient_refill_delay (default: 5s) The default per-transport maximum delay between recipients refills. When not all message recipients fit into the memory at once, keep loading more of them at least once every this many seconds. This is used to make sure the recipients are refilled in timely manner even when $default_recipient_refill_limit is too high for too slow deliveries. Use transport_recipient_refill_delay to specify a transport-specific override, where transport

is the master.cf name of the message delivery transport. This feature is available in Postfix 2.4 and later. default_recipient_refill_limit (default: 100) The default per-transport limit on the number of recipients refilled at once. When not all message recipients fit into the memory at once, keep loading more of them in batches of at least this many at a time. See also $default_recipient_refill_delay, which may result in recipient batches lower than this when this limit is too high for too slow deliveries. Use transport_recipient_refill_limit to specify a transport-specific override, where transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.4 and later. default_transport (default: smtp) The default mail delivery transport and next-hop destination for destinations that do not match $mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains, or $relay_domains. This information can be overruled with the sender_dependent_default_transport_maps parameter and with the transport(5) table. In order of decreasing precedence, the nexthop destination is taken from $sender_dependent_default_transport_maps, $default_transport, $sender_dependent_relayhost_maps, $relayhost, or from the recipient domain. Specify a string of the form transport:nexthop, where transport is the name of a mail delivery transport defined in master.cf. The :nexthop destination is optional; its syntax is documented in the manual page of the corresponding delivery agent. Example:
default_transport = uucp:relayhostname

default_verp_delimiters (default: +=) The two default VERP delimiter characters. These are used when no explicit delimiters are specified with the SMTP XVERP command or with the "sendmail -V" command-line option. Specify characters that are allowed by the verp_delimiter_filter setting. This feature is available in Postfix 1.1 and later. defer_code (default: 450) The numerical Postfix SMTP server response code when a remote SMTP client request is rejected by the "defer" restriction. Do not change this unless you have a complete understanding of RFC 2821. defer_service_name (default: defer)

The name of the defer service. This service is implemented by the bounce(8) daemon and maintains a record of failed delivery attempts and generates non-delivery notifications. This feature is available in Postfix 2.0 and later. defer_transports (default: empty) The names of message delivery transports that should not deliver mail unless someone issues "sendmail -q" or equivalent. Specify zero or more names of mail delivery transports names that appear in the first field of master.cf. Example:
defer_transports = smtp

delay_logging_resolution_limit (default: 2) The maximal number of digits after the decimal point when logging sub-second delay values. Specify a number in the range 0..6. Large delay values are rounded off to an integral number seconds; delay values below the delay_logging_resolution_limit are logged as "0", and small delay values are logged with at most two-digit precision. The format of the "delays=a/b/c/d" logging is as follows: a = time from message arrival to last active queue entry b = time from last active queue entry to connection setup c = time in connection setup, including DNS, EHLO and STARTTLS d = time in message transmission

This feature is available in Postfix 2.3 and later. delay_notice_recipient (default: postmaster) The recipient of postmaster notifications with the message headers of mail that cannot be delivered within $delay_warning_time time units. This feature is enabled with the delay_warning_time parameter. delay_warning_time (default: 0h) The time after which the sender receives the message headers of mail that is still queued. To enable this feature, specify a non-zero time value (an integral value plus an optional oneletter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is h (hours). deliver_lock_attempts (default: 20)

The maximal number of attempts to acquire an exclusive lock on a mailbox file or bounce(8) logfile. deliver_lock_delay (default: 1s) The time between attempts to acquire an exclusive lock on a mailbox file or bounce(8) logfile. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). destination_concurrency_feedback_debug (default: no) Make the queue manager's feedback algorithm verbose for performance analysis purposes. This feature is available in Postfix 2.5 and later. detect_8bit_encoding_header (default: yes) Automatically detect 8BITMIME body content by looking at Content-Transfer-Encoding: message headers; historically, this behavior was hard-coded to be "always on". This feature is available in Postfix 2.5 and later. disable_dns_lookups (default: no) Disable DNS lookups in the Postfix SMTP and LMTP clients. When disabled, hosts are looked up with the getaddrinfo() system library routine which normally also looks in /etc/hosts. DNS lookups are enabled by default. disable_mime_input_processing (default: no) Turn off MIME processing while receiving mail. This means that no special treatment is given to Content-Type: message headers, and that all text after the initial message headers is considered to be part of the message body. This feature is available in Postfix 2.0 and later. Mime input processing is enabled by default, and is needed in order to recognize MIME headers in message content. disable_mime_output_conversion (default: no) Disable the conversion of 8BITMIME format to 7BIT format. Mime output conversion is needed when the destination does not advertise 8BITMIME support. This feature is available in Postfix 2.0 and later. disable_verp_bounces (default: no) Disable sending one bounce report per recipient.

The default, one per recipient, is what ezmlm needs. This feature is available in Postfix 1.1 and later. disable_vrfy_command (default: no) Disable the SMTP VRFY command. This stops some techniques used to harvest email addresses. Example:
disable_vrfy_command = no

dont_remove (default: 0) Don't remove queue files and save them to the "saved" mail queue. This is a debugging aid. To inspect the envelope information and content of a Postfix queue file, use the postcat(1) command. double_bounce_sender (default: double-bounce) The sender address of postmaster notifications that are generated by the mail system. All mail to this address is silently discarded, in order to terminate mail bounce loops. duplicate_filter_limit (default: 1000) The maximal number of addresses remembered by the address duplicate filter for aliases(5) or virtual(5) alias expansion, or for showq(8) queue displays. empty_address_default_transport_maps_lookup_key (default: <>) The sender_dependent_default_transport_maps search string that will be used instead of the null sender address. This feature is available in Postfix 2.7 and later. empty_address_recipient (default: MAILER-DAEMON) The recipient of mail addressed to the null address. Postfix does not accept such addresses in SMTP commands, but they may still be created locally as the result of configuration or software error. empty_address_relayhost_maps_lookup_key (default: <>) The sender_dependent_relayhost_maps search string that will be used instead of the null sender address. This feature is available in Postfix 2.5 and later. With earlier versions, sender_dependent_relayhost_maps lookups were skipped for the null sender address. enable_errors_to (default: no)

Report mail delivery errors to the address specified with the non-standard Errors-To: message header, instead of the envelope sender address (this feature is removed with Postfix version 2.2, is turned off by default with Postfix version 2.1, and is always turned on with older Postfix versions). enable_original_recipient (default: yes) Enable support for the X-Original-To message header. This header is needed for multirecipient mailboxes. When this parameter is set to yes, the cleanup(8) daemon performs duplicate elimination on distinct pairs of (original recipient, rewritten recipient), and generates non-empty original recipient queue file records. When this parameter is set to no, the cleanup(8) daemon performs duplicate elimination on the rewritten recipient address only, and generates empty original recipient queue file records. This feature is available in Postfix 2.1 and later. With Postfix version 2.0, support for the XOriginal-To message header is always turned on. Postfix versions before 2.0 have no support for the X-Original-To message header. error_notice_recipient (default: postmaster) The recipient of postmaster notifications about mail delivery problems that are caused by policy, resource, software or protocol errors. These notifications are enabled with the notify_classes parameter. error_service_name (default: error) The name of the error(8) pseudo delivery agent. This service always returns mail as undeliverable. This feature is available in Postfix 2.0 and later. execution_directory_expansion_filter (default: see "postconf -d" output) Restrict the characters that the local(8) delivery agent allows in $name expansions of $command_execution_directory. Characters outside the allowed set are replaced by underscores. This feature is available in Postfix 2.2 and later. expand_owner_alias (default: no) When delivering to an alias "aliasname" that has an "owner-aliasname" companion alias, set the envelope sender address to the expansion of the "owner-aliasname" alias. Normally, Postfix sets the envelope sender address to the name of the "owner-aliasname" alias. export_environment (default: see "postconf -d" output) The list of environment variables that a Postfix process will export to non-Postfix processes. The TZ variable is needed for sane time keeping on System-V-ish systems.

Specify a list of names and/or name=value pairs, separated by whitespace or comma. The name=value form is supported with Postfix version 2.1 and later. Example:
export_environment = TZ PATH=/bin:/usr/bin

extract_recipient_limit (default: 10240) The maximal number of recipient addresses that Postfix will extract from message headers when mail is submitted with "sendmail -t". This feature was removed in Postfix version 2.1. fallback_relay (default: empty) Optional list of relay hosts for SMTP destinations that can't be found or that are unreachable. With Postfix 2.3 this parameter is renamed to smtp_fallback_relay. By default, mail is returned to the sender when a destination is not found, and delivery is deferred when a destination is unreachable. The fallback relays must be SMTP destinations. Specify a domain, host, host:port, [host]:port, [address] or [address]:port; the form [host] turns off MX lookups. If you specify multiple SMTP destinations, Postfix will try them in the specified order. Note: before Postfix 2.2, do not use the fallback_relay feature when relaying mail for a backup or primary MX domain. Mail would loop between the Postfix MX host and the fallback_relay host when the final destination is unavailable. In main.cf specify "relay_transport = relay", In master.cf specify "-o fallback_relay =" (i.e., empty) at the end of the relay entry. In transport maps, specify "relay:nexthop..." as the right-hand side for backup or primary MX domain entries. Postfix version 2.2 and later will not use the fallback_relay feature for destinations that it is MX host for. fallback_transport (default: empty) Optional message delivery transport that the local(8) delivery agent should use for names that are not found in the aliases(5) or UNIX password database. The precedence of local(8) delivery features from high to low is: aliases, .forward files, mailbox_transport_maps, mailbox_transport, mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_directory, fallback_transport_maps, fallback_transport and luser_relay. fallback_transport_maps (default: empty) Optional lookup tables with per-recipient message delivery transports for recipients that the local(8) delivery agent could not find in the aliases(5) or UNIX password database.

The precedence of local(8) delivery features from high to low is: aliases, .forward files, mailbox_transport_maps, mailbox_transport, mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_directory, fallback_transport_maps, fallback_transport and luser_relay. For safety reasons, this feature does not allow $number substitutions in regular expression maps. This feature is available in Postfix 2.3 and later. fast_flush_domains (default: $relay_domains) Optional list of destinations that are eligible for per-destination logfiles with mail that is queued to those destinations. By default, Postfix maintains "fast flush" logfiles only for destinations that the Postfix SMTP server is willing to relay to (i.e. the default is: "fast_flush_domains = $relay_domains"; see the relay_domains parameter in the postconf(5) manual). Specify a list of hosts or domains, "/file/name" patterns or "type:table" lookup tables, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when the domain or its parent domain appears as lookup key. Specify "fast_flush_domains =" (i.e., empty) to disable the feature altogether. fast_flush_purge_time (default: 7d) The time after which an empty per-destination "fast flush" logfile is deleted. You can specify the time as a number, or as a number followed by a letter that indicates the time unit: s=seconds, m=minutes, h=hours, d=days, w=weeks. The default time unit is days. fast_flush_refresh_time (default: 12h) The time after which a non-empty but unread per-destination "fast flush" logfile needs to be refreshed. The contents of a logfile are refreshed by requesting delivery of all messages listed in the logfile. You can specify the time as a number, or as a number followed by a letter that indicates the time unit: s=seconds, m=minutes, h=hours, d=days, w=weeks. The default time unit is hours. fault_injection_code (default: 0) Force specific internal tests to fail, to test the handling of errors that are difficult to reproduce otherwise. flush_service_name (default: flush) The name of the flush(8) service. This service maintains per-destination logfiles with the queue file names of mail that is queued for those destinations.

This feature is available in Postfix 2.0 and later. fork_attempts (default: 5) The maximal number of attempts to fork() a child process. fork_delay (default: 1s) The delay between attempts to fork() a child process. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). forward_expansion_filter (default: see "postconf -d" output) Restrict the characters that the local(8) delivery agent allows in $name expansions of $forward_path. Characters outside the allowed set are replaced by underscores. forward_path (default: see "postconf -d" output) The local(8) delivery agent search list for finding a .forward file with user-specified delivery methods. The first file that is found is used. The following $name expansions are done on forward_path before the search actually happens. The result of $name expansion is filtered with the character set that is specified with the forward_expansion_filter parameter. $user The recipient's username. $shell The recipient's login shell pathname. $home The recipient's home directory. $recipient The full recipient address. $extension The optional recipient address extension. $domain The recipient domain. $local The entire recipient localpart. $recipient_delimiter The system-wide recipient address extension delimiter. ${name?value} Expands to value when $name is non-empty. ${name:value} Expands to value when $name is empty. Instead of $name you can also specify ${name} or $(name). Examples:

forward_path = /var/forward/$user forward_path = /var/forward/$user/.forward$recipient_delimiter$extension, /var/forward/$user/.forward

frozen_delivered_to (default: yes) Update the local(8) delivery agent's idea of the Delivered-To: address (see prepend_delivered_header) only once, at the start of a delivery attempt; do not update the Delivered-To: address while expanding aliases or .forward files. This feature is available in Postfix 2.3 and later. With older Postfix releases, the behavior is as if this parameter is set to "no". The old setting can be expensive with deeply nested aliases or .forward files. When an alias or .forward file changes the Delivered-To: address, it ties up one queue file and one cleanup process instance while mail is being forwarded. hash_queue_depth (default: 1) The number of subdirectory levels for queue directories listed with the hash_queue_names parameter. After changing the hash_queue_names or hash_queue_depth parameter, execute the command "postfix reload". hash_queue_names (default: deferred, defer) The names of queue directories that are split across multiple subdirectory levels. Before Postfix version 2.2, the default list of hashed queues was significantly larger. Claims about improvements in file system technology suggest that hashing of the incoming and active queues is no longer needed. Fewer hashed directories speed up the time needed to restart Postfix. After changing the hash_queue_names or hash_queue_depth parameter, execute the command "postfix reload". header_address_token_limit (default: 10240) The maximal number of address tokens are allowed in an address message header. Information that exceeds the limit is discarded. The limit is enforced by the cleanup(8) server. header_checks (default: empty) Optional lookup tables for content inspection of primary non-MIME message headers, as specified in the header_checks(5) manual page. header_size_limit (default: 102400) The maximal amount of memory in bytes for storing a message header. If a header is larger, the excess is discarded. The limit is enforced by the cleanup(8) server. helpful_warnings (default: yes)

Log warnings about problematic configuration settings, and provide helpful suggestions. This feature is available in Postfix 2.0 and later. home_mailbox (default: empty) Optional pathname of a mailbox file relative to a local(8) user's home directory. Specify a pathname ending in "/" for qmail-style delivery. The precedence of local(8) delivery features from high to low is: aliases, .forward files, mailbox_transport_maps, mailbox_transport, mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_directory, fallback_transport_maps, fallback_transport and luser_relay. Examples:
home_mailbox = Mailbox home_mailbox = Maildir/

hopcount_limit (default: 50) The maximal number of Received: message headers that is allowed in the primary message headers. A message that exceeds the limit is bounced, in order to stop a mailer loop. html_directory (default: see "postconf -d" output) The location of Postfix HTML files that describe how to build, configure or operate a specific Postfix subsystem or feature. ignore_mx_lookup_error (default: no) Ignore DNS MX lookups that produce no response. By default, the Postfix SMTP client defers delivery and tries again after some delay. This behavior is required by the SMTP standard. Specify "ignore_mx_lookup_error = yes" to force a DNS A record lookup instead. This violates the SMTP standard and can result in mis-delivery of mail. import_environment (default: see "postconf -d" output) The list of environment parameters that a Postfix process will import from a non-Postfix parent process. Examples of relevant parameters: TZ Needed for sane time keeping on most System-V-ish systems. DISPLAY Needed for debugging Postfix daemons with an X-windows debugger. XAUTHORITY Needed for debugging Postfix daemons with an X-windows debugger. MAIL_CONFIG Needed to make "postfix -c" work.

Specify a list of names and/or name=value pairs, separated by whitespace or comma. The name=value form is supported with Postfix version 2.1 and later. in_flow_delay (default: 1s) Time to pause before accepting a new message, when the message arrival rate exceeds the message delivery rate. This feature is turned on by default (it's disabled on SCO UNIX due to an SCO bug). With the default 100 SMTP server process limit, "in_flow_delay = 1s" limits the mail inflow to 100 messages per second above the number of messages delivered per second. Specify 0 to disable the feature. Valid delays are 0..10. inet_interfaces (default: all) The network interface addresses that this mail system receives mail on. Specify "all" to receive mail on all network interfaces (default), and "loopback-only" to receive mail on loopback network interfaces only (Postfix version 2.2 and later). The parameter also controls delivery of mail to user@[ip.address]. Note 1: you need to stop and start Postfix when this parameter changes. Note 2: address information may be enclosed inside [], but this form is not required here. When inet_interfaces specifies just one IPv4 and/or IPv6 address that is not a loopback address, the Postfix SMTP client will use this address as the IP source address for outbound mail. Support for IPv6 is available in Postfix version 2.2 and later. On a multi-homed firewall with separate Postfix instances listening on the "inside" and "outside" interfaces, this can prevent each instance from being able to reach servers on the "other side" of the firewall. Setting smtp_bind_address to 0.0.0.0 avoids the potential problem for IPv4, and setting smtp_bind_address6 to :: solves the problem for IPv6. A better solution for multi-homed firewalls is to leave inet_interfaces at the default value and instead use explicit IP addresses in the master.cf SMTP server definitions. This preserves the Postfix SMTP client's loop detection, by ensuring that each side of the firewall knows that the other IP address is still the same host. Setting $inet_interfaces to a single IPv4 and/or IPV6 address is primarily useful with virtual hosting of domains on secondary IP addresses, when each IP address serves a different domain (and has a different $myhostname setting). See also the proxy_interfaces parameter, for network addresses that are forwarded to Postfix by way of a proxy or address translator. Examples:
inet_interfaces inet_interfaces inet_interfaces inet_interfaces inet_interfaces = = = = = all (DEFAULT) loopback-only (Postfix version 2.2 and later) 127.0.0.1 127.0.0.1, [::1] (Postfix version 2.2 and later) 192.168.1.2, 127.0.0.1

inet_protocols (default: ipv4)

The Internet protocols Postfix will attempt to use when making or accepting connections. Specify one or more of "ipv4" or "ipv6", separated by whitespace or commas. The form "all" is equivalent to "ipv4, ipv6" or "ipv4", depending on whether the operating system implements IPv6. This feature is available in Postfix 2.2 and later. Note: you MUST stop and start Postfix after changing this parameter. On systems that pre-date IPV6_V6ONLY support (RFC 3493), an IPv6 server will also accept IPv4 connections, even when IPv4 is turned off with the inet_protocols parameter. On systems with IPV6_V6ONLY support, Postfix will use separate server sockets for IPv6 and IPv4, and each will accept only connections for the corresponding protocol. When IPv4 support is enabled via the inet_protocols parameter, Postfix will to DNS type A record lookups, and will convert IPv4-in-IPv6 client IP addresses (::ffff:1.2.3.4) to their original IPv4 form (1.2.3.4). The latter is needed on hosts that pre-date IPV6_V6ONLY support (RFC 3493). When IPv6 support is enabled via the inet_protocols parameter, Postfix will do DNS type AAAA record lookups. When both IPv4 and IPv6 support are enabled, the Postfix SMTP client will attempt to connect via IPv6 before attempting to use IPv4. Examples:
inet_protocols inet_protocols inet_protocols inet_protocols = = = = ipv4 (DEFAULT) all ipv6 ipv4, ipv6

initial_destination_concurrency (default: 5) The initial per-destination concurrency level for parallel delivery to the same destination. With per-destination recipient limit > 1, a destination is a domain, otherwise it is a recipient. Use transport_initial_destination_concurrency to specify a transport-specific override, where transport is the master.cf name of the message delivery transport (Postfix 2.5 and later). Warning: with concurrency of 1, one bad message can be enough to block all mail to a site. internal_mail_filter_classes (default: empty) What categories of Postfix-generated mail are subject to before-queue content inspection by non_smtpd_milters, header_checks and body_checks. Specify zero or more of the following, separated by whitespace or comma. bounce Inspect the content of delivery status notifications. notify Inspect the content of postmaster notifications by the smtp(8) and smtpd(8) processes.

NOTE: It's generally not safe to enable content inspection of Postfix-generated email messages. The user is warned. This feature is available in Postfix 2.3 and later. invalid_hostname_reject_code (default: 501) The numerical Postfix SMTP server response code when the client HELO or EHLO command parameter is rejected by the reject_invalid_helo_hostname restriction. Do not change this unless you have a complete understanding of RFC 2821. ipc_idle (default: version dependent) The time after which a client closes an idle internal communication channel. The purpose is to allow servers to terminate voluntarily after they become idle. This is used, for example, by the address resolving and rewriting clients. With Postfix 2.4 the default value was reduced from 100s to 5s. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). ipc_timeout (default: 3600s) The time limit for sending or receiving information over an internal communication channel. The purpose is to break out of deadlock situations. If the time limit is exceeded the software aborts with a fatal error. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). ipc_ttl (default: 1000s) The time after which a client closes an active internal communication channel. The purpose is to allow servers to terminate voluntarily after reaching their client limit. This is used, for example, by the address resolving and rewriting clients. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). This feature is available in Postfix 2.1 and later. line_length_limit (default: 2048) Upon input, long lines are chopped up into pieces of at most this length; upon delivery, long lines are reconstructed. lmtp_address_preference (default: ipv6) The LMTP-specific version of the smtp_address_preference configuration parameter. See there for details.

This feature is available in Postfix 2.8 and later. lmtp_assume_final (default: no) When an LMTP server announces no DSN support, assume that the server performs final delivery, and send "delivered" delivery status notifications instead of "relayed". The default setting is backwards compatible to avoid the infinetisimal possibility of breaking existing LMTP-based content filters. lmtp_bind_address (default: empty) The LMTP-specific version of the smtp_bind_address configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_bind_address6 (default: empty) The LMTP-specific version of the smtp_bind_address6 configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_body_checks (default: empty) The LMTP-specific version of the smtp_body_checks configuration parameter. See there for details. This feature is available in Postfix 2.5 and later. lmtp_cache_connection (default: yes) Keep Postfix LMTP client connections open for up to $max_idle seconds. When the LMTP client receives a request for the same connection the connection is reused. This parameter is available in Postfix version 2.2 and earlier. With Postfix version 2.3 and later, see lmtp_connection_cache_on_demand, lmtp_connection_cache_destinations, or lmtp_connection_reuse_time_limit. The effectiveness of cached connections will be determined by the number of LMTP servers in use, and the concurrency limit specified for the LMTP client. Cached connections are closed under any of the following conditions: The LMTP client idle time limit is reached. This limit is specified with the Postfix max_idle configuration parameter. A delivery request specifies a different destination than the one currently cached. The per-process limit on the number of delivery requests is reached. This limit is specified with the Postfix max_use configuration parameter. Upon the onset of another delivery request, the LMTP server associated with the current session does not respond to the RSET command. Most of these limitations will be removed after Postfix implements a connection cache that is

shared among multiple LMTP client programs. lmtp_cname_overrides_servername (default: yes) The LMTP-specific version of the smtp_cname_overrides_servername configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_connect_timeout (default: 0s) The LMTP client time limit for completing a TCP connection, or zero (use the operating system built-in time limit). When no connection can be made within the deadline, the LMTP client tries the next address on the mail exchanger list. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). Example:
lmtp_connect_timeout = 30s

lmtp_connection_cache_destinations (default: empty) The LMTP-specific version of the smtp_connection_cache_destinations configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_connection_cache_on_demand (default: yes) The LMTP-specific version of the smtp_connection_cache_on_demand configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_connection_cache_time_limit (default: 2s) The LMTP-specific version of the smtp_connection_cache_time_limit configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_connection_reuse_time_limit (default: 300s) The LMTP-specific version of the smtp_connection_reuse_time_limit configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_data_done_timeout (default: 600s)

The LMTP client time limit for sending the LMTP ".", and for receiving the server response. When no response is received within the deadline, a warning is logged that the mail may be delivered multiple times. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). lmtp_data_init_timeout (default: 120s) The LMTP client time limit for sending the LMTP DATA command, and for receiving the server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). lmtp_data_xfer_timeout (default: 180s) The LMTP client time limit for sending the LMTP message content. When the connection stalls for more than $lmtp_data_xfer_timeout the LMTP client terminates the transfer. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). lmtp_defer_if_no_mx_address_found (default: no) The LMTP-specific version of the smtp_defer_if_no_mx_address_found configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_destination_concurrency_limit (default: $default_destination_concurrency_limit) The maximal number of parallel deliveries to the same destination via the lmtp message delivery transport. This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. lmtp_destination_recipient_limit (default: $default_destination_recipient_limit) The maximal number of recipients per message for the lmtp message delivery transport. This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. Setting this parameter to a value of 1 changes the meaning of lmtp_destination_concurrency_limit from concurrency per domain into concurrency per recipient. lmtp_discard_lhlo_keyword_address_maps (default: empty) Lookup tables, indexed by the remote LMTP server address, with case insensitive lists of LHLO keywords (pipelining, starttls, auth, etc.) that the LMTP client will ignore in the LHLO response from a remote LMTP server. See lmtp_discard_lhlo_keywords for details. The table is not indexed by hostname for consistency with

smtpd_discard_ehlo_keyword_address_maps. This feature is available in Postfix 2.3 and later. lmtp_discard_lhlo_keywords (default: empty) A case insensitive list of LHLO keywords (pipelining, starttls, auth, etc.) that the LMTP client will ignore in the LHLO response from a remote LMTP server. This feature is available in Postfix 2.3 and later. Notes: Specify the silent-discard pseudo keyword to prevent this action from being logged. Use the lmtp_discard_lhlo_keyword_address_maps feature to discard LHLO keywords selectively. lmtp_enforce_tls (default: no) The LMTP-specific version of the smtp_enforce_tls configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_generic_maps (default: empty) The LMTP-specific version of the smtp_generic_maps configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_header_checks (default: empty) The LMTP-specific version of the smtp_header_checks configuration parameter. See there for details. This feature is available in Postfix 2.5 and later. lmtp_host_lookup (default: dns) The LMTP-specific version of the smtp_host_lookup configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_lhlo_name (default: $myhostname) The hostname to send in the LMTP LHLO command. The default value is the machine hostname. Specify a hostname or [ip.add.re.ss].

This information can be specified in the main.cf file for all LMTP clients, or it can be specified in the master.cf file for a specific client, for example:
/etc/postfix/master.cf: mylmtp ... lmtp -o lmtp_lhlo_name=foo.bar.com

This feature is available in Postfix 2.3 and later. lmtp_lhlo_timeout (default: 300s) The LMTP client time limit for sending the LHLO command, and for receiving the initial server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). lmtp_line_length_limit (default: 990) The LMTP-specific version of the smtp_line_length_limit configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_mail_timeout (default: 300s) The LMTP client time limit for sending the MAIL FROM command, and for receiving the server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). lmtp_mime_header_checks (default: empty) The LMTP-specific version of the smtp_mime_header_checks configuration parameter. See there for details. This feature is available in Postfix 2.5 and later. lmtp_mx_address_limit (default: 5) The LMTP-specific version of the smtp_mx_address_limit configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_mx_session_limit (default: 2) The LMTP-specific version of the smtp_mx_session_limit configuration parameter. See there for details. This feature is available in Postfix 2.3 and later.

lmtp_nested_header_checks (default: empty) The LMTP-specific version of the smtp_nested_header_checks configuration parameter. See there for details. This feature is available in Postfix 2.5 and later. lmtp_pix_workaround_delay_time (default: 10s) The LMTP-specific version of the smtp_pix_workaround_delay_time configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_pix_workaround_maps (default: empty) The LMTP-specific version of the smtp_pix_workaround_maps configuration parameter. See there for details. This feature is available in Postfix 2.4 and later. lmtp_pix_workaround_threshold_time (default: 500s) The LMTP-specific version of the smtp_pix_workaround_threshold_time configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_pix_workarounds (default: empty) The LMTP-specific version of the smtp_pix_workaround configuration parameter. See there for details. This feature is available in Postfix 2.4 and later. lmtp_quit_timeout (default: 300s) The LMTP client time limit for sending the QUIT command, and for receiving the server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). lmtp_quote_rfc821_envelope (default: yes) The LMTP-specific version of the smtp_quote_rfc821_envelope configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_randomize_addresses (default: yes)

The LMTP-specific version of the smtp_randomize_addresses configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_rcpt_timeout (default: 300s) The LMTP client time limit for sending the RCPT TO command, and for receiving the server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). lmtp_reply_filter (default: empty) The LMTP-specific version of the smtp_reply_filter configuration parameter. See there for details. This feature is available in Postfix 2.7 and later. lmtp_rset_timeout (default: 20s) The LMTP client time limit for sending the RSET command, and for receiving the server response. The LMTP client sends RSET in order to finish a recipient address probe, or to verify that a cached connection is still alive. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). lmtp_sasl_auth_cache_name (default: empty) The LMTP-specific version of the smtp_sasl_auth_cache_name configuration parameter. See there for details. This feature is available in Postfix 2.5 and later. lmtp_sasl_auth_cache_time (default: 90d) The LMTP-specific version of the smtp_sasl_auth_cache_time configuration parameter. See there for details. This feature is available in Postfix 2.5 and later. lmtp_sasl_auth_enable (default: no) Enable SASL authentication in the Postfix LMTP client. lmtp_sasl_auth_soft_bounce (default: yes) The LMTP-specific version of the smtp_sasl_auth_soft_bounce configuration parameter. See there for details.

This feature is available in Postfix 2.5 and later. lmtp_sasl_mechanism_filter (default: empty) The LMTP-specific version of the smtp_sasl_mechanism_filter configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_sasl_password_maps (default: empty) Optional LMTP client lookup tables with one username:password entry per host or domain. If a remote host or domain has no username:password entry, then the Postfix LMTP client will not attempt to authenticate to the remote host. lmtp_sasl_path (default: empty) Implementation-specific information that is passed through to the SASL plug-in implementation that is selected with lmtp_sasl_type. Typically this specifies the name of a configuration file or rendezvous point. This feature is available in Postfix 2.3 and later. lmtp_sasl_security_options (default: noplaintext, noanonymous) SASL security options; as of Postfix 2.3 the list of available features depends on the SASL client implementation that is selected with lmtp_sasl_type. The following security features are defined for the cyrus client SASL implementation: noplaintext Disallow authentication methods that use plaintext passwords. noactive Disallow authentication methods that are vulnerable to non-dictionary active attacks. nodictionary Disallow authentication methods that are vulnerable to passive dictionary attack. noanonymous Disallow anonymous logins. Example:
lmtp_sasl_security_options = noplaintext

lmtp_sasl_tls_security_options (default: $lmtp_sasl_security_options) The LMTP-specific version of the smtp_sasl_tls_security_options configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_sasl_tls_verified_security_options (default: $lmtp_sasl_tls_security_options)

The LMTP-specific version of the smtp_sasl_tls_verified_security_options configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_sasl_type (default: cyrus) The SASL plug-in type that the Postfix LMTP client should use for authentication. The available types are listed with the "postconf -A" command. This feature is available in Postfix 2.3 and later. lmtp_send_xforward_command (default: no) Send an XFORWARD command to the LMTP server when the LMTP LHLO server response announces XFORWARD support. This allows an lmtp(8) delivery agent, used for content filter message injection, to forward the name, address, protocol and HELO name of the original client to the content filter and downstream queuing LMTP server. Before you change the value to yes, it is best to make sure that your content filter supports this command. This feature is available in Postfix 2.1 and later. lmtp_sender_dependent_authentication (default: no) The LMTP-specific version of the smtp_sender_dependent_authentication configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_skip_5xx_greeting (default: yes) The LMTP-specific version of the smtp_skip_5xx_greeting configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_skip_quit_response (default: no) Wait for the response to the LMTP QUIT command. lmtp_starttls_timeout (default: 300s) The LMTP-specific version of the smtp_starttls_timeout configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tcp_port (default: 24) The default TCP port that the Postfix LMTP client connects to. lmtp_tls_CAfile (default: empty)

The LMTP-specific version of the smtp_tls_CAfile configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_CApath (default: empty) The LMTP-specific version of the smtp_tls_CApath configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_block_early_mail_reply (default: empty) The LMTP-specific version of the smtp_tls_block_early_mail_reply configuration parameter. See there for details. This feature is available in Postfix 2.7 and later. lmtp_tls_cert_file (default: empty) The LMTP-specific version of the smtp_tls_cert_file configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_ciphers (default: export) The LMTP-specific version of the smtp_tls_ciphers configuration parameter. See there for details. This feature is available in Postfix 2.6 and later. lmtp_tls_dcert_file (default: empty) The LMTP-specific version of the smtp_tls_dcert_file configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_dkey_file (default: $lmtp_tls_dcert_file) The LMTP-specific version of the smtp_tls_dkey_file configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_eccert_file (default: empty) The LMTP-specific version of the smtp_tls_eccert_file configuration parameter. See there for details.

This feature is available in Postfix 2.6 and later, when Postfix is compiled and linked with OpenSSL 1.0.0 or later. lmtp_tls_eckey_file (default: empty) The LMTP-specific version of the smtp_tls_eckey_file configuration parameter. See there for details. This feature is available in Postfix 2.6 and later, when Postfix is compiled and linked with OpenSSL 1.0.0 or later. lmtp_tls_enforce_peername (default: yes) The LMTP-specific version of the smtp_tls_enforce_peername configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_exclude_ciphers (default: empty) The LMTP-specific version of the smtp_tls_exclude_ciphers configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_fingerprint_cert_match (default: empty) The LMTP-specific version of the smtp_tls_fingerprint_cert_match configuration parameter. See there for details. This feature is available in Postfix 2.5 and later. lmtp_tls_fingerprint_digest (default: md5) The LMTP-specific version of the smtp_tls_fingerprint_digest configuration parameter. See there for details. This feature is available in Postfix 2.5 and later. lmtp_tls_key_file (default: $lmtp_tls_cert_file) The LMTP-specific version of the smtp_tls_key_file configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_loglevel (default: 0) The LMTP-specific version of the smtp_tls_loglevel configuration parameter. See there for details. This feature is available in Postfix 2.3 and later.

lmtp_tls_mandatory_ciphers (default: empty) The LMTP-specific version of the smtp_tls_mandatory_ciphers configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_mandatory_exclude_ciphers (default: empty) The LMTP-specific version of the smtp_tls_mandatory_exclude_ciphers configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_mandatory_protocols (default: SSLv3, TLSv1) The LMTP-specific version of the smtp_tls_mandatory_protocols configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_note_starttls_offer (default: no) The LMTP-specific version of the smtp_tls_note_starttls_offer configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_per_site (default: empty) The LMTP-specific version of the smtp_tls_per_site configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_policy_maps (default: empty) The LMTP-specific version of the smtp_tls_policy_maps configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_protocols (default: empty) The LMTP-specific version of the smtp_tls_protocols configuration parameter. See there for details. This feature is available in Postfix 2.6 and later. lmtp_tls_scert_verifydepth (default: 9) The LMTP-specific version of the smtp_tls_scert_verifydepth configuration parameter. See

there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_secure_cert_match (default: nexthop) The LMTP-specific version of the smtp_tls_secure_cert_match configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_security_level (default: empty) The LMTP-specific version of the smtp_tls_security_level configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_session_cache_database (default: empty) The LMTP-specific version of the smtp_tls_session_cache_database configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_session_cache_timeout (default: 3600s) The LMTP-specific version of the smtp_tls_session_cache_timeout configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_tls_verify_cert_match (default: hostname) The LMTP-specific version of the smtp_tls_verify_cert_match configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_use_tls (default: no) The LMTP-specific version of the smtp_use_tls configuration parameter. See there for details. This feature is available in Postfix 2.3 and later. lmtp_xforward_timeout (default: 300s) The LMTP client time limit for sending the XFORWARD command, and for receiving the server response. In case of problems the client does NOT try the next address on the mail exchanger list.

Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). This feature is available in Postfix 2.1 and later. local_command_shell (default: empty) Optional shell program for local(8) delivery to non-Postfix command. By default, non-Postfix commands are executed directly; commands are given to given to the default shell (typically, /bin/sh) only when they contain shell meta characters or shell built-in commands. "sendmail's restricted shell" (smrsh) is what most people will use in order to restrict what programs can be run from e.g. .forward files (smrsh is part of the Sendmail distribution). Note: when a shell program is specified, it is invoked even when the command contains no shell built-in commands or meta characters. Example:
local_command_shell = /some/where/smrsh -c local_command_shell = /bin/bash -c

local_destination_concurrency_limit (default: 2) The maximal number of parallel deliveries via the local mail delivery transport to the same recipient (when "local_destination_recipient_limit = 1") or the maximal number of parallel deliveries to the same local domain (when "local_destination_recipient_limit > 1"). This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. A low limit of 2 is recommended, just in case someone has an expensive shell command in a .forward file or in an alias (e.g., a mailing list manager). You don't want to run lots of those at the same time. local_destination_recipient_limit (default: 1) The maximal number of recipients per message delivery via the local mail delivery transport. This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. Setting this parameter to a value > 1 changes the meaning of local_destination_concurrency_limit from concurrency per recipient into concurrency per domain. local_header_rewrite_clients (default: permit_inet_interfaces) Rewrite message header addresses in mail from these clients and update incomplete addresses with the domain name in $myorigin or $mydomain; either don't rewrite message headers from other clients at all, or rewrite message headers and update incomplete addresses with the domain specified in the remote_header_rewrite_domain parameter. See the append_at_myorigin and append_dot_mydomain parameters for details of how

domain names are appended to incomplete addresses. Specify a list of zero or more of the following: permit_inet_interfaces Append the domain name in $myorigin or $mydomain when the client IP address matches $inet_interfaces. This is enabled by default. permit_mynetworks Append the domain name in $myorigin or $mydomain when the client IP address matches any network or network address listed in $mynetworks. This setting will not prevent remote mail header address rewriting when mail from a remote client is forwarded by a neighboring system. permit_sasl_authenticated Append the domain name in $myorigin or $mydomain when the client is successfully authenticated via the RFC 4954 (AUTH) protocol. permit_tls_clientcerts Append the domain name in $myorigin or $mydomain when the client TLS certificate fingerprint is listed in $relay_clientcerts. The fingerprint digest algorithm is configurable via the smtpd_tls_fingerprint_digest parameter (hard-coded as md5 prior to Postfix version 2.5). permit_tls_all_clientcerts Append the domain name in $myorigin or $mydomain when the client TLS certificate is successfully verified, regardless of whether it is listed on the server, and regardless of the certifying authority. check_address_map type:table type:table Append the domain name in $myorigin or $mydomain when the client IP address matches the specified lookup table. The lookup result is ignored, and no subnet lookup is done. This is suitable for, e.g., pop-before-smtp lookup tables. Examples: The Postfix < 2.2 backwards compatible setting: always rewrite message headers, and always append my own domain to incomplete header addresses.
local_header_rewrite_clients = static:all

The purist (and default) setting: rewrite headers only in mail from Postfix sendmail and in SMTP mail from this machine.
local_header_rewrite_clients = permit_inet_interfaces

The intermediate setting: rewrite header addresses and append $myorigin or $mydomain information only with mail from Postfix sendmail, from local clients, or from authorized SMTP clients. Note: this setting will not prevent remote mail header address rewriting when mail from a remote client is forwarded by a neighboring system.
local_header_rewrite_clients = permit_mynetworks, permit_sasl_authenticated permit_tls_clientcerts check_address_map hash:/etc/postfix/pop-before-smtp

local_recipient_maps (default: proxy:unix:passwd.byname $alias_maps) Lookup tables with all names or addresses of local recipients: a recipient address is local when its domain matches $mydestination, $inet_interfaces or $proxy_interfaces. Specify @domain as a wild-card for domains that do not have a valid recipient list. Technically, tables listed with $local_recipient_maps are used as lists: Postfix needs to know only if a lookup string is found or not, but it does not use the result from table lookup. If this parameter is non-empty (the default), then the Postfix SMTP server will reject mail for unknown local users. To turn off local recipient checking in the Postfix SMTP server, specify "local_recipient_maps =" (i.e. empty). The default setting assumes that you use the default Postfix local delivery agent for local delivery. You need to update the local_recipient_maps setting if: You redefine the local delivery agent in master.cf. You redefine the "local_transport" setting in main.cf. You use the "luser_relay", "mailbox_transport", or "fallback_transport" feature of the Postfix local(8) delivery agent. Details are described in the LOCAL_RECIPIENT_README file. Beware: if the Postfix SMTP server runs chrooted, you need to access the passwd file via the proxymap(8) service, in order to overcome chroot access restrictions. The alternative, maintaining a copy of the system password file in the chroot jail is not practical. Examples:
local_recipient_maps =

local_transport (default: local:$myhostname) The default mail delivery transport and next-hop destination for final delivery to domains listed with mydestination, and for [ipaddress] destinations that match $inet_interfaces or $proxy_interfaces. This information can be overruled with the transport(5) table. By default, local mail is delivered to the transport called "local", which is just the name of a service that is defined the master.cf file. Specify a string of the form transport:nexthop, where transport is the name of a mail delivery transport defined in master.cf. The :nexthop destination is optional; its syntax is documented in the manual page of the corresponding delivery agent. Beware: if you override the default local delivery agent then you need to review the LOCAL_RECIPIENT_README document, otherwise the SMTP server may reject mail for local recipients. luser_relay (default: empty) Optional catch-all destination for unknown local(8) recipients. By default, mail for unknown

recipients in domains that match $mydestination, $inet_interfaces or $proxy_interfaces is returned as undeliverable. The following $name expansions are done on luser_relay: $domain The recipient domain. $extension The recipient address extension. $home The recipient's home directory. $local The entire recipient address localpart. $recipient The full recipient address. $recipient_delimiter The system-wide recipient address extension delimiter. $shell The recipient's login shell. $user The recipient username. ${name?value} Expands to value when $name has a non-empty value. ${name:value} Expands to value when $name has an empty value. Instead of $name you can also specify ${name} or $(name). Note: luser_relay works only for the Postfix local(8) delivery agent. Note: if you use this feature for accounts not in the UNIX password file, then you must specify "local_recipient_maps =" (i.e. empty) in the main.cf file, otherwise the Postfix SMTP server will reject mail for non-UNIX accounts with "User unknown in local recipient table". Examples:
luser_relay = $user@other.host luser_relay = $local@other.host luser_relay = admin+$local

mail_name (default: Postfix) The mail system name that is displayed in Received: headers, in the SMTP greeting banner, and in bounced mail. mail_owner (default: postfix) The UNIX system account that owns the Postfix queue and most Postfix daemon processes. Specify the name of a user account that does not share a group with other accounts and that owns no other files or processes on the system. In particular, don't specify nobody or daemon. PLEASE USE A DEDICATED USER ID AND GROUP ID.

When this parameter value is changed you need to re-run "postfix set-permissions" (with Postfix version 2.0 and earlier: "/etc/postfix/post-install set-permissions". mail_release_date (default: see "postconf -d" output) The Postfix release date, in "YYYYMMDD" format. mail_spool_directory (default: see "postconf -d" output) The directory where local(8) UNIX-style mailboxes are kept. The default setting depends on the system type. Specify a name ending in / for maildir-style delivery. Note: maildir delivery is done with the privileges of the recipient. If you use the mail_spool_directory setting for maildir style delivery, then you must create the top-level maildir directory in advance. Postfix will not create it. Examples:
mail_spool_directory = /var/mail mail_spool_directory = /var/spool/mail

mail_version (default: see "postconf -d" output) The version of the mail system. Stable releases are named major.minor.patchlevel. Experimental releases also include the release date. The version string can be used in, for example, the SMTP greeting banner. mailbox_command (default: empty) Optional external command that the local(8) delivery agent should use for mailbox delivery. The command is run with the user ID and the primary group ID privileges of the recipient. Exception: command delivery for root executes with $default_privs privileges. This is not a problem, because 1) mail for root should always be aliased to a real user and 2) don't log in as root, use "su" instead. The following environment variables are exported to the command: CLIENT_ADDRESS Remote client network address. Available in Postfix version 2.2 and later. CLIENT_HELO Remote client EHLO command parameter. Available in Postfix version 2.2 and later. CLIENT_HOSTNAME Remote client hostname. Available in Postfix version 2.2 and later. CLIENT_PROTOCOL Remote client protocol. Available in Postfix version 2.2 and later. DOMAIN The domain part of the recipient address. EXTENSION The optional address extension. HOME The recipient home directory. LOCAL

The recipient address localpart. LOGNAME The recipient's username. ORIGINAL_RECIPIENT The entire recipient address, before any address rewriting or aliasing. RECIPIENT The full recipient address. SASL_METHOD SASL authentication method specified in the remote client AUTH command. Available in Postfix version 2.2 and later. SASL_SENDER SASL sender address specified in the remote client MAIL FROM command. Available in Postfix version 2.2 and later. SASL_USER SASL username specified in the remote client AUTH command. Available in Postfix version 2.2 and later. SENDER The full sender address. SHELL The recipient's login shell. USER The recipient username. Unlike other Postfix configuration parameters, the mailbox_command parameter is not subjected to $name substitutions. This is to make it easier to specify shell syntax (see example below). If you can, avoid shell meta characters because they will force Postfix to run an expensive shell process. If you're delivering via Procmail then running a shell won't make a noticeable difference in the total cost. Note: if you use the mailbox_command feature to deliver mail system-wide, you must set up an alias that forwards mail for root to a real user. The precedence of local(8) delivery features from high to low is: aliases, .forward files, mailbox_transport_maps, mailbox_transport, mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_directory, fallback_transport_maps, fallback_transport and luser_relay. Examples:
mailbox_command = /some/where/procmail mailbox_command = /some/where/procmail -a "$EXTENSION" mailbox_command = /some/where/maildrop -d "$USER" -f "$SENDER" "$EXTENSION"

mailbox_command_maps (default: empty) Optional lookup tables with per-recipient external commands to use for local(8) mailbox delivery. Behavior is as with mailbox_command. The precedence of local(8) delivery features from high to low is: aliases, .forward files, mailbox_transport_maps, mailbox_transport, mailbox_command_maps, mailbox_command,

home_mailbox, mail_spool_directory, fallback_transport_maps, fallback_transport and luser_relay. mailbox_delivery_lock (default: see "postconf -d" output) How to lock a UNIX-style local(8) mailbox before attempting delivery. For a list of available file locking methods, use the "postconf -l" command. This setting is ignored with maildir style delivery, because such deliveries are safe without explicit locks. Note: The dotlock method requires that the recipient UID or GID has write access to the parent directory of the mailbox file. Note: the default setting of this parameter is system dependent. mailbox_size_limit (default: 51200000) The maximal size of any local(8) individual mailbox or maildir file, or zero (no limit). In fact, this limits the size of any file that is written to upon local delivery, including files written by external commands that are executed by the local(8) delivery agent. This limit must not be smaller than the message size limit. mailbox_transport (default: empty) Optional message delivery transport that the local(8) delivery agent should use for mailbox delivery to all local recipients, whether or not they are found in the UNIX passwd database. The precedence of local(8) delivery features from high to low is: aliases, .forward files, mailbox_transport_maps, mailbox_transport, mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_directory, fallback_transport_maps, fallback_transport and luser_relay. mailbox_transport_maps (default: empty) Optional lookup tables with per-recipient message delivery transports to use for local(8) mailbox delivery, whether or not the recipients are found in the UNIX passwd database. The precedence of local(8) delivery features from high to low is: aliases, .forward files, mailbox_transport_maps, mailbox_transport, mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_directory, fallback_transport_maps, fallback_transport and luser_relay. For safety reasons, this feature does not allow $number substitutions in regular expression maps. This feature is available in Postfix 2.3 and later. mailq_path (default: see "postconf -d" output) Sendmail compatibility feature that specifies where the Postfix mailq(1) command is

installed. This command can be used to list the Postfix mail queue. manpage_directory (default: see "postconf -d" output) Where the Postfix manual pages are installed. maps_rbl_domains (default: empty) Obsolete feature: use the reject_rbl_client feature instead. maps_rbl_reject_code (default: 554) The numerical Postfix SMTP server response code when a remote SMTP client request is blocked by the reject_rbl_client, reject_rhsbl_client, reject_rhsbl_reverse_client, reject_rhsbl_sender or reject_rhsbl_recipient restriction. Do not change this unless you have a complete understanding of RFC 2821. masquerade_classes (default: envelope_sender, header_sender, header_recipient) What addresses are subject to address masquerading. By default, address masquerading is limited to envelope sender addresses, and to header sender and header recipient addresses. This allows you to use address masquerading on a mail gateway while still being able to forward mail to users on individual machines. Specify zero or more of: envelope_sender, envelope_recipient, header_sender, header_recipient masquerade_domains (default: empty) Optional list of domains whose subdomain structure will be stripped off in email addresses. The list is processed left to right, and processing stops at the first match. Thus,
masquerade_domains = foo.example.com example.com

strips "user@any.thing.foo.example.com" to "user@foo.example.com", but strips "user@any.thing.else.example.com" to "user@example.com". A domain name prefixed with ! means do not masquerade this domain or its subdomains. Thus,
masquerade_domains = !foo.example.com example.com

does not change "user@any.thing.foo.example.com" or "user@foo.example.com", but strips "user@any.thing.else.example.com" to "user@example.com". Note: with Postfix version 2.2, message header address masquerading happens only when message header address rewriting is enabled: The message is received with the Postfix sendmail(1) command,

The message is received from a network client that matches $local_header_rewrite_clients, The message is received from the network, and the remote_header_rewrite_domain parameter specifies a non-empty value. To get the behavior before Postfix version 2.2, specify "local_header_rewrite_clients = static:all". Example:
masquerade_domains = $mydomain

masquerade_exceptions (default: empty) Optional list of user names that are not subjected to address masquerading, even when their address matches $masquerade_domains. By default, address masquerading makes no exceptions. Specify a list of user names, "/file/name" or "type:table" patterns, separated by commas and/or whitespace. The list is matched left to right, and the search stops on the first match. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a name matches a lookup key (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "!pattern" to exclude a name from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. Examples:
masquerade_exceptions = root, mailer-daemon masquerade_exceptions = root

master_service_disable (default: empty) Selectively disable master(8) listener ports by service type or by service name and type. Specify a list of service types ("inet", "unix", "fifo", or "pass") or "name.type" tuples, where "name" is the first field of a master.cf entry and "type" is a service type. As with other Postfix matchlists, a search stops at the first match. Specify "!pattern" to exclude a service from the list. By default, all master(8) listener ports are enabled. Note: this feature does not support "/file/name" or "type:table" patterns, nor does it support wildcards such as "*" or "all". This is intentional. Examples:
# Turn on all master(8) listener ports (the default). master_service_disable = # Turn off only the main SMTP listener port. master_service_disable = smtp.inet # Turn off all TCP/IP listener ports. master_service_disable = inet # Turn off all TCP/IP listener ports except "foo". master_service_disable = !foo.inet, inet

This feature is available in Postfix 2.6 and later. max_idle (default: 100s) The maximum amount of time that an idle Postfix daemon process waits for an incoming connection before terminating voluntarily. This parameter is ignored by the Postfix queue manager and by other long-lived Postfix daemon processes. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). max_use (default: 100) The maximal number of incoming connections that a Postfix daemon process will service before terminating voluntarily. This parameter is ignored by the Postfix queue manager and by other long-lived Postfix daemon processes. maximal_backoff_time (default: 4000s) The maximal time between attempts to deliver a deferred message. This parameter should be set to a value greater than or equal to $minimal_backoff_time. See also $queue_run_delay. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). maximal_queue_lifetime (default: 5d) The maximal time a message is queued before it is sent back as undeliverable. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is d (days). Specify 0 when mail delivery should be tried only once. message_reject_characters (default: empty) The set of characters that Postfix will reject in message content. The usual C-like escape sequences are recognized: \a \b \f \n \r \t \v \ddd (up to three octal digits) and \\. Example:
message_reject_characters = \0

This feature is available in Postfix 2.3 and later. message_size_limit (default: 10240000) The maximal size in bytes of a message, including envelope information.

Note: be careful when making changes. Excessively small values will result in the loss of non-delivery notifications, when a bounce message size exceeds the local or remote MTA's message size limit. message_strip_characters (default: empty) The set of characters that Postfix will remove from message content. The usual C-like escape sequences are recognized: \a \b \f \n \r \t \v \ddd (up to three octal digits) and \\. Example:
message_strip_characters = \0

This feature is available in Postfix 2.3 and later. milter_command_timeout (default: 30s) The time limit for sending an SMTP command to a Milter (mail filter) application, and for receiving the response. Specify a non-zero time value (an integral value plus an optional one-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). This feature is available in Postfix 2.3 and later. milter_connect_macros (default: see "postconf -d" output) The macros that are sent to Milter (mail filter) applications after completion of an SMTP connection. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.3 and later. milter_connect_timeout (default: 30s) The time limit for connecting to a Milter (mail filter) application, and for negotiating protocol options. Specify a non-zero time value (an integral value plus an optional one-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). This feature is available in Postfix 2.3 and later. milter_content_timeout (default: 300s) The time limit for sending message content to a Milter (mail filter) application, and for

receiving the response. Specify a non-zero time value (an integral value plus an optional one-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). This feature is available in Postfix 2.3 and later. milter_data_macros (default: see "postconf -d" output) The macros that are sent to version 4 or higher Milter (mail filter) applications after the SMTP DATA command. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.3 and later. milter_default_action (default: tempfail) The default action when a Milter (mail filter) application is unavailable or mis-configured. Specify one of the following: accept Proceed as if the mail filter was not present. reject Reject all further commands in this session with a permanent status code. tempfail Reject all further commands in this session with a temporary status code. quarantine Like "accept", but freeze the message in the "hold" queue. Available with Postfix 2.6 and later. This feature is available in Postfix 2.3 and later. milter_end_of_data_macros (default: see "postconf -d" output) The macros that are sent to Milter (mail filter) applications after the message end-of-data. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.3 and later. milter_end_of_header_macros (default: see "postconf -d" output) The macros that are sent to Milter (mail filter) applications after the end of the message header. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.5 and later. milter_header_checks (default: empty) Optional lookup tables for content inspection of message headers that are produced by Milter

applications. See the header_checks(5) manual page available actions. Currently, PREPEND is not implemented. The following example sends all mail that is marked as SPAM to a spam handling machine. Note that matches are case-insensitive by default.
/etc/postfix/main.cf: milter_header_checks = pcre:/etc/postfix/milter_header_checks /etc/postfix/milter_header_checks: /^X-SPAM-FLAG:\s+YES/ FILTER mysmtp:sanitizer.example.com:25

The milter_header_checks mechanism could also be used for whitelisting. For example it could be used to skip heavy content inspection for DKIM-signed mail from known friendly domains. This feature is available in Postfix 2.7, and as an optional patch for Postfix 2.6. milter_helo_macros (default: see "postconf -d" output) The macros that are sent to Milter (mail filter) applications after the SMTP HELO or EHLO command. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.3 and later. milter_macro_daemon_name (default: $myhostname) The {daemon_name} macro value for Milter (mail filter) applications. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.3 and later. milter_macro_v (default: $mail_name $mail_version) The {v} macro value for Milter (mail filter) applications. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.3 and later. milter_mail_macros (default: see "postconf -d" output) The macros that are sent to Milter (mail filter) applications after the SMTP MAIL FROM command. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.3 and later. milter_protocol (default: 6) The mail filter protocol version and optional protocol extensions for communication with a Milter application; prior to Postfix 2.6 the default protocol is 2. Postfix sends this version number during the initial protocol handshake. It should match the version number that is expected by the mail filter application (or by its Milter library).

Protocol versions: 2 Use Sendmail 8 mail filter protocol version 2 (default with Sendmail version 8.11 .. 8.13 and Postfix version 2.3 .. 2.5). 3 Use Sendmail 8 mail filter protocol version 3. 4 Use Sendmail 8 mail filter protocol version 4. 6 Use Sendmail 8 mail filter protocol version 6 (default with Sendmail version 8.14 and Postfix version 2.6). Protocol extensions: no_header_reply Specify this when the Milter application will not reply for each individual message header. This feature is available in Postfix 2.3 and later. milter_rcpt_macros (default: see "postconf -d" output) The macros that are sent to Milter (mail filter) applications after the SMTP RCPT TO command. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.3 and later. milter_unknown_command_macros (default: see "postconf -d" output) The macros that are sent to version 3 or higher Milter (mail filter) applications after an unknown SMTP command. See MILTER_README for a list of available macro names and their meanings. This feature is available in Postfix 2.3 and later. mime_boundary_length_limit (default: 2048) The maximal length of MIME multipart boundary strings. The MIME processor is unable to distinguish between boundary strings that do not differ in the first $mime_boundary_length_limit characters. This feature is available in Postfix 2.0 and later. mime_header_checks (default: $header_checks) Optional lookup tables for content inspection of MIME related message headers, as described in the header_checks(5) manual page. This feature is available in Postfix 2.0 and later. mime_nesting_limit (default: 100)

The maximal recursion level that the MIME processor will handle. Postfix refuses mail that is nested deeper than the specified limit. This feature is available in Postfix 2.0 and later. minimal_backoff_time (default: 300s) The minimal time between attempts to deliver a deferred message; prior to Postfix 2.4 the default value was 1000s. This parameter also limits the time an unreachable destination is kept in the short-term, inmemory, destination status cache. This parameter should be set greater than or equal to $queue_run_delay. See also $maximal_backoff_time. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). multi_instance_directories (default: empty) An optional list of non-default Postfix configuration directories; these directories belong to additional Postfix instances that share the Postfix executable files and documentation with the default Postfix instance, and that are started, stopped, etc., together with the default Postfix instance. Specify a list of pathnames separated by comma or whitespace. When $multi_instance_directories is empty, the postfix(1) command runs in single-instance mode and operates on a single Postfix instance only. Otherwise, the postfix(1) command runs in multi-instance mode and invokes the multi-instance manager specified with the multi_instance_wrapper parameter. The multi-instance manager in turn executes postfix(1) commands for the default instance and for all Postfix instances in $multi_instance_directories. Currently, this parameter setting is ignored except for the default main.cf file. This feature is available in Postfix 2.6 and later. multi_instance_enable (default: no) Allow this Postfix instance to be started, stopped, etc., by a multi-instance manager. By default, new instances are created in a safe state that prevents them from being started inadvertently. This parameter is reserved for the multi-instance manager. This feature is available in Postfix 2.6 and later. multi_instance_group (default: empty) The optional instance group name of this Postfix instance. A group identifies closely-related Postfix instances that the multi-instance manager can start, stop, etc., as a unit. This parameter is reserved for the multi-instance manager. This feature is available in Postfix 2.6 and later.

multi_instance_name (default: empty) The optional instance name of this Postfix instance. This name becomes also the default value for the syslog_name parameter. This feature is available in Postfix 2.6 and later. multi_instance_wrapper (default: empty) The pathname of a multi-instance manager command that the postfix(1) command invokes when the multi_instance_directories parameter value is non-empty. The pathname may be followed by initial command arguments separated by whitespace; shell metacharacters such as quotes are not supported in this context. The postfix(1) command invokes the manager command with the postfix(1) non-option command arguments on the manager command line, and with all installation configuration parameters exported into the manager command process environment. The manager command in turn invokes the postfix(1) command for individual Postfix instances as "postfix -c config_directory command". This feature is available in Postfix 2.6 and later. multi_recipient_bounce_reject_code (default: 550) The numerical Postfix SMTP server response code when a remote SMTP client request is blocked by the reject_multi_recipient_bounce restriction. Do not change this unless you have a complete understanding of RFC 2821. This feature is available in Postfix 2.1 and later. mydestination (default: $myhostname, localhost.$mydomain, localhost) The list of domains that are delivered via the $local_transport mail delivery transport. By default this is the Postfix local(8) delivery agent which looks up all recipients in /etc/passwd and /etc/aliases. The SMTP server validates recipient addresses with $local_recipient_maps and rejects non-existent recipients. See also the local domain class in the ADDRESS_CLASS_README file. The default mydestination value specifies names for the local machine only. On a mail domain gateway, you should also include $mydomain. The $local_transport delivery method is also selected for mail addressed to user@[the.net.work.address] of the mail system (the IP addresses specified with the inet_interfaces and proxy_interfaces parameters). Warnings: Do not specify the names of virtual domains - those domains are specified elsewhere. See VIRTUAL_README for more information. Do not specify the names of domains that this machine is backup MX host for. See

STANDARD_CONFIGURATION_README for how to set up backup MX hosts. By default, the Postfix SMTP server rejects mail for recipients not listed with the local_recipient_maps parameter. See the postconf(5) manual for a description of the local_recipient_maps and unknown_local_recipient_reject_code parameters. Specify a list of host or domain names, "/file/name" or "type:table" patterns, separated by commas and/or whitespace. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a name matches a lookup key (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Examples:
mydestination = $myhostname, localhost.$mydomain $mydomain mydestination = $myhostname, localhost.$mydomain www.$mydomain, ftp. $mydomain

mydomain (default: see "postconf -d" output) The internet domain name of this mail system. The default is to use $myhostname minus the first component, or "localdomain" (Postfix 2.3 and later). $mydomain is used as a default value for many other configuration parameters. Example:
mydomain = domain.tld

myhostname (default: see "postconf -d" output) The internet hostname of this mail system. The default is to use the fully-qualified domain name (FQDN) from gethostname(), or to use the non-FQDN result from gethostname() and append ".$mydomain". $myhostname is used as a default value for many other configuration parameters. Example:
myhostname = host.example.com

mynetworks (default: see "postconf -d" output) The list of "trusted" SMTP clients that have more privileges than "strangers". In particular, "trusted" SMTP clients are allowed to relay mail through Postfix. See the smtpd_recipient_restrictions parameter description in the postconf(5) manual. You can specify the list of "trusted" network addresses by hand or you can let Postfix do it for you (which is the default). See the description of the mynetworks_style parameter for more information. If you specify the mynetworks list by hand, Postfix ignores the mynetworks_style setting. Specify a list of network addresses or network/netmask patterns, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace.

The netmask specifies the number of bits in the network part of a host address. You can also specify "/file/name" or "type:table" patterns. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a table entry matches a lookup string (the lookup result is ignored). The list is matched left to right, and the search stops on the first match. Specify "!pattern" to exclude an address or network block from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. Note: IP version 6 address information must be specified inside [] in the mynetworks value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. Examples:
mynetworks mynetworks mynetworks mynetworks mynetworks = = = = = 127.0.0.0/8 168.100.189.0/28 !192.168.0.1, 192.168.0.0/28 127.0.0.0/8 168.100.189.0/28 [::1]/128 [2001:240:587::]/64 $config_directory/mynetworks hash:/etc/postfix/network_table

mynetworks_style (default: subnet) The method to generate the default value for the mynetworks parameter. This is the list of trusted networks for relay access control etc. Specify "mynetworks_style = host" when Postfix should "trust" only the local machine. Specify "mynetworks_style = subnet" when Postfix should "trust" SMTP clients in the same IP subnetworks as the local machine. On Linux, this works correctly only with interfaces specified with the "ifconfig" command. Specify "mynetworks_style = class" when Postfix should "trust" SMTP clients in the same IP class A/B/C networks as the local machine. Don't do this with a dialup site - it would cause Postfix to "trust" your entire provider's network. Instead, specify an explicit mynetworks list by hand, as described with the mynetworks configuration parameter. myorigin (default: $myhostname) The domain name that locally-posted mail appears to come from, and that locally posted mail is delivered to. The default, $myhostname, is adequate for small sites. If you run a domain with multiple machines, you should (1) change this to $mydomain and (2) set up a domainwide alias database that aliases each user to user@that.users.mailhost. Example:
myorigin = $mydomain

nested_header_checks (default: $header_checks) Optional lookup tables for content inspection of non-MIME message headers in attached

messages, as described in the header_checks(5) manual page. This feature is available in Postfix 2.0 and later. newaliases_path (default: see "postconf -d" output) Sendmail compatibility feature that specifies the location of the newaliases(1) command. This command can be used to rebuild the local(8) aliases(5) database. non_fqdn_reject_code (default: 504) The numerical Postfix SMTP server reply code when a client request is rejected by the reject_non_fqdn_helo_hostname, reject_non_fqdn_sender or reject_non_fqdn_recipient restriction. non_smtpd_milters (default: empty) A list of Milter (mail filter) applications for new mail that does not arrive via the Postfix smtpd(8) server. This includes local submission via the sendmail(1) command line, new mail that arrives via the Postfix qmqpd(8) server, and old mail that is re-injected into the queue with "postsuper -r". See the MILTER_README document for details. This feature is available in Postfix 2.3 and later. notify_classes (default: resource, software) The list of error classes that are reported to the postmaster. The default is to report only the most serious problems. The paranoid may wish to turn on the policy (UCE and mail relaying) and protocol error (broken mail software) reports. NOTE: postmaster notifications may contain confidential information such as SASL passwords or message content. It is the system administrator's responsibility to treat such information with care. The error classes are: bounce (also implies 2bounce) Send the postmaster copies of the headers of bounced mail, and send transcripts of SMTP sessions when Postfix rejects mail. The notification is sent to the address specified with the bounce_notice_recipient configuration parameter (default: postmaster). 2bounce Send undeliverable bounced mail to the postmaster. The notification is sent to the address specified with the 2bounce_notice_recipient configuration parameter (default: postmaster). delay Send the postmaster copies of the headers of delayed mail. The notification is sent to the address specified with the delay_notice_recipient configuration parameter (default: postmaster). policy Send the postmaster a transcript of the SMTP session when a client request was rejected because of (UCE) policy. The notification is sent to the address specified with the

error_notice_recipient configuration parameter (default: postmaster). protocol Send the postmaster a transcript of the SMTP session in case of client or server protocol errors. The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). resource Inform the postmaster of mail not delivered due to resource problems. The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). software Inform the postmaster of mail not delivered due to software problems. The notification is sent to the address specified with the error_notice_recipient configuration parameter (default: postmaster). Examples:
notify_classes = bounce, delay, policy, protocol, resource, software notify_classes = 2bounce, resource, software

owner_request_special (default: yes) Give special treatment to owner-listname and listname-request address localparts: don't split such addresses when the recipient_delimiter is set to "-". This feature is useful for mailing lists. parent_domain_matches_subdomains (default: see "postconf -d" output) What Postfix features match subdomains of "domain.tld" automatically, instead of requiring an explicit ".domain.tld" pattern. This is planned backwards compatibility: eventually, all Postfix features are expected to require explicit ".domain.tld" style patterns when you really want to match subdomains. permit_mx_backup_networks (default: empty) Restrict the use of the permit_mx_backup SMTP access feature to only domains whose primary MX hosts match the listed networks. The parameter value syntax is the same as with the mynetworks parameter; note, however, that the default value is empty. pickup_service_name (default: pickup) The name of the pickup(8) service. This service picks up local mail submissions from the Postfix maildrop queue. This feature is available in Postfix 2.0 and later. plaintext_reject_code (default: 450) The numerical Postfix SMTP server response code when a request is rejected by the reject_plaintext_session restriction. This feature is available in Postfix 2.3 and later.

postmulti_control_commands (default: reload flush) The postfix(1) commands that the postmulti(1) instance manager treats as "control" commands, that operate on running instances. For these commands, disabled instances are skipped. This feature is available in Postfix 2.6 and later. postmulti_start_commands (default: start) The postfix(1) commands that the postmulti(1) instance manager treats as "start" commands. For these commands, disabled instances are "checked" rather than "started", and failure to "start" a member instance of an instance group will abort the start-up of later instances. This feature is available in Postfix 2.6 and later. postmulti_stop_commands (default: see "postconf -d" output) The postfix(1) commands that the postmulti(1) instance manager treats as "stop" commands. For these commands, disabled instances are skipped, and enabled instances are processed in reverse order. This feature is available in Postfix 2.6 and later. postscreen_blacklist_action (default: continue) The action that postscreen(8) takes when an SMTP client is permanently blacklisted with the postscreen_blacklist_networks parameter. Specify one of the following: continue Continue waiting until the postscreen_greet_wait time has elapsed, and report whether the client triggers a PREGREET or HANGUP error, or whether the client is listed at the DNSBL sites specified with the postscreen_dnsbl_sites parameter. Take the corresponding action, or forward the connection to a real SMTP server process. drop Drop the connection immediately with a 521 SMTP reply, without reporting PREGREET, HANGUP or DNSBL results. This feature is available in Postfix 2.8. postscreen_blacklist_networks (default: empty) Network addresses that are permanently blacklisted; see the postscreen_blacklist_action parameter for possible actions. This parameter uses the same address syntax as the mynetworks parameter. The blacklist has higher precedence than whitelists. This feature never uses the remote SMTP client hostname. This feature is available in Postfix 2.8. postscreen_cache_cleanup_interval (default: 12h) The amount of time between postscreen(8) cache cleanup runs. Cache cleanup increases the

load on the cache database and should therefore not be run frequently. This feature requires that the cache database supports the "delete" and "sequence" operators. Specify a zero interval to disable cache cleanup. After each cache cleanup run, the postscreen(8) daemon logs the number of entries that were retained and dropped. A cleanup run is logged as "partial" when the daemon terminates early after "postfix reload", "postfix stop", or no requests for $max_idle seconds. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.8. postscreen_cache_map (default: btree:$data_directory/ps_whitelist) Persistent storage for the postscreen(8) server decisions. This feature is available in Postfix 2.8. postscreen_cache_retention_time (default: 1d) The amount of time that postscreen(8) will cache an expired temporary whitelist entry before it is removed. This prevents clients from being logged as "NEW" just because their cache entry expired an hour ago. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.8. postscreen_cache_ttl (default: 1d) The amount of time that postscreen(8) will cache a decision for a specific SMTP client IP address. During this time, the client IP address is excluded from tests. If possible, expired decisions are renewed automatically. Specify a non-zero time value (an integral value plus an optional one-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.8. postscreen_dnsbl_action (default: continue) The action that postscreen(8) takes when an SMTP client is listed at the DNS blocklist domains specified with the postscreen_dnsbl_sites parameter. Specify one of the following: continue Forward the connection to a real SMTP server process. drop Drop the connection with a 521 SMTP reply. This feature is available in Postfix 2.8. postscreen_dnsbl_sites (default: empty)

Optional list of DNS blocklist domains. When the list is non-enpty, the dnsblog(8) daemon will query these domains with the IP addresses of non-whitelisted postscreen(8) clients. Specify a list of domain names, separated by comma or whitespace. This feature is available in Postfix 2.8. postscreen_greet_action (default: continue) The action that postscreen(8) takes when an SMTP client speaks before its turn within the time specified with the postscreen_greet_wait parameter. Specify one of the following: continue Continue waiting until the postscreen_greet_wait time has elapsed. If the client is listed at the DNS blocklist domains specified with the postscreen_dnsbl_sites parameter, execute the action specified with the postscreen_dnsbl_action parameter, otherwise forward the connection to a real SMTP server process. drop Drop the connection immediately with a 521 SMTP reply, without examining DNSBL lookup results. In either case, postscreen(8) will not whitelist the SMTP client IP address. This feature is available in Postfix 2.8. postscreen_greet_banner (default: $smtpd_banner) The text in the optional "220-text..." server response that postscreen(8) sends ahead of the real Postfix SMTP server's "220 text..." response, in an attempt to confuse bad SMTP clients so that they speak before their turn (pre-greet). Specify an empty value to disable this feature. This feature is available in Postfix 2.8. postscreen_greet_wait (default: 4s) The amount of time that postscreen(8) will wait for an SMTP client to send a command before its turn, and for DNS blocklist lookup results to arrive. This is done only when the SMTP client IP address is not permanently whitelisted, and when it has no cached decision. Specify a non-zero time value (an integral value plus an optional one-letter suffix that specifies the time unit). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). This feature is available in Postfix 2.8. postscreen_hangup_action (default: continue) The action that postscreen(8) takes when an SMTP client disconnects without sending data, within the time specified with the postscreen_greet_wait parameter. Specify one of the following: continue Continue waiting until the postscreen_greet_wait time has elapsed, and report whether

the client is listed at the DNSBL sites specified with the postscreen_dnsbl_sites parameter. Do not forward the broken connection to a real SMTP server process. drop Drop the connection immediately, without reporting DNSBL lookup results. This feature is available in Postfix 2.8. postscreen_post_queue_limit (default: $default_process_limit) The number of clients that can be waiting for service from a real SMTP server process. When this queue is full, all clients will receive a 421 reponse. This feature is available in Postfix 2.8. postscreen_pre_queue_limit (default: $default_process_limit) The number of non-whitelisted clients that can be waiting for a decision whether they will receive service from a real SMTP server process. When this queue is full, all non-whitelisted clients will receive a 421 reponse. This feature is available in Postfix 2.8. postscreen_whitelist_networks (default: $mynetworks) Network addresses that are permanently whitelisted, and that will not be subjected to postscreen(8) checks. This parameter uses the same address syntax as the mynetworks parameter. This feature never uses the remote SMTP client hostname. This feature is available in Postfix 2.8. prepend_delivered_header (default: command, file, forward) The message delivery contexts where the Postfix local(8) delivery agent prepends a Delivered-To: message header with the address that the mail was delivered to. This information is used for mail delivery loop detection. By default, the Postfix local delivery agent prepends a Delivered-To: header when forwarding mail and when delivering to file (mailbox) and command. Turning off the Delivered-To: header when forwarding mail is not recommended. Specify zero or more of forward, file, or command. Example:
prepend_delivered_header = forward

process_id (read-only) The process ID of a Postfix command or daemon process. process_id_directory (default: pid)

The location of Postfix PID files relative to $queue_directory. This is a read-only parameter. process_name (read-only) The process name of a Postfix command or daemon process. propagate_unmatched_extensions (default: canonical, virtual) What address lookup tables copy an address extension from the lookup key to the lookup result. For example, with a virtual(5) mapping of "joe@example.com => joe.user@example.net", the address "joe+foo@example.com" would rewrite to "joe.user+foo@example.net". Specify zero or more of canonical, virtual, alias, forward, include or generic. These cause address extension propagation with canonical(5), virtual(5), and aliases(5) maps, with local(8) .forward and :include: file lookups, and with smtp(8) generic maps, respectively. Note: enabling this feature for types other than canonical and virtual is likely to cause problems when mail is forwarded to other sites, especially with mail that is sent to a mailing list exploder address. Examples:
propagate_unmatched_extensions = canonical, virtual, alias, forward, include propagate_unmatched_extensions = canonical, virtual

proxy_interfaces (default: empty) The network interface addresses that this mail system receives mail on by way of a proxy or network address translation unit. This feature is available in Postfix 2.0 and later. You must specify your "outside" proxy/NAT addresses when your system is a backup MX host for other domains, otherwise mail delivery loops will happen when the primary MX host is down. Example:
proxy_interfaces = 1.2.3.4

proxy_read_maps (default: see "postconf -d" output) The lookup tables that the proxymap(8) server is allowed to access for the read-only service. Table references that don't begin with proxy: are ignored. This feature is available in Postfix 2.0 and later. proxy_write_maps (default: see "postconf -d" output)

The lookup tables that the proxymap(8) server is allowed to access for the read-write service. Postfix-owned local database files should be stored under the Postfix-owned data_directory. Table references that don't begin with proxy: are ignored. This feature is available in Postfix 2.5 and later. proxymap_service_name (default: proxymap) The name of the proxymap read-only table lookup service. This service is normally implemented by the proxymap(8) daemon. This feature is available in Postfix 2.6 and later. proxywrite_service_name (default: proxywrite) The name of the proxywrite read-write table lookup service. This service is normally implemented by the proxymap(8) daemon. This feature is available in Postfix 2.6 and later. qmgr_clog_warn_time (default: 300s) The minimal delay between warnings that a specific destination is clogging up the Postfix active queue. Specify 0 to disable. This feature is enabled with the helpful_warnings parameter. This feature is available in Postfix 2.0 and later. qmgr_fudge_factor (default: 100) Obsolete feature: the percentage of delivery resources that a busy mail system will use up for delivery of a large mailing list message. This feature exists only in the oqmgr(8) old queue manager. The current queue manager solves the problem in a better way. qmgr_message_active_limit (default: 20000) The maximal number of messages in the active queue. qmgr_message_recipient_limit (default: 20000) The maximal number of recipients held in memory by the Postfix queue manager, and the maximal size of the size of the short-term, in-memory "dead" destination status cache. qmgr_message_recipient_minimum (default: 10) The minimal number of in-memory recipients for any message. This takes priority over any other in-memory recipient limits (i.e., the global qmgr_message_recipient_limit and the per transport _recipient_limit) if necessary. The minimum value allowed for this parameter is 1.

qmqpd_authorized_clients (default: empty) What clients are allowed to connect to the QMQP server port. By default, no client is allowed to use the service. This is because the QMQP server will relay mail to any destination. Specify a list of client patterns. A list pattern specifies a host name, a domain name, an internet address, or a network/mask pattern, where the mask specifies the number of bits in the network part. When a pattern specifies a file name, its contents are substituted for the file name; when a pattern is a "type:table" table specification, table lookup is used instead. Patterns are separated by whitespace and/or commas. In order to reverse the result, precede a pattern with an exclamation point (!). The form "!/file/name" is supported only in Postfix version 2.4 and later. Example:
qmqpd_authorized_clients = !192.168.0.1, 192.168.0.0/24

qmqpd_client_port_logging (default: no) Enable logging of the remote QMQP client port in addition to the hostname and IP address. The logging format is "host[address]:port". This feature is available in Postfix 2.5 and later. qmqpd_error_delay (default: 1s) How long the QMQP server will pause before sending a negative reply to the client. The purpose is to slow down confused or malicious clients. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). qmqpd_timeout (default: 300s) The time limit for sending or receiving information over the network. If a read or write operation blocks for more than $qmqpd_timeout seconds the QMQP server gives up and disconnects. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). queue_directory (default: see "postconf -d" output) The location of the Postfix top-level queue directory. This is the root directory of Postfix daemon processes that run chrooted. queue_file_attribute_count_limit (default: 100) The maximal number of (name=value) attributes that may be stored in a Postfix queue file.

The limit is enforced by the cleanup(8) server. This feature is available in Postfix 2.0 and later. queue_minfree (default: 0) The minimal amount of free space in bytes in the queue file system that is needed to receive mail. This is currently used by the SMTP server to decide if it will accept any mail at all. By default, the Postfix SMTP server rejects MAIL FROM commands when the amount of free space is less than 1.5*$message_size_limit (Postfix version 2.1 and later). To specify a higher minimum free space limit, specify a queue_minfree value that is at least 1.5*$message_size_limit. With Postfix versions 2.0 and earlier, a queue_minfree value of zero means there is no minimum required amount of free space. queue_run_delay (default: 300s) The time between deferred queue scans by the queue manager; prior to Postfix 2.4 the default value was 1000s. This parameter should be set less than or equal to $minimal_backoff_time. See also $maximal_backoff_time. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). queue_service_name (default: qmgr) The name of the qmgr(8) service. This service manages the Postfix queue and schedules delivery requests. This feature is available in Postfix 2.0 and later. rbl_reply_maps (default: empty) Optional lookup tables with RBL response templates. The tables are indexed by the RBL domain name. By default, Postfix uses the default template as specified with the default_rbl_reply configuration parameter. See there for a discussion of the syntax of RBL reply templates. This feature is available in Postfix 2.0 and later. readme_directory (default: see "postconf -d" output) The location of Postfix README files that describe how to build, configure or operate a specific Postfix subsystem or feature. receive_override_options (default: empty) Enable or disable recipient validation, built-in content filtering, or address mapping.

Typically, these are specified in master.cf as command-line arguments for the smtpd(8), qmqpd(8) or pickup(8) daemons. Specify zero or more of the following options. The options override main.cf settings and are either implemented by smtpd(8), qmqpd(8), or pickup(8) themselves, or they are forwarded to the cleanup server. no_unknown_recipient_checks Do not try to reject unknown recipients (SMTP server only). This is typically specified AFTER an external content filter. no_address_mappings Disable canonical address mapping, virtual alias map expansion, address masquerading, and automatic BCC (blind carbon-copy) recipients. This is typically specified BEFORE an external content filter. no_header_body_checks Disable header/body_checks. This is typically specified AFTER an external content filter. no_milters Disable Milter (mail filter) applications. This is typically specified AFTER an external content filter. Note: when the "BEFORE content filter" receive_override_options setting is specified in the main.cf file, specify the "AFTER content filter" receive_override_options setting in master.cf (and vice versa). Examples:
receive_override_options = no_unknown_recipient_checks, no_header_body_checks receive_override_options = no_address_mappings

This feature is available in Postfix 2.1 and later. recipient_bcc_maps (default: empty) Optional BCC (blind carbon-copy) address lookup tables, indexed by recipient address. The BCC address (multiple results are not supported) is added when mail enters from outside of Postfix. This feature is available in Postfix 2.1 and later. The table search order is as follows: Look up the "user+extension@domain.tld" address including the optional address extension. Look up the "user@domain.tld" address without the optional address extension. Look up the "user+extension" address local part when the recipient domain equals $myorigin, $mydestination, $inet_interfaces or $proxy_interfaces. Look up the "user" address local part when the recipient domain equals $myorigin, $mydestination, $inet_interfaces or $proxy_interfaces. Look up the "@domain.tld" part.

Specify the types and names of databases to use. After change, run "postmap /etc/postfix/recipient_bcc". Note: if mail to the BCC address bounces it will be returned to the sender. Note: automatic BCC recipients are produced only for new mail. To avoid mailer loops, automatic BCC recipients are not generated after Postfix forwards mail internally, or after Postfix generates mail itself. Example:
recipient_bcc_maps = hash:/etc/postfix/recipient_bcc

recipient_canonical_classes (default: envelope_recipient, header_recipient) What addresses are subject to recipient_canonical_maps address mapping. By default, recipient_canonical_maps address mapping is applied to envelope recipient addresses, and to header recipient addresses. Specify one or more of: envelope_recipient, header_recipient This feature is available in Postfix 2.2 and later. recipient_canonical_maps (default: empty) Optional address mapping lookup tables for envelope and header recipient addresses. The table format and lookups are documented in canonical(5). Note: $recipient_canonical_maps is processed before $canonical_maps. Example:
recipient_canonical_maps = hash:/etc/postfix/recipient_canonical

recipient_delimiter (default: empty) The separator between user names and address extensions (user+foo). See canonical(5), local(8), relocated(5) and virtual(5) for the effects this has on aliases, canonical, virtual, relocated and on .forward file lookups. Basically, the software tries user+foo and .forward+foo before trying user and .forward. Example:
recipient_delimiter = +

reject_code (default: 554) The numerical Postfix SMTP server response code when a remote SMTP client request is rejected by the "reject" restriction. Do not change this unless you have a complete understanding of RFC 2821.

reject_tempfail_action (default: defer_if_permit) The Postfix SMTP server's action when a reject-type restriction fails due to a temporary error condition. Specify "defer" to defer the remote SMTP client request immediately. With the default "defer_if_permit" action, the Postfix SMTP server continues to look for opportunities to reject mail, and defers the client request only if it would otherwise be accepted. For finer control, see: unverified_recipient_tempfail_action, unverified_sender_tempfail_action, unknown_address_tempfail_action, and unknown_helo_hostname_tempfail_action. This feature is available in Postfix 2.6 and later. relay_clientcerts (default: empty) List of tables with remote SMTP client-certificate fingerprints for which the Postfix SMTP server will allow access with the permit_tls_clientcerts feature. The fingerprint digest algorithm is configurable via the smtpd_tls_fingerprint_digest parameter (hard-coded as md5 prior to Postfix version 2.5). Postfix lookup tables are in the form of (key, value) pairs. Since we only need the key, the value can be chosen freely, e.g. the name of the user or host: D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home Example:
relay_clientcerts = hash:/etc/postfix/relay_clientcerts

For more fine-grained control, use check_ccert_access to select an appropriate access(5) policy for each client. See RESTRICTION_CLASS_README. This feature is available with Postfix version 2.2. relay_destination_concurrency_limit (default: $default_destination_concurrency_limit) The maximal number of parallel deliveries to the same destination via the relay message delivery transport. This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. This feature is available in Postfix 2.0 and later. relay_destination_recipient_limit (default: $default_destination_recipient_limit) The maximal number of recipients per message for the relay message delivery transport. This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. Setting this parameter to a value of 1 changes the meaning of relay_destination_concurrency_limit from concurrency per domain into concurrency per recipient. This feature is available in Postfix 2.0 and later.

relay_domains (default: $mydestination) What destination domains (and subdomains thereof) this system will relay mail to. Subdomain matching is controlled with the parent_domain_matches_subdomains parameter. For details about how the relay_domains value is used, see the description of the permit_auth_destination and reject_unauth_destination SMTP recipient restrictions. Domains that match $relay_domains are delivered with the $relay_transport mail delivery transport. The SMTP server validates recipient addresses with $relay_recipient_maps and rejects non-existent recipients. See also the relay domains address class in the ADDRESS_CLASS_README file. Note: Postfix will not automatically forward mail for domains that list this system as their primary or backup MX host. See the permit_mx_backup restriction in the postconf(5) manual page. Specify a list of host or domain names, "/file/name" patterns or "type:table" lookup tables, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a (parent) domain appears as lookup key. Specify "!pattern" to exclude a domain from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. relay_domains_reject_code (default: 554) The numerical Postfix SMTP server response code when a client request is rejected by the reject_unauth_destination recipient restriction. Do not change this unless you have a complete understanding of RFC 2821. relay_recipient_maps (default: empty) Optional lookup tables with all valid addresses in the domains that match $relay_domains. Specify @domain as a wild-card for domains that have no valid recipient list, and become a source of backscatter mail: Postfix accepts spam for non-existent recipients and then floods innocent people with undeliverable mail. Technically, tables listed with $relay_recipient_maps are used as lists: Postfix needs to know only if a lookup string is found or not, but it does not use the result from table lookup. If this parameter is non-empty, then the Postfix SMTP server will reject mail to unknown relay users. This feature is off by default. See also the relay domains address class in the ADDRESS_CLASS_README file. Example:
relay_recipient_maps = hash:/etc/postfix/relay_recipients

This feature is available in Postfix 2.0 and later. relay_transport (default: relay) The default mail delivery transport and next-hop destination for remote delivery to domains

listed with $relay_domains. In order of decreasing precedence, the nexthop destination is taken from $relay_transport, $sender_dependent_relayhost_maps, $relayhost, or from the recipient domain. This information can be overruled with the transport(5) table. Specify a string of the form transport:nexthop, where transport is the name of a mail delivery transport defined in master.cf. The :nexthop destination is optional; its syntax is documented in the manual page of the corresponding delivery agent. See also the relay domains address class in the ADDRESS_CLASS_README file. This feature is available in Postfix 2.0 and later. relayhost (default: empty) The next-hop destination of non-local mail; overrides non-local domains in recipient addresses. This information is overruled with relay_transport, sender_dependent_default_transport_maps, default_transport, sender_dependent_relayhost_maps and with the transport(5) table. On an intranet, specify the organizational domain name. If your internal DNS uses no MX records, specify the name of the intranet gateway host instead. In the case of SMTP, specify a domain name, hostname, hostname:port, [hostname]:port, [hostaddress] or [hostaddress]:port. The form [hostname] turns off MX lookups. If you're connected via UUCP, see the UUCP_README file for useful information. Examples:
relayhost relayhost relayhost relayhost = = = = $mydomain [gateway.example.com] uucphost [an.ip.add.ress]

relocated_maps (default: empty) Optional lookup tables with new contact information for users or domains that no longer exist. The table format and lookups are documented in relocated(5). If you use this feature, run "postmap /etc/postfix/relocated" to build the necessary DBM or DB file after change, then "postfix reload" to make the changes visible. Examples:
relocated_maps = dbm:/etc/postfix/relocated relocated_maps = hash:/etc/postfix/relocated

remote_header_rewrite_domain (default: empty) Don't rewrite message headers from remote clients at all when this parameter is empty; otherwise, rewrite message headers and append the specified domain name to incomplete addresses. The local_header_rewrite_clients parameter controls what clients Postfix considers local.

Examples: The safe setting: append "domain.invalid" to incomplete header addresses from remote SMTP clients, so that those addresses cannot be confused with local addresses.
remote_header_rewrite_domain = domain.invalid

The default, purist, setting: don't rewrite headers from remote clients at all.
remote_header_rewrite_domain =

require_home_directory (default: no) Require that a local(8) recipient's home directory exists before mail delivery is attempted. By default this test is disabled. It can be useful for environments that import home directories to the mail server (IMPORTING HOME DIRECTORIES IS NOT RECOMMENDED). resolve_dequoted_address (default: yes) Resolve a recipient address safely instead of correctly, by looking inside quotes. By default, the Postfix address resolver does not quote the address localpart as per RFC 822, so that additional @ or % or ! operators remain visible. This behavior is safe but it is also technically incorrect. If you specify "resolve_dequoted_address = no", then the Postfix resolver will not know about additional @ etc. operators in the address localpart. This opens opportunities for obscure mail relay attacks with user@domain@domain addresses when Postfix provides backup MX service for Sendmail systems. resolve_null_domain (default: no) Resolve an address that ends in the "@" null domain as if the local hostname were specified, instead of rejecting the address as invalid. This feature is available in Postfix 2.1 and later. Earlier versions always resolve the null domain as the local hostname. The Postfix SMTP server uses this feature to reject mail from or to addresses that end in the "@" null domain, and from addresses that rewrite into a form that ends in the "@" null domain. resolve_numeric_domain (default: no) Resolve "user@ipaddress" as "user@[ipaddress]", instead of rejecting the address as invalid. This feature is available in Postfix 2.3 and later. rewrite_service_name (default: rewrite) The name of the address rewriting service. This service rewrites addresses to standard form and resolves them to a (delivery method, next-hop host, recipient) triple.

This feature is available in Postfix 2.0 and later. sample_directory (default: /etc/postfix) The name of the directory with example Postfix configuration files. Starting with Postfix 2.1, these files have been replaced with the postconf(5) manual page. send_cyrus_sasl_authzid (default: no) When authenticating to a remote SMTP or LMTP server with the default setting "no", send no SASL authoriZation ID (authzid); send only the SASL authentiCation ID (authcid) plus the authcid's password. The non-default setting "yes" enables the behavior of older Postfix versions. These always send a SASL authzid that is equal to the SASL authcid, but this causes inter-operability problems with some SMTP servers. This feature is available in Postfix 2.4.4 and later. sender_based_routing (default: no) This parameter should not be used. It was replaced by sender_dependent_relayhost_maps in Postfix version 2.3. sender_bcc_maps (default: empty) Optional BCC (blind carbon-copy) address lookup tables, indexed by sender address. The BCC address (multiple results are not supported) is added when mail enters from outside of Postfix. This feature is available in Postfix 2.1 and later. The table search order is as follows: Look up the "user+extension@domain.tld" address including the optional address extension. Look up the "user@domain.tld" address without the optional address extension. Look up the "user+extension" address local part when the sender domain equals $myorigin, $mydestination, $inet_interfaces or $proxy_interfaces. Look up the "user" address local part when the sender domain equals $myorigin, $mydestination, $inet_interfaces or $proxy_interfaces. Look up the "@domain.tld" part. Specify the types and names of databases to use. After change, run "postmap /etc/postfix/sender_bcc". Note: if mail to the BCC address bounces it will be returned to the sender. Note: automatic BCC recipients are produced only for new mail. To avoid mailer loops, automatic BCC recipients are not generated after Postfix forwards mail internally, or after Postfix generates mail itself.

Example:
sender_bcc_maps = hash:/etc/postfix/sender_bcc

sender_canonical_classes (default: envelope_sender, header_sender) What addresses are subject to sender_canonical_maps address mapping. By default, sender_canonical_maps address mapping is applied to envelope sender addresses, and to header sender addresses. Specify one or more of: envelope_sender, header_sender This feature is available in Postfix 2.2 and later. sender_canonical_maps (default: empty) Optional address mapping lookup tables for envelope and header sender addresses. The table format and lookups are documented in canonical(5). Example: you want to rewrite the SENDER address "user@ugly.domain" to "user@pretty.domain", while still being able to send mail to the RECIPIENT address "user@ugly.domain". Note: $sender_canonical_maps is processed before $canonical_maps. Example:
sender_canonical_maps = hash:/etc/postfix/sender_canonical

sender_dependent_default_transport_maps (default: empty) A sender-dependent override for the global default_transport parameter setting. The tables are searched by the envelope sender address and @domain. A lookup result of DUNNO terminates the search without overriding the global default_transport parameter setting. This information is overruled with the transport(5) table. Note: this overrides default_transport, not transport_maps, and therefore the expected syntax is that of default_transport, not the syntax of transport_maps. Specifically, this does not support the transport_maps syntax for null transport, null nexthop, or null email addresses. For safety reasons, this feature does not allow $number substitutions in regular expression maps. This feature is available in Postfix 2.7 and later. sender_dependent_relayhost_maps (default: empty) A sender-dependent override for the global relayhost parameter setting. The tables are searched by the envelope sender address and @domain. A lookup result of DUNNO terminates the search without overriding the global relayhost parameter setting (Postfix 2.6 and later). This information is overruled with relay_transport, sender_dependent_default_transport_maps, default_transport and with the transport(5) table.

For safety reasons, this feature does not allow $number substitutions in regular expression maps. This feature is available in Postfix 2.3 and later. sendmail_path (default: see "postconf -d" output) A Sendmail compatibility feature that specifies the location of the Postfix sendmail(1) command. This command can be used to submit mail into the Postfix queue. service_throttle_time (default: 60s) How long the Postfix master(8) waits before forking a server that appears to be malfunctioning. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). setgid_group (default: postdrop) The group ownership of set-gid Postfix commands and of group-writable Postfix directories. When this parameter value is changed you need to re-run "postfix set-permissions" (with Postfix version 2.0 and earlier: "/etc/postfix/post-install set-permissions". show_user_unknown_table_name (default: yes) Display the name of the recipient table in the "User unknown" responses. The extra detail makes trouble shooting easier but also reveals information that is nobody elses business. This feature is available in Postfix 2.0 and later. showq_service_name (default: showq) The name of the showq(8) service. This service produces mail queue status reports. This feature is available in Postfix 2.0 and later. smtp_address_preference (default: ipv6) The address type ("ipv6", "ipv4" or "any") that the Postfix SMTP client will try first, when a destination has IPv6 and IPv4 addresses with equal MX preference. This feature has no effect unless the inet_protocols setting enables both IPv4 and IPv6. This feature is available in Postfix 2.8 and later. smtp_always_send_ehlo (default: yes) Always send EHLO at the start of an SMTP session. With "smtp_always_send_ehlo = no", Postfix sends EHLO only when the word "ESMTP" appears in the server greeting banner (example: 220 spike.porcupine.org ESMTP Postfix).

smtp_bind_address (default: empty) An optional numerical network address that the Postfix SMTP client should bind to when making an IPv4 connection. This can be specified in the main.cf file for all SMTP clients, or it can be specified in the master.cf file for a specific client, for example:
/etc/postfix/master.cf: smtp ... smtp -o smtp_bind_address=11.22.33.44

Note 1: when inet_interfaces specifies no more than one IPv4 address, and that address is a non-loopback address, it is automatically used as the smtp_bind_address. This supports virtual IP hosting, but can be a problem on multi-homed firewalls. See the inet_interfaces documentation for more detail. Note 2: address information may be enclosed inside [], but this form is not required here. smtp_bind_address6 (default: empty) An optional numerical network address that the Postfix SMTP client should bind to when making an IPv6 connection. This feature is available in Postfix 2.2 and later. This can be specified in the main.cf file for all SMTP clients, or it can be specified in the master.cf file for a specific client, for example:
/etc/postfix/master.cf: smtp ... smtp -o smtp_bind_address6=1:2:3:4:5:6:7:8

Note 1: when inet_interfaces specifies no more than one IPv6 address, and that address is a non-loopback address, it is automatically used as the smtp_bind_address6. This supports virtual IP hosting, but can be a problem on multi-homed firewalls. See the inet_interfaces documentation for more detail. Note 2: address information may be enclosed inside [], but this form is not recommended here. smtp_body_checks (default: empty) Restricted body_checks(5) tables for the Postfix SMTP client. These tables are searched while mail is being delivered. Actions that change the delivery time or destination are not available. This feature is available in Postfix 2.5 and later. smtp_cname_overrides_servername (default: version dependent) Allow DNS CNAME records to override the servername that the Postfix SMTP client uses for logging, SASL password lookup, TLS policy decisions, or TLS certificate verification. The value "no" hardens Postfix smtp_tls_per_site hostname-based policies against false hostname information in DNS CNAME records, and makes SASL password file lookups more

predictable. This is the default setting as of Postfix 2.3. This feature is available in Postfix 2.2.9 and later. smtp_connect_timeout (default: 30s) The SMTP client time limit for completing a TCP connection, or zero (use the operating system built-in time limit). When no connection can be made within the deadline, the Postfix SMTP client tries the next address on the mail exchanger list. Specify 0 to disable the time limit (i.e. use whatever timeout is implemented by the operating system). Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). smtp_connection_cache_destinations (default: empty) Permanently enable SMTP connection caching for the specified destinations. With SMTP connection caching, a connection is not closed immediately after completion of a mail transaction. Instead, the connection is kept open for up to $smtp_connection_cache_time_limit seconds. This allows connections to be reused for other deliveries, and can improve mail delivery performance. Specify a comma or white space separated list of destinations or pseudo-destinations: if mail is sent without a relay host: a domain name (the right-hand side of an email address, without the [] around a numeric IP address), if mail is sent via a relay host: a relay host name (without [] or non-default TCP port), as specified in main.cf or in the transport map, if mail is sent via a UNIX-domain socket: a pathname (without the unix: prefix), a /file/name with domain names and/or relay host names as defined above, a "type:table" with domain names and/or relay host names on the left-hand side. The right-hand side result from "type:table" lookups is ignored. This feature is available in Postfix 2.2 and later. smtp_connection_cache_on_demand (default: yes) Temporarily enable SMTP connection caching while a destination has a high volume of mail in the active queue. With SMTP connection caching, a connection is not closed immediately after completion of a mail transaction. Instead, the connection is kept open for up to $smtp_connection_cache_time_limit seconds. This allows connections to be reused for other deliveries, and can improve mail delivery performance. This feature is available in Postfix 2.2 and later. smtp_connection_cache_reuse_limit (default: 10) When SMTP connection caching is enabled, the number of times that an SMTP session may be reused before it is closed.

This feature is available in Postfix 2.2. In Postfix 2.3 it is replaced by $smtp_connection_reuse_time_limit. smtp_connection_cache_time_limit (default: 2s) When SMTP connection caching is enabled, the amount of time that an unused SMTP client socket is kept open before it is closed. Do not specify larger values without permission from the remote sites. This feature is available in Postfix 2.2 and later. smtp_connection_reuse_time_limit (default: 300s) The amount of time during which Postfix will use an SMTP connection repeatedly. The timer starts when the connection is initiated (i.e. it includes the connect, greeting and helo latency, in addition to the latencies of subsequent mail delivery transactions). This feature addresses a performance stability problem with remote SMTP servers. This problem is not specific to Postfix: it can happen when any MTA sends large amounts of SMTP email to a site that has multiple MX hosts. The problem starts when one of a set of MX hosts becomes slower than the rest. Even though SMTP clients connect to fast and slow MX hosts with equal probability, the slow MX host ends up with more simultaneous inbound connections than the faster MX hosts, because the slow MX host needs more time to serve each client request. The slow MX host becomes a connection attractor. If one MX host becomes N times slower than the rest, it dominates mail delivery latency unless there are more than N fast MX hosts to counter the effect. And if the number of MX hosts is smaller than N, the mail delivery latency becomes effectively that of the slowest MX host divided by the total number of MX hosts. The solution uses connection caching in a way that differs from Postfix version 2.2. By limiting the amount of time during which a connection can be used repeatedly (instead of limiting the number of deliveries over that connection), Postfix not only restores fairness in the distribution of simultaneous connections across a set of MX hosts, it also favors deliveries over connections that perform well, which is exactly what we want. The default reuse time limit, 300s, is comparable to the various smtp transaction timeouts which are fair estimates of maximum excess latency for a slow delivery. Note that hosts may accept thousands of messages over a single connection within the default connection reuse time limit. This number is much larger than the default Postfix version 2.2 limit of 10 messages per cached connection. It may prove necessary to lower the limit to avoid interoperability issues with MTAs that exhibit bugs when many messages are delivered via a single connection. A lower reuse time limit risks losing the benefit of connection reuse when the average connection and mail delivery latency exceeds the reuse time limit. This feature is available in Postfix 2.3 and later. smtp_data_done_timeout (default: 600s) The SMTP client time limit for sending the SMTP ".", and for receiving the server response.

When no response is received within the deadline, a warning is logged that the mail may be delivered multiple times. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). smtp_data_init_timeout (default: 120s) The SMTP client time limit for sending the SMTP DATA command, and for receiving the server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). smtp_data_xfer_timeout (default: 180s) The SMTP client time limit for sending the SMTP message content. When the connection makes no progress for more than $smtp_data_xfer_timeout seconds the Postfix SMTP client terminates the transfer. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). smtp_defer_if_no_mx_address_found (default: no) Defer mail delivery when no MX record resolves to an IP address. The default (no) is to return the mail as undeliverable. With older Postfix versions the default was to keep trying to deliver the mail until someone fixed the MX record or until the mail was too old. Note: Postfix always ignores MX records with equal or worse preference than the local MTA itself. This feature is available in Postfix 2.1 and later. smtp_destination_concurrency_limit (default: $default_destination_concurrency_limit) The maximal number of parallel deliveries to the same destination via the smtp message delivery transport. This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. smtp_destination_recipient_limit (default: $default_destination_recipient_limit) The maximal number of recipients per message for the smtp message delivery transport. This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. Setting this parameter to a value of 1 changes the meaning of smtp_destination_concurrency_limit from concurrency per domain into concurrency per recipient.

smtp_discard_ehlo_keyword_address_maps (default: empty) Lookup tables, indexed by the remote SMTP server address, with case insensitive lists of EHLO keywords (pipelining, starttls, auth, etc.) that the Postfix SMTP client will ignore in the EHLO response from a remote SMTP server. See smtp_discard_ehlo_keywords for details. The table is not indexed by hostname for consistency with smtpd_discard_ehlo_keyword_address_maps. This feature is available in Postfix 2.2 and later. smtp_discard_ehlo_keywords (default: empty) A case insensitive list of EHLO keywords (pipelining, starttls, auth, etc.) that the Postfix SMTP client will ignore in the EHLO response from a remote SMTP server. This feature is available in Postfix 2.2 and later. Notes: Specify the silent-discard pseudo keyword to prevent this action from being logged. Use the smtp_discard_ehlo_keyword_address_maps feature to discard EHLO keywords selectively. smtp_enforce_tls (default: no) Enforcement mode: require that remote SMTP servers use TLS encryption, and never send mail in the clear. This also requires that the remote SMTP server hostname matches the information in the remote server certificate, and that the remote SMTP server certificate was issued by a CA that is trusted by the Postfix SMTP client. If the certificate doesn't verify or the hostname doesn't match, delivery is deferred and mail stays in the queue. The server hostname is matched against all names provided as dNSNames in the SubjectAlternativeName. If no dNSNames are specified, the CommonName is checked. The behavior may be changed with the smtp_tls_enforce_peername option. This option is useful only if you are definitely sure that you will only connect to servers that support RFC 2487 _and_ that provide valid server certificates. Typical use is for clients that send all their email to a dedicated mailhub. This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtp_tls_security_level instead. smtp_fallback_relay (default: $fallback_relay) Optional list of relay hosts for SMTP destinations that can't be found or that are unreachable. With Postfix 2.2 and earlier this parameter is called fallback_relay. By default, mail is returned to the sender when a destination is not found, and delivery is deferred when a destination is unreachable. The fallback relays must be SMTP destinations. Specify a domain, host, host:port, [host]:port,

[address] or [address]:port; the form [host] turns off MX lookups. If you specify multiple SMTP destinations, Postfix will try them in the specified order. To prevent mailer loops between MX hosts and fall-back hosts, Postfix version 2.2 and later will not use the fallback relays for destinations that it is MX host for (assuming DNS lookup is turned on). smtp_generic_maps (default: empty) Optional lookup tables that perform address rewriting in the SMTP client, typically to transform a locally valid address into a globally valid address when sending mail across the Internet. This is needed when the local machine does not have its own Internet domain name, but uses something like localdomain.local instead. The table format and lookups are documented in generic(5); examples are shown in the ADDRESS_REWRITING_README and STANDARD_CONFIGURATION_README documents. This feature is available in Postfix 2.2 and later. smtp_header_checks (default: empty) Restricted header_checks(5) tables for the Postfix SMTP client. These tables are searched while mail is being delivered. Actions that change the delivery time or destination are not available. This feature is available in Postfix 2.5 and later. smtp_helo_name (default: $myhostname) The hostname to send in the SMTP EHLO or HELO command. The default value is the machine hostname. Specify a hostname or [ip.add.re.ss]. This information can be specified in the main.cf file for all SMTP clients, or it can be specified in the master.cf file for a specific client, for example:
/etc/postfix/master.cf: mysmtp ... smtp -o smtp_helo_name=foo.bar.com

This feature is available in Postfix 2.0 and later. smtp_helo_timeout (default: 300s) The SMTP client time limit for sending the HELO or EHLO command, and for receiving the initial server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). smtp_host_lookup (default: dns)

What mechanisms the Postfix SMTP client uses to look up a host's IP address. This parameter is ignored when DNS lookups are disabled (see: disable_dns_lookups). Specify one of the following: dns Hosts can be found in the DNS (preferred). native Use the native naming service only (nsswitch.conf, or equivalent mechanism). dns, native Use the native service for hosts not found in the DNS. This feature is available in Postfix 2.1 and later. smtp_line_length_limit (default: 990) The maximal length of message header and body lines that Postfix will send via SMTP. Longer lines are broken by inserting "<CR><LF><SPACE>". This minimizes the damage to MIME formatted mail. By default, the line length is limited to 990 characters, because some server implementations cannot receive mail with long lines. smtp_mail_timeout (default: 300s) The SMTP client time limit for sending the MAIL FROM command, and for receiving the server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). smtp_mime_header_checks (default: empty) Restricted mime_header_checks(5) tables for the Postfix SMTP client. These tables are searched while mail is being delivered. Actions that change the delivery time or destination are not available. This feature is available in Postfix 2.5 and later. smtp_mx_address_limit (default: 5) The maximal number of MX (mail exchanger) IP addresses that can result from mail exchanger lookups, or zero (no limit). Prior to Postfix version 2.3, this limit was disabled by default. This feature is available in Postfix 2.1 and later. smtp_mx_session_limit (default: 2) The maximal number of SMTP sessions per delivery request before giving up or delivering to a fall-back relay host, or zero (no limit). This restriction ignores sessions that fail to complete the SMTP initial handshake (Postfix version 2.2 and earlier) or that fail to complete the EHLO

and TLS handshake (Postfix version 2.3 and later). This feature is available in Postfix 2.1 and later. smtp_nested_header_checks (default: empty) Restricted nested_header_checks(5) tables for the Postfix SMTP client. These tables are searched while mail is being delivered. Actions that change the delivery time or destination are not available. This feature is available in Postfix 2.5 and later. smtp_never_send_ehlo (default: no) Never send EHLO at the start of an SMTP session. See also the smtp_always_send_ehlo parameter. smtp_pix_workaround_delay_time (default: 10s) How long the Postfix SMTP client pauses before sending ".<CR><LF>" in order to work around the PIX firewall "<CR><LF>.<CR><LF>" bug. Choosing a too short time makes this workaround ineffective when sending large messages over slow network connections. smtp_pix_workaround_maps (default: empty) Lookup tables, indexed by the remote SMTP server address, with per-destination workarounds for CISCO PIX firewall bugs. The table is not indexed by hostname for consistency with smtp_discard_ehlo_keyword_address_maps. This feature is available in Postfix 2.4 and later. smtp_pix_workaround_threshold_time (default: 500s) How long a message must be queued before the Postfix SMTP client turns on the PIX firewall "<CR><LF>.<CR><LF>" bug workaround for delivery through firewalls with "smtp fixup" mode turned on. By default, the workaround is turned off for mail that is queued for less than 500 seconds. In other words, the workaround is normally turned off for the first delivery attempt. Specify 0 to enable the PIX firewall "<CR><LF>.<CR><LF>" bug workaround upon the first delivery attempt. smtp_pix_workarounds (default: disable_esmtp, delay_dotcrlf) A list that specifies zero or more workarounds for CISCO PIX firewall bugs. These workarounds are implemented by the Postfix SMTP client. Workaround names are separated by comma or space, and are case insensitive. This parameter setting can be overruled with per-destination smtp_pix_workaround_maps settings.

delay_dotcrlf Insert a delay before sending ".<CR><LF>" after the end of the message content. The delay is subject to the smtp_pix_workaround_delay_time and smtp_pix_workaround_threshold_time parameter settings. disable_esmtp Disable all extended SMTP commands: send HELO instead of EHLO. This feature is available in Postfix 2.4 and later. The default settings are backwards compatible with earlier Postfix versions. smtp_quit_timeout (default: 300s) The SMTP client time limit for sending the QUIT command, and for receiving the server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). smtp_quote_rfc821_envelope (default: yes) Quote addresses in SMTP MAIL FROM and RCPT TO commands as required by RFC 2821. This includes putting quotes around an address localpart that ends in ".". The default is to comply with RFC 2821. If you have to send mail to a broken SMTP server, configure a special SMTP client in master.cf:
/etc/postfix/master.cf: broken-smtp . . . smtp -o smtp_quote_rfc821_envelope=no

and route mail for the destination in question to the "broken-smtp" message delivery with a transport(5) table. This feature is available in Postfix 2.1 and later. smtp_randomize_addresses (default: yes) Randomize the order of equal-preference MX host addresses. This is a performance feature of the Postfix SMTP client. smtp_rcpt_timeout (default: 300s) The SMTP client time limit for sending the SMTP RCPT TO command, and for receiving the server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). smtp_reply_filter (default: empty) A mechanism to transform replies from remote SMTP servers one line at a time. This is a lastresort tool to work around server replies that break inter-operability with the Postfix SMTP client. Other uses involve fault injection to test Postfix's handling of invalid responses.

Notes: In the case of a multi-line reply, the Postfix SMTP client uses the final reply line's numerical SMTP reply code and enhanced status code. The numerical SMTP reply code (XYZ) takes precedence over the enhanced status code (X.Y.Z). When the enhanced status code initial digit differs from the SMTP reply code initial digit, or when no enhanced status code is present, the Postfix SMTP client uses a generic enhanced status code (X.0.0) instead. Specify the name of a "type:table" lookup table. The search string is a single SMTP reply line as received from the remote SMTP server, except that the trailing <CR><LF> are removed. Examples:
/etc/postfix/main.cf: smtp_reply_filter = pcre:/etc/postfix/reply_filter /etc/postfix/reply_filter: # Transform garbage into "250-filler..." so that it looks like # one line from a multi-line reply. It does not matter what we # substitute here as long it has the right syntax. The Postfix # SMTP client will use the final line's numerical SMTP reply # code and enhanced status code. !/^([2-5][0-9][0-9]($|[- ]))/ 250-filler for garbage

This feature is available in Postfix 2.7. smtp_rset_timeout (default: 20s) The SMTP client time limit for sending the RSET command, and for receiving the server response. The SMTP client sends RSET in order to finish a recipient address probe, or to verify that a cached session is still usable. This feature is available in Postfix 2.1 and later. smtp_sasl_auth_cache_name (default: empty) An optional table to prevent repeated SASL authentication failures with the same remote SMTP server hostname, username and password. Each table (key, value) pair contains a server name, a username and password, and the full server response. This information is stored when a remote SMTP server rejects an authentication attempt with a 535 reply code. As long as the smtp_sasl_password_maps information does no change, and as long as the smtp_sasl_auth_cache_name information does not expire (see smtp_sasl_auth_cache_time) the Postfix SMTP client avoids SASL authentication attempts with the same server, username and password, and instead bounces or defers mail as controlled with the smtp_sasl_auth_soft_bounce configuration parameter. Use a per-destination delivery concurrency of 1 (for example, "smtp_destination_concurrency_limit = 1", "relay_destination_concurrency_limit = 1", etc.), otherwise multiple delivery agents may experience a login failure at the same time. The table must be accessed via the proxywrite service, i.e. the map name must start with

"proxy:". The table should be stored under the directory specified with the data_directory parameter. This feature uses cryptographic hashing to protect plain-text passwords, and requires that Postfix is compiled with TLS support. Example:
smtp_sasl_auth_cache_name = proxy:btree:/var/lib/postfix/sasl_auth_cache

This feature is available in Postfix 2.5 and later. smtp_sasl_auth_cache_time (default: 90d) The maximal age of an smtp_sasl_auth_cache_name entry before it is removed. This feature is available in Postfix 2.5 and later. smtp_sasl_auth_enable (default: no) Enable SASL authentication in the Postfix SMTP client. By default, the Postfix SMTP client uses no authentication. Example:
smtp_sasl_auth_enable = yes

smtp_sasl_auth_soft_bounce (default: yes) When a remote SMTP server rejects a SASL authentication request with a 535 reply code, defer mail delivery instead of returning mail as undeliverable. The latter behavior was hardcoded prior to Postfix version 2.5. Note: the setting "yes" overrides the global soft_bounce parameter, but the setting "no" does not. Example:
# Default as of Postfix 2.5 smtp_sasl_auth_soft_bounce = yes # The old hard-coded default smtp_sasl_auth_soft_bounce = no

This feature is available in Postfix 2.5 and later. smtp_sasl_mechanism_filter (default: empty) If non-empty, a Postfix SMTP client filter for the remote SMTP server's list of offered SASL mechanisms. Different client and server implementations may support different mechanism lists. By default, the Postfix SMTP client will use the intersection of the two. smtp_sasl_mechanism_filter further restricts what server mechanisms the client will take into consideration.

Specify mechanism names, "/file/name" patterns or "type:table" lookup tables. The right-hand side result from "type:table" lookups is ignored. Specify "!pattern" to exclude a mechanism name from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. This feature is available in Postfix 2.2 and later. Examples:
smtp_sasl_mechanism_filter = plain, login smtp_sasl_mechanism_filter = /etc/postfix/smtp_mechs smtp_sasl_mechanism_filter = !gssapi, !login, static:rest

smtp_sasl_password_maps (default: empty) Optional SMTP client lookup tables with one username:password entry per remote hostname or domain, or sender address when sender-dependent authentication is enabled. If no username:password entry is found, then the Postfix SMTP client will not attempt to authenticate to the remote host. The Postfix SMTP client opens the lookup table before going to chroot jail, so you can leave the password file in /etc/postfix. smtp_sasl_path (default: empty) Implementation-specific information that the Postfix SMTP client passes through to the SASL plug-in implementation that is selected with smtp_sasl_type. Typically this specifies the name of a configuration file or rendezvous point. This feature is available in Postfix 2.3 and later. smtp_sasl_security_options (default: noplaintext, noanonymous) Postfix SMTP client SASL security options; as of Postfix 2.3 the list of available features depends on the SASL client implementation that is selected with smtp_sasl_type. The following security features are defined for the cyrus client SASL implementation: Specify zero or more of the following: noplaintext Disallow methods that use plaintext passwords. noactive Disallow methods subject to active (non-dictionary) attack. nodictionary Disallow methods subject to passive (dictionary) attack. noanonymous Disallow methods that allow anonymous authentication. mutual_auth Only allow methods that provide mutual authentication (not available with SASL version 1). Example:

smtp_sasl_security_options = noplaintext

smtp_sasl_tls_security_options (default: $smtp_sasl_security_options) The SASL authentication security options that the Postfix SMTP client uses for TLS encrypted SMTP sessions. This feature is available in Postfix 2.2 and later. smtp_sasl_tls_verified_security_options (default: $smtp_sasl_tls_security_options) The SASL authentication security options that the Postfix SMTP client uses for TLS encrypted SMTP sessions with a verified server certificate. When mail is sent to the public MX host for the recipient's domain, server certificates are by default optional, and delivery proceeds even if certificate verification fails. For delivery via a submission service that requires SASL authentication, it may be appropriate to send plaintext passwords only when the connection to the server is strongly encrypted and the server identity is verified. The smtp_sasl_tls_verified_security_options parameter makes it possible to only enable plaintext mechanisms when a secure connection to the server is available. Submission servers subject to this policy must either have verifiable certificates or offer suitable non-plaintext SASL mechanisms. This feature is available in Postfix 2.6 and later. smtp_sasl_type (default: cyrus) The SASL plug-in type that the Postfix SMTP client should use for authentication. The available types are listed with the "postconf -A" command. This feature is available in Postfix 2.3 and later. smtp_send_xforward_command (default: no) Send the non-standard XFORWARD command when the Postfix SMTP server EHLO response announces XFORWARD support. This allows an "smtp" delivery agent, used for injecting mail into a content filter, to forward the name, address, protocol and HELO name of the original client to the content filter and downstream queuing SMTP server. This can produce more useful logging than localhost[127.0.0.1] etc. This feature is available in Postfix 2.1 and later. smtp_sender_dependent_authentication (default: no) Enable sender-dependent authentication in the Postfix SMTP client; this is available only with SASL authentication, and disables SMTP connection caching to ensure that mail from different senders will use the appropriate credentials.

This feature is available in Postfix 2.3 and later. smtp_skip_4xx_greeting (default: yes) Skip SMTP servers that greet with a 4XX status code (go away, try again later). By default, Postfix moves on the next mail exchanger. Specify "smtp_skip_4xx_greeting = no" if Postfix should defer delivery immediately. This feature is available in Postfix 2.0 and earlier. Later Postfix versions always skip SMTP servers that greet with a 4XX status code. smtp_skip_5xx_greeting (default: yes) Skip SMTP servers that greet with a 5XX status code (go away, do not try again later). By default, the Postfix SMTP client moves on the next mail exchanger. Specify "smtp_skip_5xx_greeting = no" if Postfix should bounce the mail immediately. The default setting is incorrect, but it is what a lot of people expect to happen. smtp_skip_quit_response (default: yes) Do not wait for the response to the SMTP QUIT command. smtp_starttls_timeout (default: 300s) Time limit for Postfix SMTP client write and read operations during TLS startup and shutdown handshake procedures. This feature is available in Postfix 2.2 and later. smtp_tls_CAfile (default: empty) A file containing CA certificates of root CAs trusted to sign either remote SMTP server certificates or intermediate CA certificates. These are loaded into memory before the smtp(8) client enters the chroot jail. If the number of trusted roots is large, consider using smtp_tls_CApath instead, but note that the latter directory must be present in the chroot jail if the smtp(8) client is chrooted. This file may also be used to augment the client certificate trust chain, but it is best to include all the required certificates directly in $smtp_tls_cert_file. Specify "tls_append_default_CA = no" to prevent Postfix from appending the systemsupplied default CAs and trusting third-party certificates. Example:
smtp_tls_CAfile = /etc/postfix/CAcert.pem

This feature is available in Postfix 2.2 and later. smtp_tls_CApath (default: empty) Directory with PEM format certificate authority certificates that the Postfix SMTP client uses

to verify a remote SMTP server certificate. Don't forget to create the necessary "hash" links with, for example, "$OPENSSL_HOME/bin/c_rehash /etc/postfix/certs". To use this option in chroot mode, this directory (or a copy) must be inside the chroot jail. Specify "tls_append_default_CA = no" to prevent Postfix from appending the systemsupplied default CAs and trusting third-party certificates. Example:
smtp_tls_CApath = /etc/postfix/certs

This feature is available in Postfix 2.2 and later. smtp_tls_block_early_mail_reply (default: no) Try to detect a mail hijacking attack based on a TLS protocol vulnerability (CVE-2009-3555), where an attacker prepends malicious HELO, MAIL, RCPT, DATA commands to a Postfix SMTP client TLS session. The attack would succeed with non-Postfix SMTP servers that reply to the malicious HELO, MAIL, RCPT, DATA commands after negotiating the Postfix SMTP client TLS session. This feature is available in Postfix 2.7. smtp_tls_cert_file (default: empty) File with the Postfix SMTP client RSA certificate in PEM format. This file may also contain the Postfix SMTP client private RSA key, and these may be the same as the Postfix SMTP server RSA certificate and key file. Do not configure client certificates unless you must present client TLS certificates to one or more servers. Client certificates are not usually needed, and can cause problems in configurations that work well without them. The recommended setting is to let the defaults stand:
smtp_tls_cert_file = smtp_tls_key_file = smtp_tls_dcert_file = smtp_tls_dkey_file = smtp_tls_eccert_file = smtp_tls_eckey_file =

The best way to use the default settings is to comment out the above parameters in main.cf if present. To enable remote SMTP servers to verify the Postfix SMTP client certificate, the issuing CA certificates must be made available to the server. You should include the required certificates in the client certificate file, the client certificate first, then the issuing CA(s) (bottom-up order). Example: the certificate for "client.example.com" was issued by "intermediate CA" which itself has a certificate issued by "root CA". Create the client.pem file with "cat client_cert.pem intermediate_CA.pem root_CA.pem > client.pem".

If you also want to verify remote SMTP server certificates issued by these CAs, you can add the CA certificates to the smtp_tls_CAfile, in which case it is not necessary to have them in the smtp_tls_cert_file, smtp_tls_dcert_file or smtp_tls_eccert_file. A certificate supplied here must be usable as an SSL client certificate and hence pass the "openssl verify -purpose sslclient ..." test. Example:
smtp_tls_cert_file = /etc/postfix/client.pem

This feature is available in Postfix 2.2 and later. smtp_tls_cipherlist (default: empty) Obsolete Postfix < 2.3 control for the Postfix SMTP client TLS cipher list. As this feature applies to all TLS security levels, it is easy to create inter-operability problems by choosing a non-default cipher list. Do not use a non-default TLS cipher list on hosts that deliver email to the public Internet: you will be unable to send email to servers that only support the ciphers you exclude. Using a restricted cipher list may be more appropriate for an internal MTA, where one can exert some control over the TLS software and settings of the peer servers. Note: do not use "" quotes around the parameter value. This feature is available in Postfix version 2.2. It is not used with Postfix 2.3 and later; use smtp_tls_mandatory_ciphers instead. smtp_tls_ciphers (default: export) The minimum TLS cipher grade that the Postfix SMTP client will use with opportunistic TLS encryption. Cipher types listed in smtp_tls_exclude_ciphers are excluded from the base definition of the selected cipher grade. The default value "export" ensures maximum interoperability. Because encryption is optional, stronger controls are not appropriate, and this setting SHOULD NOT be changed unless the change is essential. When TLS is mandatory the cipher grade is chosen via the smtp_tls_mandatory_ciphers configuration parameter, see there for syntax details. See smtp_tls_policy_maps for information on how to configure ciphers on a per-destination basis. Example:
smtp_tls_ciphers = export

This feature is available in Postfix 2.6 and later. With earlier Postfix releases only the smtp_tls_mandatory_ciphers parameter is implemented, and opportunistic TLS always uses "export" or better (i.e. all) ciphers. smtp_tls_dcert_file (default: empty) File with the Postfix SMTP client DSA certificate in PEM format. This file may also contain the Postfix SMTP client private DSA key.

See the discussion under smtp_tls_cert_file for more details. Example:


smtp_tls_dcert_file = /etc/postfix/client-dsa.pem

This feature is available in Postfix 2.2 and later. smtp_tls_dkey_file (default: $smtp_tls_dcert_file) File with the Postfix SMTP client DSA private key in PEM format. This file may be combined with the Postfix SMTP client DSA certificate file specified with $smtp_tls_dcert_file. The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only access to the system superuser account ("root"), and no access to anyone else. This feature is available in Postfix 2.2 and later. smtp_tls_eccert_file (default: empty) File with the Postfix SMTP client ECDSA certificate in PEM format. This file may also contain the Postfix SMTP client ECDSA private key. See the discussion under smtp_tls_cert_file for more details. Example:
smtp_tls_eccert_file = /etc/postfix/ecdsa-ccert.pem

This feature is available in Postfix 2.6 and later, when Postfix is compiled and linked with OpenSSL 1.0.0 or later. smtp_tls_eckey_file (default: $smtp_tls_eccert_file) File with the Postfix SMTP client ECDSA private key in PEM format. This file may be combined with the Postfix SMTP client ECDSA certificate file specified with $smtp_tls_eccert_file. The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only access to the system superuser account ("root"), and no access to anyone else. This feature is available in Postfix 2.6 and later, when Postfix is compiled and linked with OpenSSL 1.0.0 or later. smtp_tls_enforce_peername (default: yes) With mandatory TLS encryption, require that the remote SMTP server hostname matches the information in the remote SMTP server certificate. As of RFC 2487 the requirements for hostname checking for MTA clients are not specified.

This option can be set to "no" to disable strict peer name checking. This setting has no effect on sessions that are controlled via the smtp_tls_per_site table. Disabling the hostname verification can make sense in closed environment where special CAs are created. If not used carefully, this option opens the danger of a "man-in-the-middle" attack (the CommonName of this attacker will be logged). This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtp_tls_security_level instead. smtp_tls_exclude_ciphers (default: empty) List of ciphers or cipher types to exclude from the Postfix SMTP client cipher list at all TLS security levels. This is not an OpenSSL cipherlist, it is a simple list separated by whitespace and/or commas. The elements are a single cipher, or one or more "+" separated cipher properties, in which case only ciphers matching all the properties are excluded. Examples (some of these will cause problems):
smtp_tls_exclude_ciphers smtp_tls_exclude_ciphers smtp_tls_exclude_ciphers smtp_tls_exclude_ciphers smtp_tls_exclude_ciphers = = = = = aNULL MD5, DES DES+MD5 AES256-SHA, DES-CBC3-MD5 kEDH+aRSA

The first setting, disables anonymous ciphers. The next setting disables ciphers that use the MD5 digest algorithm or the (single) DES encryption algorithm. The next setting disables ciphers that use MD5 and DES together. The next setting disables the two ciphers "AES256SHA" and "DES-CBC3-MD5". The last setting disables ciphers that use "EDH" key exchange with RSA authentication. This feature is available in Postfix 2.3 and later. smtp_tls_fingerprint_cert_match (default: empty) List of acceptable remote SMTP server certificate fingerprints for the "fingerprint" TLS security level (smtp_tls_security_level = fingerprint). At this security level, certificate authorities are not used, and certificate expiration times are ignored. Instead, server certificates are verified directly via their "fingerprint". The fingerprint is a message digest of the server certificate. The digest algorithm is selected via the smtp_tls_fingerprint_digest parameter. When an smtp_tls_policy_maps table entry specifies the "fingerprint" security level, any "match" attributes in that entry specify the list of valid fingerprints for the corresponding destination. Multiple fingerprints can be combined with a "|" delimiter in a single match attribute, or multiple match attributes can be employed. Example: Certificate fingerprint verification with internal mailhub. Two matching fingerprints are listed. The relayhost may be multiple physical hosts behind a load-balancer, each with its own private/public key and self-signed certificate. Alternatively, a single relayhost may be in the process of switching from one set of private/public keys to another, and both keys are trusted just prior to the transition.

relayhost = [mailhub.example.com] smtp_tls_security_level = fingerprint smtp_tls_fingerprint_digest = md5 smtp_tls_fingerprint_cert_match = 3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1 EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35

Example: Certificate fingerprint verification with selected destinations. As in the example above, we show two matching fingerprints:
/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy smtp_tls_fingerprint_digest = md5 /etc/postfix/tls_policy: example.com fingerprint match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1 match=EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35

This feature is available in Postfix 2.5 and later. smtp_tls_fingerprint_digest (default: md5) The message digest algorithm used to construct remote SMTP server certificate fingerprints. At the "fingerprint" TLS security level (smtp_tls_security_level = fingerprint), the server certificate is verified by directly matching its fingerprint. The fingerprint is the message digest of the server certificate using the selected algorithm. With a digest algorithm resistant to "second pre-image" attacks, it is not feasible to create a new public key and a matching certificate that has the same fingerprint. The default algorithm is md5; this is consistent with the backwards compatible setting of the digest used to verify client certificates in the SMTP server. The best practice algorithm is now sha1. Recent advances in hash function cryptanalysis have led to md5 being deprecated in favor of sha1. However, as long as there are no known "second pre-image" attacks against md5, its use in this context can still be considered safe. While additional digest algorithms are often available with OpenSSL's libcrypto, only those used by libssl in SSL cipher suites are available to Postfix. For now this means just md5 or sha1. To find the fingerprint of a specific certificate file, with a specific digest algorithm, run:
$ openssl x509 -noout -fingerprint -digest -in certfile.pem

The text to the right of "=" sign is the desired fingerprint. For example:
$ openssl x509 -noout -fingerprint -sha1 -in cert.pem SHA1 Fingerprint=D4:6A:AB:19:24:79:F8:32:BB:A6:CB:66:82:C0:8E:9B:EE:29 :A8:1A

This feature is available in Postfix 2.5 and later. smtp_tls_key_file (default: $smtp_tls_cert_file)

File with the Postfix SMTP client RSA private key in PEM format. This file may be combined with the Postfix SMTP client RSA certificate file specified with $smtp_tls_cert_file. The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only access to the system superuser account ("root"), and no access to anyone else. Example:
smtp_tls_key_file = $smtp_tls_cert_file

This feature is available in Postfix 2.2 and later. smtp_tls_loglevel (default: 0) Enable additional Postfix SMTP client logging of TLS activity. Each logging level also includes the information that is logged at a lower logging level. 0 Disable logging of TLS activity. 1 Log TLS handshake and certificate information. 2 Log levels during TLS negotiation. 3 Log hexadecimal and ASCII dump of TLS negotiation process. 4 Log hexadecimal and ASCII dump of complete transmission after STARTTLS. Use "smtp_tls_loglevel = 3" only in case of problems. Use of loglevel 4 is strongly discouraged. This feature is available in Postfix 2.2 and later. smtp_tls_mandatory_ciphers (default: medium) The minimum TLS cipher grade that the Postfix SMTP client will use with mandatory TLS encryption. The default value "medium" is suitable for most destinations with which you may want to enforce TLS, and is beyond the reach of today's cryptanalytic methods. See smtp_tls_policy_maps for information on how to configure ciphers on a per-destination basis. The following cipher grades are supported: export Enable "EXPORT" grade or better OpenSSL ciphers. This is the default for opportunistic encryption. It is not recommended for mandatory encryption unless you must enforce TLS with "crippled" peers. The underlying cipherlist is specified via the tls_export_cipherlist configuration parameter, which you are strongly encouraged to not change. low Enable "LOW" grade or better OpenSSL ciphers. This setting is only appropriate for internal mail servers. The underlying cipherlist is specified via the tls_low_cipherlist configuration parameter, which you are strongly encouraged to not change. medium Enable "MEDIUM" grade or better OpenSSL ciphers. The underlying cipherlist is specified via the tls_medium_cipherlist configuration parameter, which you are strongly encouraged to not change.

high Enable only "HIGH" grade OpenSSL ciphers. This setting may be appropriate when all mandatory TLS destinations (e.g. when all mail is routed to a suitably capable relayhost) support at least one "HIGH" grade cipher. The underlying cipherlist is specified via the tls_high_cipherlist configuration parameter, which you are strongly encouraged to not change. null Enable only the "NULL" OpenSSL ciphers, these provide authentication without encryption. This setting is only appropriate in the rare case that all servers are prepared to use NULL ciphers (not normally enabled in TLS servers). A plausible use-case is an LMTP server listening on a UNIX-domain socket that is configured to support "NULL" ciphers. The underlying cipherlist is specified via the tls_null_cipherlist configuration parameter, which you are strongly encouraged to not change. The underlying cipherlists for grades other than "null" include anonymous ciphers, but these are automatically filtered out if the Postfix SMTP client is configured to verify server certificates. You are very unlikely to need to take any steps to exclude anonymous ciphers, they are excluded automatically as necessary. If you must exclude anonymous ciphers at the "may" or "encrypt" security levels, when the Postfix SMTP client does not need or use peer certificates, set "smtp_tls_exclude_ciphers = aNULL". To exclude anonymous ciphers only when TLS is enforced, set "smtp_tls_mandatory_exclude_ciphers = aNULL". This feature is available in Postfix 2.3 and later. smtp_tls_mandatory_exclude_ciphers (default: empty) Additional list of ciphers or cipher types to exclude from the SMTP client cipher list at mandatory TLS security levels. This list works in addition to the exclusions listed with smtp_tls_exclude_ciphers (see there for syntax details). Starting with Postfix 2.6, the mandatory cipher exclusions can be specified on a perdestination basis via the TLS policy "exclude" attribute. See smtp_tls_policy_maps for notes and examples. This feature is available in Postfix 2.3 and later. smtp_tls_mandatory_protocols (default: SSLv3, TLSv1) List of SSL/TLS protocols that the Postfix SMTP client will use with mandatory TLS encryption. In main.cf the values are separated by whitespace, commas or colons. In the policy table "protocols" attribute (see smtp_tls_policy_maps) the only valid separator is colon. An empty value means allow all protocols. The valid protocol names, (see SSL_get_version(3)), are "SSLv2", "SSLv3" and "TLSv1". With Postfix 2.5 the parameter syntax is expanded to support protocol exclusions. One can now explicitly exclude SSLv2 by setting "smtp_tls_mandatory_protocols = !SSLv2". To exclude both SSLv2 and SSLv3 set "smtp_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing the protocols to include, rather than protocols to exclude, is still supported; use the form you find more intuitive. Since SSL version 2 has known protocol weaknesses and is now deprecated, the default setting excludes "SSLv2". This means that by default, SSL version 2 will not be used at the

"encrypt" security level and higher. See the documentation of the smtp_tls_policy_maps parameter and TLS_README for more information about security levels. Example:
smtp_tls_mandatory_protocols = TLSv1 # Alternative form with Postfix 2.5: smtp_tls_mandatory_protocols = !SSLv2, !SSLv3

This feature is available in Postfix 2.3 and later. smtp_tls_note_starttls_offer (default: no) Log the hostname of a remote SMTP server that offers STARTTLS, when TLS is not already enabled for that server. The logfile record looks like:
postfix/smtp[pid]: Host offered STARTTLS: [name.of.host]

This feature is available in Postfix 2.2 and later. smtp_tls_per_site (default: empty) Optional lookup tables with the Postfix SMTP client TLS usage policy by next-hop destination and by remote SMTP server hostname. When both lookups succeed, the more specific per-site policy (NONE, MUST, etc) overrides the less specific one (MAY), and the more secure per-site policy (MUST, etc) overrides the less secure one (NONE). With Postfix 2.3 and later smtp_tls_per_site is strongly discouraged: use smtp_tls_policy_maps instead. Use of the bare hostname as the per-site table lookup key is discouraged. Always use the full destination nexthop (enclosed in [] with a possible ":port" suffix). A recipient domain or MXenabled transport next-hop with no port suffix may look like a bare hostname, but is still a suitable destination. Specify a next-hop destination or server hostname on the left-hand side; no wildcards are allowed. The next-hop destination is either the recipient domain, or the destination specified with a transport(5) table, the relayhost parameter, or the relay_transport parameter. On the right hand side specify one of the following keywords: NONE Don't use TLS at all. This overrides a less specific MAY lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername settings. MAY Try to use TLS if the server announces support, otherwise use the unencrypted connection. This has less precedence than a more specific result (including NONE) from the alternate host or next-hop lookup key, and has less precedence than the more specific global "smtp_enforce_tls = yes" or "smtp_tls_enforce_peername = yes". MUST_NOPEERMATCH Require TLS encryption, but do not require that the remote SMTP server hostname

matches the information in the remote SMTP server certificate, or that the server certificate was issued by a trusted CA. This overrides a less secure NONE or a less specific MAY lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. MUST Require TLS encryption, require that the remote SMTP server hostname matches the information in the remote SMTP server certificate, and require that the remote SMTP server certificate was issued by a trusted CA. This overrides a less secure NONE and MUST_NOPEERMATCH or a less specific MAY lookup result from the alternate host or next-hop lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. The above keywords correspond to the "none", "may", "encrypt" and "verify" security levels for the new smtp_tls_security_level parameter introduced in Postfix 2.3. Starting with Postfix 2.3, and independently of how the policy is specified, the smtp_tls_mandatory_ciphers and smtp_tls_mandatory_protocols parameters apply when TLS encryption is mandatory. Connections for which encryption is optional typically enable all "export" grade and better ciphers (see smtp_tls_ciphers and smtp_tls_protocols). As long as no secure DNS lookup mechanism is available, false hostnames in MX or CNAME responses can change the server hostname that Postfix uses for TLS policy lookup and server certificate verification. Even with a perfect match between the server hostname and the server certificate, there is no guarantee that Postfix is connected to the right server. See TLS_README (Closing a DNS loophole with obsolete per-site TLS policies) for a possible work-around. This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtp_tls_policy_maps instead. smtp_tls_policy_maps (default: empty) Optional lookup tables with the Postfix SMTP client TLS security policy by next-hop destination; when a non-empty value is specified, this overrides the obsolete smtp_tls_per_site parameter. See TLS_README for a more detailed discussion of TLS security levels. The TLS policy table is indexed by the full next-hop destination, which is either the recipient domain, or the verbatim next-hop specified in the transport table, $local_transport, $virtual_transport, $relay_transport or $default_transport. This includes any enclosing square brackets and any non-default destination server port suffix. The LMTP socket type prefix (inet: or unix:) is not included in the lookup key. Only the next-hop domain, or $myhostname with LMTP over UNIX-domain sockets, is used as the nexthop name for certificate verification. The port and any enclosing square brackets are used in the table lookup key, but are not used for server name verification. When the lookup key is a domain name without enclosing square brackets or any :port suffix (typically the recipient domain), and the full domain is not found in the table, just as with the transport(5) table, the parent domain starting with a leading "." is matched recursively. This allows one to specify a security policy for a recipient domain and all its sub-domains.

The lookup result is a security level, followed by an optional list of whitespace and/or comma separated name=value attributes that override related main.cf settings. The TLS security levels in order of increasing security are: none No TLS. No additional attributes are supported at this level. may Opportunistic TLS. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces inter-operability. The optional "ciphers", "exclude" and "protocols" attributes (available for opportunistic TLS with Postfix 2.6) override the "smtp_tls_ciphers", "smtp_tls_exclude_ciphers" and "smtp_tls_protocols" configuration parameters. When opportunistic TLS handshakes fail, Postfix retries the connection with TLS disabled. This allows mail delivery to sites with non-interoperable TLS implementations. encrypt Mandatory TLS encryption. At this level and higher, the optional "protocols" attribute overrides the main.cf smtp_tls_mandatory_protocols parameter, the optional "ciphers" attribute overrides the main.cf smtp_tls_mandatory_ciphers parameter, and the optional "exclude" attribute (Postfix 2.6) overrides the main.cf smtp_tls_mandatory_exclude_ciphers parameter. In the policy table, multiple protocols or excluded ciphers must be separated by colons, as attribute values may not contain whitespace or commas. fingerprint Certificate fingerprint verification. Available with Postfix 2.5 and later. At this security level, there are no trusted certificate authorities. The certificate trust chain, expiration date, ... are not checked. Instead, the optional match attribute, or else the main.cf smtp_tls_fingerprint_cert_match parameter, lists the valid "fingerprints" of the server certificate. The digest algorithm used to calculate the fingerprint is selected by the smtp_tls_fingerprint_digest parameter. Multiple fingerprints can be combined with a "|" delimiter in a single match attribute, or multiple match attributes can be employed. The ":" character is not used as a delimiter as it occurs between each pair of fingerprint (hexadecimal) digits. verify Mandatory TLS verification. At this security level, DNS MX lookups are trusted to be secure enough, and the name verified in the server certificate is usually obtained indirectly via unauthenticated DNS MX lookups. The optional "match" attribute overrides the main.cf smtp_tls_verify_cert_match parameter. In the policy table, multiple match patterns and strategies must be separated by colons. In practice explicit control over matching is more common with the "secure" policy, described below. secure Secure-channel TLS. At this security level, DNS MX lookups, though potentially used to determine the candidate next-hop gateway IP addresses, are not trusted to be secure enough for TLS peername verification. Instead, the default name verified in the server certificate is obtained directly from the next-hop, or is explicitly specified via the optional match attribute which overrides the main.cf smtp_tls_secure_cert_match parameter. In the policy table, multiple match patterns and strategies must be separated by colons. The match attribute is most useful when multiple domains are supported by common server, the policy entries for additional domains specify matching rules for the primary domain certificate. While transport table overrides routing the secondary domains to the primary nexthop also allow secure verification, they risk delivery to the wrong destination when domains change hands or are re-assigned to new gateways. With the "match" attribute approach, routing is not perturbed, and mail is deferred if

verification of a new MX host fails. Example:


/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy # Postfix 2.5 and later smtp_tls_fingerprint_digest = md5 /etc/postfix/tls_policy: example.edu none example.mil may example.gov encrypt protocols=TLSv1 example.com verify ciphers=high example.net secure .example.net secure match=.example.net:example.net [mail.example.org]:587 secure match=nexthop # Postfix 2.5 and later [thumb.example.org] fingerprint match=EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35 match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1

Note: The hostname strategy if listed in a non-default setting of smtp_tls_secure_cert_match or in the match attribute in the policy table can render the secure level vulnerable to DNS forgery. Do not use the hostname strategy for secure-channel configurations in environments where DNS security is not assured. This feature is available in Postfix 2.3 and later. smtp_tls_protocols (default: !SSLv2) List of TLS protocols that the Postfix SMTP client will exclude or include with opportunistic TLS encryption. Starting with Postfix 2.6, the Postfix SMTP client will by default not use the obsolete SSLv2 protocol. In main.cf the values are separated by whitespace, commas or colons. In the policy table (see smtp_tls_policy_maps) the only valid separator is colon. An empty value means allow all protocols. The valid protocol names, (see SSL_get_version(3)), are "SSLv2", "SSLv3" and "TLSv1". To include a protocol list its name, to exclude it, prefix the name with a "!" character. To exclude SSLv2 even for opportunistic TLS set "smtp_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set "smtp_tls_protocols = !SSLv2, !SSLv3". Explicitly listing the protocols to include, is supported, but not recommended. OpenSSL provides no mechanisms for excluding protocols not known at compile-time. If Postfix is linked against an OpenSSL library that supports additional protocol versions, they cannot be excluded using either syntax. Example:
# TLSv1 only! smtp_tls_protocols = !SSLv2, !SSLv3

This feature is available in Postfix 2.6 and later. smtp_tls_scert_verifydepth (default: 9)

The verification depth for remote SMTP server certificates. A depth of 1 is sufficient if the issuing CA is listed in a local CA file. The default verification depth is 9 (the OpenSSL default) for compatibility with earlier Postfix behavior. Prior to Postfix 2.5, the default value was 5, but the limit was not actually enforced. If you have set this to a lower non-default value, certificates with longer trust chains may now fail to verify. Certificate chains with 1 or 2 CAs are common, deeper chains are more rare and any number between 5 and 9 should suffice in practice. You can choose a lower number if, for example, you trust certificates directly signed by an issuing CA but not any CAs it delegates to. This feature is available in Postfix 2.2 and later. smtp_tls_secure_cert_match (default: nexthop, dot-nexthop) The server certificate peername verification method for the "secure" TLS security level. In a "secure" TLS policy table ($smtp_tls_policy_maps) entry the optional "match" attribute overrides this main.cf setting. This parameter specifies one or more patterns or strategies separated by commas, whitespace or colons. In the policy table the only valid separator is the colon character. For a description of the pattern and strategy syntax see the smtp_tls_verify_cert_match parameter. The "hostname" strategy should be avoided in this context, as in the absence of a secure global DNS, using the results of MX lookups in certificate verification is not immune to active (man-in-the-middle) attacks on DNS. Sample main.cf setting:
smtp_tls_secure_cert_match = nexthop

Sample policy table override:


example.net .example.net secure match=example.com:.example.com secure match=example.com:.example.com

This feature is available in Postfix 2.3 and later. smtp_tls_security_level (default: empty) The default SMTP TLS security level for the Postfix SMTP client; when a non-empty value is specified, this overrides the obsolete parameters smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername. Specify one of the following security levels: none TLS will not be used unless enabled for specific destinations via smtp_tls_policy_maps. may Opportunistic TLS. Use TLS if this is supported by the remote SMTP server, otherwise use plaintext. Since sending in the clear is acceptable, demanding stronger than default TLS security merely reduces inter-operability. The "smtp_tls_ciphers" and

"smtp_tls_protocols" (Postfix 2.6) configuration parameters provide control over the protocols and cipher grade used with opportunistic TLS. With earlier releases the opportunistic TLS cipher grade is always "export" and no protocols are disabled. When TLS handshakes fail, the connection is retried with TLS disabled. This allows mail delivery to sites with non-interoperable TLS implementations. encrypt Mandatory TLS encryption. Since a minimum level of security is intended, it is reasonable to be specific about sufficiently secure protocol versions and ciphers. At this security level and higher, the main.cf parameters smtp_tls_mandatory_protocols and smtp_tls_mandatory_ciphers specify the TLS protocols and minimum cipher grade which the administrator considers secure enough for mandatory encrypted sessions. This security level is not an appropriate default for systems delivering mail to the Internet. fingerprint Certificate fingerprint verification. Available with Postfix 2.5 and later. At this security level, there are no trusted certificate authorities. The certificate trust chain, expiration date, ... are not checked. Instead, the smtp_tls_fingerprint_cert_match parameter lists the valid "fingerprints" of the server certificate. The digest algorithm used to calculate the fingerprint is selected by the smtp_tls_fingerprint_digest parameter. verify Mandatory TLS verification. At this security level, DNS MX lookups are trusted to be secure enough, and the name verified in the server certificate is usually obtained indirectly via unauthenticated DNS MX lookups. The smtp_tls_verify_cert_match parameter controls how the server name is verified. In practice explicit control over matching is more common at the "secure" level, described below. This security level is not an appropriate default for systems delivering mail to the Internet. secure Secure-channel TLS. At this security level, DNS MX lookups, though potentially used to determine the candidate next-hop gateway IP addresses, are not trusted to be secure enough for TLS peername verification. Instead, the default name verified in the server certificate is obtained from the next-hop domain as specified in the smtp_tls_secure_cert_match configuration parameter. The default matching rule is that a server certificate matches when its name is equal to or is a sub-domain of the nexthop domain. This security level is not an appropriate default for systems delivering mail to the Internet. Examples:
# No TLS. Formerly: smtp_use_tls=no and smtp_enforce_tls=no. smtp_tls_security_level = none # Opportunistic TLS. smtp_tls_security_level = may # Postfix 2.6: # Do not tweak opportunistic ciphers or protocol unless it is essential # to do so (if a security vulnerability is found in the SSL library that # can be mitigated by disabling a particular protocol or raising the # cipher grade from "export" to "low" or "medium"). smtp_tls_ciphers = export smtp_tls_protocols = !SSLv2 # Mandatory (high-grade) TLS encryption. smtp_tls_security_level = encrypt smtp_tls_mandatory_ciphers = high

# Mandatory TLS verification of hostname or nexthop domain. smtp_tls_security_level = verify smtp_tls_mandatory_ciphers = high smtp_tls_verify_cert_match = hostname, nexthop, dot-nexthop # Secure channel TLS with exact nexthop name match. smtp_tls_security_level = secure smtp_tls_mandatory_protocols = TLSv1 smtp_tls_mandatory_ciphers = high smtp_tls_secure_cert_match = nexthop # Certificate fingerprint verification (Postfix 2.5). # The CA-less "fingerprint" security level only scales to a limited # number of destinations. As a global default rather than a per-site # setting, this is practical when mail for all recipients is sent # to a central mail hub. relayhost = [mailhub.example.com] smtp_tls_security_level = fingerprint smtp_tls_mandatory_protocols = !SSLv2, !SSLv3 smtp_tls_mandatory_ciphers = high smtp_tls_fingerprint_cert_match = 3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1 EC:3B:2D:B0:5B:B1:FB:6D:20:A3:9D:72:F6:8D:12:35

This feature is available in Postfix 2.3 and later. smtp_tls_session_cache_database (default: empty) Name of the file containing the optional Postfix SMTP client TLS session cache. Specify a database type that supports enumeration, such as btree or sdbm; there is no need to support concurrent access. The file is created if it does not exist. The smtp(8) daemon does not use this parameter directly, rather the cache is implemented indirectly in the tlsmgr(8) daemon. This means that per-smtp-instance master.cf overrides of this parameter are not effective. Note, that each of the cache databases supported by tlsmgr(8) daemon: $smtpd_tls_session_cache_database, $smtp_tls_session_cache_database (and with Postfix 2.3 and later $lmtp_tls_session_cache_database), needs to be stored separately. It is not at this time possible to store multiple caches in a single database. Note: dbm databases are not suitable. TLS session objects are too large. As of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non-Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. Example:
smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache

This feature is available in Postfix 2.2 and later. smtp_tls_session_cache_timeout (default: 3600s) The expiration time of Postfix SMTP client TLS session cache information. A cache cleanup is performed periodically every $smtp_tls_session_cache_timeout seconds. As with

$smtp_tls_session_cache_database, this parameter is implemented in the tlsmgr(8) daemon and therefore per-smtp-instance master.cf overrides are not possible. This feature is available in Postfix 2.2 and later. smtp_tls_verify_cert_match (default: hostname) The server certificate peername verification method for the "verify" TLS security level. In a "verify" TLS policy table ($smtp_tls_policy_maps) entry the optional "match" attribute overrides this main.cf setting. This parameter specifies one or more patterns or strategies separated by commas, whitespace or colons. In the policy table the only valid separator is the colon character. Patterns specify domain names, or domain name suffixes: example.com Match the example.com domain, i.e. one of the names the server certificate must be example.com, upper and lower case distinctions are ignored. .example.com Match subdomains of the example.com domain, i.e. match a name in the server certificate that consists of a non-zero number of labels followed by a .example.com suffix. Case distinctions are ignored. Strategies specify a transformation from the next-hop domain to the expected name in the server certificate: nexthop Match against the next-hop domain, which is either the recipient domain, or the transport next-hop configured for the domain stripped of any optional socket type prefix, enclosing square brackets and trailing port. When MX lookups are not suppressed, this is the original nexthop domain prior to the MX lookup, not the result of the MX lookup. For LMTP delivery via UNIX-domain sockets, the verified next-hop name is $myhostname. This strategy is suitable for use with the "secure" policy. Case is ignored. dot-nexthop As above, but match server certificate names that are subdomains of the next-hop domain. Case is ignored. hostname Match against the hostname of the server, often obtained via an unauthenticated DNS MX lookup. For LMTP delivery via UNIX-domain sockets, the verified name is $myhostname. This matches the verification strategy of the "MUST" keyword in the obsolete smtp_tls_per_site table, and is suitable for use with the "verify" security level. When the next-hop name is enclosed in square brackets to suppress MX lookups, the "hostname" strategy is the same as the "nexthop" strategy. Case is ignored. Sample main.cf setting:
smtp_tls_verify_cert_match = hostname, nexthop, dot-nexthop

Sample policy table override:

example.com .example.com

verify verify

match=hostname:nexthop match=example.com:.example.com:hostname

This feature is available in Postfix 2.3 and later. smtp_use_tls (default: no) Opportunistic mode: use TLS when a remote SMTP server announces STARTTLS support, otherwise send the mail in the clear. Beware: some SMTP servers offer STARTTLS even if it is not configured. With Postfix < 2.3, if the TLS handshake fails, and no other server is available, delivery is deferred and mail stays in the queue. If this is a concern for you, use the smtp_tls_per_site feature instead. This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtp_tls_security_level instead. smtp_xforward_timeout (default: 300s) The SMTP client time limit for sending the XFORWARD command, and for receiving the server response. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). This feature is available in Postfix 2.1 and later. smtpd_authorized_verp_clients (default: $authorized_verp_clients) What SMTP clients are allowed to specify the XVERP command. This command requests that mail be delivered one recipient at a time with a per recipient return address. By default, no clients are allowed to specify XVERP. This parameter was renamed with Postfix version 2.1. The default value is backwards compatible with Postfix version 2.0. Specify a list of network/netmask patterns, separated by commas and/or whitespace. The mask specifies the number of bits in the network part of a host address. You can also specify hostnames or .domain names (the initial dot causes the domain to match any name below it), "/file/name" or "type:table" patterns. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a table entry matches a lookup string (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "! pattern" to exclude an address or network block from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. Note: IP version 6 address information must be specified inside [] in the smtpd_authorized_verp_clients value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. smtpd_authorized_xclient_hosts (default: empty)

What SMTP clients are allowed to use the XCLIENT feature. This command overrides SMTP client information that is used for access control. Typical use is for SMTP-based content filters, fetchmail-like programs, or SMTP server access rule testing. See the XCLIENT_README document for details. This feature is available in Postfix 2.1 and later. By default, no clients are allowed to specify XCLIENT. Specify a list of network/netmask patterns, separated by commas and/or whitespace. The mask specifies the number of bits in the network part of a host address. You can also specify hostnames or .domain names (the initial dot causes the domain to match any name below it), "/file/name" or "type:table" patterns. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a table entry matches a lookup string (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "! pattern" to exclude an address or network block from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. Note: IP version 6 address information must be specified inside [] in the smtpd_authorized_xclient_hosts value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. smtpd_authorized_xforward_hosts (default: empty) What SMTP clients are allowed to use the XFORWARD feature. This command forwards information that is used to improve logging after SMTP-based content filters. See the XFORWARD_README document for details. This feature is available in Postfix 2.1 and later. By default, no clients are allowed to specify XFORWARD. Specify a list of network/netmask patterns, separated by commas and/or whitespace. The mask specifies the number of bits in the network part of a host address. You can also specify hostnames or .domain names (the initial dot causes the domain to match any name below it), "/file/name" or "type:table" patterns. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a table entry matches a lookup string (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "! pattern" to exclude an address or network block from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. Note: IP version 6 address information must be specified inside [] in the smtpd_authorized_xforward_hosts value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. smtpd_banner (default: $myhostname ESMTP $mail_name) The text that follows the 220 status code in the SMTP greeting banner. Some people like to see the mail version advertised. By default, Postfix shows no version.

You MUST specify $myhostname at the start of the text. This is required by the SMTP protocol. Example:
smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)

smtpd_client_connection_count_limit (default: 50) How many simultaneous connections any client is allowed to make to this service. By default, the limit is set to half the default process limit value. To disable this feature, specify a limit of 0. WARNING: The purpose of this feature is to limit abuse. It must not be used to regulate legitimate mail traffic. This feature is available in Postfix 2.2 and later. smtpd_client_connection_rate_limit (default: 0) The maximal number of connection attempts any client is allowed to make to this service per time unit. The time unit is specified with the anvil_rate_time_unit configuration parameter. By default, a client can make as many connections per time unit as Postfix can accept. To disable this feature, specify a limit of 0. WARNING: The purpose of this feature is to limit abuse. It must not be used to regulate legitimate mail traffic. This feature is available in Postfix 2.2 and later. Example:
smtpd_client_connection_rate_limit = 1000

smtpd_client_event_limit_exceptions (default: $mynetworks) Clients that are excluded from smtpd_client_*_count/rate_limit restrictions. See the mynetworks parameter description for the parameter value syntax. By default, clients in trusted networks are excluded. Specify a list of network blocks, hostnames or .domain names (the initial dot causes the domain to match any name below it). Note: IP version 6 address information must be specified inside [] in the smtpd_client_event_limit_exceptions value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. This feature is available in Postfix 2.2 and later.

smtpd_client_message_rate_limit (default: 0) The maximal number of message delivery requests that any client is allowed to make to this service per time unit, regardless of whether or not Postfix actually accepts those messages. The time unit is specified with the anvil_rate_time_unit configuration parameter. By default, a client can send as many message delivery requests per time unit as Postfix can accept. To disable this feature, specify a limit of 0. WARNING: The purpose of this feature is to limit abuse. It must not be used to regulate legitimate mail traffic. This feature is available in Postfix 2.2 and later. Example:
smtpd_client_message_rate_limit = 1000

smtpd_client_new_tls_session_rate_limit (default: 0) The maximal number of new (i.e., uncached) TLS sessions that a remote SMTP client is allowed to negotiate with this service per time unit. The time unit is specified with the anvil_rate_time_unit configuration parameter. By default, a remote SMTP client can negotiate as many new TLS sessions per time unit as Postfix can accept. To disable this feature, specify a limit of 0. Otherwise, specify a limit that is at least the perclient concurrent session limit, or else legitimate client sessions may be rejected. WARNING: The purpose of this feature is to limit abuse. It must not be used to regulate legitimate mail traffic. This feature is available in Postfix 2.3 and later. Example:
smtpd_client_new_tls_session_rate_limit = 100

smtpd_client_port_logging (default: no) Enable logging of the remote SMTP client port in addition to the hostname and IP address. The logging format is "host[address]:port". This feature is available in Postfix 2.5 and later. smtpd_client_recipient_rate_limit (default: 0) The maximal number of recipient addresses that any client is allowed to send to this service per time unit, regardless of whether or not Postfix actually accepts those recipients. The time

unit is specified with the anvil_rate_time_unit configuration parameter. By default, a client can send as many recipient addresses per time unit as Postfix can accept. To disable this feature, specify a limit of 0. WARNING: The purpose of this feature is to limit abuse. It must not be used to regulate legitimate mail traffic. This feature is available in Postfix 2.2 and later. Example:
smtpd_client_recipient_rate_limit = 1000

smtpd_client_restrictions (default: empty) Optional SMTP server access restrictions in the context of a client SMTP connection request. See SMTPD_ACCESS_README, section "Delayed evaluation of SMTP access restriction lists" for a discussion of evaluation context and time. The default is to allow all connection requests. Specify a list of restrictions, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace. Restrictions are applied in the order as specified; the first restriction that matches wins. The following restrictions are specific to client hostname or client network address information. check_ccert_access type:table Use the client certificate fingerprint as lookup key for the specified access(5) database; with Postfix version 2.2, also require that the SMTP client certificate is verified successfully. The fingerprint digest algorithm is configurable via the smtpd_tls_fingerprint_digest parameter (hard-coded as md5 prior to Postfix version 2.5). This feature is available with Postfix version 2.2 and later. check_client_access type:table Search the specified access database for the client hostname, parent domains, client IP address, or networks obtained by stripping least significant octets. See the access(5) manual page for details. check_client_mx_access type:table Search the specified access(5) database for the MX hosts for the client hostname, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.7 and later. check_client_ns_access type:table Search the specified access(5) database for the DNS servers for the client hostname, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.7 and later. check_reverse_client_hostname_access type:table Search the specified access database for the unverified reverse client hostname, parent

domains, client IP address, or networks obtained by stripping least significant octets. See the access(5) manual page for details. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.6 and later. check_reverse_client_hostname_mx_access type:table Search the specified access(5) database for the MX hosts for the unverified reverse client hostname, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.7 and later. check_reverse_client_hostname_ns_access type:table Search the specified access(5) database for the DNS servers for the unverified reverse client hostname, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.7 and later. permit_inet_interfaces Permit the request when the client IP address matches $inet_interfaces. permit_mynetworks Permit the request when the client IP address matches any network or network address listed in $mynetworks. permit_sasl_authenticated Permit the request when the client is successfully authenticated via the RFC 4954 (AUTH) protocol. permit_tls_all_clientcerts Permit the request when the remote SMTP client certificate is verified successfully. This option must be used only if a special CA issues the certificates and only this CA is listed as trusted CA. Otherwise, clients with a third-party certificate would also be allowed to relay. Specify "tls_append_default_CA = no" when the trusted CA is specified with smtpd_tls_CAfile or smtpd_tls_CApath, to prevent Postfix from appending the systemsupplied default CAs. This feature is available with Postfix version 2.2. permit_tls_clientcerts Permit the request when the remote SMTP client certificate fingerprint is listed in $relay_clientcerts. The fingerprint digest algorithm is configurable via the smtpd_tls_fingerprint_digest parameter (hard-coded as md5 prior to Postfix version 2.5). This feature is available with Postfix version 2.2. reject_rbl_client rbl_domain=d.d.d.d Reject the request when the reversed client network address is listed with the A record "d.d.d.d" under rbl_domain (Postfix version 2.1 and later only). If no "=d.d.d.d" is specified, reject the request when the reversed client network address is listed with any A record under rbl_domain. The maps_rbl_reject_code parameter specifies the response code for rejected requests (default: 554), the default_rbl_reply parameter specifies the default server reply, and the rbl_reply_maps parameter specifies tables with server replies indexed by rbl_domain. This feature is available in Postfix 2.0 and later. reject_rhsbl_client rbl_domain=d.d.d.d Reject the request when the client hostname is listed with the A record "d.d.d.d" under rbl_domain (Postfix version 2.1 and later only). If no "=d.d.d.d" is specified, reject the request when the client hostname is listed with any A record under rbl_domain. See the reject_rbl_client description above for additional RBL related configuration parameters. This feature is available in Postfix 2.0 and later; with Postfix version 2.8 and later, reject_rhsbl_reverse_client will usually produce better results. reject_rhsbl_reverse_client rbl_domain=d.d.d.d Reject the request when the unverified reverse client hostname is listed with the A

record "d.d.d.d" under rbl_domain. If no "=d.d.d.d" is specified, reject the request when the unverified reverse client hostname is listed with any A record under rbl_domain. See the reject_rbl_client description above for additional RBL related configuration parameters. This feature is available in Postfix 2.8 and later. reject_unknown_client_hostname (with Postfix < 2.3: reject_unknown_client) Reject the request when 1) the client IP address->name mapping fails, 2) the name>address mapping fails, or 3) the name->address mapping does not match the client IP address. This is a stronger restriction than the reject_unknown_reverse_client_hostname feature, which triggers only under condition 1) above. The unknown_client_reject_code parameter specifies the response code for rejected requests (default: 450). The reply is always 450 in case the address->name or name>address lookup failed due to a temporary problem. reject_unknown_reverse_client_hostname Reject the request when the client IP address has no address->name mapping. This is a weaker restriction than the reject_unknown_client_hostname feature, which requires not only that the address->name and name->address mappings exist, but also that the two mappings reproduce the client IP address. The unknown_client_reject_code parameter specifies the response code for rejected requests (default: 450). The reply is always 450 in case the address->name lookup failed due to a temporary problem. This feature is available in Postfix 2.3 and later. In addition, you can use any of the following generic restrictions. These restrictions are applicable in any SMTP command context. check_policy_service servername Query the specified policy server. See the SMTPD_POLICY_README document for details. This feature is available in Postfix 2.1 and later. defer Defer the request. The client is told to try again later. This restriction is useful at the end of a restriction list, to make the default policy explicit. The defer_code parameter specifies the SMTP server reply code (default: 450). defer_if_permit Defer the request if some later restriction would result in an explicit or implicit PERMIT action. This is useful when a blacklisting feature fails due to a temporary problem. This feature is available in Postfix version 2.1 and later. defer_if_reject Defer the request if some later restriction would result in a REJECT action. This is useful when a whitelisting feature fails due to a temporary problem. This feature is available in Postfix version 2.1 and later. permit Permit the request. This restriction is useful at the end of a restriction list, to make the default policy explicit. reject_multi_recipient_bounce Reject the request when the envelope sender is the null address, and the message has multiple envelope recipients. This usage has rare but legitimate applications: under certain conditions, multi-recipient mail that was posted with the DSN option NOTIFY=NEVER may be forwarded with the null sender address. Note: this restriction can only work reliably when used in smtpd_data_restrictions or smtpd_end_of_data_restrictions, because the total number of recipients is not known at an earlier stage of the SMTP conversation. Use at the RCPT stage will only reject the

second etc. recipient. The multi_recipient_bounce_reject_code parameter specifies the response code for rejected requests (default: 550). This feature is available in Postfix 2.1 and later. reject_plaintext_session Reject the request when the connection is not encrypted. This restriction should not be used before the client has had a chance to negotiate encryption with the AUTH or STARTTLS commands. The plaintext_reject_code parameter specifies the response code for rejected requests (default: 450). This feature is available in Postfix 2.3 and later. reject_unauth_pipelining Reject the request when the client sends SMTP commands ahead of time where it is not allowed, or when the client sends SMTP commands ahead of time without knowing that Postfix actually supports ESMTP command pipelining. This stops mail from bulk mail software that improperly uses ESMTP command pipelining in order to speed up deliveries. With Postfix 2.6 and later, the SMTP server sets a per-session flag whenever it detects illegal pipelining, including pipelined EHLO or HELO commands. The reject_unauth_pipelining feature simply tests whether the flag was set at any point in time during the session. With older Postfix versions, reject_unauth_pipelining checks the current status of the input read queue, and its usage is not recommended in contexts other than smtpd_data_restrictions. reject Reject the request. This restriction is useful at the end of a restriction list, to make the default policy explicit. The reject_code configuration parameter specifies the response code for rejected requests (default: 554). sleep seconds Pause for the specified number of seconds and proceed with the next restriction in the list, if any. This may stop zombie mail when used as:
/etc/postfix/main.cf: smtpd_client_restrictions = sleep 1, reject_unauth_pipelining smtpd_delay_reject = no

This feature is available in Postfix 2.3. warn_if_reject Change the meaning of the next restriction, so that it logs a warning instead of rejecting a request (look for logfile records that contain "reject_warning"). This is useful for testing new restrictions in a "live" environment without risking unnecessary loss of mail. Other restrictions that are valid in this context: SMTP command specific restrictions that are described under the smtpd_helo_restrictions, smtpd_sender_restrictions or smtpd_recipient_restrictions parameters. When helo, sender or recipient restrictions are listed under smtpd_client_restrictions, they have effect only with "smtpd_delay_reject = yes", so that $smtpd_client_restrictions is evaluated at the time of the RCPT TO command. Example:
smtpd_client_restrictions = permit_mynetworks,

reject_unknown_client_hostname

smtpd_command_filter (default: empty) A mechanism to transform commands from remote SMTP clients. This is a last-resort tool to work around client commands that break inter-operability with the Postfix SMTP server. Other uses involve fault injection to test Postfix's handling of invalid commands. Specify the name of a "type:table" lookup table. The search string is the SMTP command as received from the remote SMTP client, except that initial whitespace and the trailing <CR><LF> are removed. The result value is executed by the Postfix SMTP server. There is no need to use smtpd_command_filter for the following cases: Use "resolve_numeric_domain = yes" to accept "user@ipaddress". Postfix already accepts the correct form "user@[ipaddress]". Use virtual_alias_maps or canonical_maps to translate these into domain names if necessary. Use "strict_rfc821_envelopes = no" to accept "RCPT TO:<User Name <user@example.com>>". Postfix will ignore the "User Name" part and deliver to the <user@example.com> address. Examples of problems that can be solved with the smtpd_command_filter feature:
/etc/postfix/main.cf: smtpd_command_filter = pcre:/etc/postfix/command_filter /etc/postfix/command_filter: # Work around clients that send malformed HELO commands. /^HELO\s*$/ HELO domain.invalid # Work around clients that send empty lines. /^\s*$/ NOOP # Work around clients that send RCPT TO:<'user@domain'>. # WARNING: do not lose the parameters that follow the address. /^RCPT\s+TO:\s*<'([^[:space:]]+)'>(.*)/ RCPT TO:<$1>$2 # Bounce-never mail sink. Use notify_classes=bounce,resource,software # to send bounced mail to the postmaster (with message body removed). /^(RCPT\s+TO:.*?)\bNOTIFY=\S+\b(.*)/ $1 NOTIFY=NEVER $2 /^(RCPT\s+TO:.*)/ $1 NOTIFY=NEVER

This feature is available in Postfix 2.7. smtpd_data_restrictions (default: empty) Optional access restrictions that the Postfix SMTP server applies in the context of the SMTP DATA command. See SMTPD_ACCESS_README, section "Delayed evaluation of SMTP access restriction lists" for a discussion of evaluation context and time. This feature is available in Postfix 2.0 and later.

Specify a list of restrictions, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace. Restrictions are applied in the order as specified; the first restriction that matches wins. The following restrictions are valid in this context: Generic restrictions that can be used in any SMTP command context, described under smtpd_client_restrictions. SMTP command specific restrictions described under smtpd_client_restrictions, smtpd_helo_restrictions, smtpd_sender_restrictions or smtpd_recipient_restrictions. However, no recipient information is available in the case of multi-recipient mail. Acting on only one recipient would be misleading, because any decision will affect all recipients equally. Acting on all recipients would require a possibly very large amount of memory, and would also be misleading for the reasons mentioned before. Examples:
smtpd_data_restrictions = reject_unauth_pipelining smtpd_data_restrictions = reject_multi_recipient_bounce

smtpd_delay_open_until_valid_rcpt (default: yes) Postpone the start of an SMTP mail transaction until a valid RCPT TO command is received. Specify "no" to create a mail transaction as soon as the SMTP server receives a valid MAIL FROM command. With sites that reject lots of mail, the default setting reduces the use of disk, CPU and memory resources. The downside is that rejected recipients are logged with NOQUEUE instead of a mail transaction ID. This complicates the logfile analysis of multi-recipient mail. This feature is available in Postfix 2.3 and later. smtpd_delay_reject (default: yes) Wait until the RCPT TO command before evaluating $smtpd_client_restrictions, $smtpd_helo_restrictions and $smtpd_sender_restrictions, or wait until the ETRN command before evaluating $smtpd_client_restrictions and $smtpd_helo_restrictions. This feature is turned on by default because some clients apparently mis-behave when the Postfix SMTP server rejects commands before RCPT TO. The default setting has one major benefit: it allows Postfix to log recipient address information when rejecting a client name/address or sender address, so that it is possible to find out whose mail is being rejected. smtpd_discard_ehlo_keyword_address_maps (default: empty) Lookup tables, indexed by the remote SMTP client address, with case insensitive lists of EHLO keywords (pipelining, starttls, auth, etc.) that the SMTP server will not send in the EHLO response to a remote SMTP client. See smtpd_discard_ehlo_keywords for details. The table is not searched by hostname for robustness reasons.

This feature is available in Postfix 2.2 and later. smtpd_discard_ehlo_keywords (default: empty) A case insensitive list of EHLO keywords (pipelining, starttls, auth, etc.) that the SMTP server will not send in the EHLO response to a remote SMTP client. This feature is available in Postfix 2.2 and later. Notes: Specify the silent-discard pseudo keyword to prevent this action from being logged. Use the smtpd_discard_ehlo_keyword_address_maps feature to discard EHLO keywords selectively. smtpd_end_of_data_restrictions (default: empty) Optional access restrictions that the Postfix SMTP server applies in the context of the SMTP END-OF-DATA command. See SMTPD_ACCESS_README, section "Delayed evaluation of SMTP access restriction lists" for a discussion of evaluation context and time. This feature is available in Postfix 2.2 and later. See smtpd_data_restrictions for details and limitations. smtpd_enforce_tls (default: no) Mandatory TLS: announce STARTTLS support to SMTP clients, and require that clients use TLS encryption. According to RFC 2487 this MUST NOT be applied in case of a publiclyreferenced SMTP server. This option is off by default and should be used only on dedicated servers. Note 1: "smtpd_enforce_tls = yes" implies "smtpd_tls_auth_only = yes". Note 2: when invoked via "sendmail -bs", Postfix will never offer STARTTLS due to insufficient privileges to access the server private key. This is intended behavior. This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtpd_tls_security_level instead. smtpd_error_sleep_time (default: 1s) With Postfix version 2.1 and later: the SMTP server response delay after a client has made more than $smtpd_soft_error_limit errors, and fewer than $smtpd_hard_error_limit errors, without delivering mail. With Postfix version 2.0 and earlier: the SMTP server delay before sending a reject (4xx or 5xx) response, when the client has made fewer than $smtpd_soft_error_limit errors without delivering mail. smtpd_etrn_restrictions (default: empty)

Optional SMTP server access restrictions in the context of a client ETRN request. See SMTPD_ACCESS_README, section "Delayed evaluation of SMTP access restriction lists" for a discussion of evaluation context and time. The Postfix ETRN implementation accepts only destinations that are eligible for the Postfix "fast flush" service. See the ETRN_README file for details. Specify a list of restrictions, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace. Restrictions are applied in the order as specified; the first restriction that matches wins. The following restrictions are specific to the domain name information received with the ETRN command. check_etrn_access type:table Search the specified access database for the ETRN domain name or its parent domains. See the access(5) manual page for details. Other restrictions that are valid in this context: Generic restrictions that can be used in any SMTP command context, described under smtpd_client_restrictions. SMTP command specific restrictions described under smtpd_client_restrictions and smtpd_helo_restrictions. Example:
smtpd_etrn_restrictions = permit_mynetworks, reject

smtpd_expansion_filter (default: see "postconf -d" output) What characters are allowed in $name expansions of RBL reply templates. Characters not in the allowed set are replaced by "_". Use C like escapes to specify special characters such as whitespace. This parameter is not subjected to $parameter expansion. This feature is available in Postfix 2.0 and later. smtpd_forbidden_commands (default: CONNECT, GET, POST) List of commands that causes the Postfix SMTP server to immediately terminate the session with a 221 code. This can be used to disconnect clients that obviously attempt to abuse the system. In addition to the commands listed in this parameter, commands that follow the "Label:" format of message headers will also cause a disconnect. This feature is available in Postfix 2.2 and later. smtpd_hard_error_limit (default: normal: 20, overload: 1) The maximal number of errors a remote SMTP client is allowed to make without delivering mail. The Postfix SMTP server disconnects when the limit is exceeded. Normally the default

limit is 20, but it changes under overload to just 1. With Postfix 2.5 and earlier, the SMTP server always allows up to 20 errors by default. smtpd_helo_required (default: no) Require that a remote SMTP client introduces itself with the HELO or EHLO command before sending the MAIL command or other commands that require EHLO negotiation. Example:
smtpd_helo_required = yes

smtpd_helo_restrictions (default: empty) Optional restrictions that the Postfix SMTP server applies in the context of the SMTP HELO command. See SMTPD_ACCESS_README, section "Delayed evaluation of SMTP access restriction lists" for a discussion of evaluation context and time. The default is to permit everything. Specify a list of restrictions, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace. Restrictions are applied in the order as specified; the first restriction that matches wins. The following restrictions are specific to the hostname information received with the HELO or EHLO command. check_helo_access type:table Search the specified access(5) database for the HELO or EHLO hostname or parent domains, and execute the corresponding action. check_helo_mx_access type:table Search the specified access(5) database for the MX hosts for the HELO or EHLO hostname, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.1 and later. check_helo_ns_access type:table Search the specified access(5) database for the DNS servers for the HELO or EHLO hostname, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.1 and later. reject_invalid_helo_hostname (with Postfix < 2.3: reject_invalid_hostname) Reject the request when the HELO or EHLO hostname syntax is invalid. The invalid_hostname_reject_code specifies the response code for rejected requests (default: 501). reject_non_fqdn_helo_hostname (with Postfix < 2.3: reject_non_fqdn_hostname) Reject the request when the HELO or EHLO hostname is not in fully-qualified domain form, as required by the RFC. The non_fqdn_reject_code parameter specifies the response code for rejected requests (default: 504). reject_rhsbl_helo rbl_domain=d.d.d.d Reject the request when the HELO or EHLO hostname hostname is listed with the A record "d.d.d.d" under rbl_domain (Postfix version 2.1 and later only). If no "=d.d.d.d"

is specified, reject the request when the HELO or EHLO hostname is listed with any A record under rbl_domain. See the reject_rbl_client description for additional RBL related configuration parameters. This feature is available in Postfix 2.0 and later. reject_unknown_helo_hostname (with Postfix < 2.3: reject_unknown_hostname) Reject the request when the HELO or EHLO hostname has no DNS A or MX record. The unknown_hostname_reject_code parameter specifies the numerical response code for rejected requests (default: 450). The unknown_helo_hostname_tempfail_action parameter specifies the action after a temporary DNS error (default: defer_if_permit). Other restrictions that are valid in this context: Generic restrictions that can be used in any SMTP command context, described under smtpd_client_restrictions. Client hostname or network address specific restrictions described under smtpd_client_restrictions. SMTP command specific restrictions described under smtpd_sender_restrictions or smtpd_recipient_restrictions. When sender or recipient restrictions are listed under smtpd_helo_restrictions, they have effect only with "smtpd_delay_reject = yes", so that $smtpd_helo_restrictions is evaluated at the time of the RCPT TO command. Examples:
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname smtpd_helo_restrictions = permit_mynetworks, reject_unknown_helo_hostname

smtpd_history_flush_threshold (default: 100) The maximal number of lines in the Postfix SMTP server command history before it is flushed upon receipt of EHLO, RSET, or end of DATA. smtpd_junk_command_limit (default: normal: 100, overload: 1) The number of junk commands (NOOP, VRFY, ETRN or RSET) that a remote SMTP client can send before the Postfix SMTP server starts to increment the error counter with each junk command. The junk command count is reset after mail is delivered. See also the smtpd_error_sleep_time and smtpd_soft_error_limit configuration parameters. Normally the default limit is 100, but it changes under overload to just 1. With Postfix 2.5 and earlier, the SMTP server always allows up to 100 junk commands by default. smtpd_milters (default: empty) A list of Milter (mail filter) applications for new mail that arrives via the Postfix smtpd(8) server. See the MILTER_README document for details. This feature is available in Postfix 2.3 and later. smtpd_noop_commands (default: empty) List of commands that the Postfix SMTP server replies to with "250 Ok", without doing any syntax checks and without changing state. This list overrides any commands built into the Postfix SMTP server.

smtpd_null_access_lookup_key (default: <>) The lookup key to be used in SMTP access(5) tables instead of the null sender address. smtpd_peername_lookup (default: yes) Attempt to look up the remote SMTP client hostname, and verify that the name matches the client IP address. A client name is set to "unknown" when it cannot be looked up or verified, or when name lookup is disabled. Turning off name lookup reduces delays due to DNS lookup and increases the maximal inbound delivery rate. This feature is available in Postfix 2.3 and later. smtpd_policy_service_max_idle (default: 300s) The time after which an idle SMTPD policy service connection is closed. This feature is available in Postfix 2.1 and later. smtpd_policy_service_max_ttl (default: 1000s) The time after which an active SMTPD policy service connection is closed. This feature is available in Postfix 2.1 and later. smtpd_policy_service_timeout (default: 100s) The time limit for connecting to, writing to or receiving from a delegated SMTPD policy server. This feature is available in Postfix 2.1 and later. smtpd_proxy_ehlo (default: $myhostname) How the Postfix SMTP server announces itself to the proxy filter. By default, the Postfix hostname is used. This feature is available in Postfix 2.1 and later. smtpd_proxy_filter (default: empty) The hostname and TCP port of the mail filtering proxy server. The proxy receives all mail from the Postfix SMTP server, and is supposed to give the result to another Postfix SMTP server process. Specify "host:port" or "inet:host:port" for a TCP endpoint, or "unix:pathname" for a UNIXdomain endpoint. The host can be specified as an IP address or as a symbolic name; no MX lookups are done. When no "host" or "host:" are specified, the local machine is assumed. Pathname interpretation is relative to the Postfix queue directory. This feature is available in Postfix 2.1 and later.

The "inet:" and "unix:" prefixes are available in Postfix 2.3 and later. smtpd_proxy_options (default: empty) List of options that control how the Postfix SMTP server communicates with a before-queue content filter. Specify zero or more of the following, separated by comma or whitespace. speed_adjust Do not connect to a before-queue content filter until an entire message has been received. This reduces the number of simultaneous before-queue content filter processes. NOTE 1: A filter must not selectively reject recipients of a multi-recipient message. Rejecting all recipients is OK, as is accepting all recipients. NOTE 2: This feature increases the minimum amount of free queue space by $message_size_limit. The extra space is needed to save the message to a temporary file. This feature is available in Postfix 2.7 and later. smtpd_proxy_timeout (default: 100s) The time limit for connecting to a proxy filter and for sending or receiving information. When a connection fails the client gets a generic error message while more detailed information is logged to the maillog file. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). This feature is available in Postfix 2.1 and later. smtpd_recipient_limit (default: 1000) The maximal number of recipients that the Postfix SMTP server accepts per message delivery request. smtpd_recipient_overshoot_limit (default: 1000) The number of recipients that a remote SMTP client can send in excess of the limit specified with $smtpd_recipient_limit, before the Postfix SMTP server increments the per-session error count for each excess recipient. smtpd_recipient_restrictions (default: permit_mynetworks, reject_unauth_destination) The access restrictions that the Postfix SMTP server applies in the context of the RCPT TO command. See SMTPD_ACCESS_README, section "Delayed evaluation of SMTP access restriction lists" for a discussion of evaluation context and time. By default, the Postfix SMTP server accepts: Mail from clients whose IP address matches $mynetworks, or:

Mail to remote destinations that match $relay_domains, except for addresses that contain sender-specified routing (user@elsewhere@domain), or: Mail to local destinations that match $inet_interfaces or $proxy_interfaces, $mydestination, $virtual_alias_domains, or $virtual_mailbox_domains. IMPORTANT: If you change this parameter setting, you must specify at least one of the following restrictions. Otherwise Postfix will refuse to receive mail:
reject, defer, defer_if_permit, reject_unauth_destination

Specify a list of restrictions, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace. Restrictions are applied in the order as specified; the first restriction that matches wins. The following restrictions are specific to the recipient address that is received with the RCPT TO command. check_recipient_access type:table Search the specified access(5) database for the resolved RCPT TO address, domain, parent domains, or localpart@, and execute the corresponding action. check_recipient_mx_access type:table Search the specified access(5) database for the MX hosts for the RCPT TO domain, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.1 and later. check_recipient_ns_access type:table Search the specified access(5) database for the DNS servers for the RCPT TO domain, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.1 and later. permit_auth_destination Permit the request when one of the following is true: Postfix is mail forwarder: the resolved RCPT TO domain matches $relay_domains or a subdomain thereof, and the address contains no senderspecified routing (user@elsewhere@domain), Postfix is the final destination: the resolved RCPT TO domain matches $mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, or $virtual_mailbox_domains, and the address contains no sender-specified routing (user@elsewhere@domain). permit_mx_backup Permit the request when the local mail system is backup MX for the RCPT TO domain, or when the domain is an authorized destination (see permit_auth_destination for definition). Safety: permit_mx_backup does not accept addresses that have sender-specified routing information (example: user@elsewhere@domain). Safety: permit_mx_backup can be vulnerable to mis-use when access is not restricted with permit_mx_backup_networks. Safety: as of Postfix version 2.3, permit_mx_backup no longer accepts the address when the local mail system is primary MX for the recipient domain. Exception: permit_mx_backup accepts the address when it specifies an authorized destination (see permit_auth_destination for definition). Limitation: mail may be rejected in case of a temporary DNS lookup problem

with Postfix prior to version 2.0. reject_non_fqdn_recipient Reject the request when the RCPT TO address is not in fully-qualified domain form, as required by the RFC. The non_fqdn_reject_code parameter specifies the response code for rejected requests (default: 504). reject_rhsbl_recipient rbl_domain=d.d.d.d Reject the request when the RCPT TO domain is listed with the A record "d.d.d.d" under rbl_domain (Postfix version 2.1 and later only). If no "=d.d.d.d" is specified, reject the request when the RCPT TO domain is listed with any A record under rbl_domain. The maps_rbl_reject_code parameter specifies the response code for rejected requests (default: 554); the default_rbl_reply parameter specifies the default server reply; and the rbl_reply_maps parameter specifies tables with server replies indexed by rbl_domain. This feature is available in Postfix version 2.0 and later. reject_unauth_destination Reject the request unless one of the following is true: Postfix is mail forwarder: the resolved RCPT TO domain matches $relay_domains or a subdomain thereof, and contains no sender-specified routing (user@elsewhere@domain), Postfix is the final destination: the resolved RCPT TO domain matches $mydestination, $inet_interfaces, $proxy_interfaces, $virtual_alias_domains, or $virtual_mailbox_domains, and contains no sender-specified routing (user@elsewhere@domain). The relay_domains_reject_code parameter specifies the response code for rejected requests (default: 554). reject_unknown_recipient_domain Reject the request when Postfix is not final destination for the recipient domain, and the RCPT TO domain has no DNS A or MX record, or when it has a malformed MX record such as a record with a zero-length MX hostname (Postfix version 2.3 and later). The unknown_address_reject_code parameter specifies the numerical response code for rejected requests (default: 450). The response is always 450 in case of a temporary DNS error. The unknown_address_tempfail_action parameter specifies the action after a temporary DNS error (default: defer_if_permit). reject_unlisted_recipient (with Postfix version 2.0: check_recipient_maps) Reject the request when the RCPT TO address is not listed in the list of valid recipients for its domain class. See the smtpd_reject_unlisted_recipient parameter description for details. This feature is available in Postfix 2.1 and later. reject_unverified_recipient Reject the request when mail to the RCPT TO address is known to bounce, or when the recipient address destination is not reachable. Address verification information is managed by the verify(8) server; see the ADDRESS_VERIFICATION_README file for details. The unverified_recipient_reject_code parameter specifies the numerical response code when an address is known to bounce (default: 450, change into 550 when you are confident that it is safe to do so). The unverified_recipient_defer_code parameter specifies the numerical response code when an address probe failed due to a temporary problem (default: 450). The unverified_recipient_tempfail_action parameter specifies the action after addres probe failure due to a temporary problem (default: defer_if_permit). This feature is available in Postfix 2.1 and later.

Other restrictions that are valid in this context: Generic restrictions that can be used in any SMTP command context, described under smtpd_client_restrictions. SMTP command specific restrictions described under smtpd_client_restrictions, smtpd_helo_restrictions and smtpd_sender_restrictions. Example:
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination

smtpd_reject_unlisted_recipient (default: yes) Request that the Postfix SMTP server rejects mail for unknown recipient addresses, even when no explicit reject_unlisted_recipient access restriction is specified. This prevents the Postfix queue from filling up with undeliverable MAILER-DAEMON messages. An address is always considered "known" when it matches a virtual(5) alias or a canonical(5) mapping. The recipient domain matches $mydestination, $inet_interfaces or $proxy_interfaces, but the recipient is not listed in $local_recipient_maps, and $local_recipient_maps is not null. The recipient domain matches $virtual_alias_domains but the recipient is not listed in $virtual_alias_maps. The recipient domain matches $virtual_mailbox_domains but the recipient is not listed in $virtual_mailbox_maps, and $virtual_mailbox_maps is not null. The recipient domain matches $relay_domains but the recipient is not listed in $relay_recipient_maps, and $relay_recipient_maps is not null. This feature is available in Postfix 2.1 and later. smtpd_reject_unlisted_sender (default: no) Request that the Postfix SMTP server rejects mail from unknown sender addresses, even when no explicit reject_unlisted_sender access restriction is specified. This can slow down an explosion of forged mail from worms or viruses. An address is always considered "known" when it matches a virtual(5) alias or a canonical(5) mapping. The sender domain matches $mydestination, $inet_interfaces or $proxy_interfaces, but the sender is not listed in $local_recipient_maps, and $local_recipient_maps is not null. The sender domain matches $virtual_alias_domains but the sender is not listed in $virtual_alias_maps. The sender domain matches $virtual_mailbox_domains but the sender is not listed in $virtual_mailbox_maps, and $virtual_mailbox_maps is not null. The sender domain matches $relay_domains but the sender is not listed in $relay_recipient_maps, and $relay_recipient_maps is not null.

This feature is available in Postfix 2.1 and later. smtpd_restriction_classes (default: empty) User-defined aliases for groups of access restrictions. The aliases can be specified in smtpd_recipient_restrictions etc., and on the right-hand side of a Postfix access(5) table. One major application is for implementing per-recipient UCE control. See the RESTRICTION_CLASS_README document for other examples. smtpd_sasl_application_name (default: smtpd) The application name that the Postfix SMTP server uses for SASL server initialization. This controls the name of the SASL configuration file. The default value is smtpd, corresponding to a SASL configuration file named smtpd.conf. This feature is available in Postfix 2.1 and 2.2. With Postfix 2.3 it was renamed to smtpd_sasl_path. smtpd_sasl_auth_enable (default: no) Enable SASL authentication in the Postfix SMTP server. By default, the Postfix SMTP server does not use authentication. If a remote SMTP client is authenticated, the permit_sasl_authenticated access restriction can be used to permit relay access, like this:
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, ...

To reject all SMTP connections from unauthenticated clients, specify "smtpd_delay_reject = yes" (which is the default) and use:
smtpd_client_restrictions = permit_sasl_authenticated, reject

See the SASL_README file for SASL configuration and operation details. smtpd_sasl_authenticated_header (default: no) Report the SASL authenticated user name in the smtpd(8) Received message header. This feature is available in Postfix 2.3 and later. smtpd_sasl_exceptions_networks (default: empty) What remote SMTP clients the Postfix SMTP server will not offer AUTH support to. Some clients (Netscape 4 at least) have a bug that causes them to require a login and password whenever AUTH is offered, whether it's necessary or not. To work around this, specify, for example, $mynetworks to prevent Postfix from offering AUTH to local clients. Specify a list of network/netmask patterns, separated by commas and/or whitespace. The

mask specifies the number of bits in the network part of a host address. You can also "/file/name" or "type:table" patterns. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a table entry matches a lookup string (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "! pattern" to exclude an address or network block from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. Note: IP version 6 address information must be specified inside [] in the smtpd_sasl_exceptions_networks value, and in files specified with "/file/name". IP version 6 addresses contain the ":" character, and would otherwise be confused with a "type:table" pattern. Example:
smtpd_sasl_exceptions_networks = $mynetworks

This feature is available in Postfix 2.1 and later. smtpd_sasl_local_domain (default: empty) The name of the Postfix SMTP server's local SASL authentication realm. By default, the local authentication realm name is the null string. Examples:
smtpd_sasl_local_domain = $mydomain smtpd_sasl_local_domain = $myhostname

smtpd_sasl_path (default: smtpd) Implementation-specific information that the Postfix SMTP server passes through to the SASL plug-in implementation that is selected with smtpd_sasl_type. Typically this specifies the name of a configuration file or rendezvous point. This feature is available in Postfix 2.3 and later. In earlier releases it was called smtpd_sasl_application_name. smtpd_sasl_security_options (default: noanonymous) Postfix SMTP server SASL security options; as of Postfix 2.3 the list of available features depends on the SASL server implementation that is selected with smtpd_sasl_type. The following security features are defined for the cyrus server SASL implementation: Restrict what authentication mechanisms the Postfix SMTP server will offer to the client. The list of available authentication mechanisms is system dependent. Specify zero or more of the following: noplaintext Disallow methods that use plaintext passwords.

noactive Disallow methods subject to active (non-dictionary) attack. nodictionary Disallow methods subject to passive (dictionary) attack. noanonymous Disallow methods that allow anonymous authentication. forward_secrecy Only allow methods that support forward secrecy (Dovecot only). mutual_auth Only allow methods that provide mutual authentication (not available with Cyrus SASL version 1). By default, the Postfix SMTP server accepts plaintext passwords but not anonymous logins. Warning: it appears that clients try authentication methods in the order as advertised by the server (e.g., PLAIN ANONYMOUS CRAM-MD5) which means that if you disable plaintext passwords, clients will log in anonymously, even when they should be able to use CRAMMD5. So, if you disable plaintext logins, disable anonymous logins too. Postfix treats anonymous login as no authentication. Example:
smtpd_sasl_security_options = noanonymous, noplaintext

smtpd_sasl_tls_security_options (default: $smtpd_sasl_security_options) The SASL authentication security options that the Postfix SMTP server uses for TLS encrypted SMTP sessions. This feature is available in Postfix 2.2 and later. smtpd_sasl_type (default: cyrus) The SASL plug-in type that the Postfix SMTP server should use for authentication. The available types are listed with the "postconf -a" command. This feature is available in Postfix 2.3 and later. smtpd_sender_login_maps (default: empty) Optional lookup table with the SASL login names that own sender (MAIL FROM) addresses. Specify zero or more "type:table" lookup tables. With lookups from indexed files such as DB or DBM, or from networked tables such as NIS, LDAP or SQL, the following search operations are done with a sender address of user@domain: 1) user@domain This table lookup is always done and has the highest precedence. 2) user This table lookup is done only when the domain part of the sender address matches $myorigin, $mydestination, $inet_interfaces or $proxy_interfaces. 3) @domain

This table lookup is done last and has the lowest precedence. In all cases the result of table lookup must be either "not found" or a list of SASL login names separated by comma and/or whitespace. smtpd_sender_restrictions (default: empty) Optional restrictions that the Postfix SMTP server applies in the context of the MAIL FROM command. See SMTPD_ACCESS_README, section "Delayed evaluation of SMTP access restriction lists" for a discussion of evaluation context and time. The default is to permit everything. Specify a list of restrictions, separated by commas and/or whitespace. Continue long lines by starting the next line with whitespace. Restrictions are applied in the order as specified; the first restriction that matches wins. The following restrictions are specific to the sender address received with the MAIL FROM command. check_sender_access type:table Search the specified access(5) database for the MAIL FROM address, domain, parent domains, or localpart@, and execute the corresponding action. check_sender_mx_access type:table Search the specified access(5) database for the MX hosts for the MAIL FROM address, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.1 and later. check_sender_ns_access type:table Search the specified access(5) database for the DNS servers for the MAIL FROM address, and execute the corresponding action. Note: a result of "OK" is not allowed for safety reasons. Instead, use DUNNO in order to exclude specific hosts from blacklists. This feature is available in Postfix 2.1 and later. reject_authenticated_sender_login_mismatch Enforces the reject_sender_login_mismatch restriction for authenticated clients only. This feature is available in Postfix version 2.1 and later. reject_non_fqdn_sender Reject the request when the MAIL FROM address is not in fully-qualified domain form, as required by the RFC. The non_fqdn_reject_code parameter specifies the response code for rejected requests (default: 504). reject_rhsbl_sender rbl_domain=d.d.d.d Reject the request when the MAIL FROM domain is listed with the A record "d.d.d.d" under rbl_domain (Postfix version 2.1 and later only). If no "=d.d.d.d" is specified, reject the request when the MAIL FROM domain is listed with any A record under rbl_domain. The maps_rbl_reject_code parameter specifies the response code for rejected requests (default: 554); the default_rbl_reply parameter specifies the default server reply; and the rbl_reply_maps parameter specifies tables with server replies indexed by rbl_domain. This feature is available in Postfix 2.0 and later. reject_sender_login_mismatch Reject the request when $smtpd_sender_login_maps specifies an owner for the MAIL

FROM address, but the client is not (SASL) logged in as that MAIL FROM address owner; or when the client is (SASL) logged in, but the client login name doesn't own the MAIL FROM address according to $smtpd_sender_login_maps. reject_unauthenticated_sender_login_mismatch Enforces the reject_sender_login_mismatch restriction for unauthenticated clients only. This feature is available in Postfix version 2.1 and later. reject_unknown_sender_domain Reject the request when Postfix is not final destination for the sender address, and the MAIL FROM address has no DNS A or MX record, or when it has a malformed MX record such as a record with a zero-length MX hostname (Postfix version 2.3 and later). The unknown_address_reject_code parameter specifies the numerical response code for rejected requests (default: 450). The response is always 450 in case of a temporary DNS error. The unknown_address_tempfail_action parameter specifies the action after a temporary DNS error (default: defer_if_permit). reject_unlisted_sender Reject the request when the MAIL FROM address is not listed in the list of valid recipients for its domain class. See the smtpd_reject_unlisted_sender parameter description for details. This feature is available in Postfix 2.1 and later. reject_unverified_sender Reject the request when mail to the MAIL FROM address is known to bounce, or when the sender address destination is not reachable. Address verification information is managed by the verify(8) server; see the ADDRESS_VERIFICATION_README file for details. The unverified_sender_reject_code parameter specifies the numerical response code when an address is known to bounce (default: 450, change into 550 when you are confident that it is safe to do so). The unverified_sender_defer_code specifies the numerical response code when an address address probe failed due to a temporary problem (default: 450). The unverified_sender_tempfail_action parameter specifies the action after address probe failure due to a temporary problem (default: defer_if_permit). This feature is available in Postfix 2.1 and later. Other restrictions that are valid in this context: Generic restrictions that can be used in any SMTP command context, described under smtpd_client_restrictions. SMTP command specific restrictions described under smtpd_client_restrictions and smtpd_helo_restrictions. SMTP command specific restrictions described under smtpd_recipient_restrictions. When recipient restrictions are listed under smtpd_sender_restrictions, they have effect only with "smtpd_delay_reject = yes", so that $smtpd_sender_restrictions is evaluated at the time of the RCPT TO command. Examples:
smtpd_sender_restrictions = reject_unknown_sender_domain smtpd_sender_restrictions = reject_unknown_sender_domain, check_sender_access hash:/etc/postfix/access

smtpd_service (default: smtpd)

The internal service that postscreen(8) forwards allowed connections to. In a future version there may be different classes of SMTP service. This feature is available in Postfix 2.8. smtpd_soft_error_limit (default: 10) The number of errors a remote SMTP client is allowed to make without delivering mail before the Postfix SMTP server slows down all its responses. With Postfix version 2.1 and later, the Postfix SMTP server delays all responses by $smtpd_error_sleep_time seconds. With Postfix versions 2.0 and earlier, the Postfix SMTP server delays all responses by (number of errors) seconds. smtpd_starttls_timeout (default: 300s) The time limit for Postfix SMTP server write and read operations during TLS startup and shutdown handshake procedures. This feature is available in Postfix 2.2 and later. smtpd_timeout (default: normal: 300s, overload: 10s) The time limit for sending a Postfix SMTP server response and for receiving a remote SMTP client request. Normally the default limit is 300s, but it changes under overload to just 10s. With Postfix 2.5 and earlier, the SMTP server always uses a time limit of 300s by default. Note: if you set SMTP time limits to very large values you may have to update the global ipc_timeout parameter. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). smtpd_tls_CAfile (default: empty) A file containing (PEM format) CA certificates of root CAs trusted to sign either remote SMTP client certificates or intermediate CA certificates. These are loaded into memory before the smtpd(8) server enters the chroot jail. If the number of trusted roots is large, consider using smtpd_tls_CApath instead, but note that the latter directory must be present in the chroot jail if the smtpd(8) server is chrooted. This file may also be used to augment the server certificate trust chain, but it is best to include all the required certificates directly in the server certificate file. Specify "tls_append_default_CA = no" to prevent Postfix from appending the systemsupplied default CAs and trusting third-party certificates. By default (see smtpd_tls_ask_ccert), client certificates are not requested, and smtpd_tls_CAfile should remain empty. If you do make use of client certificates, the distinguished names (DNs) of the certificate authorities listed in smtpd_tls_CAfile are sent to the remote SMTP client in the client certificate request message. MUAs with multiple client

certificates may use the list of preferred certificate authorities to select the correct client certificate. You may want to put your "preferred" CA or CAs in this file, and install other trusted CAs in $smtpd_tls_CApath. Example:
smtpd_tls_CAfile = /etc/postfix/CAcert.pem

This feature is available in Postfix 2.2 and later. smtpd_tls_CApath (default: empty) A directory containing (PEM format) CA certificates of root CAs trusted to sign either remote SMTP client certificates or intermediate CA certificates. Do not forget to create the necessary "hash" links with, for example, "$OPENSSL_HOME/bin/c_rehash /etc/postfix/certs". To use smtpd_tls_CApath in chroot mode, this directory (or a copy) must be inside the chroot jail. Specify "tls_append_default_CA = no" to prevent Postfix from appending the systemsupplied default CAs and trusting third-party certificates. By default (see smtpd_tls_ask_ccert), client certificates are not requested, and smtpd_tls_CApath should remain empty. In contrast to smtpd_tls_CAfile, DNs of certificate authorities installed in $smtpd_tls_CApath are not included in the client certificate request message. MUAs with multiple client certificates may use the list of preferred certificate authorities to select the correct client certificate. You may want to put your "preferred" CA or CAs in $smtpd_tls_CAfile, and install the remaining trusted CAs in $smtpd_tls_CApath. Example:
smtpd_tls_CApath = /etc/postfix/certs

This feature is available in Postfix 2.2 and later. smtpd_tls_always_issue_session_ids (default: yes) Force the Postfix SMTP server to issue a TLS session id, even when TLS session caching is turned off (smtpd_tls_session_cache_database is empty). This behavior is compatible with Postfix < 2.3. With Postfix 2.3 and later the Postfix SMTP server can disable session id generation when TLS session caching is turned off. This keeps clients from caching sessions that almost certainly cannot be re-used. By default, the Postfix SMTP server always generates TLS session ids. This works around a known defect in mail client applications such as MS Outlook, and may also prevent interoperability issues with other MTAs. Example:
smtpd_tls_always_issue_session_ids = no

This feature is available in Postfix 2.3 and later.

smtpd_tls_ask_ccert (default: no) Ask a remote SMTP client for a client certificate. This information is needed for certificate based mail relaying with, for example, the permit_tls_clientcerts feature. Some clients such as Netscape will either complain if no certificate is available (for the list of CAs in $smtpd_tls_CAfile) or will offer multiple client certificates to choose from. This may be annoying, so this option is "off" by default. This feature is available in Postfix 2.2 and later. smtpd_tls_auth_only (default: no) When TLS encryption is optional in the Postfix SMTP server, do not announce or accept SASL authentication over unencrypted connections. This feature is available in Postfix 2.2 and later. smtpd_tls_ccert_verifydepth (default: 9) The verification depth for remote SMTP client certificates. A depth of 1 is sufficient if the issuing CA is listed in a local CA file. The default verification depth is 9 (the OpenSSL default) for compatibility with earlier Postfix behavior. Prior to Postfix 2.5, the default value was 5, but the limit was not actually enforced. If you have set this to a lower non-default value, certificates with longer trust chains may now fail to verify. Certificate chains with 1 or 2 CAs are common, deeper chains are more rare and any number between 5 and 9 should suffice in practice. You can choose a lower number if, for example, you trust certificates directly signed by an issuing CA but not any CAs it delegates to. This feature is available in Postfix 2.2 and later. smtpd_tls_cert_file (default: empty) File with the Postfix SMTP server RSA certificate in PEM format. This file may also contain the Postfix SMTP server private RSA key. Public Internet MX hosts without certificates signed by a "reputable" CA must generate, and be prepared to present to most clients, a self-signed or private-CA signed certificate. The client will not be able to authenticate the server, but unless it is running Postfix 2.3 or similar software, it will still insist on a server certificate. For servers that are not public Internet MX hosts, Postfix 2.3 supports configurations with no certificates. This entails the use of just the anonymous TLS ciphers, which are not supported by typical SMTP clients. Since such clients will not, as a rule, fall back to plain text after a TLS handshake failure, the server will be unable to receive email from TLS enabled clients. To avoid accidental configurations with no certificates, Postfix 2.3 enables certificate-less operation only when the administrator explicitly sets "smtpd_tls_cert_file = none". This ensures that new Postfix configurations will not accidentally run with no certificates. Both RSA and DSA certificates are supported. When both types are present, the cipher used

determines which certificate will be presented to the client. For Netscape and OpenSSL clients without special cipher choices the RSA certificate is preferred. To enable a remote SMTP client to verify the Postfix SMTP server certificate, the issuing CA certificates must be made available to the client. You should include the required certificates in the server certificate file, the server certificate first, then the issuing CA(s) (bottom-up order). Example: the certificate for "server.example.com" was issued by "intermediate CA" which itself has a certificate of "root CA". Create the server.pem file with "cat server_cert.pem intermediate_CA.pem root_CA.pem > server.pem". If you also want to verify client certificates issued by these CAs, you can add the CA certificates to the smtpd_tls_CAfile, in which case it is not necessary to have them in the smtpd_tls_cert_file or smtpd_tls_dcert_file. A certificate supplied here must be usable as an SSL server certificate and hence pass the "openssl verify -purpose sslserver ..." test. Example:
smtpd_tls_cert_file = /etc/postfix/server.pem

This feature is available in Postfix 2.2 and later. smtpd_tls_cipherlist (default: empty) Obsolete Postfix < 2.3 control for the Postfix SMTP server TLS cipher list. It is easy to create inter-operability problems by choosing a non-default cipher list. Do not use a non-default TLS cipherlist for MX hosts on the public Internet. Clients that begin the TLS handshake, but are unable to agree on a common cipher, may not be able to send any email to the SMTP server. Using a restricted cipher list may be more appropriate for a dedicated MSA or an internal mailhub, where one can exert some control over the TLS software and settings of the connecting clients. Note: do not use "" quotes around the parameter value. This feature is available with Postfix version 2.2. It is not used with Postfix 2.3 and later; use smtpd_tls_mandatory_ciphers instead. smtpd_tls_ciphers (default: export) The minimum TLS cipher grade that the Postfix SMTP server will use with opportunistic TLS encryption. Cipher types listed in smtpd_tls_exclude_ciphers are excluded from the base definition of the selected cipher grade. The default value "export" ensures maximum interoperability. Because encryption is optional, stronger controls are not appropriate, and this setting SHOULD NOT be changed unless the change is essential. When TLS is mandatory the cipher grade is chosen via the smtpd_tls_mandatory_ciphers configuration parameter, see there for syntax details. Example:

smtpd_tls_ciphers = export

This feature is available in Postfix 2.6 and later. With earlier Postfix releases only the smtpd_tls_mandatory_ciphers parameter is implemented, and opportunistic TLS always uses "export" or better (i.e. all) ciphers. smtpd_tls_dcert_file (default: empty) File with the Postfix SMTP server DSA certificate in PEM format. This file may also contain the Postfix SMTP server private DSA key. See the discussion under smtpd_tls_cert_file for more details. Example:
smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem

This feature is available in Postfix 2.2 and later. smtpd_tls_dh1024_param_file (default: empty) File with DH parameters that the Postfix SMTP server should use with EDH ciphers. Instead of using the exact same parameter sets as distributed with other TLS packages, it is more secure to generate your own set of parameters with something like the following command:
openssl gendh -out /etc/postfix/dh_1024.pem -2 1024

Your actual source for entropy may differ. Some systems have /dev/random; on other system you may consider using the "Entropy Gathering Daemon EGD", available at http://egd.sourceforge.net/ Example:
smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem

This feature is available with Postfix version 2.2. smtpd_tls_dh512_param_file (default: empty) File with DH parameters that the Postfix SMTP server should use with EDH ciphers. See also the discussion under the smtpd_tls_dh1024_param_file configuration parameter. Example:
smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem

This feature is available with Postfix version 2.2. smtpd_tls_dkey_file (default: $smtpd_tls_dcert_file)

File with the Postfix SMTP server DSA private key in PEM format. This file may be combined with the Postfix SMTP server DSA certificate file specified with $smtpd_tls_dcert_file. The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only access to the system superuser account ("root"), and no access to anyone else. This feature is available in Postfix 2.2 and later. smtpd_tls_eccert_file (default: empty) File with the Postfix SMTP server ECDSA certificate in PEM format. This file may also contain the Postfix SMTP server private ECDSA key. See the discussion under smtpd_tls_cert_file for more details. Example:
smtpd_tls_eccert_file = /etc/postfix/ecdsa-scert.pem

This feature is available in Postfix 2.6 and later, when Postfix is compiled and linked with OpenSSL 1.0.0 or later. smtpd_tls_eckey_file (default: $smtpd_tls_eccert_file) File with the Postfix SMTP server ECDSA private key in PEM format. This file may be combined with the Postfix SMTP server ECDSA certificate file specified with $smtpd_tls_eccert_file. The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only access to the system superuser account ("root"), and no access to anyone else. This feature is available in Postfix 2.6 and later, when Postfix is compiled and linked with OpenSSL 1.0.0 or later. smtpd_tls_eecdh_grade (default: see "postconf -d" output) The Postfix SMTP server security grade for ephemeral elliptic-curve Diffie-Hellman (EECDH) key exchange. The available choices are: none Don't use EECDH. Ciphers based on EECDH key exchange will be disabled. This is the default in official Postfix releases (mail_version = major.minor.patchlevel). strong Use EECDH with approximately 128 bits of security at a reasonable computational cost. This is the current best-practice trade-off between security and computational efficiency. This is the default in Postfix snapshot releases (mail_version = major.minorreleasedate).

ultra Use EECDH with approximately 192 bits of security at computational cost that is approximately twice as high as 128 bit strength ECC. Barring significant progress in attacks on elliptic curve crypto-systems, the "strong" curve is sufficient for most users. This feature is available in Postfix 2.6 and later, when it is compiled and linked with OpenSSL 1.0.0 or later. smtpd_tls_exclude_ciphers (default: empty) List of ciphers or cipher types to exclude from the SMTP server cipher list at all TLS security levels. Excluding valid ciphers can create interoperability problems. DO NOT exclude ciphers unless it is essential to do so. This is not an OpenSSL cipherlist; it is a simple list separated by whitespace and/or commas. The elements are a single cipher, or one or more "+" separated cipher properties, in which case only ciphers matching all the properties are excluded. Examples (some of these will cause problems):
smtpd_tls_exclude_ciphers smtpd_tls_exclude_ciphers smtpd_tls_exclude_ciphers smtpd_tls_exclude_ciphers smtpd_tls_exclude_ciphers = = = = = aNULL MD5, DES DES+MD5 AES256-SHA, DES-CBC3-MD5 kEDH+aRSA

The first setting disables anonymous ciphers. The next setting disables ciphers that use the MD5 digest algorithm or the (single) DES encryption algorithm. The next setting disables ciphers that use MD5 and DES together. The next setting disables the two ciphers "AES256SHA" and "DES-CBC3-MD5". The last setting disables ciphers that use "EDH" key exchange with RSA authentication. This feature is available in Postfix 2.3 and later. smtpd_tls_fingerprint_digest (default: md5) The message digest algorithm used to construct client-certificate fingerprints for check_ccert_access and permit_tls_clientcerts. The default algorithm is md5, for backwards compatibility with Postfix releases prior to 2.5. The best practice algorithm is now sha1. Recent advances in hash function cryptanalysis have led to md5 being deprecated in favor of sha1. However, as long as there are no known "second pre-image" attacks against md5, its use in this context can still be considered safe. While additional digest algorithms are often available with OpenSSL's libcrypto, only those used by libssl in SSL cipher suites are available to Postfix. For now this means just md5 or sha1. To find the fingerprint of a specific certificate file, with a specific digest algorithm, run:
$ openssl x509 -noout -fingerprint -digest -in certfile.pem

The text to the right of "=" sign is the desired fingerprint. For example:
$ openssl x509 -noout -fingerprint -sha1 -in cert.pem

SHA1 Fingerprint=D4:6A:AB:19:24:79:F8:32:BB:A6:CB:66:82:C0:8E:9B:EE:29 :A8:1A

Example: client-certificate access table, with sha1 fingerprints:


/etc/postfix/main.cf: smtpd_tls_fingerprint_digest = sha1 smtpd_client_restrictions = check_ccert_access hash:/etc/postfix/access, reject /etc/postfix/access: # Action folded to next line... AF:88:7C:AD:51:95:6F:36:96:F6:01:FB:2E:48:CD:AB:49:25:A2:3B OK 85:16:78:FD:73:6E:CE:70:E0:31:5F:0D:3C:C8:6D:C4:2C:24:59:E1 permit_auth_destination

This feature is available in Postfix 2.5 and later. smtpd_tls_key_file (default: $smtpd_tls_cert_file) File with the Postfix SMTP server RSA private key in PEM format. This file may be combined with the Postfix SMTP server RSA certificate file specified with $smtpd_tls_cert_file. The private key must be accessible without a pass-phrase, i.e. it must not be encrypted. File permissions should grant read-only access to the system superuser account ("root"), and no access to anyone else. smtpd_tls_loglevel (default: 0) Enable additional Postfix SMTP server logging of TLS activity. Each logging level also includes the information that is logged at a lower logging level. 0 Disable logging of TLS activity. 1 Log TLS handshake and certificate information. 2 Log levels during TLS negotiation. 3 Log hexadecimal and ASCII dump of TLS negotiation process. 4 Also log hexadecimal and ASCII dump of complete transmission after STARTTLS. Use "smtpd_tls_loglevel = 3" only in case of problems. Use of loglevel 4 is strongly discouraged. This feature is available in Postfix 2.2 and later. smtpd_tls_mandatory_ciphers (default: medium) The minimum TLS cipher grade that the Postfix SMTP server will use with mandatory TLS encryption. The default grade ("medium") is sufficiently strong that any benefit from globally restricting TLS sessions to a more stringent grade is likely negligible, especially given the fact that many implementations still do not offer any stronger ("high" grade) ciphers, while those that do, will always use "high" grade ciphers. So insisting on "high" grade ciphers is generally

counter-productive. Allowing "export" or "low" ciphers is typically not a good idea, as systems limited to just these are limited to obsolete browsers. No known SMTP clients fail to support at least one "medium" or "high" grade cipher. The following cipher grades are supported: export Enable "EXPORT" grade or stronger OpenSSL ciphers. This is the most appropriate setting for public MX hosts, and is always used with opportunistic TLS encryption. The underlying cipherlist is specified via the tls_export_cipherlist configuration parameter, which you are strongly encouraged to not change. low Enable "LOW" grade or stronger OpenSSL ciphers. The underlying cipherlist is specified via the tls_low_cipherlist configuration parameter, which you are strongly encouraged to not change. medium Enable "MEDIUM" grade or stronger OpenSSL ciphers. These use 128-bit or longer symmetric bulk-encryption keys. This is the default minimum strength for mandatory TLS encryption. The underlying cipherlist is specified via the tls_medium_cipherlist configuration parameter, which you are strongly encouraged to not change. high Enable only "HIGH" grade OpenSSL ciphers. The underlying cipherlist is specified via the tls_high_cipherlist configuration parameter, which you are strongly encouraged to not change. null Enable only the "NULL" OpenSSL ciphers, these provide authentication without encryption. This setting is only appropriate in the rare case that all clients are prepared to use NULL ciphers (not normally enabled in TLS clients). The underlying cipherlist is specified via the tls_null_cipherlist configuration parameter, which you are strongly encouraged to not change. Cipher types listed in smtpd_tls_mandatory_exclude_ciphers or smtpd_tls_exclude_ciphers are excluded from the base definition of the selected cipher grade. See smtpd_tls_ciphers for cipher controls that apply to opportunistic TLS. The underlying cipherlists for grades other than "null" include anonymous ciphers, but these are automatically filtered out if the server is configured to ask for client certificates. You are very unlikely to need to take any steps to exclude anonymous ciphers, they are excluded automatically as required. If you must exclude anonymous ciphers even when Postfix does not need or use peer certificates, set "smtpd_tls_exclude_ciphers = aNULL". To exclude anonymous ciphers only when TLS is enforced, set "smtpd_tls_mandatory_exclude_ciphers = aNULL". This feature is available in Postfix 2.3 and later. smtpd_tls_mandatory_exclude_ciphers (default: empty) Additional list of ciphers or cipher types to exclude from the SMTP server cipher list at mandatory TLS security levels. This list works in addition to the exclusions listed with smtpd_tls_exclude_ciphers (see there for syntax details). This feature is available in Postfix 2.3 and later.

smtpd_tls_mandatory_protocols (default: SSLv3, TLSv1) The SSL/TLS protocols accepted by the Postfix SMTP server with mandatory TLS encryption. If the list is empty, the server supports all available SSL/TLS protocol versions. A non-empty value is a list of protocol names separated by whitespace, commas or colons. The supported protocol names are "SSLv2", "SSLv3" and "TLSv1", and are not case sensitive. With Postfix 2.5 the parameter syntax is expanded to support protocol exclusions. One can now explicitly exclude SSLv2 by setting "smtpd_tls_mandatory_protocols = !SSLv2". To exclude both SSLv2 and SSLv3 set "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3". Listing the protocols to include, rather than protocols to exclude, is still supported, use the form you find more intuitive. Since SSL version 2 has known protocol weaknesses and is now deprecated, the default setting excludes "SSLv2". This means that by default, SSL version 2 will not be used at the "encrypt" security level. Example:
smtpd_tls_mandatory_protocols = TLSv1 # Alternative form with Postfix 2.5: smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3

This feature is available in Postfix 2.3 and later. smtpd_tls_protocols (default: empty) List of TLS protocols that the Postfix SMTP server will exclude or include with opportunistic TLS encryption. This parameter SHOULD be left at its default empty value, allowing all protocols to be used with opportunistic TLS. In main.cf the values are separated by whitespace, commas or colons. An empty value means allow all protocols. The valid protocol names, (see SSL_get_version(3)), are "SSLv2", "SSLv3" and "TLSv1". In smtp_tls_policy_maps table entries, "protocols" attribute values are separated by a colon. To include a protocol list its name, to exclude it, prefix the name with a "!" character. To exclude SSLv2 even for opportunistic TLS set "smtpd_tls_protocols = !SSLv2". To exclude both "SSLv2" and "SSLv3" set "smtpd_tls_protocols = !SSLv2, !SSLv3". Explicitly listing the protocols to include, is supported, but not recommended. OpenSSL provides no mechanisms for excluding protocols not known at compile-time. If Postfix is linked against an OpenSSL library that supports additional protocol versions, they cannot be excluded using either syntax. Example:
smtpd_tls_protocols = !SSLv2

This feature is available in Postfix 2.6 and later. smtpd_tls_received_header (default: no) Request that the Postfix SMTP server produces Received: message headers that include

information about the protocol and cipher used, as well as the client CommonName and client certificate issuer CommonName. This is disabled by default, as the information may be modified in transit through other mail servers. Only information that was recorded by the final destination can be trusted. This feature is available in Postfix 2.2 and later. smtpd_tls_req_ccert (default: no) With mandatory TLS encryption, require a trusted remote SMTP client certificate in order to allow TLS connections to proceed. This option implies "smtpd_tls_ask_ccert = yes". When TLS encryption is optional, this setting is ignored with a warning written to the mail log. This feature is available in Postfix 2.2 and later. smtpd_tls_security_level (default: empty) The SMTP TLS security level for the Postfix SMTP server; when a non-empty value is specified, this overrides the obsolete parameters smtpd_use_tls and smtpd_enforce_tls. This parameter is ignored with "smtpd_tls_wrappermode = yes". Specify one of the following security levels: none TLS will not be used. may Opportunistic TLS: announce STARTTLS support to SMTP clients, but do not require that clients use TLS encryption. encrypt Mandatory TLS encryption: announce STARTTLS support to SMTP clients, and require that clients use TLS encryption. According to RFC 2487 this MUST NOT be applied in case of a publicly-referenced SMTP server. Instead, this option should be used only on dedicated servers. Note 1: the "fingerprint", "verify" and "secure" levels are not supported here. The Postfix SMTP server logs a warning and uses "encrypt" instead. To verify SMTP client certificates, see TLS_README for a discussion of the smtpd_tls_ask_ccert, smtpd_tls_req_ccert, and permit_tls_clientcerts features. Note 2: The parameter setting "smtpd_tls_security_level = encrypt" implies "smtpd_tls_auth_only = yes". Note 3: when invoked via "sendmail -bs", Postfix will never offer STARTTLS due to insufficient privileges to access the server private key. This is intended behavior. This feature is available in Postfix 2.3 and later. smtpd_tls_session_cache_database (default: empty) Name of the file containing the optional Postfix SMTP server TLS session cache. Specify a

database type that supports enumeration, such as btree or sdbm; there is no need to support concurrent access. The file is created if it does not exist. The smtpd(8) daemon does not use this parameter directly, rather the cache is implemented indirectly in the tlsmgr(8) daemon. This means that per-smtpd-instance master.cf overrides of this parameter are not effective. Note, that each of the cache databases supported by tlsmgr(8) daemon: $smtpd_tls_session_cache_database, $smtp_tls_session_cache_database (and with Postfix 2.3 and later $lmtp_tls_session_cache_database), needs to be stored separately. It is not at this time possible to store multiple caches in a single database. Note: dbm databases are not suitable. TLS session objects are too large. As of version 2.5, Postfix no longer uses root privileges when opening this file. The file should now be stored under the Postfix-owned data_directory. As a migration aid, an attempt to open the file under a non-Postfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. Example:
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache

This feature is available in Postfix 2.2 and later. smtpd_tls_session_cache_timeout (default: 3600s) The expiration time of Postfix SMTP server TLS session cache information. A cache cleanup is performed periodically every $smtpd_tls_session_cache_timeout seconds. As with $smtpd_tls_session_cache_database, this parameter is implemented in the tlsmgr(8) daemon and therefore per-smtpd-instance master.cf overrides are not possible. This feature is available in Postfix 2.2 and later. smtpd_tls_wrappermode (default: no) Run the Postfix SMTP server in the non-standard "wrapper" mode, instead of using the STARTTLS command. If you want to support this service, enable a special port in master.cf, and specify "-o smtpd_tls_wrappermode=yes" on the SMTP server's command line. Port 465 (smtps) was once chosen for this purpose. This feature is available in Postfix 2.2 and later. smtpd_use_tls (default: no) Opportunistic TLS: announce STARTTLS support to SMTP clients, but do not require that clients use TLS encryption. Note: when invoked via "sendmail -bs", Postfix will never offer STARTTLS due to insufficient privileges to access the server private key. This is intended behavior. This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtpd_tls_security_level instead.

soft_bounce (default: no) Safety net to keep mail queued that would otherwise be returned to the sender. This parameter disables locally-generated bounces, and prevents the Postfix SMTP server from rejecting mail permanently, by changing 5xx reply codes into 4xx. However, soft_bounce is no cure for address rewriting mistakes or mail routing mistakes. Example:
soft_bounce = yes

stale_lock_time (default: 500s) The time after which a stale exclusive mailbox lockfile is removed. This is used for delivery to file or mailbox. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). stress (default: empty) This feature is documented in the STRESS_README document. This feature is available in Postfix 2.5 and later. strict_7bit_headers (default: no) Reject mail with 8-bit text in message headers. This blocks mail from poorly written applications. This feature should not be enabled on a general purpose mail server, because it is likely to reject legitimate email. This feature is available in Postfix 2.0 and later. strict_8bitmime (default: no) Enable both strict_7bit_headers and strict_8bitmime_body. This feature should not be enabled on a general purpose mail server, because it is likely to reject legitimate email. This feature is available in Postfix 2.0 and later. strict_8bitmime_body (default: no) Reject 8-bit message body text without 8-bit MIME content encoding information. This blocks mail from poorly written applications. Unfortunately, this also rejects majordomo approval requests when the included request contains valid 8-bit MIME mail, and it rejects bounces from mailers that do not MIME encapsulate 8-bit content (for example, bounces from qmail or from old versions of Postfix).

This feature should not be enabled on a general purpose mail server, because it is likely to reject legitimate email. This feature is available in Postfix 2.0 and later. strict_mailbox_ownership (default: yes) Defer delivery when a mailbox file is not owned by its recipient. The default setting is not backwards compatible. This feature is available in Postfix 2.5.3 and later. strict_mime_encoding_domain (default: no) Reject mail with invalid Content-Transfer-Encoding: information for the message/* or multipart/* MIME content types. This blocks mail from poorly written software. This feature should not be enabled on a general purpose mail server, because it will reject mail after a single violation. This feature is available in Postfix 2.0 and later. strict_rfc821_envelopes (default: no) Require that addresses received in SMTP MAIL FROM and RCPT TO commands are enclosed with <>, and that those addresses do not contain RFC 822 style comments or phrases. This stops mail from poorly written software. By default, the Postfix SMTP server accepts RFC 822 syntax in MAIL FROM and RCPT TO addresses. sun_mailtool_compatibility (default: no) Obsolete SUN mailtool compatibility feature. Instead, use "mailbox_delivery_lock = dotlock". swap_bangpath (default: yes) Enable the rewriting of "site!user" into "user@site". This is necessary if your machine is connected to UUCP networks. It is enabled by default. Note: with Postfix version 2.2, message header address rewriting happens only when one of the following conditions is true: The message is received with the Postfix sendmail(1) command, The message is received from a network client that matches $local_header_rewrite_clients, The message is received from the network, and the remote_header_rewrite_domain parameter specifies a non-empty value. To get the behavior before Postfix version 2.2, specify "local_header_rewrite_clients = static:all".

Example:
swap_bangpath = no

syslog_facility (default: mail) The syslog facility of Postfix logging. Specify a facility as defined in syslog.conf(5). The default facility is "mail". Warning: a non-default syslog_facility setting takes effect only after a Postfix process has completed initialization. Errors during process initialization will be logged with the default facility. Examples are errors while parsing the command line arguments, and errors while accessing the Postfix main.cf configuration file. syslog_name (default: see "postconf -d" output) The mail system name that is prepended to the process name in syslog records, so that "smtpd" becomes, for example, "postfix/smtpd". Warning: a non-default syslog_name setting takes effect only after a Postfix process has completed initialization. Errors during process initialization will be logged with the default name. Examples are errors while parsing the command line arguments, and errors while accessing the Postfix main.cf configuration file. tcp_windowsize (default: 0) An optional workaround for routers that break TCP window scaling. Specify a value > 0 and < 65536 to enable this feature. With Postfix TCP servers (smtpd(8), qmqpd(8)), this feature is implemented by the Postfix master(8) daemon. To change this parameter without stopping Postfix, you need to first terminate all Postfix TCP servers:
# postconf -e master_service_disable=inet # postfix reload

This immediately terminates all processes that accept network connections. Next, you enable Postfix TCP servers with the updated tcp_windowsize setting:
# postconf -e tcp_windowsize=65535 master_service_disable= # postfix reload

If you skip these steps with a running Postfix system, then the tcp_windowsize change will work only for Postfix TCP clients (smtp(8), lmtp(8)). This feature is available in Postfix 2.6 and later. tls_append_default_CA (default: no) Append the system-supplied default certificate authority certificates to the ones specified with *_tls_CApath or *_tls_CAfile. The default is "no"; this prevents Postfix from trusting thirdparty certificates and giving them relay permission with permit_tls_all_clientcerts.

This feature is available in Postfix 2.4.15, 2.5.11, 2.6.8, 2.7.2 and later versions. Specify "tls_append_default_CA = yes" for backwards compatibility, to avoid breaking certificate verification with sites that don't use permit_tls_all_clientcerts. tls_daemon_random_bytes (default: 32) The number of pseudo-random bytes that an smtp(8) or smtpd(8) process requests from the tlsmgr(8) server in order to seed its internal pseudo random number generator (PRNG). The default of 32 bytes (equivalent to 256 bits) is sufficient to generate a 128bit (or 168bit) session key. This feature is available in Postfix 2.2 and later. tls_eecdh_strong_curve (default: prime256v1) The elliptic curve used by the SMTP server for sensibly strong ephemeral ECDH key exchange. This curve is used by the Postfix SMTP server when "smtpd_tls_eecdh_grade = strong". The phrase "sensibly strong" means approximately 128-bit security based on best known attacks. The selected curve must be implemented by OpenSSL (as reported by ecparam(1) with the "-list_curves" option) and be one of the curves listed in Section 5.1.1 of RFC 4492. You should not generally change this setting. This default curve is specified in NSA "Suite B" Cryptography (see http://www.nsa.gov/ia/industry/crypto_suite_b.cfm) for information classified as SECRET. Note: elliptic curve names are poorly standardized; different standards groups are assigning different names to the same underlying curves. The curve with the X9.62 name "prime256v1" is also known under the SECG name "secp256r1", but OpenSSL does not recognize the latter name. This feature is available in Postfix 2.6 and later, when it is compiled and linked with OpenSSL 1.0.0 or later. tls_eecdh_ultra_curve (default: secp384r1) The elliptic curve used by the SMTP server for maximally strong ephemeral ECDH key exchange. This curve is used by the Postfix SMTP server when "smtpd_tls_eecdh_grade = ultra". The phrase "maximally strong" means approximately 192-bit security based on best known attacks. This additional strength comes at a significant computational cost, most users should instead set "smtpd_tls_eecdh_grade = strong". The selected curve must be implemented by OpenSSL (as reported by ecparam(1) with the "-list_curves" option) and be one of the curves listed in Section 5.1.1 of RFC 4492. You should not generally change this setting. This default "ultra" curve is specified in NSA "Suite B" Cryptography (see http://www.nsa.gov/ia/industry/crypto_suite_b.cfm) for information classified as TOP SECRET. This feature is available in Postfix 2.6 and later, when it is compiled and linked with OpenSSL 1.0.0 or later. tls_export_cipherlist (default: ALL:+RC4:@STRENGTH)

The OpenSSL cipherlist for "EXPORT" or higher grade ciphers. This defines the meaning of the "export" setting in smtpd_tls_mandatory_ciphers, smtp_tls_mandatory_ciphers and lmtp_tls_mandatory_ciphers. This is the cipherlist for the opportunistic ("may") TLS client security level and is the default cipherlist for the SMTP server. You are strongly encouraged to not change this setting. With OpenSSL 1.0.0 and later the cipherlist may start with an "aNULL:" prefix, which restores the 0.9.8-compatible ordering of the aNULL ciphers to the top of the list when they are enabled. This prefix is not needed with previous OpenSSL releases. This feature is available in Postfix 2.3 and later. tls_high_cipherlist (default: ALL:!EXPORT:!LOW:!MEDIUM:+RC4:@STRENGTH) The OpenSSL cipherlist for "HIGH" grade ciphers. This defines the meaning of the "high" setting in smtpd_tls_mandatory_ciphers, smtp_tls_mandatory_ciphers and lmtp_tls_mandatory_ciphers. You are strongly encouraged to not change this setting. With OpenSSL 1.0.0 and later the cipherlist may start with an "aNULL:" prefix, which restores the 0.9.8-compatible ordering of the aNULL ciphers to the top of the list when they are enabled. This prefix is not needed with previous OpenSSL releases. This feature is available in Postfix 2.3 and later. tls_low_cipherlist (default: ALL:!EXPORT:+RC4:@STRENGTH) The OpenSSL cipherlist for "LOW" or higher grade ciphers. This defines the meaning of the "low" setting in smtpd_tls_mandatory_ciphers, smtp_tls_mandatory_ciphers and lmtp_tls_mandatory_ciphers. You are strongly encouraged to not change this setting. With OpenSSL 1.0.0 and later the cipherlist may start with an "aNULL:" prefix, which restores the 0.9.8-compatible ordering of the aNULL ciphers to the top of the list when they are enabled. This prefix is not needed with previous OpenSSL releases. This feature is available in Postfix 2.3 and later. tls_medium_cipherlist (default: ALL:!EXPORT:!LOW:+RC4:@STRENGTH) The OpenSSL cipherlist for "MEDIUM" or higher grade ciphers. This defines the meaning of the "medium" setting in smtpd_tls_mandatory_ciphers, smtp_tls_mandatory_ciphers and lmtp_tls_mandatory_ciphers. This is the default cipherlist for mandatory TLS encryption in the TLS client (with anonymous ciphers disabled when verifying server certificates). You are strongly encouraged to not change this setting. With OpenSSL 1.0.0 and later the cipherlist may start with an "aNULL:" prefix, which restores the 0.9.8-compatible ordering of the aNULL ciphers to the top of the list when they are enabled. This prefix is not needed with previous OpenSSL releases. This feature is available in Postfix 2.3 and later. tls_null_cipherlist (default: eNULL:!aNULL) The OpenSSL cipherlist for "NULL" grade ciphers that provide authentication without encryption. This defines the meaning of the "null" setting in smtpd_mandatory_tls_ciphers, smtp_tls_mandatory_ciphers and lmtp_tls_mandatory_ciphers. You are strongly encouraged to not change this setting.

This feature is available in Postfix 2.3 and later. tls_random_bytes (default: 32) The number of bytes that tlsmgr(8) reads from $tls_random_source when (re)seeding the inmemory pseudo random number generator (PRNG) pool. The default of 32 bytes (256 bits) is good enough for 128bit symmetric keys. If using EGD or a device file, a maximum of 255 bytes is read. This feature is available in Postfix 2.2 and later. tls_random_exchange_name (default: see "postconf -d" output) Name of the pseudo random number generator (PRNG) state file that is maintained by tlsmgr(8). The file is created when it does not exist, and its length is fixed at 1024 bytes. As of version 2.5, Postfix no longer uses root privileges when opening this file, and the default file location was changed from ${config_directory}/prng_exch to $ {data_directory}/prng_exch. As a migration aid, an attempt to open the file under a nonPostfix directory is redirected to the Postfix-owned data_directory, and a warning is logged. This feature is available in Postfix 2.2 and later. tls_random_prng_update_period (default: 3600s) The time between attempts by tlsmgr(8) to save the state of the pseudo random number generator (PRNG) to the file specified with $tls_random_exchange_name. This feature is available in Postfix 2.2 and later. tls_random_reseed_period (default: 3600s) The maximal time between attempts by tlsmgr(8) to re-seed the in-memory pseudo random number generator (PRNG) pool from external sources. The actual time between re-seeding attempts is calculated using the PRNG, and is between 0 and the time specified. This feature is available in Postfix 2.2 and later. tls_random_source (default: see "postconf -d" output) The external entropy source for the in-memory tlsmgr(8) pseudo random number generator (PRNG) pool. Be sure to specify a non-blocking source. If this source is not a regular file, the entropy source type must be prepended: egd:/path/to/egd_socket for a source with EGD compatible socket interface, or dev:/path/to/device for a device file. Note: on OpenBSD systems specify /dev/arandom when /dev/urandom gives timeout errors. This feature is available in Postfix 2.2 and later. trace_service_name (default: trace) The name of the trace service. This service is implemented by the bounce(8) daemon and

maintains a record of mail deliveries and produces a mail delivery report when verbose delivery is requested with "sendmail -v". This feature is available in Postfix 2.1 and later. transport_delivery_slot_cost (default: $default_delivery_slot_cost) A transport-specific override for the default_delivery_slot_cost parameter value, where transport is the master.cf name of the message delivery transport. transport_delivery_slot_discount (default: $default_delivery_slot_discount) A transport-specific override for the default_delivery_slot_discount parameter value, where transport is the master.cf name of the message delivery transport. transport_delivery_slot_loan (default: $default_delivery_slot_loan) A transport-specific override for the default_delivery_slot_loan parameter value, where transport is the master.cf name of the message delivery transport. transport_destination_concurrency_failed_cohort_limit (default: $default_destination_concurrency_failed_cohort_limit) A transport-specific override for the default_destination_concurrency_failed_cohort_limit parameter value, where transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.5 and later. transport_destination_concurrency_limit (default: $default_destination_concurrency_limit) A transport-specific override for the default_destination_concurrency_limit parameter value, where transport is the master.cf name of the message delivery transport. transport_destination_concurrency_negative_feedback (default: $default_destination_concurrency_negative_feedback) A transport-specific override for the default_destination_concurrency_negative_feedback parameter value, where transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.5 and later. transport_destination_concurrency_positive_feedback (default: $default_destination_concurrency_positive_feedback) A transport-specific override for the default_destination_concurrency_positive_feedback parameter value, where transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.5 and later. transport_destination_rate_delay (default: $default_destination_rate_delay) A transport-specific override for the default_destination_rate_delay parameter value, where

transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.5 and later. transport_destination_recipient_limit (default: $default_destination_recipient_limit) A transport-specific override for the default_destination_recipient_limit parameter value, where transport is the master.cf name of the message delivery transport. transport_extra_recipient_limit (default: $default_extra_recipient_limit) A transport-specific override for the default_extra_recipient_limit parameter value, where transport is the master.cf name of the message delivery transport. transport_initial_destination_concurrency (default: $initial_destination_concurrency) A transport-specific override for the initial_destination_concurrency parameter value, where transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.5 and later. transport_maps (default: empty) Optional lookup tables with mappings from recipient address to (message delivery transport, next-hop destination). See transport(5) for details. Specify zero or more "type:table" lookup tables. If you use this feature with local files, run "postmap /etc/postfix/transport" after making a change. For safety reasons, as of Postfix 2.3 this feature does not allow $number substitutions in regular expression maps. Examples:
transport_maps = dbm:/etc/postfix/transport transport_maps = hash:/etc/postfix/transport

transport_minimum_delivery_slots (default: $default_minimum_delivery_slots) A transport-specific override for the default_minimum_delivery_slots parameter value, where transport is the master.cf name of the message delivery transport. transport_recipient_limit (default: $default_recipient_limit) A transport-specific override for the default_recipient_limit parameter value, where transport is the master.cf name of the message delivery transport. transport_recipient_refill_delay (default: $default_recipient_refill_delay) A transport-specific override for the default_recipient_refill_delay parameter value, where transport is the master.cf name of the message delivery transport.

This feature is available in Postfix 2.4 and later. transport_recipient_refill_limit (default: $default_recipient_refill_limit) A transport-specific override for the default_recipient_refill_limit parameter value, where transport is the master.cf name of the message delivery transport. This feature is available in Postfix 2.4 and later. transport_retry_time (default: 60s) The time between attempts by the Postfix queue manager to contact a malfunctioning message delivery transport. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). transport_time_limit (default: $command_time_limit) A transport-specific override for the command_time_limit parameter value, where transport is the master.cf name of the message delivery transport. trigger_timeout (default: 10s) The time limit for sending a trigger to a Postfix daemon (for example, the pickup(8) or qmgr(8) daemon). This time limit prevents programs from getting stuck when the mail system is under heavy load. Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks). The default time unit is s (seconds). undisclosed_recipients_header (default: To: undisclosed-recipients:;) Message header that the Postfix cleanup(8) server inserts when a message contains no To: or Cc: message header. With Postfix 2.4 and later, specify an empty value to disable this feature. unknown_address_reject_code (default: 450) The numerical Postfix SMTP server response code when a sender or recipient address is rejected by the reject_unknown_sender_domain or reject_unknown_recipient_domain restriction. The response is always 450 in case of a temporary DNS error. Do not change this unless you have a complete understanding of RFC 2821. unknown_address_tempfail_action (default: $reject_tempfail_action) The Postfix SMTP server's action when reject_unknown_sender_domain or reject_unknown_recipient_domain fail due to a temporary error condition. Specify "defer" to defer the remote SMTP client request immediately. With the default "defer_if_permit" action, the Postfix SMTP server continues to look for opportunities to reject mail, and defers the client request only if it would otherwise be accepted.

This feature is available in Postfix 2.6 and later. unknown_client_reject_code (default: 450) The numerical Postfix SMTP server response code when a client without valid address <=> name mapping is rejected by the reject_unknown_client_hostname restriction. The SMTP server always replies with 450 when the mapping failed due to a temporary error condition. Do not change this unless you have a complete understanding of RFC 2821. unknown_helo_hostname_tempfail_action (default: $reject_tempfail_action) The Postfix SMTP server's action when reject_unknown_helo_hostname fails due to an temporary error condition. Specify "defer" to defer the remote SMTP client request immediately. With the default "defer_if_permit" action, the Postfix SMTP server continues to look for opportunities to reject mail, and defers the client request only if it would otherwise be accepted. This feature is available in Postfix 2.6 and later. unknown_hostname_reject_code (default: 450) The numerical Postfix SMTP server response code when the hostname specified with the HELO or EHLO command is rejected by the reject_unknown_helo_hostname restriction. Do not change this unless you have a complete understanding of RFC 2821. unknown_local_recipient_reject_code (default: 550) The numerical Postfix SMTP server response code when a recipient address is local, and $local_recipient_maps specifies a list of lookup tables that does not match the recipient. A recipient address is local when its domain matches $mydestination, $proxy_interfaces or $inet_interfaces. The default setting is 550 (reject mail) but it is safer to initially use 450 (try again later) so you have time to find out if your local_recipient_maps settings are OK. Example:
unknown_local_recipient_reject_code = 450

This feature is available in Postfix 2.0 and later. unknown_relay_recipient_reject_code (default: 550) The numerical Postfix SMTP server reply code when a recipient address matches $relay_domains, and relay_recipient_maps specifies a list of lookup tables that does not match the recipient address. This feature is available in Postfix 2.0 and later. unknown_virtual_alias_reject_code (default: 550)

The SMTP server reply code when a recipient address matches $virtual_alias_domains, and $virtual_alias_maps specifies a list of lookup tables that does not match the recipient address. This feature is available in Postfix 2.0 and later. unknown_virtual_mailbox_reject_code (default: 550) The SMTP server reply code when a recipient address matches $virtual_mailbox_domains, and $virtual_mailbox_maps specifies a list of lookup tables that does not match the recipient address. This feature is available in Postfix 2.0 and later. unverified_recipient_defer_code (default: 450) The numerical Postfix SMTP server response when a recipient address probe fails due to a temporary error condition. Unlike elsewhere in Postfix, you can specify 250 in order to accept the address anyway. Do not change this unless you have a complete understanding of RFC 2821. This feature is available in Postfix 2.6 and later. unverified_recipient_reject_code (default: 450) The numerical Postfix SMTP server response when a recipient address is rejected by the reject_unverified_recipient restriction. Unlike elsewhere in Postfix, you can specify 250 in order to accept the address anyway. Do not change this unless you have a complete understanding of RFC 2821. This feature is available in Postfix 2.1 and later. unverified_recipient_reject_reason (default: empty) The Postfix SMTP server's reply when rejecting mail with reject_unverified_recipient. Do not include the numeric SMTP reply code or the enhanced status code. By default, the response includes actual address verification details. Example:
unverified_recipient_reject_reason = Recipient address lookup failed

This feature is available in Postfix 2.6 and later. unverified_recipient_tempfail_action (default: $reject_tempfail_action) The Postfix SMTP server's action when reject_unverified_recipient fails due to a temporary error condition. Specify "defer" to defer the remote SMTP client request immediately. With the default "defer_if_permit" action, the Postfix SMTP server continues to look for

opportunities to reject mail, and defers the client request only if it would otherwise be accepted. This feature is available in Postfix 2.6 and later. unverified_sender_defer_code (default: 450) The numerical Postfix SMTP server response code when a sender address probe fails due to a temporary error condition. Unlike elsewhere in Postfix, you can specify 250 in order to accept the address anyway. Do not change this unless you have a complete understanding of RFC 2821. This feature is available in Postfix 2.6 and later. unverified_sender_reject_code (default: 450) The numerical Postfix SMTP server response code when a recipient address is rejected by the reject_unverified_sender restriction. Unlike elsewhere in Postfix, you can specify 250 in order to accept the address anyway. Do not change this unless you have a complete understanding of RFC 2821. This feature is available in Postfix 2.1 and later. unverified_sender_reject_reason (default: empty) The Postfix SMTP server's reply when rejecting mail with reject_unverified_sender. Do not include the numeric SMTP reply code or the enhanced status code. By default, the response includes actual address verification details. Example:
unverified_sender_reject_reason = Sender address lookup failed

This feature is available in Postfix 2.6 and later. unverified_sender_tempfail_action (default: $reject_tempfail_action) The Postfix SMTP server's action when reject_unverified_sender fails due to a temporary error condition. Specify "defer" to defer the remote SMTP client request immediately. With the default "defer_if_permit" action, the Postfix SMTP server continues to look for opportunities to reject mail, and defers the client request only if it would otherwise be accepted. This feature is available in Postfix 2.6 and later. verp_delimiter_filter (default: -=+) The characters Postfix accepts as VERP delimiter characters on the Postfix sendmail(1)

command line and in SMTP commands. This feature is available in Postfix 1.1 and later. virtual_alias_domains (default: $virtual_alias_maps) Postfix is final destination for the specified list of virtual alias domains, that is, domains for which all addresses are aliased to addresses in other local or remote domains. The SMTP server validates recipient addresses with $virtual_alias_maps and rejects non-existent recipients. See also the virtual alias domain class in the ADDRESS_CLASS_README file This feature is available in Postfix 2.0 and later. The default value is backwards compatible with Postfix version 1.1. The default value is $virtual_alias_maps so that you can keep all information about virtual alias domains in one place. If you have many users, it is better to separate information that changes more frequently (virtual address -> local or remote address mapping) from information that changes less frequently (the list of virtual domain names). Specify a list of host or domain names, "/file/name" or "type:table" patterns, separated by commas and/or whitespace. A "/file/name" pattern is replaced by its contents; a "type:table" lookup table is matched when a table entry matches a lookup string (the lookup result is ignored). Continue long lines by starting the next line with whitespace. Specify "!pattern" to exclude a host or domain name from the list. The form "!/file/name" is supported only in Postfix version 2.4 and later. See also the VIRTUAL_README and ADDRESS_CLASS_README documents for further information. Example:
virtual_alias_domains = virtual1.tld virtual2.tld

virtual_alias_expansion_limit (default: 1000) The maximal number of addresses that virtual alias expansion produces from each original recipient. This feature is available in Postfix 2.1 and later. virtual_alias_maps (default: $virtual_maps) Optional lookup tables that alias specific mail addresses or domains to other local or remote address. The table format and lookups are documented in virtual(5). For an overview of Postfix address manipulations see the ADDRESS_REWRITING_README document. This feature is available in Postfix 2.0 and later. The default value is backwards compatible with Postfix version 1.1. If you use this feature with indexed files, run "postmap /etc/postfix/virtual" after changing the file.

Examples:
virtual_alias_maps = dbm:/etc/postfix/virtual virtual_alias_maps = hash:/etc/postfix/virtual

virtual_alias_recursion_limit (default: 1000) The maximal nesting depth of virtual alias expansion. Currently the recursion limit is applied only to the left branch of the expansion graph, so the depth of the tree can in the worst case reach the sum of the expansion and recursion limits. This may change in the future. This feature is available in Postfix 2.1 and later. virtual_destination_concurrency_limit (default: $default_destination_concurrency_limit) The maximal number of parallel deliveries to the same destination via the virtual message delivery transport. This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. virtual_destination_recipient_limit (default: $default_destination_recipient_limit) The maximal number of recipients per message for the virtual message delivery transport. This limit is enforced by the queue manager. The message delivery transport name is the first field in the entry in the master.cf file. Setting this parameter to a value of 1 changes the meaning of virtual_destination_concurrency_limit from concurrency per domain into concurrency per recipient. virtual_gid_maps (default: empty) Lookup tables with the per-recipient group ID for virtual(8) mailbox delivery. In a lookup table, specify a left-hand side of "@domain.tld" to match any user in the specified domain that does not have a specific "user@domain.tld" entry. When a recipient address has an optional address extension (user+foo@domain.tld), the virtual(8) delivery agent looks up the full address first, and when the lookup fails, it looks up the unextended address (user@domain.tld). Note 1: for security reasons, the virtual(8) delivery agent disallows regular expression substitution of $1 etc. in regular expression lookup tables, because that would open a security hole. Note 2: for security reasons, the virtual(8) delivery agent will silently ignore requests to use the proxymap(8) server. Instead it will open the table directly. Before Postfix version 2.2, the virtual(8) delivery agent will terminate with a fatal error. virtual_mailbox_base (default: empty) A prefix that the virtual(8) delivery agent prepends to all pathname results from $virtual_mailbox_maps table lookups. This is a safety measure to ensure that an out of control

map doesn't litter the file system with mailboxes. While virtual_mailbox_base could be set to "/", this setting isn't recommended. Example:
virtual_mailbox_base = /var/mail

virtual_mailbox_domains (default: $virtual_mailbox_maps) Postfix is final destination for the specified list of domains; mail is delivered via the $virtual_transport mail delivery transport. By default this is the Postfix virtual(8) delivery agent. The SMTP server validates recipient addresses with $virtual_mailbox_maps and rejects mail for non-existent recipients. See also the virtual mailbox domain class in the ADDRESS_CLASS_README file. This parameter expects the same syntax as the mydestination configuration parameter. This feature is available in Postfix 2.0 and later. The default value is backwards compatible with Postfix version 1.1. virtual_mailbox_limit (default: 51200000) The maximal size in bytes of an individual virtual(8) mailbox or maildir file, or zero (no limit). virtual_mailbox_lock (default: see "postconf -d" output) How to lock a UNIX-style virtual(8) mailbox before attempting delivery. For a list of available file locking methods, use the "postconf -l" command. This setting is ignored with maildir style delivery, because such deliveries are safe without application-level locks. Note 1: the dotlock method requires that the recipient UID or GID has write access to the parent directory of the recipient's mailbox file. Note 2: the default setting of this parameter is system dependent. virtual_mailbox_maps (default: empty) Optional lookup tables with all valid addresses in the domains that match $virtual_mailbox_domains. In a lookup table, specify a left-hand side of "@domain.tld" to match any user in the specified domain that does not have a specific "user@domain.tld" entry. The virtual(8) delivery agent uses this table to look up the per-recipient mailbox or maildir pathname. If the lookup result ends in a slash ("/"), maildir-style delivery is carried out, otherwise the path is assumed to specify a UNIX-style mailbox file. Note that $virtual_mailbox_base is unconditionally prepended to this path. When a recipient address has an optional address extension (user+foo@domain.tld), the

virtual(8) delivery agent looks up the full address first, and when the lookup fails, it looks up the unextended address (user@domain.tld). Note 1: for security reasons, the virtual(8) delivery agent disallows regular expression substitution of $1 etc. in regular expression lookup tables, because that would open a security hole. Note 2: for security reasons, the virtual(8) delivery agent will silently ignore requests to use the proxymap(8) server. Instead it will open the table directly. Before Postfix version 2.2, the virtual(8) delivery agent will terminate with a fatal error. virtual_maps (default: empty) Optional lookup tables with a) names of domains for which all addresses are aliased to addresses in other local or remote domains, and b) addresses that are aliased to addresses in other local or remote domains. Available before Postfix version 2.0. With Postfix version 2.0 and later, this is replaced by separate controls: virtual_alias_domains and virtual_alias_maps. virtual_minimum_uid (default: 100) The minimum user ID value that the virtual(8) delivery agent accepts as a result from $virtual_uid_maps table lookup. Returned values less than this will be rejected, and the message will be deferred. virtual_transport (default: virtual) The default mail delivery transport and next-hop destination for final delivery to domains listed with $virtual_mailbox_domains. This information can be overruled with the transport(5) table. Specify a string of the form transport:nexthop, where transport is the name of a mail delivery transport defined in master.cf. The :nexthop destination is optional; its syntax is documented in the manual page of the corresponding delivery agent. This feature is available in Postfix 2.0 and later. virtual_uid_maps (default: empty) Lookup tables with the per-recipient user ID that the virtual(8) delivery agent uses while writing to the recipient's mailbox. In a lookup table, specify a left-hand side of "@domain.tld" to match any user in the specified domain that does not have a specific "user@domain.tld" entry. When a recipient address has an optional address extension (user+foo@domain.tld), the virtual(8) delivery agent looks up the full address first, and when the lookup fails, it looks up the unextended address (user@domain.tld). Note 1: for security reasons, the virtual(8) delivery agent disallows regular expression substitution of $1 etc. in regular expression lookup tables, because that would open a security hole.

Note 2: for security reasons, the virtual(8) delivery agent will silently ignore requests to use the proxymap(8) server. Instead it will open the table directly. Before Postfix version 2.2, the virtual(8) delivery agent will terminate with a fatal error.

Rejecting Unknown Local Recipients with Postfix


Introduction
As of Postfix version 2.0, the Postfix SMTP server rejects mail for unknown recipients in local domains (domains that match $mydestination or the IP addresses in $inet_interfaces or $proxy_interfaces) with "User unknown in local recipient table". This feature was optional with earlier Postfix versions. The good news is that this keeps undeliverable mail out of your queue, so that your mail queue is not clogged up with undeliverable MAILER-DAEMON messages. The bad news is that it may cause mail to be rejected when you upgrade from a Postfix system that was not configured to reject mail for unknown local recipients. This document describes what steps are needed in order to reject unknown local recipients correctly. Configuring local_recipient_maps in main.cf When you need to change the local_recipient_maps setting in main.cf Local recipient table format

Configuring local_recipient_maps in main.cf


The local_recipient_maps parameter specifies lookup tables with all names or addresses of local recipients. A recipient address is local when its domain matches $mydestination, $inet_interfaces or $proxy_interfaces. If a local username or address is not listed in $local_recipient_maps, then the Postfix SMTP server will reject the address with "User unknown in local recipient table". The default setting, shown below, assumes that you use the default Postfix local(8) delivery agent for local delivery, where recipients are either UNIX accounts or local aliases:
/etc/postfix/main.cf: local_recipient_maps = proxy:unix:passwd.byname $alias_maps

To turn off unknown local recipient rejects by the SMTP server, specify:
/etc/postfix/main.cf: local_recipient_maps =

That is, an empty value. With this setting, the Postfix SMTP server will not reject mail with "User unknown in local recipient table". Don't do this on systems that receive mail directly from the Internet. With today's worms and viruses, Postfix will become a backscatter source: it accepts mail for non-existent recipients and then tries to return that mail as "undeliverable" to the often forged sender address.

When you need to change the local_recipient_maps setting in main.cf


Problem: you don't use the default Postfix local(8) delivery agent for domains matching $mydestination, $inet_interfaces, or $proxy_interfaces. For example, you redefined the "local_transport" setting in main.cf. Solution: your local_recipient_maps setting needs to specify a database that lists all the known user names or addresses for that delivery agent. For example, if you deliver users in $mydestination etc. domains via the virtual(8) delivery agent, specify:
/etc/postfix/main.cf mydestination = $myhostname localhost.$mydomain localhost ... local_transport = virtual local_recipient_maps = $virtual_mailbox_maps

If you use a different delivery agent for $mydestination etc. domains, see the section "Local recipient table format" below for a description of how the table should be populated. Problem: you use the mailbox_transport or fallback_transport feature of the Postfix local(8) delivery agent in order to deliver mail to non-UNIX accounts. Solution: you need to add the database that lists the non-UNIX users:
/etc/postfix/main.cf local_recipient_maps = proxy:unix:passwd.byname, $alias_maps, <the database with non-UNIX accounts>

See the section "Local recipient table format" below for a description of how the table should be populated. Problem: you use the luser_relay feature of the Postfix local delivery agent. Solution: you must disable the local_recipient_maps feature completely, so that Postfix accepts mail for all local addresses:
/etc/postfix/main.cf local_recipient_maps =

Local recipient table format


If you use local files in postmap(1) format, then local_recipient_maps expects the following table format: In the left-hand side, specify a bare username, an "@domain.tld" wild-card, or specify a complete "user@domain.tld" address. You have to specify something on the right-hand side of the table, but the value is ignored by local_recipient_maps. If you use lookup tables based on NIS, LDAP, MYSQL, or PGSQL, then local_recipient_maps does the same queries as for local files in postmap(1) format, and expects the same results. With regular expression tables, Postfix only queries with the full recipient address, and not with the bare username or the "@domain.tld" wild-card. NOTE: a lookup table should always return a result when the address exists, and should always return "not found" when the address does not exist. In particular, a zero-length result does not count as a "not found" result.

Postfix Address Classes


Introduction
Postfix version 2.0 introduces the concept of address classes. This is a way of grouping recipient addresses by their delivery method. The idea comes from discussions with Victor Duchovni. Although address classes introduced a few incompatibilities they also made it possible to improve the handling of hosted domains and of unknown recipients. This document provides information on the following topics: What are address classes good for? What address classes does Postfix implement? Improvements compared to Postfix 1.1 Incompatibilities with Postfix 1.1

What are address classes good for?


Why should you care about address classes? This is how Postfix decides what mail to accept, and how to deliver it. In other words, address classes are very important for the operation of Postfix. An address class is defined by three items. The list of domains that are a member of the class: for example, all local domains, or all relay domains. The default delivery transport. For example, the local, virtual or relay delivery transport (delivery transports are defined in master.cf). This helps to keep Postfix configurations simple, by avoiding the need for explicit routing information in transport maps. The list of valid recipient addresses for that address class. The Postfix SMTP server rejects invalid recipients with "User unknown in <name of address class here> table". This helps to keep the Postfix queue free of undeliverable MAILER-DAEMON messages.

What address classes does Postfix implement?


Initially the list of address classes is hard coded, but this is meant to become extensible. The summary below describes the main purpose of each class, and what the relevant configuration parameters are. The local domain class. Purpose: final delivery for traditional UNIX system accounts and traditional Sendmail-style aliases. This is typically used for the canonical domains of the machine. For a discussion of the difference between canonical domains, hosted domains and other domains, see the VIRTUAL_README file. Domain names are listed with the mydestination parameter. This domain class also includes mail for user@[ipaddress] when the IP address is listed with the inet_interfaces or proxy_interfaces parameters.

Valid recipient addresses are listed with the local_recipient_maps parameter, as described in LOCAL_RECIPIENT_README. The Postfix SMTP server rejects invalid recipients with "User unknown in local recipient table". If the local_recipient_maps parameter value is empty, then the Postfix SMTP server accepts any address in the local domain class. The mail delivery transport is specified with the local_transport parameter. The default value is local:$myhostname for delivery with the local(8) delivery agent. The virtual alias domain class. Purpose: hosted domains where each recipient address is aliased to a local UNIX system account or to a remote address. A virtual alias example is given in the VIRTUAL_README file. Domain names are listed in virtual_alias_domains. The default value is $virtual_alias_maps for Postfix 1.1 compatibility. Valid recipient addresses are listed with the virtual_alias_maps parameter. The Postfix SMTP server rejects invalid recipients with "User unknown in virtual alias table". The default value is $virtual_maps for Postfix 1.1 compatibility. There is no mail delivery transport parameter. Every address must be aliased to some other address. The virtual mailbox domain class. Purpose: final delivery for hosted domains where each recipient address can have its own mailbox, and where users do not need to have a UNIX system account. A virtual mailbox example is given in the VIRTUAL_README file. Domain names are listed with the virtual_mailbox_domains parameter. The default value is $virtual_mailbox_maps for Postfix 1.1 compatibility. Valid recipient addresses are listed with the virtual_mailbox_maps parameter. The Postfix SMTP server rejects invalid recipients with "User unknown in virtual mailbox table". If this parameter value is empty, the Postfix SMTP server accepts all recipients for domains listed in $virtual_mailbox_domains. The mail delivery transport is specified with the virtual_transport parameter. The default value is virtual for delivery with the virtual(8) delivery agent. The relay domain class. Purpose: mail forwarding to remote destinations that list your system as primary or backup MX host. For a discussion of the basic configuration details, see the BASIC_CONFIGURATION_README document. For a discussion of the difference between canonical domains, hosted domains and other domains, see the VIRTUAL_README file. Domain names are listed with the relay_domains parameter. Valid recipient addresses are listed with the relay_recipient_maps parameter. The Postfix SMTP server rejects invalid recipients with "User unknown in relay recipient table". If this parameter value is empty, the Postfix SMTP server accepts all recipients for domains listed with the relay_domains parameter. The mail delivery transport is specified with the relay_transport parameter. The default value is relay which is a clone of the smtp(8) delivery agent. The default domain class.

Purpose: mail forwarding to the Internet on behalf of authorized clients. For a discussion of the basic configuration details, see the BASIC_CONFIGURATION_README file. For a discussion of the difference between canonical domains, hosted domains and other domains, see the VIRTUAL_README file. This class has no destination domain table. This class has no valid recipient address table. The mail delivery transport is specified with the default_transport parameter. The default value is smtp for delivery with the smtp(8) delivery agent.

Improvements compared to Postfix 1.1


Postfix 2.0 address classes made the following improvements possible over earlier Postfix versions: You no longer need to specify all the virtual(8) mailbox domains in the Postfix transport map. The virtual(8) delivery agent has become a first-class citizen just like local(8) or smtp(8). On mail gateway systems, address classes provide separation of inbound mail relay traffic ($relay_transport) from outbound traffic ($default_transport). This eliminates a problem where inbound mail deliveries could become resource starved in the presence of a high volume of outbound mail. The SMTP server rejects unknown recipients in a more consistent manner than was possible with Postfix version 1. This is needed to keep undeliverable mail (and bounced undeliverable mail) out of the mail queue. This is controlled by the smtpd_reject_unlisted_recipient configuration parameter. As of Postfix version 2.1, the SMTP server also rejects unknown sender addresses (i.e. addresses that it would reject as unknown recipient addresses). Sender "egress filtering" can help to slow down an email worm explosion. This is controlled by the smtpd_reject_unlisted_sender configuration parameter.

Incompatibilities with Postfix 1.1


Postfix 2.0 address classes introduce a few incompatible changes in documented behavior. In order to ease the transitions, new parameters have default values that are backwards compatible. The virtual_maps parameter is replaced by virtual_alias_maps (for address lookups) and by virtual_alias_domains (for the names of what were formerly called "Postfix-style virtual domains"). For backwards compatibility with Postfix version 1.1, the new virtual_alias_maps parameter defaults to $virtual_maps, and the new virtual_alias_domains parameter defaults to $virtual_alias_maps. The virtual_mailbox_maps parameter now has a companion parameter called virtual_mailbox_domains (for the names of domains served by the virtual delivery agent). The virtual_mailbox_maps parameter is now used for address lookups only. For backwards compatibility with Postfix version 1.1, the new virtual_mailbox_domains parameter defaults to $virtual_mailbox_maps. Introduction of the relay_recipient_maps parameter. The Postfix SMTP server can use this to block mail for relay recipients that don't exist. This list is empty by default, which means accept any recipient.

The local_recipient_maps feature is now turned on by default. The Postfix SMTP server uses this to reject mail for unknown local recipients. See the LOCAL_RECIPIENT_README file hints and tips. Introduction of the relay delivery transport in master.cf. This helps to avoid mail delivery scheduling problems on inbound mail relays when there is a lot of outbound mail, but may require that you update your "defer_transports" setting.

Postfix Connection Cache


Introduction
This document describes the Postfix connection cache implementation, which is available with Postfix version 2.2 and later. Topics covered in this document: What SMTP connection caching can do for you Connection cache implementation Connection cache configuration Connection cache safety mechanisms Connection cache limitations Connection cache statistics

What SMTP connection caching can do for you


With SMTP connection caching, Postfix can deliver multiple messages over the same SMTP connection. By default, Postfix 2.2 reuses an SMTP connection automatically when a destination has high volume of mail in the active queue. SMTP Connection caching is a performance feature. Whether or not it actually improves performance depends on the conditions: SMTP Connection caching can greatly improve performance when delivering mail to a destination with multiple mail servers, because it can help Postfix to skip over a nonresponding server. Otherwise, the benefits of SMTP connection caching are minor: it eliminates the latency of the TCP handshake (SYN, SYN+ACK, ACK), plus the latency of the SMTP initial handshake (220 greeting, EHLO command, EHLO response). SMTP Connection caching gives no gains with respect to SMTP session tear-down. The Postfix smtp(8) client normally does not wait for the server's reply to the QUIT command, and it never waits for the TCP final handshake to complete. SMTP Connection caching introduces some overhead: the client needs to send an RSET command to find out if a connection is still usable, before it can send the next MAIL FROM command. For other potential issues with SMTP connection caching, see the discussion of limitations at the end of this document.

Connection cache implementation


For an overview of how Postfix delivers mail, see the Postfix architecture OVERVIEW document. The Postfix connection cache is shared among Postfix mail delivering processes. This maximizes the opportunity to reuse an open connection. Other MTAs such as Sendmail or exim have a non-

shared connection cache. Here, a connection can be reused only by the mail delivering process that creates the connection. To get the same performance improvement as with a shared connection cache, non-shared connections need to be kept open for a longer time. The scache(8) server, introduced with Postfix version 2.2, maintains the shared connection cache. With Postfix version 2.2, only the smtp(8) client has support to access this cache. smtp(8) --> Internet | qmgr(8) | smtp(8) --> Internet \-| | ^ v | scache(8) When SMTP connection caching is enabled (see next section), the smtp(8) client does not disconnect after a mail transaction, but gives the connection to the scache(8) server which keeps the connection open for a limited amount of time. After handing over the open connection to the scache(8) server, the smtp(8) client continues with some other mail delivery request. Meanwhile, any smtp(8) client process can ask the scache(8) server for that cached connection and reuse it for mail delivery. The connection cache can be searched by destination domain name (the right-hand side of the recipient address) and by the IP address of the host at the other end of the connection. This allows Postfix to reuse a connection even when the remote host is mail server for domains with different names. /--

Connection cache configuration


The Postfix smtp(8) client supports two connection caching strategies: On-demand connection caching. This is enabled by default, and is controlled with the smtp_connection_cache_on_demand configuration parameter. When this feature is enabled, the Postfix smtp(8) client automatically saves a connection to the connection cache when a destination has a high volume of mail in the active queue. Example:
/etc/postfix/main.cf: smtp_connection_cache_on_demand = yes

Per-destination connection caching. This is enabled by explicitly listing specific destinations with the smtp_connection_cache_destinations configuration parameter. After completing delivery to a selected destination, the Postfix smtp(8) client always saves the connection to the connection cache. Specify a comma or white space separated list of destinations or pseudo-destinations: if mail is sent without a relay host: a domain name (the right-hand side of an email address, without the [] around a numeric IP address), if mail is sent via a relay host: a relay host name (without the [] or non-default TCP port), as specified in main.cf or in the transport map, a /file/name with domain names and/or relay host names as defined above, a "type:table" with domain names and/or relay host names on the left-hand side. The right-hand side result from "type:table" lookups is ignored.

Examples:
/etc/postfix/main.cf: smtp_connection_cache_destinations = $relayhost smtp_connection_cache_destinations = hotmail.com, ... smtp_connection_cache_destinations = static:all (not recommended)

Connection cache safety mechanisms


Connection caching must be used wisely. It is anti-social to keep an unused SMTP connection open for a significant amount of time, and it is unwise to send huge numbers of messages through the same connection. In order to avoid problems with SMTP connection caching, Postfix implements the following safety mechanisms: The Postfix scache(8) server keeps a connection open for only a limited time. The time limit is specified with the smtp_connection_cache_time_limit and with the connection_cache_ttl_limit configuration parameters. This prevents anti-social behavior. The Postfix smtp(8) client reuses a session for only a limited number of times. This avoids triggering bugs in implementations that do not correctly handle multiple deliveries per session. With Postfix 2.2 the use count is limited with the smtp_connection_cache_reuse_limit configuration parameter. With Postfix 2.3 this is replaced by a time limit which is specified with the smtp_connection_reuse_time_limit parameter. In addition, Postfix 2.3 logs the use count of multiply-used connections, as shown in the following example:
Nov 3 16:04:31 myname postfix/smtp[30840]: 19B6B2900FE: to=<wietse@test.example.com>, orig_to=<wietse@test>, relay=mail.example.com[1.2.3.4], conn_use=2, delay=0.22, delays=0.04/0.01/0.05/0.1, dsn=2.0.0, status=sent (250 2.0.0 Ok)

The connection cache explicitly labels each cached connection with destination domain and IP address information. A connection cache lookup succeeds only when the correct information is specified. This prevents mis-delivery of mail.

Connection cache limitations


Postfix SMTP connection caching conflicts with certain applications: The Postfix shared connection cache cannot be used with TLS, because saved TLS session information can be used only when a new connection is created (this limitation does not exist in connection caching implementations that reuse a connection only in the process that creates it). For this reason, the Postfix smtp(8) client always closes the connection after completing an attempt to deliver mail over TLS. Postfix connection caching currently does not support multiple SASL accounts per mail server. Specifically, Postfix connection caching assumes that a SASL credential is valid for all hostnames or domain names that deliver via the same mail server IP address and TCP port, and assumes that the SASL credential does not depend on the message originator.

Connection cache statistics


The scache(8) connection cache server logs statistics about the peak cache size and the cache hit rates. This information is logged every connection_cache_status_update_time seconds, when the

process terminates after the maximal idle time is exceeded, or when Postfix is reloaded. Hit rates for connection cache lookups by domain will tell you how useful connection caching is. Connection cache lookups by network address will always fail, unless you're sending mail to different domains that share the same MX hosts. No statistics are logged when no attempts are made to access the connection cache.

Postfix DSN Support


Introduction
Postfix version 2.3 introduces support for Delivery Status Notifications as described in RFC 3464. This gives senders control over successful and failed delivery notifications. Specifically, DSN support gives an email sender the ability to specify: What notifications are sent: success, failure, delay, or none. Normally, Postfix informs the sender only when mail delivery is delayed or when delivery fails. What content is returned in case of failure: only the message headers, or the full message. An envelope ID that is returned as part of delivery status notifications. This identifies the message submission transaction, and must not be confused with the message ID, which identifies the message content. The implementation of DSN support involves extra parameters to the SMTP MAIL FROM and RCPT TO commands, as well as two Postfix sendmail command line options that provide a sub-set of the functions of the extra SMTP command parameters. This document has information on the following topics: Restricting the scope of "success" notifications Postfix sendmail command-line interface Postfix VERP support compatibility

Restricting the scope of "success" notifications


Just like reports of undeliverable mail, DSN reports of successful delivery can give away more information about the internal infrastructure than desirable. Unfortunately, disallowing "success" notification requests requires disallowing other DSN requests as well. The RFCs do not offer the option to negotiate feature subsets. This is not as bad as it sounds. When you turn off DSN for remote inbound mail, remote senders with DSN support will still be informed that their mail reached your Postfix gateway successfully; they just will not get successful delivery notices from your internal systems. Remote senders lose very little: they can no longer specify how Postfix should report delayed or failed delivery. Use the smtpd_discard_ehlo_keyword_address_maps feature if you wish to allow DSN requests from trusted clients but not from random strangers (see below for how to turn this off for all clients):
/etc/postfix/main.cf: smtpd_discard_ehlo_keyword_address_maps = cidr:/etc/postfix/esmtp_access /etc/postfix/esmtp_access: # Allow DSN requests from local subnet only 192.168.0.0/28 silent-discard 0.0.0.0/0 silent-discard, dsn

::/0

silent-discard, dsn

If you want to disallow all use of DSN requests from the network, use the smtpd_discard_ehlo_keywords feature:
/etc/postfix/main.cf: smtpd_discard_ehlo_keywords = silent-discard, dsn

Postfix sendmail command-line interface


Postfix has two Sendmail-compatible command-line options for DSN support. The first option specifies what notifications are sent for mail that is submitted via the Postfix sendmail(1) command line:
$ sendmail -N success,delay,failure ... (one or more of these) $ sendmail -N never ... (or just this by itself)

The built-in default corresponds with "delay,failure". The second option specifies an envelope ID which is reported in delivery status notifications for mail that is submitted via the Postfix sendmail(1) command line:
$ sendmail -V envelope-id ...

Note: this conflicts with VERP support in older Postfix versions, as discussed in the next section.

Postfix VERP support compatibility


With Postfix versions before 2.3, the sendmail(1) command uses the -V command-line option to request VERP-style delivery. In order to request VERP style delivery with Postfix 2.3 and later, you must specify -XV instead of -V. The Postfix 2.3 sendmail(1) command will recognize if you try to use -V for VERP-style delivery. It will do the right thing and will remind you of the new syntax.

Guidelines for Package Builders


Purpose of this document
This document has hints and tips for those who manage their own Postfix distribution for internal use, and for those who maintain Postfix distributions for general use.

General distributions: please provide a small default main.cf file


The installed main.cf file must be small. PLEASE resist the temptation to list all parameters in the main.cf file. Postfix is supposed to be easy to configure. Listing all parameters in main.cf defeats the purpose. It is an invitation for hobbyists to make random changes without understanding what they do, and gets them into endless trouble.

General distributions: please include README or HTML files


Please provide the applicable README or HTML files. They are referenced by the Postfix manual pages and by other files. Without README or HTML files, Postfix will be difficult if not impossible to configure.

Postfix Installation parameters


Postfix installation is controlled by a dozen installation parameters. See the postfix-install and postinstall files for details. Most parameters have system-dependent default settings that are configurable at compile time, as described in the INSTALL file.

Preparing a pre-built package for distribution to other systems


You can build a Postfix package on a machine that does not have Postfix installed on it. All you need is Postfix source code and a compilation environment that is compatible with the target system. You can build a pre-built Postfix package as an unprivileged user. First compile Postfix. After successful compilation, execute:
% make package

With Postfix versions before 2.2 you must invoke the post-install script directly (% sh postinstall). You will be prompted for installation parameters. Specify an install_root directory other than /. The mail_owner and setgid_group installation parameter settings will be recorded in the main.cf file, but they won't take effect until the package is unpacked and installed on the destination machine.

If you want to fully automate this process, specify all the non-default installation parameters on the command line:
% make non-interactive-package install_root=/some/where...

With Postfix versions before 2.2 you must invoke the post-install script directly (% sh postinstall -non-interactive install_root...).

Begin Security Alert


When building an archive for distribution, be sure to archive only files and symbolic links, not their parent directories. Otherwise, unpacking a pre-built Postfix package may mess up permission and/or ownership of system directories such as / /etc /usr /usr/bin /var /var/spool and so on. This is especially an issue if you executed postfix-install (see above) as an unprivileged user.

End Security Alert


Thus, to tar up the pre-built package, take the following steps:
% % % % cd INSTALL_ROOT rm -f SOMEWHERE/outputfile find . \! -type d -print | xargs tar rf SOMEWHERE/outputfile gzip SOMEWHERE/outputfile

This way you will not include any directories that might cause trouble upon extraction.

Installing a pre-built Postfix package


To unpack a pre-built Postfix package, execute the equivalent of:
# umask 022 # gzip -d <outputfile.tar.gz | (cd / ; tar xvpf -)

The umask command is necessary for getting the correct permissions on non-Postfix directories that need to be created in the process. Create the necessary mail_owner account and setgid_group group for exclusive use by Postfix. Execute the postfix command to set ownership and permission of Postfix files and directories, and to update Postfix configuration files. If necessary, specify any non-default settings for mail_owner or setgid_group on the postfix command line:
# postfix set-permissions upgrade-configuration \ setgid_group=xxx mail_owner=yyy

With Postfix versions before 2.1 you achieve the same result by invoking the post-install script directly.

Postfix Queue Scheduler


Overview
The queue manager is by far the most complex part of the Postfix mail system. It schedules delivery of new mail, retries failed deliveries at specific times, and removes mail from the queue after the last delivery attempt. There are two major classes of mechanisms that control the operation of the queue manager. Topics covered by this document: Concurrency scheduling, concerned with the number of concurrent deliveries to a specific destination, including decisions on when to suspend deliveries after persistent failures. Preemptive scheduling, concerned with the selection of email messages and recipients for a given destination. Credits, something this document would not be complete without.

Concurrency scheduling
The following sections document the Postfix 2.5 concurrency scheduler, after a discussion of the limitations of the existing concurrency scheduler. This is followed by results of mediumconcurrency experiments, and a discussion of trade-offs between performance and robustness. The material is organized as follows: Drawbacks of the existing concurrency scheduler Summary of the Postfix 2.5 concurrency feedback algorithm Summary of the Postfix 2.5 "dead destination" detection algorithm Pseudocode for the Postfix 2.5 concurrency scheduler Results for delivery to concurrency limited servers Discussion of concurrency limited server results Limitations of less-than-1 per delivery feedback Concurrency configuration parameters

Drawbacks of the existing concurrency scheduler


From the start, Postfix has used a simple but robust algorithm where the per-destination delivery concurrency is decremented by 1 after delivery failed due to connection or handshake failure, and incremented by 1 otherwise. Of course the concurrency is never allowed to exceed the maximum per-destination concurrency limit. And when a destination's concurrency level drops to zero, the destination is declared "dead" and delivery is suspended. Drawbacks of +/-1 concurrency feedback per delivery are: Overshoot due to exponential delivery concurrency growth with each pseudo-cohort(*). This can be an issue with high-concurrency channels. For example, with the default initial concurrency of 5, concurrency would proceed over time as (5-10-20).

Throttling down to zero concurrency after a single pseudo-cohort(*) failure. This was especially an issue with low-concurrency channels where a single failure could be sufficient to mark a destination as "dead", causing the suspension of further deliveries to the affected destination. (*) A pseudo-cohort is a number of delivery requests equal to a destination's delivery concurrency. The revised concurrency scheduler has a highly modular structure. It uses separate mechanisms for per-destination concurrency control and for "dead destination" detection. The concurrency control in turn is built from two separate mechanisms: it supports less-than-1 feedback per delivery to allow for more gradual concurrency adjustments, and it uses feedback hysteresis to suppress concurrency oscillations. And instead of waiting for delivery concurrency to throttle down to zero, a destination is declared "dead" after a configurable number of pseudo-cohorts reports connection or handshake failure.

Summary of the Postfix 2.5 concurrency feedback algorithm


We want to increment a destination's delivery concurrency when some (not necessarily consecutive) number of deliveries complete without connection or handshake failure. This is implemented with positive feedback g(N) where N is the destination's delivery concurrency. With g(N)=1 feedback per delivery, concurrency increases by 1 after each positive feedback event; this gives us the old scheduler's exponential growth in time. With g(N)=1/N feedback per delivery, concurrency increases by 1 after an entire pseudo-cohort N of positive feedback reports; this gives us linear growth in time. Less-than-1 feedback per delivery and integer truncation naturally give us hysteresis, so that transitions to larger concurrency happen every 1/g(N) positive feedback events. We want to decrement a destination's delivery concurrency when some (not necessarily consecutive) number of deliveries complete after connection or handshake failure. This is implemented with negative feedback f(N) where N is the destination's delivery concurrency. With f(N)=1 feedback per delivery, concurrency decreases by 1 after each negative feedback event; this gives us the old scheduler's behavior where concurrency is throttled down dramatically after a single pseudo-cohort failure. With f(N)=1/N feedback per delivery, concurrency backs off more gently. Again, less-than-1 feedback per delivery and integer truncation naturally give us hysteresis, so that transitions to lower concurrency happen every 1/f(N) negative feedback events. However, with negative feedback we introduce a subtle twist. We "reverse" the negative hysteresis cycle so that the transition to lower concurrency happens at the beginning of a sequence of 1/f(N) negative feedback events. Otherwise, a correction for overload would be made too late. This makes the choice of f(N) relatively unimportant, as borne out by measurements later in this document. In summary, the main ingredients for the Postfix 2.5 concurrency feedback algorithm are a) the option of less-than-1 positive feedback per delivery to avoid overwhelming servers, b) the option of less-than-1 negative feedback per delivery to avoid giving up too fast, c) feedback hysteresis to avoid rapid oscillation, and d) a "reverse" hysteresis cycle for negative feedback, so that it can correct for overload quickly.

Summary of the Postfix 2.5 "dead destination" detection algorithm


We want to suspend deliveries to a specific destination after some number of deliveries suffers connection or handshake failure. The old scheduler declares a destination "dead" when negative (-1) feedback throttles the delivery concurrency down to zero. With less-than-1 feedback per delivery, this throttling down would obviously take too long. We therefore have to separate "dead destination" detection from concurrency feedback. This is implemented by introducing the concept of pseudo-cohort failure. The Postfix 2.5 concurrency scheduler declares a destination "dead" after a configurable number of pseudo-cohorts suffers from connection or handshake failures. The old

scheduler corresponds to the special case where the pseudo-cohort failure limit is equal to 1.

Pseudocode for the Postfix 2.5 concurrency scheduler


The pseudo code shows how the ideas behind new concurrency scheduler are implemented as of November 2007. The actual code can be found in the module qmgr/qmgr_queue.c.
Types: Each destination has one set of the following variables int concurrency double success double failure double fail_cohorts Feedback functions: N is concurrency; x, y are arbitrary numbers in [0..1] inclusive positive feedback: g(N) = x/N | x/sqrt(N) | x negative feedback: f(N) = y/N | y/sqrt(N) | y Initialization: concurrency = initial_concurrency success = 0 failure = 0 fail_cohorts = 0 After success: fail_cohorts = 0 Be prepared for feedback > hysteresis, or rounding error success += g(concurrency) while (success >= 1) Hysteresis 1 concurrency += 1 Hysteresis 1 failure = 0 success -= 1 Hysteresis 1 Be prepared for overshoot if (concurrency > concurrency limit) concurrency = concurrency limit Safety: Don't apply positive feedback unless concurrency < busy_refcount + init_dest_concurrency otherwise negative feedback effect could be delayed After failure: if (concurrency > 0) fail_cohorts += 1.0 / concurrency if (fail_cohorts > cohort_failure_limit) concurrency = 0 if (concurrency > 0) Be prepared for feedback > hysteresis, rounding errors failure -= f(concurrency) while (failure < 0) concurrency -= 1 Hysteresis 1 failure += 1 Hysteresis 1 success = 0 Be prepared for overshoot if (concurrency < 1) concurrency = 1

Results for delivery to concurrency-limited servers


Discussions about the concurrency scheduler redesign started early 2004, when the primary goal was to find alternatives that did not exhibit exponential growth or rapid concurrency throttling. No code was implemented until late 2007, when the primary concern had shifted towards better handling of server concurrency limits. For this reason we measure how well the new scheduler does this job. The table below compares mail delivery performance of the old +/-1 feedback per delivery with several less-than-1 feedback functions, for different limited-concurrency server scenarios. Measurements were done with a FreeBSD 6.2 client and with FreeBSD 6.2 and various Linux servers. Server configuration: The mail flow was slowed down with 1 second latency per recipient ("smtpd_client_restrictions = sleep 1"). The purpose was to make results less dependent on hardware details, by avoiding slow-downs by queue file I/O, logging I/O, and network I/O. Concurrency was limited by the server process limit ("default_process_limit = 5" and "smtpd_client_event_limit_exceptions = static:all"). Postfix was stopped and started after changing the process limit, because the same number is also used as the backlog argument to the listen(2) system call, and "postfix reload" does not re-issue this call. Mail was discarded with "local_recipient_maps = static:all" and "local_transport = discard". The discard action in access maps or header/body checks could not be used as it fails to update the in_flow_delay counters. Client configuration: Queue file overhead was minimized by sending one message to a virtual alias that expanded into 2000 different remote recipients. All recipients were accounted for according to the maillog file. The virtual_alias_expansion_limit setting was increased to avoid complaints from the cleanup(8) server. The number of deliveries was maximized with "smtp_destination_recipient_limit = 2". A smaller limit would cause Postfix to schedule the concurrency per recipient instead of domain, which is not what we want. Maximum concurrency was limited with "smtp_destination_concurrency_limit = 20", and initial_destination_concurrency was set to the same value. The positive and negative concurrency feedback hysteresis was 1. Concurrency was incremented by 1 at the END of 1/feedback steps of positive feedback, and was decremented by 1 at the START of 1/feedback steps of negative feedback. The SMTP client used the default 30s SMTP connect timeout and 300s SMTP greeting timeout. Impact of the 30s SMTP connect timeout The first results are for a FreeBSD 6.2 server, where our artificially low listen(2) backlog results in a very short kernel queue for established connections. The table shows that all deferred deliveries failed due to a 30s connection timeout, and none failed due to a server greeting timeout. This measurement simulates what happens when the server's connection queue is completely full under load, and the TCP engine drops new connections. client server feedback connection percentage limit limit style caching deferred client timed-out in concurrency connect/greeting average/stddev 19.4 0.49 198 -

20

1/N

no

9.9

20 20 20 20 20

5 5 5 5 5

1/N 1/sqrt(N) 1/sqrt(N) 1 1

yes no yes no yes

10.3 10.4 10.6 10.1 10.8

19.4 19.6 19.6 19.5 19.3

0.49 0.59 0.61 1.29 1.57

206 208 212 202 216

A busy server with a completely full connection queue. N is the client delivery concurrency. Failed deliveries time out after 30s without completing the TCP handshake. See text for a discussion of results. Impact of the 300s SMTP greeting timeout The next table shows results for a Fedora Core 8 server (results for RedHat 7.3 are identical). In this case, the artificially small listen(2) backlog argument does not impact our measurement. The table shows that practically all deferred deliveries fail after the 300s SMTP greeting timeout. As these timeouts were 10x longer than with the first measurement, we increased the recipient count (and thus the running time) by a factor of 10 to keep the results comparable. The deferred mail percentages are a factor 10 lower than with the first measurement, because the 1s per-recipient delay was 1/300th of the greeting timeout instead of 1/30th of the connection timeout. client server feedback connection percentage limit limit style caching deferred client timed-out in concurrency connect/greeting average/stddev 19.8 19.8 19.9 20.0 20.0 20.0 0.37 0.36 0.23 0.23 0.16 0.16 4 230 272 238 272 236 278

20 20 20 20 20 20

5 5 5 5 5 5

1/N 1/N 1/sqrt(N) 1/sqrt(N) 1 1

no yes no yes no yes

1.16 1.36 1.21 1.36 1.18 1.39

A busy server with a non-full connection queue. N is the client delivery concurrency. Failed deliveries complete at the TCP level, but time out after 300s while waiting for the SMTP greeting. See text for a discussion of results. Impact of active server concurrency limiter The final concurrency-limited result shows what happens when SMTP connections don't time out, but are rejected immediately with the Postfix server's smtpd_client_connection_count_limit feature (the server replies with a 421 status and disconnects immediately). Similar results can be expected with concurrency limiting features built into other MTAs or firewalls. For this measurement we specified a server concurrency limit and a client initial destination concurrency of 5, and a server process limit of 10; all other conditions were the same as with the first measurement. The same result would be obtained with a FreeBSD or Linux server, because the "pushing back" is done entirely by the receiving side. client server feedback connection percentage client concurrency theoretical limit limit style caching deferred average/stddev defer rate

20 20 20 20 20 20

5 5 5 5 5 5

1/N 1/N 1/sqrt(N) 1/sqrt(N) 1 1

no yes no yes no yes

16.5 16.5 24.5 24.3 49.7 49.7

5.17 5.17 5.28 5.28 5.63 5.68

0.38 0.38 0.45 0.46 0.67 0.70

1/6 1/6 1/4 1/4 1/2 1/2

A server with active per-client concurrency limiter that replies with 421 and disconnects. N is the client delivery concurrency. The theoretical defer rate is 1/ (1+roundup(1/feedback)). This is always 1/2 with the fixed +/-1 feedback per delivery; with the concurrency-dependent feedback variants, the defer rate decreases with increasing concurrency. See text for a discussion of results.

Discussion of concurrency-limited server results


All results in the previous sections are based on the first delivery runs only; they do not include any second etc. delivery attempts. It's also worth noting that the measurements look at steady-state behavior only. They don't show what happens when the client starts sending at a much higher or lower concurrency. The first two examples show that the effect of feedback is negligible when concurrency is limited due to congestion. This is because the initial concurrency is already at the client's concurrency maximum, and because there is 10-100 times more positive than negative feedback. Under these conditions, it is no surprise that the contribution from SMTP connection caching is also negligible. In the last example, the old +/-1 feedback per delivery will defer 50% of the mail when confronted with an active (anvil-style) server concurrency limit, where the server hangs up immediately with a 421 status (a TCP-level RST would have the same result). Less aggressive feedback mechanisms fare better than more aggressive ones. Concurrency-dependent feedback fares even better at higher concurrencies than shown here, but has limitations as discussed in the next section.

Limitations of less-than-1 per delivery feedback


Less-than-1 feedback is of interest primarily when sending large amounts of mail to destinations with active concurrency limiters (servers that reply with 421, or firewalls that send RST). When sending small amounts of mail per destination, less-than-1 per-delivery feedback won't have a noticeable effect on the per-destination concurrency, because the number of deliveries to the same destination is too small. You might just as well use zero per-delivery feedback and stay with the initial per-destination concurrency. And when mail deliveries fail due to congestion instead of active concurrency limiters, the measurements above show that per-delivery feedback has no effect. With large amounts of mail you might just as well use zero per-delivery feedback and start with the maximal per-destination concurrency. The scheduler with less-than-1 concurrency feedback per delivery solves a problem with servers that have active concurrency limiters. This works only because feedback is handled in a peculiar manner: positive feedback will increment the concurrency by 1 at the end of a sequence of events of length 1/feedback, while negative feedback will decrement concurrency by 1 at the beginning of such a sequence. This is how Postfix adjusts quickly for overshoot without causing lots of mail to be deferred. Without this difference in feedback treatment, less-than-1 feedback per delivery would defer 50% of the mail, and would be no better in this respect than the old +/-1 feedback per

delivery. Unfortunately, the same feature that corrects quickly for concurrency overshoot also makes the scheduler more sensitive for noisy negative feedback. The reason is that one lonely negative feedback event has the same effect as a complete sequence of length 1/feedback: in both cases delivery concurrency is dropped by 1 immediately. As a worst-case scenario, consider multiple servers behind a load balancer on a single IP address, and no backup MX address. When 1 out of K servers fails to complete the SMTP handshake or drops the connection, a scheduler with 1/N (N = concurrency) feedback stops increasing its concurrency once it reaches a concurrency level of about K, even though the good servers behind the load balancer are perfectly capable of handling more traffic. This noise problem gets worse as the amount of positive feedback per delivery gets smaller. A compromise is to use fixed less-than-1 positive feedback values instead of concurrency-dependent positive feedback. For example, to tolerate 1 of 4 bad servers in the above load balancer scenario, use positive feedback of 1/4 per "good" delivery (no connect or handshake error), and use an equal or smaller amount of negative feedback per "bad" delivery. The downside of using concurrencyindependent feedback is that some of the old +/-1 feedback problems will return at large concurrencies. Sites that must deliver mail at non-trivial per-destination concurrencies will require special configuration.

Concurrency configuration parameters


The Postfix 2.5 concurrency scheduler is controlled with the following configuration parameters, where "transport_foo" provides a transport-specific parameter override. All parameter default settings are compatible with earlier Postfix versions. Parameter name Postfix version Description

initial_destination_concurre ncy transport_initial_destinatio n_concurrency default_destination_concurr ency_limit transport_destination_conc urrency_limit default_destination_concurr ency_positive_feedback transport_destination_conc urrency_positive_feedback default_destination_concurr ency_negative_feedback transport_destination_conc urrency_negative_feedback default_destination_concurr ency_failed_cohort_limit transport_destination_conc urrency_failed_cohort_limit destination_concurrency_fe edback_debug

all 2.5

Initial per-destination delivery concurrency

all all

Maximum per-destination delivery concurrency Per-destination positive feedback amount, per delivery that does not fail with connection or handshake failure Per-destination negative feedback amount, per delivery that fails with connection or handshake failure Number of failed pseudo-cohorts after which a destination is declared "dead" and delivery is suspended Enable verbose logging of concurrency scheduler activity

2.5 2.5

2.5 2.5

2.5 2.5 2.5

Preemptive scheduling
The following sections describe the new queue manager and its preemptive scheduler algorithm. Note that the document was originally written to describe the changes between the new queue manager (in this text referred to as nqmgr, the name it was known by before it became the default queue manager) and the old queue manager (referred to as oqmgr). This is why it refers to oqmgr every so often. This document is divided into sections as follows: The structures used by nqmgr What happens when nqmgr picks up the message - how it is assigned to transports, jobs, peers, entries How the entry selection works How the preemption works - what messages may be preempted and how and what messages are chosen to preempt them How destination concurrency limits affect the scheduling algorithm Dealing with memory resource limits

The structures used by nqmgr


Let's start by recapitulating the structures and terms used when referring to queue manager and how it operates. Many of these are partially described elsewhere, but it is nice to have a coherent overview in one place: Each message structure represents one mail message which Postfix is to deliver. The message recipients specify to what destinations is the message to be delivered and what transports are going to be used for the delivery. Each recipient entry groups a batch of recipients of one message which are all going to be delivered to the same destination. Each transport structure groups everything what is going to be delivered by delivery agents dedicated for that transport. Each transport maintains a set of queues (describing the destinations it shall talk to) and jobs (referencing the messages it shall deliver). Each transport queue (not to be confused with the on-disk active queue or incoming queue) groups everything what is going be delivered to given destination (aka nexthop) by its transport. Each queue belongs to one transport, so each destination may be referred to by several queues, one for each transport. Each queue maintains a list of all recipient entries (batches of message recipients) which shall be delivered to given destination (the todo list), and a list of recipient entries already being delivered by the delivery agents (the busy list). Each queue corresponds to multiple peer structures. Each peer structure is like the queue structure, belonging to one transport and referencing one destination. The difference is that it lists only the recipient entries which all originate from the same message, unlike the queue structure, whose entries may originate from various messages. For messages with few recipients, there is usually just one recipient entry for each destination, resulting in one recipient entry per peer. But for large mailing list messages the recipients may need to be split to multiple recipient entries, in which case the peer structure may list many entries for single destination. Each transport job groups everything it takes to deliver one message via its transport. Each

job represents one message within the context of the transport. The job belongs to one transport and message, so each message may have multiple jobs, one for each transport. The job groups all the peer structures, which describe the destinations the job's message has to be delivered to. The first four structures are common to both nqmgr and oqmgr, the latter two were introduced by nqmgr. These terms are used extensively in the text below, feel free to look up the description above anytime you'll feel you have lost a sense what is what.

What happens when nqmgr picks up the message


Whenever nqmgr moves a queue file into the active queue, the following happens: It reads all necessary information from the queue file as oqmgr does, and also reads as many recipients as possible - more on that later, for now let's just pretend it always reads all recipients. Then it resolves the recipients as oqmgr does, which means obtaining (address, nexthop, transport) triple for each recipient. For each triple, it finds the transport; if it does not exist yet, it instantiates it (unless it's dead). Within the transport, it finds the destination queue for given nexthop; if it does not exist yet, it instantiates it (unless it's dead). The triple is then bound to given destination queue. This happens in qmgr_resolve() and is basically the same as in oqmgr. Then for each triple which was bound to some queue (and thus transport), the program finds the job which represents the message within that transport's context; if it does not exist yet, it instantiates it. Within the job, it finds the peer which represents the bound destination queue within this jobs context; if it does not exist yet, it instantiates it. Finally, it stores the address from the resolved triple to the recipient entry which is appended to both the queue entry list and the peer entry list. The addresses for same nexthop are batched in the entries up to recipient_concurrency limit for that transport. This happens in qmgr_assign() and apart from that it operates with job and peer structures it is basically the same as in oqmgr. When the job is instantiated, it is enqueued on the transport's job list based on the time its message was picked up by nqmgr. For first batch of recipients this means it is appended to the end of the job list, but the ordering of the job list by the enqueue time is important as we will see shortly. [Now you should have pretty good idea what is the state of the nqmgr after couple of messages was picked up, what is the relation between all those job, peer, queue and entry structures.]

How the entry selection works


Having prepared all those above mentioned structures, the task of the nqmgr's scheduler is to choose the recipient entries one at a time and pass them to the delivery agent for corresponding transport. Now how does this work? The first approximation of the new scheduling algorithm is like this:
foreach transport (round-robin-by-transport) do if transport busy continue if transport process limit reached continue foreach transport's job (in the order of the transport's job list) do foreach job's peer (round-robin-by-destination) if peer->queue->concurrency < peer->queue->window return next peer entry. done done done

Now what is the "order of the transport's job list"? As we know already, the job list is by default kept in the order the message was picked up by the nqmgr. So by default we get the top-level round-robin transport, and within each transport we get the FIFO message delivery. The round-robin of the peers by the destination is perhaps of little importance in most real-life cases (unless the recipient_concurrency limit is reached, in one job there is only one peer structure for each destination), but theoretically it makes sure that even within single jobs, destinations are treated fairly. [By now you should have a feeling you really know how the scheduler works, except for the preemption, under ideal conditions - that is, no recipient resource limits and no destination concurrency problems.]

How the preemption works


As you might perhaps expect by now, the transport's job list does not remain sorted by the job's message enqueue time all the time. The most cool thing about nqmgr is not the simple FIFO delivery, but that it is able to slip mail with little recipients past the mailing-list bulk mail. This is what the job preemption is about - shuffling the jobs on the transport's job list to get the best message delivery rates. Now how is it achieved? First I have to tell you that there are in fact two job lists in each transport. One is the scheduler's job list, which the scheduler is free to play with, while the other one keeps the jobs always listed in the order of the enqueue time and is used for recipient pool management we will discuss later. For now, we will deal with the scheduler's job list only. So, we have the job list, which is first ordered by the time the jobs' messages were enqueued, oldest messages first, the most recently picked one at the end. For now, let's assume that there are no destination concurrency problems. Without preemption, we pick some entry of the first (oldest) job on the queue, assign it to delivery agent, pick another one from the same job, assign it again, and so on, until all the entries are used and the job is delivered. We would then move onto the next job and so on and on. Now how do we manage to sneak in some entries from the recently added jobs when the first job on the job list belongs to a message going to the mailing-list and has thousands of recipient entries? The nqmgr's answer is that we can artificially "inflate" the delivery time of that first job by some constant for free - it is basically the same trick you might remember as "accumulation of potential" from the amortized complexity lessons. For example, instead of delivering the entries of the first job on the job list every time a delivery agent becomes available, we can do it only every second time. If you view the moments the delivery agent becomes available on a timeline as "delivery slots", then instead of using every delivery slot for the first job, we can use only every other slot, and still the overall delivery efficiency of the first job remains the same. So the delivery 11112222 becomes 1.1.1.1.2.2.2.2 (1 and 2 are the imaginary job numbers, . denotes the free slot). Now what do we do with free slots? As you might have guessed, we will use them for sneaking the mail with little recipients in. For example, if we have one four-recipient mail followed by four one recipients mail, the delivery sequence (that is, the sequence in which the jobs are assigned to the delivery slots) might look like this: 12131415. Hmm, fine for sneaking in the single recipient mail, but how do we sneak in the mail with more than one recipient? Say if we have one four-recipient mail followed by two tworecipient mails? The simple answer would be to use delivery sequence 12121313. But the problem is that this does not scale well. Imagine you have mail with thousand recipients followed by mail with hundred recipients. It is tempting to suggest the delivery sequence like 121212...., but alas! Imagine there arrives another mail with say ten recipients. But there are no free slots anymore, so it can't slip by, not even if it had just only one recipients. It will be stuck until the hundred-recipient mail is

delivered, which really sucks. So, it becomes obvious that while inflating the message to get free slots is great idea, one has to be really careful of how the free slots are assigned, otherwise one might corner himself. So, how does nqmgr really use the free slots? The key idea is that one does not have to generate the free slots in a uniform way. The delivery sequence 111...1 is no worse than 1.1.1.1, in fact, it is even better as some entries are in the first case selected earlier than in the second case, and none is selected later! So it is possible to first "accumulate" the free delivery slots and then use them all at once. It is even possible to accumulate some, then use them, then accumulate some more and use them again, as in 11..1.1 . Let's get back to the one hundred recipient example. We now know that we could first accumulate one hundred free slots, and only after then to preempt the first job and sneak the one hundred recipient mail in. Applying the algorithm recursively, we see the hundred recipient job can accumulate ten free delivery slots, and then we could preempt it and sneak in the ten-recipient mail... Wait wait wait! Could we? Aren't we overinflating the original one thousand recipient mail? Well, despite it looks so at the first glance, another trick will allow us to answer "no, we are not!". If we had said that we will inflate the delivery time twice at maximum, and then we consider every other slot as a free slot, then we would overinflate in case of the recursive preemption. BUT! The trick is that if we use only every n-th slot as a free slot for n>2, there is always some worst inflation factor which we can guarantee not to be breached, even if we apply the algorithm recursively. To be precise, if for every k>1 normally used slots we accumulate one free delivery slot, than the inflation factor is not worse than k/(k-1) no matter how many recursive preemptions happen. And it's not worse than (k+1)/k if only non-recursive preemption happens. Now, having got through the theory and the related math, let's see how nqmgr implements this. Each job has so called "available delivery slot" counter. Each transport has a transport_delivery_slot_cost parameter, which defaults to default_delivery_slot_cost parameter which is set to 5 by default. This is the k from the paragraph above. Each time k entries of the job are selected for delivery, this counter is incremented by one. Once there are some slots accumulated, job which requires no more than that number of slots to be fully delivered can preempt this job. [Well, the truth is, the counter is incremented every time an entry is selected and it is divided by k when it is used. Or even more true, there is no division, the other side of the equation is multiplied by k. But for the understanding it's good enough to use the above approximation of the truth.] OK, so now we know the conditions which must be satisfied so one job can preempt another one. But what job gets preempted, how do we choose what job preempts it if there are several valid candidates, and when does all this exactly happen? The answer for the first part is simple. The job whose entry was selected the last time is so called current job. Normally, it is the first job on the scheduler's job list, but destination concurrency limits may change this as we will see later. It is always only the current job which may get preempted. Now for the second part. The current job has certain amount of recipient entries, and as such may accumulate at maximum some amount of available delivery slots. It might have already accumulated some, and perhaps even already used some when it was preempted before (remember a job can be preempted several times). In either case, we know how many are accumulated and how many are left to deliver, so we know how many it may yet accumulate at maximum. Every other job which may be delivered by less than that number of slots is a valid candidate for preemption. How do we choose among them? The answer is - the one with maximum enqueue_time/recipient_entry_count. That is, the older the job is, the more we should try to deliver it in order to get best message delivery rates. These rates are of course subject to how many recipients the message has, therefore the division by the recipient (entry) count. No one shall be surprised that message with n recipients takes n times longer to

deliver than message with one recipient. Now let's recap the previous two paragraphs. Isn't it too complicated? Why don't the candidates come only among the jobs which can be delivered within the number of slots the current job already accumulated? Why do we need to estimate how much it has yet to accumulate? If you found out the answer, congratulate yourself. If we did it this simple way, we would always choose the candidate with least recipient entries. If there were enough single recipient mails coming in, they would always slip by the bulk mail as soon as possible, and the two and more recipients mail would never get a chance, no matter how long they have been sitting around in the job list. This candidate selection has interesting implication - that when we choose the best candidate for preemption (this is done in qmgr_choose_candidate()), it may happen that we may not use it for preemption immediately. This leads to an answer to the last part of the original question - when does the preemption happen? The preemption attempt happens every time next transport's recipient entry is to be chosen for delivery. To avoid needless overhead, the preemption is not attempted if the current job could never accumulate more than transport_minimum_delivery_slots (defaults to default_minimum_delivery_slots which defaults to 3). If there is already enough accumulated slots to preempt the current job by the chosen best candidate, it is done immediately. This basically means that the candidate is moved in front of the current job on the scheduler's job list and decreasing the accumulated slot counter by the amount used by the candidate. If there is not enough slots... well, I could say that nothing happens and the another preemption is attempted the next time. But that's not the complete truth. The truth is that it turns out that it is not really necessary to wait until the jobs counter accumulates all the delivery slots in advance. Say we have ten-recipient mail followed by two two-recipient mails. If the preemption happened when enough delivery slot accumulate (assuming slot cost 2), the delivery sequence becomes 11112211113311. Now what would we get if we would wait only for 50% of the necessary slots to accumulate and we promise we would wait for the remaining 50% later, after we get back to the preempted job? If we use such slot loan, the delivery sequence becomes 11221111331111. As we can see, it makes it no considerably worse for the delivery of the ten-recipient mail, but it allows the small messages to be delivered sooner. The concept of these slot loans is where the transport_delivery_slot_discount and transport_delivery_slot_loan come from (they default to default_delivery_slot_discount and default_delivery_slot_loan, whose values are by default 50 and 3, respectively). The discount (resp. loan) specifies how many percent (resp. how many slots) one "gets in advance", when the number of slots required to deliver the best candidate is compared with the number of slots the current slot had accumulated so far. And it pretty much concludes this chapter. [Now you should have a feeling that you pretty much understand the scheduler and the preemption, or at least that you will have it after you read the last chapter couple more times. You shall clearly see the job list and the preemption happening at its head, in ideal delivery conditions. The feeling of understanding shall last until you start wondering what happens if some of the jobs are blocked, which you might eventually figure out correctly from what had been said already. But I would be surprised if your mental image of the scheduler's functionality is not completely shattered once you start wondering how it works when not all recipients may be read in-core. More on that later.]

How destination concurrency limits affect the scheduling algorithm


The nqmgr uses the same algorithm for destination concurrency control as oqmgr. Now what happens when the destination limits are reached and no more entries for that destination may be selected by the scheduler?

From user's point of view it is all simple. If some of the peers of a job can't be selected, those peers are simply skipped by the entry selection algorithm (the pseudo-code described before) and only the selectable ones are used. If none of the peers may be selected, the job is declared a "blocker job". Blocker jobs are skipped by the entry selection algorithm and they are also excluded from the candidates for preemption of current job. Thus the scheduler effectively behaves as if the blocker jobs didn't exist on the job list at all. As soon as at least one of the peers of a blocker job becomes unblocked (that is, the delivery agent handling the delivery of the recipient entry for given destination successfully finishes), the job's blocker status is removed and the job again participates in all further scheduler actions normally. So the summary is that the users don't really have to be concerned about the interaction of the destination limits and scheduling algorithm. It works well on its own and there are no knobs they would need to control it. From a programmer's point of view, the blocker jobs complicate the scheduler quite a lot. Without them, the jobs on the job list would be normally delivered in strict FIFO order. If the current job is preempted, the job preempting it is completely delivered unless it is preempted itself. Without blockers, the current job is thus always either the first job on the job list, or the top of the stack of jobs preempting the first job on the job list. The visualization of the job list and the preemption stack without blockers would be like this:
first job-> on job list current job-> 1--2--3--5--6--8--... <- job list | 4 <- preemption stack | 7

In the example above we see that job 1 was preempted by job 4 and then job 4 was preempted by job 7. After job 7 is completed, remaining entries of job 4 are selected, and once they are all selected, job 1 continues. As we see, it's all very clean and straightforward. Now how does this change because of blockers? The answer is: a lot. Any job may become blocker job at any time, and also become normal job again at any time. This has several important implications: 1. The jobs may be completed in arbitrary order. For example, in the example above, if the current job 7 becomes blocked, the next job 4 may complete before the job 7 becomes unblocked again. Or if both 7 and 4 are blocked, then 1 is completed, then 7 becomes unblocked and is completed, then 2 is completed and only after that 4 becomes unblocked and is completed... You get the idea. [Interesting side note: even when jobs are delivered out of order, from single destination's point of view the jobs are still delivered in the expected order (that is, FIFO unless there was some preemption involved). This is because whenever a destination queue becomes unblocked (the destination limit allows selection of more recipient entries for that destination), all jobs which have peers for that destination are unblocked at once.] 2. The idea of the preemption stack at the head of the job list is gone. That is, it must be possible to preempt any job on the job list. For example, if the jobs 7, 4, 1 and 2 in the example above become all blocked, job 3 becomes the current job. And of course we do not want the preemption to be affected by the fact that there are some blocked jobs or not. Therefore, if it turns out that job 3 might be preempted by job 6, the implementation shall make it possible. 3. The idea of the linear preemption stack itself is gone. It's no longer true that one job is always preempted by only one job at one time (that is directly preempted, not counting the recursively nested jobs). For example, in the example above, job 1 is directly preempted by

only job 4, and job 4 by job 7. Now assume job 7 becomes blocked, and job 4 is being delivered. If it accumulates enough delivery slots, it is natural that it might be preempted for example by job 8. Now job 4 is preempted by both job 7 AND job 8 at the same time. Now combine the points 2) and 3) with point 1) again and you realize that the relations on the once linear job list became pretty complicated. If we extend the point 3) example: jobs 7 and 8 preempt job 4, now job 8 becomes blocked too, then job 4 completes. Tricky, huh? If I illustrate the relations after the above mentioned examples (but those in point 1)), the situation would look like this:
v- parent adoptive parent -> parent gone -> children -> 1--2--3--5--... | | ? 6 / \ 7 8 ^- child ^- siblings <- "stack" level 0 <- "stack" level 1 <- "stack" level 2

Now how does nqmgr deal with all these complicated relations? Well, it maintains them all as described, but fortunately, all these relations are necessary only for purposes of proper counting of available delivery slots. For purposes of ordering the jobs for entry selection, the original rule still applies: "the job preempting the current job is moved in front of the current job on the job list". So for entry selection purposes, the job relations remain as simple as this:
7--8--1--2--6--3--5--.. <- scheduler's job list order

The job list order and the preemption parent/child/siblings relations are maintained separately. And because the selection works only with the job list, you can happily forget about those complicated relations unless you want to study the nqmgr sources. In that case the text above might provide some helpful introduction to the problem domain. Otherwise I suggest you just forget about all this and stick with the user's point of view: the blocker jobs are simply ignored. [By now, you should have a feeling that there is more things going under the hood than you ever wanted to know. You decide that forgetting about this chapter is the best you can do for the sake of your mind's health and you basically stick with the idea how the scheduler works in ideal conditions, when there are no blockers, which is good enough.]

Dealing with memory resource limits


When discussing the nqmgr scheduler, we have so far assumed that all recipients of all messages in the active queue are completely read into the memory. This is simply not true. There is an upper bound on the amount of memory the nqmgr may use, and therefore it must impose some limits on the information it may store in the memory at any given time. First of all, not all messages may be read in-core at once. At any time, only qmgr_message_active_limit messages may be read in-core at maximum. When read into memory, the messages are picked from the incoming and deferred message queues and moved to the active queue (incoming having priority), so if there is more than qmgr_message_active_limit messages queued in the active queue, the rest will have to wait until (some of) the messages in the active queue are completely delivered (or deferred). Even with the limited amount of in-core messages, there is another limit which must be imposed in order to avoid memory exhaustion. Each message may contain huge amount of recipients (tens or

hundreds of thousands are not uncommon), so if nqmgr read all recipients of all messages in the active queue, it may easily run out of memory. Therefore there must be some upper bound on the amount of message recipients which are read into the memory at the same time. Before discussing how exactly nqmgr implements the recipient limits, let's see how the sole existence of the limits themselves affects the nqmgr and its scheduler. The message limit is straightforward - it just limits the size of the lookahead the nqmgr's scheduler has when choosing which message can preempt the current one. Messages not in the active queue simply are not considered at all. The recipient limit complicates more things. First of all, the message reading code must support reading the recipients in batches, which among other things means accessing the queue file several times and continuing where the last recipient batch ended. This is invoked by the scheduler whenever the current job has space for more recipients, subject to transport's refill_limit and refill_delay parameters. It is also done any time when all in-core recipients of the message are dealt with (which may also mean they were deferred) but there are still more in the queue file. The second complication is that with some recipients left unread in the queue file, the scheduler can't operate with exact counts of recipient entries. With unread recipients, it is not clear how many recipient entries there will be, as they are subject to per-destination grouping. It is not even clear to what transports (and thus jobs) the recipients will be assigned. And with messages coming from the deferred queue, it is not even clear how many unread recipients are still to be delivered. This all means that the scheduler must use only estimates of how many recipients entries there will be. Fortunately, it is possible to estimate the minimum and maximum correctly, so the scheduler can always err on the safe side. Obviously, the better the estimates, the better results, so it is best when we are able to read all recipients in-core and turn the estimates into exact counts, or at least try to read as many as possible to make the estimates as accurate as possible. The third complication is that it is no longer true that the scheduler is done with a job once all of its in-core recipients are delivered. It is possible that the job will be revived later, when another batch of recipients is read in core. It is also possible that some jobs will be created for the first time long after the first batch of recipients was read in core. The nqmgr code must be ready to handle all such situations. And finally, the fourth complication is that the nqmgr code must somehow impose the recipient limit itself. Now how does it achieve it? Perhaps the easiest solution would be to say that each message may have at maximum X recipients stored in-core, but such solution would be poor for several reasons. With reasonable qmgr_message_active_limit values, the X would have to be quite low to maintain reasonable memory footprint. And with low X lots of things would not work well. The nqmgr would have problems to use the transport_destination_recipient_limit efficiently. The scheduler's preemption would be suboptimal as the recipient count estimates would be inaccurate. The message queue file would have to be accessed many times to read in more recipients again and again. Therefore it seems reasonable to have a solution which does not use a limit imposed on per-message basis, but which maintains a pool of available recipient slots, which can be shared among all messages in the most efficient manner. And as we do not want separate transports to compete for resources whenever possible, it seems appropriate to maintain such recipient pool for each transport separately. This is the general idea, now how does it work in practice? First we have to solve little chicken-and-egg problem. If we want to use the per-transport recipient pools, we first need to know to what transport(s) is the message assigned. But we will find that out only after we read in the recipients first. So it is obvious that we first have to read in some recipients, use them to find out to what transports is the message to be assigned, and only after that we can use the per-transport recipient pools.

Now how many recipients shall we read for the first time? This is what qmgr_message_recipient_minimum and qmgr_message_recipient_limit values control. The qmgr_message_recipient_minimum value specifies how many recipients of each message we will read for the first time, no matter what. It is necessary to read at least one recipient before we can assign the message to a transport and create the first job. However, reading only qmgr_message_recipient_minimum recipients even if there are only few messages with few recipients in-core would be wasteful. Therefore if there is less than qmgr_message_recipient_limit recipients in-core so far, the first batch of recipients may be larger than qmgr_message_recipient_minimum - as large as is required to reach the qmgr_message_recipient_limit limit. Once the first batch of recipients was read in core and the message jobs were created, the size of the subsequent recipient batches (if any - of course it's best when all recipients are read in one batch) is based solely on the position of the message jobs on their corresponding transports' job lists. Each transport has a pool of transport_recipient_limit recipient slots which it can distribute among its jobs (how this is done is described later). The subsequent recipient batch may be as large as the sum of all recipient slots of all jobs of the message permits (plus the qmgr_message_recipient_minimum amount which always applies). For example, if a message has three jobs, first with 1 recipient still in-core and 4 recipient slots, second with 5 recipient in-core and 5 recipient slots, and third with 2 recipients in-core and 0 recipient slots, it has 1+5+2=7 recipients in-core and 4+5+0=9 jobs' recipients slots in total. This means that we could immediately read 2+qmgr_message_recipient_minimum more recipients of that message in core. The above example illustrates several things which might be worth mentioning explicitly: first, note that although the per-transport slots are assigned to particular jobs, we can't guarantee that once the next batch of recipients is read in core, that the corresponding amounts of recipients will be assigned to those jobs. The jobs lend its slots to the message as a whole, so it is possible that some jobs end up sponsoring other jobs of their message. For example, if in the example above the 2 newly read recipients were assigned to the second job, the first job sponsored the second job with 2 slots. The second notable thing is the third job, which has more recipients in-core than it has slots. Apart from sponsoring by other job we just saw it can be result of the first recipient batch, which is sponsored from global recipient pool of qmgr_message_recipient_limit recipients. It can be also sponsored from the message recipient pool of qmgr_message_recipient_minimum recipients. Now how does each transport distribute the recipient slots among its jobs? The strategy is quite simple. As most scheduler activity happens on the head of the job list, it is our intention to make sure that the scheduler has the best estimates of the recipient counts for those jobs. As we mentioned above, this means that we want to try to make sure that the messages of those jobs have all recipients read in-core. Therefore the transport distributes the slots "along" the job list from start to end. In this case the job list sorted by message enqueue time is used, because it doesn't change over time as the scheduler's job list does. More specifically, each time a job is created and appended to the job list, it gets all unused recipient slots from its transport's pool. It keeps them until all recipients of its message are read. When this happens, all unused recipient slots are transferred to the next job (which is now in fact now first such job) on the job list which still has some recipients unread, or eventually back to the transport pool if there is no such job. Such transfer then also happens whenever a recipient entry of that job is delivered. There is also a scenario when a job is not appended to the end of the job list (for example it was created as a result of second or later recipient batch). Then it works exactly as above, except that if it was put in front of the first unread job (that is, the job of a message which still has some unread recipients in queue file), that job is first forced to return all of its unused recipient slots to the transport pool.

The algorithm just described leads to the following state: The first unread job on the job list always gets all the remaining recipient slots of that transport (if there are any). The jobs queued before this job are completely read (that is, all recipients of their message were already read in core) and have at maximum as many slots as they still have recipients in-core (the maximum is there because of the sponsoring mentioned before) and the jobs after this job get nothing from the transport recipient pool (unless they got something before and then the first unread job was created and enqueued in front of them later - in such case the also get at maximum as many slots as they have recipients incore). Things work fine in such state for most of the time, because the current job is either completely read in-core or has as much recipient slots as there are, but there is one situation which we still have to take care of specially. Imagine if the current job is preempted by some unread job from the job list and there are no more recipient slots available, so this new current job could read only batches of qmgr_message_recipient_minimum recipients at a time. This would really degrade performance. For this reason, each transport has extra pool of transport_extra_recipient_limit recipient slots, dedicated exactly for this situation. Each time an unread job preempts the current job, it gets half of the remaining recipient slots from the normal pool and this extra pool. And that's it. It sure does sound pretty complicated, but fortunately most people don't really have to care how exactly it works as long as it works. Perhaps the only important things to know for most people are the following upper bound formulas: Each transport has at maximum
max( qmgr_message_recipient_minimum * qmgr_message_active_limit + *_recipient_limit + *_extra_recipient_limit, qmgr_message_recipient_limit )

recipients in core. The total amount of recipients in core is


max( qmgr_message_recipient_minimum * qmgr_message_active_limit + sum( *_recipient_limit + *_extra_recipient_limit ), qmgr_message_recipient_limit )

where the sum is over all used transports. And this terribly complicated chapter concludes the documentation of nqmgr scheduler. [By now you should theoretically know the nqmgr scheduler inside out. In practice, you still hope that you will never have to really understand the last or last two chapters completely, and fortunately most people really won't. Understanding how the scheduler works in ideal conditions is more than good enough for vast majority of users.]

Credits
Wietse Venema designed and implemented the initial queue manager with per-domain FIFO scheduling, and per-delivery +/-1 concurrency feedback. Patrik Rak designed and implemented preemption where mail with fewer recipients can slip past mail with more recipients in a controlled manner, and wrote up its documentation. Wietse Venema initiated a discussion with Patrik Rak and Victor Duchovni on alternatives for the +/-1 feedback scheduler's aggressive behavior. This is when K/N feedback was reviewed (N = concurrency). The discussion ended without a good solution for both negative

feedback and dead site detection. Victor Duchovni resumed work on concurrency feedback in the context of concurrencylimited servers. Wietse Venema then re-designed the concurrency scheduler in terms of the simplest possible concepts: less-than-1 concurrency feedback per delivery, forward and reverse concurrency feedback hysteresis, and pseudo-cohort failure. At this same time, concurrency feedback was separated from dead site detection. These simplifications, and their modular implementation, helped to develop further insights into the different roles that positive and negative concurrency feedback play, and helped to identify some worst-case scenarios.

Postfix XCLIENT Howto


Purpose of the XCLIENT extension to SMTP
When an SMTP server announces support for the XCLIENT command, an SMTP client may send information that overrides one or more client-related session attributes. The XCLIENT command targets the following problems: 1. Access control tests. SMTP server access rules are difficult to verify when decisions can be triggered only by remote clients. In order to facilitate access rule testing, an authorized SMTP client test program needs the ability to override the SMTP server's idea of the SMTP client hostname, network address, and other client information, for the entire duration of an SMTP session. 2. Client software that downloads mail from an up-stream mail server and injects it into a local MTA via SMTP. In order to take advantage of the local MTA's SMTP server access rules, the client software needs the ability to override the SMTP server's idea of the remote client name, client address and other information. Such information can typically be extracted from the up-stream mail server's Received: message header. 3. Post-filter access control and logging. With Internet->filter->MTA style content filter applications, the filter can be simplified if it can delegate decisions concerning mail relay and other access control to the MTA. This is especially useful when the filter acts as a transparent proxy for SMTP commands. This requires that the filter can override the MTA's idea of the SMTP client hostname, network address, and other information.

XCLIENT Command syntax


An example client-server conversation is given at the end of this document. In SMTP server EHLO replies, the keyword associated with this extension is XCLIENT. It is followed by the names of the attributes that the XCLIENT implementation supports. The XCLIENT command may be sent at any time, except in the middle of a mail delivery transaction (i.e. between MAIL and DOT, or MAIL and RSET). The XCLIENT command may be pipelined when the server supports ESMTP command pipelining. To avoid triggering spamware detectors, the command should be sent at the end of a command group. The syntax of XCLIENT requests is described below. Upper case and quoted strings specify terminals, lowercase strings specify meta terminals, and SP is whitespace. Although command and attribute names are shown in upper case, they are in fact case insensitive. xclient-command = XCLIENT 1*( SP attribute-name"="attribute-value ) attribute-name = ( NAME | ADDR | PORT | PROTO | HELO ) attribute-value = xtext Attribute values are xtext encoded as per RFC 1891.

The NAME attribute specifies an SMTP client hostname (not an SMTP client address), [UNAVAILABLE] when client hostname lookup failed due to a permanent error, or [TEMPUNAVAIL] when the lookup error condition was transient. The ADDR attribute specifies an SMTP client numerical IPv4 network address, an IPv6 address prefixed with IPV6:, or [UNAVAILABLE] when the address information is unavailable. Address information is not enclosed with []. The PORT attribute specifies the SMTP client TCP port number as a decimal number, or [UNAVAILABLE] when the information is unavailable. The PROTO attribute specifies either SMTP or ESMTP. The HELO attribute specifies an SMTP HELO parameter value, or the value [UNAVAILABLE] when the information is unavailable. Note 1: syntactically valid NAME and HELO attribute-value elements can be up to 255 characters long. The client must not send XCLIENT commands that exceed the 512 character limit for SMTP commands. To avoid exceeding the limit the client should send the information in multiple XCLIENT commands; for example, send NAME and ADDR first, then HELO and PROTO. Note 2: [UNAVAILABLE], [TEMPUNAVAIL] and IPV6: may be specified in upper case, lower case or mixed case. Note 3: Postfix implementations prior to version 2.3 do not xtext encode attribute values. Servers that wish to interoperate with these older implementations should be prepared to receive unencoded information. Note 4: Postfix implementations prior to version 2.5 do not implement the PORT attribute.

XCLIENT Server response


Upon receipt of a correctly formatted XCLIENT command, the server resets state to the initial SMTP greeting protocol stage. Depending on the outcome of optional access decisions, the server responds with 220 or with a suitable rejection code. For practical reasons it is not always possible to reset the complete server state to the initial SMTP greeting protocol stage: TLS session information may not be reset, because turning off TLS leaves the connection in an undefined state. Consequently, the server may not announce STARTTLS when TLS is already active, and access decisions may be influenced by client certificate information that was received prior to the XCLIENT command. The SMTP server must not reset attributes that were received with the last XCLIENT command. This includes HELO or PROTO attributes. NOTE: Postfix implementations prior to version 2.3 do not jump back to the initial SMTP greeting protocol stage. These older implementations will not correctly simulate connection-level access decisions under some conditions.

XCLIENT server reply codes


Code 220 421 success unable to proceed, disconnecting Meaning

501 503 550

bad command parameter syntax mail transaction in progress insufficient authorization

other connection rejected by connection-level access decision

XCLIENT Example
In the example, the client impersonates a mail originating system by passing all SMTP client information via the XCLIENT command. Information sent by the client is shown in bold font.
220 server.example.com ESMTP Postfix EHLO client.example.com 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-XCLIENT NAME ADDR PROTO HELO 250 8BITMIME XCLIENT NAME=spike.porcupine.org ADDR=168.100.189.2 220 server.example.com ESMTP Postfix EHLO spike.porcupine.org 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-XCLIENT NAME ADDR PROTO HELO 250 8BITMIME MAIL FROM:<wietse@porcupine.org> 250 Ok RCPT TO:<user@example.com> 250 Ok DATA 354 End data with <CR><LF>.<CR><LF> . . .message content. . . . 250 Ok: queued as 763402AAE6 QUIT 221 Bye

Security
The XCLIENT command changes audit trails and/or SMTP client access permissions. Use of this command must be restricted to authorized SMTP clients.

SMTP connection caching


XCLIENT attributes persist until the end of an SMTP session. If one session is used to deliver mail on behalf of different SMTP clients, the XCLIENT attributes need to be reset as appropriate before each MAIL FROM command.

References
Moore, K, "SMTP Service Extension for Delivery Status Notifications", RFC 1891, January 1996.

Postfix XFORWARD Howto


Purpose of the XFORWARD extension to SMTP
When an SMTP server announces support for the XFORWARD command, an SMTP client may send information that overrides one or more client-related logging attributes. The XFORWARD command targets the following problem: Logging after SMTP-based content filter. With the deployment of Internet->MTA1->filter>MTA2 style content filter applications, the logging of client and message identifying information changes when MTA1 gives the mail to the content filter. To simplify the interpretation of MTA2 logging, it would help if MTA1 could forward remote client and/or message identifying information through the content filter to MTA2, so that the information could be logged as part of mail handling transactions. This extension is implemented as a separate EMSTP command, and can be used to transmit client or message attributes incrementally. It is not implemented by passing additional parameters via the MAIL FROM command, because doing so would require extending the MAIL FROM command length limit by another 600 or more characters beyond the space that is already needed to support other extensions such as AUTH and DSN.

XFORWARD Command syntax


An example of a client-server conversation is given at the end of this document. In SMTP server EHLO replies, the keyword associated with this extension is XFORWARD. The keyword is followed by the names of the attributes that the XFORWARD implementation supports. After receiving the server's announcement for XFORWARD support, the client may send XFORWARD requests at any time except in the middle of a mail delivery transaction (i.e. between MAIL and RSET or DOT). The command may be pipelined when the server supports ESMTP command pipelining. The syntax of XFORWARD requests is described below. Upper case and quoted strings specify terminals, lowercase strings specify meta terminals, and SP is whitespace. Although command and attribute names are shown in upper case, they are in fact case insensitive. xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value ) attribute-name = ( NAME | ADDR | PORT | PROTO | HELO | IDENT | SOURCE ) attribute-value = xtext Attribute values are xtext encoded as per RFC 1891. The NAME attribute specifies the up-stream hostname, or [UNAVAILABLE] when the information is unavailable. The hostname may be a non-DNS hostname. The ADDR attribute specifies the up-stream network address: a numerical IPv4 network address, an IPv6 address prefixed with IPV6:, or [UNAVAILABLE] when the address

information is unavailable. Address information is not enclosed with []. The PORT attribute specifies an up-stream client TCP port number in decimal, or [UNAVAILABLE] when the information is unavailable. The PROTO attribute specifies the mail protocol for receiving mail from the up-stream host. This may be an SMTP or non-SMTP protocol name of up to 64 characters, or [UNAVAILABLE] when the information is unavailable. The HELO attribute specifies the hostname that the up-stream host announced itself with (not necessarily via the SMTP HELO command), or [UNAVAILABLE] when the information is unavailable. The hostname may be a non-DNS hostname. The IDENT attribute specifies a local message identifier on the up-stream host, or [UNAVAILABLE] when the information is unavailable. The down-stream MTA may log this information together with its own local message identifier to facilitate message tracking across MTAs. The SOURCE attribute specifies LOCAL when the message was received from a source that is local with respect to the up-stream host (for example, the message originated from the upstream host itself), REMOTE for all other mail, or [UNAVAILABLE] when the information is unavailable. The down-stream MTA may decide to enable features such as header munging or address qualification with mail from local sources but not other sources. Note 1: an attribute-value element must not be longer than 255 characters (specific attributes may impose shorter lengths). After xtext decoding, attribute values must not contain control characters, non-ASCII characters, whitespace, or other characters that are special in message headers. Note 2: DNS hostnames can be up to 255 characters long. The XFORWARD client implementation must not send XFORWARD commands that exceed the 512 character limit for SMTP commands. Note 3: [UNAVAILABLE] may be specified in upper case, lower case or mixed case. Note 4: Postfix implementations prior to version 2.3 do not xtext encode attribute values. Servers that wish to interoperate with these older implementations should be prepared to receive unencoded information.

XFORWARD Server operation


The server maintains a set of XFORWARD attributes with forwarded information, in addition the current SMTP session attributes. Normally, all XFORWARD attributes are in the undefined state, and the server uses the current SMTP session attributes for logging purposes. Upon receipt of an initial XFORWARD command, the SMTP server initializes all XFORWARD attributes to [UNAVAILABLE]. With each valid XFORWARD command, the server updates XFORWARD attributes with the specified values. The server must not mix client attributes from XFORWARD with client attributes from the current SMTP session. At the end of each MAIL FROM transaction (i.e. RSET or DOT), the server resets all XFORWARD attributes to the undefined state, and is ready to receive another initial XFORWARD command.

XFORWARD Server reply codes


Code 250 success Meaning

421 501 503 550

unable to proceed, disconnecting bad command parameter syntax mail transaction in progress insufficient authorization

XFORWARD Example
In the following example, information sent by the client is shown in bold font.
220 server.example.com ESMTP Postfix EHLO client.example.com 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-XFORWARD NAME ADDR PROTO HELO 250 8BITMIME XFORWARD NAME=spike.porcupine.org ADDR=168.100.189.2 PROTO=ESMTP 250 Ok XFORWARD HELO=spike.porcupine.org 250 Ok MAIL FROM:<wietse@porcupine.org> 250 Ok RCPT TO:<user@example.com> 250 Ok DATA 354 End data with <CR><LF>.<CR><LF> . . .message content. . . . 250 Ok: queued as 3CF6B2AAE8 QUIT 221 Bye

Security
The XFORWARD command changes audit trails. Use of this command must be restricted to authorized clients.

SMTP connection caching


SMTP connection caching makes it possible to deliver multiple messages within the same SMTP session. The XFORWARD attributes are reset after the MAIL FROM transaction completes (after RSET or DOT), so there is no risk of information leakage.

References
Moore, K, "SMTP Service Extension for Delivery Status Notifications", RFC 1891, January 1996.

Postfix XFORWARD Howto


Purpose of the XFORWARD extension to SMTP
When an SMTP server announces support for the XFORWARD command, an SMTP client may send information that overrides one or more client-related logging attributes. The XFORWARD command targets the following problem: Logging after SMTP-based content filter. With the deployment of Internet->MTA1->filter>MTA2 style content filter applications, the logging of client and message identifying information changes when MTA1 gives the mail to the content filter. To simplify the interpretation of MTA2 logging, it would help if MTA1 could forward remote client and/or message identifying information through the content filter to MTA2, so that the information could be logged as part of mail handling transactions. This extension is implemented as a separate EMSTP command, and can be used to transmit client or message attributes incrementally. It is not implemented by passing additional parameters via the MAIL FROM command, because doing so would require extending the MAIL FROM command length limit by another 600 or more characters beyond the space that is already needed to support other extensions such as AUTH and DSN.

XFORWARD Command syntax


An example of a client-server conversation is given at the end of this document. In SMTP server EHLO replies, the keyword associated with this extension is XFORWARD. The keyword is followed by the names of the attributes that the XFORWARD implementation supports. After receiving the server's announcement for XFORWARD support, the client may send XFORWARD requests at any time except in the middle of a mail delivery transaction (i.e. between MAIL and RSET or DOT). The command may be pipelined when the server supports ESMTP command pipelining. The syntax of XFORWARD requests is described below. Upper case and quoted strings specify terminals, lowercase strings specify meta terminals, and SP is whitespace. Although command and attribute names are shown in upper case, they are in fact case insensitive. xforward-command = XFORWARD 1*( SP attribute-name"="attribute-value ) attribute-name = ( NAME | ADDR | PORT | PROTO | HELO | IDENT | SOURCE ) attribute-value = xtext Attribute values are xtext encoded as per RFC 1891. The NAME attribute specifies the up-stream hostname, or [UNAVAILABLE] when the information is unavailable. The hostname may be a non-DNS hostname. The ADDR attribute specifies the up-stream network address: a numerical IPv4 network address, an IPv6 address prefixed with IPV6:, or [UNAVAILABLE] when the address

information is unavailable. Address information is not enclosed with []. The PORT attribute specifies an up-stream client TCP port number in decimal, or [UNAVAILABLE] when the information is unavailable. The PROTO attribute specifies the mail protocol for receiving mail from the up-stream host. This may be an SMTP or non-SMTP protocol name of up to 64 characters, or [UNAVAILABLE] when the information is unavailable. The HELO attribute specifies the hostname that the up-stream host announced itself with (not necessarily via the SMTP HELO command), or [UNAVAILABLE] when the information is unavailable. The hostname may be a non-DNS hostname. The IDENT attribute specifies a local message identifier on the up-stream host, or [UNAVAILABLE] when the information is unavailable. The down-stream MTA may log this information together with its own local message identifier to facilitate message tracking across MTAs. The SOURCE attribute specifies LOCAL when the message was received from a source that is local with respect to the up-stream host (for example, the message originated from the upstream host itself), REMOTE for all other mail, or [UNAVAILABLE] when the information is unavailable. The down-stream MTA may decide to enable features such as header munging or address qualification with mail from local sources but not other sources. Note 1: an attribute-value element must not be longer than 255 characters (specific attributes may impose shorter lengths). After xtext decoding, attribute values must not contain control characters, non-ASCII characters, whitespace, or other characters that are special in message headers. Note 2: DNS hostnames can be up to 255 characters long. The XFORWARD client implementation must not send XFORWARD commands that exceed the 512 character limit for SMTP commands. Note 3: [UNAVAILABLE] may be specified in upper case, lower case or mixed case. Note 4: Postfix implementations prior to version 2.3 do not xtext encode attribute values. Servers that wish to interoperate with these older implementations should be prepared to receive unencoded information.

XFORWARD Server operation


The server maintains a set of XFORWARD attributes with forwarded information, in addition the current SMTP session attributes. Normally, all XFORWARD attributes are in the undefined state, and the server uses the current SMTP session attributes for logging purposes. Upon receipt of an initial XFORWARD command, the SMTP server initializes all XFORWARD attributes to [UNAVAILABLE]. With each valid XFORWARD command, the server updates XFORWARD attributes with the specified values. The server must not mix client attributes from XFORWARD with client attributes from the current SMTP session. At the end of each MAIL FROM transaction (i.e. RSET or DOT), the server resets all XFORWARD attributes to the undefined state, and is ready to receive another initial XFORWARD command.

XFORWARD Server reply codes


Code 250 success Meaning

421 501 503 550

unable to proceed, disconnecting bad command parameter syntax mail transaction in progress insufficient authorization

XFORWARD Example
In the following example, information sent by the client is shown in bold font.
220 server.example.com ESMTP Postfix EHLO client.example.com 250-server.example.com 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-XFORWARD NAME ADDR PROTO HELO 250 8BITMIME XFORWARD NAME=spike.porcupine.org ADDR=168.100.189.2 PROTO=ESMTP 250 Ok XFORWARD HELO=spike.porcupine.org 250 Ok MAIL FROM:<wietse@porcupine.org> 250 Ok RCPT TO:<user@example.com> 250 Ok DATA 354 End data with <CR><LF>.<CR><LF> . . .message content. . . . 250 Ok: queued as 3CF6B2AAE8 QUIT 221 Bye

Security
The XFORWARD command changes audit trails. Use of this command must be restricted to authorized clients.

SMTP connection caching


SMTP connection caching makes it possible to deliver multiple messages within the same SMTP session. The XFORWARD attributes are reset after the MAIL FROM transaction completes (after RSET or DOT), so there is no risk of information leakage.

References
Moore, K, "SMTP Service Extension for Delivery Status Notifications", RFC 1891, January 1996.

Das könnte Ihnen auch gefallen