Postfix3.3.1
resolve.c
[詳解]
1 /*++
2 /* NAME
3 /* resolve 3
4 /* SUMMARY
5 /* resolve recipient and deliver locally or remotely
6 /* SYNOPSIS
7 /* #include "local.h"
8 /*
9 /* int deliver_resolve_tree(state, usr_attr, addr)
10 /* LOCAL_STATE state;
11 /* USER_ATTR usr_attr;
12 /* TOK822 *addr;
13 /*
14 /* int deliver_resolve_addr(state, usr_attr, addr)
15 /* LOCAL_STATE state;
16 /* USER_ATTR usr_attr;
17 /* char *addr;
18 /* DESCRIPTION
19 /* deliver_resolve_XXX() resolves a recipient that is the result from
20 /* e.g., alias expansion, and delivers locally or via forwarding.
21 /*
22 /* Arguments:
23 /* .IP state
24 /* The attributes that specify the message, sender and more.
25 /* A table with the results from expanding aliases or lists.
26 /* A table with delivered-to: addresses taken from the message.
27 /* .IP addr
28 /* An address from, e.g., alias expansion.
29 /* DIAGNOSTICS
30 /* Fatal errors: out of memory. The result is non-zero when the
31 /* operation should be tried again. Warnings: malformed address.
32 /* SEE ALSO
33 /* recipient(3) local delivery
34 /* indirect(3) deliver via forwarding
35 /* LICENSE
36 /* .ad
37 /* .fi
38 /* The Secure Mailer license must be distributed with this software.
39 /* AUTHOR(S)
40 /* Wietse Venema
41 /* IBM T.J. Watson Research
42 /* P.O. Box 704
43 /* Yorktown Heights, NY 10598, USA
44 /*--*/
45 
46 /* System library. */
47 
48 #include <sys_defs.h>
49 #include <unistd.h>
50 #include <string.h>
51 
52 /* Utility library. */
53 
54 #include <msg.h>
55 #include <vstring.h>
56 #include <htable.h>
57 
58 /* Global library. */
59 
60 #include <mail_proto.h>
61 #include <resolve_clnt.h>
62 #include <rewrite_clnt.h>
63 #include <tok822.h>
64 #include <mail_params.h>
65 #include <defer.h>
66 
67 /* Application-specific. */
68 
69 #include "local.h"
70 
71 /* deliver_resolve_addr - resolve and deliver */
72 
73 int deliver_resolve_addr(LOCAL_STATE state, USER_ATTR usr_attr, char *addr)
74 {
75  TOK822 *tree;
76  int result;
77 
78  tree = tok822_scan_addr(addr);
79  result = deliver_resolve_tree(state, usr_attr, tree);
80  tok822_free_tree(tree);
81  return (result);
82 }
83 
84 /* deliver_resolve_tree - resolve and deliver */
85 
86 int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr)
87 {
88  const char *myname = "deliver_resolve_tree";
89  RESOLVE_REPLY reply;
90  int status;
91  ssize_t ext_len;
92  char *ratsign;
93  int rcpt_delim;
94 
95  /*
96  * Make verbose logging easier to understand.
97  */
98  state.level++;
99  if (msg_verbose)
100  MSG_LOG_STATE(myname, state);
101 
102  /*
103  * Initialize.
104  */
105  resolve_clnt_init(&reply);
106 
107  /*
108  * Rewrite the address to canonical form, just like the cleanup service
109  * does. Then, resolve the address to (transport, nexhop, recipient),
110  * just like the queue manager does. The only part missing here is the
111  * virtual address substitution. Message forwarding fixes most of that.
112  */
114  tok822_resolve(addr, &reply);
115 
116  /*
117  * First, a healthy portion of error handling.
118  */
119  if (reply.flags & RESOLVE_FLAG_FAIL) {
120  dsb_simple(state.msg_attr.why, "4.3.0", "address resolver failure");
121  status = defer_append(BOUNCE_FLAGS(state.request),
122  BOUNCE_ATTR(state.msg_attr));
123  } else if (reply.flags & RESOLVE_FLAG_ERROR) {
124  dsb_simple(state.msg_attr.why, "5.1.3",
125  "bad recipient address syntax: %s", STR(reply.recipient));
126  status = bounce_append(BOUNCE_FLAGS(state.request),
127  BOUNCE_ATTR(state.msg_attr));
128  } else {
129 
130  /*
131  * Splice in the optional unmatched address extension.
132  */
133  if (state.msg_attr.unmatched) {
134  rcpt_delim = state.msg_attr.local[strlen(state.msg_attr.user)];
135  if ((ratsign = strrchr(STR(reply.recipient), '@')) == 0) {
136  VSTRING_ADDCH(reply.recipient, rcpt_delim);
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 = rcpt_delim;
145  memcpy(ratsign + 1, state.msg_attr.unmatched, ext_len);
146  VSTRING_SKIP(reply.recipient);
147  }
148  }
149  state.msg_attr.rcpt.address = STR(reply.recipient);
150 
151  /*
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.
156  */
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);
161  }
162  }
163 
164  /*
165  * Cleanup.
166  */
167  resolve_clnt_free(&reply);
168 
169  return (status);
170 }
int msg_verbose
Definition: msg.c:177
#define RESOLVE_FLAG_FAIL
Definition: resolve_clnt.h:28
#define BOUNCE_ATTR(attr)
Definition: local.h:134
int deliver_indirect(LOCAL_STATE state)
Definition: indirect.c:60
const char * address
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
char * local
Definition: local.h:81
Definition: tok822.h:27
void resolve_clnt_free(RESOLVE_REPLY *reply)
Definition: resolve_clnt.c:287
DELIVER_REQUEST * request
Definition: local.h:113
int deliver_recipient(LOCAL_STATE, USER_ATTR)
Definition: recipient.c:206
#define BOUNCE_FLAGS(request)
TOK822 * tok822_free_tree(TOK822 *)
Definition: tok822_tree.c:262
int bounce_append(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn)
Definition: bounce.c:222
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
#define tok822_resolve(t, r)
Definition: tok822.h:108
#define RESOLVE_FLAG_ERROR
Definition: resolve_clnt.h:27
char * unmatched
Definition: local.h:84
void resolve_clnt_init(RESOLVE_REPLY *reply)
Definition: resolve_clnt.c:147
#define VSTRING_SKIP(vp)
Definition: vstring.h:82
char * user
Definition: local.h:82
DELIVER_ATTR msg_attr
Definition: local.h:110
#define STR
Definition: resolve.c:135
DSN_BUF * dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
Definition: dsn_buf.c:275
VSTRING * recipient
Definition: resolve_clnt.h:46
DSN_BUF * why
Definition: local.h:92
int level
Definition: local.h:109
#define REWRITE_CANON
Definition: rewrite_clnt.h:28
#define VSTRING_SPACE(vp, len)
Definition: vstring.h:70
char * relay
Definition: local.h:87
TOK822 * tok822_scan_addr(const char *)
Definition: tok822_parse.c:648
VSTRING * transport
Definition: resolve_clnt.h:44
int defer_append(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn)
Definition: defer.c:187
int deliver_resolve_addr(LOCAL_STATE state, USER_ATTR usr_attr, char *addr)
Definition: resolve.c:73
RECIPIENT rcpt
Definition: local.h:79
#define MSG_LOG_STATE(m, p)
Definition: local.h:150
TOK822 * tok822_rewrite(TOK822 *, const char *)
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
Definition: vstring.c:459
int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr)
Definition: resolve.c:86