]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20000918
authorWietse Venema <wietse@porcupine.org>
Mon, 18 Sep 2000 00:00:00 +0000 (00:00 +0000)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 23:12:19 +0000 (18:12 -0500)
28 files changed:
postfix/FILTER_README
postfix/HISTORY
postfix/INSPECT_README [deleted file]
postfix/auxiliary/rmail/rmail
postfix/cleanup/cleanup_extracted.c
postfix/cleanup/cleanup_message.c
postfix/dns/dns_lookup.c
postfix/examples/chroot-setup/LINUX2
postfix/global/mail_addr_crunch.c
postfix/global/mail_copy.c
postfix/global/mail_version.h
postfix/html/pipe.8.html
postfix/html/smtp.8.html
postfix/html/transport.5.html
postfix/html/virtual.5.html
postfix/local/recipient.c
postfix/man/man5/transport.5
postfix/man/man5/virtual.5
postfix/man/man8/pipe.8
postfix/man/man8/smtp.8
postfix/pipe/pipe.c
postfix/postalias/postalias.c
postfix/proto/transport
postfix/proto/virtual
postfix/smtp/smtp.c
postfix/smtp/smtp_unalias.c
postfix/smtpd/smtpd_sasl_proto.c
postfix/util/dict_tcp.c

index c6a3a71c01a131217c0913e49118c4d38808862c..7c1ebfc61c5157678b5b34b281b10f0cdf57a6c5 100644 (file)
@@ -1,7 +1,6 @@
 This is a very first implementation of Postfix content filtering.
-A Postfix content filter re-injects filtered mail back into Postfix.
-If all you want is content _inspection_, see the INSPECT_README
-file instead.
+A Postfix content filter receives unfiltered mail from Postfix and
+re-injects filtered mail back into Postfix.
 
 It involves an incompatible change to queue file formats.  Older
 Postfix versions will reject mail that needs to be content filtered,
index 106f87a42690c97e0d300a619ea17e9f2d41ff27..35cdcb3f304ae5c9ef8bf4a17adb608efa1d684b 100644 (file)
@@ -4055,12 +4055,6 @@ Apologies for any names omitted.
        lying around after unsuccessful delivery (problem reported
        by Brian Laughton @ Corp.Axxent.Ca).
 
-20000619
-
-       Workaround: if append_dot_mydomain=no, turn on parent domain
-       search in the Postfix SMTP client, so that mail does not
-       bounce. Files: smtp/smtp.c, smtp/smtp_unalias.c.
-
 20000621
 
        AIX 4.x had POSIX regular expression support all the time
@@ -4127,7 +4121,7 @@ Apologies for any names omitted.
        not exist, defer mail instead of bouncing it (which would
        lose the mail if the bounce would have to be delivered to
        that same non-existent relayhost). Problem reported by
-       Chris Cooper @ maths.ox.ac.uk.
+       Chris Cooper @ maths.ox.ac.uk. File: smtp/smtp_connect.c.
 
 20000821
 
@@ -4136,6 +4130,7 @@ Apologies for any names omitted.
        Cleanup: smtpd now replies with 555 when the client sends
        unrecognized RCPT TO parameters, as required by RFC 1869
        (problem report by Robert Norris @ its.monash.edu.au).
+       File: smtpd/smtpd.c.
 
 20000822
 
@@ -4156,3 +4151,58 @@ Apologies for any names omitted.
        access controls, for example, hold off mail from an unknown
        client or sender until we have completed some investigation,
        after which we will either reject or accept.
+
+20000905
+
+       Robustness: the dns client now rejects malformed domain
+       names rather than depending on the DNS to report that the
+       name does not exist. Linux returns a rather misleading
+       server failure code as found out by Patrik Rak. File:
+       dns/dns_lookup.c.
+
+20000911
+
+       Feature: added IGNORE keyword to header_checks and body_checks
+       to pretend that certain data does not exist. File:
+       cleanup/cleanup_message.c.
+
+20000911
+
+       Bugfix: the SASL code did not allow MAIL FROM... AUTH=sender
+       without prior authentication. The RFC allows this, although
+       one wonders what the reasoning behind this is. File:
+       smtpd/smtpd_sasl_proto.c.
+
+20000913
+
+       Bugfix: the rmail script did not handle remote UUCP systems
+       that send a from_ line with unqualified envelope sender.
+       Reported by Luciano Mannucci.
+
+       Compatibility: don't insert Sender: header lines. Sendmail
+       has not done so for at least 10 years, if it ever did.
+       Problem reported by Brad Knowles. File: cleanup/cleanup_message.c.
+
+20000916
+
+       Bugfix: when propagating an address extension in a virtual
+       or canonical mapping, cleanup accesses memory that is no
+       longer allocated. This can happen when the result address
+       length is more than 100 characters.  Problem reported by
+       Adi Prasaja @ satunet.com. File: global/mail_addr_crunch.c.
+
+       Bugfix: fixed a misleading error message when the cleanup
+       server reaches the queue file size limit. Fix by Robby
+       Griffin @ MIT.EDU.  File: cleanup/cleanup_extracted.c.
+
+20000917
+
+       Bugfix: postalias -i would complain about duplicate entries
+       for the Sendmail-compatible @ entry and for the NIS-compatible
+       YP_LAST_MODIFIED and YP_MASTER_NAME entries.
+
+20000918
+
+       Gross hack: prevent looping a bad recipient by always
+       forwarding recipients in :include: files, even when
+       owner-listname is not set. File: local/recipient.c.
diff --git a/postfix/INSPECT_README b/postfix/INSPECT_README
deleted file mode 100644 (file)
index 2b91d34..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-This is a very first implementation of Postfix content inspection.
-A Postfix content inspector causes "bad" mail to be bounced. All
-other mail is delivered normally.  If you want content _inspection_,
-which allows you to modify mail content or destination, see the
-FILTER_README file instead.
-
-Content inspection involves an incompatible change to queue file
-formats.  Older Postfix versions will reject mail that needs to be
-content inspected, and will move the queue file to the "corrupt"
-mail queue subdirectory.
-
-This document describes two approaches to content inspection.
-
-Simple content inspection example
-=================================
-
-The example is relatively simple to set up, but is resource intensive
-because it runs a shell script for each message.
-
-With the shell script as shown you can lose a factor in Postfix
-performance for each temporary file that is created and deleted in
-the process of content inspection.  The performance impact is less
-for mail that is submitted or delivered locally, because such
-deliveries are not as fast as SMTP transit mail.
-
-The example assumes that only mail received via SMTP needs to be
-content inspected.
-
-      ..................................
-      .            Postfix             .
-   ------smtpd \                /local-----
-      .         -cleanup->queue-       .
-   -----pickup /                \smtp------
-      .                        |       .
-      .                         \pipe------>inspector
-      ..................................
-
-Create a dedicated local user account called "inspect".  The user
-will never log in, and can be given a "*" password and non-existent
-shell and home.
-
-Create a directory /var/spool/inspect that is accessible only to
-the "inspect" user. This is where the content inspection software
-will store any temporary files.
-
-Define a content inspection entry in the Postfix master file:
-
-    /etc/postfix/master.cf:
-       inspect   unix  -       n       n       -       -       pipe
-           user=inspect argv=/some/where/inspect ${sender} ${recipient}
-
-The filter program can start out as a simple shell script like this:
-
-    #!/bin/sh
-
-    # Localize this
-    INSPECT_DIR=/var/spool/inspect
-
-    # Exit codes from <sysexits.h>
-    EX_TEMPFAIL=75
-    EX_UNAVAILABLE=69
-
-    cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }
-
-    # Clean up when done or when aborting.
-    trap "rm -f in.$$; exit" 0 1 2 3 15
-
-    cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }
-
-    # inspect <in.$$ || { echo Message content rejected; exit $EX_UNAVAILABLE; }
-
-    exit 0
-
-The idea is to first capture the message to file and then run the
-content through run a third-party content inspection program.  If
-the mail cannot be captured to file, mail delivery is deferred by
-terminating with exit status 75 (EX_TEMPFAIL).  If the content
-inspection program finds a problem, the mail is bounced by terminating
-the shell script with exit status 69 (EX_UNAVAILABLE). An exit
-status of zero means everything is hunky-dory and the mail can
-be delivered to its recipients.
-
-If mail is rejected, another possible action is to mail a copy to
-the local postmaster. If you do that, be sure not to enable content
-inspection for locally-posted mail or else rejected mail will loop.
-
-The problem with content inspection sotware like this is that it is
-not very robust, because the software does not talk a well-defined
-protocol with Postfix. If the shell scripts aborts because the
-shell runs into some memory allocation problem, the script will
-not produce a nice exit status as per /usr/include/sysexits.h and
-mail will probably bounce. The same lack of robustness is possible
-when the content inspection software itself runs into a resource
-problem.
-
-I suggest that you play with this script for a while until you are
-satisfied with the results. Run it as root or as the filter user,
-with a real message (headers+body) as input:
-
-    # /some/where/inspect sender recipient... <message-file
-
-Turn on content inspection for mail arriving via SMTP only, by
-appending "-o content_inspector=inspect:dummy" to the master.cf
-entry that defines the Postfix SMTP server:
-
-    /etc/postfix/master.cf:
-       smtp      inet     ...stuff...      smtpd
-           -o content_inspector=inspect:dummy
-
-The content_inspector configuration parameter accepts the same
-syntax as the right-hand side in a Postfix transport table.
-
-Advanced content inspection example
-===================================
-
-The second example is more complex, but can give better performance,
-and is less likely to bounce mail when the machine runs into a
-resource problem.  This approach uses content inspection software
-that can receive mail via SMTP, and that can run as a resident
-server.  You can expect to lose about a factor in Postfix performance
-for every temporary file created.
-
-We will set up a content inspection program listening on localhost
-port 10025 that receives mail via the SMTP protocol.
-
-      ..................................
-      .            Postfix             .
-   ------smtpd \                /local-----
-      .         -cleanup->queue-       .
-   -----pickup /            |   \smtp------
-      .                     v          .
-      .                    smtp        .
-      .                     |          .
-      ......................|...........
-                            |
-                            v
-                .................
-                .         10025 .
-                .   inspection  .
-                .               .
-                .................
-
-To enable content inspection in this manner, specify in main.cf a
-new parameter:
-
-    /etc/postfix/main.cf:
-       content_filter = smtp:localhost:10025
-
-This causes Postfix to add one extra content inspection record to
-each incoming mail message, with content smtp:localhost:10025.
-You can use the same syntax as in the right-hand side of a Postfix
-transport table.  The content inspection records are added by the
-smtpd and pickup servers.
-
-When a queue file has content inspection information, the queue
-manager will deliver the mail to the specified content inspector
-before attempting final delivery.
-
-The content filter can be set up with the Postfix spawn service,
-which is the Postfix equivalent of inetd. For example, to instantiate
-up to 10 content inspection processes on demand:
-
-    /etc/postfix/master.cf:
-       localhost:10025     inet  n      n      n      -      10     spawn
-           user=inspect argv=/some/where/inspect
-
-"inspect" is a dedicated local user account.  The user will never
-log in, and can be given a "*" password and non-existent shell and
-home.
-
-The spawn server is part of Postfix but is not installed by default.
-Edit the top-level Makefile.in file, run "make makefiles", "make",
-and "make install". The manual page isn't installed by default,
-either. See the spawn.c source file.
-
-The /some/where/inspect command is most likely a PERL script. PERL
-has modules that make talking SMTP easy.
-
-For now, it is left up to the Postfix users to come up with a
-PERL/SMTP framework for Postfix content inspection. If done well,
-it can be used with other mailers too, which is a nice spin-off.
index 44c999ee788dd2dc7b847f1cc9d948dca837d47d..eb35bf1c24c7636e2fca94c0c0af2b53cd81344d 100755 (executable)
@@ -3,6 +3,11 @@
 # Dummy UUCP rmail command for postfix/qmail systems
 
 SENDMAIL="/usr/sbin/sendmail"
-IFS=" " read junk from junk
+IFS=" " read junk from junk junk junk junk junk junk junk relay
+
+case "$from" in
+ *[@!]*) ;;
+      *) from="$from@$relay";;
+esac
 
 exec $SENDMAIL -f "$from" -- "$@"
index 1f5c5407296ec433d4afb1ab0bd874dbb7b04647..1a4982fa1db2fb01ab9419bd83b191271c2bf552 100644 (file)
@@ -183,10 +183,13 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf,
      */
     if (vstream_fflush(state->dst)) {
        msg_warn("%s: write queue file: %m", state->queue_id);
-       if (errno == EFBIG)
+       if (errno == EFBIG) {
+           msg_warn("%s: queue file size limit exceeded", state->queue_id);
            state->errs |= CLEANUP_STAT_SIZE;
-       else
+       } else {
+           msg_warn("%s: write queue file: %m", state->queue_id);
            state->errs |= CLEANUP_STAT_WRITE;
+       }
        return;
     }
 
index ed43a59293f7251b0de58b4118235c02f0c302ac..151bbb15402b7404eb6438e386f883eee2e32c1b 100644 (file)
@@ -267,6 +267,8 @@ static void cleanup_header(CLEANUP_STATE *state)
                         state->queue_id, header, state->sender,
                         state->recip ? state->recip : "unknown");
                state->errs |= CLEANUP_STAT_CONT;
+           } else if (strcasecmp(value, "IGNORE") == 0) {
+               return;
            }
        }
     }
@@ -346,12 +348,8 @@ static void cleanup_missing_headers(CLEANUP_STATE *state)
     }
 
     /*
-     * Add a missing (Resent-)From: header. If a (Resent-)From: header is
-     * present, see if we need a (Resent-)Sender: header.
+     * Add a missing (Resent-)From: header.
      */
-#define NOT_SPECIAL_SENDER(addr) (*(addr) != 0 \
-          && strcasecmp(addr, mail_addr_double_bounce()) != 0)
-
     if ((state->headers_seen & (1 << (state->resent[0] ?
                                      HDR_RESENT_FROM : HDR_FROM))) == 0) {
        quote_822_local(state->temp1, *state->sender ?
@@ -366,15 +364,6 @@ static void cleanup_missing_headers(CLEANUP_STATE *state)
            tok822_free_tree(token);
        }
        CLEANUP_OUT_BUF(state, REC_TYPE_NORM, state->temp2);
-    } else if ((state->headers_seen & (1 << (state->resent[0] ?
-                                     HDR_RESENT_SENDER : HDR_SENDER))) == 0
-              && NOT_SPECIAL_SENDER(state->sender)) {
-       from = (state->resent[0] ? state->resent_from : state->from);
-       if (from == 0 || strcasecmp(state->sender, from) != 0) {
-           quote_822_local(state->temp1, state->sender);
-           cleanup_out_format(state, REC_TYPE_NORM, "%sSender: %s",
-                              state->resent, vstring_str(state->temp1));
-       }
     }
 
     /*
@@ -508,6 +497,8 @@ static void cleanup_message_body(CLEANUP_STATE *state, int type, char *buf, int
                             state->queue_id, buf, state->sender,
                             state->recip ? state->recip : "unknown");
                    state->errs |= CLEANUP_STAT_CONT;
+               } else if (strcasecmp(value, "IGNORE") == 0) {
+                   return;
                }
            }
        }
index 15caa6760b8d232078d80ccb78b294af3862d2a7..fedd6a8700093ca5ab9590fedc537f68b139b06f 100644 (file)
 #include <msg.h>
 #include <valid_hostname.h>
 #include <stringops.h>
+#include <valid_hostname.h>
 
 /* DNS library. */
 
@@ -430,6 +431,16 @@ int     dns_lookup(const char *name, unsigned type, unsigned flags,
     int     count;
     int     status;
 
+    /*
+     * The Linux resolver misbehaves when given an invalid domain name.
+     */
+    if (!valid_hostname(name)) {
+       if (why)
+           vstring_sprintf(why, "Name service error for %s: invalid name",
+                           name);
+       return (DNS_NOTFOUND);
+    }
+
     /*
      * Perform the lookup. Follow CNAME chains, but only up to a
      * pre-determined maximum.
index e6b18024641c3acf20cb140ff7f7be136dd6164e..1d35e1c8ec0636f29d122cfe32302fb06de7f30d 100644 (file)
@@ -8,11 +8,9 @@ POSTFIX_DIR=${POSTFIX_DIR-/var/spool/postfix}
 cd ${POSTFIX_DIR}
 
 mkdir etc
-cp /etc/localtime /etc/services /etc/resolv.conf etc
+cp /etc/localtime /etc/services /etc/resolv.conf /etc/nsswitch.conf etc
 mkdir -p usr/lib/zoneinfo
 ln -s /etc/localtime usr/lib/zoneinfo
 
-if [ -e /lib/libnss_dns.so.1 ]; then
-    mkdir lib
-    cp /lib/libnss_dns.so.1 lib
-fi
+mkdir lib
+cp /lib/libnss_* lib
index 5f1c3a707b82fd5516c43b1063a0d634d97687aa..23383e0410cd6b4fb322359bf12c9358c5e6f736 100644 (file)
@@ -84,10 +84,10 @@ ARGV   *mail_addr_crunch(const char *string, const char *extension)
        tok822_externalize(extern_addr, tpp[0]->head, TOK822_STR_DEFL);
        canon_addr_external(canon_addr, STR(extern_addr));
        if (extension) {
+           VSTRING_SPACE(canon_addr, extlen + 1);
            if ((ratsign = strrchr(STR(canon_addr), '@')) == 0) {
                vstring_strcat(canon_addr, extension);
            } else {
-               VSTRING_SPACE(canon_addr, extlen + 1);
                memmove(ratsign + extlen, ratsign, strlen(ratsign) + 1);
                memcpy(ratsign, extension, extlen);
                VSTRING_SKIP(canon_addr);
index c8fae4f5f7970037a097b36ab1d0ebbfdbe42c43..e08d301f56ec38c7229d52b99764fdd429f6f968 100644 (file)
@@ -42,8 +42,9 @@
 /*     data to stable storage, and truncate the destination
 /*     file to its original length in case of problems.
 /* .IP MAIL_COPY_FROM
-/*     Prepend a UNIX-style From_ line to the message, and append
-/*     an empty line to the end of the message.
+/*     Prepend a UNIX-style From_ line to the message.
+/* .IP MAIL_COPY_BLANK
+/*     Append an empty line to the end of the message.
 /* .IP MAIL_COPY_DELIVERED
 /*     Prepend a Delivered-To: header with the name of the
 /*     \fIdelivered\fR attribute.
index 64a3274c30d58e17924ffb9c09c24e63d5bf2aa7..8830407cf7c807c03a3409eda3bc5e4e06917d9d 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20000823"
+#define DEF_MAIL_VERSION       "Snapshot-20000918"
 extern char *var_mail_version;
 
 /* LICENSE
index fa0f42390cf6b4f22ce1af1061c0964badfeb74d..c98431c7dc46ae0252669fb94b94f463d71033f9 100644 (file)
@@ -41,9 +41,7 @@ PIPE(8)                                                   PIPE(8)
 
               <b>F</b>      Prepend a "<b>From</b> <i>sender</i> <i>time_stamp</i>"  envelope
                      header  to  the  message  content.   This is
-                     expected by, for example, <b>UUCP</b> software. The
-                     <b>F</b>  flag  also  causes  an  empty  line to be
-                     appended to the message.
+                     expected by, for example, <b>UUCP</b> software.
 
               <b>R</b>      Prepend a <b>Return-Path:</b> message  header  with
                      the envelope sender address.
@@ -59,6 +57,8 @@ PIPE(8)                                                   PIPE(8)
 
        <b>user</b>=<i>username</i>:<i>groupname</i>
               The external command is executed with the rights of
+              the  specified  <i>username</i>.   The software refuses to
+              execute commands with root privileges, or with  the
 
 
 
@@ -71,8 +71,6 @@ PIPE(8)                                                   PIPE(8)
 PIPE(8)                                                   PIPE(8)
 
 
-              the  specified  <i>username</i>.   The software refuses to
-              execute commands with root privileges, or with  the
               privileges  of  the mail system owner. If <i>groupname</i>
               is specified, the corresponding group  ID  is  used
               instead of the group ID of <i>username</i>.
@@ -125,6 +123,8 @@ PIPE(8)                                                   PIPE(8)
                      tains <b>${recipient</b>} expands into as many com-
                      mand-line arguments as there are recipients.
 
+              <b>${sender</b>}
+                     This macro expands to  the  envelope  sender
 
 
 
@@ -137,8 +137,6 @@ PIPE(8)                                                   PIPE(8)
 PIPE(8)                                                   PIPE(8)
 
 
-              <b>${sender</b>}
-                     This macro expands to  the  envelope  sender
                      address.
 
               <b>${size</b>}
@@ -190,7 +188,9 @@ PIPE(8)                                                   PIPE(8)
        <i>transport_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
               Limit the number of parallel deliveries to the same
               destination,  for delivery via the named <i>transport</i>.
-              The   default   limit    is    taken    from    the
+              The default limit is taken from the  <b>default</b><i>_</i><b>desti-</b>
+              <b>nation</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>  parameter.   The limit is
+              enforced by the Postfix queue manager.
 
 
 
@@ -203,21 +203,18 @@ PIPE(8)                                                   PIPE(8)
 PIPE(8)                                                   PIPE(8)
 
 
-              <b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>    parameter.
-              The limit is enforced by the Postfix queue manager.
-
        <i>transport_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
-              Limit  the  number of recipients per message deliv-
-              ery, for delivery  via  the  named  <i>transport</i>.  The
-              default  limit  is  taken from the <b>default</b><i>_</i><b>destina-</b>
-              <b>tion</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>  parameter.   The   limit   is
+              Limit the number of recipients per  message  deliv-
+              ery,  for  delivery  via  the  named <i>transport</i>. The
+              default limit is taken  from  the  <b>default</b><i>_</i><b>destina-</b>
+              <b>tion</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>   parameter.    The  limit  is
               enforced by the Postfix queue manager.
 
        <i>transport_</i><b>time</b><i>_</i><b>limit</b>
-              Limit  the  time  for delivery to external command,
-              for delivery via the named <b>transport</b>.  The  default
-              limit  is taken from the <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b> parame-
-              ter.  The limit is enforced by  the  Postfix  queue
+              Limit the time for delivery  to  external  command,
+              for  delivery  via the named <b>transport</b>. The default
+              limit is taken from the <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b>  parame-
+              ter.   The  limit  is enforced by the Postfix queue
               manager.
 
 <b>SEE</b> <b>ALSO</b>
@@ -227,7 +224,7 @@ PIPE(8)                                                   PIPE(8)
        syslogd(8) system logging
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
@@ -256,6 +253,9 @@ PIPE(8)                                                   PIPE(8)
 
 
 
+
+
+
 
 
 
index 1529182fb7ab49eefbfe92c73d5009aac1041b2c..05e2d06e6131e7f84c10e9e12446630d3cedc172 100644 (file)
@@ -75,9 +75,6 @@ SMTP(8)                                                   SMTP(8)
        command after a configuration change.
 
 <b>Miscellaneous</b>
-       <b>append</b><i>_</i><b>dot</b><i>_</i><b>mydomain</b>
-              Rewrite <i>user</i>@<i>host</i> to <i>user</i>@<i>host</i>.$<b>mydomain</b>.
-
        <b>best</b><i>_</i><b>mx</b><i>_</i><b>transport</b>
               Name  of  the  delivery  transport  to use when the
               local machine is the most-preferred mail  exchanger
@@ -126,6 +123,9 @@ SMTP(8)                                                   SMTP(8)
        <b>smtp</b><i>_</i><b>always</b><i>_</i><b>send</b><i>_</i><b>ehlo</b>
               Always send EHLO at the start of a connection.
 
+       <b>smtp</b><i>_</i><b>skip</b><i>_</i><b>4xx</b><i>_</i><b>greeting</b>
+              Skip  servers that greet us with a 4xx status code.
+
 
 
                                                                 2
@@ -137,9 +137,6 @@ SMTP(8)                                                   SMTP(8)
 SMTP(8)                                                   SMTP(8)
 
 
-       <b>smtp</b><i>_</i><b>skip</b><i>_</i><b>4xx</b><i>_</i><b>greeting</b>
-              Skip  servers that greet us with a 4xx status code.
-
        <b>smtp</b><i>_</i><b>skip</b><i>_</i><b>5xx</b><i>_</i><b>greeting</b>
               Skip servers that greet us with a 5xx status  code.
 
@@ -191,6 +188,9 @@ SMTP(8)                                                   SMTP(8)
               ery.   The  default  limit  is   taken   from   the
               <b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
 
+<b>Timeout</b> <b>controls</b>
+       <b>smtp</b><i>_</i><b>connect</b><i>_</i><b>timeout</b>
+              Timeout in seconds for completing a TCP connection.
 
 
 
@@ -203,9 +203,6 @@ SMTP(8)                                                   SMTP(8)
 SMTP(8)                                                   SMTP(8)
 
 
-<b>Timeout</b> <b>controls</b>
-       <b>smtp</b><i>_</i><b>connect</b><i>_</i><b>timeout</b>
-              Timeout in seconds for completing a TCP connection.
               When no connection can be made within the deadline,
               the  SMTP client tries the next address on the mail
               exchanger list.
@@ -257,6 +254,9 @@ SMTP(8)                                                   SMTP(8)
        The Secure Mailer license must be  distributed  with  this
        software.
 
+<b>AUTHOR(S)</b>
+       Wietse Venema
+       IBM T.J. Watson Research
 
 
 
@@ -269,9 +269,6 @@ SMTP(8)                                                   SMTP(8)
 SMTP(8)                                                   SMTP(8)
 
 
-<b>AUTHOR(S)</b>
-       Wietse Venema
-       IBM T.J. Watson Research
        P.O. Box 704
        Yorktown Heights, NY 10598, USA
 
@@ -322,6 +319,9 @@ SMTP(8)                                                   SMTP(8)
 
 
 
+
+
+
 
 
 
index 9b760ccd327e7f4e3afaa972dee331864871831d..31c595d35377478395c63065a3b5a15aa0c6b2e2 100644 (file)
@@ -84,47 +84,47 @@ TRANSPORT(5)                                         TRANSPORT(5)
        names.
 
 <b>EXAMPLES</b>
-       In order to send mail for <b>foo.org</b> and its subdomains
-       via the <b>uucp</b> transport to the UUCP host named <b>foo</b>:
+       In order to send mail for <b>foo.org</b> and its  subdomains  via
+       the <b>uucp</b> transport to the UUCP host named <b>foo</b>:
 
             <b>foo.org</b>      <b>uucp:foo</b>
             <b>.foo.org</b>     <b>uucp:foo</b>
 
-       When no <i>nexthop</i> host name is specified, the destination domain
-       name is used instead. For example, the following directs mail for
-       <i>user</i>@<b>foo.org</b> via the <b>slow</b> transport to a mail
-       exchanger for <b>foo.org</b>.  The <b>slow</b> transport could be
-       something that runs at most one delivery process at a time:
+       When  no  <i>nexthop</i>  host name is specified, the destination
+       domain name is used instead. For  example,  the  following
+       directs  mail for <i>user</i>@<b>foo.org</b> via the <b>slow</b> transport to a
+       mail exchanger for <b>foo.org</b>.  The <b>slow</b> transport  could  be
+       something  that  runs  at  most  one delivery process at a
+       time:
 
             <b>foo.org</b>      <b>slow:</b>
 
-       When no <i>transport</i> is specified, the default transport is
+       When no <i>transport</i> is specified, the default  transport  is
        used, as specified via the <b>default</b><i>_</i><b>transport</b> configuration
-       parameter. The following sends all mail for <b>foo.org</b> and its
-       subdomains to host <b>gateway.foo.org</b>:
+       parameter. The following sends all mail  for  <b>foo.org</b>  and
+       its subdomains to host <b>gateway.foo.org</b>:
 
             <b>foo.org</b>      <b>:[gateway.foo.org]</b>
             <b>.foo.org</b>     <b>:[gateway.foo.org]</b>
 
-       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  []  are used to suppress MX
+       lookups.  The result would  likely  point  to  your  local
+       machine.
 
-       In the case of delivery via SMTP, one may specify
-       <i>hostname</i>:<i>service</i> instead of just a host:
+       In  the  case  of delivery via SMTP, one may specify <i>host-</i>
+       <i>name</i>:<i>service</i> instead of just a host:
 
             <b>foo.org</b>      <b>smtp:bar.org:2025</b>
 
-       This directs mail for <i>user</i>@<b>foo.org</b> to host <b>bar.org</b>
-       port <b>2025</b>. Instead of a numerical port a symbolic name may be
-       used. Specify [] around the destination in order to disable MX lookups.
+       This directs mail for <i>user</i>@<b>foo.org</b> to  host  <b>bar.org</b>  port
+       <b>2025</b>.  Instead  of a numerical port a symbolic name may be
+       used. Specify [] around the destination in order  to  dis-
+       able MX lookups.
 
        The error mailer can be used to bounce mail:
 
-            <b>.foo.org</b>      <b>error:mail</b> <b>for</b> <b>*.foo.org</b> <b>is</b> <b>not</b> <b>deliverable</b>
-
-       This causes all mail for <i>user</i>@<i>anything</i><b>.foo.org</b>
-       to be bounced.
-
+            <b>.foo.org</b>       <b>error:mail</b> <b>for</b> <b>*.foo.org</b> <b>is</b> <b>not</b> <b>deliv-</b>
+       <b>erable</b>
 
 
 
@@ -137,28 +137,31 @@ TRANSPORT(5)                                         TRANSPORT(5)
 TRANSPORT(5)                                         TRANSPORT(5)
 
 
+       This causes  all  mail  for  <i>user</i>@<i>anything</i><b>.foo.org</b>  to  be
+       bounced.
+
 <b>REGULAR</b> <b>EXPRESSION</b> <b>TABLES</b>
-       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 <a href="regexp_table.5.html"><b>regexp</b><i>_</i><b>table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre</b><i>_</i><b>table</b>(5)</a>.
 
-       Each  pattern  is  a regular expression that is applied to
+       Each pattern is a regular expression that  is  applied  to
        the entire domain being looked up. Thus, <i>some.domain.hier-</i>
        <i>archy</i> is not broken up into parent domains.
 
-       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 normal indexed file lookups,
-       with the additional feature that parenthesized  substrings
-       from  the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so on.
+       Results are the same as with normal indexed file  lookups,
+       with  the additional feature that parenthesized substrings
+       from the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so  on.
 
 <b>CONFIGURATION</b> <b>PARAMETERS</b>
-       The following <b>main.cf</b> parameters are  especially  relevant
-       to  this  topic.  See  the Postfix <b>main.cf</b> file for syntax
-       details and for default values.  Use  the  <b>postfix</b>  <b>reload</b>
+       The  following  <b>main.cf</b> parameters are especially relevant
+       to this topic. See the Postfix  <b>main.cf</b>  file  for  syntax
+       details  and  for  default  values. Use the <b>postfix</b> <b>reload</b>
        command after a configuration change.
 
        <b>transport</b><i>_</i><b>maps</b>
@@ -167,7 +170,7 @@ TRANSPORT(5)                                         TRANSPORT(5)
        Other parameters of interest:
 
        <b>default</b><i>_</i><b>transport</b>
-              The  transport  to use when no transport is explic-
+              The transport to use when no transport  is  explic-
               itly specified.
 
        <b>relayhost</b>
@@ -181,20 +184,83 @@ TRANSPORT(5)                                         TRANSPORT(5)
        <a href="regexp_table.5.html">regexp_table(5)</a> format of POSIX regular expression tables
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
        Wietse Venema
        IBM T.J. Watson Research
        P.O. Box 704
+
+
+
+                                                                3
+
+
+
+
+
+TRANSPORT(5)                                         TRANSPORT(5)
+
+
        Yorktown Heights, NY 10598, USA
 
 
 
 
 
-                                                                3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                4
 
 
 </pre> </body> </html>
index 6e3daa2abd5624cb991803059be113ce117d3f4d..5f606500663cdcbfb3e9aa84e56229fa2d7734e6 100644 (file)
@@ -43,6 +43,7 @@ VIRTUAL(5)                                             VIRTUAL(5)
        lowing:
 
            <i>virtual.domain</i>       <i>anything</i> (right-hand content does not matter)
+           <i>postmaster@virtual.domain</i>    <i>postmaster</i>
            <i>user1@virtual.domain</i> <i>address1</i>
            <i>user2@virtual.domain</i> <i>address2,</i> <i>address3</i>
 
@@ -57,8 +58,7 @@ VIRTUAL(5)                                             VIRTUAL(5)
               Blank  lines  are  ignored,  as are lines beginning
               with `#'.
 
-       <i>pattern</i> <i>result</i>
-              When <i>pattern</i> matches a mail address, replace it  by
+
 
 
 
@@ -71,6 +71,8 @@ VIRTUAL(5)                                             VIRTUAL(5)
 VIRTUAL(5)                                             VIRTUAL(5)
 
 
+       <i>pattern</i> <i>result</i>
+              When <i>pattern</i> matches a mail address, replace it  by
               the corresponding <i>result</i>.
 
        With lookups from indexed files such as DB or DBM, or from
@@ -124,8 +126,6 @@ VIRTUAL(5)                                             VIRTUAL(5)
        table,  until  a  pattern is found that matches the search
        string.
 
-       Results are the same as with normal indexed file  lookups,
-
 
 
                                                                 2
@@ -137,6 +137,7 @@ VIRTUAL(5)                                             VIRTUAL(5)
 VIRTUAL(5)                                             VIRTUAL(5)
 
 
+       Results are the same as with normal indexed file  lookups,
        with  the additional feature that parenthesized substrings
        from the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so  on.
 
@@ -193,7 +194,6 @@ VIRTUAL(5)                                             VIRTUAL(5)
 
 
 
-
                                                                 3
 
 
index 4db8441739aae2d426a99e5c7e999c7250d4c96b..dbc7bc0f6140eb863c3de86199ba35376a30fbf4 100644 (file)
@@ -158,6 +158,12 @@ static int deliver_switch(LOCAL_STATE state, USER_ATTR usr_attr)
        && strcasecmp(state.msg_attr.owner, state.msg_attr.user) != 0)
        return (deliver_indirect(state));
 
+    /*
+     * Always forward recipients in :include: files.
+     */
+    if (state.msg_attr.exp_type = EXPAND_TYPE_INCL)
+       return (deliver_indirect(state));
+
     /*
      * Delivery to local user. First try expansion of the recipient's
      * $HOME/.forward file, then mailbox delivery.
index 12fa3c2736b7dc4c79d0fe63bab51a438ba87473..97cafb5642e79185051c91ea187f0331f3541894 100644 (file)
@@ -70,6 +70,7 @@ can also be used with IP addresses instead of hostnames.
 .na
 .nf
 .ad
+.fi
 In order to send mail for \fBfoo.org\fR and its subdomains
 via the \fBuucp\fR transport to the UUCP host named \fBfoo\fR:
 
index e03f6d7da1d972f64fd02a0d6586bc990816e2bb..092ef209cd3408bfab9457bc76e410684fee2120 100644 (file)
@@ -43,6 +43,7 @@ Typical support for a virtual domain looks like the following:
 .in +4
 .nf
 \fIvirtual.domain       anything\fR (right-hand content does not matter)
+\fIpostmaster@virtual.domain    postmaster\fR
 \fIuser1@virtual.domain address1\fR
 \fIuser2@virtual.domain address2, address3\fR
 .fi
index 65ce68a8c13df6904e98e7ffdba21e4a177065f9..13a5696747d6c1afddaeb054a2925cbc3cebc893 100644 (file)
@@ -41,8 +41,7 @@ when preceded by a blank line.
 .IP \fBF\fR
 Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
 the message content.
-This is expected by, for example, \fBUUCP\fR software. The \fBF\fR
-flag also causes an empty line to be appended to the message.
+This is expected by, for example, \fBUUCP\fR software.
 .IP \fBR\fR
 Prepend a \fBReturn-Path:\fR message header with the envelope sender
 address.
index 2942eb9ff6dfb2611accce945ba41894774303a0..bcf367a204424793eb0a4302799a9f337f3d628a 100644 (file)
@@ -72,8 +72,6 @@ a configuration change.
 .SH Miscellaneous
 .ad
 .fi
-.IP \fBappend_dot_mydomain\fR
-Rewrite \fIuser\fR@\fIhost\fR to \fIuser\fR@\fIhost\fR.$\fBmydomain\fR.
 .IP \fBbest_mx_transport\fR
 Name of the delivery transport to use when the local machine
 is the most-preferred mail exchanger (by default, a mailer
index e85e328f149c486bf119d3332447c9522e02fc99..2a777833e9c08294ef6ff9565038ada17c948c8f 100644 (file)
@@ -33,8 +33,7 @@
 /* .IP \fBF\fR
 /*     Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
 /*     the message content.
-/*     This is expected by, for example, \fBUUCP\fR software. The \fBF\fR
-/*     flag also causes an empty line to be appended to the message.
+/*     This is expected by, for example, \fBUUCP\fR software.
 /* .IP \fBR\fR
 /*     Prepend a \fBReturn-Path:\fR message header with the envelope sender
 /*     address.
index 3ff29848926de565930f15deba884a34418a25b8..e38e183fcadd4f3a6c51541458fc7b690fad8369 100644 (file)
@@ -263,6 +263,12 @@ static void postalias(char *map_type, char *path_name,
        mkmap_append(mkmap, STR(key_buffer), STR(value_buffer));
     }
 
+    /*
+     * Update or append sendmail and NIS signatures.
+     */
+    if ((open_flags & O_TRUNC) == 0)
+       mkmap->dict->flags |= DICT_FLAG_DUP_REPLACE;
+
     /*
      * Sendmail compatibility: add the @:@ signature to indicate that the
      * database is complete. This might be needed by NIS clients running
@@ -328,7 +334,7 @@ static int postalias_delete(const char *map_type, const char *map_name,
     dict = dict_open3(map_type, map_name, O_RDWR, DICT_FLAG_LOCK);
     status = dict_del(dict, key);
     dict_close(dict);
-    return (status);
+    return (status == 0);
 }
 
 /* usage - explain */
index 0905cd58362a27b6b4ad66220d2f22ce1f1293ae..81fd357333ecbccc79120b8f2ca429e27322d53a 100644 (file)
@@ -60,6 +60,7 @@
 #      can also be used with IP addresses instead of hostnames.
 # EXAMPLES
 # .ad
+# .fi
 #      In order to send mail for \fBfoo.org\fR and its subdomains
 #      via the \fBuucp\fR transport to the UUCP host named \fBfoo\fR:
 #
index c7dfc70a5acc973d70a06b19f0ce57e8f3be8f62..1b706dffe6b2bac1761b081b0fcdaf89f465c333 100644 (file)
@@ -35,6 +35,7 @@
 # .in +4
 # .nf
 #      \fIvirtual.domain       anything\fR (right-hand content does not matter)
+#      \fIpostmaster@virtual.domain    postmaster\fR
 #      \fIuser1@virtual.domain address1\fR
 #      \fIuser2@virtual.domain address2, address3\fR
 # .fi
index 5a5b30b20dc0d8d2f80b201da22b42eeabe148fa..d9d54357e852b83a56273251fc4b6ef0fde5f915 100644 (file)
@@ -56,8 +56,6 @@
 /* .SH Miscellaneous
 /* .ad
 /* .fi
-/* .IP \fBappend_dot_mydomain\fR
-/*     Rewrite \fIuser\fR@\fIhost\fR to \fIuser\fR@\fIhost\fR.$\fBmydomain\fR.
 /* .IP \fBbest_mx_transport\fR
 /*     Name of the delivery transport to use when the local machine
 /*     is the most-preferred mail exchanger (by default, a mailer
@@ -241,7 +239,6 @@ char   *var_smtp_sasl_opts;
 char   *var_smtp_sasl_passwd;
 bool    var_smtp_sasl_enable;
 char   *var_smtp_bind_addr;
-bool    var_append_dot_mydomain;
 
  /*
   * Global variables. smtp_errno is set by the address lookup routines and by
@@ -411,7 +408,6 @@ int     main(int argc, char **argv)
        VAR_SKIP_QUIT_RESP, DEF_SKIP_QUIT_RESP, &var_skip_quit_resp,
        VAR_SMTP_ALWAYS_EHLO, DEF_SMTP_ALWAYS_EHLO, &var_smtp_always_ehlo,
        VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
-       VAR_APP_DOT_MYDOMAIN, DEF_APP_DOT_MYDOMAIN, &var_append_dot_mydomain,
        0,
     };
 
index f92fb24771a8e5fe9c76b96c5d36a1c16b46a67b..91cf6f9897ffb8162a2402b950fd80add65698c8 100644 (file)
 #include <vstring.h>
 #include <msg.h>
 
-/* Global library. */
-
-#include <mail_params.h>
-
 /* DNS library. */
 
 #include <dns.h>
@@ -77,11 +73,8 @@ const char *smtp_unalias_name(const char *name)
      * after servicing a limited number of requests, so there is no need to
      * prevent the cache from growing too large, or to expire old entries.
      */
-    if (cache == 0) {
+    if (cache == 0)
        cache = htable_create(10);
-       if (var_append_dot_mydomain == 0)
-           smtp_unalias_flags |= RES_DNSRCH;
-    }
 
     /*
      * Look up the fqdn. If none is found use the query name instead, so that
index 8e762f41fcdcac6ec5ac58956097447621336768..8b983455461f71288bf1fb529455707ef9d5827e 100644 (file)
@@ -176,10 +176,12 @@ char   *smtpd_sasl_mail_opt(SMTPD_STATE *state, const char *addr)
        state->error_mask |= MAIL_ERROR_PROTOCOL;
        return ("503 Error: authentication disabled");
     }
+#if 0
     if (state->sasl_username == 0) {
        state->error_mask |= MAIL_ERROR_PROTOCOL;
        return ("503 Error: send AUTH command first");
     }
+#endif
     if (state->sasl_sender != 0) {
        state->error_mask |= MAIL_ERROR_PROTOCOL;
        return ("503 Error: multiple AUTH= options");
index 1cb4b1504b8bf95582cc6cf3abde58e02e3a1d1f..a862a5f2ced487743ca4809b281edb8bc5be49eb 100644 (file)
 /* DESCRIPTION
 /*     dict_tcp_open() makes a TCP server accessible via the generic
 /*     dictionary operations described in dict_open(3).
-/*     The \fIdummy\fR argument is not used. Server access is read-only
-/*     (i.e., only lookups are implemented).
+/*     The \fIdummy\fR argument is not used. The only implemented
+/*     operation is dictionary lookup.
 /*
 /*     Map names have the form host:port.
 /*
-/*     The map implements a very simple protocol: the query is sent as
-/*     one line of text, and the reply is sent back in the same format.
-/*     Data is sent as a newline-terminated string. % and non-printable
-/*     characters are replaced by %xx, xx being the corresponding
-/*     hexadecimal value.
+/*     The TCP map class implements a very simple protocol: a query is sent
+/*     as one line of text, and a reply is sent back in the same format.
+/*     % and non-printable characters are replaced by %xx, xx being the
+/*     corresponding hexadecimal value.
 /* SEE ALSO
 /*     dict(3) generic dictionary manager
+/*     hex_quote(3) http-style quoting
 /* DIAGNOSTICS
 /*     Fatal errors: out of memory, unknown host or service name,
-/*     attempt to update map.
+/*     attempt to update or iterate over map.
 /* LICENSE
 /* .ad
 /* .fi
@@ -63,8 +63,8 @@
 typedef struct {
     DICT    dict;                      /* generic members */
     char   *map;                       /* server host:port */
-    VSTRING *raw_buf;                  /* raw buffer */
-    VSTRING *hex_buf;                  /* hexified buffer */
+    VSTRING *raw_buf;                  /* raw I/O buffer */
+    VSTRING *hex_buf;                  /* quoted I/O buffer */
     VSTREAM *fp;                       /* I/O stream */
 } DICT_TCP;
 
@@ -73,12 +73,48 @@ typedef struct {
 
 #define STR(x)         vstring_str(x)
 
+/* dict_tcp_connect - connect to TCP server */
+
+static int dict_tcp_connect(DICT_TCP *dict_tcp)
+{
+    int     fd;
+
+    /*
+     * Connect to the server. Enforce a time limit on read/write operations
+     * so that we do not get stuck.
+     */
+    if ((fd = inet_connect(dict_tcp->map, BLOCKING, 0)) < 0) {
+       msg_warn("connect to TCP map %s: %m", dict_tcp->map);
+       return (-1);
+    }
+    dict_tcp->fp = vstream_fdopen(fd, O_RDWR);
+    vstream_control(dict_tcp->fp,
+                   VSTREAM_CTL_TIMEOUT, DICT_TCP_TMOUT,
+                   VSTREAM_CTL_END);
+
+    /*
+     * Allocate per-map I/O buffers on the fly.
+     */
+    if (dict_tcp->raw_buf == 0) {
+       dict_tcp->raw_buf = vstring_alloc(10);
+       dict_tcp->hex_buf = vstring_alloc(10);
+    }
+    return (0);
+}
+
+/* dict_tcp_disconnect - disconnect from TCP server */
+
+static void dict_tcp_disconnect(DICT_TCP *dict_tcp)
+{
+    (void) vstream_fclose(dict_tcp->fp);
+    dict_tcp->fp = 0;
+}
+
 /* dict_tcp_lookup - query TCP server */
 
 static const char *dict_tcp_lookup(DICT *dict, const char *key)
 {
     DICT_TCP *dict_tcp = (DICT_TCP *) dict;
-    int     fd;
     int     i;
 
     dict_errno = 0;
@@ -86,7 +122,7 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
     for (i = 0; /* see below */ ; i++) {
 
        /*
-        * Try to connect a few times before giving up.
+        * Try to connect a limited number of times before giving up.
         */
        if (i >= DICT_TCP_MAXTRY) {
            dict_errno = DICT_ERR_RETRY;
@@ -94,36 +130,22 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
        }
 
        /*
-        * Sleep between connection attempts.
+        * Sleep between attempts, instead of hammering the server.
         */
        if (i > 0)
            sleep(1);
 
        /*
-        * Try to connect to the server.
+        * Connect to the server.
         */
-       if (dict_tcp->fp == 0) {
-           if ((fd = inet_connect(dict_tcp->map, BLOCKING, 0)) < 0) {
-               msg_warn("connect to TCP map %s: %m", dict_tcp->map);
+       if (dict_tcp->fp == 0)
+           if (dict_tcp_connect(dict_tcp) < 0)
                continue;
-           }
-           dict_tcp->fp = vstream_fdopen(fd, O_RDWR);
-           vstream_control(dict_tcp->fp,
-                           VSTREAM_CTL_TIMEOUT, DICT_TCP_TMOUT,
-                           VSTREAM_CTL_END);
-       }
-
-       /*
-        * Allocate per-map buffers on the fly.
-        */
-       if (dict_tcp->raw_buf == 0) {
-           dict_tcp->raw_buf = vstring_alloc(10);
-           dict_tcp->hex_buf = vstring_alloc(10);
-       }
 
        /*
         * Send query and receive response. Both are %XX quoted and both are
-        * terminated by newline.
+        * terminated by newline. This encoding is convenient for data that
+        * is mostly text.
         */
        hex_quote(dict_tcp->hex_buf, key);
        vstream_fprintf(dict_tcp->fp, "%s\n", STR(dict_tcp->hex_buf));
@@ -140,8 +162,7 @@ static const char *dict_tcp_lookup(DICT *dict, const char *key)
        /*
         * That did not work. Clean up and try again.
         */
-       (void) vstream_fclose(dict_tcp->fp);
-       dict_tcp->fp = 0;
+       dict_tcp_disconnect(dict_tcp);
     }
 }
 
@@ -154,6 +175,25 @@ static void dict_tcp_update(DICT *dict, const char *unused_name, const char *unu
     msg_fatal("dict_tcp_update: attempt to update map %s", dict_tcp->map);
 }
 
+/* dict_tcp_delete - remove table entry */
+
+static int dict_tcp_delete(DICT *dict, const char *unused_name)
+{
+    DICT_TCP *dict_tcp = (DICT_TCP *) dict;
+
+    msg_fatal("dict_tcp_delete: attempt to update map %s", dict_tcp->map);
+}
+
+/* dict_tcp_sequence - iterate over table */
+
+static int dict_tcp_sequence(DICT *dict, int unused_func,
+                       const char **unused_name, const char **unused_value)
+{
+    DICT_TCP *dict_tcp = (DICT_TCP *) dict;
+
+    msg_fatal("dict_tcp_sequence: attempt to iterate map %s", dict_tcp->map);
+}
+
 /* dict_tcp_close - close TCP map */
 
 static void dict_tcp_close(DICT *dict)
@@ -183,6 +223,8 @@ DICT   *dict_tcp_open(const char *map, int unused_flags, int dict_flags)
     dict_tcp->raw_buf = dict_tcp->hex_buf = 0;
     dict_tcp->dict.lookup = dict_tcp_lookup;
     dict_tcp->dict.update = dict_tcp_update;
+    dict_tcp->dict.delete = dict_tcp_delete;
+    dict_tcp->dict.sequence = dict_tcp_sequence;
     dict_tcp->dict.close = dict_tcp_close;
     dict_tcp->dict.fd = -1;
     dict_tcp->map = mystrdup(map);