summaryrefslogtreecommitdiffstats
path: root/src/cleanup/cleanup_addr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cleanup/cleanup_addr.c')
-rw-r--r--src/cleanup/cleanup_addr.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/src/cleanup/cleanup_addr.c b/src/cleanup/cleanup_addr.c
new file mode 100644
index 0000000..fd8a511
--- /dev/null
+++ b/src/cleanup/cleanup_addr.c
@@ -0,0 +1,286 @@
+/*++
+/* NAME
+/* cleanup_addr 3
+/* SUMMARY
+/* process envelope addresses
+/* SYNOPSIS
+/* #include <cleanup.h>
+/*
+/* off_t cleanup_addr_sender(state, addr)
+/* CLEANUP_STATE *state;
+/* const char *addr;
+/*
+/* void cleanup_addr_recipient(state, addr)
+/* CLEANUP_STATE *state;
+/* const char *addr;
+/*
+/* void cleanup_addr_bcc_dsn(state, addr, dsn_orcpt, dsn_notify)
+/* CLEANUP_STATE *state;
+/* const char *addr;
+/* const char *dsn_orcpt;
+/* int dsn_notify;
+/*
+/* void cleanup_addr_bcc(state, addr)
+/* CLEANUP_STATE *state;
+/* const char *addr;
+/* DESCRIPTION
+/* This module processes envelope address records and writes the result
+/* to the queue file. Processing includes address rewriting and
+/* sender/recipient auto bcc address generation.
+/*
+/* cleanup_addr_sender() processes sender envelope information and updates
+/* state->sender. The result value is the offset of the record that
+/* follows the sender record if milters are enabled, otherwise zero.
+/*
+/* cleanup_addr_recipient() processes recipient envelope information
+/* and updates state->recip.
+/*
+/* cleanup_addr_bcc_dsn() processes recipient envelope information. This
+/* is a separate function to avoid invoking cleanup_addr_recipient()
+/* recursively.
+/*
+/* cleanup_addr_bcc() is a backwards-compatibility wrapper for
+/* cleanup_addr_bcc_dsn() that requests no delivery status
+/* notification for the recipient.
+/*
+/* Arguments:
+/* .IP state
+/* Queue file and message processing state. This state is updated
+/* as records are processed and as errors happen.
+/* .IP buf
+/* Record content.
+/* .IP dsn_orcpt
+/* The DSN original recipient (or NO_DSN_ORCPT to specify none).
+/* .IP dsn_notify
+/* DSN notification options. Specify NO_DSN_NOTIFY to disable
+/* notification, and DEF_DSN_NOTIFY for default notification.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <mymalloc.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include <rec_type.h>
+#include <record.h>
+#include <cleanup_user.h>
+#include <mail_params.h>
+#include <ext_prop.h>
+#include <mail_addr.h>
+#include <canon_addr.h>
+#include <mail_addr_find.h>
+#include <mail_proto.h>
+#include <dsn_mask.h>
+#include <smtputf8.h>
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+#define STR vstring_str
+#define LEN VSTRING_LEN
+#define IGNORE_EXTENSION (char **) 0
+
+/* cleanup_addr_sender - process envelope sender record */
+
+off_t cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
+{
+ const char myname[] = "cleanup_addr_sender";
+ VSTRING *clean_addr = vstring_alloc(100);
+ off_t after_sender_offs = 0;
+ const char *bcc;
+ size_t len;
+
+ /*
+ * Note: an unqualified envelope address is for all practical purposes
+ * equivalent to a fully qualified local address, both for delivery and
+ * for replying. Having to support both forms is error prone, therefore
+ * an incomplete envelope address is rewritten to fully qualified form in
+ * the local domain context.
+ *
+ * 20000520: Replace mailer-daemon@$myorigin by the null address, to handle
+ * bounced mail traffic more robustly.
+ */
+ cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, buf);
+ if (strncasecmp_utf8(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@",
+ sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) {
+ canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON);
+ if (strcasecmp_utf8(STR(clean_addr), STR(state->temp1)) == 0)
+ vstring_strcpy(clean_addr, "");
+ }
+ if (state->flags & CLEANUP_FLAG_MAP_OK) {
+ if (cleanup_send_canon_maps
+ && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM))
+ cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_comm_canon_maps
+ && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM))
+ cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_masq_domains
+ && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM))
+ cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
+ }
+ /* Fix 20140711: Auto-detect an UTF8 sender. */
+ if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
+ && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
+ state->smtputf8 |= SMTPUTF8_FLAG_SENDER;
+ /* Fix 20140713: request SMTPUTF8 support selectively. */
+ if (state->flags & CLEANUP_FLAG_AUTOUTF8)
+ state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
+ }
+ CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr);
+ if (state->sender) /* XXX Can't happen */
+ myfree(state->sender);
+ state->sender = mystrdup(STR(clean_addr)); /* Used by Milter client */
+ /* Fix 20160310: Moved from cleanup_envelope.c. */
+ if (state->milters || cleanup_milters) {
+ /* Make room to replace sender. */
+ if ((len = LEN(clean_addr)) < REC_TYPE_PTR_PAYL_SIZE)
+ rec_pad(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_PAYL_SIZE - len);
+ /* Remember the after-sender record offset. */
+ if ((after_sender_offs = vstream_ftell(state->dst)) < 0)
+ msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path);
+ }
+ if ((state->flags & CLEANUP_FLAG_BCC_OK)
+ && *STR(clean_addr)
+ && cleanup_send_bcc_maps) {
+ if ((bcc = mail_addr_find_to_internal(cleanup_send_bcc_maps,
+ STR(clean_addr),
+ IGNORE_EXTENSION)) != 0) {
+ cleanup_addr_bcc(state, bcc);
+ } else if (cleanup_send_bcc_maps->error) {
+ msg_warn("%s: %s map lookup problem -- "
+ "message not accepted, try again later",
+ state->queue_id, cleanup_send_bcc_maps->title);
+ state->errs |= CLEANUP_STAT_WRITE;
+ }
+ }
+ vstring_free(clean_addr);
+ return after_sender_offs;
+}
+
+/* cleanup_addr_recipient - process envelope recipient */
+
+void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
+{
+ VSTRING *clean_addr = vstring_alloc(100);
+ const char *bcc;
+
+ /*
+ * Note: an unqualified envelope address is for all practical purposes
+ * equivalent to a fully qualified local address, both for delivery and
+ * for replying. Having to support both forms is error prone, therefore
+ * an incomplete envelope address is rewritten to fully qualified form in
+ * the local domain context.
+ */
+ cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL,
+ clean_addr, *buf ? buf : var_empty_addr);
+ if (state->flags & CLEANUP_FLAG_MAP_OK) {
+ if (cleanup_rcpt_canon_maps
+ && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
+ cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_comm_canon_maps
+ && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
+ cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_masq_domains
+ && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
+ cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
+ }
+ /* Fix 20140711: Auto-detect an UTF8 recipient. */
+ if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
+ && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
+ /* Fix 20140713: request SMTPUTF8 support selectively. */
+ if (state->flags & CLEANUP_FLAG_AUTOUTF8)
+ state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
+ }
+ /* Fix 20141024: Don't fake up a "bare" DSN original rcpt in smtp(8). */
+ if (state->dsn_orcpt == 0 && *STR(clean_addr) != 0)
+ state->dsn_orcpt = concatenate((!allascii(STR(clean_addr))
+ && (state->smtputf8 & SMTPUTF8_FLAG_REQUESTED)) ?
+ "utf-8" : "rfc822", ";", STR(clean_addr), (char *) 0);
+ cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify,
+ state->orig_rcpt, STR(clean_addr));
+ if (state->recip) /* This can happen */
+ myfree(state->recip);
+ state->recip = mystrdup(STR(clean_addr)); /* Used by Milter client */
+ if ((state->flags & CLEANUP_FLAG_BCC_OK)
+ && *STR(clean_addr)
+ && cleanup_rcpt_bcc_maps) {
+ if ((bcc = mail_addr_find_to_internal(cleanup_rcpt_bcc_maps,
+ STR(clean_addr),
+ IGNORE_EXTENSION)) != 0) {
+ cleanup_addr_bcc(state, bcc);
+ } else if (cleanup_rcpt_bcc_maps->error) {
+ msg_warn("%s: %s map lookup problem -- "
+ "message not accepted, try again later",
+ state->queue_id, cleanup_rcpt_bcc_maps->title);
+ state->errs |= CLEANUP_STAT_WRITE;
+ }
+ }
+ vstring_free(clean_addr);
+}
+
+/* cleanup_addr_bcc_dsn - process automatic BCC recipient */
+
+void cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc,
+ const char *dsn_orcpt, int dsn_notify)
+{
+ VSTRING *clean_addr = vstring_alloc(100);
+
+ /*
+ * Note: BCC addresses are supplied locally, and must be rewritten in the
+ * local address rewriting context.
+ */
+ cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, bcc);
+ if (state->flags & CLEANUP_FLAG_MAP_OK) {
+ if (cleanup_rcpt_canon_maps
+ && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
+ cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_comm_canon_maps
+ && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
+ cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_masq_domains
+ && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
+ cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains);
+ }
+ /* Fix 20140711: Auto-detect an UTF8 recipient. */
+ if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr))
+ && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) {
+ /* Fix 20140713: request SMTPUTF8 support selectively. */
+ if (state->flags & CLEANUP_FLAG_AUTOUTF8)
+ state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED;
+ }
+ cleanup_out_recipient(state, dsn_orcpt, dsn_notify,
+ STR(clean_addr), STR(clean_addr));
+ vstring_free(clean_addr);
+}