bounce_workaround.c revision 1.1
1/* $NetBSD: bounce_workaround.c,v 1.1 2010/06/17 18:06:53 tron Exp $ */ 2 3/*++ 4/* NAME 5/* bounce_workaround 3 6/* SUMMARY 7/* Send non-delivery notification with sender override 8/* SYNOPSIS 9/* #include "local.h" 10/* 11/* int bounce_workaround(state) 12/* LOCAL_STATE state; 13/* DESCRIPTION 14/* This module works around a limitation in the bounce daemon 15/* protocol, namely, the assumption that the envelope sender 16/* address in a queue file is the delivery status notification 17/* address for all recipients in that queue file. The assumption 18/* is not valid when the local(8) delivery agent overrides the 19/* envelope sender address by an owner- alias, for one or more 20/* recipients in the queue file. 21/* 22/* Sender address override is a problem only when delivering 23/* to command or file, or when breaking a Delivered-To loop. 24/* The local(8) delivery agent saves normal recipients to a 25/* new queue file, together with the replacement envelope 26/* sender address; delivery then proceeds from that new queue 27/* file, and no workaround is needed. 28/* 29/* The workaround sends one non-delivery notification for each 30/* failed delivery that has a replacement sender address. The 31/* notifications are not aggregated, unlike notifications to 32/* non-replaced sender addresses. In practice, a local alias 33/* rarely has more than one file or command destination (if 34/* only because soft error handling is problematic). 35/* 36/* Arguments: 37/* .IP state 38/* The attributes that specify the message, recipient and more. 39/* Attributes describing alias, include or forward expansion. 40/* A table with the results from expanding aliases or lists. 41/* A table with delivered-to: addresses taken from the message. 42/* DIAGNOSTICS 43/* Fatal errors: out of memory. The result is non-zero when 44/* the operation should be tried again. Warnings: malformed 45/* address. 46/* BUGS 47/* The proper fix is to record in the bounce logfile an error 48/* return address for each individual recipient. This would 49/* eliminate the need for VERP-specific bounce protocol code, 50/* and would move complexity from the bounce client side to 51/* the bounce server side where it more likely belongs. 52/* LICENSE 53/* .ad 54/* .fi 55/* The Secure Mailer license must be distributed with this 56/* software. 57/* AUTHOR(S) 58/* Wietse Venema 59/* IBM T.J. Watson Research 60/* P.O. Box 704 61/* Yorktown Heights, NY 10598, USA 62/*--*/ 63 64/* System library. */ 65 66#include <sys_defs.h> 67#include <strings.h> 68 69/* Utility library. */ 70 71#include <msg.h> 72#include <mymalloc.h> 73#include <vstring.h> 74#include <split_at.h> 75 76/* Global library. */ 77 78#include <mail_params.h> 79#include <strip_addr.h> 80#include <stringops.h> 81#include <bounce.h> 82#include <split_addr.h> 83#include <canon_addr.h> 84 85/* Application-specific. */ 86 87#include "local.h" 88 89int bounce_workaround(LOCAL_STATE state) 90{ 91 const char *myname = "bounce_workaround"; 92 VSTRING *canon_owner = 0; 93 int rcpt_stat; 94 95 /* 96 * Look up the substitute sender address. 97 */ 98 if (var_ownreq_special) { 99 char *stripped_recipient; 100 char *owner_alias; 101 const char *owner_expansion; 102 103#define FIND_OWNER(lhs, rhs, addr) { \ 104 lhs = concatenate("owner-", addr, (char *) 0); \ 105 (void) split_at_right(lhs, '@'); \ 106 rhs = maps_find(alias_maps, lhs, DICT_FLAG_NONE); \ 107 } 108 109 FIND_OWNER(owner_alias, owner_expansion, state.msg_attr.rcpt.address); 110 if (owner_expansion == 0 111 && (stripped_recipient = strip_addr(state.msg_attr.rcpt.address, 112 (char **) 0, 113 *var_rcpt_delim)) != 0) { 114 myfree(owner_alias); 115 FIND_OWNER(owner_alias, owner_expansion, stripped_recipient); 116 myfree(stripped_recipient); 117 } 118 if (owner_expansion != 0) { 119 canon_owner = canon_addr_internal(vstring_alloc(10), 120 var_exp_own_alias ? 121 owner_expansion : owner_alias); 122 SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level); 123 } 124 myfree(owner_alias); 125 } 126 127 /* 128 * Send a delivery status notification with a single recipient to the 129 * substitute sender address, before completion of the delivery request. 130 */ 131 if (canon_owner) { 132 rcpt_stat = bounce_one(BOUNCE_FLAGS(state.request), 133 BOUNCE_ONE_ATTR(state.msg_attr)); 134 vstring_free(canon_owner); 135 } 136 137 /* 138 * Send a regular delivery status notification, after completion of the 139 * delivery request. 140 */ 141 else { 142 rcpt_stat = bounce_append(BOUNCE_FLAGS(state.request), 143 BOUNCE_ATTR(state.msg_attr)); 144 } 145 return (rcpt_stat); 146} 147