1/*++ 2/* NAME 3/* cleanup_addr 3 4/* SUMMARY 5/* process envelope addresses 6/* SYNOPSIS 7/* #include <cleanup.h> 8/* 9/* void cleanup_addr_sender(state, addr) 10/* CLEANUP_STATE *state; 11/* const char *addr; 12/* 13/* void cleanup_addr_recipient(state, addr) 14/* CLEANUP_STATE *state; 15/* const char *addr; 16/* 17/* void cleanup_addr_bcc_dsn(state, addr, dsn_orcpt, dsn_notify) 18/* CLEANUP_STATE *state; 19/* const char *addr; 20/* const char *dsn_orcpt; 21/* int dsn_notify; 22/* 23/* void cleanup_addr_bcc(state, addr) 24/* CLEANUP_STATE *state; 25/* const char *addr; 26/* DESCRIPTION 27/* This module processes envelope address records and writes the result 28/* to the queue file. Processing includes address rewriting and 29/* sender/recipient auto bcc address generation. 30/* 31/* cleanup_addr_sender() processes sender envelope information and updates 32/* state->sender. 33/* 34/* cleanup_addr_recipient() processes recipient envelope information 35/* and updates state->recip. 36/* 37/* cleanup_addr_bcc_dsn() processes recipient envelope information. This 38/* is a separate function to avoid invoking cleanup_addr_recipient() 39/* recursively. 40/* 41/* cleanup_addr_bcc() is a backwards-compatibility wrapper for 42/* cleanup_addr_bcc_dsn() that requests no delivery status 43/* notification for the recipient. 44/* 45/* Arguments: 46/* .IP state 47/* Queue file and message processing state. This state is updated 48/* as records are processed and as errors happen. 49/* .IP buf 50/* Record content. 51/* .IP dsn_orcpt 52/* The DSN original recipient (or NO_DSN_ORCPT to specify none). 53/* .IP dsn_notify 54/* DSN notification options. Specify NO_DSN_NOTIFY to disable 55/* notification, and DEF_DSN_NOTIFY for default notification. 56/* LICENSE 57/* .ad 58/* .fi 59/* The Secure Mailer license must be distributed with this software. 60/* AUTHOR(S) 61/* Wietse Venema 62/* IBM T.J. Watson Research 63/* P.O. Box 704 64/* Yorktown Heights, NY 10598, USA 65/*--*/ 66 67/* System library. */ 68 69#include <sys_defs.h> 70#include <string.h> 71#include <stdlib.h> 72 73#ifdef STRCASECMP_IN_STRINGS_H 74#include <strings.h> 75#endif 76 77/* Utility library. */ 78 79#include <msg.h> 80#include <vstring.h> 81#include <vstream.h> 82#include <mymalloc.h> 83#include <stringops.h> 84 85/* Global library. */ 86 87#include <rec_type.h> 88#include <cleanup_user.h> 89#include <mail_params.h> 90#include <ext_prop.h> 91#include <mail_addr.h> 92#include <canon_addr.h> 93#include <mail_addr_find.h> 94#include <mail_proto.h> 95#include <dsn_mask.h> 96 97/* Application-specific. */ 98 99#include "cleanup.h" 100 101#define STR vstring_str 102#define IGNORE_EXTENSION (char **) 0 103 104/* cleanup_addr_sender - process envelope sender record */ 105 106void cleanup_addr_sender(CLEANUP_STATE *state, const char *buf) 107{ 108 VSTRING *clean_addr = vstring_alloc(100); 109 const char *bcc; 110 111 /* 112 * Note: an unqualified envelope address is for all practical purposes 113 * equivalent to a fully qualified local address, both for delivery and 114 * for replying. Having to support both forms is error prone, therefore 115 * an incomplete envelope address is rewritten to fully qualified form in 116 * the local domain context. 117 * 118 * 20000520: Replace mailer-daemon@$myorigin by the null address, to handle 119 * bounced mail traffic more robustly. 120 */ 121 cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, buf); 122 if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@", 123 sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) { 124 canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON); 125 if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0) 126 vstring_strcpy(clean_addr, ""); 127 } 128 if (state->flags & CLEANUP_FLAG_MAP_OK) { 129 if (cleanup_send_canon_maps 130 && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM)) 131 cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps, 132 cleanup_ext_prop_mask & EXT_PROP_CANONICAL); 133 if (cleanup_comm_canon_maps 134 && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM)) 135 cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, 136 cleanup_ext_prop_mask & EXT_PROP_CANONICAL); 137 if (cleanup_masq_domains 138 && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM)) 139 cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); 140 } 141 CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr); 142 if (state->sender) /* XXX Can't happen */ 143 myfree(state->sender); 144 state->sender = mystrdup(STR(clean_addr)); /* Used by Milter client */ 145 if ((state->flags & CLEANUP_FLAG_BCC_OK) 146 && *STR(clean_addr) 147 && cleanup_send_bcc_maps) { 148 if ((bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr), 149 IGNORE_EXTENSION)) != 0) { 150 cleanup_addr_bcc(state, bcc); 151 } else if (cleanup_send_bcc_maps->error) { 152 msg_warn("%s: %s lookup problem", 153 state->queue_id, cleanup_send_bcc_maps->title); 154 state->errs |= CLEANUP_STAT_WRITE; 155 } 156 } 157 vstring_free(clean_addr); 158} 159 160/* cleanup_addr_recipient - process envelope recipient */ 161 162void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf) 163{ 164 VSTRING *clean_addr = vstring_alloc(100); 165 const char *bcc; 166 167 /* 168 * Note: an unqualified envelope address is for all practical purposes 169 * equivalent to a fully qualified local address, both for delivery and 170 * for replying. Having to support both forms is error prone, therefore 171 * an incomplete envelope address is rewritten to fully qualified form in 172 * the local domain context. 173 */ 174 cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, 175 clean_addr, *buf ? buf : var_empty_addr); 176 if (state->flags & CLEANUP_FLAG_MAP_OK) { 177 if (cleanup_rcpt_canon_maps 178 && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) 179 cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, 180 cleanup_ext_prop_mask & EXT_PROP_CANONICAL); 181 if (cleanup_comm_canon_maps 182 && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) 183 cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, 184 cleanup_ext_prop_mask & EXT_PROP_CANONICAL); 185 if (cleanup_masq_domains 186 && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) 187 cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); 188 } 189 cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify, 190 state->orig_rcpt, STR(clean_addr)); 191 if (state->recip) /* This can happen */ 192 myfree(state->recip); 193 state->recip = mystrdup(STR(clean_addr)); /* Used by Milter client */ 194 if ((state->flags & CLEANUP_FLAG_BCC_OK) 195 && *STR(clean_addr) 196 && cleanup_rcpt_bcc_maps) { 197 if ((bcc = mail_addr_find(cleanup_rcpt_bcc_maps, STR(clean_addr), 198 IGNORE_EXTENSION)) != 0) { 199 cleanup_addr_bcc(state, bcc); 200 } else if (cleanup_rcpt_bcc_maps->error) { 201 msg_warn("%s: %s lookup problem", 202 state->queue_id, cleanup_rcpt_bcc_maps->title); 203 state->errs |= CLEANUP_STAT_WRITE; 204 } 205 } 206 vstring_free(clean_addr); 207} 208 209/* cleanup_addr_bcc_dsn - process automatic BCC recipient */ 210 211void cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc, 212 const char *dsn_orcpt, int dsn_notify) 213{ 214 VSTRING *clean_addr = vstring_alloc(100); 215 216 /* 217 * Note: BCC addresses are supplied locally, and must be rewritten in the 218 * local address rewriting context. 219 */ 220 cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, bcc); 221 if (state->flags & CLEANUP_FLAG_MAP_OK) { 222 if (cleanup_rcpt_canon_maps 223 && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) 224 cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, 225 cleanup_ext_prop_mask & EXT_PROP_CANONICAL); 226 if (cleanup_comm_canon_maps 227 && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) 228 cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, 229 cleanup_ext_prop_mask & EXT_PROP_CANONICAL); 230 if (cleanup_masq_domains 231 && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) 232 cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); 233 } 234 cleanup_out_recipient(state, dsn_orcpt, dsn_notify, 235 STR(clean_addr), STR(clean_addr)); 236 vstring_free(clean_addr); 237} 238