From aeab334cf6df2732c78855bcafb6ae544888b34f Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Thu, 22 Apr 2004 00:00:00 -0500 Subject: [PATCH] postfix-2.2-20040422 --- postfix/AAAREADME | 5 +- postfix/README_FILES/PACKAGE_README | 14 +- postfix/README_FILES/QSHAPE_README | 26 +- postfix/README_FILES/RESTRICTION_CLASS_README | 3 +- postfix/README_FILES/SMTPD_ACCESS_README | 14 +- .../{RELEASE_NOTES-2.2 => RELEASE_NOTES-2.1} | 18 +- postfix/TODO-BEFORE-RELEASE | 28 - postfix/conf/postfix-files | 1 + postfix/conf/transport | 143 +- postfix/html/Makefile.in | 7 +- postfix/html/PACKAGE_README.html | 15 +- postfix/html/QSHAPE_README.html | 28 +- postfix/html/RESTRICTION_CLASS_README.html | 3 +- postfix/html/SMTPD_ACCESS_README.html | 12 +- .../html/STANDARD_CONFIGURATION_README.html | 4 +- postfix/html/postconf.1.html | 32 +- postfix/html/postconf.5.html | 30 +- postfix/html/qshape.1.html | 117 + postfix/html/transport.5.html | 141 +- postfix/man/junk | 2796 +++++++++++++++++ postfix/man/man1/postconf.1 | 4 + postfix/man/man5/postconf.5 | 26 +- postfix/man/man5/transport.5 | 60 +- postfix/mantools/postlink | 2 + postfix/proto/PACKAGE_README.html | 15 +- postfix/proto/QSHAPE_README.html | 28 +- postfix/proto/RESTRICTION_CLASS_README.html | 3 +- postfix/proto/SMTPD_ACCESS_README.html | 12 +- postfix/proto/postconf.proto | 30 +- postfix/proto/transport | 62 +- postfix/src/global/mail_version.h | 2 +- postfix/src/postconf/postconf.c | 4 + postfix/src/smtpd/Makefile.in | 3 + 33 files changed, 3310 insertions(+), 378 deletions(-) rename postfix/{RELEASE_NOTES-2.2 => RELEASE_NOTES-2.1} (97%) delete mode 100644 postfix/TODO-BEFORE-RELEASE create mode 100644 postfix/html/qshape.1.html create mode 100644 postfix/man/junk diff --git a/postfix/AAAREADME b/postfix/AAAREADME index ef5fe0553..937c7091e 100644 --- a/postfix/AAAREADME +++ b/postfix/AAAREADME @@ -97,10 +97,6 @@ navigate faster. The PORTING file discusses how to go about porting Postfix to other UNIX platforms. -The TODO file lists things that still need to be done. If you want -to set your teeth into one of those problems, drop me a note at -wietse@porcupine.org to avoid duplication of effort. - Documentation: README_FILES/ Instructions for specific Postfix features @@ -123,6 +119,7 @@ Command-line utilities: src/postalias/ Alias database management src/postcat/ List Postfix queue file src/postconf/ Configuration utility + src/postdrop/ Postfix mail submission program src/postfix/ Postfix administrative interface src/postkick/ Postfix IPC for shell scripts src/postlock/ Postfix locking for shell scripts diff --git a/postfix/README_FILES/PACKAGE_README b/postfix/README_FILES/PACKAGE_README index dcbb679f9..2ca445ae2 100644 --- a/postfix/README_FILES/PACKAGE_README +++ b/postfix/README_FILES/PACKAGE_README @@ -85,12 +85,14 @@ IInnssttaalllliinngg aa pprree--bbuuiilltt PPoossttffi * Create the necessary mail_owner account and setgid_group group for exclusive use by Postfix. - * Execute the post-install script in the Postfix configuration directory to - set ownership and permission of Postfix files and directories. Specify any - non-default settings for mail_owner or setgid_group on the post-install - command line: + * 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: - # sh post-install upgrade-package setgid_group=xxx mail_owner=yyy + # postfix set-permissions upgrade-configuration \ + setgid_group=xxx mail_owner=yyy - This will also update the main.cf and master.cf files if necessary. + With Postfix versions before 2.1 you achieve the same result by invoking + the post-install script directly. diff --git a/postfix/README_FILES/QSHAPE_README b/postfix/README_FILES/QSHAPE_README index 0a0c8f961..fc04162d5 100644 --- a/postfix/README_FILES/QSHAPE_README +++ b/postfix/README_FILES/QSHAPE_README @@ -4,13 +4,15 @@ PPoossttffiixx BBoottttlleenneecckk AAnnaallyyssiiss PPuurrppoossee ooff tthhiiss ddooccuummeenntt -This document describes the "qshape" program which helps the administrator +This document describes the qshape(1) program which helps the administrator understand the Postfix queue message distribution sorted by time and by sender -or recipient domain. qshape is bundled with the Postfix 2.1 source under the -"auxiliary" directory. In order to understand the output of qshape, it useful -to understand the various Postfix queues. To this end the role of each Postfix -queue directory is described briefly in the "Background info: Postfix queue -directories" section near the end of this document. +or recipient domain. qshape(1) is bundled with the Postfix 2.1 source under the +"auxiliary" directory. + +In order to understand the output of qshape(1), it useful to understand the +various Postfix queues. To this end the role of each Postfix queue directory is +described briefly in the "Background info: Postfix queue directories" section +near the end of this document. This document covers the following topics: @@ -32,8 +34,8 @@ This document covers the following topics: IInnttrroodduucciinngg tthhee qqsshhaappee ttooooll -When mail is draining slowly or the queue is unexpectedly large, run "qshape" -as the super-user (root) to help zero in on the problem. The "qshape" program +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 @@ -133,7 +135,7 @@ 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" output. +forget to include the top 10 or 20 lines of qshape(1) output. EExxaammppllee 11:: HHeeaalltthhyy qquueeuuee @@ -188,7 +190,7 @@ 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.msg.com +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. @@ -214,7 +216,7 @@ 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" it was quickly determined that all the +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) @@ -597,6 +599,6 @@ strategies) to reduce the chances of repeated complete deferred queue flushes. CCrreeddiittss -The "qshape" program was developed by Victor Duchovni of Morgan Stanley, who +The qshape(1) program was developed by Victor Duchovni of Morgan Stanley, who also wrote the initial version of this document. diff --git a/postfix/README_FILES/RESTRICTION_CLASS_README b/postfix/README_FILES/RESTRICTION_CLASS_README index 7b62659ce..0dc53a08d 100644 --- a/postfix/README_FILES/RESTRICTION_CLASS_README +++ b/postfix/README_FILES/RESTRICTION_CLASS_README @@ -65,7 +65,8 @@ SMTP client IP address, and therefore is subject to IP spoofing. ...the usual stuff... /etc/postfix/access: - all permit_mynetworks,reject + all@my.domain permit_mynetworks,reject + all@my.hostname permit_mynetworks,reject Specify ddbbmm instead of hhaasshh if your system uses ddbbmm files instead of ddbb files. To find out what map types Postfix supports, use the command ppoossttccoonnff --mm. diff --git a/postfix/README_FILES/SMTPD_ACCESS_README b/postfix/README_FILES/SMTPD_ACCESS_README index 26fcbe611..3e442b0c6 100644 --- a/postfix/README_FILES/SMTPD_ACCESS_README +++ b/postfix/README_FILES/SMTPD_ACCESS_README @@ -77,29 +77,29 @@ apply to all SMTP mail. SMTPD_PROXY_README document. This happens while Postfix receives mail, before it is stored in the incoming queue. - * Require that the client sends the HELO or EHLO command before sending the + * 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"). - * Disallow illegal syntax in MAIL FROM or RCPT TO commands. This may cause + * 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"). - o Disallow RFC 822 address syntax (example: "MAIL FROM: the dude + o Disallowing RFC 822 address syntax (example: "MAIL FROM: the dude "). - o Disallow addresses that are not enclosed with <> (example: "MAIL FROM: - dude@example.com"). + o Disallowing addresses that are not enclosed with <> (example: "MAIL + FROM: dude@example.com"). - * Reject mail from a non-existent sender address. This form of egress + * 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"). - * Reject mail for a non-existent recipient address. This form of ingress + * 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"). diff --git a/postfix/RELEASE_NOTES-2.2 b/postfix/RELEASE_NOTES-2.1 similarity index 97% rename from postfix/RELEASE_NOTES-2.2 rename to postfix/RELEASE_NOTES-2.1 index ddc2aa428..87e3d5b1d 100644 --- a/postfix/RELEASE_NOTES-2.2 +++ b/postfix/RELEASE_NOTES-2.1 @@ -5,19 +5,19 @@ incompatibility. The official Postfix release is called 2.1.x where 2=major release number, 1=minor release number, x=patchlevel. Snapshot releases -are now called 2.2-yyyymmdd where yyyymmdd is the release date -(yyyy=year, mm=month, dd=day). The mail_release_date configuration -parameter contains the release date (both for official release and -snapshot release). Patches are issued for the official release -and change the patchlevel and the release date. Patches are never -issued for snapshot releases. +are called 2.2-yyyymmdd where yyyymmdd is the release date (yyyy=year, +mm=month, dd=day). The mail_release_date configuration parameter +contains the release date (both for official release and snapshot +release). Patches are issued for the official release and change +the patchlevel and the release date. Patches are never issued for +snapshot releases. Major changes - critical ------------------------ -You must stop Postfix 1.x before upgrading. This is because the -master-child protocols have changed, and nothing will work with -the old master daemon process. +If you run Postfix 1.x or earlier then you must stop Postfix before +upgrading. This is because the master-child protocols have changed, +and very little will work with the old master daemon process. [Incompat 20021119] You can upgrade Postfix 2.0 without stopping. After upgrading an existing Postfix 2.0 system you must use "postfix diff --git a/postfix/TODO-BEFORE-RELEASE b/postfix/TODO-BEFORE-RELEASE deleted file mode 100644 index 9a311b8ec..000000000 --- a/postfix/TODO-BEFORE-RELEASE +++ /dev/null @@ -1,28 +0,0 @@ -Documentation needed before official release: -============================================= - -- RELEASE_NOTES file with all changes since Postfix version 2.0. - -Tools cleanup -============= - -Remove mantools script for 2.0 to 2.1 migration: - - docparam docuseparam double makepostconf makepostconflinks - readme2html specmiss spell useparam user2var var2user - -Functionality to be removed before official release: -==================================================== - -- The anvil daemon. Its user interface needs to evolve. - - find . type f -print | xargs grep -i anvil - -- The tcp_table dictionary type. It's a weak protocol, and the -SMTPD policy delegation protocol provides a superior mechanism. - - find . type f -print | xargs egrep -i 'tcp_table|tcp-based' - -- Change top-level Makefile.stable/snapshot, makedefs.stable/snapshot - -- Delete TODO-BEFORE-RELEASE :-) diff --git a/postfix/conf/postfix-files b/postfix/conf/postfix-files index a6da7df7e..7f48a82f7 100644 --- a/postfix/conf/postfix-files +++ b/postfix/conf/postfix-files @@ -325,6 +325,7 @@ $html_directory/postlog.1.html:f:root:-:644 $html_directory/postmap.1.html:f:root:-:644 $html_directory/postqueue.1.html:f:root:-:644 $html_directory/postsuper.1.html:f:root:-:644 +$html_directory/qshape.1.html:f:root:-:644 $html_directory/proxymap.8.html:f:root:-:644 $html_directory/qmgr.8.html:f:root:-:644 $html_directory/qmqp-sink.1.html:f:root:-:644 diff --git a/postfix/conf/transport b/postfix/conf/transport index b3f011d37..9f6265515 100644 --- a/postfix/conf/transport +++ b/postfix/conf/transport @@ -75,11 +75,9 @@ # a domain name hierarchy, as described in section "TABLE # LOOKUP". # -# The result is of the form transport:nexthop. The trans- -# port field specifies a mail delivery transport such as -# smtp or local. The nexthop field specifies where and how -# to deliver mail. More details are given in section "RESULT -# FORMAT". +# The result is of the form transport:nexthop and specifies +# how or where to deliver mail. This is described in section +# "RESULT FORMAT". # # TABLE LOOKUP # With lookups from indexed files such as DB or DBM, or from @@ -114,129 +112,134 @@ # mon@hostname). # # RESULT FORMAT -# The transport field specifies the name of a mail delivery +# The lookup result is of the form transport:nexthop. The +# transport field specifies a mail delivery transport such +# as smtp or local. The nexthop field specifies where and +# how to deliver mail. +# +# The transport field specifies the name of a mail delivery # transport (the first name of a mail delivery service entry # in the Postfix master.cf file). # -# The interpretation of the nexthop field is transport -# dependent. In the case of SMTP, specify host:service for a -# non-default server port, and use [host] or [host]:port in -# order to disable MX (mail exchanger) DNS lookups. The [] +# The interpretation of the nexthop field is transport +# dependent. In the case of SMTP, specify a service on a +# non-default port as host:service, and disable MX (mail +# exchanger) DNS lookups with [host] or [host]:port. The [] # form is required when you specify an IP address instead of # a hostname. # -# A null transport and null nexthop result means "do not -# change": use the delivery transport and nexthop informa- -# tion that would be used when the entire transport table +# A null transport and null nexthop result means "do not +# change": use the delivery transport and nexthop informa- +# tion that would be used when the entire transport table # did not exist. # -# A non-null transport field with a null nexthop field +# A non-null transport field with a null nexthop field # resets the nexthop information to the recipient domain. # -# A null transport field with non-null nexthop field does +# A null transport field with non-null nexthop field does # not modify the transport information. # # EXAMPLES -# In order to deliver internal mail directly, while using a -# mail relay for all other mail, specify a null entry for -# internal destinations (do not change the delivery trans- -# port or the nexthop information) and specify a wildcard +# In order to deliver internal mail directly, while using a +# mail relay for all other mail, specify a null entry for +# internal destinations (do not change the delivery trans- +# port or the nexthop information) and specify a wildcard # for all other destinations. # # my.domain : # .my.domain : # * smtp:outbound-relay.my.domain # -# In order to send mail for foo.org and its subdomains via -# the uucp transport to the UUCP host named foo: +# In order to send mail for example.com and its subdomains +# via the uucp transport to the UUCP host named example: # -# foo.org uucp:foo -# .foo.org uucp:foo +# example.com uucp:example +# .example.com uucp:example # -# When no nexthop host name is specified, the destination -# domain name is used instead. For example, the following -# directs mail for user@foo.org via the slow transport to a -# mail exchanger for foo.org. The slow transport could be -# something that runs at most one delivery process at a -# time: +# When no nexthop host name is specified, the destination +# domain name is used instead. For example, the following +# directs mail for user@example.com via the slow transport +# to a mail exchanger for example.com. The slow transport +# could be configured to run at most one delivery process at +# a time: # -# foo.org slow: +# example.com slow: # # When no transport is specified, Postfix uses the transport -# that matches the address domain class (see TRANSPORT FIELD -# discussion above). The following sends all mail for -# foo.org and its subdomains to host gateway.foo.org: +# that matches the address domain class (see DESCRIPTION +# above). The following sends all mail for example.com and +# its subdomains to host gateway.example.com: # -# foo.org :[gateway.foo.org] -# .foo.org :[gateway.foo.org] +# example.com :[gateway.example.com] +# .example.com :[gateway.example.com] # -# In the above example, the [] are used to suppress MX -# lookups. The result would likely point to your local -# machine. +# In the above example, the [] suppress MX lookups. This +# prevents mail routing loops when your machine is primary +# MX host for example.com. # -# In the case of delivery via SMTP, one may specify host- +# In the case of delivery via SMTP, one may specify host- # name:service instead of just a host: # -# foo.org smtp:bar.org:2025 +# example.com smtp:bar.example:2025 # -# This directs mail for user@foo.org to host bar.org port -# 2025. Instead of a numerical port a symbolic name may be -# used. Specify [] around the hostname in order to disable -# MX lookups. +# This directs mail for user@example.com to host bar.example +# port 2025. Instead of a numerical port a symbolic name may +# be used. Specify [] around the hostname if MX lookups must +# be disabled. # # The error mailer can be used to bounce mail: # -# .foo.org error:mail for *.foo.org is not deliv- -# erable +# .example.com error:mail for *.example.com is not +# deliverable # -# This causes all mail for user@anything.foo.org to be +# This causes all mail for user@anything.example.com to be # bounced. # # REGULAR EXPRESSION TABLES -# This section describes how the table lookups change when +# This section describes how the table lookups change when # the table is given in the form of regular expressions. For -# a description of regular expression lookup table syntax, +# a description of regular expression lookup table syntax, # see regexp_table(5) or pcre_table(5). # -# Each pattern is a regular expression that is applied to -# the entire address being looked up. Thus, -# some.domain.hierarchy is not looked up via its parent -# domains, nor is user+foo@domain looked up as user@domain. +# Each pattern is a regular expression that is applied to +# the entire address being looked up. Thus, +# some.domain.hierarchy is not looked up via its parent +# domains, nor is user+foo@domain looked up as user@domain. # -# Patterns are applied in the order as specified in the -# table, until a pattern is found that matches the search +# Patterns are applied in the order as specified in the +# table, until a pattern is found that matches the search # string. # -# Results are the same as with indexed file lookups, with -# the additional feature that parenthesized substrings from +# Results are the same as with indexed file lookups, with +# the additional feature that parenthesized substrings from # the pattern can be interpolated as $1, $2 and so on. # # TCP-BASED TABLES -# This section describes how the table lookups change when +# This section describes how the table lookups change when # lookups are directed to a TCP-based server. For a descrip- -# tion of the TCP client/server lookup protocol, see -# tcp_table(5). This feature is not available in Postfix +# tion of the TCP client/server lookup protocol, see +# tcp_table(5). This feature is not available in Postfix # version 2.1. # -# Each lookup operation uses the entire recipient address -# once. Thus, some.domain.hierarchy is not looked up via -# its parent domains, nor is user+foo@domain looked up as +# Each lookup operation uses the entire recipient address +# once. Thus, some.domain.hierarchy is not looked up via +# its parent domains, nor is user+foo@domain looked up as # user@domain. # # Results are the same as with indexed file lookups. # # CONFIGURATION PARAMETERS -# The following main.cf parameters are especially relevant. -# The text below provides only a parameter summary. See +# The following main.cf parameters are especially relevant. +# The text below provides only a parameter summary. See # postconf(5) for more details including examples. # # empty_address_recipient -# The address that is looked up instead of the null +# The address that is looked up instead of the null # sender address. # # parent_domain_matches_subdomains -# List of Postfix features that use domain.tld pat- -# terns to match sub.domain.tld (as opposed to +# List of Postfix features that use domain.tld pat- +# terns to match sub.domain.tld (as opposed to # requiring .domain.tld patterns). # # transport_maps @@ -248,13 +251,13 @@ # postmap(1), Postfix lookup table manager # # README FILES -# Use "postconf readme_directory" or "postconf html_direc- +# Use "postconf readme_directory" or "postconf html_direc- # tory" to locate this information. # DATABASE_README, Postfix lookup table overview # FILTER_README, external content filter # # LICENSE -# The Secure Mailer license must be distributed with this +# The Secure Mailer license must be distributed with this # software. # # AUTHOR(S) diff --git a/postfix/html/Makefile.in b/postfix/html/Makefile.in index e7a7fc3df..043407236 100644 --- a/postfix/html/Makefile.in +++ b/postfix/html/Makefile.in @@ -11,7 +11,8 @@ COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \ postconf.1.html postfix.1.html postkick.1.html postlock.1.html \ postlog.1.html postdrop.1.html postmap.1.html sendmail.1.html \ postqueue.1.html postsuper.1.html smtp-source.1.html \ - smtp-sink.1.html qmqp-source.1.html qmqp-sink.1.html + smtp-sink.1.html qmqp-source.1.html qmqp-sink.1.html \ + qshape.1.html CONFIG = access.5.html aliases.5.html canonical.5.html relocated.5.html \ transport.5.html virtual.5.html pcre_table.5.html regexp_table.5.html \ cidr_table.5.html tcp_table.5.html header_checks.5.html \ @@ -201,6 +202,10 @@ qmqp-sink.1.html: ../src/smtpstone/qmqp-sink.c PATH=../mantools:$$PATH; \ srctoman $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@ +qshape.1.html: ../auxiliary/qshape/qshape.pl + PATH=../mantools:$$PATH; \ + srctoman - $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@ + access.5.html: ../proto/access PATH=../mantools:$$PATH; \ srctoman - $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@ diff --git a/postfix/html/PACKAGE_README.html b/postfix/html/PACKAGE_README.html index 19027e3b5..3aa2a9361 100644 --- a/postfix/html/PACKAGE_README.html +++ b/postfix/html/PACKAGE_README.html @@ -118,17 +118,18 @@ 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 post-install script in the Postfix configuration -directory to set ownership and permission of Postfix files and -directories. Specify any non-default settings for mail_owner or -setgid_group on the post-install command line:

    +
  • 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:

    -# sh post-install upgrade-package setgid_group=xxx mail_owner=yyy
    +# postfix set-permissions upgrade-configuration \
    +       setgid_group=xxx mail_owner=yyy
     
    -

    This will also update the main.cf and master.cf files if -necessary.

    +

    With Postfix versions before 2.1 you achieve the same result +by invoking the post-install script directly.

    diff --git a/postfix/html/QSHAPE_README.html b/postfix/html/QSHAPE_README.html index ba9f161cc..c15d95efd 100644 --- a/postfix/html/QSHAPE_README.html +++ b/postfix/html/QSHAPE_README.html @@ -19,16 +19,18 @@

    Purpose of this document

    -

    This document describes the "qshape" program which helps the +

    This document describes the qshape(1) program which helps the administrator understand the Postfix queue message distribution -sorted by time and by sender or recipient domain. qshape is bundled -with the Postfix 2.1 source under the "auxiliary" directory. In -order to understand the output of qshape, it useful to understand -the various Postfix queues. To this end the role of each Postfix -queue directory is described briefly in the "Background info: -Postfix queue directories" section near the end of this document. +sorted by time and by sender or recipient domain. qshape(1) is +bundled with the Postfix 2.1 source under the "auxiliary" directory.

    +

    In order to understand the output of qshape(1), it useful to +understand the various Postfix queues. To this end the role of each +Postfix queue directory is described briefly in the "Background +info: Postfix queue directories" section near the end of this +document.

    +

    This document covers the following topics:

      @@ -71,8 +73,8 @@ queue

      When mail is draining slowly or the queue is unexpectedly large, -run "qshape" as the super-user (root) to help zero in on the problem. -The "qshape" program displays a tabular view of the Postfix queue +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.

        @@ -217,7 +219,7 @@ $ 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" +please don't forget to include the top 10 or 20 lines of qshape(1) output.

        Example 1: Healthy queue

        @@ -290,7 +292,7 @@ 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.msg.com undeliverables 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.

        @@ -322,7 +324,7 @@ 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" it was quickly determined +

        Using an older version of qshape(1) it was quickly determined that all the messages were for just a few destinations:

        @@ -780,7 +782,7 @@ queue flushes.

        Credits

        -

        The "qshape" program was developed by Victor Duchovni of Morgan +

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

        diff --git a/postfix/html/RESTRICTION_CLASS_README.html b/postfix/html/RESTRICTION_CLASS_README.html index cf184e253..836ca79c8 100644 --- a/postfix/html/RESTRICTION_CLASS_README.html +++ b/postfix/html/RESTRICTION_CLASS_README.html @@ -105,7 +105,8 @@ to IP spoofing.

        ...the usual stuff... /etc/postfix/access: - all permit_mynetworks,reject + all@my.domain permit_mynetworks,reject + all@my.hostname permit_mynetworks,reject
        diff --git a/postfix/html/SMTPD_ACCESS_README.html b/postfix/html/SMTPD_ACCESS_README.html index 130b11dfd..3435f7ef2 100644 --- a/postfix/html/SMTPD_ACCESS_README.html +++ b/postfix/html/SMTPD_ACCESS_README.html @@ -122,13 +122,13 @@ the incoming queue.

        in the SMTPD_PROXY_README document. This happens while Postfix receives mail, before it is stored in the incoming queue.

        -
      • Require that the client sends the HELO or EHLO command +

      • 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").

        -
      • Disallow illegal syntax in MAIL FROM or RCPT TO commands. +

      • 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 = @@ -136,21 +136,21 @@ no").

          -
        • Disallow RFC 822 address syntax (example: "MAIL FROM: the +

        • Disallowing RFC 822 address syntax (example: "MAIL FROM: the dude <dude@example.com>").

          -
        • Disallow addresses that are not enclosed with <> +

        • Disallowing addresses that are not enclosed with <> (example: "MAIL FROM: dude@example.com").

        -
      • Reject mail from a non-existent sender address. This form +

      • 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").

        -
      • Reject mail for a non-existent recipient address. This +

      • 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").

        diff --git a/postfix/html/STANDARD_CONFIGURATION_README.html b/postfix/html/STANDARD_CONFIGURATION_README.html index 67cbe86df..32d152b0a 100644 --- a/postfix/html/STANDARD_CONFIGURATION_README.html +++ b/postfix/html/STANDARD_CONFIGURATION_README.html @@ -108,7 +108,7 @@ their default settings.

        2 myorigin = $mydomain 3 relayhost = $mydomain 4 inet_interfaces = 127.0.0.1 -5 local_transport = error:local delivery is disabled +5 local_transport = error:local delivery is disabled 6 7 /etc/postfix/master.cf: 8 Comment out the local delivery agent entry @@ -282,7 +282,7 @@ harder to break.

        2 myorigin = example.com 3 mydestination = 4 local_recipient_maps = -5 local_transport = error:local mail delivery is disabled +5 local_transport = error:local mail delivery is disabled 6 7 /etc/postfix/master.cf: 8 Comment out the local delivery agent diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html index c2e837498..0398b2c0b 100644 --- a/postfix/html/postconf.1.html +++ b/postfix/html/postconf.1.html @@ -118,24 +118,30 @@ POSTCONF(1) POSTCONF(1) always returns the string foobar as lookup result. + tcp (read-only) + Perform lookups using a simple request-reply + protocol that is described in tcp_table(5). + This feature is not included with Postfix + 2.1. + unix (read-only) - A limited way to query the UNIX authentica- + A limited way to query the UNIX authentica- tion 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 + 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 + 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 table types may exist depending on how Postfix was + Other table types may exist depending on how Postfix was built. -n Print parameter settings that are not left at their @@ -143,7 +149,7 @@ POSTCONF(1) POSTCONF(1) specified in main.cf. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. DIAGNOSTICS @@ -154,14 +160,14 @@ POSTCONF(1) POSTCONF(1) Directory with Postfix configuration files. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf parameters are especially relevant to this program. - The text below provides only a parameter summary. See + The text below provides only a parameter summary. See postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. FILES @@ -174,7 +180,7 @@ POSTCONF(1) POSTCONF(1) DATABASE_README, Postfix lookup table overview LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 4c02d767e..353fa6d01 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -2245,11 +2245,9 @@ 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, -Postfix defers delivery and tries again after some delay. This -behavior is required by the SMTP standard. -

        +

        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 @@ -5578,12 +5576,10 @@ Skip SMTP servers that greet with a 5XX status code (go away, do not try again later).

        -

        -By default, Postfix 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. -

        +

        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.

        @@ -6605,7 +6601,8 @@ code for rejected requests (default: 554).
        reject_unknown_recipient_domain
        Reject the request when the RCPT TO address has no DNS A or MX -record.
        The unknown_address_reject_code parameter specifies +record and Postfix is not final destination for the recipient +address.
        The unknown_address_reject_code parameter specifies the response code for rejected requests (default: 450). The response is always 450 in case of a temporary DNS error.
        @@ -7050,10 +7047,11 @@ Postfix version 2.1 and later.
        reject_unknown_sender_domain
        -
        Reject the request when the MAIL FROM address has no DNS A -or MX record.
        The unknown_address_reject_code parameter -specifies the response code for rejected requests (default: 450). -The response is always 450 in case of a temporary DNS error.
        +
        Reject the request when the MAIL FROM address has no DNS A or +MX record and Postfix is not final destination for the sender +address.
        The unknown_address_reject_code parameter specifies +the response code for rejected requests (default: 450). The response +is always 450 in case of a temporary DNS error.
        reject_unlisted_sender
        diff --git a/postfix/html/qshape.1.html b/postfix/html/qshape.1.html new file mode 100644 index 000000000..506a503b9 --- /dev/null +++ b/postfix/html/qshape.1.html @@ -0,0 +1,117 @@ + + + + Postfix manual - qshape(1) +
        +QSHAPE(1)                                               QSHAPE(1)
        +
        +NAME
        +       qshape - Print Postfix queue domain and age distribution
        +
        +SYNOPSIS
        +       qshape [-s] [-p] [-m min_subdomains]
        +               [-b bucket_count] [-t bucket_time]
        +               [-w terminal_width]
        +               [-c config_directory] [queue_name ...]
        +
        +DESCRIPTION
        +       The  qshape program helps the administrator understand the
        +       Postfix queue message distribution in time and  by  sender
        +       domain  or recipient domain. The program needs read access
        +       to the queue directories and queue files, so it  must  run
        +       as  the  superuser  or the mail_owner specified in main.cf
        +       (typically postfix).
        +
        +       Options:
        +
        +       -s     Display the sender domain distribution  instead  of
        +              the  recipient domain distribution.  By default the
        +              recipient distribution is displayed. There  can  be
        +              more  recipients than messages, but as each message
        +              has only one sender, the sender distribution is a a
        +              message distribution.
        +
        +       -p     Generate  aggregate  statistics for parent domains.
        +              Top level domains are not shown,  nor  are  domains
        +              with  fewer  than  min_subdomains  subdomains.  The
        +              names of parent domains are shown  with  a  leading
        +              dot, (e.g. .example.com).
        +
        +       -m min_subdomains
        +              When used with the -p option, sets the minimum sub-
        +              domain count needed to show a separate line  for  a
        +              parent domain. The default is 5.
        +
        +       -b bucket_count
        +              The  age  distribution is broken up into a sequence
        +              of geometrically increasing intervals. This  option
        +              sets  the  number  of  intervals or "buckets". Each
        +              bucket has a maximum queue age  that  is  twice  as
        +              large  as  that  of  the  previous bucket. The last
        +              bucket has no age limit.
        +
        +       -b bucket_time
        +              The age limit in minutes for the first time bucket.
        +              The  default  value  is  5,  meaning that the first
        +              bucket counts messages between 0 and 5 minutes old.
        +
        +       -w terminal_width
        +              The  output is right justified, with the counts for
        +              the last bucket shown on the 80th column, the  ter-
        +              minal_width  can  be  adjusted  for  wider  screens
        +              allowing more buckets to be displayed with truncat-
        +              ing  the domain names on the left. When a row for a
        +              full domain name and its counters does not  fit  in
        +              the  specified  number of columns, only the last 17
        +              bytes of the domain name are shown with the  prefix
        +              replaced  by  a  '+'  character.  Truncated  parent
        +              domain rows are shown as '.+' followed by the  last
        +              16  bytes  of the domain name. If this is still too
        +              narrow to show the domain name and  all  the  coun-
        +              ters, the terminal_width limit is violated.
        +
        +       -c config_directory
        +              The  main.cf  configuration  file  is  in the named
        +              directory  instead  of  the  default  configuration
        +              directory.
        +
        +       Arguments:
        +
        +       queue_name
        +              By  default  qshape displays the combined distribu-
        +              tion of the incoming and active queues. To  display
        +              a  different  set of queues, just list their direc-
        +              tory names on the command line.  Absolute paths are
        +              used  as  is, other paths are taken relative to the
        +              main.cf queue_directory parameter  setting.   While
        +              main.cf  supports the use of $variable expansion in
        +              the definition of  the  queue_directory  parameter,
        +              the  qshape program does not. If you must use vari-
        +              able expansions in the queue_directory setting, you
        +              must  specify  an  explicit  absolute path for each
        +              queue subdirectory even if  you  want  the  default
        +              incoming and active queue distribution.
        +
        +SEE ALSO
        +       mailq(1) List all messages in the queue.
        +       QSHAPE_README Examples and background material.
        +
        +FILES
        +       $config_directory/main.cf, Postfix installation parameters.
        +       $queue_directory/maildrop/, local submission directory.
        +       $queue_directory/incoming/, new message queue.
        +       $queue_directory/hold/, messages waiting for tech support.
        +       $queue_directory/active/, messages scheduled for delivery.
        +       $queue_directory/deferred/, messages postponed for later delivery.
        +
        +LICENSE
        +       The  Secure  Mailer  license must be distributed with this
        +       software.
        +
        +AUTHOR(S)
        +       Victor Duchovni
        +       Morgan Stanley
        +
        +                                                        QSHAPE(1)
        +
        diff --git a/postfix/html/transport.5.html b/postfix/html/transport.5.html index 2e8f826dc..a6609d7b8 100644 --- a/postfix/html/transport.5.html +++ b/postfix/html/transport.5.html @@ -81,11 +81,9 @@ TRANSPORT(5) TRANSPORT(5) a domain name hierarchy, as described in section "TABLE LOOKUP". - The result is of the form transport:nexthop. The trans- - port field specifies a mail delivery transport such as - smtp or local. The nexthop field specifies where and how - to deliver mail. More details are given in section "RESULT - FORMAT". + The result is of the form transport:nexthop and specifies + how or where to deliver mail. This is described in section + "RESULT FORMAT". TABLE LOOKUP With lookups from indexed files such as DB or DBM, or from @@ -120,129 +118,134 @@ TRANSPORT(5) TRANSPORT(5) mon@hostname). RESULT FORMAT - The transport field specifies the name of a mail delivery + The lookup result is of the form transport:nexthop. The + transport field specifies a mail delivery transport such + as smtp or local. The nexthop field specifies where and + how to deliver mail. + + The transport field specifies the name of a mail delivery transport (the first name of a mail delivery service entry in the Postfix master.cf file). - The interpretation of the nexthop field is transport - dependent. In the case of SMTP, specify host:service for a - non-default server port, and use [host] or [host]:port in - order to disable MX (mail exchanger) DNS lookups. The [] + The interpretation of the nexthop field is transport + dependent. In the case of SMTP, specify a service on a + non-default port as host:service, and disable MX (mail + exchanger) DNS lookups with [host] or [host]:port. The [] form is required when you specify an IP address instead of a hostname. - A null transport and null nexthop result means "do not - change": use the delivery transport and nexthop informa- - tion that would be used when the entire transport table + A null transport and null nexthop result means "do not + change": use the delivery transport and nexthop informa- + tion that would be used when the entire transport table did not exist. - A non-null transport field with a null nexthop field + A non-null transport field with a null nexthop field resets the nexthop information to the recipient domain. - A null transport field with non-null nexthop field does + A null transport field with non-null nexthop field does not modify the transport information. EXAMPLES - In order to deliver internal mail directly, while using a - mail relay for all other mail, specify a null entry for - internal destinations (do not change the delivery trans- - port or the nexthop information) and specify a wildcard + In order to deliver internal mail directly, while using a + mail relay for all other mail, specify a null entry for + internal destinations (do not change the delivery trans- + port or the nexthop information) and specify a wildcard for all other destinations. my.domain : .my.domain : * smtp:outbound-relay.my.domain - In order to send mail for foo.org and its subdomains via - the uucp transport to the UUCP host named foo: + In order to send mail for example.com and its subdomains + via the uucp transport to the UUCP host named example: - foo.org uucp:foo - .foo.org uucp:foo + example.com uucp:example + .example.com uucp:example - When no nexthop host name is specified, the destination - domain name is used instead. For example, the following - directs mail for user@foo.org via the slow transport to a - mail exchanger for foo.org. The slow transport could be - something that runs at most one delivery process at a - time: + When no nexthop host name is specified, the destination + domain name is used instead. For example, the following + directs mail for user@example.com via the slow transport + to a mail exchanger for example.com. The slow transport + could be configured to run at most one delivery process at + a time: - foo.org slow: + example.com slow: When no transport is specified, Postfix uses the transport - that matches the address domain class (see TRANSPORT FIELD - discussion above). The following sends all mail for - foo.org and its subdomains to host gateway.foo.org: + that matches the address domain class (see DESCRIPTION + above). The following sends all mail for example.com and + its subdomains to host gateway.example.com: - foo.org :[gateway.foo.org] - .foo.org :[gateway.foo.org] + example.com :[gateway.example.com] + .example.com :[gateway.example.com] - In the above example, the [] are used to suppress MX - lookups. The result would likely point to your local - machine. + In the above example, the [] suppress MX lookups. This + prevents mail routing loops when your machine is primary + MX host for example.com. - In the case of delivery via SMTP, one may specify host- + In the case of delivery via SMTP, one may specify host- name:service instead of just a host: - foo.org smtp:bar.org:2025 + example.com smtp:bar.example:2025 - This directs mail for user@foo.org to host bar.org port - 2025. Instead of a numerical port a symbolic name may be - used. Specify [] around the hostname in order to disable - MX lookups. + This directs mail for user@example.com to host bar.example + port 2025. Instead of a numerical port a symbolic name may + be used. Specify [] around the hostname if MX lookups must + be disabled. The error mailer can be used to bounce mail: - .foo.org error:mail for *.foo.org is not deliv- - erable + .example.com error:mail for *.example.com is not + deliverable - This causes all mail for user@anything.foo.org to be + This causes all mail for user@anything.example.com to be bounced. REGULAR EXPRESSION TABLES - This section describes how the table lookups change when + This section describes how the table lookups change when the table is given in the form of regular expressions. For - a description of regular expression lookup table syntax, + a description of regular expression lookup table syntax, see regexp_table(5) or pcre_table(5). - Each pattern is a regular expression that is applied to - the entire address being looked up. Thus, - some.domain.hierarchy is not looked up via its parent - domains, nor is user+foo@domain looked up as user@domain. + Each pattern is a regular expression that is applied to + the entire address being looked up. Thus, + some.domain.hierarchy is not looked up via its parent + domains, nor is user+foo@domain looked up as user@domain. - Patterns are applied in the order as specified in the - table, until a pattern is found that matches the search + Patterns are applied in the order as specified in the + table, until a pattern is found that matches the search string. - Results are the same as with indexed file lookups, with - the additional feature that parenthesized substrings from + Results are the same as with indexed file lookups, with + the additional feature that parenthesized substrings from the pattern can be interpolated as $1, $2 and so on. TCP-BASED TABLES - This section describes how the table lookups change when + This section describes how the table lookups change when lookups are directed to a TCP-based server. For a descrip- - tion of the TCP client/server lookup protocol, see - tcp_table(5). This feature is not available in Postfix + tion of the TCP client/server lookup protocol, see + tcp_table(5). This feature is not available in Postfix version 2.1. - Each lookup operation uses the entire recipient address - once. Thus, some.domain.hierarchy is not looked up via - its parent domains, nor is user+foo@domain looked up as + Each lookup operation uses the entire recipient address + once. Thus, some.domain.hierarchy is not looked up via + its parent domains, nor is user+foo@domain looked up as user@domain. Results are the same as with indexed file lookups. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant. - The text below provides only a parameter summary. See + The following main.cf parameters are especially relevant. + The text below provides only a parameter summary. See postconf(5) for more details including examples. empty_address_recipient - The address that is looked up instead of the null + The address that is looked up instead of the null sender address. parent_domain_matches_subdomains - List of Postfix features that use domain.tld pat- - terns to match sub.domain.tld (as opposed to + List of Postfix features that use domain.tld pat- + terns to match sub.domain.tld (as opposed to requiring .domain.tld patterns). transport_maps @@ -258,7 +261,7 @@ TRANSPORT(5) TRANSPORT(5) FILTER_README, external content filter LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/man/junk b/postfix/man/junk new file mode 100644 index 000000000..c5f44b835 --- /dev/null +++ b/postfix/man/junk @@ -0,0 +1,2796 @@ +/*++ +/* NAME +/* smtpd 8 +/* SUMMARY +/* Postfix SMTP server +/* SYNOPSIS +/* \fBsmtpd\fR [generic Postfix daemon options] +/* DESCRIPTION +/* The SMTP server accepts network connection requests +/* and performs zero or more SMTP transactions per connection. +/* Each received message is piped through the \fBcleanup\fR(8) +/* daemon, and is placed into the \fBincoming\fR queue as one +/* single queue file. For this mode of operation, the program +/* expects to be run from the \fBmaster\fR(8) process manager. +/* +/* Alternatively, the SMTP server takes an established +/* connection on standard input and deposits messages directly +/* into the \fBmaildrop\fR queue. In this so-called stand-alone +/* mode, the SMTP server can accept mail even while the mail +/* system is not running. +/* +/* The SMTP server implements a variety of policies for connection +/* requests, and for parameters given to \fBHELO, ETRN, MAIL FROM, VRFY\fR +/* and \fBRCPT TO\fR commands. They are detailed below and in the +/* \fBmain.cf\fR configuration file. +/* SECURITY +/* .ad +/* .fi +/* The SMTP server is moderately security-sensitive. It talks to SMTP +/* clients and to DNS servers on the network. The SMTP server can be +/* run chrooted at fixed low privilege. +/* STANDARDS +/* RFC 821 (SMTP protocol) +/* RFC 1123 (Host requirements) +/* RFC 1652 (8bit-MIME transport) +/* RFC 1869 (SMTP service extensions) +/* RFC 1870 (Message Size Declaration) +/* RFC 1985 (ETRN command) +/* RFC 2554 (AUTH command) +/* RFC 2821 (SMTP protocol) +/* RFC 2920 (SMTP Pipelining) +/* DIAGNOSTICS +/* Problems and transactions are logged to \fBsyslogd\fR(8). +/* +/* Depending on the setting of the \fBnotify_classes\fR parameter, +/* the postmaster is notified of bounces, protocol problems, +/* policy violations, and of other trouble. +/* CONFIGURATION PARAMETERS +/* .ad +/* .fi +/* Changes to \fBmain.cf\fR are picked up automatically, as smtpd(8) +/* processes run for only a limited amount of time. Use the command +/* "\fBpostfix reload\fR" to speed up a change. +/* +/* The text below provides only a parameter summary. See +/* postconf(5) for more details including examples. +/* COMPATIBILITY CONTROLS +/* .ad +/* .fi +/* The following parameters work around implementation errors in other +/* software, and/or allow you to override standards in order to prevent +/* undesirable use. +/* .ad +/* .fi +/* .IP "\fBbroken_sasl_auth_clients (no)\fR" +/* Enable inter-operability with SMTP clients that implement an obsolete +/* version of the AUTH command (RFC 2554). +/* .IP "\fBdisable_vrfy_command (no)\fR" +/* Disable the SMTP VRFY command. +/* .IP "\fBsmtpd_noop_commands (empty)\fR" +/* List of commands that the Postfix SMTP server replies to with "250 +/* Ok", without doing any syntax checks and without changing state. +/* .IP "\fBstrict_rfc821_envelopes (no)\fR" +/* 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. +/* .PP +/* Available in Postfix version 2.1 and later: +/* .IP "\fBresolve_null_domain (no)\fR" +/* Resolve an address that ends in the "@" null domain as if the +/* local hostname were specified, instead of rejecting the address as +/* invalid. +/* .IP "\fBsmtpd_reject_unlisted_sender (no)\fR" +/* Request that the Postfix SMTP server rejects mail from unknown +/* sender addresses, even when no explicit reject_unlisted_sender +/* access restriction is specified. +/* .IP "\fBsmtpd_sasl_exceptions_networks (empty)\fR" +/* What SMTP clients Postfix will not offer AUTH support to. +/* AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS +/* .ad +/* .fi +/* As of version 1.0, Postfix can be configured to send new mail to +/* an external content filter AFTER the mail is queued. This content +/* filter is expected to inject mail back into a (Postfix or other) +/* MTA for further delivery. See the FILTER_README document for details. +/* .IP "\fBcontent_filter (empty)\fR" +/* The name of a mail delivery transport that filters mail after +/* it is queued. +/* BEFORE QUEUE EXTERNAL CONTENT INSPECTION CONTROLS +/* .ad +/* .fi +/* As of version 2.1, the Postfix SMTP server can be configured +/* to send incoming mail to a real-time SMTP-based content filter +/* BEFORE mail is queued. This content filter is expected to inject +/* mail back into Postfix. See the SMTPD_PROXY_README document for +/* details on how to configure and operate this feature. +/* .IP "\fBsmtpd_proxy_filter (empty)\fR" +/* The hostname and TCP port of the mail filtering proxy server. +/* .IP "\fBsmtpd_proxy_ehlo ($myhostname)\fR" +/* How the Postfix SMTP server announces itself to the proxy filter. +/* .IP "\fBsmtpd_proxy_timeout (100s)\fR" +/* The time limit for connecting to a proxy filter and for sending or +/* receiving information. +/* GENERAL CONTENT INSPECTION CONTROLS +/* .ad +/* .fi +/* The following parameters are applicable for both built-in +/* and external content filters. +/* .PP +/* Available in Postfix version 2.1 and later: +/* .IP "\fBreceive_override_options (empty)\fR" +/* Enable or disable recipient validation, built-in content +/* filtering, or address rewriting. +/* EXTERNAL CONTENT INSPECTION CONTROLS +/* .ad +/* .fi +/* The following parameters are applicable for both before-queue +/* and after-queue content filtering. +/* .PP +/* Available in Postfix version 2.1 and later: +/* .IP "\fBsmtpd_authorized_xforward_hosts (empty)\fR" +/* What SMTP clients are allowed to use the XFORWARD feature. +/* SASL AUTHENTICATION CONTROLS +/* .ad +/* .fi +/* Postfix SASL support (RFC 2554) can be used to authenticate remote +/* SMTP clients to the Postfix SMTP server, and to authenticate the +/* Postfix SMTP client to a remote SMTP server. +/* See the SASL_README document for details. +/* .IP "\fBbroken_sasl_auth_clients (no)\fR" +/* Enable inter-operability with SMTP clients that implement an obsolete +/* version of the AUTH command (RFC 2554). +/* .IP "\fBsmtpd_sasl_auth_enable (no)\fR" +/* Enable SASL authentication in the Postfix SMTP server. +/* .IP "\fBsmtpd_sasl_application_name (smtpd)\fR" +/* The application name used for SASL server initialization. +/* .IP "\fBsmtpd_sasl_local_domain (empty)\fR" +/* The name of the local SASL authentication realm. +/* .IP "\fBsmtpd_sasl_security_options (noanonymous)\fR" +/* Restrict what authentication mechanisms the Postfix SMTP server +/* will offer to the client. +/* .IP "\fBsmtpd_sender_login_maps (empty)\fR" +/* Optional lookup table with the SASL login names that own sender +/* (MAIL FROM) addresses. +/* .PP +/* Available in Postfix version 2.1 and later: +/* .IP "\fBsmtpd_sasl_exceptions_networks (empty)\fR" +/* What SMTP clients Postfix will not offer AUTH support to. +/* VERP SUPPORT CONTROLS +/* .ad +/* .fi +/* With VERP style delivery, each recipient of a message receives a +/* customized copy of the message with his/her own recipient address +/* encoded in the envelope sender address. The VERP_README file +/* describes configuration and operation details of Postfix support +/* for variable envelope return path addresses. VERP style delivery +/* is requested with the SMTP XVERP command or with the "sendmail +/* -V" command-line option and is available in Postfix version 1.1 +/* and later. +/* .IP "\fBdefault_verp_delimiters (+=)\fR" +/* The two default VERP delimiter characters. +/* .IP "\fBverp_delimiter_filter (-=+)\fR" +/* The characters Postfix accepts as VERP delimiter characters on the +/* Postfix sendmail(1) command line and in SMTP commands. +/* .PP +/* Available in Postfix version 1.1 and 2.0: +/* .IP "\fBauthorized_verp_clients ($mynetworks)\fR" +/* What SMTP clients are allowed to specify the XVERP command. +/* .PP +/* Available in Postfix version 2.1 and later: +/* .IP "\fBsmtpd_authorized_verp_clients ($authorized_verp_clients)\fR" +/* What SMTP clients are allowed to specify the XVERP command. +/* TROUBLE SHOOTING CONTROLS +/* .ad +/* .fi +/* The DEBUG_README document describes how to debug parts of the +/* Postfix mail system. The methods vary from making the software log +/* a lot of detail, to running some daemon processes under control of +/* a call tracer or debugger. +/* .IP "\fBdebug_peer_level (2)\fR" +/* The increment in verbose logging level when a remote client or +/* server matches a pattern in the debug_peer_list parameter. +/* .IP "\fBdebug_peer_list (empty)\fR" +/* 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. +/* .IP "\fBerror_notice_recipient (postmaster)\fR" +/* The recipient of postmaster notifications about mail delivery +/* problems that are caused by policy, resource, software or protocol +/* errors. +/* .IP "\fBnotify_classes (resource, software)\fR" +/* The list of error classes that are reported to the postmaster. +/* .IP "\fBsoft_bounce (no)\fR" +/* Safety net to keep mail queued that would otherwise be returned to +/* the sender. +/* .PP +/* Available in Postfix version 2.1 and later: +/* .IP "\fBsmtpd_authorized_xclient_hosts (empty)\fR" +/* What SMTP clients are allowed to use the XCLIENT feature. +/* KNOWN VERSUS UNKNOWN RECIPIENT CONTROLS +/* .ad +/* .fi +/* As of Postfix version 2.0, the SMTP server rejects mail for +/* unknown recipients. This prevents the mail queue from clogging up +/* with undeliverable MAILER-DAEMON messages. Additional information +/* on this topic is in the LOCAL_RECIPIENT_README and ADDRESS_CLASS_README +/* documents. +/* .IP "\fBshow_user_unknown_table_name (yes)\fR" +/* Display the name of the recipient table in the "User unknown" +/* responses. +/* .IP "\fBcanonical_maps (empty)\fR" +/* Optional address mapping lookup tables for message headers and +/* envelopes. +/* .IP "\fBrecipient_canonical_maps (empty)\fR" +/* Optional address mapping lookup tables for envelope and header +/* recipient addresses. +/* .PP +/* Parameters concerning known/unknown local recipients: +/* .IP "\fBmydestination ($myhostname, localhost.$mydomain, localhost)\fR" +/* The list of domains that are delivered via the $local_transport +/* mail delivery transport. +/* .IP "\fBinet_interfaces (all)\fR" +/* The network interface addresses that this mail system receives mail +/* on. +/* .IP "\fBproxy_interfaces (empty)\fR" +/* The network interface addresses that this mail system receives mail +/* on by way of a proxy or network address translation unit. +/* .IP "\fBlocal_recipient_maps (proxy:unix:passwd.byname $alias_maps)\fR" +/* 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. +/* .IP "\fBunknown_local_recipient_reject_code (550)\fR" +/* 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. +/* .PP +/* Parameters concerning known/unknown recipients of relay destinations: +/* .IP "\fBrelay_domains ($mydestination)\fR" +/* What destination domains (and subdomains thereof) this system +/* will relay mail to. +/* .IP "\fBrelay_recipient_maps (empty)\fR" +/* Optional lookup tables with all valid addresses in the domains +/* that match $relay_domains. +/* .IP "\fBunknown_relay_recipient_reject_code (550)\fR" +/* 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. +/* .PP +/* Parameters concerning known/unknown recipients in virtual alias +/* domains: +/* .IP "\fBvirtual_alias_domains ($virtual_alias_maps)\fR" +/* Optional list of names of virtual alias domains, that is, +/* domains for which all addresses are aliased to addresses in other +/* local or remote domains. +/* .IP "\fBvirtual_alias_maps ($virtual_maps)\fR" +/* Optional lookup tables that alias specific mail addresses or domains +/* to other local or remote address. +/* .IP "\fBunknown_virtual_alias_reject_code (550)\fR" +/* 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. +/* .PP +/* Parameters concerning known/unknown recipients in virtual mailbox +/* domains: +/* .IP "\fBvirtual_mailbox_domains ($virtual_mailbox_maps)\fR" +/* The list of domains that are delivered via the $virtual_transport +/* mail delivery transport. +/* .IP "\fBvirtual_mailbox_maps (empty)\fR" +/* Optional lookup tables with all valid addresses in the domains that +/* match $virtual_mailbox_domains. +/* .IP "\fBunknown_virtual_mailbox_reject_code (550)\fR" +/* 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. +/* RESOURCE AND RATE CONTROLS +/* .ad +/* .fi +/* The following parameters limit resource usage by the SMTP +/* server and/or control client request rates. +/* .IP "\fBline_length_limit (2048)\fR" +/* Upon input, long lines are chopped up into pieces of at most +/* this length; upon delivery, long lines are reconstructed. +/* .IP "\fBqueue_minfree (0)\fR" +/* The minimal amount of free space in bytes in the queue file system +/* that is needed to receive mail. +/* .IP "\fBmessage_size_limit (10240000)\fR" +/* The maximal size in bytes of a message, including envelope information. +/* .IP "\fBsmtpd_recipient_limit (1000)\fR" +/* The maximal number of recipients that the Postfix SMTP server +/* accepts per message delivery request. +/* .IP "\fBsmtpd_timeout (300s)\fR" +/* The time limit for sending a Postfix SMTP server response and for +/* receiving a remote SMTP client request. +/* .IP "\fBsmtpd_history_flush_threshold (100)\fR" +/* 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. +/* .PP +/* Not available in Postfix version 2.1: +/* .IP "\fBsmtpd_client_connection_count_limit (50)\fR" +/* How many simultaneous connections any SMTP client is allowed to +/* make to the SMTP service. +/* .IP "\fBsmtpd_client_connection_rate_limit (0)\fR" +/* The maximal number of connection attempts any client is allowed to +/* make to this service per time unit. +/* .IP "\fBsmtpd_client_connection_limit_exceptions ($mynetworks)\fR" +/* Clients that are excluded from connection count or connection rate +/* restrictions. +/* TARPIT CONTROLS +/* .ad +/* .fi +/* When a remote SMTP client makes errors, the Postfix SMTP server +/* can insert delays before responding. This can help to slow down +/* run-away software. The behavior is controlled by an error counter +/* that counts the number of errors within an SMTP session that a +/* client makes without delivering mail. +/* .IP "\fBsmtpd_error_sleep_time (1s)\fR" +/* With Postfix 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. +/* .IP "\fBsmtpd_soft_error_limit (10)\fR" +/* 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. +/* .IP "\fBsmtpd_hard_error_limit (20)\fR" +/* The maximal number of errors a remote SMTP client is allowed to +/* make without delivering mail. +/* .IP "\fBsmtpd_junk_command_limit (100)\fR" +/* 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. +/* .IP "\fBsmtpd_recipient_overshoot_limit (1000)\fR" +/* 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. +/* ACCESS POLICY DELEGATION CONTROLS +/* .ad +/* .fi +/* As of version 2.1, Postfix can be configured to delegate access +/* policy decisions to an external server that runs outside Postfix. +/* See the file SMTPD_POLICY_README for more information. +/* .IP "\fBsmtpd_policy_service_timeout (100s)\fR" +/* The time limit for connecting to, writing to or receiving from a +/* delegated SMTPD policy server. +/* .IP "\fBsmtpd_policy_service_max_idle (300s)\fR" +/* The time after which an idle SMTPD policy service connection is +/* closed. +/* .IP "\fBsmtpd_policy_service_max_ttl (1000s)\fR" +/* The time after which an active SMTPD policy service connection is +/* closed. +/* .IP "\fBsmtpd_policy_service_timeout (100s)\fR" +/* The time limit for connecting to, writing to or receiving from a +/* delegated SMTPD policy server. +/* ACCESS CONTROLS +/* .ad +/* .fi +/* The SMTPD_ACCESS_README document gives an introduction to all the +/* SMTP server access control features. +/* .IP "\fBsmtpd_delay_reject (yes)\fR" +/* 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. +/* .IP "\fBparent_domain_matches_subdomains (see 'postconf -d' output)\fR" +/* What Postfix features match subdomains of "domain.tld" automatically, +/* instead of requiring an explicit ".domain.tld" pattern. +/* .IP "\fBsmtpd_client_restrictions (empty)\fR" +/* Optional SMTP server access restrictions in the context of a client +/* SMTP connection request. +/* .IP "\fBsmtpd_helo_required (no)\fR" +/* Require that a remote SMTP client introduces itself at the beginning +/* of an SMTP session with the HELO or EHLO command. +/* .IP "\fBsmtpd_helo_restrictions (empty)\fR" +/* Optional restrictions that the Postfix SMTP server applies in the +/* context of the SMTP HELO command. +/* .IP "\fBsmtpd_sender_restrictions (empty)\fR" +/* Optional restrictions that the Postfix SMTP server applies in the +/* context of the MAIL FROM command. +/* .IP "\fBsmtpd_recipient_restrictions (permit_mynetworks, reject_unauth_destination)\fR" +/* The access restrictions that the Postfix SMTP server applies in +/* the context of the RCPT TO command. +/* .IP "\fBsmtpd_etrn_restrictions (empty)\fR" +/* Optional SMTP server access restrictions in the context of a client +/* ETRN request. +/* .IP "\fBallow_untrusted_routing (no)\fR" +/* Forward mail with sender-specified routing (user[@%!]remote[@%!]site) +/* from untrusted clients to destinations matching $relay_domains. +/* .IP "\fBsmtpd_restriction_classes (empty)\fR" +/* User-defined aliases for groups of access restrictions. +/* .IP "\fBsmtpd_null_access_lookup_key (<>)\fR" +/* The lookup key to be used in SMTP access(5) tables instead of the +/* null sender address. +/* .IP "\fBpermit_mx_backup_networks (empty)\fR" +/* Restrict the use of the permit_mx_backup SMTP access feature to +/* only domains whose primary MX hosts match the listed networks. +/* .PP +/* Available in Postfix version 2.0 and later: +/* .IP "\fBsmtpd_data_restrictions (empty)\fR" +/* Optional access restrictions that the Postfix SMTP server applies +/* in the context of the SMTP DATA command. +/* .IP "\fBsmtpd_expansion_filter (see 'postconf -d' output)\fR" +/* What characters are allowed in $name expansions of RBL reply +/* templates. +/* .PP +/* Available in Postfix version 2.1 and later: +/* .IP "\fBsmtpd_reject_unlisted_sender (no)\fR" +/* Request that the Postfix SMTP server rejects mail from unknown +/* sender addresses, even when no explicit reject_unlisted_sender +/* access restriction is specified. +/* .IP "\fBsmtpd_reject_unlisted_recipient (yes)\fR" +/* Request that the Postfix SMTP server rejects mail for unknown +/* recipient addresses, even when no explicit reject_unlisted_recipient +/* access restriction is specified. +/* SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS +/* .ad +/* .fi +/* Postfix version 2.1 introduces sender and address verification. +/* This feature is implemented by sending probe email messages that +/* are not actually delivered. +/* This feature is requested via the reject_unverified_sender and +/* reject_unverified_recipient access restrictions. The status of +/* verification probes is maintained by the verify(8) server. +/* See the file ADDRESS_VERIFICATION_README for information +/* about how to configure and operate the Postfix sender/recipient +/* address verification service. +/* .IP "\fBaddress_verify_poll_count (3)\fR" +/* How many times to query the verify(8) service for the completion +/* of an address verification request in progress. +/* .IP "\fBaddress_verify_poll_delay (3s)\fR" +/* The delay between queries for the completion of an address +/* verification request in progress. +/* .IP "\fBaddress_verify_sender (postmaster)\fR" +/* The sender address to use in address verification probes. +/* .IP "\fBunverified_sender_reject_code (450)\fR" +/* The numerical Postfix SMTP server response code when a recipient +/* address is rejected by the reject_unverified_sender restriction. +/* .IP "\fBunverified_recipient_reject_code (450)\fR" +/* The numerical Postfix SMTP server response when a recipient address +/* is rejected by the reject_unverified_recipient restriction. +/* ACCESS CONTROL RESPONSES +/* .ad +/* .fi +/* The following parameters control numerical SMTP reply codes +/* and/or text responses. +/* .IP "\fBaccess_map_reject_code (554)\fR" +/* The numerical Postfix SMTP server response code when a client +/* is rejected by an access(5) map restriction. +/* .IP "\fBdefer_code (450)\fR" +/* The numerical Postfix SMTP server response code when a remote SMTP +/* client request is rejected by the "defer" restriction. +/* .IP "\fBinvalid_hostname_reject_code (501)\fR" +/* The numerical Postfix SMTP server response code when the client +/* HELO or EHLO command parameter is rejected by the reject_invalid_hostname +/* restriction. +/* .IP "\fBmaps_rbl_reject_code (554)\fR" +/* 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_sender or reject_rhsbl_recipient restriction. +/* .IP "\fBnon_fqdn_reject_code (504)\fR" +/* The numerical Postfix SMTP server reply code when a client request +/* is rejected by the reject_non_fqdn_hostname, reject_non_fqdn_sender +/* or reject_non_fqdn_recipient restriction. +/* .IP "\fBreject_code (554)\fR" +/* The numerical Postfix SMTP server response code when a remote SMTP +/* client request is rejected by the "\fBreject\fR" restriction. +/* .IP "\fBrelay_domains_reject_code (554)\fR" +/* The numerical Postfix SMTP server response code when a client +/* request is rejected by the reject_unauth_destination recipient +/* restriction. +/* .IP "\fBunknown_address_reject_code (450)\fR" +/* 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. +/* .IP "\fBunknown_client_reject_code (450)\fR" +/* The numerical Postfix SMTP server response code when a client +/* without valid address <=> name mapping is rejected by the +/* reject_unknown_client restriction. +/* .IP "\fBunknown_hostname_reject_code (450)\fR" +/* The numerical Postfix SMTP server response code when the hostname +/* specified with the HELO or EHLO command is rejected by the +/* reject_unknown_hostname restriction. +/* .PP +/* Available in Postfix version 2.0 and later: +/* .IP "\fBdefault_rbl_reply (see 'postconf -d' output)\fR" +/* The default SMTP server response template for a request that is +/* rejected by an RBL-based restriction. +/* .IP "\fBmulti_recipient_bounce_reject_code (550)\fR" +/* The numerical Postfix SMTP server response code when a remote SMTP +/* client request is blocked by the reject_multi_recipient_bounce +/* restriction. +/* .IP "\fBrbl_reply_maps (empty)\fR" +/* Optional lookup tables with RBL response templates. +/* MISCELLANEOUS CONTROLS +/* .ad +/* .fi +/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" +/* The default location of the Postfix main.cf and master.cf +/* configuration files. +/* .IP "\fBdaemon_timeout (18000s)\fR" +/* How much time a Postfix daemon process may take to handle a +/* request before it is terminated by a built-in watchdog timer. +/* .IP "\fBcommand_directory (see 'postconf -d' output)\fR" +/* The location of all postfix administrative commands. +/* .IP "\fBdouble_bounce_sender (double-bounce)\fR" +/* The sender address of postmaster notifications that are generated +/* by the mail system. +/* .IP "\fBipc_timeout (3600s)\fR" +/* The time limit for sending or receiving information over an internal +/* communication channel. +/* .IP "\fBmail_name (Postfix)\fR" +/* The mail system name that is displayed in Received: headers, in +/* the SMTP greeting banner, and in bounced mail. +/* .IP "\fBmail_owner (postfix)\fR" +/* The UNIX system account that owns the Postfix queue and most Postfix +/* daemon processes. +/* .IP "\fBmax_idle (100s)\fR" +/* The maximum amount of time that an idle Postfix daemon process +/* waits for the next service request before exiting. +/* .IP "\fBmax_use (100)\fR" +/* The maximal number of connection requests before a Postfix daemon +/* process terminates. +/* .IP "\fBmyhostname (see 'postconf -d' output)\fR" +/* The internet hostname of this mail system. +/* .IP "\fBmynetworks (see 'postconf -d' output)\fR" +/* The list of "trusted" SMTP clients that have more privileges than +/* "strangers". +/* .IP "\fBmyorigin ($myhostname)\fR" +/* The default domain name that locally-posted mail appears to come +/* from, and that locally posted mail is delivered to. +/* .IP "\fBprocess_id (read-only)\fR" +/* The process ID of a Postfix command or daemon process. +/* .IP "\fBprocess_name (read-only)\fR" +/* The process name of a Postfix command or daemon process. +/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" +/* The location of the Postfix top-level queue directory. +/* .IP "\fBrecipient_delimiter (empty)\fR" +/* The separator between user names and address extensions (user+foo). +/* .IP "\fBsmtpd_banner ($myhostname ESMTP $mail_name)\fR" +/* The text that follows the 220 status code in the SMTP greeting +/* banner. +/* .IP "\fBsyslog_facility (mail)\fR" +/* The syslog facility of Postfix logging. +/* .IP "\fBsyslog_name (postfix)\fR" +/* The mail system name that is prepended to the process name in syslog +/* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* SEE ALSO +/* cleanup(8), message canonicalization +/* trivial-rewrite(8), address resolver +/* verify(8), address verification service +/* postconf(5), configuration parameters +/* master(8), process manager +/* syslogd(8), system logging +/* README FILES +/* .ad +/* .fi +/* Use "\fBpostconf readme_directory\fR" or +/* "\fBpostconf html_directory\fR" to locate this information. +/* .na +/* .nf +/* ADDRESS_CLASS_README, blocking unknown hosted or relay recipients +/* FILTER_README, external after-queue content filter +/* LOCAL_RECIPIENT_README, blocking unknown local recipients +/* SMTPD_ACCESS_README, built-in access policies +/* SMTPD_POLICY_README, external policy server +/* SMTPD_PROXY_README, external before-queue content filter +/* SASL_README, Postfix SASL howto +/* VERP_README, Postfix XVERP extension +/* XCLIENT_README, Postfix XCLIENT extension +/* XFORWARD_README, Postfix XFORWARD extension +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include +#include +#include +#include +#include +#include /* remove() */ +#include +#include +#include +#include +#include +#include +#include /* offsetof() */ + +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global library. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SNAPSHOT +#include +#endif +#include + +/* Single-threaded server skeleton. */ + +#include + +/* Application-specific */ + +#include +#include +#include +#include +#include +#include +#include + + /* + * Tunable parameters. Make sure that there is some bound on the length of + * an SMTP command, so that the mail system stays in control even when a + * malicious client sends commands of unreasonable length (qmail-dos-1). + * Make sure there is some bound on the number of recipients, so that the + * mail system stays in control even when a malicious client sends an + * unreasonable number of recipients (qmail-dos-2). + */ +int var_smtpd_rcpt_limit; +int var_smtpd_tmout; +int var_smtpd_soft_erlim; +int var_smtpd_hard_erlim; +int var_queue_minfree; /* XXX use off_t */ +char *var_smtpd_banner; +char *var_notify_classes; +char *var_client_checks; +char *var_helo_checks; +char *var_mail_checks; +char *var_rcpt_checks; +char *var_etrn_checks; +char *var_data_checks; +int var_unk_client_code; +int var_bad_name_code; +int var_unk_name_code; +int var_unk_addr_code; +int var_relay_code; +int var_maps_rbl_code; +int var_access_map_code; +char *var_maps_rbl_domains; +char *var_rbl_reply_maps; +int var_helo_required; +int var_reject_code; +int var_defer_code; +int var_smtpd_err_sleep; +int var_non_fqdn_code; +char *var_error_rcpt; +int var_smtpd_delay_reject; +char *var_rest_classes; +int var_strict_rfc821_env; +bool var_disable_vrfy_cmd; +char *var_canonical_maps; +char *var_rcpt_canon_maps; +char *var_virt_alias_maps; +char *var_virt_mailbox_maps; +char *var_alias_maps; +char *var_local_rcpt_maps; +bool var_allow_untrust_route; +int var_smtpd_junk_cmd_limit; +int var_smtpd_rcpt_overlim; +bool var_smtpd_sasl_enable; +char *var_smtpd_sasl_opts; +char *var_smtpd_sasl_appname; +char *var_smtpd_sasl_realm; +char *var_smtpd_sasl_exceptions_networks; +char *var_filter_xport; +bool var_broken_auth_clients; +char *var_perm_mx_networks; +char *var_smtpd_snd_auth_maps; +char *var_smtpd_noop_cmds; +char *var_smtpd_null_key; +int var_smtpd_hist_thrsh; +char *var_smtpd_exp_filter; +char *var_def_rbl_reply; +int var_unv_from_code; +int var_unv_rcpt_code; +int var_mul_rcpt_code; +char *var_relay_rcpt_maps; +char *var_verify_sender; +int var_local_rcpt_code; +int var_virt_alias_code; +int var_virt_mailbox_code; +int var_relay_rcpt_code; +char *var_verp_clients; +int var_show_unk_rcpt_table; +int var_verify_poll_count; +int var_verify_poll_delay; +char *var_smtpd_proxy_filt; +int var_smtpd_proxy_tmout; +char *var_smtpd_proxy_ehlo; +char *var_input_transp; +int var_smtpd_policy_tmout; +int var_smtpd_policy_idle; +int var_smtpd_policy_ttl; +char *var_xclient_hosts; +char *var_xforward_hosts; +bool var_smtpd_rej_unl_from; +bool var_smtpd_rej_unl_rcpt; + +#ifdef SNAPSHOT +int var_smtpd_crate_limit; +int var_smtpd_cconn_limit; +char *var_smtpd_hoggers; + +#endif + + /* + * Silly little macros. + */ +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + + /* + * VERP command name. + */ +#define VERP_CMD "XVERP" +#define VERP_CMD_LEN 5 + +static NAMADR_LIST *verp_clients; + + /* + * XCLIENT command. Access control is cached, so that XCLIENT can't override + * its own access control. + */ +static NAMADR_LIST *xclient_hosts; +static int xclient_allowed; + + /* + * XFORWARD command. Access control is cached. + */ +static NAMADR_LIST *xforward_hosts; +static int xforward_allowed; + + /* + * Client connection and rate limiting. + */ +#ifdef SNAPSHOT +ANVIL_CLNT *anvil_clnt; +static NAMADR_LIST *hogger_list; + +#endif + + /* + * Other application-specific globals. + */ +int smtpd_input_transp_mask; + + /* + * Forward declarations. + */ +static void helo_reset(SMTPD_STATE *); +static void mail_reset(SMTPD_STATE *); +static void rcpt_reset(SMTPD_STATE *); +static void chat_reset(SMTPD_STATE *, int); + +#ifdef USE_SASL_AUTH + + /* + * SASL exceptions. + */ +static NAMADR_LIST *sasl_exceptions_networks; + +/* sasl_client_exception - can we offer AUTH for this client */ + +static int sasl_client_exception(SMTPD_STATE *state) +{ + int match; + + /* + * This is to work around a Netscape mail client bug where it tries to + * use AUTH if available, even if user has not configured it. Returns + * TRUE if AUTH should be offered in the EHLO. + */ + if (sasl_exceptions_networks == 0) + return (0); + + match = namadr_list_match(sasl_exceptions_networks, + state->name, state->addr); + + if (msg_verbose) + msg_info("sasl_exceptions: %s[%s], match=%d", + state->name, state->addr, match); + + return (match); +} + +#endif + +/* collapse_args - put arguments together again */ + +static void collapse_args(int argc, SMTPD_TOKEN *argv) +{ + int i; + + for (i = 1; i < argc; i++) { + vstring_strcat(argv[0].vstrval, " "); + vstring_strcat(argv[0].vstrval, argv[i].strval); + } + argv[0].strval = STR(argv[0].vstrval); +} + +/* helo_cmd - process HELO command */ + +static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) +{ + char *err; + + if (argc < 2) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: HELO hostname"); + return (-1); + } + if (argc > 2) + collapse_args(argc - 1, argv + 1); + if (SMTPD_STAND_ALONE(state) == 0 + && var_smtpd_delay_reject == 0 + && (err = smtpd_check_helo(state, argv[1].strval)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } + if (state->helo_name != 0) + helo_reset(state); + chat_reset(state, var_smtpd_hist_thrsh); + mail_reset(state); + rcpt_reset(state); + state->helo_name = mystrdup(printable(argv[1].strval, '?')); + neuter(state->helo_name, "<>()\\\";:@", '?'); + /* Downgrading the protocol name breaks the unauthorized pipelining test. */ + if (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0 + && strcasecmp(state->protocol, MAIL_PROTO_SMTP) != 0) { + myfree(state->protocol); + state->protocol = mystrdup(MAIL_PROTO_SMTP); + } + smtpd_chat_reply(state, "250 %s", var_myhostname); + return (0); +} + +/* ehlo_cmd - process EHLO command */ + +static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) +{ + char *err; + + /* + * XXX 2821 new feature: Section 4.1.4 specifies that a server must clear + * all buffers and reset the state exactly as if a RSET command had been + * issued. + */ + if (argc < 2) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: EHLO hostname"); + return (-1); + } + if (argc > 2) + collapse_args(argc - 1, argv + 1); + if (SMTPD_STAND_ALONE(state) == 0 + && var_smtpd_delay_reject == 0 + && (err = smtpd_check_helo(state, argv[1].strval)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } + if (state->helo_name != 0) + helo_reset(state); + chat_reset(state, var_smtpd_hist_thrsh); + mail_reset(state); + rcpt_reset(state); + state->helo_name = mystrdup(printable(argv[1].strval, '?')); + neuter(state->helo_name, "<>()\\\";:@", '?'); + if (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0) { + myfree(state->protocol); + state->protocol = mystrdup(MAIL_PROTO_ESMTP); + } + smtpd_chat_reply(state, "250-%s", var_myhostname); + smtpd_chat_reply(state, "250-PIPELINING"); + if (var_message_limit) + smtpd_chat_reply(state, "250-SIZE %lu", + (unsigned long) var_message_limit); /* XXX */ + else + smtpd_chat_reply(state, "250-SIZE"); + if (var_disable_vrfy_cmd == 0) + smtpd_chat_reply(state, "250-VRFY"); + smtpd_chat_reply(state, "250-ETRN"); +#ifdef USE_SASL_AUTH + if (var_smtpd_sasl_enable && !sasl_client_exception(state)) { + smtpd_chat_reply(state, "250-AUTH %s", state->sasl_mechanism_list); + if (var_broken_auth_clients) + smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list); + } +#endif + if (namadr_list_match(verp_clients, state->name, state->addr)) + smtpd_chat_reply(state, "250-%s", VERP_CMD); + /* XCLIENT must not override its own access control. */ + if (xclient_allowed) + smtpd_chat_reply(state, "250-" XCLIENT_CMD + " " XCLIENT_NAME " " XCLIENT_ADDR + " " XCLIENT_PROTO " " XCLIENT_HELO); + if (xforward_allowed) + smtpd_chat_reply(state, "250-" XFORWARD_CMD + " " XFORWARD_NAME " " XFORWARD_ADDR + " " XFORWARD_PROTO " " XFORWARD_HELO); + smtpd_chat_reply(state, "250 8BITMIME"); + return (0); +} + +/* helo_reset - reset HELO/EHLO command stuff */ + +static void helo_reset(SMTPD_STATE *state) +{ + if (state->helo_name) + myfree(state->helo_name); + state->helo_name = 0; +} + +/* mail_open_stream - open mail queue file or IPC stream */ + +static void mail_open_stream(SMTPD_STATE *state) +{ + char *postdrop_command; + int cleanup_flags; + + /* + * XXX 2821: An SMTP server is not allowed to "clean up" mail except in + * the case of original submissions. Presently, Postfix always runs all + * mail through the cleanup server. + * + * We could approximate the RFC as follows: Postfix rewrites mail if it + * comes from a source that we are willing to relay for. This way, we + * avoid rewriting most mail that comes from elsewhere. However, that + * requires moving functionality away from the cleanup daemon elsewhere, + * such as virtual address expansion, and header/body pattern matching. + */ + + /* + * If running from the master or from inetd, connect to the cleanup + * service. + */ + cleanup_flags = CLEANUP_FLAG_MASK_EXTERNAL; + if (smtpd_input_transp_mask & INPUT_TRANSP_ADDRESS_MAPPING) + cleanup_flags &= ~(CLEANUP_FLAG_BCC_OK | CLEANUP_FLAG_MAP_OK); + if (smtpd_input_transp_mask & INPUT_TRANSP_HEADER_BODY) + cleanup_flags &= ~CLEANUP_FLAG_FILTER; + + if (SMTPD_STAND_ALONE(state) == 0) { + state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, + var_cleanup_service); + if (state->dest == 0 + || attr_print(state->dest->stream, ATTR_FLAG_NONE, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, cleanup_flags, + ATTR_TYPE_END) != 0) + msg_fatal("unable to connect to the %s %s service", + MAIL_CLASS_PUBLIC, var_cleanup_service); + } + + /* + * Otherwise, pipe the message through the privileged postdrop helper. + * XXX Make postdrop a manifest constant. + */ + else { + postdrop_command = concatenate(var_command_dir, "/postdrop", + msg_verbose ? " -v" : (char *) 0, (char *) 0); + state->dest = mail_stream_command(postdrop_command); + if (state->dest == 0) + msg_fatal("unable to execute %s", postdrop_command); + myfree(postdrop_command); + } + state->cleanup = state->dest->stream; + state->queue_id = mystrdup(state->dest->id); + + /* + * Record the time of arrival, the sender envelope address, some session + * information, and some additional attributes. + */ + if (SMTPD_STAND_ALONE(state) == 0) { + rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld", state->time); + if (*var_filter_xport) + rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport); + } + rec_fputs(state->cleanup, REC_TYPE_FROM, state->sender); + if (state->encoding != 0) + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ENCODING, state->encoding); + + /* + * Store the client attributes for logging purposes. + */ + if (SMTPD_STAND_ALONE(state) == 0) { + if (IS_AVAIL_CLIENT_NAME(FORWARD_NAME(state))) + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_CLIENT_NAME, FORWARD_NAME(state)); + if (IS_AVAIL_CLIENT_ADDR(FORWARD_ADDR(state))) + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_CLIENT_ADDR, FORWARD_ADDR(state)); + if (IS_AVAIL_CLIENT_NAMADDR(FORWARD_NAMADDR(state))) + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ORIGIN, FORWARD_NAMADDR(state)); + if (IS_AVAIL_CLIENT_HELO(FORWARD_HELO(state))) + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_HELO_NAME, FORWARD_HELO(state)); + if (IS_AVAIL_CLIENT_PROTO(FORWARD_PROTO(state))) + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_PROTO_NAME, FORWARD_PROTO(state)); + } + if (state->verp_delims) + rec_fputs(state->cleanup, REC_TYPE_VERP, state->verp_delims); +} + +/* extract_addr - extract address from rubble */ + +static char *extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg, + int allow_empty_addr, int strict_rfc821) +{ + char *myname = "extract_addr"; + TOK822 *tree; + TOK822 *tp; + TOK822 *addr = 0; + int naddr; + int non_addr; + char *err = 0; + char *junk = 0; + char *text; + char *colon; + + /* + * Special case. + */ +#define PERMIT_EMPTY_ADDR 1 +#define REJECT_EMPTY_ADDR 0 + + /* + * Some mailers send RFC822-style address forms (with comments and such) + * in SMTP envelopes. We cannot blame users for this: the blame is with + * programmers violating the RFC, and with sendmail for being permissive. + * + * XXX The SMTP command tokenizer must leave the address in externalized + * (quoted) form, so that the address parser can correctly extract the + * address from surrounding junk. + * + * XXX We have only one address parser, written according to the rules of + * RFC 822. That standard differs subtly from RFC 821. + */ + if (msg_verbose) + msg_info("%s: input: %s", myname, STR(arg->vstrval)); + if (STR(arg->vstrval)[0] == '<' + && STR(arg->vstrval)[LEN(arg->vstrval) - 1] == '>') { + junk = text = mystrndup(STR(arg->vstrval) + 1, LEN(arg->vstrval) - 2); + } else + text = STR(arg->vstrval); + + /* + * Truncate deprecated route address form. + */ + if (*text == '@' && (colon = strchr(text, ':')) != 0) + text = colon + 1; + tree = tok822_parse(text); + + if (junk) + myfree(junk); + + /* + * Find trouble. + */ + for (naddr = non_addr = 0, tp = tree; tp != 0; tp = tp->next) { + if (tp->type == TOK822_ADDR) { + addr = tp; + naddr += 1; /* count address forms */ + } else if (tp->type == '<' || tp->type == '>') { + /* void */ ; /* ignore brackets */ + } else { + non_addr += 1; /* count non-address forms */ + } + } + + /* + * Report trouble. Log a warning only if we are going to sleep+reject so + * that attackers can't flood our logfiles. + */ + if (naddr > 1 + || (strict_rfc821 && (non_addr || *STR(arg->vstrval) != '<'))) { + msg_warn("Illegal address syntax from %s in %s command: %s", + state->namaddr, state->where, STR(arg->vstrval)); + err = "501 Bad address syntax"; + } + + /* + * Overwrite the input with the extracted address. This seems bad design, + * but we really are not going to use the original data anymore. What we + * start with is quoted (external) form, and what we need is unquoted + * (internal form). + */ + if (addr) + tok822_internalize(arg->vstrval, addr->head, TOK822_STR_DEFL); + else + vstring_strcpy(arg->vstrval, ""); + arg->strval = STR(arg->vstrval); + + /* + * Report trouble. Log a warning only if we are going to sleep+reject so + * that attackers can't flood our logfiles. + */ + if (err == 0) + if ((arg->strval[0] == 0 && !allow_empty_addr) + || (strict_rfc821 && arg->strval[0] == '@') + || (SMTPD_STAND_ALONE(state) == 0 + && smtpd_check_addr(STR(arg->vstrval)) != 0)) { + msg_warn("Illegal address syntax from %s in %s command: %s", + state->namaddr, state->where, STR(arg->vstrval)); + err = "501 Bad address syntax"; + } + + /* + * Cleanup. + */ + tok822_free_tree(tree); + if (msg_verbose) + msg_info("%s: result: %s", myname, STR(arg->vstrval)); + return (err); +} + +/* mail_cmd - process MAIL command */ + +static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) +{ + char *err; + int narg; + char *arg; + char *verp_delims = 0; + + state->encoding = 0; + + /* + * Sanity checks. + * + * XXX 2821 pedantism: Section 4.1.2 says that SMTP servers that receive a + * command in which invalid character codes have been employed, and for + * which there are no other reasons for rejection, MUST reject that + * command with a 501 response. So much for the principle of "be liberal + * in what you accept, be strict in what you send". + */ + if (var_helo_required && state->helo_name == 0) { + state->error_mask |= MAIL_ERROR_POLICY; + smtpd_chat_reply(state, "503 Error: send HELO/EHLO first"); + return (-1); + } +#define IN_MAIL_TRANSACTION(state) ((state)->sender != 0) + + if (IN_MAIL_TRANSACTION(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "503 Error: nested MAIL command"); + return (-1); + } + if (argc < 3 + || strcasecmp(argv[1].strval, "from:") != 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: MAIL FROM:
        "); + return (-1); + } + if (argv[2].tokval == SMTPD_TOK_ERROR) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad sender address syntax"); + return (-1); + } + if ((err = extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "%s", err); + return (-1); + } + for (narg = 3; narg < argc; narg++) { + arg = argv[narg].strval; + if (strcasecmp(arg, "BODY=8BITMIME") == 0) { /* RFC 1652 */ + state->encoding = MAIL_ATTR_ENC_8BIT; + } else if (strcasecmp(arg, "BODY=7BIT") == 0) { /* RFC 1652 */ + state->encoding = MAIL_ATTR_ENC_7BIT; + } else if (strncasecmp(arg, "SIZE=", 5) == 0) { /* RFC 1870 */ + /* Reject non-numeric size. */ + if (!alldig(arg + 5)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad message size syntax"); + return (-1); + } + /* Reject size overflow. */ + if ((state->msg_size = off_cvt_string(arg + 5)) < 0) { + smtpd_chat_reply(state, "552 Message size exceeds file system imposed limit"); + state->error_mask |= MAIL_ERROR_POLICY; + return (-1); + } +#ifdef USE_SASL_AUTH + } else if (var_smtpd_sasl_enable && strncasecmp(arg, "AUTH=", 5) == 0) { + if ((err = smtpd_sasl_mail_opt(state, arg + 5)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } +#endif + } else if (namadr_list_match(verp_clients, state->name, state->addr) + && strncasecmp(arg, VERP_CMD, VERP_CMD_LEN) == 0 + && (arg[VERP_CMD_LEN] == '=' || arg[VERP_CMD_LEN] == 0)) { + if (arg[VERP_CMD_LEN] == 0) { + verp_delims = var_verp_delims; + } else { + verp_delims = arg + VERP_CMD_LEN + 1; + if (verp_delims_verify(verp_delims) != 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Error: %s needs two characters from %s", + VERP_CMD, var_verp_filter); + return (-1); + } + } + } else { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "555 Unsupported option: %s", arg); + return (-1); + } + } + if (verp_delims && argv[2].strval[0] == 0) { + smtpd_chat_reply(state, "503 Error: %s requires non-null sender", + VERP_CMD); + return (-1); + } + if (SMTPD_STAND_ALONE(state) == 0 + && var_smtpd_delay_reject == 0 + && (err = smtpd_check_mail(state, argv[2].strval)) != 0) { + smtpd_chat_reply(state, "%s", err); + /* XXX Reset access map side effects. */ + mail_reset(state); + return (-1); + } + + /* + * Check the queue file space, if applicable. + */ + if (!USE_SMTPD_PROXY(state)) { + if ((err = smtpd_check_size(state, state->msg_size)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } + } + + /* + * No more early returns. The mail transaction is in progress. + */ + state->time = time((time_t *) 0); + state->sender = mystrdup(argv[2].strval); + vstring_sprintf(state->instance, "%x.%lx.%x", + var_pid, (unsigned long) state->time, state->seqno++); + if (verp_delims) + state->verp_delims = mystrdup(verp_delims); + if (USE_SMTPD_PROXY(state)) + state->proxy_mail = mystrdup(STR(state->buffer)); + smtpd_chat_reply(state, "250 Ok"); + return (0); +} + +/* mail_reset - reset MAIL command stuff */ + +static void mail_reset(SMTPD_STATE *state) +{ + state->msg_size = 0; + + /* + * Unceremoniously close the pipe to the cleanup service. The cleanup + * service will delete the queue file when it detects a premature + * end-of-file condition on input. + */ + if (state->cleanup != 0) { + mail_stream_cleanup(state->dest); + state->dest = 0; + state->cleanup = 0; + } + state->err = 0; + if (state->queue_id != 0) { + myfree(state->queue_id); + state->queue_id = 0; + } + if (state->sender) { + myfree(state->sender); + state->sender = 0; + } + if (state->verp_delims) { + myfree(state->verp_delims); + state->verp_delims = 0; + } + if (state->proxy_mail) { + myfree(state->proxy_mail); + state->proxy_mail = 0; + } + if (state->saved_filter) { + myfree(state->saved_filter); + state->saved_filter = 0; + } + if (state->saved_redirect) { + myfree(state->saved_redirect); + state->saved_redirect = 0; + } + state->saved_flags = 0; +#ifdef USE_SASL_AUTH + if (var_smtpd_sasl_enable) + smtpd_sasl_mail_reset(state); +#endif + state->discard = 0; + VSTRING_RESET(state->instance); + VSTRING_TERMINATE(state->instance); + + /* + * Try to be nice. Don't bother when we lost the connection. Don't bother + * waiting for a reply, it just increases latency. + */ + if (state->proxy) { + (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_NONE, "QUIT"); + smtpd_proxy_close(state); + } + if (state->xforward.flags) + smtpd_xforward_reset(state); + if (state->prepend) + state->prepend = argv_free(state->prepend); +} + +/* rcpt_cmd - process RCPT TO command */ + +static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) +{ + char *err; + int narg; + char *arg; + + /* + * Sanity checks. + * + * XXX 2821 pedantism: Section 4.1.2 says that SMTP servers that receive a + * command in which invalid character codes have been employed, and for + * which there are no other reasons for rejection, MUST reject that + * command with a 501 response. So much for the principle of "be liberal + * in what you accept, be strict in what you send". + */ + if (!IN_MAIL_TRANSACTION(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "503 Error: need MAIL command"); + return (-1); + } + if (argc < 3 + || strcasecmp(argv[1].strval, "to:") != 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: RCPT TO:
        "); + return (-1); + } + if (argv[2].tokval == SMTPD_TOK_ERROR) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad recipient address syntax"); + return (-1); + } + if ((err = extract_addr(state, argv + 2, REJECT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "%s", err); + return (-1); + } + for (narg = 3; narg < argc; narg++) { + arg = argv[narg].strval; + if (1) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "555 Unsupported option: %s", arg); + return (-1); + } + } + if (var_smtpd_rcpt_limit && state->rcpt_count >= var_smtpd_rcpt_limit) { + smtpd_chat_reply(state, "452 Error: too many recipients"); + if (state->rcpt_overshoot++ < var_smtpd_rcpt_overlim) + return (0); + state->error_mask |= MAIL_ERROR_POLICY; + return (-1); + } + if (SMTPD_STAND_ALONE(state) == 0) { + if ((err = smtpd_check_rcpt(state, argv[2].strval)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } + } + + /* + * Don't access the proxy, queue file, or queue file writer process until + * we have a valid recipient address. + */ + if (state->proxy == 0 && state->cleanup == 0) { + if (state->proxy_mail) { + if (smtpd_proxy_open(state, var_smtpd_proxy_filt, + var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo, + state->proxy_mail) != 0) { + smtpd_chat_reply(state, "%s", STR(state->proxy_buffer)); + return (-1); + } + } else { + mail_open_stream(state); + } + + /* + * Log the queue ID with the message origin. + */ +#ifdef USE_SASL_AUTH + if (var_smtpd_sasl_enable) + smtpd_sasl_mail_log(state); + else +#endif + msg_info("%s: client=%s", state->queue_id ? + state->queue_id : "NOQUEUE", FORWARD_NAMADDR(state)); + } + + /* + * Proxy the recipient. OK, so we lied. If the real-time proxy rejects + * the recipient then we can have a proxy connection without having + * accepted a recipient. + */ + if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_WANT_OK, + "%s", STR(state->buffer)) != 0) { + smtpd_chat_reply(state, "%s", STR(state->proxy_buffer)); + return (-1); + } + + /* + * Store the recipient. Remember the first one. + * + * Flush recipients to maintain a stiffer coupling with the next stage and + * to better utilize parallelism. + */ + state->rcpt_count++; + if (state->recipient == 0) + state->recipient = mystrdup(argv[2].strval); + if (state->cleanup) { + rec_fputs(state->cleanup, REC_TYPE_RCPT, argv[2].strval); + vstream_fflush(state->cleanup); + } + smtpd_chat_reply(state, "250 Ok"); + return (0); +} + +/* rcpt_reset - reset RCPT stuff */ + +static void rcpt_reset(SMTPD_STATE *state) +{ + if (state->recipient) { + myfree(state->recipient); + state->recipient = 0; + } + state->rcpt_count = 0; + /* XXX Must flush the command history. */ + state->rcpt_overshoot = 0; +} + +/* data_cmd - process DATA command */ + +static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) +{ + char *err; + char *start; + int len; + int curr_rec_type; + int prev_rec_type; + int first = 1; + VSTRING *why = 0; + int saved_err; + int (*out_record) (VSTREAM *, int, const char *, int); + int (*out_fprintf) (VSTREAM *, int, const char *,...); + VSTREAM *out_stream; + int out_error; + char **cpp; + + /* + * Sanity checks. With ESMTP command pipelining the client can send DATA + * before all recipients are rejected, so don't report that as a protocol + * error. + */ + if (state->rcpt_count == 0) { + if (!IN_MAIL_TRANSACTION(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "503 Error: need RCPT command"); + } else { + smtpd_chat_reply(state, "554 Error: no valid recipients"); + } + return (-1); + } + if (argc != 1) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: DATA"); + return (-1); + } + if (SMTPD_STAND_ALONE(state) == 0 && (err = smtpd_check_data(state)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } + if (state->proxy && smtpd_proxy_cmd(state, SMTPD_PROX_WANT_MORE, + "%s", STR(state->buffer)) != 0) { + smtpd_chat_reply(state, "%s", STR(state->proxy_buffer)); + return (-1); + } + + /* + * One level of indirection to choose between normal or proxied + * operation. We want to avoid massive code duplication within tons of + * if-else clauses. + */ + if (state->proxy) { + out_stream = state->proxy; + out_record = smtpd_proxy_rec_put; + out_fprintf = smtpd_proxy_rec_fprintf; + out_error = CLEANUP_STAT_PROXY; + } else { + out_stream = state->cleanup; + out_record = rec_put; + out_fprintf = rec_fprintf; + out_error = CLEANUP_STAT_WRITE; + } + + /* + * Flush out any access table actions that are delegated to the cleanup + * server, and that may trigger before we accept the first valid + * recipient. + * + * Terminate the message envelope segment. Start the message content + * segment, and prepend our own Received: header. If there is only one + * recipient, list the recipient address. + */ + if (state->cleanup) { + if (state->saved_filter) + rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", state->saved_filter); + if (state->saved_redirect) + rec_fprintf(state->cleanup, REC_TYPE_RDR, "%s", state->saved_redirect); + if (state->saved_flags) + rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d", state->saved_flags); + rec_fputs(state->cleanup, REC_TYPE_MESG, ""); + } + + /* + * PREPEND message headers. + */ + if (state->prepend) + for (cpp = state->prepend->argv; *cpp; cpp++) + out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp); + + /* + * Suppress our own Received: header in the unlikely case that we are an + * intermediate proxy. + */ + if (!state->proxy || state->xforward.flags == 0) { + out_fprintf(out_stream, REC_TYPE_NORM, + "Received: from %s (%s [%s])", + state->helo_name ? state->helo_name : state->name, + state->name, state->addr); + if (state->rcpt_count == 1 && state->recipient) { + out_fprintf(out_stream, REC_TYPE_NORM, + state->cleanup ? "\tby %s (%s) with %s id %s" : + "\tby %s (%s) with %s", + var_myhostname, var_mail_name, + state->protocol, state->queue_id); + quote_822_local(state->buffer, state->recipient); + out_fprintf(out_stream, REC_TYPE_NORM, + "\tfor <%s>; %s", STR(state->buffer), mail_date(state->time)); + } else { + out_fprintf(out_stream, REC_TYPE_NORM, + state->cleanup ? "\tby %s (%s) with %s id %s;" : + "\tby %s (%s) with %s;", + var_myhostname, var_mail_name, + state->protocol, state->queue_id); + out_fprintf(out_stream, REC_TYPE_NORM, + "\t%s", mail_date(state->time)); + } +#ifdef RECEIVED_ENVELOPE_FROM + quote_822_local(state->buffer, state->sender); + out_fprintf(out_stream, REC_TYPE_NORM, + "\t(envelope-from %s)", STR(state->buffer)); +#endif + } + smtpd_chat_reply(state, "354 End data with ."); + + /* + * Copy the message content. If the cleanup process has a problem, keep + * reading until the remote stops sending, then complain. Produce typed + * records from the SMTP stream so we can handle data that spans buffers. + * + * XXX Force an empty record when the queue file content begins with + * whitespace, so that it won't be considered as being part of our own + * Received: header. What an ugly Kluge. + * + * XXX Deal with UNIX-style From_ lines at the start of message content + * because sendmail permits it. + */ + for (prev_rec_type = 0; /* void */ ; prev_rec_type = curr_rec_type) { + if (smtp_get(state->buffer, state->client, var_line_limit) == '\n') + curr_rec_type = REC_TYPE_NORM; + else + curr_rec_type = REC_TYPE_CONT; + start = vstring_str(state->buffer); + len = VSTRING_LEN(state->buffer); + if (first) { + if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) { + out_fprintf(out_stream, curr_rec_type, + "X-Mailbox-Line: %s", start); + continue; + } + first = 0; + if (len > 0 && IS_SPACE_TAB(start[0])) + out_record(out_stream, REC_TYPE_NORM, "", 0); + } + if (prev_rec_type != REC_TYPE_CONT && *start == '.' + && (state->proxy == 0 ? (++start, --len) == 0 : len == 1)) + break; + if (state->err == CLEANUP_STAT_OK + && out_record(out_stream, curr_rec_type, start, len) < 0) + state->err = out_error; + } + + /* + * Send the end of DATA and finish the proxy connection. Set the + * CLEANUP_STAT_PROXY error flag in case of trouble. + * + * XXX The low-level proxy output routines should set "state" error + * attributes. This requires making "state" a context attribute of the + * VSTREAM. + */ + if (state->proxy) { + if (state->err == CLEANUP_STAT_OK) { + (void) smtpd_proxy_cmd(state, SMTPD_PROX_WANT_ANY, "."); + if (state->err == CLEANUP_STAT_OK && + *STR(state->proxy_buffer) != '2') + state->err = CLEANUP_STAT_CONT; + } else { + state->error_mask |= MAIL_ERROR_SOFTWARE; + state->err |= CLEANUP_STAT_PROXY; + vstring_sprintf(state->proxy_buffer, + "451 Error: queue file write error"); + } + } + + /* + * Send the end-of-segment markers and finish the queue file record + * stream. + */ + else { + if (state->err == CLEANUP_STAT_OK) + if (rec_fputs(state->cleanup, REC_TYPE_XTRA, "") < 0 + || rec_fputs(state->cleanup, REC_TYPE_END, "") < 0 + || vstream_fflush(state->cleanup)) + state->err = CLEANUP_STAT_WRITE; + if (state->err == 0) { + why = vstring_alloc(10); + state->err = mail_stream_finish(state->dest, why); + } else + mail_stream_cleanup(state->dest); + state->dest = 0; + state->cleanup = 0; + } + + /* + * Handle any errors. One message may suffer from multiple errors, so + * complain only about the most severe error. Forgive any previous client + * errors when a message was received successfully. + * + * See also: qmqpd.c + */ + if (state->err == CLEANUP_STAT_OK) { + state->error_count = 0; + state->error_mask = 0; + state->junk_cmds = 0; + if (state->queue_id) + smtpd_chat_reply(state, "250 Ok: queued as %s", state->queue_id); + else + smtpd_chat_reply(state, "%s", STR(state->proxy_buffer)); + } else if ((state->err & CLEANUP_STAT_BAD) != 0) { + state->error_mask |= MAIL_ERROR_SOFTWARE; + smtpd_chat_reply(state, "451 Error: internal error %d", state->err); + } else if ((state->err & CLEANUP_STAT_SIZE) != 0) { + state->error_mask |= MAIL_ERROR_BOUNCE; + smtpd_chat_reply(state, "552 Error: message too large"); + } else if ((state->err & CLEANUP_STAT_HOPS) != 0) { + state->error_mask |= MAIL_ERROR_BOUNCE; + smtpd_chat_reply(state, "554 Error: too many hops"); + } else if ((state->err & CLEANUP_STAT_CONT) != 0) { + state->error_mask |= MAIL_ERROR_POLICY; + if (state->proxy_buffer) + smtpd_chat_reply(state, "%s", STR(state->proxy_buffer)); + else + smtpd_chat_reply(state, "550 Error: %s", LEN(why) ? + STR(why) : "content rejected"); + } else if ((state->err & CLEANUP_STAT_WRITE) != 0) { + state->error_mask |= MAIL_ERROR_RESOURCE; + smtpd_chat_reply(state, "451 Error: queue file write error"); + } else if ((state->err & CLEANUP_STAT_PROXY) != 0) { + state->error_mask |= MAIL_ERROR_SOFTWARE; + smtpd_chat_reply(state, "%s", STR(state->proxy_buffer)); + } else { + state->error_mask |= MAIL_ERROR_SOFTWARE; + smtpd_chat_reply(state, "451 Error: internal error %d", state->err); + } + + /* + * Disconnect after transmission must not be treated as "lost connection + * after DATA". + */ + state->where = SMTPD_AFTER_DOT; + + /* + * Cleanup. The client may send another MAIL command. + */ + saved_err = state->err; + chat_reset(state, var_smtpd_hist_thrsh); + mail_reset(state); + rcpt_reset(state); + if (why) + vstring_free(why); + return (saved_err); +} + +/* rset_cmd - process RSET */ + +static int rset_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) +{ + + /* + * Sanity checks. + */ + if (argc != 1) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: RSET"); + return (-1); + } + + /* + * Restore state to right after HELO/EHLO command. + */ + chat_reset(state, var_smtpd_hist_thrsh); + mail_reset(state); + rcpt_reset(state); + smtpd_chat_reply(state, "250 Ok"); + return (0); +} + +/* noop_cmd - process NOOP */ + +static int noop_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) +{ + + /* + * XXX 2821 incompatibility: Section 4.1.1.9 says that NOOP can have a + * parameter string which is to be ignored. NOOP instructions with + * parameters? Go figure. + * + * RFC 2821 violates RFC 821, which says that NOOP takes no parameters. + */ +#ifdef RFC821_SYNTAX + + /* + * Sanity checks. + */ + if (argc != 1) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: NOOP"); + return (-1); + } +#endif + smtpd_chat_reply(state, "250 Ok"); + return (0); +} + +/* vrfy_cmd - process VRFY */ + +static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) +{ + char *err = 0; + + /* + * The SMTP standard (RFC 821) disallows unquoted special characters in + * the VRFY argument. Common practice violates the standard, however. + * Postfix accomodates common practice where it violates the standard. + * + * XXX Impedance mismatch! The SMTP command tokenizer preserves quoting, + * whereas the recipient restrictions checks expect unquoted (internal) + * address forms. Therefore we must parse out the address, or we must + * stop doing recipient restriction checks and lose the opportunity to + * say "user unknown" at the SMTP port. + * + * XXX 2821 incompatibility and brain damage: Section 4.5.1 requires that + * VRFY is implemented. RFC 821 specifies that VRFY is optional. It gets + * even worse: section 3.5.3 says that a 502 (command recognized but not + * implemented) reply is not fully compliant. + * + * Thus, an RFC 2821 compliant implementation cannot refuse to supply + * information in reply to VRFY queries. That is simply bogus. The only + * reply we could supply is a generic 252 reply. This causes spammers to + * add tons of bogus addresses to their mailing lists (spam harvesting by + * trying out large lists of potential recipient names with VRFY). + */ +#define SLOPPY 0 + + if (var_disable_vrfy_cmd) { + state->error_mask |= MAIL_ERROR_POLICY; + smtpd_chat_reply(state, "502 VRFY command is disabled"); + return (-1); + } + if (argc < 2) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: VRFY address"); + return (-1); + } + if (argc > 2) + collapse_args(argc - 1, argv + 1); + if ((err = extract_addr(state, argv + 1, REJECT_EMPTY_ADDR, SLOPPY)) != 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "%s", err); + return (-1); + } + if (SMTPD_STAND_ALONE(state) == 0 + && (err = smtpd_check_rcpt(state, argv[1].strval)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } + + /* + * XXX 2821 new feature: Section 3.5.1 requires that the VRFY response is + * either "full name " or "user@domain". Postfix replies + * with the address that was provided by the client, whether or not it is + * in fully qualified domain form or not. + * + * Reply code 250 is reserved for the case where the address is verified; + * reply code 252 should be used when no definitive certainty exists. + */ + smtpd_chat_reply(state, "252 %s", argv[1].strval); + return (0); +} + +/* etrn_cmd - process ETRN command */ + +static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) +{ + char *err; + + /* + * Sanity checks. + */ + if (var_helo_required && state->helo_name == 0) { + state->error_mask |= MAIL_ERROR_POLICY; + smtpd_chat_reply(state, "503 Error: send HELO/EHLO first"); + return (-1); + } + if (IN_MAIL_TRANSACTION(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "503 Error: MAIL transaction in progress"); + return (-1); + } + if (argc != 2) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "500 Syntax: ETRN domain"); + return (-1); + } + if (!ISALNUM(argv[1].strval[0])) + argv[1].strval++; + if (!valid_hostname(argv[1].strval, DONT_GRIPE)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Error: invalid parameter syntax"); + return (-1); + } + + /* + * XXX The implementation borrows heavily from the code that implements + * UCE restrictions. These typically return 450 or 550 when a request is + * rejected. RFC 1985 requires that 459 be sent when the server refuses + * to perform the request. + */ + if (SMTPD_STAND_ALONE(state)) { + msg_warn("do not use ETRN in \"sendmail -bs\" mode"); + smtpd_chat_reply(state, "458 Unable to queue messages"); + return (-1); + } + if ((err = smtpd_check_etrn(state, argv[1].strval)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } + switch (flush_send(argv[1].strval)) { + case FLUSH_STAT_OK: + smtpd_chat_reply(state, "250 Queuing started"); + return (0); + case FLUSH_STAT_DENY: + msg_warn("reject: ETRN %.100s... from %s", + argv[1].strval, state->namaddr); + smtpd_chat_reply(state, "459 <%s>: service unavailable", + argv[1].strval); + return (-1); + case FLUSH_STAT_BAD: + msg_warn("bad ETRN %.100s... from %s", argv[1].strval, state->namaddr); + smtpd_chat_reply(state, "458 Unable to queue messages"); + return (-1); + default: + msg_warn("unable to talk to fast flush service"); + smtpd_chat_reply(state, "458 Unable to queue messages"); + return (-1); + } +} + +/* quit_cmd - process QUIT command */ + +static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_argv) +{ + + /* + * Don't bother checking the syntax. + */ + smtpd_chat_reply(state, "221 Bye"); + + /* + * When the "." and quit replies are pipelined, make sure they are + * flushed now, to avoid repeated mail deliveries in case of a crash in + * the "clean up before disconnect" code. + */ + vstream_fflush(state->client); + return (0); +} + +/* xclient_cmd - override SMTP client attributes */ + +static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) +{ + SMTPD_TOKEN *argp; + char *attr_value; + char *attr_name; + int update_namaddr = 0; + int peer_code; + static NAME_CODE peer_codes[] = { + XCLIENT_UNAVAILABLE, SMTPD_PEER_CODE_PERM, + XCLIENT_TEMPORARY, SMTPD_PEER_CODE_TEMP, + 0, SMTPD_PEER_CODE_OK, + }; + static NAME_CODE proto_names[] = { + MAIL_PROTO_SMTP, 1, + MAIL_PROTO_ESMTP, 2, + 0, -1, + }; + + /* + * Sanity checks. The XCLIENT command does not override its own access + * control. + */ + if (IN_MAIL_TRANSACTION(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "503 Error: MAIL transaction in progress"); + return (-1); + } + if (argc < 2) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: %s attribute=value...", + XCLIENT_CMD); + return (-1); + } + if (!xclient_allowed) { + state->error_mask |= MAIL_ERROR_POLICY; + smtpd_chat_reply(state, "554 Error: insufficient authorization"); + return (-1); + } +#define STREQ(x,y) (strcasecmp((x), (y)) == 0) +#define UPDATE_STR(s, v) do { \ + if (s) myfree(s); \ + s = (v) ? mystrdup(v) : 0; \ + } while(0) +#define NEUTER_CHARACTERS "<>()\\\";:@" + + /* + * Iterate over all attribute=value elements. + */ + for (argp = argv + 1; argp < argv + argc; argp++) { + attr_name = argp->strval; + + /* + * For safety's sake mask non-printable characters. We'll do more + * specific censoring later. + */ + if ((attr_value = split_at(attr_name, '=')) == 0 || *attr_value == 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Error: attribute=value expected"); + return (-1); + } + printable(attr_value, '?'); + + /* + * NAME=substitute SMTP client hostname. Also updates the client + * hostname lookup status code. + */ + if (STREQ(attr_name, XCLIENT_NAME)) { + peer_code = name_code(peer_codes, NAME_CODE_FLAG_NONE, attr_value); + if (peer_code != SMTPD_PEER_CODE_OK) { + attr_value = CLIENT_NAME_UNKNOWN; + } else { + if (!valid_hostname(attr_value, DONT_GRIPE) + || valid_hostaddr(attr_value, DONT_GRIPE)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad %s syntax: %s", + XCLIENT_NAME, attr_value); + return (-1); + } + } + state->peer_code = peer_code; + UPDATE_STR(state->name, attr_value); + update_namaddr = 1; + } + + /* + * ADDR=substitute SMTP client network address. + */ + else if (STREQ(attr_name, XCLIENT_ADDR)) { + if (STREQ(attr_value, XCLIENT_UNAVAILABLE)) { + attr_value = CLIENT_ADDR_UNKNOWN; + } else { + if (!valid_hostaddr(attr_value, DONT_GRIPE)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad %s syntax: %s", + XCLIENT_ADDR, attr_value); + return (-1); + } + } + UPDATE_STR(state->addr, attr_value); + update_namaddr = 1; + } + + /* + * HELO=substitute SMTP client HELO parameter. Censor special + * characters that could mess up message headers. + */ + else if (STREQ(attr_name, XCLIENT_HELO)) { + if (STREQ(attr_value, XCLIENT_UNAVAILABLE)) { + attr_value = CLIENT_HELO_UNKNOWN; + } else { + if (strlen(attr_value) > VALID_HOSTNAME_LEN) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad %s syntax: %s", + XCLIENT_HELO, attr_value); + return (-1); + } + neuter(attr_value, NEUTER_CHARACTERS, '?'); + } + UPDATE_STR(state->helo_name, attr_value); + } + + /* + * PROTO=SMTP protocol name. + */ + else if (STREQ(attr_name, XCLIENT_PROTO)) { + if (name_code(proto_names, NAME_CODE_FLAG_NONE, attr_value) < 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad %s syntax: %s", + XCLIENT_PROTO, attr_value); + return (-1); + } + UPDATE_STR(state->protocol, uppercase(attr_value)); + } + + /* + * Unknown attribute name. Complain. + */ + else { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad %s attribute name: %s", + XCLIENT_CMD, attr_name); + return (-1); + } + } + + /* + * Update the combined name and address when either has changed. + */ + if (update_namaddr) { + if (state->namaddr) + myfree(state->namaddr); + state->namaddr = + concatenate(state->name, "[", state->addr, "]", (char *) 0); + } + smtpd_chat_reply(state, "250 Ok"); + return (0); +} + +/* xforward_cmd - forward logging attributes */ + +static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) +{ + SMTPD_TOKEN *argp; + char *attr_value; + char *attr_name; + int updated = 0; + static NAME_CODE xforward_flags[] = { + XFORWARD_NAME, SMTPD_STATE_XFORWARD_NAME, + XFORWARD_ADDR, SMTPD_STATE_XFORWARD_ADDR, + XFORWARD_PROTO, SMTPD_STATE_XFORWARD_PROTO, + XFORWARD_HELO, SMTPD_STATE_XFORWARD_HELO, + 0, 0, + }; + int flag; + + /* + * Sanity checks. + */ + if (IN_MAIL_TRANSACTION(state)) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "503 Error: MAIL transaction in progress"); + return (-1); + } + if (argc < 2) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Syntax: %s attribute=value...", + XFORWARD_CMD); + return (-1); + } + if (!xforward_allowed) { + state->error_mask |= MAIL_ERROR_POLICY; + smtpd_chat_reply(state, "554 Error: insufficient authorization"); + return (-1); + } + + /* + * Initialize. + */ + if (state->xforward.flags == 0) + smtpd_xforward_preset(state); + + /* + * Iterate over all attribute=value elements. + */ + for (argp = argv + 1; argp < argv + argc; argp++) { + attr_name = argp->strval; + + /* + * For safety's sake mask non-printable characters. We'll do more + * specific censoring later. + */ + if ((attr_value = split_at(attr_name, '=')) == 0 || *attr_value == 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Error: attribute=value expected"); + return (-1); + } + if (strlen(attr_value) > 255) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Error: attribute value too long"); + return (-1); + } + printable(attr_value, '?'); + + flag = name_code(xforward_flags, NAME_CODE_FLAG_NONE, attr_name); + switch (flag) { + + /* + * NAME=up-stream host name, not necessarily in the DNS. Censor + * special characters that could mess up message headers. + */ + case SMTPD_STATE_XFORWARD_NAME: + if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) { + attr_value = CLIENT_NAME_UNKNOWN; + } else { + neuter(attr_value, NEUTER_CHARACTERS, '?'); + } + UPDATE_STR(state->xforward.name, attr_value); + break; + + /* + * ADDR=up-stream host network address, not necessarily on the + * Internet. Censor special characters that could mess up message + * headers. + */ + case SMTPD_STATE_XFORWARD_ADDR: + if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) { + attr_value = CLIENT_ADDR_UNKNOWN; + } else { + neuter(attr_value, NEUTER_CHARACTERS, '?'); + } + UPDATE_STR(state->xforward.addr, attr_value); + break; + + /* + * HELO=hostname that the up-stream MTA introduced itself with + * (not necessarily SMTP HELO). Censor special characters that + * could mess up message headers. + */ + case SMTPD_STATE_XFORWARD_HELO: + if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) { + attr_value = CLIENT_HELO_UNKNOWN; + } else { + neuter(attr_value, NEUTER_CHARACTERS, '?'); + } + UPDATE_STR(state->xforward.helo_name, attr_value); + break; + + /* + * PROTO=up-stream protocol, not necessarily SMTP or ESMTP. + * Censor special characters that could mess up message headers. + */ + case SMTPD_STATE_XFORWARD_PROTO: + if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) { + attr_value = CLIENT_PROTO_UNKNOWN; + } else { + if (strlen(attr_value) > 64) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad %s syntax: %s", + XFORWARD_PROTO, attr_value); + return (-1); + } + neuter(attr_value, NEUTER_CHARACTERS, '?'); + } + UPDATE_STR(state->xforward.protocol, attr_value); + break; + + /* + * Unknown attribute name. Complain. + */ + default: + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "501 Bad %s attribute name: %s", + XFORWARD_CMD, attr_name); + return (-1); + } + updated |= flag; + } + state->xforward.flags |= updated; + + /* + * Update the combined name and address when either has changed. Use only + * the name when no address is available. + */ + if (updated & (SMTPD_STATE_XFORWARD_NAME | SMTPD_STATE_XFORWARD_ADDR)) { + if (state->xforward.namaddr) + myfree(state->xforward.namaddr); + state->xforward.namaddr = + IS_AVAIL_CLIENT_ADDR(state->xforward.addr) ? + concatenate(state->xforward.name, "[", + state->xforward.addr, "]", + (char *) 0) : mystrdup(state->xforward.name); + } + smtpd_chat_reply(state, "250 Ok"); + return (0); +} + +/* chat_reset - notify postmaster and reset conversation log */ + +static void chat_reset(SMTPD_STATE *state, int threshold) +{ + + /* + * Notify the postmaster if there were errors. This usually indicates a + * client configuration problem, or that someone is trying nasty things. + * Either is significant enough to bother the postmaster. XXX Can't + * report problems when running in stand-alone mode: postmaster notices + * require availability of the cleanup service. + */ + if (state->history != 0 && state->history->argc > threshold) { + if (SMTPD_STAND_ALONE(state) == 0 + && (state->error_mask & state->notify_mask)) + smtpd_chat_notify(state); + state->error_mask = 0; + smtpd_chat_reset(state); + } +} + + /* + * The table of all SMTP commands that we know. Set the junk limit flag on + * any command that can be repeated an arbitrary number of times without + * triggering a tarpit delay of some sort. + */ +typedef struct SMTPD_CMD { + char *name; + int (*action) (SMTPD_STATE *, int, SMTPD_TOKEN *); + int flags; +} SMTPD_CMD; + +#define SMTPD_CMD_FLAG_LIMIT (1<<0) /* limit usage */ +#define SMTPD_CMD_FLAG_FORBID (1<<1) /* RFC 2822 mail header */ + +static SMTPD_CMD smtpd_cmd_table[] = { + "HELO", helo_cmd, SMTPD_CMD_FLAG_LIMIT, + "EHLO", ehlo_cmd, SMTPD_CMD_FLAG_LIMIT, + +#ifdef USE_SASL_AUTH + "AUTH", smtpd_sasl_auth_cmd, 0, +#endif + + "MAIL", mail_cmd, 0, + "RCPT", rcpt_cmd, 0, + "DATA", data_cmd, 0, + "RSET", rset_cmd, SMTPD_CMD_FLAG_LIMIT, + "NOOP", noop_cmd, SMTPD_CMD_FLAG_LIMIT, + "VRFY", vrfy_cmd, SMTPD_CMD_FLAG_LIMIT, + "ETRN", etrn_cmd, SMTPD_CMD_FLAG_LIMIT, + "QUIT", quit_cmd, 0, + "XCLIENT", xclient_cmd, SMTPD_CMD_FLAG_LIMIT, + "XFORWARD", xforward_cmd, SMTPD_CMD_FLAG_LIMIT, + "Received:", 0, SMTPD_CMD_FLAG_FORBID, + "Reply-To:", 0, SMTPD_CMD_FLAG_FORBID, + "Message-ID:", 0, SMTPD_CMD_FLAG_FORBID, + "Subject:", 0, SMTPD_CMD_FLAG_FORBID, + "From:", 0, SMTPD_CMD_FLAG_FORBID, + "CONNECT", 0, SMTPD_CMD_FLAG_FORBID, + "User-Agent:", 0, SMTPD_CMD_FLAG_FORBID, + 0, +}; + +static STRING_LIST *smtpd_noop_cmds; + +/* smtpd_proto - talk the SMTP protocol */ + +static void smtpd_proto(SMTPD_STATE *state, const char *service) +{ + int argc; + SMTPD_TOKEN *argv; + SMTPD_CMD *cmdp; + int count; + int crate; + + /* + * Print a greeting banner and run the state machine. Read SMTP commands + * one line at a time. According to the standard, a sender or recipient + * address could contain an escaped newline. I think this is perverse, + * and anyone depending on this is really asking for trouble. + * + * In case of mail protocol trouble, the program jumps back to this place, + * so that it can perform the necessary cleanup before talking to the + * next client. The setjmp/longjmp primitives are like a sharp tool: use + * with care. I would certainly recommend against the use of + * setjmp/longjmp in programs that change privilege levels. + * + * In case of file system trouble the program terminates after logging the + * error and after informing the client. In all other cases (out of + * memory, panic) the error is logged, and the msg_cleanup() exit handler + * cleans up, but no attempt is made to inform the client of the nature + * of the problem. + */ + smtp_timeout_setup(state->client, var_smtpd_tmout); + + switch (vstream_setjmp(state->client)) { + + default: + msg_panic("smtpd_proto: unknown error reading from %s[%s]", + state->name, state->addr); + break; + + case SMTP_ERR_TIME: + state->reason = "timeout"; + smtpd_chat_reply(state, "421 %s Error: timeout exceeded", + var_myhostname); + break; + + case SMTP_ERR_EOF: + state->reason = "lost connection"; + break; + + case 0: + + /* + * XXX The client connection count/rate control must be consistent in + * its use of client address information in connect and disconnect + * events. For now we exclude xclient authorized hosts from + * connection count/rate control. + */ +#ifdef SNAPSHOT + if (SMTPD_STAND_ALONE(state) == 0 + && !xclient_allowed + && anvil_clnt + && !namadr_list_match(hogger_list, state->name, state->addr) + && anvil_clnt_connect(anvil_clnt, service, state->addr, + &count, &crate) == ANVIL_STAT_OK) { + if (var_smtpd_cconn_limit > 0 && count > var_smtpd_cconn_limit) { + smtpd_chat_reply(state, "421 %s Error: too many connections from %s", + var_myhostname, state->addr); + msg_warn("Too many connections: %d from %s for service %s", + count, state->namaddr, service); + break; + } + if (var_smtpd_crate_limit > 0 && crate > var_smtpd_crate_limit) { + smtpd_chat_reply(state, "421 %s Error: too many connections from %s", + var_myhostname, state->addr); + msg_warn("Too frequent connections: %d from %s for service %s", + crate, state->namaddr, service); + break; + } + } +#endif + /* XXX We use the real client for connect access control. */ + if (SMTPD_STAND_ALONE(state) == 0 + && var_smtpd_delay_reject == 0 + && (state->access_denied = smtpd_check_client(state)) != 0) { + smtpd_chat_reply(state, "%s", state->access_denied); + } else { + smtpd_chat_reply(state, "220 %s", var_smtpd_banner); + } + + for (;;) { + if (state->error_count >= var_smtpd_hard_erlim) { + state->reason = "too many errors"; + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "421 %s Error: too many errors", + var_myhostname); + break; + } + watchdog_pat(); + smtpd_chat_query(state); + if ((argc = smtpd_token(vstring_str(state->buffer), &argv)) == 0) { + state->error_mask |= MAIL_ERROR_PROTOCOL; + smtpd_chat_reply(state, "500 Error: bad syntax"); + state->error_count++; + continue; + } + if (*var_smtpd_noop_cmds + && string_list_match(smtpd_noop_cmds, argv[0].strval)) { + smtpd_chat_reply(state, "250 Ok"); + if (state->junk_cmds++ > var_smtpd_junk_cmd_limit) + state->error_count++; + continue; + } + for (cmdp = smtpd_cmd_table; cmdp->name != 0; cmdp++) + if (strcasecmp(argv[0].strval, cmdp->name) == 0) + break; + if (cmdp->name == 0) { + smtpd_chat_reply(state, "502 Error: command not implemented"); + state->error_mask |= MAIL_ERROR_PROTOCOL; + state->error_count++; + continue; + } + if (cmdp->flags & SMTPD_CMD_FLAG_FORBID) { + msg_warn("%s sent non-SMTP command: %.100s", + state->namaddr, vstring_str(state->buffer)); + smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye."); + break; + } + /* XXX We use the real client for connect access control. */ + if (state->access_denied && cmdp->action != quit_cmd) { + smtpd_chat_reply(state, "503 Error: access denied for %s", + state->namaddr); /* RFC 2821 Sec 3.1 */ + state->error_count++; + continue; + } + state->where = cmdp->name; + if (cmdp->action(state, argc, argv) != 0) + state->error_count++; + if ((cmdp->flags & SMTPD_CMD_FLAG_LIMIT) + && state->junk_cmds++ > var_smtpd_junk_cmd_limit) + state->error_count++; + if (cmdp->action == quit_cmd) + break; + } + break; + } + + /* + * XXX The client connection count/rate control must be consistent in its + * use of client address information in connect and disconnect events. + * For now we exclude xclient authorized hosts from connection count/rate + * control. + */ +#ifdef SNAPSHOT + if (SMTPD_STAND_ALONE(state) == 0 + && !xclient_allowed + && anvil_clnt + && !namadr_list_match(hogger_list, state->name, state->addr)) + anvil_clnt_disconnect(anvil_clnt, service, state->addr); +#endif + + /* + * Log abnormal session termination, in case postmaster notification has + * been turned off. In the log, indicate the last recognized state before + * things went wrong. Don't complain about clients that go away without + * sending QUIT. + */ + if (state->reason && state->where + && (strcmp(state->where, SMTPD_AFTER_DOT) + || strcmp(state->reason, "lost connection"))) + msg_info("%s after %s from %s[%s]", + state->reason, state->where, state->name, state->addr); + + /* + * Cleanup whatever information the client gave us during the SMTP + * dialog. + */ + helo_reset(state); +#ifdef USE_SASL_AUTH + if (var_smtpd_sasl_enable) + smtpd_sasl_auth_reset(state); +#endif + chat_reset(state, 0); + mail_reset(state); + rcpt_reset(state); +} + +/* smtpd_service - service one client */ + +static void smtpd_service(VSTREAM *stream, char *service, char **argv) +{ + SMTPD_STATE state; + + /* + * Sanity check. This service takes no command-line arguments. + */ + if (argv[0]) + msg_fatal("unexpected command-line argument: %s", argv[0]); + + /* + * This routine runs when a client has connected to our network port, or + * when the smtp server is run in stand-alone mode (input from pipe). + * + * Look up and sanitize the peer name, then initialize some connection- + * specific state. When the name service is hosed, hostname lookup will + * take a while. This is why I always run a local name server on critical + * machines. + */ + smtpd_state_init(&state, stream); + msg_info("connect from %s[%s]", state.name, state.addr); + + /* + * XCLIENT must not override its own access control. + */ + xclient_allowed = + namadr_list_match(xclient_hosts, state.name, state.addr); + + /* + * Overriding XFORWARD access control makes no sense, either. + */ + xforward_allowed = + namadr_list_match(xforward_hosts, state.name, state.addr); + + /* + * See if we need to turn on verbose logging for this client. + */ + debug_peer_check(state.name, state.addr); + + /* + * Provide the SMTP service. + */ + smtpd_proto(&state, service); + + /* + * After the client has gone away, clean up whatever we have set up at + * connection time. + */ + msg_info("disconnect from %s[%s]", state.name, state.addr); + smtpd_state_reset(&state); + debug_peer_restore(); +} + +/* pre_accept - see if tables have changed */ + +static void pre_accept(char *unused_name, char **unused_argv) +{ + const char *table; + + if ((table = dict_changed_name()) != 0) { + msg_info("table %s has changed -- restarting", table); + exit(0); + } +} + +/* pre_jail_init - pre-jail initialization */ + +static void pre_jail_init(char *unused_name, char **unused_argv) +{ + + /* + * Initialize blacklist/etc. patterns before entering the chroot jail, in + * case they specify a filename pattern. + */ + smtpd_noop_cmds = string_list_init(MATCH_FLAG_NONE, var_smtpd_noop_cmds); + verp_clients = namadr_list_init(MATCH_FLAG_NONE, var_verp_clients); + xclient_hosts = namadr_list_init(MATCH_FLAG_NONE, var_xclient_hosts); + xforward_hosts = namadr_list_init(MATCH_FLAG_NONE, var_xforward_hosts); +#ifdef SNAPSHOT + hogger_list = namadr_list_init(MATCH_FLAG_NONE, var_smtpd_hoggers); +#endif + if (getuid() == 0 || getuid() == var_owner_uid) + smtpd_check_init(); + debug_peer_init(); + + if (var_smtpd_sasl_enable) +#ifdef USE_SASL_AUTH + smtpd_sasl_initialize(); + + if (*var_smtpd_sasl_exceptions_networks) + sasl_exceptions_networks = + namadr_list_init(MATCH_FLAG_NONE, + var_smtpd_sasl_exceptions_networks); +#else + msg_warn("%s is true, but SASL support is not compiled in", + VAR_SMTPD_SASL_ENABLE); +#endif + + /* + * flush client. + */ + flush_init(); +} + +/* post_jail_init - post-jail initialization */ + +static void post_jail_init(char *unused_name, char **unused_argv) +{ + + /* + * Initialize the receive transparency options: do we want unknown + * recipient checks, address mapping, header_body_checks?. + */ + smtpd_input_transp_mask = + input_transp_mask(VAR_INPUT_TRANSP, var_input_transp); + + /* + * Sanity checks. The queue_minfree value should be at least as large as + * (process_limit * message_size_limit) but that is unpractical, so we + * arbitrarily pick a number and require twice the message size limit. + */ + if (var_queue_minfree > 0 + && var_message_limit > 0 + && var_queue_minfree / 1.5 < var_message_limit) + msg_warn("%s(%lu) should be at least 1.5*%s(%lu)", + VAR_QUEUE_MINFREE, (unsigned long) var_queue_minfree, + VAR_MESSAGE_LIMIT, (unsigned long) var_message_limit); + + /* + * Connection rate management. + */ +#ifdef SNAPSHOT + if (var_smtpd_crate_limit || var_smtpd_cconn_limit) + anvil_clnt = anvil_clnt_create(); +#endif +} + +/* main - the main program */ + +int main(int argc, char **argv) +{ + static CONFIG_INT_TABLE int_table[] = { + VAR_SMTPD_RCPT_LIMIT, DEF_SMTPD_RCPT_LIMIT, &var_smtpd_rcpt_limit, 1, 0, + VAR_SMTPD_SOFT_ERLIM, DEF_SMTPD_SOFT_ERLIM, &var_smtpd_soft_erlim, 1, 0, + VAR_SMTPD_HARD_ERLIM, DEF_SMTPD_HARD_ERLIM, &var_smtpd_hard_erlim, 1, 0, + VAR_QUEUE_MINFREE, DEF_QUEUE_MINFREE, &var_queue_minfree, 0, 0, + VAR_UNK_CLIENT_CODE, DEF_UNK_CLIENT_CODE, &var_unk_client_code, 0, 0, + VAR_BAD_NAME_CODE, DEF_BAD_NAME_CODE, &var_bad_name_code, 0, 0, + VAR_UNK_NAME_CODE, DEF_UNK_NAME_CODE, &var_unk_name_code, 0, 0, + VAR_UNK_ADDR_CODE, DEF_UNK_ADDR_CODE, &var_unk_addr_code, 0, 0, + VAR_RELAY_CODE, DEF_RELAY_CODE, &var_relay_code, 0, 0, + VAR_MAPS_RBL_CODE, DEF_MAPS_RBL_CODE, &var_maps_rbl_code, 0, 0, + VAR_ACCESS_MAP_CODE, DEF_ACCESS_MAP_CODE, &var_access_map_code, 0, 0, + VAR_REJECT_CODE, DEF_REJECT_CODE, &var_reject_code, 0, 0, + VAR_DEFER_CODE, DEF_DEFER_CODE, &var_defer_code, 0, 0, + VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code, 0, 0, + VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0, + VAR_SMTPD_RCPT_OVERLIM, DEF_SMTPD_RCPT_OVERLIM, &var_smtpd_rcpt_overlim, 1, 0, + VAR_SMTPD_HIST_THRSH, DEF_SMTPD_HIST_THRSH, &var_smtpd_hist_thrsh, 1, 0, + VAR_UNV_FROM_CODE, DEF_UNV_FROM_CODE, &var_unv_from_code, 0, 0, + VAR_UNV_RCPT_CODE, DEF_UNV_RCPT_CODE, &var_unv_rcpt_code, 0, 0, + VAR_MUL_RCPT_CODE, DEF_MUL_RCPT_CODE, &var_mul_rcpt_code, 0, 0, + VAR_LOCAL_RCPT_CODE, DEF_LOCAL_RCPT_CODE, &var_local_rcpt_code, 0, 0, + VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code, 0, 0, + VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0, + VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0, + VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count, 1, 0, +#ifdef SNAPSHOT + VAR_SMTPD_CRATE_LIMIT, DEF_SMTPD_CRATE_LIMIT, &var_smtpd_crate_limit, 0, 0, + VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0, +#endif + 0, + }; + static CONFIG_TIME_TABLE time_table[] = { + VAR_SMTPD_TMOUT, DEF_SMTPD_TMOUT, &var_smtpd_tmout, 1, 0, + VAR_SMTPD_ERR_SLEEP, DEF_SMTPD_ERR_SLEEP, &var_smtpd_err_sleep, 0, 0, + VAR_SMTPD_PROXY_TMOUT, DEF_SMTPD_PROXY_TMOUT, &var_smtpd_proxy_tmout, 1, 0, + VAR_VERIFY_POLL_DELAY, DEF_VERIFY_POLL_DELAY, &var_verify_poll_delay, 1, 0, + VAR_SMTPD_POLICY_TMOUT, DEF_SMTPD_POLICY_TMOUT, &var_smtpd_policy_tmout, 1, 0, + VAR_SMTPD_POLICY_IDLE, DEF_SMTPD_POLICY_IDLE, &var_smtpd_policy_idle, 1, 0, + VAR_SMTPD_POLICY_TTL, DEF_SMTPD_POLICY_TTL, &var_smtpd_policy_ttl, 1, 0, + 0, + }; + static CONFIG_BOOL_TABLE bool_table[] = { + VAR_HELO_REQUIRED, DEF_HELO_REQUIRED, &var_helo_required, + VAR_SMTPD_DELAY_REJECT, DEF_SMTPD_DELAY_REJECT, &var_smtpd_delay_reject, + VAR_STRICT_RFC821_ENV, DEF_STRICT_RFC821_ENV, &var_strict_rfc821_env, + VAR_DISABLE_VRFY_CMD, DEF_DISABLE_VRFY_CMD, &var_disable_vrfy_cmd, + VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route, + VAR_SMTPD_SASL_ENABLE, DEF_SMTPD_SASL_ENABLE, &var_smtpd_sasl_enable, + VAR_BROKEN_AUTH_CLNTS, DEF_BROKEN_AUTH_CLNTS, &var_broken_auth_clients, + VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table, + VAR_SMTPD_REJ_UNL_FROM, DEF_SMTPD_REJ_UNL_FROM, &var_smtpd_rej_unl_from, + VAR_SMTPD_REJ_UNL_RCPT, DEF_SMTPD_REJ_UNL_RCPT, &var_smtpd_rej_unl_rcpt, + 0, + }; + static CONFIG_STR_TABLE str_table[] = { + VAR_SMTPD_BANNER, DEF_SMTPD_BANNER, &var_smtpd_banner, 1, 0, + VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0, + VAR_CLIENT_CHECKS, DEF_CLIENT_CHECKS, &var_client_checks, 0, 0, + VAR_HELO_CHECKS, DEF_HELO_CHECKS, &var_helo_checks, 0, 0, + VAR_MAIL_CHECKS, DEF_MAIL_CHECKS, &var_mail_checks, 0, 0, + VAR_RCPT_CHECKS, DEF_RCPT_CHECKS, &var_rcpt_checks, 0, 0, + VAR_ETRN_CHECKS, DEF_ETRN_CHECKS, &var_etrn_checks, 0, 0, + VAR_DATA_CHECKS, DEF_DATA_CHECKS, &var_data_checks, 0, 0, + VAR_MAPS_RBL_DOMAINS, DEF_MAPS_RBL_DOMAINS, &var_maps_rbl_domains, 0, 0, + VAR_RBL_REPLY_MAPS, DEF_RBL_REPLY_MAPS, &var_rbl_reply_maps, 0, 0, + VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0, + VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes, 0, 0, + VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 0, 0, + VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, 0, 0, + VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, 0, 0, + VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, + VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps, 0, 0, + VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, 0, 0, + VAR_SMTPD_SASL_OPTS, DEF_SMTPD_SASL_OPTS, &var_smtpd_sasl_opts, 0, 0, + VAR_SMTPD_SASL_APPNAME, DEF_SMTPD_SASL_APPNAME, &var_smtpd_sasl_appname, 1, 0, + VAR_SMTPD_SASL_REALM, DEF_SMTPD_SASL_REALM, &var_smtpd_sasl_realm, 0, 0, + VAR_SMTPD_SASL_EXCEPTIONS_NETWORKS, DEF_SMTPD_SASL_EXCEPTIONS_NETWORKS, &var_smtpd_sasl_exceptions_networks, 0, 0, + VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, + VAR_PERM_MX_NETWORKS, DEF_PERM_MX_NETWORKS, &var_perm_mx_networks, 0, 0, + VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps, 0, 0, + VAR_SMTPD_NOOP_CMDS, DEF_SMTPD_NOOP_CMDS, &var_smtpd_noop_cmds, 0, 0, + VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 0, 0, + VAR_RELAY_RCPT_MAPS, DEF_RELAY_RCPT_MAPS, &var_relay_rcpt_maps, 0, 0, + VAR_VERIFY_SENDER, DEF_VERIFY_SENDER, &var_verify_sender, 0, 0, + VAR_VERP_CLIENTS, DEF_VERP_CLIENTS, &var_verp_clients, 0, 0, + VAR_SMTPD_PROXY_FILT, DEF_SMTPD_PROXY_FILT, &var_smtpd_proxy_filt, 0, 0, + VAR_SMTPD_PROXY_EHLO, DEF_SMTPD_PROXY_EHLO, &var_smtpd_proxy_ehlo, 0, 0, + VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0, + VAR_XCLIENT_HOSTS, DEF_XCLIENT_HOSTS, &var_xclient_hosts, 0, 0, + VAR_XFORWARD_HOSTS, DEF_XFORWARD_HOSTS, &var_xforward_hosts, 0, 0, +#ifdef SNAPSHOT + VAR_SMTPD_HOGGERS, DEF_SMTPD_HOGGERS, &var_smtpd_hoggers, 0, 0, +#endif + 0, + }; + static CONFIG_RAW_TABLE raw_table[] = { + VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, 1, 0, + VAR_DEF_RBL_REPLY, DEF_DEF_RBL_REPLY, &var_def_rbl_reply, 1, 0, + 0, + }; + + /* + * Pass control to the single-threaded service skeleton. + */ + single_server_main(argc, argv, smtpd_service, + MAIL_SERVER_INT_TABLE, int_table, + MAIL_SERVER_STR_TABLE, str_table, + MAIL_SERVER_RAW_TABLE, raw_table, + MAIL_SERVER_BOOL_TABLE, bool_table, + MAIL_SERVER_TIME_TABLE, time_table, + MAIL_SERVER_PRE_INIT, pre_jail_init, + MAIL_SERVER_PRE_ACCEPT, pre_accept, + MAIL_SERVER_POST_INIT, post_jail_init, + 0); +} diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1 index cefdb9504..b2a24623d 100644 --- a/postfix/man/man1/postconf.1 +++ b/postfix/man/man1/postconf.1 @@ -99,6 +99,10 @@ described in \fBregexp_table\fR(5). A table that always returns its name as lookup result. For example, \fBstatic:foobar\fR always returns the string \fBfoobar\fR as lookup result. +.IP "\fBtcp\fR (read-only)" +Perform lookups using a simple request-reply protocol that is +described in tcp_table(5). +This feature is not included with Postfix 2.1. .IP "\fBunix\fR (read-only)" A limited way to query the UNIX authentication database. The following tables are implemented: diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index bf8c83a03..7379efd13 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -1116,8 +1116,8 @@ The location of Postfix HTML files that describe how to build, configure or operate a specific Postfix subsystem or feature. .SH ignore_mx_lookup_error (default: no) Ignore DNS MX lookups that produce no response. By default, -Postfix defers delivery and tries again after some delay. This -behavior is required by the SMTP standard. +the Postfix SMTP client defers delivery and tries again after some +delay. This behavior is required by the SMTP standard. .PP Specify "\fBignore_mx_lookup_error = yes\fR" to force a DNS A record lookup instead. This violates the SMTP standard and can result in @@ -2882,10 +2882,10 @@ Later Postfix versions always skip SMTP servers that greet with a Skip SMTP servers that greet with a 5XX status code (go away, do not try again later). .PP -By default, Postfix 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. +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. .SH smtp_skip_quit_response (default: yes) Do not wait for the response to the SMTP QUIT command. .SH smtp_xforward_timeout (default: 300s) @@ -3501,7 +3501,8 @@ no sender-specified routing (user@elsewhere@domain). code for rejected requests (default: 554). .IP "\fBreject_unknown_recipient_domain\fR" Reject the request when the RCPT TO address has no DNS A or MX -record. +record and Postfix is not final destination for the recipient +address. .br The unknown_address_reject_code parameter specifies the response code for rejected requests (default: 450). The response @@ -3793,12 +3794,13 @@ Enforces the reject_sender_login_mismatch restriction for unauthenticated clients only. This feature is available in Postfix version 2.1 and later. .IP "\fBreject_unknown_sender_domain\fR" -Reject the request when the MAIL FROM address has no DNS A -or MX record. +Reject the request when the MAIL FROM address has no DNS A or +MX record and Postfix is not final destination for the sender +address. .br -The unknown_address_reject_code parameter -specifies the response code for rejected requests (default: 450). -The response is always 450 in case of a temporary DNS error. +The unknown_address_reject_code parameter specifies +the response code for rejected requests (default: 450). The response +is always 450 in case of a temporary DNS error. .IP "\fBreject_unlisted_sender\fR" Reject the request when the MAIL FROM address is not listed in the list of valid recipients for its domain class. See the diff --git a/postfix/man/man5/transport.5 b/postfix/man/man5/transport.5 index 6c5d8da0a..094a75bed 100644 --- a/postfix/man/man5/transport.5 +++ b/postfix/man/man5/transport.5 @@ -70,11 +70,9 @@ starts with whitespace continues a logical line. The \fIpattern\fR specifies an email address, a domain name, or a domain name hierarchy, as described in section "TABLE LOOKUP". -The \fIresult\fR is of the form \fItransport\fB:\fInexthop\fR. -The \fItransport\fR field specifies a mail delivery transport -such as \fBsmtp\fR or \fBlocal\fR. The \fInexthop\fR field -specifies where and how to deliver mail. More details are given -in section "RESULT FORMAT". +The \fIresult\fR is of the form \fItransport:nexthop\fR and +specifies how or where to deliver mail. This is described in +section "RESULT FORMAT". .SH "TABLE LOOKUP" .na .nf @@ -111,14 +109,19 @@ mailer-daemon@hostname). .nf .ad .fi +The lookup result is of the form \fItransport\fB:\fInexthop\fR. +The \fItransport\fR field specifies a mail delivery transport +such as \fBsmtp\fR or \fBlocal\fR. The \fInexthop\fR field +specifies where and how to deliver mail. + The transport field specifies the name of a mail delivery transport (the first name of a mail delivery service entry in the Postfix \fBmaster.cf\fR file). The interpretation of the nexthop field is transport -dependent. In the case of SMTP, specify \fIhost\fR:\fIservice\fR for a -non-default server port, and use [\fIhost\fR] or [\fIhost\fR]:\fIport\fR -in order to disable MX (mail exchanger) DNS lookups. The [] form +dependent. In the case of SMTP, specify a service on a non-default +port as \fIhost\fR:\fIservice\fR, and disable MX (mail exchanger) +DNS lookups with [\fIhost\fR] or [\fIhost\fR]:\fIport\fR. The [] form is required when you specify an IP address instead of a hostname. A null \fItransport\fR and null \fInexthop\fR result means "do @@ -148,52 +151,53 @@ destinations. .ti +5 \fB* smtp:outbound-relay.my.domain\fR -In order to send mail for \fBfoo.org\fR and its subdomains -via the \fBuucp\fR transport to the UUCP host named \fBfoo\fR: +In order to send mail for \fBexample.com\fR and its subdomains +via the \fBuucp\fR transport to the UUCP host named \fBexample\fR: .ti +5 -\fBfoo.org uucp:foo\fR +\fBexample.com uucp:example\fR .ti +5 -\fB\&.foo.org uucp:foo\fR +\fB\&.example.com uucp:example\fR When no nexthop host name is specified, the destination domain name is used instead. For example, the following directs mail for -\fIuser\fR@\fBfoo.org\fR via the \fBslow\fR transport to a mail -exchanger for \fBfoo.org\fR. The \fBslow\fR transport could be -something that runs at most one delivery process at a time: +\fIuser\fR@\fBexample.com\fR via the \fBslow\fR transport to a mail +exchanger for \fBexample.com\fR. The \fBslow\fR transport could be +configured to run at most one delivery process at a time: .ti +5 -\fBfoo.org slow:\fR +\fBexample.com slow:\fR When no transport is specified, Postfix uses the transport that -matches the address domain class (see TRANSPORT FIELD discussion -above). The following sends all mail for \fBfoo.org\fR and its -subdomains to host \fBgateway.foo.org\fR: +matches the address domain class (see DESCRIPTION +above). The following sends all mail for \fBexample.com\fR and its +subdomains to host \fBgateway.example.com\fR: .ti +5 -\fBfoo.org :[gateway.foo.org]\fR +\fBexample.com :[gateway.example.com]\fR .ti +5 -\fB\&.foo.org :[gateway.foo.org]\fR +\fB\&.example.com :[gateway.example.com]\fR -In the above example, the [] are used to suppress MX lookups. -The result would likely point to your local machine. +In the above example, the [] suppress MX lookups. +This prevents mail routing loops when your machine is primary MX +host for \fBexample.com\fR. In the case of delivery via SMTP, one may specify \fIhostname\fR:\fIservice\fR instead of just a host: .ti +5 -\fBfoo.org smtp:bar.org:2025\fR +\fBexample.com smtp:bar.example:2025\fR -This directs mail for \fIuser\fR@\fBfoo.org\fR to host \fBbar.org\fR +This directs mail for \fIuser\fR@\fBexample.com\fR to host \fBbar.example\fR port \fB2025\fR. Instead of a numerical port a symbolic name may be -used. Specify [] around the hostname in order to disable MX lookups. +used. Specify [] around the hostname if MX lookups must be disabled. The error mailer can be used to bounce mail: .ti +5 -\fB\&.foo.org error:mail for *.foo.org is not deliverable\fR +\fB\&.example.com error:mail for *.example.com is not deliverable\fR -This causes all mail for \fIuser\fR@\fIanything\fB.foo.org\fR +This causes all mail for \fIuser\fR@\fIanything\fB.example.com\fR to be bounced. .SH "REGULAR EXPRESSION TABLES" .na diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index ed340b369..15fe55913 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -450,6 +450,7 @@ exec sed ' s/[]*smtp-[]*\n* *[]*sink[]*(1)/&<\/a>/g s/[]*qmqp-[]*\n* *[]*source[]*(1)/&<\/a>/g s/[]*qmqp-[]*\n* *[]*sink[]*(1)/&<\/a>/g + s/[]*qshape[]*(1)/&<\/a>/g s/[]*access[]*(5)/&<\/a>/g s/[]*aliases[]*(5)/&<\/a>/g s/[]*canonical[]*(5)/&<\/a>/g @@ -594,6 +595,7 @@ exec sed ' # Do nice links for smtp:host:port etc. + s/[[:<:]]\(error\):/\1<\/a>:/g s/[[:<:]]\(smtp\):/\1<\/a>:/g s/[[:<:]]\(lmtp\):/\1<\/a>:/g diff --git a/postfix/proto/PACKAGE_README.html b/postfix/proto/PACKAGE_README.html index ae84ba9da..ef14f6428 100644 --- a/postfix/proto/PACKAGE_README.html +++ b/postfix/proto/PACKAGE_README.html @@ -118,17 +118,18 @@ 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 post-install script in the Postfix configuration -directory to set ownership and permission of Postfix files and -directories. Specify any non-default settings for mail_owner or -setgid_group on the post-install command line:

        +
      • 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:

        -# sh post-install upgrade-package setgid_group=xxx mail_owner=yyy
        +# postfix set-permissions upgrade-configuration \
        +       setgid_group=xxx mail_owner=yyy
         
        -

        This will also update the main.cf and master.cf files if -necessary.

        +

        With Postfix versions before 2.1 you achieve the same result +by invoking the post-install script directly.

      diff --git a/postfix/proto/QSHAPE_README.html b/postfix/proto/QSHAPE_README.html index 7cfd1e433..2418eba7b 100644 --- a/postfix/proto/QSHAPE_README.html +++ b/postfix/proto/QSHAPE_README.html @@ -19,16 +19,18 @@

      Purpose of this document

      -

      This document describes the "qshape" program which helps the +

      This document describes the qshape(1) program which helps the administrator understand the Postfix queue message distribution -sorted by time and by sender or recipient domain. qshape is bundled -with the Postfix 2.1 source under the "auxiliary" directory. In -order to understand the output of qshape, it useful to understand -the various Postfix queues. To this end the role of each Postfix -queue directory is described briefly in the "Background info: -Postfix queue directories" section near the end of this document. +sorted by time and by sender or recipient domain. qshape(1) is +bundled with the Postfix 2.1 source under the "auxiliary" directory.

      +

      In order to understand the output of qshape(1), it useful to +understand the various Postfix queues. To this end the role of each +Postfix queue directory is described briefly in the "Background +info: Postfix queue directories" section near the end of this +document.

      +

      This document covers the following topics:

        @@ -71,8 +73,8 @@ queue

        When mail is draining slowly or the queue is unexpectedly large, -run "qshape" as the super-user (root) to help zero in on the problem. -The "qshape" program displays a tabular view of the Postfix queue +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.

          @@ -217,7 +219,7 @@ $ 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" +please don't forget to include the top 10 or 20 lines of qshape(1) output.

          Example 1: Healthy queue

          @@ -290,7 +292,7 @@ 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.msg.com undeliverables 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.

          @@ -322,7 +324,7 @@ 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" it was quickly determined +

          Using an older version of qshape(1) it was quickly determined that all the messages were for just a few destinations:

          @@ -780,7 +782,7 @@ queue flushes.

          Credits

          -

          The "qshape" program was developed by Victor Duchovni of Morgan +

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

          diff --git a/postfix/proto/RESTRICTION_CLASS_README.html b/postfix/proto/RESTRICTION_CLASS_README.html index bb3ed862b..7d9ad751f 100644 --- a/postfix/proto/RESTRICTION_CLASS_README.html +++ b/postfix/proto/RESTRICTION_CLASS_README.html @@ -105,7 +105,8 @@ to IP spoofing.

          ...the usual stuff... /etc/postfix/access: - all permit_mynetworks,reject + all@my.domain permit_mynetworks,reject + all@my.hostname permit_mynetworks,reject
          diff --git a/postfix/proto/SMTPD_ACCESS_README.html b/postfix/proto/SMTPD_ACCESS_README.html index 6aeb575a5..70dbcf8b2 100644 --- a/postfix/proto/SMTPD_ACCESS_README.html +++ b/postfix/proto/SMTPD_ACCESS_README.html @@ -122,13 +122,13 @@ the incoming queue.

          in the SMTPD_PROXY_README document. This happens while Postfix receives mail, before it is stored in the incoming queue.

          -
        • Require that the client sends the HELO or EHLO command +

        • 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").

          -
        • Disallow illegal syntax in MAIL FROM or RCPT TO commands. +

        • 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 = @@ -136,21 +136,21 @@ no").

            -
          • Disallow RFC 822 address syntax (example: "MAIL FROM: the +

          • Disallowing RFC 822 address syntax (example: "MAIL FROM: the dude <dude@example.com>").

            -
          • Disallow addresses that are not enclosed with <> +

          • Disallowing addresses that are not enclosed with <> (example: "MAIL FROM: dude@example.com").

          -
        • Reject mail from a non-existent sender address. This form +

        • 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").

          -
        • Reject mail for a non-existent recipient address. This +

        • 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").

          diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 8fe41b20e..d07d2a83a 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -1364,11 +1364,9 @@ is bounced, in order to stop a mailer loop. %PARAM ignore_mx_lookup_error no -

          -Ignore DNS MX lookups that produce no response. By default, -Postfix defers delivery and tries again after some delay. This -behavior is required by the SMTP standard. -

          +

          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 @@ -3565,12 +3563,10 @@ Skip SMTP servers that greet with a 5XX status code (go away, do not try again later).

          -

          -By default, Postfix 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. -

          +

          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.

          %PARAM smtp_skip_quit_response yes @@ -4443,7 +4439,8 @@ code for rejected requests (default: 554).
          reject_unknown_recipient_domain
          Reject the request when the RCPT TO address has no DNS A or MX -record.
          The unknown_address_reject_code parameter specifies +record and Postfix is not final destination for the recipient +address.
          The unknown_address_reject_code parameter specifies the response code for rejected requests (default: 450). The response is always 450 in case of a temporary DNS error.
          @@ -4767,10 +4764,11 @@ Postfix version 2.1 and later.
          reject_unknown_sender_domain
          -
          Reject the request when the MAIL FROM address has no DNS A -or MX record.
          The unknown_address_reject_code parameter -specifies the response code for rejected requests (default: 450). -The response is always 450 in case of a temporary DNS error.
          +
          Reject the request when the MAIL FROM address has no DNS A or +MX record and Postfix is not final destination for the sender +address.
          The unknown_address_reject_code parameter specifies +the response code for rejected requests (default: 450). The response +is always 450 in case of a temporary DNS error.
          reject_unlisted_sender
          diff --git a/postfix/proto/transport b/postfix/proto/transport index b0ff1e520..23c956421 100644 --- a/postfix/proto/transport +++ b/postfix/proto/transport @@ -62,11 +62,9 @@ # The \fIpattern\fR specifies an email address, a domain name, or # a domain name hierarchy, as described in section "TABLE LOOKUP". # -# The \fIresult\fR is of the form \fItransport\fB:\fInexthop\fR. -# The \fItransport\fR field specifies a mail delivery transport -# such as \fBsmtp\fR or \fBlocal\fR. The \fInexthop\fR field -# specifies where and how to deliver mail. More details are given -# in section "RESULT FORMAT". +# The \fIresult\fR is of the form \fItransport:nexthop\fR and +# specifies how or where to deliver mail. This is described in +# section "RESULT FORMAT". # TABLE LOOKUP # .ad # .fi @@ -99,14 +97,19 @@ # RESULT FORMAT # .ad # .fi +# The lookup result is of the form \fItransport\fB:\fInexthop\fR. +# The \fItransport\fR field specifies a mail delivery transport +# such as \fBsmtp\fR or \fBlocal\fR. The \fInexthop\fR field +# specifies where and how to deliver mail. +# # The transport field specifies the name of a mail delivery transport # (the first name of a mail delivery service entry in the Postfix # \fBmaster.cf\fR file). # # The interpretation of the nexthop field is transport -# dependent. In the case of SMTP, specify \fIhost\fR:\fIservice\fR for a -# non-default server port, and use [\fIhost\fR] or [\fIhost\fR]:\fIport\fR -# in order to disable MX (mail exchanger) DNS lookups. The [] form +# dependent. In the case of SMTP, specify a service on a non-default +# port as \fIhost\fR:\fIservice\fR, and disable MX (mail exchanger) +# DNS lookups with [\fIhost\fR] or [\fIhost\fR]:\fIport\fR. The [] form # is required when you specify an IP address instead of a hostname. # # A null \fItransport\fR and null \fInexthop\fR result means "do @@ -134,52 +137,53 @@ # .ti +5 # \fB* smtp:outbound-relay.my.domain\fR # -# In order to send mail for \fBfoo.org\fR and its subdomains -# via the \fBuucp\fR transport to the UUCP host named \fBfoo\fR: +# In order to send mail for \fBexample.com\fR and its subdomains +# via the \fBuucp\fR transport to the UUCP host named \fBexample\fR: # # .ti +5 -# \fBfoo.org uucp:foo\fR +# \fBexample.com uucp:example\fR # .ti +5 -# \fB\&.foo.org uucp:foo\fR +# \fB\&.example.com uucp:example\fR # # When no nexthop host name is specified, the destination domain # name is used instead. For example, the following directs mail for -# \fIuser\fR@\fBfoo.org\fR via the \fBslow\fR transport to a mail -# exchanger for \fBfoo.org\fR. The \fBslow\fR transport could be -# something that runs at most one delivery process at a time: +# \fIuser\fR@\fBexample.com\fR via the \fBslow\fR transport to a mail +# exchanger for \fBexample.com\fR. The \fBslow\fR transport could be +# configured to run at most one delivery process at a time: # # .ti +5 -# \fBfoo.org slow:\fR +# \fBexample.com slow:\fR # # When no transport is specified, Postfix uses the transport that -# matches the address domain class (see TRANSPORT FIELD discussion -# above). The following sends all mail for \fBfoo.org\fR and its -# subdomains to host \fBgateway.foo.org\fR: +# matches the address domain class (see DESCRIPTION +# above). The following sends all mail for \fBexample.com\fR and its +# subdomains to host \fBgateway.example.com\fR: # # .ti +5 -# \fBfoo.org :[gateway.foo.org]\fR +# \fBexample.com :[gateway.example.com]\fR # .ti +5 -# \fB\&.foo.org :[gateway.foo.org]\fR +# \fB\&.example.com :[gateway.example.com]\fR # -# In the above example, the [] are used to suppress MX lookups. -# The result would likely point to your local machine. +# In the above example, the [] suppress MX lookups. +# This prevents mail routing loops when your machine is primary MX +# host for \fBexample.com\fR. # # In the case of delivery via SMTP, one may specify # \fIhostname\fR:\fIservice\fR instead of just a host: # # .ti +5 -# \fBfoo.org smtp:bar.org:2025\fR +# \fBexample.com smtp:bar.example:2025\fR # -# This directs mail for \fIuser\fR@\fBfoo.org\fR to host \fBbar.org\fR +# This directs mail for \fIuser\fR@\fBexample.com\fR to host \fBbar.example\fR # port \fB2025\fR. Instead of a numerical port a symbolic name may be -# used. Specify [] around the hostname in order to disable MX lookups. +# used. Specify [] around the hostname if MX lookups must be disabled. # # The error mailer can be used to bounce mail: # # .ti +5 -# \fB\&.foo.org error:mail for *.foo.org is not deliverable\fR +# \fB\&.example.com error:mail for *.example.com is not deliverable\fR # -# This causes all mail for \fIuser\fR@\fIanything\fB.foo.org\fR +# This causes all mail for \fIuser\fR@\fIanything\fB.example.com\fR # to be bounced. # REGULAR EXPRESSION TABLES # .ad @@ -216,7 +220,7 @@ # CONFIGURATION PARAMETERS # .ad # .fi -# The following \fBmain.cf\fR parameters are especially relevant. +# The following \fBmain.cf\fR parameters are especially relevant. # The text below provides only a parameter summary. See # postconf(5) for more details including examples. # .IP \fBempty_address_recipient\fR diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 184b07f7e..f1638b332 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only. */ -#define MAIL_RELEASE_DATE "20040421" +#define MAIL_RELEASE_DATE "20040422" #define MAIL_VERSION_NUMBER "2.2" #define VAR_MAIL_VERSION "mail_version" diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index d20bf0d8f..07567361d 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -93,6 +93,10 @@ /* A table that always returns its name as lookup result. For example, /* \fBstatic:foobar\fR always returns the string \fBfoobar\fR as lookup /* result. +/* .IP "\fBtcp\fR (read-only)" +/* Perform lookups using a simple request-reply protocol that is +/* described in tcp_table(5). +/* This feature is not included with Postfix 2.1. /* .IP "\fBunix\fR (read-only)" /* A limited way to query the UNIX authentication database. The /* following tables are implemented: diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index f3793e620..292ac1fca 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -149,6 +149,8 @@ smtpd.o: ../../include/quote_flags.h smtpd.o: ../../include/lex_822.h smtpd.o: ../../include/namadr_list.h smtpd.o: ../../include/input_transp.h +smtpd.o: ../../include/anvil_clnt.h +smtpd.o: ../../include/attr_clnt.h smtpd.o: ../../include/mail_server.h smtpd.o: smtpd_token.h smtpd.o: smtpd.h @@ -230,6 +232,7 @@ smtpd_check.o: ../../include/verify_clnt.h smtpd_check.o: ../../include/deliver_request.h smtpd_check.o: ../../include/recipient_list.h smtpd_check.o: ../../include/input_transp.h +smtpd_check.o: ../../include/is_header.h smtpd_check.o: smtpd.h smtpd_check.o: ../../include/mail_stream.h smtpd_check.o: smtpd_sasl_glue.h