1/*++ 2/* NAME 3/* unknown 3 4/* SUMMARY 5/* delivery of unknown recipients 6/* SYNOPSIS 7/* #include "local.h" 8/* 9/* int deliver_unknown(state, usr_attr) 10/* LOCAL_STATE state; 11/* USER_ATTR usr_attr; 12/* DESCRIPTION 13/* deliver_unknown() delivers a message for unknown recipients. 14/* .IP \(bu 15/* If an alternative message transport is specified via the 16/* fallback_transport parameter, delivery is delegated to the 17/* named transport. 18/* .IP \(bu 19/* If an alternative address is specified via the luser_relay 20/* configuration parameter, mail is forwarded to that address. 21/* .IP \(bu 22/* Otherwise the recipient is bounced. 23/* .PP 24/* The luser_relay parameter is subjected to $name expansion of 25/* the standard message attributes: $user, $home, $shell, $domain, 26/* $recipient, $mailbox, $extension, $recipient_delimiter, not 27/* all of which actually make sense. 28/* 29/* Arguments: 30/* .IP state 31/* Message delivery attributes (sender, recipient etc.). 32/* Attributes describing alias, include or forward expansion. 33/* A table with the results from expanding aliases or lists. 34/* A table with delivered-to: addresses taken from the message. 35/* .IP usr_attr 36/* Attributes describing user rights and environment. 37/* DIAGNOSTICS 38/* The result status is non-zero when delivery should be tried again. 39/* LICENSE 40/* .ad 41/* .fi 42/* The Secure Mailer license must be distributed with this software. 43/* AUTHOR(S) 44/* Wietse Venema 45/* IBM T.J. Watson Research 46/* P.O. Box 704 47/* Yorktown Heights, NY 10598, USA 48/*--*/ 49 50/* System library. */ 51 52#include <sys_defs.h> 53#include <string.h> 54 55#ifdef STRCASECMP_IN_STRINGS_H 56#include <strings.h> 57#endif 58 59/* Utility library. */ 60 61#include <msg.h> 62#include <stringops.h> 63#include <mymalloc.h> 64#include <vstring.h> 65 66/* Global library. */ 67 68#include <been_here.h> 69#include <mail_params.h> 70#include <mail_proto.h> 71#include <bounce.h> 72#include <mail_addr.h> 73#include <sent.h> 74#include <deliver_pass.h> 75#include <defer.h> 76 77/* Application-specific. */ 78 79#include "local.h" 80 81/* deliver_unknown - delivery for unknown recipients */ 82 83int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) 84{ 85 const char *myname = "deliver_unknown"; 86 int status; 87 VSTRING *expand_luser; 88 static MAPS *transp_maps; 89 const char *map_transport; 90 91 /* 92 * Make verbose logging easier to understand. 93 */ 94 state.level++; 95 if (msg_verbose) 96 MSG_LOG_STATE(myname, state); 97 98 /* 99 * DUPLICATE/LOOP ELIMINATION 100 * 101 * Don't deliver the same user twice. 102 */ 103 if (been_here(state.dup_filter, "%s %s", myname, state.msg_attr.local)) 104 return (0); 105 106 /* 107 * The fall-back transport specifies a delivery machanism that handles 108 * users not found in the aliases or UNIX passwd databases. 109 */ 110 if (*var_fbck_transp_maps && transp_maps == 0) 111 transp_maps = maps_create(VAR_FBCK_TRANSP_MAPS, var_fbck_transp_maps, 112 DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB); 113 /* The -1 is a hint for the down-stream deliver_completed() function. */ 114 if (transp_maps 115 && (map_transport = maps_find(transp_maps, state.msg_attr.user, 116 DICT_FLAG_NONE)) != 0) { 117 state.msg_attr.rcpt.offset = -1L; 118 return (deliver_pass(MAIL_CLASS_PRIVATE, map_transport, 119 state.request, &state.msg_attr.rcpt)); 120 } else if (transp_maps && transp_maps->error != 0) { 121 /* Details in the logfile. */ 122 dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure"); 123 return (defer_append(BOUNCE_FLAGS(state.request), 124 BOUNCE_ATTR(state.msg_attr))); 125 } 126 if (*var_fallback_transport) { 127 state.msg_attr.rcpt.offset = -1L; 128 return (deliver_pass(MAIL_CLASS_PRIVATE, var_fallback_transport, 129 state.request, &state.msg_attr.rcpt)); 130 } 131 132 /* 133 * Subject the luser_relay address to $name expansion, disable 134 * propagation of unmatched address extension, and re-inject the address 135 * into the delivery machinery. Do not give special treatment to "|stuff" 136 * or /stuff. 137 */ 138 if (*var_luser_relay) { 139 state.msg_attr.unmatched = 0; 140 expand_luser = vstring_alloc(100); 141 local_expand(expand_luser, var_luser_relay, &state, &usr_attr, (char *) 0); 142 status = deliver_resolve_addr(state, usr_attr, STR(expand_luser)); 143 vstring_free(expand_luser); 144 return (status); 145 } 146 147 /* 148 * If no alias was found for a required reserved name, toss the message 149 * into the bit bucket, and issue a warning instead. 150 */ 151#define STREQ(x,y) (strcasecmp(x,y) == 0) 152 153 if (STREQ(state.msg_attr.user, MAIL_ADDR_MAIL_DAEMON) 154 || STREQ(state.msg_attr.user, MAIL_ADDR_POSTMASTER)) { 155 msg_warn("required alias not found: %s", state.msg_attr.user); 156 dsb_simple(state.msg_attr.why, "2.0.0", "discarded"); 157 return (sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr))); 158 } 159 160 /* 161 * Bounce the message when no luser relay is specified. 162 */ 163 dsb_simple(state.msg_attr.why, "5.1.1", 164 "unknown user: \"%s\"", state.msg_attr.user); 165 return (bounce_append(BOUNCE_FLAGS(state.request), 166 BOUNCE_ATTR(state.msg_attr))); 167} 168