mirror of
https://github.com/vdukhovni/postfix
synced 2025-09-01 06:35:27 +00:00
postfix-3.2-20170122
This commit is contained in:
committed by
Viktor Dukhovni
parent
7a51b3ef05
commit
e69c67e916
@@ -22845,3 +22845,21 @@ Apologies for any names omitted.
|
|||||||
compatibility, for check_sender_access and check_recipient_access.
|
compatibility, for check_sender_access and check_recipient_access.
|
||||||
This now uses 'user@' lookup support in the mail_addr_find()
|
This now uses 'user@' lookup support in the mail_addr_find()
|
||||||
engine. File: global/mail_addr_find.*, smtpd/smtpd_check.c.
|
engine. File: global/mail_addr_find.*, smtpd/smtpd_check.c.
|
||||||
|
|
||||||
|
20170122
|
||||||
|
|
||||||
|
Cleanup: separated the database query form from the address
|
||||||
|
form that is input to mail_addr_find_() or mail_addr_map*(),
|
||||||
|
in attempt to make code more obviously correct. Files:
|
||||||
|
global/mail_addr_find.c, global/mail_addr_map.c.
|
||||||
|
|
||||||
|
Abandoned an experiment that used internal-form queries for
|
||||||
|
all maps, because it would be very difficult to test. The
|
||||||
|
tests inputs would have to compensate for multiple levels
|
||||||
|
of unquoting by postmap, C compilers, or shell interpreters.
|
||||||
|
|
||||||
|
Cleanup: moved the backwards-compatibility lookup strategy
|
||||||
|
(try the external address form first, then the internal
|
||||||
|
address form if it is different) inside the loop that
|
||||||
|
iterates over full and partial address forms. File:
|
||||||
|
global/mail_addr_find.c.
|
||||||
|
@@ -8,15 +8,11 @@ Wish list:
|
|||||||
|
|
||||||
Enable external-form lookups for smtpd access maps.
|
Enable external-form lookups for smtpd access maps.
|
||||||
|
|
||||||
Enable caching in quote_822_local.
|
Convert postalias(1) to store external-form keys, and convert
|
||||||
|
aliases(5) to perform external-first lookup with fallback to
|
||||||
Quoting: in smtp_map11, don't convert to external.
|
internal form, to make it consistent with the rest of Postfix.
|
||||||
|
In several years we may remove the internal-form fallbacks
|
||||||
Make the address substring generation ("strategy") suitable
|
with a compatibility_level safety net.
|
||||||
for dict-based applications such as access(5) maps or local
|
|
||||||
aliases. Either that, or do some serious surgery on the
|
|
||||||
dict-based mechanisms. For access(5) maps this requires a
|
|
||||||
localpart[+ext]@ query that comes after the domain queries.
|
|
||||||
|
|
||||||
In the bounce daemon, set util_utf8_enable if returning an
|
In the bounce daemon, set util_utf8_enable if returning an
|
||||||
SMTPUTF8 message.
|
SMTPUTF8 message.
|
||||||
@@ -37,18 +33,6 @@ Wish list:
|
|||||||
RHS. This will not preserve trailing comments in lines that
|
RHS. This will not preserve trailing comments in lines that
|
||||||
are modified with "postconf -e" and the like.
|
are modified with "postconf -e" and the like.
|
||||||
|
|
||||||
The cleanup daemon searches canonical_maps and virtual_alias_maps
|
|
||||||
with quoted address forms. The address local part should
|
|
||||||
be in unquoted form before it is split into name and
|
|
||||||
extension. Note, however, that although quoting is done
|
|
||||||
over the entire localpart, unquoting is not simply a matter
|
|
||||||
of removing the outer quotes. The fix will require careful
|
|
||||||
consideration of the responsibilities of mail_addr_map(),
|
|
||||||
mail_addr_find(), and mail_addr_crunch(), and making sure
|
|
||||||
that the callers can handle quoted results. For example,
|
|
||||||
sender_bcc_maps and recipient_bcc_maps invoke mail_addr_find()
|
|
||||||
with unquoted forms and expects an unquoted result, and so on.
|
|
||||||
|
|
||||||
Maintainability: replace lengthy libmilter-API argument lists
|
Maintainability: replace lengthy libmilter-API argument lists
|
||||||
with named parameters, as with the libtls API.
|
with named parameters, as with the libtls API.
|
||||||
|
|
||||||
|
@@ -46,7 +46,8 @@ POSTMAP(1) POSTMAP(1)
|
|||||||
|
|
||||||
When the <i>key</i> specifies email address information, the localpart should
|
When the <i>key</i> specifies email address information, the localpart should
|
||||||
be enclosed with double quotes if required by <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a>. For example, an
|
be enclosed with double quotes if required by <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a>. For example, an
|
||||||
address localpart that contains
|
address localpart that contains ";", or a localpart that starts or ends
|
||||||
|
with ".".
|
||||||
|
|
||||||
By default the lookup key is mapped to lowercase to make the lookups
|
By default the lookup key is mapped to lowercase to make the lookups
|
||||||
case insensitive; as of Postfix 2.3 this case folding happens only with
|
case insensitive; as of Postfix 2.3 this case folding happens only with
|
||||||
@@ -59,7 +60,7 @@ POSTMAP(1) POSTMAP(1)
|
|||||||
<b>COMMAND-LINE ARGUMENTS</b>
|
<b>COMMAND-LINE ARGUMENTS</b>
|
||||||
<b>-b</b> Enable message body query mode. When reading lookup keys from
|
<b>-b</b> Enable message body query mode. When reading lookup keys from
|
||||||
standard input with "<b>-q -</b>", process the input as if it is an
|
standard input with "<b>-q -</b>", process the input as if it is an
|
||||||
email message in <a href="http://tools.ietf.org/html/rfc2822">RFC 2822</a> format. Each line of body content
|
email message in <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a> format. Each line of body content
|
||||||
becomes one lookup key.
|
becomes one lookup key.
|
||||||
|
|
||||||
By default, the <b>-b</b> option starts generating lookup keys at the
|
By default, the <b>-b</b> option starts generating lookup keys at the
|
||||||
@@ -96,7 +97,7 @@ POSTMAP(1) POSTMAP(1)
|
|||||||
|
|
||||||
<b>-h</b> Enable message header query mode. When reading lookup keys from
|
<b>-h</b> Enable message header query mode. When reading lookup keys from
|
||||||
standard input with "<b>-q -</b>", process the input as if it is an
|
standard input with "<b>-q -</b>", process the input as if it is an
|
||||||
email message in <a href="http://tools.ietf.org/html/rfc2822">RFC 2822</a> format. Each logical header line
|
email message in <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a> format. Each logical header line
|
||||||
becomes one lookup key. A multi-line header becomes one lookup
|
becomes one lookup key. A multi-line header becomes one lookup
|
||||||
key with one or more embedded newline characters.
|
key with one or more embedded newline characters.
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ keys is supported as of Postfix 3.2.
|
|||||||
When the \fIkey\fR specifies email address information, the
|
When the \fIkey\fR specifies email address information, the
|
||||||
localpart should be enclosed with double quotes if required
|
localpart should be enclosed with double quotes if required
|
||||||
by RFC 5322. For example, an address localpart that contains
|
by RFC 5322. For example, an address localpart that contains
|
||||||
';' or that ends on '.'.
|
";", or a localpart that starts or ends with ".".
|
||||||
|
|
||||||
By default the lookup key is mapped to lowercase to make
|
By default the lookup key is mapped to lowercase to make
|
||||||
the lookups case insensitive; as of Postfix 2.3 this case
|
the lookups case insensitive; as of Postfix 2.3 this case
|
||||||
@@ -74,7 +74,7 @@ information with $\fInumber\fR substitutions.
|
|||||||
.IP \fB\-b\fR
|
.IP \fB\-b\fR
|
||||||
Enable message body query mode. When reading lookup keys
|
Enable message body query mode. When reading lookup keys
|
||||||
from standard input with "\fB\-q \-\fR", process the input
|
from standard input with "\fB\-q \-\fR", process the input
|
||||||
as if it is an email message in RFC 2822 format. Each line
|
as if it is an email message in RFC 5322 format. Each line
|
||||||
of body content becomes one lookup key.
|
of body content becomes one lookup key.
|
||||||
.sp
|
.sp
|
||||||
By default, the \fB\-b\fR option starts generating lookup
|
By default, the \fB\-b\fR option starts generating lookup
|
||||||
@@ -111,7 +111,7 @@ is controlled by appending a flag to a pattern.
|
|||||||
.IP \fB\-h\fR
|
.IP \fB\-h\fR
|
||||||
Enable message header query mode. When reading lookup keys
|
Enable message header query mode. When reading lookup keys
|
||||||
from standard input with "\fB\-q \-\fR", process the input
|
from standard input with "\fB\-q \-\fR", process the input
|
||||||
as if it is an email message in RFC 2822 format. Each
|
as if it is an email message in RFC 5322 format. Each
|
||||||
logical header line becomes one lookup key. A multi\-line
|
logical header line becomes one lookup key. A multi\-line
|
||||||
header becomes one lookup key with one or more embedded
|
header becomes one lookup key with one or more embedded
|
||||||
newline characters.
|
newline characters.
|
||||||
|
@@ -165,7 +165,8 @@ off_t cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
|
|||||||
if ((state->flags & CLEANUP_FLAG_BCC_OK)
|
if ((state->flags & CLEANUP_FLAG_BCC_OK)
|
||||||
&& *STR(clean_addr)
|
&& *STR(clean_addr)
|
||||||
&& cleanup_send_bcc_maps) {
|
&& cleanup_send_bcc_maps) {
|
||||||
if ((bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr),
|
if ((bcc = mail_addr_find_to_internal(cleanup_send_bcc_maps,
|
||||||
|
STR(clean_addr),
|
||||||
IGNORE_EXTENSION)) != 0) {
|
IGNORE_EXTENSION)) != 0) {
|
||||||
cleanup_addr_bcc(state, bcc);
|
cleanup_addr_bcc(state, bcc);
|
||||||
} else if (cleanup_send_bcc_maps->error) {
|
} else if (cleanup_send_bcc_maps->error) {
|
||||||
@@ -228,7 +229,8 @@ void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
|
|||||||
if ((state->flags & CLEANUP_FLAG_BCC_OK)
|
if ((state->flags & CLEANUP_FLAG_BCC_OK)
|
||||||
&& *STR(clean_addr)
|
&& *STR(clean_addr)
|
||||||
&& cleanup_rcpt_bcc_maps) {
|
&& cleanup_rcpt_bcc_maps) {
|
||||||
if ((bcc = mail_addr_find(cleanup_rcpt_bcc_maps, STR(clean_addr),
|
if ((bcc = mail_addr_find_to_internal(cleanup_rcpt_bcc_maps,
|
||||||
|
STR(clean_addr),
|
||||||
IGNORE_EXTENSION)) != 0) {
|
IGNORE_EXTENSION)) != 0) {
|
||||||
cleanup_addr_bcc(state, bcc);
|
cleanup_addr_bcc(state, bcc);
|
||||||
} else if (cleanup_rcpt_bcc_maps->error) {
|
} else if (cleanup_rcpt_bcc_maps->error) {
|
||||||
|
@@ -105,6 +105,7 @@ int cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr,
|
|||||||
*/
|
*/
|
||||||
for (count = 0; count < MAX_RECURSION; count++) {
|
for (count = 0; count < MAX_RECURSION; count++) {
|
||||||
if ((new_addr = mail_addr_map_opt(maps, STR(addr), propagate,
|
if ((new_addr = mail_addr_map_opt(maps, STR(addr), propagate,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
MAIL_ADDR_FORM_EXTERNAL,
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
MAIL_ADDR_FORM_EXTERNAL)) != 0) {
|
MAIL_ADDR_FORM_EXTERNAL)) != 0) {
|
||||||
if (new_addr->argc > 1)
|
if (new_addr->argc > 1)
|
||||||
|
@@ -118,7 +118,7 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
|
|||||||
valid_mailhost_addr own_inet_addr header_body_checks \
|
valid_mailhost_addr own_inet_addr header_body_checks \
|
||||||
data_redirect addr_match_list safe_ultostr verify_sender_addr \
|
data_redirect addr_match_list safe_ultostr verify_sender_addr \
|
||||||
mail_version mail_dict server_acl uxtext mail_parm_split \
|
mail_version mail_dict server_acl uxtext mail_parm_split \
|
||||||
fold_addr smtp_reply_footer mail_addr_map_tester
|
fold_addr smtp_reply_footer mail_addr_map
|
||||||
|
|
||||||
LIBS = ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
|
LIBS = ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
|
||||||
LIB_DIR = ../../lib
|
LIB_DIR = ../../lib
|
||||||
@@ -249,8 +249,10 @@ off_cvt: $(LIB) $(LIBS)
|
|||||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
||||||
mv junk $@.o
|
mv junk $@.o
|
||||||
|
|
||||||
mail_addr_map_tester: mail_addr_map_tester.c $(LIB) $(LIBS)
|
mail_addr_map: mail_addr_map.c $(LIB) $(LIBS)
|
||||||
|
mv $@.o junk
|
||||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
|
||||||
|
mv junk $@.o
|
||||||
|
|
||||||
mail_addr_find: $(LIB) $(LIBS)
|
mail_addr_find: $(LIB) $(LIBS)
|
||||||
mv $@.o junk
|
mv $@.o junk
|
||||||
@@ -683,9 +685,9 @@ mail_addr_find_test: update mail_addr_find mail_addr_find.in mail_addr_find.ref
|
|||||||
diff mail_addr_find.ref mail_addr_find.tmp
|
diff mail_addr_find.ref mail_addr_find.tmp
|
||||||
rm -f mail_addr_find.tmp
|
rm -f mail_addr_find.tmp
|
||||||
|
|
||||||
mail_addr_map_test: update mail_addr_map_tester mail_addr_map.ref
|
mail_addr_map_test: update mail_addr_map mail_addr_map.ref
|
||||||
-$(SHLIB_ENV) $(VALGRIND) ./mail_addr_map_tester pass_tests
|
-$(SHLIB_ENV) $(VALGRIND) ./mail_addr_map pass_tests
|
||||||
-$(SHLIB_ENV) $(VALGRIND) ./mail_addr_map_tester fail_tests >mail_addr_map.tmp 2>&1
|
-$(SHLIB_ENV) $(VALGRIND) ./mail_addr_map fail_tests >mail_addr_map.tmp 2>&1
|
||||||
diff mail_addr_map.ref mail_addr_map.tmp
|
diff mail_addr_map.ref mail_addr_map.tmp
|
||||||
rm -f mail_addr_map.tmp
|
rm -f mail_addr_map.tmp
|
||||||
|
|
||||||
@@ -1490,6 +1492,7 @@ mail_addr_find.o: ../../include/dict.h
|
|||||||
mail_addr_find.o: ../../include/msg.h
|
mail_addr_find.o: ../../include/msg.h
|
||||||
mail_addr_find.o: ../../include/myflock.h
|
mail_addr_find.o: ../../include/myflock.h
|
||||||
mail_addr_find.o: ../../include/mymalloc.h
|
mail_addr_find.o: ../../include/mymalloc.h
|
||||||
|
mail_addr_find.o: ../../include/name_mask.h
|
||||||
mail_addr_find.o: ../../include/stringops.h
|
mail_addr_find.o: ../../include/stringops.h
|
||||||
mail_addr_find.o: ../../include/sys_defs.h
|
mail_addr_find.o: ../../include/sys_defs.h
|
||||||
mail_addr_find.o: ../../include/vbuf.h
|
mail_addr_find.o: ../../include/vbuf.h
|
||||||
@@ -1526,23 +1529,6 @@ mail_addr_map.o: mail_addr_map.h
|
|||||||
mail_addr_map.o: maps.h
|
mail_addr_map.o: maps.h
|
||||||
mail_addr_map.o: quote_822_local.h
|
mail_addr_map.o: quote_822_local.h
|
||||||
mail_addr_map.o: quote_flags.h
|
mail_addr_map.o: quote_flags.h
|
||||||
mail_addr_map_tester.o: ../../include/argv.h
|
|
||||||
mail_addr_map_tester.o: ../../include/check_arg.h
|
|
||||||
mail_addr_map_tester.o: ../../include/dict.h
|
|
||||||
mail_addr_map_tester.o: ../../include/msg.h
|
|
||||||
mail_addr_map_tester.o: ../../include/myflock.h
|
|
||||||
mail_addr_map_tester.o: ../../include/mymalloc.h
|
|
||||||
mail_addr_map_tester.o: ../../include/sys_defs.h
|
|
||||||
mail_addr_map_tester.o: ../../include/vbuf.h
|
|
||||||
mail_addr_map_tester.o: ../../include/vstream.h
|
|
||||||
mail_addr_map_tester.o: ../../include/vstring.h
|
|
||||||
mail_addr_map_tester.o: canon_addr.h
|
|
||||||
mail_addr_map_tester.o: mail_addr_form.h
|
|
||||||
mail_addr_map_tester.o: mail_addr_map.h
|
|
||||||
mail_addr_map_tester.o: mail_addr_map_tester.c
|
|
||||||
mail_addr_map_tester.o: mail_conf.h
|
|
||||||
mail_addr_map_tester.o: mail_params.h
|
|
||||||
mail_addr_map_tester.o: maps.h
|
|
||||||
mail_command_client.o: ../../include/attr.h
|
mail_command_client.o: ../../include/attr.h
|
||||||
mail_command_client.o: ../../include/check_arg.h
|
mail_command_client.o: ../../include/check_arg.h
|
||||||
mail_command_client.o: ../../include/htable.h
|
mail_command_client.o: ../../include/htable.h
|
||||||
|
@@ -11,12 +11,13 @@
|
|||||||
/* const char *address;
|
/* const char *address;
|
||||||
/* char **extension;
|
/* char **extension;
|
||||||
/*
|
/*
|
||||||
/* const char *mail_addr_find_opt(maps, address, extension,
|
/* const char *mail_addr_find_opt(maps, address, extension, in_form,
|
||||||
/* in_form, out_form, strategy)
|
/* query_form, out_form, strategy)
|
||||||
/* MAPS *maps;
|
/* MAPS *maps;
|
||||||
/* const char *address;
|
/* const char *address;
|
||||||
/* char **extension;
|
/* char **extension;
|
||||||
/* int in_form;
|
/* int in_form;
|
||||||
|
/* int in_form;
|
||||||
/* int out_form;
|
/* int out_form;
|
||||||
/* int strategy;
|
/* int strategy;
|
||||||
/* LEGACY SUPPORT
|
/* LEGACY SUPPORT
|
||||||
@@ -25,6 +26,11 @@
|
|||||||
/* const char *address;
|
/* const char *address;
|
||||||
/* char **extension;
|
/* char **extension;
|
||||||
/*
|
/*
|
||||||
|
/* const char *mail_addr_find_to_internal(maps, address, extension)
|
||||||
|
/* MAPS *maps;
|
||||||
|
/* const char *address;
|
||||||
|
/* char **extension;
|
||||||
|
/*
|
||||||
/* const char *mail_addr_find_strategy(maps, address, extension)
|
/* const char *mail_addr_find_strategy(maps, address, extension)
|
||||||
/* MAPS *maps;
|
/* MAPS *maps;
|
||||||
/* const char *address;
|
/* const char *address;
|
||||||
@@ -37,33 +43,37 @@
|
|||||||
/* preferences when it opens the maps.
|
/* preferences when it opens the maps.
|
||||||
/* The result is overwritten upon each call.
|
/* The result is overwritten upon each call.
|
||||||
/*
|
/*
|
||||||
/* The table key and value are expected to be in external
|
/* In the lookup table, the key is expected to be in external
|
||||||
/* (quoted) form. Override these assumptions with the in_form
|
/* form (as produced with the postmap command) and the value is
|
||||||
|
/* expected to be in external (quoted) form if it is an email
|
||||||
|
/* address. Override these assumptions with the query_form
|
||||||
/* and out_form arguments.
|
/* and out_form arguments.
|
||||||
/*
|
/*
|
||||||
/* With mail_addr_find_int_to_ext(), the specified address is in
|
/* With mail_addr_find_int_to_ext(), the specified address is in
|
||||||
/* internal (unquoted) form. The result is in the form found
|
/* internal (unquoted) form, the query is made in external (quoted)
|
||||||
/* in the table (it is not necessarily an email address). This
|
/* form, and the result is in the form found in the table (it is
|
||||||
/* version minimizes internal/external (unquoted/quoted)
|
/* not necessarily an email address). This version minimizes
|
||||||
/* conversions of the query, extension, or result.
|
/* internal/external (unquoted/quoted) conversions of the input,
|
||||||
|
/* query, extension, or result.
|
||||||
/*
|
/*
|
||||||
/* mail_addr_find_opt() gives more control, at the cost of
|
/* mail_addr_find_opt() gives more control, at the cost of
|
||||||
/* additional conversions between internal and external forms.
|
/* additional conversions between internal and external forms.
|
||||||
/* In particular, the output conversion to internal form assumes
|
/* In particular, output conversion to internal form assumes
|
||||||
/* that the lookup result is an email address.
|
/* that the lookup result is an email address.
|
||||||
/*
|
/*
|
||||||
/* mail_addr_find() is used by legacy code that historically
|
/* mail_addr_find() is used by legacy code that historically searched
|
||||||
/* searched with internal-form keys. The lookup strategy is
|
/* with internal-form queries. The input is in internal form. It
|
||||||
/* to first look up with (in_form, out_form) of (INTERNAL,
|
/* searches with external-form queries first, and falls back to
|
||||||
/* NOCONV), which converts the key to external form. If no
|
/* internal-form queries if no result was found and the external
|
||||||
/* result is found, and the internal and external key forms
|
/* and internal forms differ. The result is external form (i.e. no
|
||||||
/* differ, there is a backwards-compatibility lookup with
|
/* conversion).
|
||||||
/* (in_form, out_form) of (NOCONV, NOCONV).
|
|
||||||
/*
|
/*
|
||||||
/* mail_addr_find_strategy() overrides the default search
|
/* mail_addr_find_to_internal() is like mail_addr_find() but assumes
|
||||||
/* strategy for full and partial addresses.
|
/* that the lookup result is one external-form email address,
|
||||||
|
/* and converts it to internal form.
|
||||||
/*
|
/*
|
||||||
/* An address that is in the form \fIuser\fR matches itself.
|
/* mail_addr_find_strategy() is like mail_addr_find() but overrides
|
||||||
|
/* the default search strategy for full and partial addresses.
|
||||||
/*
|
/*
|
||||||
/* Arguments:
|
/* Arguments:
|
||||||
/* .IP maps
|
/* .IP maps
|
||||||
@@ -77,48 +87,54 @@
|
|||||||
/* The copy includes the recipient address delimiter.
|
/* The copy includes the recipient address delimiter.
|
||||||
/* The copy is in internal (unquoted) form.
|
/* The copy is in internal (unquoted) form.
|
||||||
/* The caller is expected to pass the copy to myfree().
|
/* The caller is expected to pass the copy to myfree().
|
||||||
|
/* .IP query_form
|
||||||
|
/* The address form to use for database queries: one of
|
||||||
|
/* MAIL_ADDR_FORM_INTERNAL (unquoted form), MAIL_ADDR_FORM_EXTERNAL
|
||||||
|
/* (quoted form), or MAIL_ADDR_FORM_EXTERNAL_FIRST (external form,
|
||||||
|
/* then internal form if the external and internal forms differ).
|
||||||
/* .IP in_form
|
/* .IP in_form
|
||||||
/* .IP out_form
|
/* .IP out_form
|
||||||
/* Input and output address forms, either MAIL_ADDR_FORM_INTERNAL
|
/* Input and output address forms, one of MAIL_ADDR_FORM_INTERNAL
|
||||||
/* (unquoted form), MAIL_ADDR_FORM_EXTERNAL (quoted form), or
|
/* (unquoted form), or MAIL_ADDR_FORM_EXTERNAL (quoted form).
|
||||||
/* MAIL_ADDR_FORM_NOCONV (don't convert between unquoted and
|
|
||||||
/* quoted form).
|
|
||||||
/* .IP strategy
|
/* .IP strategy
|
||||||
/* The lookup strategy for full and partial addresses, specified
|
/* The lookup strategy for full and partial addresses, specified
|
||||||
/* as the binary OR of one or more of the following. These
|
/* as the binary OR of one or more of the following. These lookups
|
||||||
/* lookups are implemented in the order as listed below.
|
/* are implemented in the order as listed below.
|
||||||
/* .RS
|
/* .RS
|
||||||
/* .IP MAIL_ADDR_FIND_FULL
|
/* .IP MAF_STRATEGY_DEFAULT
|
||||||
|
/* A convenience alias for (MAF_STRATEGY_FULL | MAF_STRATEGY_NOEXT |
|
||||||
|
/* MAF_STRATEGY_LOCALPART_IF_LOCAL | MAF_STRATEGY_AT_DOMAIN).
|
||||||
|
/* .IP MAF_STRATEGY_FULL
|
||||||
/* Look up the full email address.
|
/* Look up the full email address.
|
||||||
/* .IP MAIL_ADDR_FIND_NOEXT
|
/* .IP MAF_STRATEGY_NOEXT
|
||||||
/* If no match was found, and the address has an extension,
|
/* If no match was found, and the address has a localpart extension,
|
||||||
/* look up the address after removing the address extension.
|
/* look up the address after removing the extension.
|
||||||
/* .IP MAIL_ADDR_FIND_LOCALPART_IF_LOCAL
|
/* .IP MAF_STRATEGY_LOCALPART_IF_LOCAL
|
||||||
/* If no match was found, and the domain matches myorigin,
|
/* If no match was found, and the domain matches myorigin,
|
||||||
/* mydestination, or any proxy_interfaces IP address, look up
|
/* mydestination, or any inet_interfaces or proxy_interfaces IP
|
||||||
/* the localpart. If no match was found, and the address has
|
/* address, look up the localpart. If no match was found, and the
|
||||||
/* an extension, repeat the same query after removing the
|
/* address has a localpart extension, repeat the same query after
|
||||||
/* address extension unless MAIL_ADDR_FIND_NOEXT is specified.
|
/* removing the extension unless MAF_STRATEGY_NOEXT is specified.
|
||||||
/* .IP MAIL_ADDR_FIND_LOCALPART_AT_IF_LOCAL
|
/* .IP MAF_STRATEGY_LOCALPART_AT_IF_LOCAL
|
||||||
/* As above, but using the localpart@ instead.
|
/* As above, but using the localpart@ instead.
|
||||||
/* .IP MAIL_ADDR_FIND_ATDOMAIN
|
/* .IP MAF_STRATEGY_AT_DOMAIN
|
||||||
/* If no match was found, look up the @domain without localpart.
|
/* If no match was found, look up the @domain without localpart.
|
||||||
/* .IP MAIL_ADDR_FIND_DOMAIN
|
/* .IP MAF_STRATEGY_DOMAIN
|
||||||
/* If no match was found, look up the domain without localpart.
|
/* If no match was found, look up the domain without localpart.
|
||||||
/* .IP MAIL_ADDR_FIND_PMS
|
/* .IP MAF_STRATEGY_PMS
|
||||||
/* When used with MAIL_ADDR_FIND_DOMAIN, also matches subdomains.
|
/* When used with MAF_STRATEGY_DOMAIN, also matches subdomains.
|
||||||
/* .IP MAIL_ADDR_FIND_PMDS
|
/* .IP MAF_STRATEGY_PMDS
|
||||||
/* When used with MAIL_ADDR_FIND_DOMAIN, also matches dot-subdomains.
|
/* When used with MAF_STRATEGY_DOMAIN, also matches dot-subdomains.
|
||||||
/* .IP MAIL_ADDR_FIND_LOCALPART_AT
|
/* .IP MAF_STRATEGY_LOCALPART_AT
|
||||||
/* If no match was found, look up the localpart@, regardless
|
/* If no match was found, look up the localpart@, regardless of
|
||||||
/* of the domain content.
|
/* the domain content.
|
||||||
/* .RE
|
/* .RE
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* The maps->error value is non-zero when the lookup
|
/* The maps->error value is non-zero when the lookup should be
|
||||||
/* should be tried again.
|
/* tried again.
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* maps(3), multi-dictionary search
|
/* maps(3), multi-dictionary search resolve_local(3), recognize
|
||||||
/* resolve_local(3), recognize local system
|
/* local system
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@@ -156,27 +172,22 @@
|
|||||||
|
|
||||||
#define STR vstring_str
|
#define STR vstring_str
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
|
||||||
static const NAME_MASK strategy_table[] = {
|
static const NAME_MASK strategy_table[] = {
|
||||||
"full", MAIL_ADDR_FIND_FULL,
|
"full", MAF_STRATEGY_FULL,
|
||||||
"noext", MAIL_ADDR_FIND_NOEXT,
|
"noext", MAF_STRATEGY_NOEXT,
|
||||||
"localpart_if_local", MAIL_ADDR_FIND_LOCALPART_IF_LOCAL,
|
"localpart_if_local", MAF_STRATEGY_LOCALPART_IF_LOCAL,
|
||||||
"localpart_at_if_local", MAIL_ADDR_FIND_LOCALPART_AT_IF_LOCAL,
|
"localpart_at_if_local", MAF_STRATEGY_LOCALPART_AT_IF_LOCAL,
|
||||||
"atdomain", MAIL_ADDR_FIND_ATDOMAIN,
|
"atdomain", MAF_STRATEGY_AT_DOMAIN,
|
||||||
"domain", MAIL_ADDR_FIND_DOMAIN,
|
"domain", MAF_STRATEGY_DOMAIN,
|
||||||
"pms", MAIL_ADDR_FIND_PMS,
|
"pms", MAF_STRATEGY_PMS,
|
||||||
"pmds", MAIL_ADDR_FIND_PMDS,
|
"pmds", MAF_STRATEGY_PMDS,
|
||||||
"localpartat", MAIL_ADDR_FIND_LOCALPART_AT,
|
"localpart_at", MAF_STRATEGY_LOCALPART_AT,
|
||||||
"default", MAIL_ADDR_FIND_DEFAULT,
|
"default", MAF_STRATEGY_DEFAULT,
|
||||||
0, -1,
|
0, -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Specify what keys are partial or full, to avoid matching partial
|
|
||||||
* addresses with regular expressions.
|
|
||||||
*/
|
|
||||||
#define FULL 0
|
|
||||||
#define PARTIAL DICT_FLAG_FIXED
|
|
||||||
|
|
||||||
/* strategy_from_string - symbolic strategy flags to internal form */
|
/* strategy_from_string - symbolic strategy flags to internal form */
|
||||||
|
|
||||||
static int strategy_from_string(const char *strategy_string)
|
static int strategy_from_string(const char *strategy_string)
|
||||||
@@ -199,29 +210,63 @@ static const char *strategy_to_string(VSTRING *res_buf, int strategy_mask)
|
|||||||
NAME_MASK_WARN | NAME_MASK_PIPE));
|
NAME_MASK_WARN | NAME_MASK_PIPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find_addr - helper to search map with external-form address */
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specify what keys are partial or full, to avoid matching partial
|
||||||
|
* addresses with regular expressions.
|
||||||
|
*/
|
||||||
|
#define FULL 0
|
||||||
|
#define PARTIAL DICT_FLAG_FIXED
|
||||||
|
|
||||||
|
/* find_addr - helper to search maps with the right query form */
|
||||||
|
|
||||||
static const char *find_addr(MAPS *path, const char *address, int flags,
|
static const char *find_addr(MAPS *path, const char *address, int flags,
|
||||||
int with_domain, int find_form, VSTRING *ext_addr_buf)
|
int with_domain, int query_form, VSTRING *ext_addr_buf)
|
||||||
{
|
{
|
||||||
|
const char *result;
|
||||||
|
|
||||||
#define SANS_DOMAIN 0
|
#define SANS_DOMAIN 0
|
||||||
#define WITH_DOMAIN 1
|
#define WITH_DOMAIN 1
|
||||||
|
|
||||||
if (find_form == MAIL_ADDR_FORM_INTERNAL) {
|
switch (query_form) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query with external-form (quoted) address.
|
||||||
|
*/
|
||||||
|
case MAIL_ADDR_FORM_EXTERNAL:
|
||||||
|
case MAIL_ADDR_FORM_EXTERNAL_FIRST:
|
||||||
quote_822_local_flags(ext_addr_buf, address,
|
quote_822_local_flags(ext_addr_buf, address,
|
||||||
with_domain ? QUOTE_FLAG_DEFAULT :
|
with_domain ? QUOTE_FLAG_DEFAULT :
|
||||||
QUOTE_FLAG_DEFAULT | QUOTE_FLAG_BARE_LOCALPART);
|
QUOTE_FLAG_DEFAULT | QUOTE_FLAG_BARE_LOCALPART);
|
||||||
address = STR(ext_addr_buf);
|
result = maps_find(path, STR(ext_addr_buf), flags);
|
||||||
|
if (result != 0 || path->error != 0
|
||||||
|
|| query_form == MAIL_ADDR_FORM_EXTERNAL
|
||||||
|
|| strcmp(address, STR(ext_addr_buf)) == 0)
|
||||||
|
break;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query with internal-form (unquoted) address.
|
||||||
|
*/
|
||||||
|
case MAIL_ADDR_FORM_INTERNAL:
|
||||||
|
result = maps_find(path, address, flags);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Can't happen.
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
msg_panic("mail_addr_find: bad query_form: %d", query_form);
|
||||||
}
|
}
|
||||||
return (maps_find(path, address, flags));
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find_local - search on localpart info */
|
/* find_local - search on localpart info */
|
||||||
|
|
||||||
static const char *find_local(MAPS *path, char *ratsign, int rats_offs,
|
static const char *find_local(MAPS *path, char *ratsign, int rats_offs,
|
||||||
char *int_full_key, char *int_bare_key,
|
char *int_full_key, char *int_bare_key,
|
||||||
int find_form, char **extp, char **saved_ext,
|
int query_form, char **extp, char **saved_ext,
|
||||||
VSTRING *ext_addr_buf)
|
VSTRING *ext_addr_buf)
|
||||||
{
|
{
|
||||||
const char *myname = "mail_addr_find";
|
const char *myname = "mail_addr_find";
|
||||||
@@ -230,15 +275,15 @@ static const char *find_local(MAPS *path, char *ratsign, int rats_offs,
|
|||||||
int saved_ch;
|
int saved_ch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This was ripped from the middle of a function so it can be reused,
|
* This code was ripped from the middle of a function so that it can be
|
||||||
* that's why the interface makes no sense.
|
* reused multiple times, that's why the interface makes little sense.
|
||||||
*/
|
*/
|
||||||
with_domain = rats_offs ? WITH_DOMAIN : SANS_DOMAIN;
|
with_domain = rats_offs ? WITH_DOMAIN : SANS_DOMAIN;
|
||||||
|
|
||||||
saved_ch = *(unsigned char *) (ratsign + rats_offs);
|
saved_ch = *(unsigned char *) (ratsign + rats_offs);
|
||||||
*(ratsign + rats_offs) = 0;
|
*(ratsign + rats_offs) = 0;
|
||||||
result = find_addr(path, int_full_key, PARTIAL, with_domain,
|
result = find_addr(path, int_full_key, PARTIAL, with_domain,
|
||||||
find_form, ext_addr_buf);
|
query_form, ext_addr_buf);
|
||||||
*(ratsign + rats_offs) = saved_ch;
|
*(ratsign + rats_offs) = saved_ch;
|
||||||
if (result == 0 && path->error == 0 && int_bare_key != 0) {
|
if (result == 0 && path->error == 0 && int_bare_key != 0) {
|
||||||
if ((ratsign = strrchr(int_bare_key, '@')) == 0)
|
if ((ratsign = strrchr(int_bare_key, '@')) == 0)
|
||||||
@@ -246,7 +291,7 @@ static const char *find_local(MAPS *path, char *ratsign, int rats_offs,
|
|||||||
saved_ch = *(unsigned char *) (ratsign + rats_offs);
|
saved_ch = *(unsigned char *) (ratsign + rats_offs);
|
||||||
*(ratsign + rats_offs) = 0;
|
*(ratsign + rats_offs) = 0;
|
||||||
if ((result = find_addr(path, int_bare_key, PARTIAL, with_domain,
|
if ((result = find_addr(path, int_bare_key, PARTIAL, with_domain,
|
||||||
find_form, ext_addr_buf)) != 0
|
query_form, ext_addr_buf)) != 0
|
||||||
&& extp != 0) {
|
&& extp != 0) {
|
||||||
*extp = *saved_ext;
|
*extp = *saved_ext;
|
||||||
*saved_ext = 0;
|
*saved_ext = 0;
|
||||||
@@ -259,11 +304,11 @@ static const char *find_local(MAPS *path, char *ratsign, int rats_offs,
|
|||||||
/* mail_addr_find_opt - map a canonical address */
|
/* mail_addr_find_opt - map a canonical address */
|
||||||
|
|
||||||
const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
|
const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
|
||||||
int in_form, int out_form, int strategy)
|
int in_form, int query_form,
|
||||||
|
int out_form, int strategy)
|
||||||
{
|
{
|
||||||
const char *myname = "mail_addr_find";
|
const char *myname = "mail_addr_find";
|
||||||
VSTRING *ext_addr_buf = 0;
|
VSTRING *ext_addr_buf = 0;
|
||||||
int find_form;
|
|
||||||
VSTRING *int_addr_buf = 0;
|
VSTRING *int_addr_buf = 0;
|
||||||
const char *int_addr;
|
const char *int_addr;
|
||||||
static VSTRING *int_result = 0;
|
static VSTRING *int_result = 0;
|
||||||
@@ -275,27 +320,27 @@ const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Optionally convert input from external form.
|
* Optionally convert the address from external form.
|
||||||
*/
|
*/
|
||||||
if (in_form == MAIL_ADDR_FORM_EXTERNAL) {
|
if (in_form == MAIL_ADDR_FORM_EXTERNAL) {
|
||||||
int_addr_buf = vstring_alloc(100);
|
int_addr_buf = vstring_alloc(100);
|
||||||
unquote_822_local(int_addr_buf, address);
|
unquote_822_local(int_addr_buf, address);
|
||||||
int_addr = STR(int_addr_buf);
|
int_addr = STR(int_addr_buf);
|
||||||
find_form = MAIL_ADDR_FORM_INTERNAL;
|
|
||||||
} else {
|
} else {
|
||||||
int_addr = address;
|
int_addr = address;
|
||||||
find_form = in_form;
|
|
||||||
}
|
}
|
||||||
if (find_form == MAIL_ADDR_FORM_INTERNAL)
|
if (query_form == MAIL_ADDR_FORM_EXTERNAL_FIRST
|
||||||
|
|| query_form == MAIL_ADDR_FORM_EXTERNAL)
|
||||||
ext_addr_buf = vstring_alloc(100);
|
ext_addr_buf = vstring_alloc(100);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize.
|
* Initialize.
|
||||||
*/
|
*/
|
||||||
int_full_key = mystrdup(int_addr);
|
int_full_key = mystrdup(int_addr);
|
||||||
if (*var_rcpt_delim == 0 || (strategy & MAIL_ADDR_FIND_NOEXT) == 0) {
|
if (*var_rcpt_delim == 0 || (strategy & MAF_STRATEGY_NOEXT) == 0) {
|
||||||
int_bare_key = saved_ext = 0;
|
int_bare_key = saved_ext = 0;
|
||||||
} else {
|
} else {
|
||||||
|
/* XXX This could be done after user+foo@domain fails. */
|
||||||
int_bare_key =
|
int_bare_key =
|
||||||
strip_addr_internal(int_full_key, &saved_ext, var_rcpt_delim);
|
strip_addr_internal(int_full_key, &saved_ext, var_rcpt_delim);
|
||||||
}
|
}
|
||||||
@@ -303,9 +348,9 @@ const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
|
|||||||
/*
|
/*
|
||||||
* Try user+foo@domain and user@domain.
|
* Try user+foo@domain and user@domain.
|
||||||
*/
|
*/
|
||||||
if ((strategy & MAIL_ADDR_FIND_FULL) != 0) {
|
if ((strategy & MAF_STRATEGY_FULL) != 0) {
|
||||||
result = find_addr(path, int_full_key, FULL, WITH_DOMAIN,
|
result = find_addr(path, int_full_key, FULL, WITH_DOMAIN,
|
||||||
find_form, ext_addr_buf);
|
query_form, ext_addr_buf);
|
||||||
} else {
|
} else {
|
||||||
result = 0;
|
result = 0;
|
||||||
path->error = 0;
|
path->error = 0;
|
||||||
@@ -313,31 +358,31 @@ const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
|
|||||||
|
|
||||||
if (result == 0 && path->error == 0 && int_bare_key != 0
|
if (result == 0 && path->error == 0 && int_bare_key != 0
|
||||||
&& (result = find_addr(path, int_bare_key, PARTIAL, WITH_DOMAIN,
|
&& (result = find_addr(path, int_bare_key, PARTIAL, WITH_DOMAIN,
|
||||||
find_form, ext_addr_buf)) != 0
|
query_form, ext_addr_buf)) != 0
|
||||||
&& extp != 0) {
|
&& extp != 0) {
|
||||||
*extp = saved_ext;
|
*extp = saved_ext;
|
||||||
saved_ext = 0;
|
saved_ext = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try user+foo, if the domain matches user+foo@$myorigin,
|
* Try user+foo if the domain matches user+foo@$myorigin,
|
||||||
* user+foo@$mydestination or user+foo@[${proxy,inet}_interfaces]. Then
|
* user+foo@$mydestination or user+foo@[${proxy,inet}_interfaces]. Then
|
||||||
* try with +foo stripped off.
|
* try with +foo stripped off.
|
||||||
*/
|
*/
|
||||||
if (result == 0 && path->error == 0
|
if (result == 0 && path->error == 0
|
||||||
&& (ratsign = strrchr(int_full_key, '@')) != 0
|
&& (ratsign = strrchr(int_full_key, '@')) != 0
|
||||||
&& (strategy & (MAIL_ADDR_FIND_LOCALPART_IF_LOCAL
|
&& (strategy & (MAF_STRATEGY_LOCALPART_IF_LOCAL
|
||||||
| MAIL_ADDR_FIND_LOCALPART_AT_IF_LOCAL)) != 0) {
|
| MAF_STRATEGY_LOCALPART_AT_IF_LOCAL)) != 0) {
|
||||||
if (strcasecmp_utf8(ratsign + 1, var_myorigin) == 0
|
if (strcasecmp_utf8(ratsign + 1, var_myorigin) == 0
|
||||||
|| (rc = resolve_local(ratsign + 1)) > 0) {
|
|| (rc = resolve_local(ratsign + 1)) > 0) {
|
||||||
if ((strategy & MAIL_ADDR_FIND_LOCALPART_IF_LOCAL) != 0)
|
if ((strategy & MAF_STRATEGY_LOCALPART_IF_LOCAL) != 0)
|
||||||
result = find_local(path, ratsign, 0, int_full_key,
|
result = find_local(path, ratsign, 0, int_full_key,
|
||||||
int_bare_key, find_form, extp, &saved_ext,
|
int_bare_key, query_form, extp, &saved_ext,
|
||||||
ext_addr_buf);
|
ext_addr_buf);
|
||||||
if (result == 0 && path->error == 0
|
if (result == 0 && path->error == 0
|
||||||
&& (strategy & MAIL_ADDR_FIND_LOCALPART_AT_IF_LOCAL) != 0)
|
&& (strategy & MAF_STRATEGY_LOCALPART_AT_IF_LOCAL) != 0)
|
||||||
result = find_local(path, ratsign, 1, int_full_key,
|
result = find_local(path, ratsign, 1, int_full_key,
|
||||||
int_bare_key, find_form, extp, &saved_ext,
|
int_bare_key, query_form, extp, &saved_ext,
|
||||||
ext_addr_buf);
|
ext_addr_buf);
|
||||||
} else if (rc < 0)
|
} else if (rc < 0)
|
||||||
path->error = rc;
|
path->error = rc;
|
||||||
@@ -347,40 +392,40 @@ const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
|
|||||||
* Try @domain.
|
* Try @domain.
|
||||||
*/
|
*/
|
||||||
if (result == 0 && path->error == 0 && ratsign != 0
|
if (result == 0 && path->error == 0 && ratsign != 0
|
||||||
&& (strategy & MAIL_ADDR_FIND_ATDOMAIN) != 0)
|
&& (strategy & MAF_STRATEGY_AT_DOMAIN) != 0)
|
||||||
result = maps_find(path, ratsign, PARTIAL);
|
result = maps_find(path, ratsign, PARTIAL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try domain (optionally, subdomains).
|
* Try domain (optionally, subdomains).
|
||||||
*/
|
*/
|
||||||
if (result == 0 && path->error == 0 && ratsign != 0
|
if (result == 0 && path->error == 0 && ratsign != 0
|
||||||
&& (strategy & MAIL_ADDR_FIND_DOMAIN) != 0) {
|
&& (strategy & MAF_STRATEGY_DOMAIN) != 0) {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *next;
|
const char *next;
|
||||||
|
|
||||||
for (name = ratsign + 1; *name != 0; name = next) {
|
for (name = ratsign + 1; *name != 0; name = next) {
|
||||||
if ((result = maps_find(path, name, PARTIAL)) != 0
|
if ((result = maps_find(path, name, PARTIAL)) != 0
|
||||||
|| path->error != 0
|
|| path->error != 0
|
||||||
|| (strategy & (MAIL_ADDR_FIND_PMS | MAIL_ADDR_FIND_PMDS)) == 0
|
|| (strategy & (MAF_STRATEGY_PMS | MAF_STRATEGY_PMDS)) == 0
|
||||||
|| (next = strchr(name + 1, '.')) == 0)
|
|| (next = strchr(name + 1, '.')) == 0)
|
||||||
break;
|
break;
|
||||||
if ((strategy & MAIL_ADDR_FIND_PMDS) == 0)
|
if ((strategy & MAF_STRATEGY_PMDS) == 0)
|
||||||
next++;
|
next++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try localpart@ even if not local.
|
* Try localpart@ even if the domain is not local.
|
||||||
*/
|
*/
|
||||||
if ((strategy & MAIL_ADDR_FIND_LOCALPART_AT) != 0 \
|
if ((strategy & MAF_STRATEGY_LOCALPART_AT) != 0 \
|
||||||
&&result == 0 && path->error == 0)
|
&&result == 0 && path->error == 0)
|
||||||
result = find_local(path, ratsign, 1, int_full_key,
|
result = find_local(path, ratsign, 1, int_full_key,
|
||||||
int_bare_key, find_form, extp, &saved_ext,
|
int_bare_key, query_form, extp, &saved_ext,
|
||||||
ext_addr_buf);
|
ext_addr_buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Optionally convert the result to internal form. The lookup result is
|
* Optionally convert the result to internal form. The lookup result is
|
||||||
* supposed to be in external form.
|
* supposed to be one external-form email address.
|
||||||
*/
|
*/
|
||||||
if (result != 0 && out_form == MAIL_ADDR_FORM_INTERNAL) {
|
if (result != 0 && out_form == MAIL_ADDR_FORM_INTERNAL) {
|
||||||
if (int_result == 0)
|
if (int_result == 0)
|
||||||
@@ -409,40 +454,6 @@ const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mail_addr_find_strategy - map a canonical address */
|
|
||||||
|
|
||||||
const char *mail_addr_find_strategy(MAPS *path, const char *address,
|
|
||||||
char **extp, int strategy)
|
|
||||||
{
|
|
||||||
static VSTRING *ext_addr_buf;
|
|
||||||
const char *result;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The future: look up with MAIL_ADDR_FORM_INTERNAL, which converts keys
|
|
||||||
* to external form.
|
|
||||||
*/
|
|
||||||
if ((result = mail_addr_find_opt(path, address, extp,
|
|
||||||
MAIL_ADDR_FORM_INTERNAL,
|
|
||||||
MAIL_ADDR_FORM_NOCONV,
|
|
||||||
strategy)) != 0
|
|
||||||
|| path->error != 0)
|
|
||||||
return (result);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The past: look up with MAIL_ADDR_FORM_NOCONV, which leaves keys in
|
|
||||||
* internal form.
|
|
||||||
*/
|
|
||||||
if (ext_addr_buf == 0)
|
|
||||||
ext_addr_buf = vstring_alloc(100);
|
|
||||||
quote_822_local(ext_addr_buf, address);
|
|
||||||
if (strcmp(STR(ext_addr_buf), address) != 0)
|
|
||||||
result = mail_addr_find_opt(path, address, extp,
|
|
||||||
MAIL_ADDR_FORM_NOCONV,
|
|
||||||
MAIL_ADDR_FORM_NOCONV,
|
|
||||||
strategy);
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -455,23 +466,25 @@ const char *mail_addr_find_strategy(MAPS *path, const char *address,
|
|||||||
|
|
||||||
static NORETURN usage(const char *progname)
|
static NORETURN usage(const char *progname)
|
||||||
{
|
{
|
||||||
msg_fatal("usage: %s [-v] database", progname);
|
msg_fatal("usage: %s [-v]", progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
VSTRING *buffer = vstring_alloc(100);
|
VSTRING *buffer = vstring_alloc(100);
|
||||||
char *bp;
|
char *bp;
|
||||||
MAPS *path;
|
MAPS *path = 0;
|
||||||
const char *result;
|
const char *result;
|
||||||
char *extent;
|
char *extent;
|
||||||
char *in_field;
|
char *in_field;
|
||||||
|
char *query_field;
|
||||||
char *out_field;
|
char *out_field;
|
||||||
char *strategy_field;
|
char *strategy_field;
|
||||||
char *key_field;
|
char *key_field;
|
||||||
char *expect_res;
|
char *expect_res;
|
||||||
char *expect_ext;
|
char *expect_ext;
|
||||||
int in_form;
|
int in_form;
|
||||||
|
int query_form;
|
||||||
int out_form;
|
int out_form;
|
||||||
int strategy_flags;
|
int strategy_flags;
|
||||||
int ch;
|
int ch;
|
||||||
@@ -489,7 +502,7 @@ int main(int argc, char **argv)
|
|||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (argc != optind + 1)
|
if (argc != optind)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -502,26 +515,38 @@ int main(int argc, char **argv)
|
|||||||
UPDATE(var_mydomain, "localdomain");
|
UPDATE(var_mydomain, "localdomain");
|
||||||
UPDATE(var_myorigin, "localdomain");
|
UPDATE(var_myorigin, "localdomain");
|
||||||
UPDATE(var_mydest, "localhost.localdomain");
|
UPDATE(var_mydest, "localhost.localdomain");
|
||||||
path = maps_create(argv[0], argv[optind], DICT_FLAG_LOCK
|
|
||||||
| DICT_FLAG_FOLD_FIX | DICT_FLAG_UTF8_REQUEST);
|
|
||||||
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
|
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
|
||||||
bp = STR(buffer);
|
bp = STR(buffer);
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("> %s", bp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quick and dirty.
|
||||||
|
*/
|
||||||
|
if (path == 0) {
|
||||||
|
path = maps_create(argv[0], bp, DICT_FLAG_LOCK
|
||||||
|
| DICT_FLAG_FOLD_FIX | DICT_FLAG_UTF8_REQUEST);
|
||||||
|
vstream_printf("%s\n", bp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse the input and expectations.
|
* Parse the input and expectations.
|
||||||
*/
|
*/
|
||||||
/* internal, external, noconv, or compat. */
|
/* internal, external. */
|
||||||
if ((in_field = mystrtok(&bp, ":")) == 0)
|
if ((in_field = mystrtok(&bp, ":")) == 0)
|
||||||
msg_fatal("no input form");
|
msg_fatal("no input form");
|
||||||
if ((in_form = mail_addr_form_from_string(in_field)) < 0
|
if ((in_form = mail_addr_form_from_string(in_field)) < 0)
|
||||||
&& strcmp(in_field, "compat") != 0)
|
|
||||||
msg_fatal("bad input form: '%s'", in_field);
|
msg_fatal("bad input form: '%s'", in_field);
|
||||||
|
if ((query_field = mystrtok(&bp, ":")) == 0)
|
||||||
|
msg_fatal("no query form");
|
||||||
|
/* internal, external, external-first. */
|
||||||
|
if ((query_form = mail_addr_form_from_string(query_field)) < 0)
|
||||||
|
msg_fatal("bad query form: '%s'", query_field);
|
||||||
if ((out_field = mystrtok(&bp, ":")) == 0)
|
if ((out_field = mystrtok(&bp, ":")) == 0)
|
||||||
msg_fatal("no output form");
|
msg_fatal("no output form");
|
||||||
/* internal, external, noconv, or compat, depending on in_form. */
|
/* internal, external. */
|
||||||
if (((out_form = mail_addr_form_from_string(out_field)) < 0
|
if ((out_form = mail_addr_form_from_string(out_field)) < 0)
|
||||||
&& strcmp(out_field, "compat") != 0)
|
|
||||||
|| ((in_form >= 0) != (out_form >= 0)))
|
|
||||||
msg_fatal("bad output form: '%s'", out_field);
|
msg_fatal("bad output form: '%s'", out_field);
|
||||||
if ((strategy_field = mystrtok(&bp, ":")) == 0)
|
if ((strategy_field = mystrtok(&bp, ":")) == 0)
|
||||||
msg_fatal("no strategy field");
|
msg_fatal("no strategy field");
|
||||||
@@ -538,18 +563,11 @@ int main(int argc, char **argv)
|
|||||||
* Lookups.
|
* Lookups.
|
||||||
*/
|
*/
|
||||||
extent = 0;
|
extent = 0;
|
||||||
if (in_form >= 0 && out_form >= 0) {
|
|
||||||
/* It's the future. */
|
|
||||||
result = mail_addr_find_opt(path, key_field, &extent,
|
result = mail_addr_find_opt(path, key_field, &extent,
|
||||||
in_form, out_form,
|
in_form, query_form, out_form,
|
||||||
strategy_flags);
|
strategy_flags);
|
||||||
} else {
|
vstream_printf("%s:%s -%s-> %s:%s (%s)\n",
|
||||||
/* Backwards compatibility. */
|
in_field, key_field, query_field, out_field, result ? result :
|
||||||
result = mail_addr_find_strategy(path, key_field, &extent,
|
|
||||||
strategy_flags);
|
|
||||||
}
|
|
||||||
vstream_printf("%s:%s -> %s:%s (%s)\n",
|
|
||||||
in_field, key_field, out_field, result ? result :
|
|
||||||
path->error ? "(try again)" :
|
path->error ? "(try again)" :
|
||||||
"(not found)", extent ? extent : "null extension");
|
"(not found)", extent ? extent : "null extension");
|
||||||
vstream_fflush(VSTREAM_OUT);
|
vstream_fflush(VSTREAM_OUT);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef _MAIL_ADDR_FIND_H_INCLUDED_
|
#ifndef _MAF_STRATEGY_H_INCLUDED_
|
||||||
#define _MAIL_ADDR_FIND_H_INCLUDED_
|
#define _MAF_STRATEGY_H_INCLUDED_
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
/* NAME
|
/* NAME
|
||||||
@@ -21,37 +21,47 @@
|
|||||||
* External interface.
|
* External interface.
|
||||||
*/
|
*/
|
||||||
extern const char *mail_addr_find_opt(MAPS *, const char *, char **,
|
extern const char *mail_addr_find_opt(MAPS *, const char *, char **,
|
||||||
int, int, int);
|
int, int, int, int);
|
||||||
|
|
||||||
#define MAIL_ADDR_FIND_FULL (1<<0) /* localpart+ext@domain */
|
#define MAF_STRATEGY_FULL (1<<0) /* localpart+ext@domain */
|
||||||
#define MAIL_ADDR_FIND_NOEXT (1<<1) /* localpart@domain */
|
#define MAF_STRATEGY_NOEXT (1<<1) /* localpart@domain */
|
||||||
#define MAIL_ADDR_FIND_LOCALPART_IF_LOCAL \
|
#define MAF_STRATEGY_LOCALPART_IF_LOCAL \
|
||||||
(1<<2) /* localpart (maybe localpart+ext) */
|
(1<<2) /* localpart (maybe localpart+ext) */
|
||||||
#define MAIL_ADDR_FIND_LOCALPART_AT_IF_LOCAL \
|
#define MAF_STRATEGY_LOCALPART_AT_IF_LOCAL \
|
||||||
(1<<3) /* ditto, with @ at end */
|
(1<<3) /* ditto, with @ at end */
|
||||||
#define MAIL_ADDR_FIND_ATDOMAIN (1<<4) /* @domain */
|
#define MAF_STRATEGY_AT_DOMAIN (1<<4) /* @domain */
|
||||||
#define MAIL_ADDR_FIND_DOMAIN (1<<5) /* domain */
|
#define MAF_STRATEGY_DOMAIN (1<<5) /* domain */
|
||||||
#define MAIL_ADDR_FIND_PMS (1<<6) /* parent matches subdomain */
|
#define MAF_STRATEGY_PMS (1<<6) /* parent matches subdomain */
|
||||||
#define MAIL_ADDR_FIND_PMDS (1<<7) /* parent matches dot-subdomain */
|
#define MAF_STRATEGY_PMDS (1<<7) /* parent matches dot-subdomain */
|
||||||
#define MAIL_ADDR_FIND_LOCALPART_AT \
|
#define MAF_STRATEGY_LOCALPART_AT \
|
||||||
(1<<8) /* localpart@ (maybe localpart+ext@) */
|
(1<<8) /* localpart@ (maybe localpart+ext@) */
|
||||||
|
|
||||||
#define MAIL_ADDR_FIND_DEFAULT (MAIL_ADDR_FIND_FULL | MAIL_ADDR_FIND_NOEXT \
|
#define MAF_STRATEGY_DEFAULT (MAF_STRATEGY_FULL | MAF_STRATEGY_NOEXT \
|
||||||
| MAIL_ADDR_FIND_LOCALPART_IF_LOCAL \
|
| MAF_STRATEGY_LOCALPART_IF_LOCAL \
|
||||||
| MAIL_ADDR_FIND_ATDOMAIN)
|
| MAF_STRATEGY_AT_DOMAIN)
|
||||||
|
|
||||||
/* The least-overhead form. */
|
/* The least-overhead form. */
|
||||||
#define mail_addr_find_int_to_ext(maps, address, extension) \
|
#define mail_addr_find_int_to_ext(maps, address, extension) \
|
||||||
mail_addr_find_opt((maps), (address), (extension), \
|
mail_addr_find_opt((maps), (address), (extension), \
|
||||||
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_EXTERNAL, \
|
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_EXTERNAL, \
|
||||||
MAIL_ADDR_FIND_DEFAULT)
|
MAIL_ADDR_FORM_EXTERNAL, MAF_STRATEGY_DEFAULT)
|
||||||
|
|
||||||
/* The legacy form. */
|
/* The legacy forms. */
|
||||||
extern const char *mail_addr_find_strategy(MAPS *, const char *, char **, int);
|
#define MAF_FORM_LEGACY \
|
||||||
|
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_EXTERNAL_FIRST, \
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL
|
||||||
|
|
||||||
|
#define mail_addr_find_strategy(maps, address, extension, strategy) \
|
||||||
|
mail_addr_find_opt((maps), (address), (extension), \
|
||||||
|
MAF_FORM_LEGACY, (strategy))
|
||||||
|
|
||||||
#define mail_addr_find(maps, address, extension) \
|
#define mail_addr_find(maps, address, extension) \
|
||||||
mail_addr_find_strategy((maps), (address), (extension), \
|
mail_addr_find_strategy((maps), (address), (extension), \
|
||||||
MAIL_ADDR_FIND_DEFAULT)
|
MAF_STRATEGY_DEFAULT)
|
||||||
|
|
||||||
|
#define mail_addr_find_to_internal(maps, address, extension) \
|
||||||
|
mail_addr_find_opt((maps), (address), (extension), \
|
||||||
|
MAF_FORM_LEGACY, MAF_STRATEGY_DEFAULT)
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
|
@@ -4,78 +4,94 @@
|
|||||||
# The last fields are optional.
|
# The last fields are optional.
|
||||||
|
|
||||||
echo ==== no search string extension
|
echo ==== no search string extension
|
||||||
$VALGRIND ./mail_addr_find 'inline:{plain1@1.example=plain2@2.example,{"aa bb"@cc.example="dd ee"@dd.example}}' <<'EOF'
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
internal:external:default:plain1@1.example:plain2@2.example
|
inline:{plain1@1.example=plain2@2.example,{"aa bb"@cc.example="dd ee"@dd.example}}
|
||||||
internal:external:default:aa bb@cc.example:"dd ee"@dd.example
|
internal:external:external:default:plain1@1.example:plain2@2.example
|
||||||
external:external:default:"aa bb"@cc.example:"dd ee"@dd.example
|
internal:external:external:default:aa bb@cc.example:"dd ee"@dd.example
|
||||||
external:internal:default:"aa bb"@cc.example:dd ee@dd.example
|
external:external:external:default:"aa bb"@cc.example:"dd ee"@dd.example
|
||||||
noconv:noconv:default:plain1@1.example:plain2@2.example
|
external:external:internal:default:"aa bb"@cc.example:dd ee@dd.example
|
||||||
noconv:noconv:default:aa bb@cc.example
|
internal:internal:external:default:plain1@1.example:plain2@2.example
|
||||||
noconv:noconv:default:"aa bb"@cc.example:"dd ee"@dd.example
|
internal:internal:external:default:aa bb@cc.example
|
||||||
|
internal:internal:external:default:"aa bb"@cc.example:"dd ee"@dd.example
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo ==== with search string extension
|
echo ==== with search string extension
|
||||||
$VALGRIND ./mail_addr_find 'inline:{plain1@1.example=plain2@2.example,{"aa bb"@cc.example="dd ee"@dd.example}}' <<'EOF'
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
internal:external:default:plain1+ext@1.example:plain2@2.example:+ext
|
inline:{plain1@1.example=plain2@2.example,{"aa bb"@cc.example="dd ee"@dd.example}}
|
||||||
internal:external:default:aa bb+ax bx@cc.example:"dd ee"@dd.example:+ax bx
|
internal:external:external:default:plain1+ext@1.example:plain2@2.example:+ext
|
||||||
external:external:default:"aa bb+ax bx"@cc.example:"dd ee"@dd.example:+ax bx
|
internal:external:external:default:aa bb+ax bx@cc.example:"dd ee"@dd.example:+ax bx
|
||||||
external:internal:default:"aa bb+ax bx"@cc.example:dd ee@dd.example:+ax bx
|
external:external:external:default:"aa bb+ax bx"@cc.example:"dd ee"@dd.example:+ax bx
|
||||||
noconv:noconv:default:plain1+ext@1.example:plain2@2.example:+ext
|
external:external:internal:default:"aa bb+ax bx"@cc.example:dd ee@dd.example:+ax bx
|
||||||
noconv:noconv:default:"aa bb+ax bx"@cc.example
|
internal:internal:external:default:plain1+ext@1.example:plain2@2.example:+ext
|
||||||
noconv:noconv:default:"aa bb"+ax bx@cc.example:"dd ee"@dd.example:+ax bx
|
internal:internal:external:default:"aa bb+ax bx"@cc.example
|
||||||
|
internal:internal:external:default:"aa bb"+ax bx@cc.example:"dd ee"@dd.example:+ax bx
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo ==== at in localpart
|
echo ==== at in localpart
|
||||||
$VALGRIND ./mail_addr_find 'inline:{"a@b"=foo@example,"a.b."=bar@example}' <<'EOF'
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
external:external:default:"a@b"@localhost.localdomain:foo@example
|
inline:{"a@b"=foo@example,"a.b."=bar@example}
|
||||||
external:external:default:"a@b+ext"@localhost.localdomain:foo@example:+ext
|
external:external:external:default:"a@b"@localhost.localdomain:foo@example
|
||||||
external:external:default:"a.b."@localhost.localdomain:bar@example
|
external:external:external:default:"a@b+ext"@localhost.localdomain:foo@example:+ext
|
||||||
|
external:external:external:default:"a.b."@localhost.localdomain:bar@example
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo ==== legacy support
|
echo ==== legacy support
|
||||||
$VALGRIND ./mail_addr_find 'inline:{"a@b"=extern-1@example,a@b=intern-1@example,a.b.=intern-2@example}' <<'EOF'
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
compat:compat:default:a@b@localhost.localdomain:extern-1@example
|
inline:{"a@b"=extern-1@example,a@b=intern-1@example,a.b.=intern-2@example}
|
||||||
compat:compat:default:a.b.@localhost.localdomain:intern-2@example
|
internal:external-first:external:default:a@b@localhost.localdomain:extern-1@example
|
||||||
|
internal:external-first:external:default:a.b.@localhost.localdomain:intern-2@example
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo ==== atdomain test
|
echo ==== at_domain test
|
||||||
$VALGRIND ./mail_addr_find 'inline:{plain1@1.example=plain2@2.example,@3.example=plain4@4.example,plain5@3.example=plain6@6.example}' <<'EOF'
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
external:external:default:plain1+ext@1.example:plain2@2.example:+ext
|
inline:{plain1@1.example=plain2@2.example,@3.example=plain4@4.example,plain5@3.example=plain6@6.example}
|
||||||
external:external:default:plain2@2.example:
|
external:external:external:default:plain1+ext@1.example:plain2@2.example:+ext
|
||||||
external:external:default:plain3@3.example:plain4@4.example
|
external:external:external:default:plain2@2.example:
|
||||||
external:external:default:plain5@3.example:plain6@6.example
|
external:external:external:default:plain3@3.example:plain4@4.example
|
||||||
|
external:external:external:default:plain5@3.example:plain6@6.example
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo ==== domain test
|
echo ==== domain test
|
||||||
$VALGRIND ./mail_addr_find 'inline:{plain1@1.example=plain2@2.example,3.example=plain4@4.example,plain5@3.example=plain6@6.example}' <<'EOF'
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
external:external:full|noext|domain:plain1+ext@1.example:plain2@2.example:+ext
|
inline:{plain1@1.example=plain2@2.example,3.example=plain4@4.example,plain5@3.example=plain6@6.example}
|
||||||
external:external:full|noext|domain:plain2@2.example:
|
external:external:external:full|noext|domain:plain1+ext@1.example:plain2@2.example:+ext
|
||||||
external:external:full|noext|domain:plain3@3.example:plain4@4.example
|
external:external:external:full|noext|domain:plain2@2.example:
|
||||||
external:external:full|noext|domain:plain5@3.example:plain6@6.example
|
external:external:external:full|noext|domain:plain3@3.example:plain4@4.example
|
||||||
|
external:external:external:full|noext|domain:plain5@3.example:plain6@6.example
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo ==== atdomain for local domain
|
echo ==== at_domain for local domain
|
||||||
$VALGRIND ./mail_addr_find 'inline:{ab=foo@example,@localhost.localdomain=@bar.example}' <<'EOF'
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
external:external:default:ab@localhost.localdomain:foo@example:
|
inline:{ab=foo@example,@localhost.localdomain=@bar.example}
|
||||||
external:external:default:cd@localhost.localdomain:@bar.example
|
external:external:external:default:ab@localhost.localdomain:foo@example:
|
||||||
|
external:external:external:default:cd@localhost.localdomain:@bar.example
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo ==== localat and domain test
|
echo ==== localpart_at_if_local and domain test
|
||||||
$VALGRIND ./mail_addr_find 'inline:{ab@=foo@example,localhost.localdomain=@bar.example}' <<'EOF'
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
internal:external:localpart_at_if_local|domain:ab@localhost.localdomain:foo@example:
|
inline:{ab@=foo@example,localhost.localdomain=@bar.example}
|
||||||
internal:external:localpart_at_if_local|noext|domain:ab+ext@localhost.localdomain:foo@example:+ext
|
internal:external:external:localpart_at_if_local|domain:ab@localhost.localdomain:foo@example:
|
||||||
internal:external:localpart_at_if_local|domain:cd@localhost.localdomain:@bar.example
|
internal:external:external:localpart_at_if_local|noext|domain:ab+ext@localhost.localdomain:foo@example:+ext
|
||||||
|
internal:external:external:localpart_at_if_local|domain:cd@localhost.localdomain:@bar.example
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ==== localpart_at has less precedence than domain test
|
||||||
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
|
inline:{ab@=foo@example,localhost.localdomain=@bar.example}
|
||||||
|
external:external:external:localpart_at|domain:ab@localhost.localdomain:@bar.example:
|
||||||
|
external:external:external:localpart_at|domain:ab@foo:foo@example
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo ==== domain and subdomain test
|
echo ==== domain and subdomain test
|
||||||
$VALGRIND ./mail_addr_find 'inline:{example=example-result,.example=dot-example-result}' <<'EOF'
|
$VALGRIND ./mail_addr_find <<'EOF'
|
||||||
external:external:domain:plain1+ext@1.example
|
inline:{example=example-result,.example=dot-example-result}
|
||||||
external:external:domain:foo@sub.example
|
external:external:external:domain:plain1+ext@1.example
|
||||||
external:external:domain:foo@example:example-result
|
external:external:external:domain:foo@sub.example
|
||||||
external:external:domain|pms:foo@example:example-result
|
external:external:external:domain:foo@example:example-result
|
||||||
external:external:domain|pms:foo@sub.example:example-result
|
external:external:external:domain|pms:foo@example:example-result
|
||||||
external:external:domain|pms:foo@sub.sub.example:example-result
|
external:external:external:domain|pms:foo@sub.example:example-result
|
||||||
external:external:domain|pmds:foo@example:example-result
|
external:external:external:domain|pms:foo@sub.sub.example:example-result
|
||||||
external:external:domain|pmds:foo@sub.example:dot-example-result
|
external:external:external:domain|pmds:foo@example:example-result
|
||||||
external:external:domain|pmds:foo@sub.sub.example:dot-example-result
|
external:external:external:domain|pmds:foo@sub.example:dot-example-result
|
||||||
|
external:external:external:domain|pmds:foo@sub.sub.example:dot-example-result
|
||||||
EOF
|
EOF
|
||||||
|
@@ -1,50 +1,63 @@
|
|||||||
==== no search string extension
|
==== no search string extension
|
||||||
internal:plain1@1.example -> external:plain2@2.example (null extension)
|
inline:{plain1@1.example=plain2@2.example,{"aa bb"@cc.example="dd ee"@dd.example}}
|
||||||
internal:aa bb@cc.example -> external:"dd ee"@dd.example (null extension)
|
internal:plain1@1.example -external-> external:plain2@2.example (null extension)
|
||||||
external:"aa bb"@cc.example -> external:"dd ee"@dd.example (null extension)
|
internal:aa bb@cc.example -external-> external:"dd ee"@dd.example (null extension)
|
||||||
external:"aa bb"@cc.example -> internal:dd ee@dd.example (null extension)
|
external:"aa bb"@cc.example -external-> external:"dd ee"@dd.example (null extension)
|
||||||
noconv:plain1@1.example -> noconv:plain2@2.example (null extension)
|
external:"aa bb"@cc.example -external-> internal:dd ee@dd.example (null extension)
|
||||||
noconv:aa bb@cc.example -> noconv:(not found) (null extension)
|
internal:plain1@1.example -internal-> external:plain2@2.example (null extension)
|
||||||
noconv:"aa bb"@cc.example -> noconv:"dd ee"@dd.example (null extension)
|
internal:aa bb@cc.example -internal-> external:(not found) (null extension)
|
||||||
|
internal:"aa bb"@cc.example -internal-> external:"dd ee"@dd.example (null extension)
|
||||||
==== with search string extension
|
==== with search string extension
|
||||||
internal:plain1+ext@1.example -> external:plain2@2.example (+ext)
|
inline:{plain1@1.example=plain2@2.example,{"aa bb"@cc.example="dd ee"@dd.example}}
|
||||||
internal:aa bb+ax bx@cc.example -> external:"dd ee"@dd.example (+ax bx)
|
internal:plain1+ext@1.example -external-> external:plain2@2.example (+ext)
|
||||||
external:"aa bb+ax bx"@cc.example -> external:"dd ee"@dd.example (+ax bx)
|
internal:aa bb+ax bx@cc.example -external-> external:"dd ee"@dd.example (+ax bx)
|
||||||
external:"aa bb+ax bx"@cc.example -> internal:dd ee@dd.example (+ax bx)
|
external:"aa bb+ax bx"@cc.example -external-> external:"dd ee"@dd.example (+ax bx)
|
||||||
noconv:plain1+ext@1.example -> noconv:plain2@2.example (+ext)
|
external:"aa bb+ax bx"@cc.example -external-> internal:dd ee@dd.example (+ax bx)
|
||||||
noconv:"aa bb+ax bx"@cc.example -> noconv:(not found) (null extension)
|
internal:plain1+ext@1.example -internal-> external:plain2@2.example (+ext)
|
||||||
noconv:"aa bb"+ax bx@cc.example -> noconv:"dd ee"@dd.example (+ax bx)
|
internal:"aa bb+ax bx"@cc.example -internal-> external:(not found) (null extension)
|
||||||
|
internal:"aa bb"+ax bx@cc.example -internal-> external:"dd ee"@dd.example (+ax bx)
|
||||||
==== at in localpart
|
==== at in localpart
|
||||||
external:"a@b"@localhost.localdomain -> external:foo@example (null extension)
|
inline:{"a@b"=foo@example,"a.b."=bar@example}
|
||||||
external:"a@b+ext"@localhost.localdomain -> external:foo@example (+ext)
|
external:"a@b"@localhost.localdomain -external-> external:foo@example (null extension)
|
||||||
external:"a.b."@localhost.localdomain -> external:bar@example (null extension)
|
external:"a@b+ext"@localhost.localdomain -external-> external:foo@example (+ext)
|
||||||
|
external:"a.b."@localhost.localdomain -external-> external:bar@example (null extension)
|
||||||
==== legacy support
|
==== legacy support
|
||||||
compat:a@b@localhost.localdomain -> compat:extern-1@example (null extension)
|
inline:{"a@b"=extern-1@example,a@b=intern-1@example,a.b.=intern-2@example}
|
||||||
compat:a.b.@localhost.localdomain -> compat:intern-2@example (null extension)
|
internal:a@b@localhost.localdomain -external-first-> external:extern-1@example (null extension)
|
||||||
==== atdomain test
|
internal:a.b.@localhost.localdomain -external-first-> external:intern-2@example (null extension)
|
||||||
external:plain1+ext@1.example -> external:plain2@2.example (+ext)
|
==== at_domain test
|
||||||
external:plain2@2.example -> external:(not found) (null extension)
|
inline:{plain1@1.example=plain2@2.example,@3.example=plain4@4.example,plain5@3.example=plain6@6.example}
|
||||||
external:plain3@3.example -> external:plain4@4.example (null extension)
|
external:plain1+ext@1.example -external-> external:plain2@2.example (+ext)
|
||||||
external:plain5@3.example -> external:plain6@6.example (null extension)
|
external:plain2@2.example -external-> external:(not found) (null extension)
|
||||||
|
external:plain3@3.example -external-> external:plain4@4.example (null extension)
|
||||||
|
external:plain5@3.example -external-> external:plain6@6.example (null extension)
|
||||||
==== domain test
|
==== domain test
|
||||||
external:plain1+ext@1.example -> external:plain2@2.example (+ext)
|
inline:{plain1@1.example=plain2@2.example,3.example=plain4@4.example,plain5@3.example=plain6@6.example}
|
||||||
external:plain2@2.example -> external:(not found) (null extension)
|
external:plain1+ext@1.example -external-> external:plain2@2.example (+ext)
|
||||||
external:plain3@3.example -> external:plain4@4.example (null extension)
|
external:plain2@2.example -external-> external:(not found) (null extension)
|
||||||
external:plain5@3.example -> external:plain6@6.example (null extension)
|
external:plain3@3.example -external-> external:plain4@4.example (null extension)
|
||||||
==== atdomain for local domain
|
external:plain5@3.example -external-> external:plain6@6.example (null extension)
|
||||||
external:ab@localhost.localdomain -> external:foo@example (null extension)
|
==== at_domain for local domain
|
||||||
external:cd@localhost.localdomain -> external:@bar.example (null extension)
|
inline:{ab=foo@example,@localhost.localdomain=@bar.example}
|
||||||
==== localat and domain test
|
external:ab@localhost.localdomain -external-> external:foo@example (null extension)
|
||||||
internal:ab@localhost.localdomain -> external:foo@example (null extension)
|
external:cd@localhost.localdomain -external-> external:@bar.example (null extension)
|
||||||
internal:ab+ext@localhost.localdomain -> external:foo@example (+ext)
|
==== localpart_at_if_local and domain test
|
||||||
internal:cd@localhost.localdomain -> external:@bar.example (null extension)
|
inline:{ab@=foo@example,localhost.localdomain=@bar.example}
|
||||||
|
internal:ab@localhost.localdomain -external-> external:foo@example (null extension)
|
||||||
|
internal:ab+ext@localhost.localdomain -external-> external:foo@example (+ext)
|
||||||
|
internal:cd@localhost.localdomain -external-> external:@bar.example (null extension)
|
||||||
|
==== localpart_at has less precedence than domain test
|
||||||
|
inline:{ab@=foo@example,localhost.localdomain=@bar.example}
|
||||||
|
external:ab@localhost.localdomain -external-> external:@bar.example (null extension)
|
||||||
|
external:ab@foo -external-> external:foo@example (null extension)
|
||||||
==== domain and subdomain test
|
==== domain and subdomain test
|
||||||
external:plain1+ext@1.example -> external:(not found) (null extension)
|
inline:{example=example-result,.example=dot-example-result}
|
||||||
external:foo@sub.example -> external:(not found) (null extension)
|
external:plain1+ext@1.example -external-> external:(not found) (null extension)
|
||||||
external:foo@example -> external:example-result (null extension)
|
external:foo@sub.example -external-> external:(not found) (null extension)
|
||||||
external:foo@example -> external:example-result (null extension)
|
external:foo@example -external-> external:example-result (null extension)
|
||||||
external:foo@sub.example -> external:example-result (null extension)
|
external:foo@example -external-> external:example-result (null extension)
|
||||||
external:foo@sub.sub.example -> external:example-result (null extension)
|
external:foo@sub.example -external-> external:example-result (null extension)
|
||||||
external:foo@example -> external:example-result (null extension)
|
external:foo@sub.sub.example -external-> external:example-result (null extension)
|
||||||
external:foo@sub.example -> external:dot-example-result (null extension)
|
external:foo@example -external-> external:example-result (null extension)
|
||||||
external:foo@sub.sub.example -> external:dot-example-result (null extension)
|
external:foo@sub.example -external-> external:dot-example-result (null extension)
|
||||||
|
external:foo@sub.sub.example -external-> external:dot-example-result (null extension)
|
||||||
|
@@ -11,9 +11,9 @@
|
|||||||
/* const char *mail_addr_form_to_string(int addr_form)
|
/* const char *mail_addr_form_to_string(int addr_form)
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* mail_addr_form_from_string() converts a symbolic mail address
|
/* mail_addr_form_from_string() converts a symbolic mail address
|
||||||
/* form name ("internal", "external", "noconv") into the
|
/* form name ("internal", "external", "internal-first") into the
|
||||||
/* corresponding internal code. The result is -1 if an
|
/* corresponding internal code. The result is -1 if an unrecognized
|
||||||
/* unrecognized name was specified.
|
/* name was specified.
|
||||||
/*
|
/*
|
||||||
/* mail_addr_form_to_string() converts from internal code
|
/* mail_addr_form_to_string() converts from internal code
|
||||||
/* to the corresponding symbolic name. The result is null if
|
/* to the corresponding symbolic name. The result is null if
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
static const NAME_CODE addr_form_table[] = {
|
static const NAME_CODE addr_form_table[] = {
|
||||||
"external", MAIL_ADDR_FORM_EXTERNAL,
|
"external", MAIL_ADDR_FORM_EXTERNAL,
|
||||||
"internal", MAIL_ADDR_FORM_INTERNAL,
|
"internal", MAIL_ADDR_FORM_INTERNAL,
|
||||||
"noconv", MAIL_ADDR_FORM_NOCONV,
|
"external-first", MAIL_ADDR_FORM_EXTERNAL_FIRST,
|
||||||
0, -1,
|
0, -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -12,12 +12,11 @@
|
|||||||
/* .nf
|
/* .nf
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* External interface. The MAIL_ADDR_FORM_NOCONV is for legacy code that
|
* External interface.
|
||||||
* hasn't yet been converted to external-form address lookups.
|
|
||||||
*/
|
*/
|
||||||
#define MAIL_ADDR_FORM_NOCONV 0 /* do not convert */
|
|
||||||
#define MAIL_ADDR_FORM_INTERNAL 1 /* unquoted form */
|
#define MAIL_ADDR_FORM_INTERNAL 1 /* unquoted form */
|
||||||
#define MAIL_ADDR_FORM_EXTERNAL 2 /* quoted form */
|
#define MAIL_ADDR_FORM_EXTERNAL 2 /* quoted form */
|
||||||
|
#define MAIL_ADDR_FORM_EXTERNAL_FIRST 3 /* quoted form, then unquoted */
|
||||||
|
|
||||||
extern int mail_addr_form_from_string(const char *);
|
extern int mail_addr_form_from_string(const char *);
|
||||||
extern const char *mail_addr_form_to_string(int);
|
extern const char *mail_addr_form_to_string(int);
|
||||||
|
@@ -11,11 +11,14 @@
|
|||||||
/* const char *address;
|
/* const char *address;
|
||||||
/* int propagate;
|
/* int propagate;
|
||||||
/*
|
/*
|
||||||
/* ARGV *mail_addr_map_opt(path, address, propagate, in_form, out_form)
|
/* ARGV *mail_addr_map_opt(path, address, propagate, in_form,
|
||||||
|
/* query_form, out_form)
|
||||||
/* MAPS *path;
|
/* MAPS *path;
|
||||||
/* const char *address;
|
/* const char *address;
|
||||||
/* int propagate;
|
/* int propagate;
|
||||||
/* int how;
|
/* int in_form;
|
||||||
|
/* int query_form;
|
||||||
|
/* int out_form;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* mail_addr_map_*() returns the translation for the named address,
|
/* mail_addr_map_*() returns the translation for the named address,
|
||||||
/* or a null pointer if none is found.
|
/* or a null pointer if none is found.
|
||||||
@@ -35,18 +38,17 @@
|
|||||||
/* form \fI@otherdomain\fR, the result is the original user in
|
/* form \fI@otherdomain\fR, the result is the original user in
|
||||||
/* \fIotherdomain\fR.
|
/* \fIotherdomain\fR.
|
||||||
/*
|
/*
|
||||||
/* mail_addr_map_opt() gives additional control over whether the
|
|
||||||
/* input is in internal (unquoted) or external (quoted) form.
|
|
||||||
/* to internal form and invokes mail_addr_map_int_to_ext().
|
|
||||||
/* This may introduce additional unqoute822_local() and
|
|
||||||
/* quote_833_local() calls.
|
|
||||||
/*
|
|
||||||
/* Arguments:
|
/* Arguments:
|
||||||
/* .IP path
|
/* .IP path
|
||||||
/* Dictionary search path (see maps(3)).
|
/* Dictionary search path (see maps(3)).
|
||||||
/* .IP address
|
/* .IP address
|
||||||
/* The address to be looked up in external (quoted) form, or
|
/* The address to be looked up in external (quoted) form, or
|
||||||
/* in the form specified with the in_form argument.
|
/* in the form specified with the in_form argument.
|
||||||
|
/* .IP query_form
|
||||||
|
/* Database query address forms, either MAIL_ADDR_FORM_INTERNAL
|
||||||
|
/* (unquoted form), MAIL_ADDR_FORM_EXTERNAL_FIRST (external, then
|
||||||
|
/* internal if the forms differ) or MAIL_ADDR_FORM_EXTERNAL
|
||||||
|
/* (quoted form).
|
||||||
/* .IP in_form
|
/* .IP in_form
|
||||||
/* .IP out_form
|
/* .IP out_form
|
||||||
/* Input and output address forms, either MAIL_ADDR_FORM_INTERNAL
|
/* Input and output address forms, either MAIL_ADDR_FORM_INTERNAL
|
||||||
@@ -98,7 +100,7 @@
|
|||||||
/* mail_addr_map - map a canonical address */
|
/* mail_addr_map - map a canonical address */
|
||||||
|
|
||||||
ARGV *mail_addr_map_opt(MAPS *path, const char *address, int propagate,
|
ARGV *mail_addr_map_opt(MAPS *path, const char *address, int propagate,
|
||||||
int in_form, int out_form)
|
int in_form, int query_form, int out_form)
|
||||||
{
|
{
|
||||||
VSTRING *buffer = 0;
|
VSTRING *buffer = 0;
|
||||||
const char *myname = "mail_addr_map";
|
const char *myname = "mail_addr_map";
|
||||||
@@ -111,16 +113,9 @@ ARGV *mail_addr_map_opt(MAPS *path, const char *address, int propagate,
|
|||||||
VSTRING *ext_address = 0;
|
VSTRING *ext_address = 0;
|
||||||
const char *int_addr;
|
const char *int_addr;
|
||||||
|
|
||||||
/* Crutch until we can retire MAIL_ADDR_FORM_NOCONV. */
|
|
||||||
int mid_form = (out_form == MAIL_ADDR_FORM_NOCONV ?
|
|
||||||
MAIL_ADDR_FORM_NOCONV : MAIL_ADDR_FORM_EXTERNAL);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Optionally convert input from external form. We prefer internal-form
|
* Optionally convert input from external form. We prefer internal-form
|
||||||
* input to avoid an unnecessary input conversion in
|
* input to avoid unnecessary input conversion in mail_addr_find_opt().
|
||||||
* mail_addr_find_opt(). But the consequence is that we have to convert
|
|
||||||
* the internal-form input's localpart to external form when mapping
|
|
||||||
* @domain -> @domain.
|
|
||||||
*/
|
*/
|
||||||
if (in_form == MAIL_ADDR_FORM_EXTERNAL) {
|
if (in_form == MAIL_ADDR_FORM_EXTERNAL) {
|
||||||
int_address = vstring_alloc(100);
|
int_address = vstring_alloc(100);
|
||||||
@@ -134,16 +129,16 @@ ARGV *mail_addr_map_opt(MAPS *path, const char *address, int propagate,
|
|||||||
/*
|
/*
|
||||||
* Look up the full address; if no match is found, look up the address
|
* Look up the full address; if no match is found, look up the address
|
||||||
* with the extension stripped off, and remember the unmatched extension.
|
* with the extension stripped off, and remember the unmatched extension.
|
||||||
* We explicitly call the mail_addr_find_opt() variant that does not
|
|
||||||
* convert the lookup result.
|
|
||||||
*/
|
*/
|
||||||
if ((string = mail_addr_find_opt(path, int_addr, &extension,
|
if ((string = mail_addr_find_opt(path, int_addr, &extension,
|
||||||
in_form, mid_form,
|
in_form, query_form,
|
||||||
MAIL_ADDR_FIND_DEFAULT)) != 0) {
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAF_STRATEGY_DEFAULT)) != 0) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepend the original user to @otherdomain, but do not propagate
|
* Prepend the original user to @otherdomain, but do not propagate
|
||||||
* the unmatched address extension.
|
* the unmatched address extension. Convert the address to external
|
||||||
|
* form just like the mail_addr_find_opt() output.
|
||||||
*/
|
*/
|
||||||
if (*string == '@') {
|
if (*string == '@') {
|
||||||
buffer = vstring_alloc(100);
|
buffer = vstring_alloc(100);
|
||||||
@@ -153,9 +148,9 @@ ARGV *mail_addr_map_opt(MAPS *path, const char *address, int propagate,
|
|||||||
vstring_strcpy(buffer, int_addr);
|
vstring_strcpy(buffer, int_addr);
|
||||||
if (extension)
|
if (extension)
|
||||||
vstring_truncate(buffer, LEN(buffer) - strlen(extension));
|
vstring_truncate(buffer, LEN(buffer) - strlen(extension));
|
||||||
ext_address = vstring_alloc(100);
|
vstring_strcat(buffer, string);
|
||||||
|
ext_address = vstring_alloc(2 * LEN(buffer));
|
||||||
quote_822_local(ext_address, STR(buffer));
|
quote_822_local(ext_address, STR(buffer));
|
||||||
vstring_strcat(ext_address, string);
|
|
||||||
string = STR(ext_address);
|
string = STR(ext_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +159,7 @@ ARGV *mail_addr_map_opt(MAPS *path, const char *address, int propagate,
|
|||||||
* each address found.
|
* each address found.
|
||||||
*/
|
*/
|
||||||
argv = mail_addr_crunch_opt(string, propagate ? extension : 0,
|
argv = mail_addr_crunch_opt(string, propagate ? extension : 0,
|
||||||
mid_form, out_form);
|
MAIL_ADDR_FORM_EXTERNAL, out_form);
|
||||||
if (buffer)
|
if (buffer)
|
||||||
vstring_free(buffer);
|
vstring_free(buffer);
|
||||||
if (ext_address)
|
if (ext_address)
|
||||||
@@ -199,3 +194,334 @@ ARGV *mail_addr_map_opt(MAPS *path, const char *address, int propagate,
|
|||||||
|
|
||||||
return (argv);
|
return (argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SYNOPSIS
|
||||||
|
* mail_addr_map pass_tests | fail_tests
|
||||||
|
* DESCRIPTION
|
||||||
|
* mail_addr_map performs the specified set of built-in
|
||||||
|
* unit tests. With 'pass_tests', all tests must pass, and
|
||||||
|
* with 'fail_tests' all tests must fail.
|
||||||
|
* DIAGNOSTICS
|
||||||
|
* When a unit test fails, the program prints details of the
|
||||||
|
* failed test.
|
||||||
|
*
|
||||||
|
* The program terminates with a non-zero exit status when at
|
||||||
|
* least one test does not pass with 'pass_tests', or when at
|
||||||
|
* least one test does not fail with 'fail_tests'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* System library. */
|
||||||
|
|
||||||
|
#include <sys_defs.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <argv.h>
|
||||||
|
#include <msg.h>
|
||||||
|
#include <mymalloc.h>
|
||||||
|
#include <vstring.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <canon_addr.h>
|
||||||
|
#include <mail_addr_map.h>
|
||||||
|
#include <mail_conf.h> /* XXX eliminate main.cf dependency */
|
||||||
|
#include <mail_params.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
#define STR vstring_str
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *testname;
|
||||||
|
const char *database;
|
||||||
|
int propagate;
|
||||||
|
const char *delimiter;
|
||||||
|
int in_form;
|
||||||
|
int query_form;
|
||||||
|
int out_form;
|
||||||
|
const char *address;
|
||||||
|
const char *expect_argv[2];
|
||||||
|
int expect_argc;
|
||||||
|
} MAIL_ADDR_MAP_TEST;
|
||||||
|
|
||||||
|
#define DONT_PROPAGATE_UNMATCHED_EXTENSION 0
|
||||||
|
#define DO_PROPAGATE_UNMATCHED_EXTENSION 1
|
||||||
|
#define NO_RECIPIENT_DELIMITER ""
|
||||||
|
#define PLUS_RECIPIENT_DELIMITER "+"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All these tests must pass, so that we know that mail_addr_map_opt() works
|
||||||
|
* as intended. mail_addr_map() has always been used for maps that expect
|
||||||
|
* external-form queries, so there are no tests here for internal-form
|
||||||
|
* queries.
|
||||||
|
*/
|
||||||
|
static MAIL_ADDR_MAP_TEST pass_tests[] = {
|
||||||
|
{
|
||||||
|
"1 external -external-> external, no extension",
|
||||||
|
"inline:{ aa@example.com=bb@example.com }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"aa@example.com",
|
||||||
|
{"bb@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"2 external -external-> external, extension, propagation",
|
||||||
|
"inline:{ aa@example.com=bb@example.com }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"aa+ext@example.com",
|
||||||
|
{"bb+ext@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"3 external -external-> external, extension, no propagation, no match",
|
||||||
|
"inline:{ aa@example.com=bb@example.com }",
|
||||||
|
DONT_PROPAGATE_UNMATCHED_EXTENSION, NO_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"aa+ext@example.com",
|
||||||
|
{0}, 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"4 external -external-> external, extension, full match",
|
||||||
|
"inline:{{cc+ext@example.com=dd@example.com,ee@example.com}}",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"cc+ext@example.com",
|
||||||
|
{"dd@example.com", "ee@example.com"}, 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"5 external -external-> external, no extension, quoted",
|
||||||
|
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"\"a a\"@example.com",
|
||||||
|
{"\"b b\"@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"6 external -external-> external, extension, propagation, quoted",
|
||||||
|
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"\"a a+ext\"@example.com",
|
||||||
|
{"\"b b+ext\"@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"7 internal -external-> internal, no extension, propagation, embedded space",
|
||||||
|
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_INTERNAL,
|
||||||
|
"a a@example.com",
|
||||||
|
{"b b@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"8 internal -external-> internal, extension, propagation, embedded space",
|
||||||
|
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_INTERNAL,
|
||||||
|
"a a+ext@example.com",
|
||||||
|
{"b b+ext@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"9 internal -external-> internal, no extension, propagation, embedded space",
|
||||||
|
"inline:{ {a_a@example.com=\"b b\"@example.com} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_INTERNAL,
|
||||||
|
"a_a@example.com",
|
||||||
|
{"b b@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"10 internal -external-> internal, extension, propagation, embedded space",
|
||||||
|
"inline:{ {a_a@example.com=\"b b\"@example.com} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_INTERNAL,
|
||||||
|
"a_a+ext@example.com",
|
||||||
|
{"b b+ext@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"11 internal -external-> internal, no extension, @domain",
|
||||||
|
"inline:{ {@example.com=@example.net} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"a@a@example.com",
|
||||||
|
{"\"a@a\"@example.net"}, 1,
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All these tests must fail, so that we know that the tests work.
|
||||||
|
*/
|
||||||
|
static MAIL_ADDR_MAP_TEST fail_tests[] = {
|
||||||
|
{
|
||||||
|
"selftest 1 external -external-> external, no extension, quoted",
|
||||||
|
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"\"a a\"@example.com",
|
||||||
|
{"\"bXb\"@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selftest 2 external -external-> external, no extension, quoted",
|
||||||
|
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"\"aXa\"@example.com",
|
||||||
|
{"\"b b\"@example.com"}, 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"selftest 3 external -external-> external, no extension, quoted",
|
||||||
|
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
||||||
|
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
"\"a a\"@example.com",
|
||||||
|
{0}, 0,
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* canon_addr_external - surrogate to avoid trivial-rewrite dependency */
|
||||||
|
|
||||||
|
VSTRING *canon_addr_external(VSTRING *result, const char *addr)
|
||||||
|
{
|
||||||
|
return (vstring_strcpy(result, addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare(const char *testname,
|
||||||
|
const char **expect_argv, int expect_argc,
|
||||||
|
char **result_argv, int result_argc)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (expect_argc != 0 && result_argc != 0) {
|
||||||
|
for (n = 0; n < expect_argc && n < result_argc; n++) {
|
||||||
|
if (strcmp(expect_argv[n], result_argv[n]) != 0) {
|
||||||
|
msg_warn("fail test %s: expect[%d]='%s', result[%d]='%s'",
|
||||||
|
testname, n, expect_argv[n], n, result_argv[n]);
|
||||||
|
err = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (expect_argc != result_argc) {
|
||||||
|
msg_warn("fail test %s: expects %d results but there were %d",
|
||||||
|
testname, expect_argc, result_argc);
|
||||||
|
for (n = expect_argc; n < result_argc; n++)
|
||||||
|
msg_info("no expect to match result[%d]='%s'", n, result_argv[n]);
|
||||||
|
for (n = result_argc; n < expect_argc; n++)
|
||||||
|
msg_info("no result to match expect[%d]='%s'", n, expect_argv[n]);
|
||||||
|
err = 1;
|
||||||
|
}
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
|
static NORETURN usage(void)
|
||||||
|
{
|
||||||
|
msg_fatal("usage: %s pass_test | fail_test", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
MAIL_ADDR_MAP_TEST *test;
|
||||||
|
MAIL_ADDR_MAP_TEST *tests;
|
||||||
|
int errs = 0;
|
||||||
|
|
||||||
|
#define UPDATE(dst, src) { if (dst) myfree(dst); dst = mystrdup(src); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse JCL.
|
||||||
|
*/
|
||||||
|
progname = argv[0];
|
||||||
|
if (argc != 2) {
|
||||||
|
usage();
|
||||||
|
} else if (strcmp(argv[1], "pass_tests") == 0) {
|
||||||
|
tests = pass_tests;
|
||||||
|
} else if (strcmp(argv[1], "fail_tests") == 0) {
|
||||||
|
tests = fail_tests;
|
||||||
|
} else {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize.
|
||||||
|
*/
|
||||||
|
mail_conf_read(); /* XXX eliminate */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A read-eval-print loop, because specifying C strings with quotes and
|
||||||
|
* backslashes is painful.
|
||||||
|
*/
|
||||||
|
for (test = tests; test->testname; test++) {
|
||||||
|
ARGV *result;
|
||||||
|
int fail = 0;
|
||||||
|
|
||||||
|
if (mail_addr_form_to_string(test->in_form) == 0) {
|
||||||
|
msg_warn("test %s: bad in_form field: %d",
|
||||||
|
test->testname, test->in_form);
|
||||||
|
fail = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mail_addr_form_to_string(test->query_form) == 0) {
|
||||||
|
msg_warn("test %s: bad query_form field: %d",
|
||||||
|
test->testname, test->query_form);
|
||||||
|
fail = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mail_addr_form_to_string(test->out_form) == 0) {
|
||||||
|
msg_warn("test %s: bad out_form field: %d",
|
||||||
|
test->testname, test->out_form);
|
||||||
|
fail = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
MAPS *maps = maps_create("test", test->database, DICT_FLAG_LOCK
|
||||||
|
| DICT_FLAG_FOLD_FIX | DICT_FLAG_UTF8_REQUEST);
|
||||||
|
|
||||||
|
UPDATE(var_rcpt_delim, test->delimiter);
|
||||||
|
result = mail_addr_map_opt(maps, test->address, test->propagate,
|
||||||
|
test->in_form, test->query_form, test->out_form);
|
||||||
|
if (compare(test->testname, test->expect_argv, test->expect_argc,
|
||||||
|
result ? result->argv : 0, result ? result->argc : 0) != 0) {
|
||||||
|
msg_info("database = %s", test->database);
|
||||||
|
msg_info("propagate = %d", test->propagate);
|
||||||
|
msg_info("delimiter = '%s'", var_rcpt_delim);
|
||||||
|
msg_info("in_form = %s", mail_addr_form_to_string(test->in_form));
|
||||||
|
msg_info("query_form = %s", mail_addr_form_to_string(test->query_form));
|
||||||
|
msg_info("out_form = %s", mail_addr_form_to_string(test->out_form));
|
||||||
|
msg_info("address = %s", test->address);
|
||||||
|
fail = 1;
|
||||||
|
}
|
||||||
|
maps_free(maps);
|
||||||
|
if (result)
|
||||||
|
argv_free(result);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is an error if a test does not pass or fail as intended.
|
||||||
|
*/
|
||||||
|
errs += (tests == pass_tests ? fail : !fail);
|
||||||
|
}
|
||||||
|
return (errs != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@@ -25,12 +25,13 @@
|
|||||||
/*
|
/*
|
||||||
* External interface.
|
* External interface.
|
||||||
*/
|
*/
|
||||||
extern ARGV *mail_addr_map_opt(MAPS *, const char *, int, int, int);
|
extern ARGV *mail_addr_map_opt(MAPS *, const char *, int, int, int, int);
|
||||||
|
|
||||||
/* The least-overhead form. */
|
/* The least-overhead form. */
|
||||||
#define mail_addr_map_internal(path, address, propagate) \
|
#define mail_addr_map_internal(path, address, propagate) \
|
||||||
mail_addr_map_opt((path), (address), (propagate), \
|
mail_addr_map_opt((path), (address), (propagate), \
|
||||||
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_INTERNAL)
|
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_EXTERNAL, \
|
||||||
|
MAIL_ADDR_FORM_INTERNAL)
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
|
@@ -1,23 +1,26 @@
|
|||||||
unknown: warning: fail test selftest 1 external to external, no extension, quoted: expect[0]='"bXb"@example.com', result[0]='"b b"@example.com'
|
unknown: warning: fail test selftest 1 external -external-> external, no extension, quoted: expect[0]='"bXb"@example.com', result[0]='"b b"@example.com'
|
||||||
unknown: database = inline:{ {"a a"@example.com="b b"@example.com} }
|
unknown: database = inline:{ {"a a"@example.com="b b"@example.com} }
|
||||||
unknown: propagate = 1
|
unknown: propagate = 1
|
||||||
unknown: delimiter = '+'
|
unknown: delimiter = '+'
|
||||||
unknown: in_form = external
|
unknown: in_form = external
|
||||||
|
unknown: query_form = external
|
||||||
unknown: out_form = external
|
unknown: out_form = external
|
||||||
unknown: address = "a a"@example.com
|
unknown: address = "a a"@example.com
|
||||||
unknown: warning: fail test selftest 2 external to external, no extension, quoted: expects 1 results but there were 0
|
unknown: warning: fail test selftest 2 external -external-> external, no extension, quoted: expects 1 results but there were 0
|
||||||
unknown: no result to match expect[0]='"b b"@example.com'
|
unknown: no result to match expect[0]='"b b"@example.com'
|
||||||
unknown: database = inline:{ {"a a"@example.com="b b"@example.com} }
|
unknown: database = inline:{ {"a a"@example.com="b b"@example.com} }
|
||||||
unknown: propagate = 1
|
unknown: propagate = 1
|
||||||
unknown: delimiter = '+'
|
unknown: delimiter = '+'
|
||||||
unknown: in_form = external
|
unknown: in_form = external
|
||||||
|
unknown: query_form = external
|
||||||
unknown: out_form = external
|
unknown: out_form = external
|
||||||
unknown: address = "aXa"@example.com
|
unknown: address = "aXa"@example.com
|
||||||
unknown: warning: fail test selftest 3 external to external, no extension, quoted: expects 0 results but there were 1
|
unknown: warning: fail test selftest 3 external -external-> external, no extension, quoted: expects 0 results but there were 1
|
||||||
unknown: no expect to match result[0]='"b b"@example.com'
|
unknown: no expect to match result[0]='"b b"@example.com'
|
||||||
unknown: database = inline:{ {"a a"@example.com="b b"@example.com} }
|
unknown: database = inline:{ {"a a"@example.com="b b"@example.com} }
|
||||||
unknown: propagate = 1
|
unknown: propagate = 1
|
||||||
unknown: delimiter = '+'
|
unknown: delimiter = '+'
|
||||||
unknown: in_form = external
|
unknown: in_form = external
|
||||||
|
unknown: query_form = external
|
||||||
unknown: out_form = external
|
unknown: out_form = external
|
||||||
unknown: address = "a a"@example.com
|
unknown: address = "a a"@example.com
|
||||||
|
@@ -1,309 +0,0 @@
|
|||||||
/*++
|
|
||||||
/* NAME
|
|
||||||
/* mail_addr_map_tester 1
|
|
||||||
/* SUMMARY
|
|
||||||
/* mail_addr_map test program
|
|
||||||
/* SYNOPSIS
|
|
||||||
/* mail_addr_map pass_tests | fail_tests
|
|
||||||
/* DESCRIPTION
|
|
||||||
/* mail_addr_map performs the specified set of built-in
|
|
||||||
/* unit tests. With 'pass_tests', all tests must pass, and
|
|
||||||
/* with 'fail_tests' all tests must fail.
|
|
||||||
/* DIAGNOSTICS
|
|
||||||
/* When a unit test fails, the program prints details of the
|
|
||||||
/* failed test.
|
|
||||||
/*
|
|
||||||
/* The program terminates with a non-zero exit status when at
|
|
||||||
/* least one test does not pass with 'pass_tests', or when at
|
|
||||||
/* least one test does not fail with 'fail_tests'.
|
|
||||||
/* SEE ALSO
|
|
||||||
/* mail_addr_map(3), generic address mapping
|
|
||||||
/* LICENSE
|
|
||||||
/* .ad
|
|
||||||
/* .fi
|
|
||||||
/* The Secure Mailer license must be distributed with this software.
|
|
||||||
/* AUTHOR(S)
|
|
||||||
/* Wietse Venema
|
|
||||||
/* Google, Inc.
|
|
||||||
/* 111 8th Avenue
|
|
||||||
/* New York, NY 10011, USA
|
|
||||||
/*--*/
|
|
||||||
|
|
||||||
/* System library. */
|
|
||||||
|
|
||||||
#include <sys_defs.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/* Utility library. */
|
|
||||||
|
|
||||||
#include <argv.h>
|
|
||||||
#include <msg.h>
|
|
||||||
#include <mymalloc.h>
|
|
||||||
#include <vstring.h>
|
|
||||||
|
|
||||||
/* Global library. */
|
|
||||||
|
|
||||||
#include <canon_addr.h>
|
|
||||||
#include <mail_addr_map.h>
|
|
||||||
#include <mail_conf.h> /* XXX eliminate main.cf dependency */
|
|
||||||
#include <mail_params.h>
|
|
||||||
|
|
||||||
/* Application-specific. */
|
|
||||||
|
|
||||||
#define STR vstring_str
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *testname;
|
|
||||||
const char *database;
|
|
||||||
int propagate;
|
|
||||||
const char *delimiter;
|
|
||||||
int in_form;
|
|
||||||
int out_form;
|
|
||||||
const char *address;
|
|
||||||
const char *expect_argv[2];
|
|
||||||
int expect_argc;
|
|
||||||
} MAIL_ADDR_MAP_TEST;
|
|
||||||
|
|
||||||
#define DONT_PROPAGATE_UNMATCHED_EXTENSION 0
|
|
||||||
#define DO_PROPAGATE_UNMATCHED_EXTENSION 1
|
|
||||||
#define NO_RECIPIENT_DELIMITER ""
|
|
||||||
#define PLUS_RECIPIENT_DELIMITER "+"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* All these tests must pass, so that we know that mail_addr_map_opt() works
|
|
||||||
* as intended.
|
|
||||||
*/
|
|
||||||
static MAIL_ADDR_MAP_TEST pass_tests[] = {
|
|
||||||
{
|
|
||||||
"1 external to external, no extension",
|
|
||||||
"inline:{ aa@example.com=bb@example.com }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
|
||||||
"aa@example.com",
|
|
||||||
{"bb@example.com"}, 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"2 external to external, extension, propagation",
|
|
||||||
"inline:{ aa@example.com=bb@example.com }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
|
||||||
"aa+ext@example.com",
|
|
||||||
{"bb+ext@example.com"}, 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"3 external to external, extension, no propagation, no match",
|
|
||||||
"inline:{ aa@example.com=bb@example.com }",
|
|
||||||
DONT_PROPAGATE_UNMATCHED_EXTENSION, NO_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
|
||||||
"aa+ext@example.com",
|
|
||||||
{0}, 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"4 external to external, extension, full match",
|
|
||||||
"inline:{{cc+ext@example.com=dd@example.com,ee@example.com}}",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
|
||||||
"cc+ext@example.com",
|
|
||||||
{"dd@example.com", "ee@example.com"}, 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"5 external to external, no extension, quoted",
|
|
||||||
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
|
||||||
"\"a a\"@example.com",
|
|
||||||
{"\"b b\"@example.com"}, 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"6 external to external, extension, propagation, quoted",
|
|
||||||
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
|
||||||
"\"a a+ext\"@example.com",
|
|
||||||
{"\"b b+ext\"@example.com"}, 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"7 internal to internal, no extension, propagation, embedded space",
|
|
||||||
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_INTERNAL,
|
|
||||||
"a a@example.com",
|
|
||||||
{"b b@example.com"}, 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"8 internal to internal, extension, propagation, embedded space",
|
|
||||||
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_INTERNAL,
|
|
||||||
"a a+ext@example.com",
|
|
||||||
{"b b+ext@example.com"}, 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"9 noconv to noconv, no extension, propagation, embedded space",
|
|
||||||
"inline:{ {a_a@example.com=\"b b\"@example.com} }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_INTERNAL,
|
|
||||||
"a_a@example.com",
|
|
||||||
{"b b@example.com"}, 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"10 noconv to noconv, extension, propagation, embedded space",
|
|
||||||
"inline:{ {a_a@example.com=\"b b\"@example.com} }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_INTERNAL, MAIL_ADDR_FORM_INTERNAL,
|
|
||||||
"a_a+ext@example.com",
|
|
||||||
{"b b+ext@example.com"}, 1,
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* All these tests must fail, so that we know that the tests work.
|
|
||||||
*/
|
|
||||||
static MAIL_ADDR_MAP_TEST fail_tests[] = {
|
|
||||||
{
|
|
||||||
"selftest 1 external to external, no extension, quoted",
|
|
||||||
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
|
||||||
"\"a a\"@example.com",
|
|
||||||
{"\"bXb\"@example.com"}, 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"selftest 2 external to external, no extension, quoted",
|
|
||||||
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
|
||||||
"\"aXa\"@example.com",
|
|
||||||
{"\"b b\"@example.com"}, 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"selftest 3 external to external, no extension, quoted",
|
|
||||||
"inline:{ {\"a a\"@example.com=\"b b\"@example.com} }",
|
|
||||||
DO_PROPAGATE_UNMATCHED_EXTENSION, PLUS_RECIPIENT_DELIMITER,
|
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL,
|
|
||||||
"\"a a\"@example.com",
|
|
||||||
{0}, 0,
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* canon_addr_external - surrogate to avoid trivial-rewrite dependency */
|
|
||||||
|
|
||||||
VSTRING *canon_addr_external(VSTRING *result, const char *addr)
|
|
||||||
{
|
|
||||||
return (vstring_strcpy(result, addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int compare(const char *testname,
|
|
||||||
const char **expect_argv, int expect_argc,
|
|
||||||
char **result_argv, int result_argc)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (expect_argc != 0 && result_argc != 0) {
|
|
||||||
for (n = 0; n < expect_argc && n < result_argc; n++) {
|
|
||||||
if (strcmp(expect_argv[n], result_argv[n]) != 0) {
|
|
||||||
msg_warn("fail test %s: expect[%d]='%s', result[%d]='%s'",
|
|
||||||
testname, n, expect_argv[n], n, result_argv[n]);
|
|
||||||
err = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (expect_argc != result_argc) {
|
|
||||||
msg_warn("fail test %s: expects %d results but there were %d",
|
|
||||||
testname, expect_argc, result_argc);
|
|
||||||
for (n = expect_argc; n < result_argc; n++)
|
|
||||||
msg_info("no expect to match result[%d]='%s'", n, result_argv[n]);
|
|
||||||
for (n = result_argc; n < expect_argc; n++)
|
|
||||||
msg_info("no result to match expect[%d]='%s'", n, expect_argv[n]);
|
|
||||||
err = 1;
|
|
||||||
}
|
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *progname;
|
|
||||||
|
|
||||||
static NORETURN usage(void)
|
|
||||||
{
|
|
||||||
msg_fatal("usage: %s pass_test | fail_test", progname);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
MAIL_ADDR_MAP_TEST *test;
|
|
||||||
MAIL_ADDR_MAP_TEST *tests;
|
|
||||||
int errs = 0;
|
|
||||||
|
|
||||||
#define UPDATE(dst, src) { if (dst) myfree(dst); dst = mystrdup(src); }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse JCL.
|
|
||||||
*/
|
|
||||||
progname = argv[0];
|
|
||||||
if (argc != 2) {
|
|
||||||
usage();
|
|
||||||
} else if (strcmp(argv[1], "pass_tests") == 0) {
|
|
||||||
tests = pass_tests;
|
|
||||||
} else if (strcmp(argv[1], "fail_tests") == 0) {
|
|
||||||
tests = fail_tests;
|
|
||||||
} else {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize.
|
|
||||||
*/
|
|
||||||
mail_conf_read(); /* XXX eliminate */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A read-eval-print loop, because specifying C strings with quotes and
|
|
||||||
* backslashes is painful.
|
|
||||||
*/
|
|
||||||
for (test = tests; test->testname; test++) {
|
|
||||||
ARGV *result;
|
|
||||||
int fail = 0;
|
|
||||||
|
|
||||||
if (mail_addr_form_to_string(test->in_form) == 0) {
|
|
||||||
msg_warn("test %s: bad in_form field: %d",
|
|
||||||
test->testname, test->in_form);
|
|
||||||
fail = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (mail_addr_form_to_string(test->out_form) == 0) {
|
|
||||||
msg_warn("test %s: bad out_form field: %d",
|
|
||||||
test->testname, test->out_form);
|
|
||||||
fail = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MAPS *maps = maps_create("test", test->database, DICT_FLAG_LOCK
|
|
||||||
| DICT_FLAG_FOLD_FIX | DICT_FLAG_UTF8_REQUEST);
|
|
||||||
|
|
||||||
UPDATE(var_rcpt_delim, test->delimiter);
|
|
||||||
result = mail_addr_map_opt(maps, test->address, test->propagate,
|
|
||||||
test->in_form, test->out_form);
|
|
||||||
if (compare(test->testname, test->expect_argv, test->expect_argc,
|
|
||||||
result ? result->argv : 0, result ? result->argc : 0) != 0) {
|
|
||||||
msg_info("database = %s", test->database);
|
|
||||||
msg_info("propagate = %d", test->propagate);
|
|
||||||
msg_info("delimiter = '%s'", var_rcpt_delim);
|
|
||||||
msg_info("in_form = %s", mail_addr_form_to_string(test->in_form));
|
|
||||||
msg_info("out_form = %s", mail_addr_form_to_string(test->out_form));
|
|
||||||
msg_info("address = %s", test->address);
|
|
||||||
fail = 1;
|
|
||||||
}
|
|
||||||
maps_free(maps);
|
|
||||||
if (result)
|
|
||||||
argv_free(result);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It is an error if a test does not pass or fail as intended.
|
|
||||||
*/
|
|
||||||
errs += (tests == pass_tests ? fail : !fail);
|
|
||||||
}
|
|
||||||
return (errs != 0);
|
|
||||||
}
|
|
@@ -20,7 +20,7 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20170117"
|
#define MAIL_RELEASE_DATE "20170122"
|
||||||
#define MAIL_VERSION_NUMBER "3.2"
|
#define MAIL_VERSION_NUMBER "3.2"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@@ -48,7 +48,7 @@
|
|||||||
/* When the \fIkey\fR specifies email address information, the
|
/* When the \fIkey\fR specifies email address information, the
|
||||||
/* localpart should be enclosed with double quotes if required
|
/* localpart should be enclosed with double quotes if required
|
||||||
/* by RFC 5322. For example, an address localpart that contains
|
/* by RFC 5322. For example, an address localpart that contains
|
||||||
/* ';' or that ends on '.'.
|
/* ";", or a localpart that starts or ends with ".".
|
||||||
/*
|
/*
|
||||||
/* By default the lookup key is mapped to lowercase to make
|
/* By default the lookup key is mapped to lowercase to make
|
||||||
/* the lookups case insensitive; as of Postfix 2.3 this case
|
/* the lookups case insensitive; as of Postfix 2.3 this case
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
/* .IP \fB-b\fR
|
/* .IP \fB-b\fR
|
||||||
/* Enable message body query mode. When reading lookup keys
|
/* Enable message body query mode. When reading lookup keys
|
||||||
/* from standard input with "\fB-q -\fR", process the input
|
/* from standard input with "\fB-q -\fR", process the input
|
||||||
/* as if it is an email message in RFC 2822 format. Each line
|
/* as if it is an email message in RFC 5322 format. Each line
|
||||||
/* of body content becomes one lookup key.
|
/* of body content becomes one lookup key.
|
||||||
/* .sp
|
/* .sp
|
||||||
/* By default, the \fB-b\fR option starts generating lookup
|
/* By default, the \fB-b\fR option starts generating lookup
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
/* .IP \fB-h\fR
|
/* .IP \fB-h\fR
|
||||||
/* Enable message header query mode. When reading lookup keys
|
/* Enable message header query mode. When reading lookup keys
|
||||||
/* from standard input with "\fB-q -\fR", process the input
|
/* from standard input with "\fB-q -\fR", process the input
|
||||||
/* as if it is an email message in RFC 2822 format. Each
|
/* as if it is an email message in RFC 5322 format. Each
|
||||||
/* logical header line becomes one lookup key. A multi-line
|
/* logical header line becomes one lookup key. A multi-line
|
||||||
/* header becomes one lookup key with one or more embedded
|
/* header becomes one lookup key with one or more embedded
|
||||||
/* newline characters.
|
/* newline characters.
|
||||||
|
@@ -81,7 +81,9 @@ int smtp_map11_external(VSTRING *addr, MAPS *maps, int propagate)
|
|||||||
const char *result;
|
const char *result;
|
||||||
|
|
||||||
if ((new_addr = mail_addr_map_opt(maps, STR(addr), propagate,
|
if ((new_addr = mail_addr_map_opt(maps, STR(addr), propagate,
|
||||||
MAIL_ADDR_FORM_EXTERNAL, MAIL_ADDR_FORM_EXTERNAL)) != 0) {
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL,
|
||||||
|
MAIL_ADDR_FORM_EXTERNAL)) != 0) {
|
||||||
if (new_addr->argc > 1)
|
if (new_addr->argc > 1)
|
||||||
msg_warn("multi-valued %s result for %s", maps->title, STR(addr));
|
msg_warn("multi-valued %s result for %s", maps->title, STR(addr));
|
||||||
result = new_addr->argv[0];
|
result = new_addr->argv[0];
|
||||||
|
@@ -114,6 +114,8 @@ smtpd_addr_valid_test: smtpd_check smtpd_addr_valid.in smtpd_addr_valid.ref
|
|||||||
|
|
||||||
# This requires that the DNS server can query porcupine.org.
|
# This requires that the DNS server can query porcupine.org.
|
||||||
|
|
||||||
|
ADDRINFO_FIX = sed 's/No address associated with hostname/hostname nor servname provided, or not known/'
|
||||||
|
|
||||||
smtpd_exp_test: smtpd_check smtpd_exp.in smtpd_exp.ref
|
smtpd_exp_test: smtpd_check smtpd_exp.in smtpd_exp.ref
|
||||||
$(SHLIB_ENV) $(VALGRIND) ../postmap/postmap hash:smtpd_check_access
|
$(SHLIB_ENV) $(VALGRIND) ../postmap/postmap hash:smtpd_check_access
|
||||||
$(SHLIB_ENV) $(VALGRIND) ./smtpd_check <smtpd_exp.in >smtpd_exp.tmp 2>&1
|
$(SHLIB_ENV) $(VALGRIND) ./smtpd_check <smtpd_exp.in >smtpd_exp.tmp 2>&1
|
||||||
@@ -122,13 +124,13 @@ smtpd_exp_test: smtpd_check smtpd_exp.in smtpd_exp.ref
|
|||||||
|
|
||||||
smtpd_server_test: smtpd_check smtpd_server.in smtpd_server.ref
|
smtpd_server_test: smtpd_check smtpd_server.in smtpd_server.ref
|
||||||
$(SHLIB_ENV) $(VALGRIND) ./smtpd_check <smtpd_server.in >smtpd_server.tmp 2>&1
|
$(SHLIB_ENV) $(VALGRIND) ./smtpd_check <smtpd_server.in >smtpd_server.tmp 2>&1
|
||||||
diff smtpd_server.ref smtpd_server.tmp
|
$(ADDRINFO_FIX) smtpd_server.tmp | diff smtpd_server.ref -
|
||||||
rm -f smtpd_server.tmp smtpd_check_access.*
|
rm -f smtpd_server.tmp smtpd_check_access.*
|
||||||
|
|
||||||
smtpd_nullmx_test: smtpd_check smtpd_nullmx.in smtpd_nullmx.ref
|
smtpd_nullmx_test: smtpd_check smtpd_nullmx.in smtpd_nullmx.ref
|
||||||
$(SHLIB_ENV) $(VALGRIND) ../postmap/postmap hash:smtpd_check_access
|
$(SHLIB_ENV) $(VALGRIND) ../postmap/postmap hash:smtpd_check_access
|
||||||
$(SHLIB_ENV) $(VALGRIND) ./smtpd_check <smtpd_nullmx.in >smtpd_nullmx.tmp 2>&1
|
$(SHLIB_ENV) $(VALGRIND) ./smtpd_check <smtpd_nullmx.in >smtpd_nullmx.tmp 2>&1
|
||||||
diff smtpd_nullmx.ref smtpd_nullmx.tmp
|
$(ADDRINFO_FIX) smtpd_nullmx.tmp | diff smtpd_nullmx.ref -
|
||||||
rm -f smtpd_nullmx.tmp smtpd_check_access.*
|
rm -f smtpd_nullmx.tmp smtpd_check_access.*
|
||||||
|
|
||||||
smtpd_dns_filter_test: smtpd_check smtpd_dns_filter.in smtpd_dns_filter.ref \
|
smtpd_dns_filter_test: smtpd_check smtpd_dns_filter.in smtpd_dns_filter.ref \
|
||||||
|
@@ -653,6 +653,8 @@ static ARGV *smtpd_check_parse(int flags, const char *checks)
|
|||||||
return (argv);
|
return (argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TEST
|
||||||
|
|
||||||
/* has_required - make sure required restriction is present */
|
/* has_required - make sure required restriction is present */
|
||||||
|
|
||||||
static int has_required(ARGV *restrictions, const char **required)
|
static int has_required(ARGV *restrictions, const char **required)
|
||||||
@@ -711,6 +713,8 @@ static void fail_required(const char *name, const char **required)
|
|||||||
name, STR(example));
|
name, STR(example));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* smtpd_check_init - initialize once during process lifetime */
|
/* smtpd_check_init - initialize once during process lifetime */
|
||||||
|
|
||||||
void smtpd_check_init(void)
|
void smtpd_check_init(void)
|
||||||
@@ -719,6 +723,7 @@ void smtpd_check_init(void)
|
|||||||
const char *name;
|
const char *name;
|
||||||
const char *value;
|
const char *value;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
#ifndef TEST
|
||||||
static const char *rcpt_required[] = {
|
static const char *rcpt_required[] = {
|
||||||
REJECT_UNAUTH_DEST,
|
REJECT_UNAUTH_DEST,
|
||||||
DEFER_UNAUTH_DEST,
|
DEFER_UNAUTH_DEST,
|
||||||
@@ -728,6 +733,7 @@ void smtpd_check_init(void)
|
|||||||
CHECK_RELAY_DOMAINS,
|
CHECK_RELAY_DOMAINS,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
static NAME_CODE tempfail_actions[] = {
|
static NAME_CODE tempfail_actions[] = {
|
||||||
DEFER_ALL, DEFER_ALL_ACT,
|
DEFER_ALL, DEFER_ALL_ACT,
|
||||||
DEFER_IF_PERMIT, DEFER_IF_PERMIT_ACT,
|
DEFER_IF_PERMIT, DEFER_IF_PERMIT_ACT,
|
||||||
@@ -3205,9 +3211,9 @@ static int check_mail_access(SMTPD_STATE *state, const char *table,
|
|||||||
* Look up user+foo@domain if the address has an extension, user@domain
|
* Look up user+foo@domain if the address has an extension, user@domain
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
#define LOOKUP_STRATEGY (MAIL_ADDR_FIND_FULL | MAIL_ADDR_FIND_NOEXT \
|
#define LOOKUP_STRATEGY (MAF_STRATEGY_FULL | MAF_STRATEGY_NOEXT \
|
||||||
| MAIL_ADDR_FIND_DOMAIN | MAIL_ADDR_FIND_PMS \
|
| MAF_STRATEGY_DOMAIN | MAF_STRATEGY_PMS \
|
||||||
| MAIL_ADDR_FIND_LOCALPART_AT)
|
| MAF_STRATEGY_LOCALPART_AT)
|
||||||
|
|
||||||
if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) {
|
if ((maps = (MAPS *) htable_find(map_command_table, table)) == 0) {
|
||||||
msg_warn("%s: unexpected dictionary: %s", myname, table);
|
msg_warn("%s: unexpected dictionary: %s", myname, table);
|
||||||
@@ -5893,7 +5899,6 @@ int main(int argc, char **argv)
|
|||||||
char *bp;
|
char *bp;
|
||||||
char *resp;
|
char *resp;
|
||||||
char *addr;
|
char *addr;
|
||||||
INET_PROTO_INFO *proto_info;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialization. Use dummies for client information.
|
* Initialization. Use dummies for client information.
|
||||||
@@ -5905,7 +5910,7 @@ int main(int argc, char **argv)
|
|||||||
int_init();
|
int_init();
|
||||||
smtpd_check_init();
|
smtpd_check_init();
|
||||||
smtpd_expand_init();
|
smtpd_expand_init();
|
||||||
proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_IPV4);
|
(void) inet_proto_init(argv[0], INET_PROTO_NAME_IPV4);
|
||||||
smtpd_state_init(&state, VSTREAM_IN, "smtpd");
|
smtpd_state_init(&state, VSTREAM_IN, "smtpd");
|
||||||
state.queue_id = "<queue id>";
|
state.queue_id = "<queue id>";
|
||||||
|
|
||||||
|
@@ -261,9 +261,9 @@ int transport_lookup(TRANSPORT_INFO *tp, const char *addr,
|
|||||||
* internal form.
|
* internal form.
|
||||||
*/
|
*/
|
||||||
#define LOOKUP_STRATEGY \
|
#define LOOKUP_STRATEGY \
|
||||||
(MAIL_ADDR_FIND_FULL | MAIL_ADDR_FIND_NOEXT | MAIL_ADDR_FIND_DOMAIN | \
|
(MAF_STRATEGY_FULL | MAF_STRATEGY_NOEXT | MAF_STRATEGY_DOMAIN | \
|
||||||
(transport_match_parent_style == MATCH_FLAG_PARENT ? \
|
(transport_match_parent_style == MATCH_FLAG_PARENT ? \
|
||||||
MAIL_ADDR_FIND_PMS : MAIL_ADDR_FIND_PMDS))
|
MAF_STRATEGY_PMS : MAF_STRATEGY_PMDS))
|
||||||
|
|
||||||
if ((ratsign = strrchr(addr, '@')) == 0 || ratsign[1] == 0)
|
if ((ratsign = strrchr(addr, '@')) == 0 || ratsign[1] == 0)
|
||||||
msg_panic("transport_lookup: bad address: \"%s\"", addr);
|
msg_panic("transport_lookup: bad address: \"%s\"", addr);
|
||||||
@@ -427,7 +427,7 @@ int main(int argc, char **argv)
|
|||||||
vstring_free(nexthop);
|
vstring_free(nexthop);
|
||||||
vstring_free(channel);
|
vstring_free(channel);
|
||||||
vstring_free(buffer);
|
vstring_free(buffer);
|
||||||
exit(0);
|
exit(errs != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user