Postfix3.3.1
mail_addr_find.c
[詳解]
1 /*++
2 /* NAME
3 /* mail_addr_find 3
4 /* SUMMARY
5 /* generic address-based lookup
6 /* SYNOPSIS
7 /* #include <mail_addr_find.h>
8 /*
9 /* const char *mail_addr_find_int_to_ext(maps, address, extension)
10 /* MAPS *maps;
11 /* const char *address;
12 /* char **extension;
13 /*
14 /* const char *mail_addr_find_opt(maps, address, extension, in_form,
15 /* query_form, out_form, strategy)
16 /* MAPS *maps;
17 /* const char *address;
18 /* char **extension;
19 /* int in_form;
20 /* int in_form;
21 /* int out_form;
22 /* int strategy;
23 /* LEGACY SUPPORT
24 /* const char *mail_addr_find(maps, address, extension)
25 /* MAPS *maps;
26 /* const char *address;
27 /* char **extension;
28 /*
29 /* const char *mail_addr_find_to_internal(maps, address, extension)
30 /* MAPS *maps;
31 /* const char *address;
32 /* char **extension;
33 /*
34 /* const char *mail_addr_find_strategy(maps, address, extension)
35 /* MAPS *maps;
36 /* const char *address;
37 /* char **extension;
38 /* int strategy;
39 /* DESCRIPTION
40 /* mail_addr_find*() searches the specified maps for an entry with as
41 /* key the specified address, and derivations from that address.
42 /* It is up to the caller to specify its case sensitivity
43 /* preferences when it opens the maps.
44 /* The result is overwritten upon each call.
45 /*
46 /* In the lookup table, the key is expected to be in external
47 /* form (as produced with the postmap command) and the value is
48 /* expected to be in external (quoted) form if it is an email
49 /* address. Override these assumptions with the query_form
50 /* and out_form arguments.
51 /*
52 /* With mail_addr_find_int_to_ext(), the specified address is in
53 /* internal (unquoted) form, the query is made in external (quoted)
54 /* form, and the result is in the form found in the table (it is
55 /* not necessarily an email address). This version minimizes
56 /* internal/external (unquoted/quoted) conversions of the input,
57 /* query, extension, or result.
58 /*
59 /* mail_addr_find_opt() gives more control, at the cost of
60 /* additional conversions between internal and external forms.
61 /* In particular, output conversion to internal form assumes
62 /* that the lookup result is an email address.
63 /*
64 /* mail_addr_find() is used by legacy code that historically searched
65 /* with internal-form queries. The input is in internal form. It
66 /* searches with external-form queries first, and falls back to
67 /* internal-form queries if no result was found and the external
68 /* and internal forms differ. The result is external form (i.e. no
69 /* conversion).
70 /*
71 /* mail_addr_find_to_internal() is like mail_addr_find() but assumes
72 /* that the lookup result is one external-form email address,
73 /* and converts it to internal form.
74 /*
75 /* mail_addr_find_strategy() is like mail_addr_find() but overrides
76 /* the default search strategy for full and partial addresses.
77 /*
78 /* Arguments:
79 /* .IP maps
80 /* Dictionary search path (see maps(3)).
81 /* .IP address
82 /* The address to be looked up.
83 /* .IP extension
84 /* A null pointer, or the address of a pointer that is set to
85 /* the address of a dynamic memory copy of the address extension
86 /* that had to be chopped off in order to match the lookup tables.
87 /* The copy includes the recipient address delimiter.
88 /* The copy is in internal (unquoted) form.
89 /* The caller is expected to pass the copy to myfree().
90 /* .IP query_form
91 /* The address form to use for database queries: one of
92 /* MA_FORM_INTERNAL (unquoted form), MA_FORM_EXTERNAL (quoted form),
93 /* MA_FORM_EXTERNAL_FIRST (external form, then internal form if the
94 /* external and internal forms differ), or MA_FORM_INTERNAL_FIRST
95 /* (internal form, then external form if the internal and external
96 /* forms differ).
97 /* .IP in_form .IP out_form
98 /* Input and output address forms, one of MA_FORM_INTERNAL (unquoted
99 /* form), or MA_FORM_EXTERNAL (quoted form).
100 /* .IP strategy
101 /* The lookup strategy for full and partial addresses, specified
102 /* as the binary OR of one or more of the following. These lookups
103 /* are implemented in the order as listed below.
104 /* .RS
105 /* .IP MA_FIND_DEFAULT
106 /* A convenience alias for (MA_FIND_FULL |
107 /* MA_FIND_NOEXT | MA_FIND_LOCALPART_IF_LOCAL |
108 /* MA_FIND_AT_DOMAIN).
109 /* .IP MA_FIND_FULL
110 /* Look up the full email address.
111 /* .IP MA_FIND_NOEXT
112 /* If no match was found, and the address has a localpart extension,
113 /* look up the address after removing the extension.
114 /* .IP MA_FIND_LOCALPART_IF_LOCAL
115 /* If no match was found, and the domain matches myorigin,
116 /* mydestination, or any inet_interfaces or proxy_interfaces IP
117 /* address, look up the localpart. If no match was found, and the
118 /* address has a localpart extension, repeat the same query after
119 /* removing the extension unless MA_FIND_NOEXT is specified.
120 /* .IP MA_FIND_LOCALPART_AT_IF_LOCAL
121 /* As above, but using the localpart@ instead.
122 /* .IP MA_FIND_AT_DOMAIN
123 /* If no match was found, look up the @domain without localpart.
124 /* .IP MA_FIND_DOMAIN
125 /* If no match was found, look up the domain without localpart.
126 /* .IP MA_FIND_PDMS
127 /* When used with MA_FIND_DOMAIN, the domain also matches subdomains.
128 /* .IP MA_FIND_PDDMDS
129 /* When used with MA_FIND_DOMAIN, dot-domain also matches
130 /* dot-subdomains.
131 /* .IP MA_FIND_LOCALPART_AT
132 /* If no match was found, look up the localpart@, regardless of
133 /* the domain content.
134 /* .RE
135 /* DIAGNOSTICS
136 /* The maps->error value is non-zero when the lookup failed due to
137 /* a non-permanent error.
138 /* SEE ALSO
139 /* maps(3), multi-dictionary search resolve_local(3), recognize
140 /* local system
141 /* LICENSE
142 /* .ad
143 /* .fi
144 /* The Secure Mailer license must be distributed with this software.
145 /* AUTHOR(S)
146 /* Wietse Venema
147 /* IBM T.J. Watson Research
148 /* P.O. Box 704
149 /* Yorktown Heights, NY 10598, USA
150 /*
151 /* Wietse Venema
152 /* Google, Inc.
153 /* 111 8th Avenue
154 /* New York, NY 10011, USA
155 /*--*/
156 
157 /* System library. */
158 
159 #include <sys_defs.h>
160 #include <string.h>
161 
162 /* Utility library. */
163 
164 #include <msg.h>
165 #include <name_mask.h>
166 #include <dict.h>
167 #include <stringops.h>
168 #include <mymalloc.h>
169 #include <vstring.h>
170 
171 /* Global library. */
172 
173 #include <mail_params.h>
174 #include <strip_addr.h>
175 #include <mail_addr_find.h>
176 #include <resolve_local.h>
177 #include <quote_822_local.h>
178 
179 /* Application-specific. */
180 
181 #define STR vstring_str
182 
183 #ifdef TEST
184 
185 static const NAME_MASK strategy_table[] = {
186  "full", MA_FIND_FULL,
187  "noext", MA_FIND_NOEXT,
188  "localpart_if_local", MA_FIND_LOCALPART_IF_LOCAL,
189  "localpart_at_if_local", MA_FIND_LOCALPART_AT_IF_LOCAL,
190  "at_domain", MA_FIND_AT_DOMAIN,
191  "domain", MA_FIND_DOMAIN,
192  "pdms", MA_FIND_PDMS,
193  "pddms", MA_FIND_PDDMDS,
194  "localpart_at", MA_FIND_LOCALPART_AT,
195  "default", MA_FIND_DEFAULT,
196  0, -1,
197 };
198 
199 /* strategy_from_string - symbolic strategy flags to internal form */
200 
201 static int strategy_from_string(const char *strategy_string)
202 {
203  return (name_mask_delim_opt("strategy_from_string", strategy_table,
204  strategy_string, "|",
206 }
207 
208 /* strategy_to_string - internal form to symbolic strategy flags */
209 
210 static const char *strategy_to_string(VSTRING *res_buf, int strategy_mask)
211 {
212  static VSTRING *my_buf;
213 
214  if (res_buf == 0 && (res_buf = my_buf) == 0)
215  res_buf = my_buf = vstring_alloc(20);
216  return (str_name_mask_opt(res_buf, "strategy_to_string",
217  strategy_table, strategy_mask,
219 }
220 
221 #endif
222 
223  /*
224  * Specify what keys are partial or full, to avoid matching partial
225  * addresses with regular expressions.
226  */
227 #define FULL 0
228 #define PARTIAL DICT_FLAG_FIXED
229 
230 /* find_addr - helper to search maps with the right query form */
231 
232 static const char *find_addr(MAPS *path, const char *address, int flags,
233  int with_domain, int query_form, VSTRING *ext_addr_buf)
234 {
235  const char *result;
236 
237 #define SANS_DOMAIN 0
238 #define WITH_DOMAIN 1
239 
240  switch (query_form) {
241 
242  /*
243  * Query with external-form (quoted) address. The code looks a bit
244  * unusual to emphasize the symmetry with the other cases.
245  */
246  case MA_FORM_EXTERNAL:
248  quote_822_local_flags(ext_addr_buf, address,
249  with_domain ? QUOTE_FLAG_DEFAULT :
251  result = maps_find(path, STR(ext_addr_buf), flags);
252  if (result != 0 || path->error != 0
253  || query_form != MA_FORM_EXTERNAL_FIRST
254  || strcmp(address, STR(ext_addr_buf)) == 0)
255  break;
256  result = maps_find(path, address, flags);
257  break;
258 
259  /*
260  * Query with internal-form (unquoted) address. The code looks a bit
261  * unusual to emphasize the symmetry with the other cases.
262  */
263  case MA_FORM_INTERNAL:
265  result = maps_find(path, address, flags);
266  if (result != 0 || path->error != 0
267  || query_form != MA_FORM_INTERNAL_FIRST)
268  break;
269  quote_822_local_flags(ext_addr_buf, address,
270  with_domain ? QUOTE_FLAG_DEFAULT :
272  if (strcmp(address, STR(ext_addr_buf)) == 0)
273  break;
274  result = maps_find(path, STR(ext_addr_buf), flags);
275  break;
276 
277  /*
278  * Can't happen.
279  */
280  default:
281  msg_panic("mail_addr_find: bad query_form: %d", query_form);
282  }
283  return (result);
284 }
285 
286 /* find_local - search on localpart info */
287 
288 static const char *find_local(MAPS *path, char *ratsign, int rats_offs,
289  char *int_full_key, char *int_bare_key,
290  int query_form, char **extp, char **saved_ext,
291  VSTRING *ext_addr_buf)
292 {
293  const char *myname = "mail_addr_find";
294  const char *result;
295  int with_domain;
296  int saved_ch;
297 
298  /*
299  * This code was ripped from the middle of a function so that it can be
300  * reused multiple times, that's why the interface makes little sense.
301  */
302  with_domain = rats_offs ? WITH_DOMAIN : SANS_DOMAIN;
303 
304  saved_ch = *(unsigned char *) (ratsign + rats_offs);
305  *(ratsign + rats_offs) = 0;
306  result = find_addr(path, int_full_key, PARTIAL, with_domain,
307  query_form, ext_addr_buf);
308  *(ratsign + rats_offs) = saved_ch;
309  if (result == 0 && path->error == 0 && int_bare_key != 0) {
310  if ((ratsign = strrchr(int_bare_key, '@')) == 0)
311  msg_panic("%s: bare key botch", myname);
312  saved_ch = *(unsigned char *) (ratsign + rats_offs);
313  *(ratsign + rats_offs) = 0;
314  if ((result = find_addr(path, int_bare_key, PARTIAL, with_domain,
315  query_form, ext_addr_buf)) != 0
316  && extp != 0) {
317  *extp = *saved_ext;
318  *saved_ext = 0;
319  }
320  *(ratsign + rats_offs) = saved_ch;
321  }
322  return result;
323 }
324 
325 /* mail_addr_find_opt - map a canonical address */
326 
327 const char *mail_addr_find_opt(MAPS *path, const char *address, char **extp,
328  int in_form, int query_form,
329  int out_form, int strategy)
330 {
331  const char *myname = "mail_addr_find";
332  VSTRING *ext_addr_buf = 0;
333  VSTRING *int_addr_buf = 0;
334  const char *int_addr;
335  static VSTRING *int_result = 0;
336  const char *result;
337  char *ratsign = 0;
338  char *int_full_key;
339  char *int_bare_key;
340  char *saved_ext;
341  int rc = 0;
342 
343  /*
344  * Optionally convert the address from external form.
345  */
346  if (in_form == MA_FORM_EXTERNAL) {
347  int_addr_buf = vstring_alloc(100);
348  unquote_822_local(int_addr_buf, address);
349  int_addr = STR(int_addr_buf);
350  } else {
351  int_addr = address;
352  }
353  if (query_form == MA_FORM_EXTERNAL_FIRST
354  || query_form == MA_FORM_EXTERNAL)
355  ext_addr_buf = vstring_alloc(100);
356 
357  /*
358  * Initialize.
359  */
360  int_full_key = mystrdup(int_addr);
361  if (*var_rcpt_delim == 0 || (strategy & MA_FIND_NOEXT) == 0) {
362  int_bare_key = saved_ext = 0;
363  } else {
364  /* XXX This could be done after user+foo@domain fails. */
365  int_bare_key =
366  strip_addr_internal(int_full_key, &saved_ext, var_rcpt_delim);
367  }
368 
369  /*
370  * Try user+foo@domain and user@domain.
371  */
372  if ((strategy & MA_FIND_FULL) != 0) {
373  result = find_addr(path, int_full_key, FULL, WITH_DOMAIN,
374  query_form, ext_addr_buf);
375  } else {
376  result = 0;
377  path->error = 0;
378  }
379 
380  if (result == 0 && path->error == 0 && int_bare_key != 0
381  && (result = find_addr(path, int_bare_key, PARTIAL, WITH_DOMAIN,
382  query_form, ext_addr_buf)) != 0
383  && extp != 0) {
384  *extp = saved_ext;
385  saved_ext = 0;
386  }
387 
388  /*
389  * Try user+foo if the domain matches user+foo@$myorigin,
390  * user+foo@$mydestination or user+foo@[${proxy,inet}_interfaces]. Then
391  * try with +foo stripped off.
392  */
393  if (result == 0 && path->error == 0
394  && (ratsign = strrchr(int_full_key, '@')) != 0
395  && (strategy & (MA_FIND_LOCALPART_IF_LOCAL
397  if (strcasecmp_utf8(ratsign + 1, var_myorigin) == 0
398  || (rc = resolve_local(ratsign + 1)) > 0) {
399  if ((strategy & MA_FIND_LOCALPART_IF_LOCAL) != 0)
400  result = find_local(path, ratsign, 0, int_full_key,
401  int_bare_key, query_form, extp, &saved_ext,
402  ext_addr_buf);
403  if (result == 0 && path->error == 0
404  && (strategy & MA_FIND_LOCALPART_AT_IF_LOCAL) != 0)
405  result = find_local(path, ratsign, 1, int_full_key,
406  int_bare_key, query_form, extp, &saved_ext,
407  ext_addr_buf);
408  } else if (rc < 0)
409  path->error = rc;
410  }
411 
412  /*
413  * Try @domain.
414  */
415  if (result == 0 && path->error == 0 && ratsign != 0
416  && (strategy & MA_FIND_AT_DOMAIN) != 0)
417  result = maps_find(path, ratsign, PARTIAL);
418 
419  /*
420  * Try domain (optionally, subdomains).
421  */
422  if (result == 0 && path->error == 0 && ratsign != 0
423  && (strategy & MA_FIND_DOMAIN) != 0) {
424  const char *name;
425  const char *next;
426 
427  if ((strategy & MA_FIND_PDMS) && (strategy & MA_FIND_PDDMDS))
428  msg_warn("mail_addr_find_opt: do not specify both "
429  "MA_FIND_PDMS and MA_FIND_PDDMDS");
430  for (name = ratsign + 1; *name != 0; name = next) {
431  if ((result = maps_find(path, name, PARTIAL)) != 0
432  || path->error != 0
433  || (strategy & (MA_FIND_PDMS | MA_FIND_PDDMDS)) == 0
434  || (next = strchr(name + 1, '.')) == 0)
435  break;
436  if ((strategy & MA_FIND_PDDMDS) == 0)
437  next++;
438  }
439  }
440 
441  /*
442  * Try localpart@ even if the domain is not local.
443  */
444  if ((strategy & MA_FIND_LOCALPART_AT) != 0 \
445  &&result == 0 && path->error == 0)
446  result = find_local(path, ratsign, 1, int_full_key,
447  int_bare_key, query_form, extp, &saved_ext,
448  ext_addr_buf);
449 
450  /*
451  * Optionally convert the result to internal form. The lookup result is
452  * supposed to be one external-form email address.
453  */
454  if (result != 0 && out_form == MA_FORM_INTERNAL) {
455  if (int_result == 0)
456  int_result = vstring_alloc(100);
457  unquote_822_local(int_result, result);
458  result = STR(int_result);
459  }
460 
461  /*
462  * Clean up.
463  */
464  if (msg_verbose)
465  msg_info("%s: %s -> %s", myname, address,
466  result ? result :
467  path->error ? "(try again)" :
468  "(not found)");
469  myfree(int_full_key);
470  if (int_bare_key)
471  myfree(int_bare_key);
472  if (saved_ext)
473  myfree(saved_ext);
474  if (int_addr_buf)
475  vstring_free(int_addr_buf);
476  if (ext_addr_buf)
477  vstring_free(ext_addr_buf);
478  return (result);
479 }
480 
481 #ifdef TEST
482 
483  /*
484  * Proof-of-concept test program. Read an address and expected results from
485  * stdin, and warn about any discrepancies.
486  */
487 #include <ctype.h>
488 #include <stdlib.h>
489 
490 #include <vstream.h>
491 #include <vstring_vstream.h>
492 #include <mail_params.h>
493 
494 static NORETURN usage(const char *progname)
495 {
496  msg_fatal("usage: %s [-v]", progname);
497 }
498 
499 int main(int argc, char **argv)
500 {
501  VSTRING *buffer = vstring_alloc(100);
502  char *bp;
503  MAPS *path = 0;
504  const char *result;
505  char *extent;
506  char *cmd;
507  char *in_field;
508  char *query_field;
509  char *out_field;
510  char *strategy_field;
511  char *key_field;
512  char *expect_res;
513  char *expect_ext;
514  int in_form;
515  int query_form;
516  int out_form;
517  int strategy_flags;
518  int ch;
519  int errs = 0;
520 
521  /*
522  * Parse JCL.
523  */
524  while ((ch = GETOPT(argc, argv, "v")) > 0) {
525  switch (ch) {
526  case 'v':
527  msg_verbose++;
528  break;
529  default:
530  usage(argv[0]);
531  }
532  }
533  if (argc != optind)
534  usage(argv[0]);
535 
536  /*
537  * Initialize.
538  */
539 #define UPDATE(var, val) do { myfree(var); var = mystrdup(val); } while (0)
540 
542 
543  /*
544  * TODO: move these assignments into the read/eval loop.
545  */
546  UPDATE(var_rcpt_delim, "+");
547  UPDATE(var_mydomain, "localdomain");
548  UPDATE(var_myorigin, "localdomain");
549  UPDATE(var_mydest, "localhost.localdomain");
550  while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
551  bp = STR(buffer);
552  if (msg_verbose)
553  msg_info("> %s", bp);
554  if ((cmd = mystrtok(&bp, CHARS_SPACE)) == 0 || *cmd == '#')
555  continue;
556  while (ISSPACE(*bp))
557  bp++;
558 
559  /*
560  * Visible comment.
561  */
562  if (strcmp(cmd, "echo") == 0) {
563  vstream_printf("%s\n", bp);
564  }
565 
566  /*
567  * Open maps.
568  */
569  else if (strcmp(cmd, "maps") == 0) {
570  if (path)
571  maps_free(path);
572  path = maps_create(argv[0], bp, DICT_FLAG_LOCK
574  vstream_printf("%s\n", bp);
575  continue;
576  }
577 
578  /*
579  * Lookup and verify.
580  */
581  else if (path && strcmp(cmd, "test") == 0) {
582 
583  /*
584  * Parse the input and expectations.
585  */
586  /* internal, external. */
587  if ((in_field = mystrtok(&bp, ":")) == 0)
588  msg_fatal("no input form");
589  if ((in_form = mail_addr_form_from_string(in_field)) < 0)
590  msg_fatal("bad input form: '%s'", in_field);
591  if ((query_field = mystrtok(&bp, ":")) == 0)
592  msg_fatal("no query form");
593  /* internal, external, external-first. */
594  if ((query_form = mail_addr_form_from_string(query_field)) < 0)
595  msg_fatal("bad query form: '%s'", query_field);
596  if ((out_field = mystrtok(&bp, ":")) == 0)
597  msg_fatal("no output form");
598  /* internal, external. */
599  if ((out_form = mail_addr_form_from_string(out_field)) < 0)
600  msg_fatal("bad output form: '%s'", out_field);
601  if ((strategy_field = mystrtok(&bp, ":")) == 0)
602  msg_fatal("no strategy field");
603  if ((strategy_flags = strategy_from_string(strategy_field)) < 0)
604  msg_fatal("bad strategy field: '%s'", strategy_field);
605  if ((key_field = mystrtok(&bp, ":")) == 0)
606  msg_fatal("no search key");
607  expect_res = mystrtok(&bp, ":");
608  expect_ext = mystrtok(&bp, ":");
609  if (mystrtok(&bp, ":") != 0)
610  msg_fatal("garbage after extension field");
611 
612  /*
613  * Lookups.
614  */
615  extent = 0;
616  result = mail_addr_find_opt(path, key_field, &extent,
617  in_form, query_form, out_form,
618  strategy_flags);
619  vstream_printf("%s:%s -%s-> %s:%s (%s)\n",
620  in_field, key_field, query_field, out_field, result ? result :
621  path->error ? "(try again)" :
622  "(not found)", extent ? extent : "null extension");
624 
625  /*
626  * Enforce expectations.
627  */
628  if (expect_res && result) {
629  if (strcmp(expect_res, result) != 0) {
630  msg_warn("expect result '%s' but got '%s'", expect_res, result);
631  errs = 1;
632  if (expect_ext && extent) {
633  if (strcmp(expect_ext, extent) != 0)
634  msg_warn("expect extension '%s' but got '%s'",
635  expect_ext, extent);
636  errs = 1;
637  } else if (expect_ext && !extent) {
638  msg_warn("expect extension '%s' but got none", expect_ext);
639  errs = 1;
640  } else if (!expect_ext && extent) {
641  msg_warn("expect no extension but got '%s'", extent);
642  errs = 1;
643  }
644  }
645  } else if (expect_res && !result) {
646  msg_warn("expect result '%s' but got none", expect_res);
647  errs = 1;
648  } else if (!expect_res && result) {
649  msg_warn("expected no result but got '%s'", result);
650  errs = 1;
651  }
653  if (extent)
654  myfree(extent);
655  }
656 
657  /*
658  * Unknown request.
659  */
660  else {
661  msg_warn("bad request: %s", cmd);
662  }
663  }
664  vstring_free(buffer);
665 
666  maps_free(path);
667  return (errs != 0);
668 }
669 
670 #endif
int msg_verbose
Definition: msg.c:177
#define MA_FORM_INTERNAL_FIRST
#define vstring_fgets_nonl(s, p)
void mail_params_init()
Definition: mail_params.c:658
void myfree(void *ptr)
Definition: mymalloc.c:207
#define MA_FORM_INTERNAL
char * mystrdup(const char *str)
Definition: mymalloc.c:225
#define MA_FIND_NOEXT
#define NORETURN
Definition: sys_defs.h:1583
#define MA_FIND_LOCALPART_AT_IF_LOCAL
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define VSTREAM_OUT
Definition: vstream.h:67
int main(int argc, char **argv)
Definition: anvil.c:1010
#define MA_FIND_DEFAULT
Definition: maps.h:22
VSTRING * unquote_822_local(VSTRING *dst, const char *mbox)
int resolve_local(const char *addr)
Definition: resolve_local.c:78
char * var_mydomain
Definition: mail_params.c:224
#define DICT_FLAG_UTF8_REQUEST
Definition: dict.h:130
#define VSTREAM_IN
Definition: vstream.h:66
#define strcasecmp_utf8(s1, s2)
Definition: stringops.h:75
#define FULL
char * var_myorigin
Definition: mail_params.c:225
char * mystrtok(char **src, const char *sep)
Definition: mystrtok.c:54
#define SANS_DOMAIN
#define DICT_FLAG_FOLD_FIX
Definition: dict.h:124
#define PARTIAL
VSTRING * quote_822_local_flags(VSTRING *dst, const char *mbox, int flags)
char * var_rcpt_delim
Definition: mail_params.c:274
const char * str_name_mask_opt(VSTRING *buf, const char *context, const NAME_MASK *table, int mask, int flags)
Definition: name_mask.c:265
#define MA_FIND_FULL
const char * mail_addr_find_opt(MAPS *path, const char *address, char **extp, int in_form, int query_form, int out_form, int strategy)
MAPS * maps_create(const char *title, const char *map_names, int dict_flags)
Definition: maps.c:112
#define QUOTE_FLAG_BARE_LOCALPART
Definition: quote_flags.h:22
VSTREAM * vstream_printf(const char *fmt,...)
Definition: vstream.c:1335
#define DICT_FLAG_LOCK
Definition: dict.h:116
void msg_warn(const char *fmt,...)
Definition: msg.c:215
int name_mask_delim_opt(const char *context, const NAME_MASK *table, const char *names, const char *delim, int flags)
Definition: name_mask.c:206
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define CHARS_SPACE
Definition: sys_defs.h:1762
#define WITH_DOMAIN
#define QUOTE_FLAG_DEFAULT
Definition: quote_flags.h:24
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
MAPS * maps_free(MAPS *maps)
Definition: maps.c:213
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
#define MA_FIND_PDDMDS
int error
Definition: maps.h:25
#define GETOPT(argc, argv, str)
Definition: sys_defs.h:1313
#define STR
#define MA_FIND_LOCALPART_AT
#define MA_FIND_LOCALPART_IF_LOCAL
#define MA_FIND_PDMS
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
#define MA_FIND_AT_DOMAIN
#define NAME_MASK_ANY_CASE
Definition: name_mask.h:28
#define UPDATE(ptr, new)
#define ISSPACE(c)
Definition: sys_defs.h:1753
int mail_addr_form_from_string(const char *addr_form_name)
char * strip_addr_internal(const char *full, char **extension, const char *delimiter_set)
Definition: strip_addr.c:74
#define NAME_MASK_WARN
Definition: name_mask.h:33
#define NAME_MASK_PIPE
Definition: name_mask.h:31
#define MA_FIND_DOMAIN
const char * maps_find(MAPS *maps, const char *name, int flags)
Definition: maps.c:162
#define MA_FORM_EXTERNAL
#define MA_FORM_EXTERNAL_FIRST
void msg_info(const char *fmt,...)
Definition: msg.c:199
char * var_mydest
Definition: mail_params.c:226