7 /* generic address-based lookup
9 /* #include <mail_addr_find.h>
11 /* const char *mail_addr_find(maps, address, extension)
13 /* const char *address;
16 /* mail_addr_find() searches the specified maps for an entry with as
17 /* key the specified address, and derivations from that address.
18 /* It is up to the caller to specify its case sensitivity
19 /* preferences when it opens the maps.
20 /* The result is overwritten upon each call.
22 /* An address that is in the form \fIuser\fR matches itself.
24 /* Given an address of the form \fIuser@domain\fR, the following
25 /* lookups are done in the given order until one returns a result:
27 /* Look up the entire address.
29 /* Look up \fIuser\fR when \fIdomain\fR is equal to $myorigin,
30 /* when \fIdomain\fR matches $mydestination, or when it matches
31 /* $inet_interfaces or $proxy_interfaces.
33 /* Look for an entry that matches the domain specified in \fIaddress\fR.
35 /* With address extension enabled, the table lookup order is:
36 /* \fIuser+extension\fR@\fIdomain\fR, \fIuser\fR@\fIdomain\fR,
37 /* \fIuser+extension\fR, \fIuser\fR, and @\fIdomain\fR.
41 /* Dictionary search path (see maps(3)).
43 /* The address to be looked up.
45 /* A null pointer, or the address of a pointer that is set to
46 /* the address of a dynamic memory copy of the address extension
47 /* that had to be chopped off in order to match the lookup tables.
48 /* The copy includes the recipient address delimiter.
49 /* The caller is expected to pass the copy to myfree().
51 /* The global \fIdict_errno\fR is non-zero when the lookup
52 /* should be tried again.
54 /* maps(3), multi-dictionary search
55 /* resolve_local(3), recognize local system
59 /* The Secure Mailer license must be distributed with this software.
62 /* IBM T.J. Watson Research
64 /* Yorktown Heights, NY 10598, USA
72 #ifdef STRCASECMP_IN_STRINGS_H
76 /* Utility library. */
80 #include <stringops.h>
86 #include <mail_params.h>
87 #include <strip_addr.h>
88 #include <mail_addr_find.h>
89 #include <resolve_local.h>
91 /* Application-specific. */
93 #define STR vstring_str
95 /* mail_addr_find - map a canonical address */
97 const char *mail_addr_find(MAPS
*path
, const char *address
, char **extp
)
99 const char *myname
= "mail_addr_find";
109 full_key
= mystrdup(address
);
110 if (*var_rcpt_delim
== 0) {
111 bare_key
= saved_ext
= 0;
113 bare_key
= strip_addr(full_key
, &saved_ext
, *var_rcpt_delim
);
117 * Try user+foo@domain and user@domain.
119 * Specify what keys are partial or full, to avoid matching partial
120 * addresses with regular expressions.
123 #define PARTIAL DICT_FLAG_FIXED
125 if ((result
= maps_find(path
, full_key
, FULL
)) == 0 && dict_errno
== 0
126 && bare_key
!= 0 && (result
= maps_find(path
, bare_key
, PARTIAL
)) != 0
133 * Try user+foo@$myorigin, user+foo@$mydestination or
134 * user+foo@[${proxy,inet}_interfaces]. Then try with +foo stripped off.
136 if (result
== 0 && dict_errno
== 0
137 && (ratsign
= strrchr(full_key
, '@')) != 0
138 && (strcasecmp(ratsign
+ 1, var_myorigin
) == 0
139 || resolve_local(ratsign
+ 1))) {
141 result
= maps_find(path
, full_key
, PARTIAL
);
142 if (result
== 0 && dict_errno
== 0 && bare_key
!= 0) {
143 if ((ratsign
= strrchr(bare_key
, '@')) == 0)
144 msg_panic("%s: bare key botch", myname
);
146 if ((result
= maps_find(path
, bare_key
, PARTIAL
)) != 0 && extp
!= 0) {
157 if (result
== 0 && dict_errno
== 0 && ratsign
)
158 result
= maps_find(path
, ratsign
, PARTIAL
);
164 msg_info("%s: %s -> %s", myname
, address
,
166 dict_errno
? "(try again)" :
180 * Proof-of-concept test program. Read an address from stdin, and spit out
184 #include <vstring_vstream.h>
185 #include <mail_conf.h>
187 int main(int argc
, char **argv
)
189 VSTRING
*buffer
= vstring_alloc(100);
198 msg_fatal("usage: %s database", argv
[0]);
205 path
= maps_create(argv
[0], argv
[1], DICT_FLAG_LOCK
| DICT_FLAG_FOLD_FIX
);
206 while (vstring_fgets_nonl(buffer
, VSTREAM_IN
)) {
208 result
= mail_addr_find(path
, STR(buffer
), &extent
);
209 vstream_printf("%s -> %s (%s)\n", STR(buffer
), result
? result
:
210 dict_errno
? "(try again)" :
211 "(not found)", extent
? extent
: "null extension");
212 vstream_fflush(VSTREAM_OUT
);
216 vstring_free(buffer
);