7 /* resolve recipient and deliver locally or remotely
11 /* int deliver_resolve_tree(state, usr_attr, addr)
13 /* USER_ATTR usr_attr;
16 /* int deliver_resolve_addr(state, usr_attr, addr)
18 /* USER_ATTR usr_attr;
21 /* deliver_resolve_XXX() resolves a recipient that is the result from
22 /* e.g., alias expansion, and delivers locally or via forwarding.
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.
30 /* An address from, e.g., alias expansion.
32 /* Fatal errors: out of memory. The result is non-zero when the
33 /* operation should be tried again. Warnings: malformed address.
35 /* recipient(3) local delivery
36 /* indirect(3) deliver via forwarding
40 /* The Secure Mailer license must be distributed with this software.
43 /* IBM T.J. Watson Research
45 /* Yorktown Heights, NY 10598, USA
54 /* Utility library. */
62 #include <mail_proto.h>
63 #include <resolve_clnt.h>
64 #include <rewrite_clnt.h>
66 #include <mail_params.h>
69 /* Application-specific. */
73 /* deliver_resolve_addr - resolve and deliver */
75 int deliver_resolve_addr(LOCAL_STATE state
, USER_ATTR usr_attr
, char *addr
)
80 tree
= tok822_scan_addr(addr
);
81 result
= deliver_resolve_tree(state
, usr_attr
, tree
);
82 tok822_free_tree(tree
);
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";
97 * Make verbose logging easier to understand.
101 MSG_LOG_STATE(myname
, state
);
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
));
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
);
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
157 if (strcmp(state
.msg_attr
.relay
, STR(reply
.transport
)) == 0) {
158 status
= deliver_recipient(state
, usr_attr
);
160 status
= deliver_indirect(state
);
167 resolve_clnt_free(&reply
);