7 /* parse and canonicalize addresses, apply address extension
9 /* #include <mail_addr_crunch.h>
11 /* ARGV *mail_addr_crunch(string, extension)
12 /* const char *string;
13 /* const char *extension;
15 /* mail_addr_crunch() parses a string with zero or more addresses,
16 /* rewrites each address to canonical form, and optionally applies
17 /* an address extension to each resulting address. Input and result
18 /* are in external (quoted) format. The caller is expected to pass
19 /* the result to argv_free().
23 /* A string with zero or more addresses in RFC 822 (external) format.
25 /* A null pointer, or an address extension (including the recipient
26 /* address delimiter) that is propagated to all result addresses.
28 /* Fatal error: out of memory.
30 /* tok822_parse(3), address parser
31 /* canon_addr(3), address canonicalization
35 /* The Secure Mailer license must be distributed with this software.
38 /* IBM T.J. Watson Research
40 /* Yorktown Heights, NY 10598, USA
48 /* Utility library. */
57 #include <canon_addr.h>
58 #include <mail_addr_crunch.h>
60 /* mail_addr_crunch - break string into addresses, optionally add extension */
62 ARGV
*mail_addr_crunch(const char *string
, const char *extension
)
64 VSTRING
*extern_addr
= vstring_alloc(100);
65 VSTRING
*canon_addr
= vstring_alloc(100);
66 ARGV
*argv
= argv_alloc(1);
74 extlen
= strlen(extension
);
76 #define STR(x) vstring_str(x)
79 * Parse the string, rewrite each address to canonical form, and convert
80 * the result to external (quoted) form. Optionally apply the extension
81 * to each address found.
83 * XXX Workaround for the null address. This works for envelopes but
84 * produces ugly results for message headers.
86 if (*string
== 0 || strcmp(string
, "<>") == 0)
88 tree
= tok822_parse(string
);
89 addr_list
= tok822_grep(tree
, TOK822_ADDR
);
90 for (tpp
= addr_list
; *tpp
; tpp
++) {
91 tok822_externalize(extern_addr
, tpp
[0]->head
, TOK822_STR_DEFL
);
92 canon_addr_external(canon_addr
, STR(extern_addr
));
94 VSTRING_SPACE(canon_addr
, extlen
+ 1);
95 if ((ratsign
= strrchr(STR(canon_addr
), '@')) == 0) {
96 vstring_strcat(canon_addr
, extension
);
98 memmove(ratsign
+ extlen
, ratsign
, strlen(ratsign
) + 1);
99 memcpy(ratsign
, extension
, extlen
);
100 VSTRING_SKIP(canon_addr
);
103 argv_add(argv
, STR(canon_addr
), ARGV_END
);
105 argv_terminate(argv
);
106 myfree((char *) addr_list
);
107 tok822_free_tree(tree
);
108 vstring_free(canon_addr
);
109 vstring_free(extern_addr
);
116 * Stand-alone test program, sort of interactive.
122 #include <vstring_vstream.h>
123 #include <mail_conf.h>
124 #include <mail_params.h>
126 int main(int unused_argc
, char **unused_argv
)
128 VSTRING
*extension
= vstring_alloc(1);
129 VSTRING
*buf
= vstring_alloc(1);
134 if (chdir(var_queue_dir
) < 0)
135 msg_fatal("chdir %s: %m", var_queue_dir
);
137 vstream_printf("extension: (CR for none): ");
138 vstream_fflush(VSTREAM_OUT
);
139 if (vstring_get_nonl(extension
, VSTREAM_IN
) == VSTREAM_EOF
)
142 vstream_printf("print strings to be translated, one per line\n");
143 vstream_fflush(VSTREAM_OUT
);
144 while (vstring_get_nonl(buf
, VSTREAM_IN
) != VSTREAM_EOF
) {
145 argv
= mail_addr_crunch(STR(buf
), VSTRING_LEN(extension
) ? STR(extension
) : 0);
146 for (cpp
= argv
->argv
; *cpp
; cpp
++)
147 vstream_printf(" %s\n", *cpp
);
148 vstream_fflush(VSTREAM_OUT
);