]>
Commit | Line | Data |
---|---|---|
28be0b96 SS |
1 | /* |
2 | * Copyright (c) 2008 The DragonFly Project. All rights reserved. | |
3 | * | |
4 | * This code is derived from software contributed to The DragonFly Project | |
5 | * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * 3. Neither the name of The DragonFly Project nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific, prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
25 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | |
33 | */ | |
34 | ||
35 | #include <errno.h> | |
36 | #include <syslog.h> | |
37 | #include <unistd.h> | |
38 | ||
39 | #include "dma.h" | |
40 | ||
41 | void | |
42 | bounce(struct qitem *it, const char *reason) | |
43 | { | |
44 | struct queue bounceq; | |
45 | char line[1000]; | |
46 | size_t pos; | |
47 | int error; | |
48 | ||
49 | /* Don't bounce bounced mails */ | |
50 | if (it->sender[0] == 0) { | |
51 | syslog(LOG_INFO, "can not bounce a bounce message, discarding"); | |
52 | exit(1); | |
53 | } | |
54 | ||
6f5efe4f | 55 | bzero(&bounceq, sizeof(bounceq)); |
28be0b96 SS |
56 | LIST_INIT(&bounceq.queue); |
57 | if (add_recp(&bounceq, it->sender, "", 1) != 0) | |
58 | goto fail; | |
59 | ||
60 | if (newspoolf(&bounceq, "") != 0) | |
61 | goto fail; | |
62 | ||
63 | syslog(LOG_ERR, "delivery failed, bouncing as %s", bounceq.id); | |
64 | setlogident("%s", bounceq.id); | |
65 | ||
66 | error = fprintf(bounceq.mailf, | |
67 | "Received: from MAILER-DAEMON\n" | |
68 | "\tid %s\n" | |
69 | "\tby %s (%s)\n" | |
70 | "\t%s\n" | |
71 | "X-Original-To: <%s>\n" | |
72 | "From: MAILER-DAEMON <>\n" | |
73 | "To: %s\n" | |
74 | "Subject: Mail delivery failed\n" | |
75 | "Message-Id: <%s@%s>\n" | |
76 | "Date: %s\n" | |
77 | "\n" | |
78 | "This is the %s at %s.\n" | |
79 | "\n" | |
80 | "There was an error delivering your mail to <%s>.\n" | |
81 | "\n" | |
82 | "%s\n" | |
83 | "\n" | |
84 | "%s\n" | |
85 | "\n", | |
86 | bounceq.id, | |
87 | hostname(), VERSION, | |
88 | rfc822date(), | |
89 | it->addr, | |
90 | it->sender, | |
91 | bounceq.id, hostname(), | |
92 | rfc822date(), | |
93 | VERSION, hostname(), | |
94 | it->addr, | |
95 | reason, | |
96 | config->features & FULLBOUNCE ? | |
97 | "Original message follows." : | |
98 | "Message headers follow."); | |
99 | if (error < 0) | |
100 | goto fail; | |
101 | ||
102 | if (fseek(it->mailf, it->hdrlen, SEEK_SET) != 0) | |
103 | goto fail; | |
104 | if (config->features & FULLBOUNCE) { | |
105 | while ((pos = fread(line, 1, sizeof(line), it->mailf)) > 0) { | |
106 | if (fwrite(line, 1, pos, bounceq.mailf) != pos) | |
107 | goto fail; | |
108 | } | |
109 | } else { | |
110 | while (!feof(it->mailf)) { | |
111 | if (fgets(line, sizeof(line), it->mailf) == NULL) | |
112 | break; | |
113 | if (line[0] == '\n') | |
114 | break; | |
115 | if (fwrite(line, strlen(line), 1, bounceq.mailf) != 1) | |
116 | goto fail; | |
117 | } | |
118 | } | |
119 | ||
120 | if (linkspool(&bounceq, "") != 0) | |
121 | goto fail; | |
122 | /* bounce is safe */ | |
123 | ||
124 | delqueue(it); | |
125 | ||
126 | run_queue(&bounceq); | |
127 | /* NOTREACHED */ | |
128 | ||
129 | fail: | |
130 | syslog(LOG_CRIT, "error creating bounce: %m"); | |
131 | delqueue(it); | |
132 | exit(1); | |
133 | } | |
134 | ||
135 | int | |
136 | readmail(struct queue *queue, const char *sender, int nodot) | |
137 | { | |
138 | char line[1000]; /* by RFC2822 */ | |
139 | size_t linelen; | |
140 | size_t error; | |
141 | int had_headers = 0; | |
142 | int had_from = 0; | |
143 | int had_messagid = 0; | |
144 | int had_date = 0; | |
145 | ||
146 | error = fprintf(queue->mailf, | |
147 | "Received: from %s (uid %d)\n" | |
148 | "\t(envelope-from %s)\n" | |
149 | "\tid %s\n" | |
150 | "\tby %s (%s)\n" | |
151 | "\t%s\n", | |
152 | username, getuid(), | |
153 | sender, | |
154 | queue->id, | |
155 | hostname(), VERSION, | |
156 | rfc822date()); | |
157 | if ((ssize_t)error < 0) | |
158 | return (-1); | |
159 | ||
160 | while (!feof(stdin)) { | |
161 | if (fgets(line, sizeof(line), stdin) == NULL) | |
162 | break; | |
163 | linelen = strlen(line); | |
164 | if (linelen == 0 || line[linelen - 1] != '\n') { | |
165 | errno = EINVAL; /* XXX mark permanent errors */ | |
166 | return (-1); | |
167 | } | |
168 | if (!had_headers) { | |
169 | if (strprefixcmp(line, "Date:") == 0) | |
170 | had_date = 1; | |
171 | else if (strprefixcmp(line, "Message-Id:") == 0) | |
172 | had_messagid = 1; | |
173 | else if (strprefixcmp(line, "From:") == 0) | |
174 | had_from = 1; | |
175 | } | |
176 | if (strcmp(line, "\n") == 0 && !had_headers) { | |
177 | had_headers = 1; | |
178 | while (!had_date || !had_messagid || !had_from) { | |
179 | if (!had_date) { | |
180 | had_date = 1; | |
181 | snprintf(line, sizeof(line), "Date: %s\n", rfc822date()); | |
182 | } else if (!had_messagid) { | |
183 | /* XXX better msgid, assign earlier and log? */ | |
184 | had_messagid = 1; | |
185 | snprintf(line, sizeof(line), "Message-Id: <%s@%s>\n", | |
186 | queue->id, hostname()); | |
187 | } else if (!had_from) { | |
188 | had_from = 1; | |
189 | snprintf(line, sizeof(line), "From: <%s>\n", sender); | |
190 | } | |
191 | if (fwrite(line, strlen(line), 1, queue->mailf) != 1) | |
192 | return (-1); | |
193 | } | |
194 | strcpy(line, "\n"); | |
195 | } | |
196 | if (!nodot && linelen == 2 && line[0] == '.') | |
197 | break; | |
198 | if (fwrite(line, strlen(line), 1, queue->mailf) != 1) | |
199 | return (-1); | |
200 | } | |
201 | ||
202 | return (0); | |
203 | } |