2003052[3-9]
+ Cleanup: qmgr_fudge_factor is gone.
+
Cleanup: rewrote the queue file record processing loops in
cleanup and in [n]qmgr. This code had deteriorated a lot
as the result of small changes over the years. This change
Compatibility: allow <@site,@site:address> route addresses
in SMTP commands. File: smtpd/smtpd.c.
+20030605
+
+ Cleanup: input checks moved from the pickup daemon to the
+ postdrop mail submission command; this is to prepare for
+ mail submission from postdrop->cleanup without going through
+ the maildrop directory. Files: pickup/pickup.c,
+ postdrop/postdrop.c.
+
+ Bugfix: the "dead host" backoff timer in the MySQL client
+ didn't work. Fix by Leandro Santi. File: util/dict_mysql.c.
+
+ Bugfix: same problem in the PostgreSQL client. File:
+ util/dict_pgsql.c.
+
+ Workaround: turned off non-blocking write to pipe because
+ too many systems give a weird write() result. File:
+ global/pipe_command.c.
+
+ Cleanup: added support for vstream_fseek(.., .., SEEK_END).
+ File: util/vstream.c.
+
Open problems:
Low: smtp-source may block when sending large test messages.
maps, and the mailbox location map can specify either mailbox or
maildir delivery (controlled by trailing slash on mailbox name).
-The agent allows but ignores user+foo address extensions, does not
+The agent does support user+foo address extensions, but does not
support aliases or .forward files (use the virtual table instead),
and therefore doesn't support file or program aliases. This choice
was made to simplify and streamline the code (it allowed me to
In a lookup table, specify a left-hand side of @domain.tld to
match any user in the specified domain that does not have her
own user@domain.tld entry. While searching a lookup table, an
- address extension (user+foo@domain.tld) is ignored.
+ extended address (user+foo@domain.tld) is searched before the
+ bare address (user@domain.tld).
If a recipient is not found the mail is returned to the sender.
The mailbox location is controlled by the <b>virtual</b><i>_</i><b>mail-</b>
<b>box</b><i>_</i><b>base</b> and <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>maps</b> configuration parameters
(see below). The <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>maps</b> table is indexed by
- the full recipient address.
+ the recipient address as described under TABLE SEARCH
+ ORDER below.
The mailbox pathname is constructed as follows:
where <i>recipient</i> is the full recipient address.
<b>UNIX</b> <b>MAILBOX</b> <b>FORMAT</b>
- When the mailbox location does not end in <b>/</b>, the message
- is delivered in UNIX mailbox format. This format stores
+ When the mailbox location does not end in <b>/</b>, the message
+ is delivered in UNIX mailbox format. This format stores
multiple messages in one textfile.
- The <b>virtual</b> delivery agent prepends a "<b>From</b> <i>sender</i>
- <i>time_stamp</i>" envelope header to each message, prepends a
- <b>Delivered-To:</b> message header with the envelope recipient
+ The <b>virtual</b> delivery agent prepends a "<b>From</b> <i>sender</i>
+ <i>time_stamp</i>" envelope header to each message, prepends a
+ <b>Delivered-To:</b> message header with the envelope recipient
address, prepends an <b>X-Original-To:</b> header with the recip-
- ient address as given to Postfix, prepends a <b>Return-Path:</b>
- message header with the envelope sender address, prepends
+ ient address as given to Postfix, prepends a <b>Return-Path:</b>
+ message header with the envelope sender address, prepends
a > character to lines beginning with "<b>From</b> ", and appends
an empty line.
- The mailbox is locked for exclusive access while delivery
+ The mailbox is locked for exclusive access while delivery
is in progress. In case of problems, an attempt is made to
truncate the mailbox to its original length.
<b>QMAIL</b> <b>MAILDIR</b> <b>FORMAT</b>
When the mailbox location ends in <b>/</b>, the message is deliv-
- ered in qmail <b>maildir</b> format. This format stores one mes-
+ ered in qmail <b>maildir</b> format. This format stores one mes-
sage per file.
The <b>virtual</b> delivery agent daemon prepends a <b>Delivered-To:</b>
- message header with the final envelope recipient address,
+ message header with the final envelope recipient address,
prepends an <b>X-Original-To:</b> header with the recipient
- address as given to Postfix, and prepends a <b>Return-Path:</b>
+ address as given to Postfix, and prepends a <b>Return-Path:</b>
message header with the envelope sender address.
- By definition, <b>maildir</b> format does not require file lock-
+ By definition, <b>maildir</b> format does not require file lock-
ing during mail delivery or retrieval.
<b>MAILBOX</b> <b>OWNERSHIP</b>
- Mailbox ownership is controlled by the <b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>
+ Mailbox ownership is controlled by the <b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>
and <b>virtual</b><i>_</i><b>gid</b><i>_</i><b>maps</b> lookup tables, which are indexed with
- the full recipient address. Each table provides a string
+ the full recipient address. Each table provides a string
with the numerical user and group ID, respectively.
The <b>virtual</b><i>_</i><b>minimum</b><i>_</i><b>uid</b> parameter imposes a lower bound on
numerical user ID values that may be specified in any <b>vir-</b>
<b>tual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>.
+<b>TABLE</b> <b>SEARCH</b> <b>ORDER</b>
+ Normally, a lookup table is specified as a text file that
+ serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The result, an
+ indexed file in <b>dbm</b> or <b>db</b> format, is used for fast search-
+ ing by the mail system.
+
+ The canonical search order is as follows. The search stops
+ upon the first successful lookup.
+
+ <b>o</b> When the recipient has an optional address exten-
+ sion the <i>user+extension@domain.tld</i> address is
+ looked up first.
+
+ <b>o</b> The <i>user@domain.tld</i> address, without address exten-
+ sion, is looked up next.
+
+ <b>o</b> Finally, the recipient <i>@domain</i> is looked up.
+
+ When the table is provided via other means such as NIS,
+ LDAP or SQL, the same lookups are done as for ordinary
+ indexed files.
+
+ Alternatively, a table can be provided as a regular-
+ expression map where patterns are given as regular expres-
+ sions. In that case, only the full recipient address is
+ given to the regular-expression map.
+
<b>SECURITY</b>
The virtual delivery agent is not security sensitive, pro-
- vided that the lookup tables with recipient user/group ID
- information are adequately protected. This program is not
+ vided that the lookup tables with recipient user/group ID
+ information are adequately protected. This program is not
designed to run chrooted.
<b>STANDARDS</b>
recipient is over disk quota. In all other cases, mail for
an existing recipient is deferred and a warning is logged.
- Problems and transactions are logged to <b>syslogd</b>(8). Cor-
- rupted message files are marked so that the queue manager
+ Problems and transactions are logged to <b>syslogd</b>(8). Cor-
+ rupted message files are marked so that the queue manager
can move them to the <b>corrupt</b> queue afterwards.
- Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
- the postmaster is notified of bounces and of other trou-
+ Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
+ the postmaster is notified of bounces and of other trou-
ble.
<b>BUGS</b>
- This delivery agent silently ignores address extensions.
+ This delivery agent supports address extensions in email
+ addresses and in lookup table keys, but does not propagate
+ address extension information to the result of table
+ lookup.
Postfix should have lookup tables that can return multiple
result attributes. In order to avoid the inconvenience of
<b>virtual</b><i>_</i><b>minimum</b><i>_</i><b>uid</b>
Specifies a minimum uid that will be accepted as a
- return from a <b>virtual</b><i>_</i><b>owner</b><i>_</i><b>maps</b> or <b>vir-</b>
- <b>tual</b><i>_</i><b>uid</b><i>_</i><b>maps</b> lookup. Returned values less than
- this will be rejected, and the message will be
- deferred.
+ return from a <b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b> lookup. Returned
+ values less than this will be rejected, and the
+ message will be deferred.
<b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>
Recipients are looked up in these maps to determine
- the user ID to be used when writing to the target
+ the user ID to be used when writing to the target
mailbox.
- While searching a lookup table, an address exten-
+ While searching a lookup table, an address exten-
sion (<i>user+foo@domain.tld</i>) is ignored.
- In a lookup table, specify a left-hand side of
- <i>@domain.tld</i> to match any user in the specified
- domain that does not have a specific
+ In a lookup table, specify a left-hand side of
+ <i>@domain.tld</i> to match any user in the specified
+ domain that does not have a specific
<i>user@domain.tld</i> entry.
- For security reasons, regular expression maps are
- allowed but regular expression substitution of $1
+ For security reasons, regular expression maps are
+ allowed but regular expression substitution of $1
etc. is disallowed, because that would open a secu-
rity hole.
- For security reasons, proxied table lookup is not
+ For security reasons, proxied table lookup is not
allowed, because that would open a security hole.
<b>virtual</b><i>_</i><b>gid</b><i>_</i><b>maps</b>
Recipients are looked up in these maps to determine
- the group ID to be used when writing to the target
+ the group ID to be used when writing to the target
mailbox.
- While searching a lookup table, an address exten-
+ While searching a lookup table, an address exten-
sion (<i>user+foo@domain.tld</i>) is ignored.
- In a lookup table, specify a left-hand side of
- <i>@domain.tld</i> to match any user in the specified
- domain that does not have a specific
+ In a lookup table, specify a left-hand side of
+ <i>@domain.tld</i> to match any user in the specified
+ domain that does not have a specific
<i>user@domain.tld</i> entry.
- For security reasons, regular expression maps are
- allowed but regular expression substitution of $1
+ For security reasons, regular expression maps are
+ allowed but regular expression substitution of $1
etc. is disallowed, because that would open a secu-
rity hole.
- For security reasons, proxied table lookup is not
+ For security reasons, proxied table lookup is not
allowed, because that would open a security hole.
<b>Locking</b> <b>controls</b>
<b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>lock</b>
- How to lock UNIX-style mailboxes: one or more of
- <b>flock</b>, <b>fcntl</b> or <b>dotlock</b>. The <b>dotlock</b> method
- requires that the recipient UID or GID has write
+ How to lock UNIX-style mailboxes: one or more of
+ <b>flock</b>, <b>fcntl</b> or <b>dotlock</b>. The <b>dotlock</b> method
+ requires that the recipient UID or GID has write
access to the parent directory of the mailbox file.
- This setting is ignored with <b>maildir</b> style deliv-
+ This setting is ignored with <b>maildir</b> style deliv-
ery, because such deliveries are safe without
explicit locks.
- Use the command <b>postconf</b> <b>-l</b> to find out what lock-
+ Use the command <b>postconf</b> <b>-l</b> to find out what lock-
ing methods are available on your system.
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
- Limit the number of attempts to acquire an exclu-
+ Limit the number of attempts to acquire an exclu-
sive lock on a UNIX-style mailbox file.
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
Time (default: seconds) between successive attempts
- to acquire an exclusive lock on a UNIX-style mail-
- box file. The actual delay is slightly randomized.
+ to acquire an exclusive lock on a UNIX-style mail-
+ box file. The actual delay is slightly randomized.
<b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
- Limit the time after which a stale lockfile is
- removed (applicable to UNIX-style mailboxes only).
+ Limit the time after which a stale lockfile is
+ removed (applicable to UNIX-style mailboxes only).
<b>Resource</b> <b>controls</b>
<b>virtual</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
Limit the number of parallel deliveries to the same
domain via the <b>virtual</b> delivery agent. The default
limit is taken from the <b>default</b><i>_</i><b>destination</b><i>_</i><b>concur-</b>
- <b>rency</b><i>_</i><b>limit</b> parameter. The limit is enforced by
+ <b>rency</b><i>_</i><b>limit</b> parameter. The limit is enforced by
the Postfix queue manager.
<b>virtual</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
Limit the number of recipients per message delivery
- via the <b>virtual</b> delivery agent. The default limit
- is taken from the <b>default</b><i>_</i><b>destination</b><i>_</i><b>recipi-</b>
- <b>ent</b><i>_</i><b>limit</b> parameter. The limit is enforced by the
+ via the <b>virtual</b> delivery agent. The default limit
+ is taken from the <b>default</b><i>_</i><b>destination</b><i>_</i><b>recipi-</b>
+ <b>ent</b><i>_</i><b>limit</b> parameter. The limit is enforced by the
Postfix queue manager.
<b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>limit</b>
- The maximal size in bytes of a mailbox or maildir
+ The maximal size in bytes of a mailbox or maildir
file. Set to zero to disable the limit.
<b>HISTORY</b>
- This agent was originally based on the Postfix local
+ This agent was originally based on the Postfix local
delivery agent. Modifications mainly consisted of removing
- code that either was not applicable or that was not safe
- in this context: aliases, ~user/.forward files, delivery
+ code that either was not applicable or that was not safe
+ in this context: aliases, ~user/.forward files, delivery
to "|command" or to /file/name.
- The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
+ The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
Daniel Bernstein.
- The <b>maildir</b> structure appears in the <b>qmail</b> system by
+ The <b>maildir</b> structure appears in the <b>qmail</b> system by
Daniel Bernstein.
<b>SEE</b> <b>ALSO</b>
<a href="qmgr.8.html">qmgr(8)</a> queue manager
<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>
.fi
The mailbox location is controlled by the \fBvirtual_mailbox_base\fR
and \fBvirtual_mailbox_maps\fR configuration parameters (see below).
-The \fBvirtual_mailbox_maps\fR table is indexed by the full recipient
-address.
+The \fBvirtual_mailbox_maps\fR table is indexed by the recipient
+address as described under TABLE SEARCH ORDER below.
The mailbox pathname is constructed as follows:
The \fBvirtual_minimum_uid\fR parameter imposes a lower bound on
numerical user ID values that may be specified in any
\fBvirtual_uid_maps\fR.
+.SH TABLE SEARCH ORDER
+.na
+.nf
+.ad
+.fi
+Normally, a lookup table is specified as a text file that
+serves as input to the \fBpostmap\fR(1) command. The result, an
+indexed file in \fBdbm\fR or \fBdb\fR format, is used for fast
+searching by the mail system.
+
+The canonical search order is as follows. The search stops
+upon the first successful lookup.
+.IP \(bu
+When the recipient has an optional address extension the
+\fIuser+extension@domain.tld\fR address is looked up first.
+.IP \(bu
+The \fIuser@domain.tld\fR address, without address extension,
+is looked up next.
+.IP \(bu
+Finally, the recipient \fI@domain\fR is looked up.
+.PP
+When the table is provided via other means such as NIS, LDAP
+or SQL, the same lookups are done as for ordinary indexed files.
+
+Alternatively, a table can be provided as a regular-expression
+map where patterns are given as regular expressions. In that case,
+only the full recipient address is given to the regular-expression
+map.
.SH SECURITY
.na
.nf
.SH BUGS
.ad
.fi
-This delivery agent silently ignores address extensions.
+This delivery agent supports address extensions in email
+addresses and in lookup table keys, but does not propagate
+address extension information to the result of table lookup.
Postfix should have lookup tables that can return multiple result
attributes. In order to avoid the inconvenience of maintaining
configuration parameter.
.IP \fBvirtual_minimum_uid\fR
Specifies a minimum uid that will be accepted as a return from
-a \fBvirtual_owner_maps\fR or \fBvirtual_uid_maps\fR lookup.
+a \fBvirtual_uid_maps\fR lookup.
Returned values less than this will be rejected, and the message
will be deferred.
.IP \fBvirtual_uid_maps\fR
cleanup_envelope.o: ../../include/rec_type.h
cleanup_envelope.o: ../../include/cleanup_user.h
cleanup_envelope.o: ../../include/qmgr_user.h
-cleanup_envelope.o: ../../include/tok822.h
-cleanup_envelope.o: ../../include/resolve_clnt.h
cleanup_envelope.o: ../../include/mail_params.h
-cleanup_envelope.o: ../../include/ext_prop.h
-cleanup_envelope.o: ../../include/mail_addr.h
-cleanup_envelope.o: ../../include/canon_addr.h
cleanup_envelope.o: ../../include/verp_sender.h
cleanup_envelope.o: cleanup.h
cleanup_envelope.o: ../../include/argv.h
cleanup_envelope.o: ../../include/maps.h
cleanup_envelope.o: ../../include/dict.h
+cleanup_envelope.o: ../../include/tok822.h
+cleanup_envelope.o: ../../include/resolve_clnt.h
cleanup_envelope.o: ../../include/been_here.h
cleanup_envelope.o: ../../include/mail_stream.h
cleanup_envelope.o: ../../include/mail_conf.h
cleanup_extracted.o: ../../include/vstring.h
cleanup_extracted.o: ../../include/vbuf.h
cleanup_extracted.o: ../../include/vstream.h
-cleanup_extracted.o: ../../include/argv.h
cleanup_extracted.o: ../../include/mymalloc.h
cleanup_extracted.o: ../../include/nvtable.h
cleanup_extracted.o: ../../include/htable.h
cleanup_extracted.o: ../../include/record.h
cleanup_extracted.o: ../../include/rec_type.h
cleanup_extracted.o: ../../include/mail_params.h
-cleanup_extracted.o: ../../include/ext_prop.h
cleanup_extracted.o: ../../include/mail_proto.h
cleanup_extracted.o: ../../include/iostuff.h
cleanup_extracted.o: ../../include/attr.h
cleanup_extracted.o: cleanup.h
+cleanup_extracted.o: ../../include/argv.h
cleanup_extracted.o: ../../include/maps.h
cleanup_extracted.o: ../../include/dict.h
cleanup_extracted.o: ../../include/tok822.h
#include <rec_type.h>
#include <cleanup_user.h>
#include <qmgr_user.h>
-#include <tok822.h>
#include <mail_params.h>
-#include <ext_prop.h>
-#include <mail_addr.h>
-#include <canon_addr.h>
#include <verp_sender.h>
/* Application-specific. */
*/
if ((state->flags & CLEANUP_FLAG_INRCPT) == 0
&& strchr(REC_TYPE_ENV_RECIPIENT, type) != 0) {
- if ((state->flags & CLEANUP_FLAG_WARN_SEEN) == 0
- && var_delay_warn_time > 0) {
- cleanup_out_format(state, REC_TYPE_WARN, REC_TYPE_WARN_FORMAT,
- (long) var_delay_warn_time);
- }
if (state->sender == 0) {
msg_warn("%s: message rejected: missing sender envelope record",
state->queue_id);
state->errs |= CLEANUP_STAT_BAD;
return;
}
+ if ((state->flags & CLEANUP_FLAG_WARN_SEEN) == 0
+ && var_delay_warn_time > 0) {
+ cleanup_out_format(state, REC_TYPE_WARN, REC_TYPE_WARN_FORMAT,
+ (long) state->time + var_delay_warn_time);
+ }
state->flags |= CLEANUP_FLAG_INRCPT;
}
/*
- * Regular initial envelope record processing.
+ * Initial envelope recipient record processing.
*/
if (type == REC_TYPE_RCPT) {
if (state->sender == 0) { /* protect showq */
state->orig_rcpt = mystrdup(buf);
return;
}
- if (type != REC_TYPE_MESG && (state->flags & CLEANUP_FLAG_INRCPT))
- /* Tell qmgr that recipients are mixed with other information. */
+ if (type == REC_TYPE_MESG) {
+ state->action = cleanup_message;
+ state->flags &= ~CLEANUP_FLAG_INRCPT;
+ return;
+ }
+
+ /*
+ * Initial envelope non-recipient record processing.
+ */
+ if (state->flags & CLEANUP_FLAG_INRCPT)
+ /* Tell qmgr that recipient records are mixed with other information. */
state->qmgr_opts |= QMGR_READ_FLAG_MIXED_RCPT_OTHER;
if (type == REC_TYPE_SIZE)
/* Use our own SIZE record instead. */
myfree(sbuf);
cleanup_out(state, type, buf, len);
return;
- }
- if (type != REC_TYPE_MESG) {
+ } else {
cleanup_out(state, type, buf, len);
return;
}
- state->action = cleanup_message;
- state->flags &= ~CLEANUP_FLAG_INRCPT;
}
#include <msg.h>
#include <vstring.h>
#include <vstream.h>
-#include <argv.h>
#include <mymalloc.h>
#include <nvtable.h>
#include <record.h>
#include <rec_type.h>
#include <mail_params.h>
-#include <ext_prop.h>
#include <mail_proto.h>
/* Application-specific. */
#define STR(x) vstring_str(x)
static void cleanup_extracted_process(CLEANUP_STATE *, int, const char *, int);
+static void cleanup_extracted_finish(CLEANUP_STATE *);
/* cleanup_extracted - initialize extracted segment */
void cleanup_extracted_process(CLEANUP_STATE *state, int type,
const char *buf, int len)
{
- const char myname[] = "cleanup_extracted_process";
const char *encoding;
const char generated_by_cleanup[] = {
REC_TYPE_FILT, REC_TYPE_RDR, REC_TYPE_ATTR,
}
/*
- * At the end of the non-recipient records, emit optional information
- * from header/body content.
+ * On the transition from non-recipient records to recipient records,
+ * emit optional information from header/body content.
*/
if ((state->flags & CLEANUP_FLAG_INRCPT) == 0
&& strchr(REC_TYPE_EXT_RECIPIENT, type) != 0) {
if ((encoding = nvtable_find(state->attr, MAIL_ATTR_ENCODING)) != 0)
cleanup_out_format(state, REC_TYPE_ATTR, "%s=%s",
MAIL_ATTR_ENCODING, encoding);
+ if (state->return_receipt)
+ cleanup_out_string(state, REC_TYPE_RRTO, state->return_receipt);
+ if (state->errors_to)
+ cleanup_out_string(state, REC_TYPE_ERTO, state->errors_to);
state->flags |= CLEANUP_FLAG_INRCPT;
}
/*
- * Regular extracted envelope record processing.
+ * Extracted envelope recipient record processing.
*/
if (type == REC_TYPE_RCPT) {
if (state->sender == 0) { /* protect showq */
state->orig_rcpt = mystrdup(buf);
return;
}
- if (type != REC_TYPE_END && (state->flags & CLEANUP_FLAG_INRCPT))
- /* Tell qmgr that recipients are mixed with other information. */
+ if (type == REC_TYPE_END) {
+ state->flags &= ~CLEANUP_FLAG_INRCPT;
+ state->flags |= CLEANUP_FLAG_END_SEEN;
+ cleanup_extracted_finish(state);
+ return;
+ }
+
+ /*
+ * Extracted envelope non-recipient record processing.
+ */
+ if (state->flags & CLEANUP_FLAG_INRCPT)
+ /* Tell qmgr that recipient records are mixed with other information. */
state->qmgr_opts |= QMGR_READ_FLAG_MIXED_RCPT_OTHER;
if (strchr(generated_by_cleanup, type) != 0) {
/* Use our own header/body info instead. */
return;
- }
- if (type != REC_TYPE_END) {
+ } else {
/* Pass on other non-recipient record. */
cleanup_out(state, type, buf, len);
return;
}
- state->flags &= ~CLEANUP_FLAG_INRCPT;
- state->flags |= CLEANUP_FLAG_END_SEEN;
+}
+
+/* cleanup_extracted_finish - process one extracted envelope record */
+
+void cleanup_extracted_finish(CLEANUP_STATE *state)
+{
+ const char myname[] = "cleanup_extracted_finish";
/*
* On the way out, add the optional automatic BCC recipient.
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20030531"
+#define MAIL_RELEASE_DATE "20030605"
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "2.0.10-" MAIL_RELEASE_DATE
+#define DEF_MAIL_VERSION "2.0.11-" MAIL_RELEASE_DATE
extern char *var_mail_version;
/*
* Turn on non-blocking writes to the child process so that we can enforce
* timeouts after partial writes.
*
- * XXX This breaks on IRIX where select reports that a pipe is writable
- * while write transfers zero bytes.
+ * XXX Too much trouble with different systems returning weird write()
+ * results when a pipe is writable.
*/
if (pipe(cmd_in_pipe) < 0 || pipe(cmd_out_pipe) < 0)
msg_fatal("%s: pipe: %m", myname);
non_blocking(cmd_out_pipe[1], NON_BLOCKING);
-#ifndef BROKEN_WRITE_SELECT_ON_NON_BLOCKING_PIPE
+#if 0
non_blocking(cmd_in_pipe[1], NON_BLOCKING);
#endif
#define REC_TYPE_CONTENT "XLN"
#define REC_TYPE_EXTRACT "EDROPreAFIL>"
+ /*
+ * The subset of inputs that the postdrop command allows.
+ */
+#define REC_TYPE_POST_ENVELOPE "MFSRVA"
+#define REC_TYPE_POST_CONTENT "XLN"
+#define REC_TYPE_POST_EXTRACT "ERA"
+
/*
* The record at the beginning of the envelope segment specifies the message
* content size, data offset, recipient count, and processing flags. These
#define REC_TYPE_SIZE_CAST3 long
#define REC_TYPE_SIZE_CAST4 long
- /*
- * The record at the beginning of the message content records specifies the
- * position of the next record group. This is the format of the position
- * field. It is a fixed-width field so it can be updated in place.
- */
-#define REC_TYPE_MESG_FORMAT "%15ld" /* message length format */
-#define REC_TYPE_MESG_CAST long
-
/*
* The warn record specifies when the next warning that the message was
* deferred should be sent. It is updated in place by qmgr, so changing
{
VSTRING *buf;
long orig_offset,
- curr_offset,
extra_offset;
int rec_type;
char *start;
*/
message->rcpt_unread = 0;
for (;;) {
- if ((curr_offset = vstream_ftell(message->fp)) < 0)
- msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
rec_type = rec_get(message->fp, buf, 0);
if (rec_type <= 0)
/* Report missing end record later. */
* queue file, to protect against memory exhaustion. Recipient records
* may appear before or after the message content, so we keep reading
* from the queue file until we have enough recipients (rcpt_offset != 0)
- * and until we know all the non-recipient extracted segment information.
+ * and until we know all the non-recipient information.
*
* Note that the total recipient count record is accurate only for fresh
* queue files. After some of the recipients are marked as done and the
* XXX We know how to skip over large numbers of recipient records in the
* initial envelope segment but we haven't yet implemented code to skip
* over large numbers of recipient records in the extracted envelope
- * segment. This is not a problem as long as only "sendmail -t" produces
- * extracted segment recipients.
+ * segment. This is not a problem as long as extracted segment recipients
+ * are not mixed with non-recipient information (sendmail -t, qmqpd).
*/
for (;;) {
if ((curr_offset = vstream_ftell(message->fp)) < 0)
#include <vstream.h>
#include <set_ugid.h>
#include <safe_open.h>
-#include <stringops.h>
/* Global library. */
{
int type;
int check_first = (*expected == REC_TYPE_CONTENT[0]);
- const char *error_text;
- char *attr_name;
- char *attr_value;
/*
* Limit the input record size. All front-end programs should protect the
if (type == REC_TYPE_FROM)
if (info->sender == 0)
info->sender = mystrdup(vstring_str(buf));
- if (type == REC_TYPE_ORCP)
- if (info->st.st_uid != var_owner_uid) {
- msg_warn("uid=%ld: ignoring original recipient record: %.200s",
- (long) info->st.st_uid, vstring_str(buf));
- continue;
- }
if (type == REC_TYPE_TIME)
/* Use our own arrival time record instead. */
continue;
- if (type == REC_TYPE_ATTR) {
- if ((error_text = split_nameval(vstring_str(buf), &attr_name,
- &attr_value)) != 0) {
- msg_warn("uid=%ld: malformed attribute record: %s: %.200s",
- (long) info->st.st_uid, error_text, vstring_str(buf));
- continue;
- }
-#define STREQ(x,y) (strcmp(x,y) == 0)
-
- if ((STREQ(attr_name, MAIL_ATTR_ENCODING)
- && (STREQ(attr_value, MAIL_ATTR_ENC_7BIT)
- || STREQ(attr_value, MAIL_ATTR_ENC_8BIT)
- || STREQ(attr_value, MAIL_ATTR_ENC_NONE)))
- || STREQ(attr_name, MAIL_ATTR_TRACE_FLAGS)) { /* XXX */
- rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s",
- attr_name, attr_value);
- } else if (info->st.st_uid != var_owner_uid) {
- msg_warn("uid=%ld: ignoring attribute record: %.200s=%.200s",
- (long) info->st.st_uid, attr_name, attr_value);
- }
- continue;
- }
/*
* 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.
*/
- if (check_first && *expected == REC_TYPE_CONTENT[0]) {
+ if (check_first
+ && (type == REC_TYPE_NORM || type == REC_TYPE_CONT)) {
check_first = 0;
if (VSTRING_LEN(buf) > 0 && IS_SPACE_TAB(vstring_str(buf)[0]))
rec_put(cleanup, REC_TYPE_NORM, "", 0);
#include <msg_syslog.h>
#include <argv.h>
#include <iostuff.h>
+#include <stringops.h>
/* Global library. */
MAIL_STREAM *dst;
int rec_type;
static char *segment_info[] = {
- REC_TYPE_ENVELOPE, REC_TYPE_CONTENT, REC_TYPE_EXTRACT,
+ REC_TYPE_POST_ENVELOPE, REC_TYPE_POST_CONTENT, REC_TYPE_POST_EXTRACT, ""
};
char **expected;
uid_t uid = getuid();
ARGV *import_env;
+ const char *error_text;
+ char *attr_name;
+ char *attr_value;
/*
* Be consistent with file permissions.
*
* If something goes wrong, slurp up the input before responding to the
* client, otherwise the client will give up after detecting SIGPIPE.
+ *
+ * Allow attribute records if the attribute specifies the MIME body type
+ * (sendmail -B).
*/
vstream_control(VSTREAM_IN, VSTREAM_CTL_PATH, "stdin", VSTREAM_CTL_END);
buf = vstring_alloc(100);
msg_fatal("uid=%ld: unexpected record type: %d", (long) uid, rec_type);
if (rec_type == **expected)
expected++;
+ if (rec_type == REC_TYPE_ATTR) {
+ if ((error_text = split_nameval(vstring_str(buf), &attr_name,
+ &attr_value)) != 0) {
+ msg_warn("uid=%ld: ignoring malformed record: %s: %.200s",
+ (long) uid, error_text, vstring_str(buf));
+ continue;
+ }
+#define STREQ(x,y) (strcmp(x,y) == 0)
+
+ if ((STREQ(attr_name, MAIL_ATTR_ENCODING)
+ && (STREQ(attr_value, MAIL_ATTR_ENC_7BIT)
+ || STREQ(attr_value, MAIL_ATTR_ENC_8BIT)
+ || STREQ(attr_value, MAIL_ATTR_ENC_NONE)))
+ || STREQ(attr_name, MAIL_ATTR_TRACE_FLAGS)) { /* XXX */
+ rec_fprintf(dst->stream, REC_TYPE_ATTR, "%s=%s",
+ attr_name, attr_value);
+ } else {
+ msg_warn("uid=%ld: ignoring attribute record: %.200s=%.200s",
+ (long) uid, attr_name, attr_value);
+ }
+ continue;
+ }
if (REC_PUT_BUF(dst->stream, rec_type, buf) < 0) {
while ((rec_type = rec_get(VSTREAM_IN, buf, var_line_limit)) > 0
&& rec_type != REC_TYPE_END)
{
VSTRING *buf;
long orig_offset,
- curr_offset,
extra_offset;
int rec_type;
char *start;
* completely.
*/
for (;;) {
- if ((curr_offset = vstream_ftell(message->fp)) < 0)
- msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
rec_type = rec_get(message->fp, buf, 0);
if (rec_type <= 0)
/* Report missing end record later. */
* queue file, to protect against memory exhaustion. Recipient records
* may appear before or after the message content, so we keep reading
* from the queue file until we have enough recipients (rcpt_offset != 0)
- * and until we know all the non-recipient extracted segment information.
+ * and until we know all the non-recipient information.
*
* When reading recipients from queue file, stop reading when we reach a
* per-message in-core recipient limit rather than a global in-core
* XXX We know how to skip over large numbers of recipient records in the
* initial envelope segment but we haven't yet implemented code to skip
* over large numbers of recipient records in the extracted envelope
- * segment. This is not a problem as long as only "sendmail -t" produces
- * extracted segment recipients.
+ * segment. This is not a problem as long as extracted segment recipients
+ * are not mixed with non-recipient information (sendmail -t, qmqpd).
*/
for (;;) {
if ((curr_offset = vstream_ftell(message->fp)) < 0)
* delivered intact via SMTP. Strip leading From_ lines. For the benefit
* of UUCP environments, also get rid of leading >>>From_ lines.
*/
- rec_fprintf(dst, REC_TYPE_MESG, REC_TYPE_MESG_FORMAT, 0L);
+ rec_fputs(dst, REC_TYPE_MESG, "");
if (DEL_REQ_TRACE_ONLY(flags) != 0) {
rec_fprintf(dst, REC_TYPE_NORM, "Subject: probe");
if (recipients) {
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 %s needs two characters from %s",
+ smtpd_chat_reply(state, "501 Error: %s needs two characters from %s",
VERP_CMD, var_verp_filter);
return (-1);
}
}
}
if (verp_delims && argv[2].strval[0] == 0) {
- smtpd_chat_reply(state, "503 Error: XVERP requires non-null sender");
+ smtpd_chat_reply(state, "503 Error: %s requires non-null sender",
+ VERP_CMD);
return (-1);
}
state->time = time((time_t *) 0);
int defer_if_permit_sender; /* force permit into warning */
int discard; /* discard message */
VSTRING *expand_buf; /* scratch space for $name expansion */
- int session_hold; /* per-session hold action */
- int session_discard; /* per-session discard_action */
- char *session_filter; /* per-session filter action */
- char *session_redirect; /* per-session redirect action */
} SMTPD_STATE;
extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
*/
#define STR vstring_str
#define CONST_STR(x) ((const char *) vstring_str(x))
-#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
-
- /*
- * Safety.
- */
-#define SAFE_STRDUP(dst, src) { \
- if (src) { \
- if (dst) { \
- myfree(dst); \
- } \
- dst = mystrdup(src); \
- } \
- }
/*
* If some decision can't be made due to a temporary error, then change
vstring_sprintf(error_text, "<%s>: %s triggers FILTER %s",
reply_name, reply_class, cmd_text);
log_whatsup(state, "filter", STR(error_text));
- /* This action must execute with every MAIL FROM command. */
- if (var_smtpd_delay_reject == 0
- && (STREQ(reply_class, SMTPD_NAME_CLIENT)
- || STREQ(reply_class, SMTPD_NAME_HELO))) {
- SAFE_STRDUP(state->session_filter, cmd_text);
- } else {
#ifndef TEST
- rec_fprintf(state->dest->stream, REC_TYPE_FILT, "%s", cmd_text);
+ rec_fprintf(state->dest->stream, REC_TYPE_FILT, "%s", cmd_text);
#endif
- }
return (SMTPD_CHECK_DUNNO);
}
}
vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
*cmd_text ? cmd_text : "triggers HOLD action");
log_whatsup(state, "hold", STR(error_text));
- /* This action must execute with every MAIL FROM command. */
- if (var_smtpd_delay_reject == 0
- && (STREQ(reply_class, SMTPD_NAME_CLIENT)
- || STREQ(reply_class, SMTPD_NAME_HELO))) {
- state->session_hold = 1;
- } else {
#ifndef TEST
- rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
- CLEANUP_FLAG_HOLD);
+ rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
+ CLEANUP_FLAG_HOLD);
#endif
- }
return (SMTPD_CHECK_DUNNO);
}
vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
*cmd_text ? cmd_text : "triggers DISCARD action");
log_whatsup(state, "discard", STR(error_text));
- /* This action must execute with every MAIL FROM command. */
- if (var_smtpd_delay_reject == 0
- && (STREQ(reply_class, SMTPD_NAME_CLIENT)
- || STREQ(reply_class, SMTPD_NAME_HELO))) {
- state->session_discard = 1;
- } else {
#ifndef TEST
- rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
- CLEANUP_FLAG_DISCARD);
- state->discard = 1;
+ rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
+ CLEANUP_FLAG_DISCARD);
+ state->discard = 1;
#endif
- }
return (SMTPD_CHECK_OK);
}
vstring_sprintf(error_text, "<%s>: %s triggers REDIRECT %s",
reply_name, reply_class, cmd_text);
log_whatsup(state, "redirect", STR(error_text));
- /* This action must execute with every MAIL FROM command. */
- if (var_smtpd_delay_reject == 0
- && (STREQ(reply_class, SMTPD_NAME_CLIENT)
- || STREQ(reply_class, SMTPD_NAME_HELO))) {
- SAFE_STRDUP(state->session_redirect, cmd_text);
- } else {
#ifndef TEST
- rec_fprintf(state->dest->stream, REC_TYPE_RDR, "%s", cmd_text);
+ rec_fprintf(state->dest->stream, REC_TYPE_RDR, "%s", cmd_text);
#endif
- }
return (SMTPD_CHECK_DUNNO);
}
}
/*
* "sender_name" or "recipient_name".
*/
+#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
+
else if (STREQ(suffix, MAIL_ATTR_S_NAME)) {
if (*addr) {
if ((p = strrchr(addr, '@')) != 0) {
if (sender == 0)
return (0);
- /*
- * Actions that were triggered during connect or HELO need to be repeated
- * with each MAIL FROM command.
- */
- if (var_smtpd_delay_reject == 0) {
-#ifndef TEST
- if (state->session_hold)
- rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
- CLEANUP_FLAG_HOLD);
- if (state->session_discard)
- rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
- CLEANUP_FLAG_DISCARD);
- if (state->session_redirect)
- rec_fprintf(state->dest->stream, REC_TYPE_RDR, "%s",
- state->session_redirect);
- if (state->session_filter)
- rec_fprintf(state->dest->stream, REC_TYPE_FILT, "%s",
- state->session_filter);
-#endif
- }
-
/*
* Minor kluge so that we can delegate work to the generic routine and so
* that we can syslog the recipient with the reject messages.
extern char *smtpd_check_rcpt(SMTPD_STATE *, char *);
extern char *smtpd_check_etrn(SMTPD_STATE *, char *);
extern char *smtpd_check_data(SMTPD_STATE *);
-extern char *smtpd_check_dot(SMTPD_STATE *);
/* LICENSE
/* .ad
state->defer_if_permit.reason = 0;
state->discard = 0;
state->expand_buf = 0;
- state->session_hold = 0;
- state->session_discard = 0;
- state->session_filter = 0;
- state->session_redirect = 0;
#ifdef USE_SASL_AUTH
if (SMTPD_STAND_ALONE(state))
vstring_free(state->defer_if_reject.reason);
if (state->expand_buf)
vstring_free(state->expand_buf);
- if (state->session_filter)
- myfree(state->session_filter);
- if (state->session_redirect)
- myfree(state->session_redirect);
#ifdef USE_SASL_AUTH
if (var_smtpd_sasl_enable)
static PLMYSQL *plmysql_init(char *hostnames[], int);
static MYSQL_RES *plmysql_query(PLMYSQL *, const char *, char *, char *, char *);
static void plmysql_dealloc(PLMYSQL *);
+static void plmysql_close_host(HOST *);
static void plmysql_down_host(HOST *);
static void plmysql_connect_single(HOST *, char *, char *, char *);
static int plmysql_ready_reconn(HOST *);
if (msg_verbose)
msg_info("dict_mysql: closing unnessary connection to %s",
host->hostname);
- plmysql_down_host(host);
+ plmysql_close_host(host);
}
/* try to connect for the first time if we don't have a result yet */
if (res == 0 && host->stat == STATUNTRIED) {
myfree(hostname);
}
+/* plmysql_close_host - close an established MySQL connection */
+static void plmysql_close_host(HOST *host)
+{
+ mysql_close(host->db);
+ host->db = 0;
+ host->stat = STATUNTRIED;
+}
+
/*
- * plmysql_down_host - mark a HOST down update ts if marked down
- * for the first time so that we'll know when to retry the connection
+ * plmysql_down_host - close a failed connection AND set a "stay away from
+ * this host" timer
*/
static void plmysql_down_host(HOST *host)
{
- if (host->stat != STATFAIL) {
- host->ts = time((time_t *) 0) + RETRY_CONN_INTV;
- host->stat = STATFAIL;
- }
mysql_close(host->db);
host->db = 0;
+ host->ts = time((time_t *) 0) + RETRY_CONN_INTV;
+ host->stat = STATFAIL;
}
/**********************************************************************
static PLPGSQL *plpgsql_init(char *hostnames[], int);
static PGSQL_RES *plpgsql_query(PLPGSQL *, const char *, char *, char *, char *);
static void plpgsql_dealloc(PLPGSQL *);
+static void plpgsql_close_host(HOST *);
static void plpgsql_down_host(HOST *);
static void plpgsql_connect_single(HOST *, char *, char *, char *);
static const char *dict_pgsql_lookup(DICT *, const char *);
if (msg_verbose)
msg_info("dict_pgsql: closing unnessary connection to %s",
host->hostname);
- plpgsql_down_host(host);
+ plpgsql_close_host(host);
}
/* try to connect for the first time if we don't have a result yet */
if (res == 0 && host->stat == STATUNTRIED) {
myfree(hostname);
}
+/* plpgsql_close_host - close an established PostgreSQL connection */
+
+static void plpgsql_close_host(HOST *host)
+{
+ PQfinish(host->db);
+ host->db = 0;
+ host->stat = STATUNTRIED;
+}
+
/*
- * plpgsql_down_host - mark a HOST down update ts if marked down
- * for the first time so that we'll know when to retry the connection
+ * plpgsql_down_host - close a failed connection AND set a "stay away from
+ * this host" timer.
*/
static void plpgsql_down_host(HOST *host)
{
- if (host->stat != STATFAIL) {
- host->ts = time((time_t *) 0) + RETRY_CONN_INTV;
- host->stat = STATFAIL;
- }
PQfinish(host->db);
host->db = 0;
+ host->ts = time((time_t *) 0) + RETRY_CONN_INTV;
+ host->stat = STATFAIL;
}
/**********************************************************************
#include "iostuff.h"
/* Backwards compatibility */
-#ifdef FNDELAY
+#ifndef O_NONBLOCK
#define PATTERN FNDELAY
#else
#define PATTERN O_NONBLOCK
if (bp->ptr > bp->data) {
if (whence == SEEK_CUR)
offset += (bp->ptr - bp->data); /* add unwritten data */
+ else if (whence == SEEK_END)
+ bp->flags &= ~VSTREAM_FLAG_SEEK;
if (VSTREAM_FFLUSH_SOME(stream))
return (-1);
}
case VSTREAM_FLAG_READ:
if (whence == SEEK_CUR)
offset += bp->cnt; /* subtract unread data */
+ else if (whence == SEEK_END)
+ bp->flags &= ~VSTREAM_FLAG_SEEK;
case 0:
VSTREAM_BUF_AT_END(bp);
break;
mailbox.o: ../../include/recipient_list.h
mailbox.o: ../../include/sent.h
mailbox.o: ../../include/mail_params.h
-mailbox.o: ../../include/virtual8_maps.h
+mailbox.o: ../../include/mail_addr_find.h
mailbox.o: ../../include/maps.h
mailbox.o: ../../include/dict.h
mailbox.o: ../../include/argv.h
virtual.o: ../../include/deliver_completed.h
virtual.o: ../../include/mail_params.h
virtual.o: ../../include/mail_conf.h
-virtual.o: ../../include/virtual8_maps.h
+virtual.o: ../../include/mail_addr_find.h
virtual.o: ../../include/maps.h
virtual.o: ../../include/mail_server.h
virtual.o: virtual.h
#include <defer.h>
#include <sent.h>
#include <mail_params.h>
-#include <virtual8_maps.h>
+#include <mail_addr_find.h>
#ifndef EDQUOT
#define EDQUOT EFBIG
* Look up the mailbox location. Bounce if not found, defer in case of
* trouble.
*/
- mailbox_res = virtual8_maps_find(virtual_mailbox_maps, state.msg_attr.user);
+#define IGNORE_EXTENSION ((char **) 0)
+
+ mailbox_res = mail_addr_find(virtual_mailbox_maps, state.msg_attr.user,
+ IGNORE_EXTENSION);
if (mailbox_res == 0) {
if (dict_errno == 0)
return (NO);
/*
* Look up the mailbox owner rights. Defer in case of trouble.
*/
- uid_res = virtual8_maps_find(virtual_uid_maps, state.msg_attr.user);
+ uid_res = mail_addr_find(virtual_uid_maps, state.msg_attr.user,
+ IGNORE_EXTENSION);
if (uid_res == 0) {
*statusp = defer_append(BOUNCE_FLAGS(state.request),
BOUNCE_ATTR(state.msg_attr),
/*
* Look up the mailbox group rights. Defer in case of trouble.
*/
- gid_res = virtual8_maps_find(virtual_gid_maps, state.msg_attr.user);
+ gid_res = mail_addr_find(virtual_gid_maps, state.msg_attr.user,
+ IGNORE_EXTENSION);
if (gid_res == 0) {
*statusp = defer_append(BOUNCE_FLAGS(state.request),
BOUNCE_ATTR(state.msg_attr),
/* .fi
/* The mailbox location is controlled by the \fBvirtual_mailbox_base\fR
/* and \fBvirtual_mailbox_maps\fR configuration parameters (see below).
-/* The \fBvirtual_mailbox_maps\fR table is indexed by the full recipient
-/* address.
+/* The \fBvirtual_mailbox_maps\fR table is indexed by the recipient
+/* address as described under TABLE SEARCH ORDER below.
/*
/* The mailbox pathname is constructed as follows:
/*
/* The \fBvirtual_minimum_uid\fR parameter imposes a lower bound on
/* numerical user ID values that may be specified in any
/* \fBvirtual_uid_maps\fR.
+/* TABLE SEARCH ORDER
+/* .ad
+/* .fi
+/* Normally, a lookup table is specified as a text file that
+/* serves as input to the \fBpostmap\fR(1) command. The result, an
+/* indexed file in \fBdbm\fR or \fBdb\fR format, is used for fast
+/* searching by the mail system.
+/*
+/* The canonical search order is as follows. The search stops
+/* upon the first successful lookup.
+/* .IP \(bu
+/* When the recipient has an optional address extension the
+/* \fIuser+extension@domain.tld\fR address is looked up first.
+/* .IP \(bu
+/* The \fIuser@domain.tld\fR address, without address extension,
+/* is looked up next.
+/* .IP \(bu
+/* Finally, the recipient \fI@domain\fR is looked up.
+/* .PP
+/* When the table is provided via other means such as NIS, LDAP
+/* or SQL, the same lookups are done as for ordinary indexed files.
+/*
+/* Alternatively, a table can be provided as a regular-expression
+/* map where patterns are given as regular expressions. In that case,
+/* only the full recipient address is given to the regular-expression
+/* map.
/* SECURITY
/* .ad
/* .fi
/* Depending on the setting of the \fBnotify_classes\fR parameter,
/* the postmaster is notified of bounces and of other trouble.
/* BUGS
-/* This delivery agent silently ignores address extensions.
+/* This delivery agent supports address extensions in email
+/* addresses and in lookup table keys, but does not propagate
+/* address extension information to the result of table lookup.
/*
/* Postfix should have lookup tables that can return multiple result
/* attributes. In order to avoid the inconvenience of maintaining
/* configuration parameter.
/* .IP \fBvirtual_minimum_uid\fR
/* Specifies a minimum uid that will be accepted as a return from
-/* a \fBvirtual_owner_maps\fR or \fBvirtual_uid_maps\fR lookup.
+/* a \fBvirtual_uid_maps\fR lookup.
/* Returned values less than this will be rejected, and the message
/* will be deferred.
/* .IP \fBvirtual_uid_maps\fR
#include <mail_params.h>
#include <mail_conf.h>
#include <mail_params.h>
-#include <virtual8_maps.h>
+#include <mail_addr_find.h>
/* Single server skeleton. */
set_eugid(var_owner_uid, var_owner_gid);
virtual_mailbox_maps =
- virtual8_maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps,
+ maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps,
DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
virtual_uid_maps =
- virtual8_maps_create(VAR_VIRT_UID_MAPS, var_virt_uid_maps,
+ maps_create(VAR_VIRT_UID_MAPS, var_virt_uid_maps,
DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
virtual_gid_maps =
- virtual8_maps_create(VAR_VIRT_GID_MAPS, var_virt_gid_maps,
+ maps_create(VAR_VIRT_GID_MAPS, var_virt_gid_maps,
DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
virtual_mbox_lock_mask = mbox_lock_mask(var_virt_mailbox_lock);