No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / smtpd / smtpd_dsn_fix.c
blob526d760bc75263b149dac4a7d56b7788df135194
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* smtpd_dsn_fix 3
6 /* SUMMARY
7 /* fix DSN status
8 /* SYNOPSIS
9 /* #include <smtpd_dsn_fix.h>
11 /* const char *smtpd_dsn_fix(status, reply_class)
12 /* const char *status;
13 /* const char *reply_class;
14 /* DESCRIPTION
15 /* smtpd_dsn_fix() transforms DSN status codes according to the
16 /* status information that is actually being reported. The
17 /* following transformations are implemented:
18 /* .IP \(bu
19 /* Transform a recipient address DSN into a sender address DSN
20 /* when reporting sender address status information, and vice
21 /* versa. This transformation may be needed because some Postfix
22 /* access control features don't know whether the address being
23 /* rejected is a sender or recipient. Examples are smtpd access
24 /* tables, rbl reply templates, and the error mailer.
25 /* .IP \(bu
26 /* Transform a sender or recipient address DSN into a non-address
27 /* DSN when reporting non-address status information. For
28 /* example, if something rejects HELO with DSN status 4.1.1
29 /* (unknown recipient address), then we send the more neutral
30 /* 4.0.0 DSN instead. This transformation is needed when the
31 /* same smtpd access map entry or rbl reply template is used
32 /* for both address and non-address information.
33 /* .PP
34 /* A non-address DSN is not transformed
35 /* when reporting sender or recipient address status information,
36 /* as there are many legitimate instances of such usage.
38 /* It is left up to the caller to update the initial DSN digit
39 /* appropriately; in Postfix this is done as late as possible,
40 /* because hard rejects may be changed into soft rejects for
41 /* all kinds of reasons.
43 /* Arguments:
44 /* .IP status
45 /* A DSN status as per RFC 3463.
46 /* .IP reply_class
47 /* SMTPD_NAME_SENDER, SMTPD_NAME_RECIPIENT or some other
48 /* null-terminated string.
49 /* LICENSE
50 /* .ad
51 /* .fi
52 /* The Secure Mailer license must be distributed with this software.
53 /* AUTHOR(S)
54 /* Wietse Venema
55 /* IBM T.J. Watson Research
56 /* P.O. Box 704
57 /* Yorktown Heights, NY 10598, USA
58 /*--*/
59 /* System library. */
61 #include <sys_defs.h>
62 #include <ctype.h>
63 #include <string.h>
65 /* Utility library. */
67 #include <msg.h>
69 /* Global library. */
71 /* Application-specific. */
73 #include <smtpd_dsn_fix.h>
75 struct dsn_map {
76 const char *micro_code; /* Final digits in mailbox D.S.N. */
77 const char *sender_dsn; /* Replacement sender D.S.N. */
78 const char *rcpt_dsn; /* Replacement recipient D.S.N. */
81 static struct dsn_map dsn_map[] = {
82 /* - Sender - Recipient */
83 "1", SND_DSN, "4.1.1", /* 4.1.1: Bad dest mbox addr */
84 "2", "4.1.8", "4.1.2", /* 4.1.2: Bad dest system addr */
85 "3", "4.1.7", "4.1.3", /* 4.1.3: Bad dest mbox addr syntax */
86 "4", SND_DSN, "4.1.4", /* 4.1.4: Dest mbox addr ambiguous */
87 "5", "4.1.0", "4.1.5", /* 4.1.5: Dest mbox addr valid */
88 "6", SND_DSN, "4.1.6", /* 4.1.6: Mailbox has moved */
89 "7", "4.1.7", "4.1.3", /* 4.1.7: Bad sender mbox addr syntax */
90 "8", "4.1.8", "4.1.2", /* 4.1.8: Bad sender system addr */
91 0, "4.1.0", "4.1.0", /* Default mapping */
94 /* smtpd_dsn_fix - fix DSN status */
96 const char *smtpd_dsn_fix(const char *status, const char *reply_class)
98 struct dsn_map *dp;
99 const char *result = status;
102 * Update an address-specific DSN according to what is being rejected.
104 if (ISDIGIT(status[0]) && strncmp(status + 1, ".1.", 3) == 0) {
107 * Fix recipient address DSN while rejecting a sender address. Don't
108 * let future recipient-specific DSN codes slip past us.
110 if (strcmp(reply_class, SMTPD_NAME_SENDER) == 0) {
111 for (dp = dsn_map; dp->micro_code != 0; dp++)
112 if (strcmp(status + 4, dp->micro_code) == 0)
113 break;
114 result = dp->sender_dsn;
118 * Fix sender address DSN while rejecting a recipient address. Don't
119 * let future sender-specific DSN codes slip past us.
121 else if (strcmp(reply_class, SMTPD_NAME_RECIPIENT) == 0) {
122 for (dp = dsn_map; dp->micro_code != 0; dp++)
123 if (strcmp(status + 4, dp->micro_code) == 0)
124 break;
125 result = dp->rcpt_dsn;
129 * Fix address-specific DSN while rejecting a non-address.
131 else {
132 result = "4.0.0";
136 * Give them a clue of what is going on.
138 if (strcmp(status + 2, result + 2) != 0)
139 msg_info("mapping DSN status %s into %s status %c%s",
140 status, reply_class, status[0], result + 1);
141 return (result);
145 * Don't update a non-address DSN. There are many legitimate uses for
146 * these while rejecting address or non-address information.
148 else {
149 return (status);