Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / local / resolve.c
blobc558d7a8e4a0b58c4d915a3f2a0211daaa22aa73
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* resolve 3
6 /* SUMMARY
7 /* resolve recipient and deliver locally or remotely
8 /* SYNOPSIS
9 /* #include "local.h"
11 /* int deliver_resolve_tree(state, usr_attr, addr)
12 /* LOCAL_STATE state;
13 /* USER_ATTR usr_attr;
14 /* TOK822 *addr;
16 /* int deliver_resolve_addr(state, usr_attr, addr)
17 /* LOCAL_STATE state;
18 /* USER_ATTR usr_attr;
19 /* char *addr;
20 /* DESCRIPTION
21 /* deliver_resolve_XXX() resolves a recipient that is the result from
22 /* e.g., alias expansion, and delivers locally or via forwarding.
24 /* Arguments:
25 /* .IP state
26 /* The attributes that specify the message, sender and more.
27 /* A table with the results from expanding aliases or lists.
28 /* A table with delivered-to: addresses taken from the message.
29 /* .IP addr
30 /* An address from, e.g., alias expansion.
31 /* DIAGNOSTICS
32 /* Fatal errors: out of memory. The result is non-zero when the
33 /* operation should be tried again. Warnings: malformed address.
34 /* SEE ALSO
35 /* recipient(3) local delivery
36 /* indirect(3) deliver via forwarding
37 /* LICENSE
38 /* .ad
39 /* .fi
40 /* The Secure Mailer license must be distributed with this software.
41 /* AUTHOR(S)
42 /* Wietse Venema
43 /* IBM T.J. Watson Research
44 /* P.O. Box 704
45 /* Yorktown Heights, NY 10598, USA
46 /*--*/
48 /* System library. */
50 #include <sys_defs.h>
51 #include <unistd.h>
52 #include <string.h>
54 /* Utility library. */
56 #include <msg.h>
57 #include <vstring.h>
58 #include <htable.h>
60 /* Global library. */
62 #include <mail_proto.h>
63 #include <resolve_clnt.h>
64 #include <rewrite_clnt.h>
65 #include <tok822.h>
66 #include <mail_params.h>
67 #include <defer.h>
69 /* Application-specific. */
71 #include "local.h"
73 /* deliver_resolve_addr - resolve and deliver */
75 int deliver_resolve_addr(LOCAL_STATE state, USER_ATTR usr_attr, char *addr)
77 TOK822 *tree;
78 int result;
80 tree = tok822_scan_addr(addr);
81 result = deliver_resolve_tree(state, usr_attr, tree);
82 tok822_free_tree(tree);
83 return (result);
86 /* deliver_resolve_tree - resolve and deliver */
88 int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr)
90 const char *myname = "deliver_resolve_tree";
91 RESOLVE_REPLY reply;
92 int status;
93 ssize_t ext_len;
94 char *ratsign;
97 * Make verbose logging easier to understand.
99 state.level++;
100 if (msg_verbose)
101 MSG_LOG_STATE(myname, state);
104 * Initialize.
106 resolve_clnt_init(&reply);
109 * Rewrite the address to canonical form, just like the cleanup service
110 * does. Then, resolve the address to (transport, nexhop, recipient),
111 * just like the queue manager does. The only part missing here is the
112 * virtual address substitution. Message forwarding fixes most of that.
114 tok822_rewrite(addr, REWRITE_CANON);
115 tok822_resolve(addr, &reply);
118 * First, a healthy portion of error handling.
120 if (reply.flags & RESOLVE_FLAG_FAIL) {
121 dsb_simple(state.msg_attr.why, "4.3.0", "address resolver failure");
122 status = defer_append(BOUNCE_FLAGS(state.request),
123 BOUNCE_ATTR(state.msg_attr));
124 } else if (reply.flags & RESOLVE_FLAG_ERROR) {
125 dsb_simple(state.msg_attr.why, "5.1.3",
126 "bad recipient address syntax: %s", STR(reply.recipient));
127 status = bounce_append(BOUNCE_FLAGS(state.request),
128 BOUNCE_ATTR(state.msg_attr));
129 } else {
132 * Splice in the optional unmatched address extension.
134 if (state.msg_attr.unmatched) {
135 if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0) {
136 VSTRING_ADDCH(reply.recipient, *var_rcpt_delim);
137 vstring_strcat(reply.recipient, state.msg_attr.unmatched);
138 } else {
139 ext_len = strlen(state.msg_attr.unmatched);
140 VSTRING_SPACE(reply.recipient, ext_len + 2);
141 if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0)
142 msg_panic("%s: recipient @ botch", myname);
143 memmove(ratsign + ext_len + 1, ratsign, strlen(ratsign) + 1);
144 *ratsign = *var_rcpt_delim;
145 memcpy(ratsign + 1, state.msg_attr.unmatched, ext_len);
146 VSTRING_SKIP(reply.recipient);
149 state.msg_attr.rcpt.address = STR(reply.recipient);
152 * Delivery to a local or non-local address. For a while there was
153 * some ugly code to force local recursive alias expansions on a host
154 * with no authority over the local domain, but that code was just
155 * too unclean.
157 if (strcmp(state.msg_attr.relay, STR(reply.transport)) == 0) {
158 status = deliver_recipient(state, usr_attr);
159 } else {
160 status = deliver_indirect(state);
165 * Cleanup.
167 resolve_clnt_free(&reply);
169 return (status);