162
162
TOK822 **addr_list;
166
167
msg_info("rewrite_sender: %s", hdr_opts->name);
169
* Parse the header line, rewrite each address found, save copies of
170
* sender addresses, and regenerate the header line. Finally, pipe the
171
* result through the header line folding routine.
170
* Parse the header line, rewrite each address found, and regenerate the
171
* header line. Finally, pipe the result through the header line folding
173
174
tree = tok822_parse_limit(vstring_str(header_buf)
174
175
+ strlen(hdr_opts->name) + 1,
175
176
var_token_limit);
176
177
addr_list = tok822_grep(tree, TOK822_ADDR);
177
178
for (tpp = addr_list; *tpp; tpp++) {
178
cleanup_rewrite_tree(*tpp);
179
did_rewrite |= cleanup_rewrite_tree(state->hdr_rewrite_context, *tpp);
179
180
if (state->flags & CLEANUP_FLAG_MAP_OK) {
180
if (cleanup_send_canon_maps)
181
cleanup_map11_tree(state, *tpp, cleanup_send_canon_maps,
181
if (cleanup_send_canon_maps
182
&& (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_HDR_FROM))
184
cleanup_map11_tree(state, *tpp, cleanup_send_canon_maps,
182
185
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
183
if (cleanup_comm_canon_maps)
184
cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
186
if (cleanup_comm_canon_maps
187
&& (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_HDR_FROM))
189
cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
185
190
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
186
191
if (cleanup_masq_domains
187
192
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_FROM))
188
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
194
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
190
if (hdr_opts->type == HDR_FROM && state->from == 0)
191
state->from = cleanup_extract_internal(header_buf, *tpp);
192
if (hdr_opts->type == HDR_RESENT_FROM && state->resent_from == 0)
194
cleanup_extract_internal(header_buf, *tpp);
196
if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt)
197
state->return_receipt =
198
cleanup_extract_internal(header_buf, *tpp);
200
if (var_enable_errors_to)
201
if (hdr_opts->type == HDR_ERRORS_TO && !state->errors_to)
203
cleanup_extract_internal(header_buf, *tpp);
205
vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
206
tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
198
vstring_truncate(header_buf, strlen(hdr_opts->name));
199
vstring_strcat(header_buf, ": ");
200
tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
207
202
myfree((char *) addr_list);
208
203
tok822_free_tree(tree);
209
if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
210
cleanup_fold_header(state, header_buf);
204
if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
206
cleanup_fold_header(state, header_buf);
208
cleanup_out_header(state, header_buf);
213
212
/* cleanup_rewrite_recip - recipient address rewriting */
219
218
TOK822 **addr_list;
223
223
msg_info("rewrite_recip: %s", hdr_opts->name);
226
* Parse the header line, rewrite each address found, save copies of
227
* recipient addresses, and regenerate the header line. Finally, pipe the
228
* result through the header line folding routine.
226
* Parse the header line, rewrite each address found, and regenerate the
227
* header line. Finally, pipe the result through the header line folding
230
230
tree = tok822_parse_limit(vstring_str(header_buf)
231
231
+ strlen(hdr_opts->name) + 1,
232
232
var_token_limit);
233
233
addr_list = tok822_grep(tree, TOK822_ADDR);
234
234
for (tpp = addr_list; *tpp; tpp++) {
235
cleanup_rewrite_tree(*tpp);
235
did_rewrite |= cleanup_rewrite_tree(state->hdr_rewrite_context, *tpp);
236
236
if (state->flags & CLEANUP_FLAG_MAP_OK) {
237
if (cleanup_rcpt_canon_maps)
238
cleanup_map11_tree(state, *tpp, cleanup_rcpt_canon_maps,
239
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
240
if (cleanup_comm_canon_maps)
241
cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
242
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
237
if (cleanup_rcpt_canon_maps
238
&& (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_HDR_RCPT))
240
cleanup_map11_tree(state, *tpp, cleanup_rcpt_canon_maps,
241
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
242
if (cleanup_comm_canon_maps
243
&& (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_HDR_RCPT))
245
cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
246
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
244
247
if (cleanup_masq_domains
245
248
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT))
246
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
250
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
249
vstring_sprintf(header_buf, "%s: ", hdr_opts->name);
250
tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
254
vstring_truncate(header_buf, strlen(hdr_opts->name));
255
vstring_strcat(header_buf, ": ");
256
tok822_externalize(header_buf, tree, TOK822_STR_HEAD);
251
258
myfree((char *) addr_list);
252
259
tok822_free_tree(tree);
253
if ((hdr_opts->flags & HDR_OPT_DROP) == 0)
254
cleanup_fold_header(state, header_buf);
260
if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
262
cleanup_fold_header(state, header_buf);
264
cleanup_out_header(state, header_buf);
257
268
/* cleanup_act_log - log action with context */
285
296
/* cleanup_act - act upon a header/body match */
287
static int cleanup_act(CLEANUP_STATE *state, char *context, const char *buf,
288
const char *value, const char *map_class)
298
static const char *cleanup_act(CLEANUP_STATE *state, char *context,
299
const char *buf, const char *value,
300
const char *map_class)
290
302
const char *optional_text = value + strcspn(value, " \t");
291
303
int command_len = optional_text - value;
304
315
state->errs |= CLEANUP_STAT_CONT;
305
316
state->flags &= ~CLEANUP_FLAG_FILTER;
306
317
cleanup_act_log(state, "reject", context, buf, state->reason);
307
return (CLEANUP_ACT_KEEP);
309
320
if (STREQUAL(value, "WARN", command_len)) {
310
321
cleanup_act_log(state, "warning", context, buf, optional_text);
311
return (CLEANUP_ACT_KEEP);
313
324
if (STREQUAL(value, "FILTER", command_len)) {
314
325
if (*optional_text == 0) {
315
326
msg_warn("missing FILTER command argument in %s map", map_class);
316
327
} else if (strchr(optional_text, ':') == 0) {
317
msg_warn("bad FILTER command %s in %s, need transport:destination",
328
msg_warn("bad FILTER command %s in %s -- "
329
"need transport:destination",
318
330
optional_text, map_class);
320
332
if (state->filter)
322
334
state->filter = mystrdup(optional_text);
323
335
cleanup_act_log(state, "filter", context, buf, optional_text);
325
return (CLEANUP_ACT_KEEP);
327
339
if (STREQUAL(value, "DISCARD", command_len)) {
328
340
cleanup_act_log(state, "discard", context, buf, optional_text);
329
341
state->flags |= CLEANUP_FLAG_DISCARD;
330
342
state->flags &= ~CLEANUP_FLAG_FILTER;
331
return (CLEANUP_ACT_KEEP);
333
345
if (STREQUAL(value, "HOLD", command_len)) {
334
346
cleanup_act_log(state, "hold", context, buf, optional_text);
335
347
state->flags |= CLEANUP_FLAG_HOLD;
336
return (CLEANUP_ACT_KEEP);
338
350
if (STREQUAL(value, "PREPEND", command_len)) {
339
351
if (*optional_text == 0) {
340
352
msg_warn("PREPEND action without text in %s map", map_class);
341
353
} else if (strcmp(context, CLEANUP_ACT_CTXT_HEADER) == 0
342
354
&& !is_header(optional_text)) {
343
msg_warn("bad PREPEND header text \"%s\" in %s map, "
355
msg_warn("bad PREPEND header text \"%s\" in %s map -- "
344
356
"need \"headername: headervalue\"",
345
357
optional_text, map_class);
347
359
cleanup_act_log(state, "prepend", context, buf, optional_text);
348
360
cleanup_out_string(state, REC_TYPE_NORM, optional_text);
350
return (CLEANUP_ACT_KEEP);
364
if (STREQUAL(value, "REPLACE", command_len)) {
365
if (*optional_text == 0) {
366
msg_warn("REPLACE action without text in %s map", map_class);
368
} else if (strcmp(context, CLEANUP_ACT_CTXT_HEADER) == 0
369
&& !is_header(optional_text)) {
370
msg_warn("bad REPLACE header text \"%s\" in %s map -- "
371
"need \"headername: headervalue\"",
372
optional_text, map_class);
375
cleanup_act_log(state, "replace", context, buf, optional_text);
376
return (mystrdup(optional_text));
352
379
if (STREQUAL(value, "REDIRECT", command_len)) {
353
380
if (strchr(optional_text, '@') == 0) {
354
msg_warn("bad REDIRECT target \"%s\" in %s map, need user@domain",
381
msg_warn("bad REDIRECT target \"%s\" in %s map -- "
355
383
optional_text, map_class);
357
385
if (state->redirect)
368
396
return (CLEANUP_ACT_DROP);
370
398
if (STREQUAL(value, "DUNNO", command_len)) /* preferred */
371
return (CLEANUP_ACT_KEEP);
373
401
if (STREQUAL(value, "OK", command_len)) /* compat */
374
return (CLEANUP_ACT_KEEP);
376
404
msg_warn("unknown command in %s map: %s", map_class, value);
377
return (CLEANUP_ACT_KEEP);
380
408
/* cleanup_header_callback - process one complete header line */
423
451
const char *value;
425
453
if ((value = maps_find(checks, header, 0)) != 0) {
426
if (cleanup_act(state, CLEANUP_ACT_CTXT_HEADER,
427
header, value, map_class)
456
if ((result = cleanup_act(state, CLEANUP_ACT_CTXT_HEADER,
457
header, value, map_class))
458
== CLEANUP_ACT_DROP) {
460
} else if (result != header) {
461
vstring_strcpy(header_buf, result);
462
hdr_opts = header_opts_find(result);
463
myfree((char *) result);
508
543
if (CLEANUP_OUT_OK(state)) {
509
544
if (hdr_opts->flags & HDR_OPT_RR)
510
545
state->resent = "Resent-";
511
if (hdr_opts->flags & HDR_OPT_SENDER) {
546
if ((hdr_opts->flags & HDR_OPT_SENDER)
547
&& state->hdr_rewrite_context) {
512
548
cleanup_rewrite_sender(state, hdr_opts, header_buf);
513
} else if (hdr_opts->flags & HDR_OPT_RECIP) {
549
} else if ((hdr_opts->flags & HDR_OPT_RECIP)
550
&& state->hdr_rewrite_context) {
514
551
cleanup_rewrite_recip(state, hdr_opts, header_buf);
515
552
} else if ((hdr_opts->flags & HDR_OPT_DROP) == 0) {
516
553
cleanup_out_header(state, header_buf);
537
575
* XXX It is the queue ID non-inode bits that prevent messages from getting
538
576
* the same Message-Id within the same second.
578
* XXX An arbitrary amount of time may pass between the start of the mail
579
* transaction and the creation of a queue file. Since we guarantee queue
580
* ID uniqueness only within a second, we must ensure that the time in
581
* the message ID matches the queue ID creation time, as long as we use
582
* the queue ID in the message ID.
540
584
if ((state->headers_seen & (1 << (state->resent[0] ?
541
585
HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) {
542
tp = gmtime(&state->time);
586
tv = state->handle->ctime.tv_sec;
543
588
strftime(time_stamp, sizeof(time_stamp), "%Y%m%d%H%M%S", tp);
544
589
cleanup_out_format(state, REC_TYPE_NORM, "%sMessage-Id: <%s.%s@%s>",
545
590
state->resent, time_stamp, state->queue_id, var_myhostname);
630
675
const char *value;
632
677
if ((value = maps_find(cleanup_body_checks, buf, 0)) != 0) {
633
if (cleanup_act(state, CLEANUP_ACT_CTXT_BODY,
634
buf, value, VAR_BODY_CHECKS)
680
if ((result = cleanup_act(state, CLEANUP_ACT_CTXT_BODY,
681
buf, value, VAR_BODY_CHECKS))
682
== CLEANUP_ACT_DROP) {
684
} else if (result != buf) {
685
cleanup_out(state, type, result, strlen(result));
686
myfree((char *) result);
639
691
cleanup_out(state, type, buf, len);