Table of Contents for
Postfix: The Definitive Guide

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Postfix: The Definitive Guide by Kyle D. Dent Published by O'Reilly Media, Inc., 2003
  1. Postfix: The Definitive Guide
  2. Cover
  3. Postfix: The Definitive Guide
  4. Foreword
  5. Preface
  6. Audience
  7. Organization
  8. Conventions Used in This Book
  9. Comments and Questions
  10. Acknowledgments
  11. 1. Introduction
  12. 1.1. Postfix Origins and Philosophy
  13. 1.2. Email and the Internet
  14. 1.3. The Role of Postfix
  15. 1.4. Postfix Security
  16. 1.5. Additional Information and How to Obtain Postfix
  17. 2. Prerequisites
  18. 2.1. Unix Topics
  19. 2.2. Email Topics
  20. 3. Postfix Architecture
  21. 3.1. Postfix Components
  22. 3.2. How Messages Enter the Postfix System
  23. 3.3. The Postfix Queue
  24. 3.4. Mail Delivery
  25. 3.5. Tracing a Message Through Postfix
  26. 4. General Configuration and Administration
  27. 4.1. Starting Postfix the First Time
  28. 4.2. Configuration Files
  29. 4.3. Important Configuration Considerations
  30. 4.4. Administration
  31. 4.5. master.cf
  32. 4.6. Receiving Limits
  33. 4.7. Rewriting Addresses
  34. 4.8. chroot
  35. 4.9. Documentation
  36. 5. Queue Management
  37. 5.1. How qmgr Works
  38. 5.2. Queue Tools
  39. 6. Email and DNS
  40. 6.1. DNS Overview
  41. 6.2. Email Routing
  42. 6.3. Postfix and DNS
  43. 6.4. Common Problems
  44. 7. Local Delivery and POP/IMAP
  45. 7.1. Postfix Delivery Transports
  46. 7.2. Message Store Formats
  47. 7.3. Local Delivery
  48. 7.4. POP and IMAP
  49. 7.5. Local Mail Transfer Protocol
  50. 8. Hosting Multiple Domains
  51. 8.1. Shared Domains with System Accounts
  52. 8.2. Separate Domains with System Accounts
  53. 8.3. Separate Domains with Virtual Accounts
  54. 8.4. Separate Message Store
  55. 8.5. Delivery to Commands
  56. 9. Mail Relaying
  57. 9.1. Backup MX
  58. 9.2. Transport Maps
  59. 9.3. Inbound Mail Gateway
  60. 9.4. Outbound Mail Relay
  61. 9.5. UUCP, Fax, and Other Deliveries
  62. 10. Mailing Lists
  63. 10.1. Simple Mailing Lists
  64. 10.2. Mailing-List Managers
  65. 11. Blocking Unsolicited Bulk Email
  66. 11.1. The Nature of Spam
  67. 11.2. The Problem of Spam
  68. 11.3. Open Relays
  69. 11.4. Spam Detection
  70. 11.5. Anti-Spam Actions
  71. 11.6. Postfix Configuration
  72. 11.7. Client-Detection Rules
  73. 11.8. Strict Syntax Parameters
  74. 11.9. Content-Checking
  75. 11.10. Customized Restriction Classes
  76. 11.11. Postfix Anti-Spam Example
  77. 12. SASL Authentication
  78. 12.1. SASL Overview
  79. 12.2. Postfix and SASL
  80. 12.3. Configuring Postfix for SASL
  81. 12.4. Testing Your Authentication Configuration
  82. 12.5. SMTP Client Authentication
  83. 13. Transport Layer Security
  84. 13.1. Postfix and TLS
  85. 13.2. TLS Certificates
  86. 14. Content Filtering
  87. 14.1. Command-Based Filtering
  88. 14.2. Daemon-Based Filtering
  89. 14.3. Other Considerations
  90. 15. External Databases
  91. 15.1. MySQL
  92. 15.2. LDAP
  93. A. Configuration Parameters
  94. A.1. Postfix Parameter Reference
  95. 2bounce_notice_recipient
  96. access_map_reject_code
  97. alias_maps
  98. allow_mail_to_files
  99. allow_percent_hack
  100. alternate_config_directories
  101. append_at_myorigin
  102. authorized_verp_clients
  103. berkeley_db_read_buffer_size
  104. biff
  105. body_checks_size_limit
  106. bounce_service_name
  107. canonical_maps
  108. command_directory
  109. command_time_limit
  110. content_filter
  111. daemon_timeout
  112. debug_peer_list
  113. default_destination_concurrency_limit
  114. default_extra_recipient_limit
  115. default_process_limit
  116. default_recipient_limit
  117. default_verp_delimiters
  118. defer_service_name
  119. delay_notice_recipient
  120. deliver_lock_attempts
  121. disable_dns_lookups
  122. disable_mime_output_conversion
  123. disable_vrfy_command
  124. double_bounce_sender
  125. empty_address_recipient
  126. error_service_name
  127. export_environment
  128. fallback_relay
  129. fast_flush_domains
  130. fast_flush_refresh_time
  131. fork_attempts
  132. forward_expansion_filter
  133. hash_queue_depth
  134. header_address_token_limit
  135. header_size_limit
  136. home_mailbox
  137. ignore_mx_lookup_error
  138. in_flow_delay
  139. initial_destination_concurrency
  140. ipc_idle
  141. line_length_limit
  142. lmtp_connect_timeout
  143. lmtp_data_init_timeout
  144. lmtp_lhlo_timeout
  145. lmtp_quit_timeout
  146. lmtp_rset_timeout
  147. lmtp_tcp_port
  148. local_destination_concurrency_limit
  149. local_recipient_maps
  150. luser_relay
  151. mail_owner
  152. mail_spool_directory
  153. mailbox_command
  154. mailbox_delivery_lock
  155. mailbox_transport
  156. manpage_directory
  157. masquerade_domains
  158. max_idle
  159. maximal_backoff_time
  160. message_size_limit
  161. mime_header_checks
  162. minimal_backoff_time
  163. mydomain
  164. mynetworks
  165. myorigin
  166. newaliases_path
  167. notify_classes
  168. parent_domain_matches_subdomains
  169. pickup_service_name
  170. process_id_directory
  171. proxy_interfaces
  172. qmgr_clog_warn_time
  173. qmgr_message_active_limit
  174. qmgr_message_recipient_minimum
  175. qmqpd_error_delay
  176. queue_directory
  177. queue_run_delay
  178. rbl_reply_maps
  179. recipient_canonical_maps
  180. reject_code
  181. relay_domains_reject_code
  182. relay_transport
  183. relocated_maps
  184. resolve_dequoted_address
  185. sample_directory
  186. sendmail_path
  187. setgid_group
  188. showq_service_name
  189. smtp_bind_address
  190. smtp_data_done_timeout
  191. smtp_data_xfer_timeout
  192. smtp_destination_recipient_limit
  193. smtp_helo_timeout
  194. smtp_mail_timeout
  195. smtp_pix_workaround_delay_time
  196. smtp_quit_timeout
  197. smtp_rcpt_timeout
  198. smtp_skip_5xx_greeting
  199. smtpd_banner
  200. smtpd_data_restrictions
  201. smtpd_error_sleep_time
  202. smtpd_expansion_filter
  203. smtpd_helo_required
  204. smtpd_history_flush_threshold
  205. smtpd_noop_commands
  206. smtpd_recipient_limit
  207. smtpd_restriction_classes
  208. smtpd_soft_error_limit
  209. soft_bounce
  210. strict_7bit_headers
  211. strict_8bitmime_body
  212. strict_rfc821_envelopes
  213. swap_bangpath
  214. syslog_name
  215. transport_retry_time
  216. undisclosed_recipients_header
  217. unknown_client_reject_code
  218. unknown_local_recipient_reject_code
  219. unknown_virtual_alias_reject_code
  220. verp_delimiter_filter
  221. virtual_alias_maps
  222. virtual_mailbox_base
  223. virtual_mailbox_limit
  224. virtual_mailbox_maps
  225. virtual_transport
  226. B. Postfix Commands
  227. C. Compiling and Installing Postfix
  228. C.1. Obtaining Postfix
  229. C.2. Postfix Compiling Primer
  230. C.3. Building Postfix
  231. C.4. Installation
  232. C.5. Compiling Add-on Packages
  233. C.6. Common Problems
  234. C.7. Wrapping Things Up
  235. D. Frequently Asked Questions
  236. Index
  237. About the Author
  238. Colophon
  239. Copyright

Delivery to Commands

As mentioned earlier in the chapter, you can’t use local aliases, .forward files, and mailing-list programs with virtual domains delivered by the virtual delivery agent. You’ve seen that you can easily set up aliases through the virtual_alias_maps parameter, but you cannot deliver messages to a command. In this last section, we’ll look at working around that issue by demonstrating how to deliver virtual addresses to external programs. The first example sets up delivery to an autoreply program, and the second to a mailing-list manager.

Auto-responders are scripts or programs that process incoming messages and return a reply to the sender of the message without any human intervention. The autoreply program used in this example, inforeply.pl, is listed in Example 8-1. This program is meant to handle mail for a dedicated information email address. Users or customers can send a message to the address to request special information. Note that this simple example is inadequate as a general autoreply program, such as the Unix vacation command. It does not cache addresses it has already replied to, and it does not do full checking for addresses that should not receive automatic replies (see the sidebar). You might also like to enhance the program to return different types of information, based on the subject or a keyword in the body of the request messages.

Example 8-1. Simple automatic reply program
#!/usr/bin/perl -w
#
# inforeply.pl - Automatic email reply.
#
# All messages are logged to your mail log. Check the
# log after executing the script to see the results.
#
# Set $UID to the uid of the process that runs the script.
# Check the entry in master.cf that calls this script. Use
# the uid of the account you assign to the user= attribute.
# If you want to test the script from the command line, 
# set $UID to your own uid.
#
# Set $ENV_FROM to the envelope FROM address you want on
# outgoing replies. By default it's blank, which will
# use the NULL sender address <>. You can set it to an
# address to receive bounces, but make sure you don't set
# it to the same address that invokes the program, or
# you'll create a mail loop.
#
# Point $INFOFILE to a text file that contains the text of
# the outgoing reply. Include any headers you want in the
# message such as Subject: and From:. The To: header is 
# set automatically based on the sender's address. Make
# sure you have an empty line between your headers and the
# body of the message.
#
# If necessary, change the path to sendmail in $MAILBIN.
#
# @MAILOPTS contains options to sendmail. Make changes if
# necessary. The default options should work in most 
# situations.
#
# The calls to syslog require that your Perl installation
# converted the necessary header files. See h2ph in your
# Perl distribution.
# 

require 5.004;  # for setlogsock in Sys::Syslog module

use strict;
use Sys::Syslog qw(:DEFAULT setlogsock);

#
# Config options. Set these according to your needs.
#
my $UID = 500;
my $ENV_FROM = "";
my $INFOFILE = "/home/autoresp/inforeply.txt";
my $MAILBIN = "/usr/sbin/sendmail";
my @MAILOPTS = ("-oi", "-tr", "$ENV_FROM");
my $SELF = "inforeply.pl";
#
# end of config options

my $EX_TEMPFAIL = 75;
my $EX_UNAVAILABLE = 69;
my $EX_OK = 0;
my $sender;
my $euid = $>;

$SIG{PIPE} = \&PipeHandler;
$ENV{PATH} = "/bin:/usr/bin:/sbin:/usr/sbin";

setlogsock('unix');
openlog($SELF, 'ndelay,pid', 'user');

#
# Check our environment.
#
if ( $euid != $UID ) {
        syslog('mail|err',"error: invalid uid: $> (expecting: $UID)");
        exit($EX_TEMPFAIL);
}
if ( @ARGV != 1 ) {
        syslog('mail|err',"error: invalid invocation (expecting 1 argument)");
        exit($EX_TEMPFAIL);
} else {
        $sender = $ARGV[0];
        if ( $sender =~ /([\w\-.%]+\@[\w.-]+)/ ) {   # scrub address
                $sender = $1;
        } else {
                syslog('mail|err',"error: Illegal sender address");
                exit($EX_UNAVAILABLE);
        }
}
if (! -x $MAILBIN ) {
        syslog('mail|err', "error: $MAILBIN not found or not executable");
        exit($EX_TEMPFAIL);
}
if (! -f $INFOFILE ) {
        syslog('mail|err', "error: $INFOFILE not found");
        exit($EX_TEMPFAIL);
}

#
# Check sender exceptions.
#
if ($sender eq ""
    || $sender =~ /^owner-|-(request|owner)\@|^(mailer-daemon|postmaster)\@/i) {
    exit($EX_OK);
}

#
# Check message contents for Precedence header.
#
while ( <STDIN> ) {
        last if (/^$/);
        exit($EX_OK) if (/^precedence:\s+(bulk|list|junk)/i);
}

#
# Open info file.
#
if (! open(INFO, "<$INFOFILE") ) {
        syslog('mail|err',"error: can't open $INFOFILE: %m");
        exit($EX_TEMPFAIL);
}

#
# Open pipe to mailer.
#
my $pid = open(MAIL, "|-") || exec("$MAILBIN", @MAILOPTS);

#
# Send reply.
#
print MAIL "To: $sender\n";
print MAIL while (<INFO>);

if (! close(MAIL) ) {
        syslog('mail|err',"error: failure invoking $MAILBIN: %m");
        exit($EX_UNAVAILABLE);
}

close(INFO);
syslog('mail|info',"sent reply to $sender");
exit($EX_OK);


sub PipeHandler {
        syslog('mail|err',"error: broken pipe to mailer");
}

Configuring a Virtual Auto-Responder

To configure an auto-responder to work with virtual domains, you must create a special transport type in master.cf for delivery to the specific command. In order to have messages delivered to your new component, you have to map an address to the transport you created using transport maps.

Many auto-responders can handle only a single message at a time with only one recipient. You can limit the number of recipients to any transport type by setting a parameter of the form transport _destination_recipient_limit, where the string transport is the name of the transport type. If a transport called inforeply should be limited to only one recipient at a time, set the following parameter:

inforeply_destination_recipient_limit = 1

The following steps walk through setting up the email address info@ora.com to use inforeply.pl. The domain http://ora.com is configured as a virtual domain. The local domain on the host is http://example.com:

  1. Create a local account under whose privileges the inforeply.pl program should execute. In this example, an account called autoresp is used. You should create a new pseudo-account for this purpose. Use the normal administrative tools on your system to make the account.

  2. Create a transport type called inforeply by adding an entry to your master.cf file. The entry should look something like the following:

    inforeply     unix  -       n       n       -       -       pipe
      flags= user=autoresp argv=/usr/local/bin/inforeply.pl ${sender}

    The pipe daemon is used to deliver messages to external commands. You can specify flags if your program requires any special options. (See the pipe(8) man page for information on the available options.) The user attribute is required for any pipe components in master.cf. The argv attribute must be specified last, and should start with the path to the autoreply command. There are several values that you can pass to your command when Postfix executes it. The values are supplied through special macros. In this example, the envelope sender address (${sender}) is passed. For the simple inforeply.pl responder, you need only the sender address, but you will often want the recipient (${recipient}) address, too, for auto-responders that can handle multiple recipient addresses. See the pipe(8) manpage for the list of available macros.

  3. If you haven’t already set up any transports on your system, set the transport_maps parameter in main.cf to point to the transport table:

    transport_maps = hash:/etc/postfix/transport
  4. Add an entry in your transport table that contains the address to direct messages to the inforeply transport. In this case, we’ll use the address autoresp@ora.com:

    autoresp@ora.com             inforeply

    Now, all messages sent to autoresp@ora.com are delivered to the auto-responder.

  5. Execute postmap against the transport lookup table:

    # postmap /etc/postfix/transport
  6. Point virtual_alias_maps to your virtual alias lookup table:

    virtual_alias_maps = hash:/etc/postfix/virtual_alias
  7. Add an entry to the virtual_alias lookup table to map info@ora.com to both the new autoreply address and the actual recipient address that can receive the messages:

    info@ora.com        autoresp@ora.com, service@oreilly.com
  8. Execute postmap against the virtual alias lookup table:

    # postmap /etc/postfix/virtual_alias

    Now messages sent to info@ora.com will be delivered to and .

  9. Reload Postfix so that it recognizes the changes to its main.cf and master.cf files:

    # postfix reload

    When a message is sent to info@ora.com, Postfix first finds the destination address in the virtual_alias lookup table. The address points both to autoresp@ora.com and service@oreilly.com. Postfix finds autoresp@ora.com in the transport lookup table, which points to the inforeply transport in the master.cf file. The entry in master.cf pipes the message to the inforeply.pl program, which sends the reply to the original sender. Finally, the message is also resubmitted for delivery to service@oreilly.com.

Configuring a Virtual Mailing List Manager

In the next example, you’ll set up a mailing list for a virtual domain. Mailing-list managers are discussed in Chapter 10. You may want to review that chapter before setting up your virtual mailing lists. This example creates a mailing list for Majordomo. You should first install and configure Majordomo according to the directions in Chapter 10.

Virtual mailing lists work by creating a parallel version of the list under a local domain. The local version is only used internally on your system. External users can use the virtual addresses and never know that the local version exists. When naming the local version, you may want to include the virtual domain name in some way to distinguish the list from lists for other virtual domains hosted on your system. The following procedure creates a mailing list at the virtual address astronomy@ora.com that is handled by the local version astronomy-ora@example.com:

  1. Set up the local version of the mailing list just as you would a normal mailing list, as described in Chapter 10, by adding the following entries to /usr/local/majordomo/aliases:

    # astronomy@ora.com list
    astronomy-ora:    :include:/usr/local/majordomo/lists/astronomy
    owner-astronomy-ora:    kdent@ora.com
    astronomy-ora-request: "|/usr/local/majordomo/wrapper request-answer \
         astronomy-ora"
    astronomy-ora-approval:     kdent@ora.com
  2. Rebuild the Majordomo aliases table:

    # postaliases /usr/local/majordomo/aliases
  3. Create the file to hold the email addresses for list subscribers, and set its ownership to the majordom account:

    # touch /usr/local/majordomo/lists/astronomy
    # chown majordom /usr/local/majordomo/lists/astronomy
  4. If desired, create an info file for the list at /usr/local/majordomo/lists/astronomy-ora.info.

  5. Create the necessary addresses for the list at the virtual domain. Add the following entries to the virtual alias map file virtual_alias:

    # astronomy@ora.com list
    astronomy@ora.com            astronomy-ora@localhost
    owner-astronomy@ora.com      owner-astronomy-ora@localhost
    astronomy-request@ora.com    astronomy-ora-request@localhost
    astronomy-approval@ora.com   astronomy-ora-approval@localhost
  6. Rebuild the virtual alias map file:

    # postmap virtual_alias
  7. Add addresses to the /usr/local/majordomo/lists/astronomy list file.

You should now be able to send messages to astronomy@ora.com for distribution to all of the addresses in your list file.