]>
Commit | Line | Data |
---|---|---|
3a8fb3b3 AM |
1 | diff -urN exim-4.64.org/README.DSN exim-4.64/README.DSN |
2 | --- exim-4.64.org/README.DSN 1970-01-01 01:00:00.000000000 +0100 | |
3 | +++ exim-4.64/README.DSN 2006-12-21 16:43:20.808508250 +0100 | |
f2481dd7 AM |
4 | @@ -0,0 +1,104 @@ |
5 | +Exim DSN Patch (4.60) | |
6 | +--------------------- | |
7 | + | |
8 | +This patch is free software; you can redistribute it and/or modify | |
9 | +it under the terms of the GNU General Public License as published by | |
10 | +the Free Software Foundation; either version 2 of the License, or | |
11 | +(at your option) any later version. | |
12 | + | |
13 | +This patch is distributed in the hope that it will be useful, | |
14 | +but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | +GNU General Public License for more details. | |
17 | + | |
18 | +You should have received a copy of the GNU General Public License | |
19 | +along with this patch; if not, write to the Free Software | |
20 | +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. | |
21 | + | |
22 | +Install | |
23 | +------- | |
24 | +cd into the source tree for a vanilla exim | |
25 | + | |
26 | +patch -p1 </path/to/patch/file.patch | |
27 | + | |
28 | +Example :- | |
29 | +[root@linuxbuild exim-4.60-test]# patch -p1 <../exim.dsn.patch.460 | |
30 | + | |
31 | +Expected Output :- | |
32 | +patching file README.DSN | |
33 | +patching file src/config.h.defaults | |
34 | +patching file src/deliver.c | |
35 | +patching file src/exim.c | |
36 | +patching file src/exim.h | |
37 | +patching file src/globals.c | |
38 | +patching file src/globals.h | |
39 | +patching file src/local_scan.h | |
40 | +patching file src/macros.h | |
41 | +patching file src/readconf.c | |
42 | +patching file src/route.c | |
43 | +patching file src/smtp_in.c | |
44 | +patching file src/spool_in.c | |
45 | +patching file src/spool_out.c | |
46 | +patching file src/structs.h | |
47 | +patching file src/transport.c | |
48 | +patching file src/transports/smtp.c | |
49 | + | |
50 | + | |
51 | +This patch can be included / excluded from the compilation by use of the #define SUPPORT_DSN | |
52 | +which gets added into src/config.h.defaults & src/EDITME by the patch. | |
53 | + | |
54 | +Use | |
55 | +--- | |
56 | + | |
57 | +The facility (once compiled in) can be turned on for a particular router via the | |
58 | +dsn_process directive Eg :- | |
59 | + | |
60 | +dest_delivery_int: | |
61 | + driver = manualroute | |
62 | + domains = +relay_to_domains | |
63 | + condition = ${if eq {${lc:$sender_address_domain}}\ | |
64 | + {domain.com}\ | |
65 | + {yes}{no}\ | |
66 | + } | |
67 | + dsn_process | |
68 | + hide route_data = ${lc:${extract{mailHost}{$address_data}{$value}{}}} | |
69 | + transport = remote_smtp | |
70 | + | |
71 | +Exim will produce 1 of 2 DSN's back to the originator, or pass on the DSN request. | |
72 | +The 2 DSN's will either contain (relayed via non "Remote SMTP" router) or | |
73 | +(relayed to non-DSN-aware mailer) depending on if the delivery was VIA an SMTP | |
74 | +transport or not. | |
75 | + | |
76 | + | |
77 | +Credits | |
78 | +------- | |
79 | + | |
80 | +The original work for the patch was done by Philip Hazel in Exim 3 | |
81 | + | |
82 | +The extract was taken and re-applied to Exim 4 by the following :- | |
83 | +Phil Bingham (phil.bingham@cwipapps.net) | |
84 | +Steve Falla (steve.falla@cwipapps.net) | |
85 | +Ray Edah (ray.edah@cwipapps.net) | |
86 | +Andrew Johnson (andrew.johnson@cwippaps.net) | |
87 | +Adrian Hungate (adrian.hungate@cwipapps.net) | |
88 | + | |
89 | +Contributions | |
90 | +------------- | |
91 | +Andrey J. Melnikoff (TEMHOTA) (temnota@kmv.ru) | |
92 | + | |
93 | + | |
94 | +ChangeLog | |
95 | +--------- | |
96 | + | |
97 | +14-Apr-2006 : Changed subject to "Delivery Status Notification" | |
98 | + | |
99 | +17-May-2006 : debug_printf in spool-in.c were not wrapped with #ifndef COMPILE_UTILITY | |
100 | + thanks to Andrey J. Melnikoff for this information | |
101 | + | |
102 | + | |
103 | + | |
104 | +Support for this patch (limited though it is) will only be provided through the SourceForge | |
105 | +project page (http://sourceforge.net/projects/eximdsn/) | |
106 | + | |
107 | +-- | |
108 | +Andrew Johnson Cable & Wireless | |
3a8fb3b3 AM |
109 | diff -urN exim-4.64.org/src/config.h.defaults exim-4.64/src/config.h.defaults |
110 | --- exim-4.64.org/src/config.h.defaults 2006-12-20 10:46:04.000000000 +0100 | |
111 | +++ exim-4.64/src/config.h.defaults 2006-12-21 16:43:20.808508250 +0100 | |
112 | @@ -121,6 +121,7 @@ | |
f2481dd7 AM |
113 | #define SUPPORT_MOVE_FROZEN_MESSAGES |
114 | #define SUPPORT_PAM | |
115 | #define SUPPORT_TLS | |
116 | +#define SUPPORT_DSN | |
117 | #define SUPPORT_TRANSLATE_IP_ADDRESS | |
118 | ||
119 | #define SYSLOG_LOG_PID | |
3a8fb3b3 AM |
120 | diff -urN exim-4.64.org/src/deliver.c exim-4.64/src/deliver.c |
121 | --- exim-4.64.org/src/deliver.c 2006-12-20 10:46:04.000000000 +0100 | |
122 | +++ exim-4.64/src/deliver.c 2006-12-21 16:43:20.812508500 +0100 | |
f2481dd7 AM |
123 | @@ -65,6 +65,9 @@ |
124 | static address_item *addr_remote = NULL; | |
125 | static address_item *addr_route = NULL; | |
126 | static address_item *addr_succeed = NULL; | |
127 | +#ifdef SUPPORT_DSN | |
128 | +static address_item *addr_dsntmp = NULL; | |
129 | +#endif | |
130 | ||
131 | static FILE *message_log = NULL; | |
132 | static BOOL update_spool; | |
133 | @@ -2866,6 +2869,15 @@ | |
134 | break; | |
135 | #endif | |
136 | ||
137 | + #ifdef SUPPORT_DSN | |
138 | + case 'D': | |
139 | + if (addr == NULL) break; | |
140 | + addr->dsn_aware = (*ptr)? string_copy(ptr) : string_copy(" "); | |
141 | + while (*ptr++); | |
142 | + DEBUG(D_deliver) debug_printf("DSN read: addr->dsn_aware = %s\n", addr->dsn_aware); | |
143 | + break; | |
144 | + #endif | |
145 | + | |
146 | case 'A': | |
147 | if (addr == NULL) | |
148 | { | |
149 | @@ -3935,6 +3947,15 @@ | |
150 | } | |
151 | #endif | |
152 | ||
153 | + #ifdef SUPPORT_DSN | |
154 | + if (addr->dsn_aware == NULL) | |
155 | + addr->dsn_aware = string_copy(" "); | |
156 | + DEBUG(D_deliver) debug_printf("DSN write: addr->dsn_aware = %s\n", addr->dsn_aware); | |
157 | + sprintf(big_buffer, "D%s", addr->dsn_aware); | |
158 | + DEBUG(D_deliver) debug_printf("DSN write: big_buffer = %s (%d)\n", big_buffer, strlen(big_buffer)+1); | |
159 | + write(fd, big_buffer, strlen(big_buffer)+1); | |
160 | + #endif | |
161 | + | |
162 | /* Retry information: for most success cases this will be null. */ | |
163 | ||
164 | for (r = addr->retries; r != NULL; r = r->next) | |
165 | @@ -5072,6 +5093,14 @@ | |
166 | if (r->pno >= 0) | |
167 | new->onetime_parent = recipients_list[r->pno].address; | |
168 | ||
169 | + #ifdef SUPPORT_DSN | |
170 | + /* If DSN support is enabled, set the dsn flags and the original receipt | |
171 | + to be passed on to other DSN enabled MTAs */ | |
172 | + new->dsn_flags = r->dsn_flags & rf_dsnflags; | |
173 | + new->dsn_orcpt = r->orcpt; | |
174 | + debug_printf("DSN (deliver): orcpt: %s flags: %d\n", new->dsn_orcpt, new->dsn_flags); | |
175 | + #endif | |
176 | + | |
177 | switch (process_recipients) | |
178 | { | |
179 | /* RECIP_DEFER is set when a system filter freezes a message. */ | |
3a8fb3b3 | 180 | @@ -5981,6 +6010,12 @@ |
f2481dd7 AM |
181 | regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE); |
182 | #endif | |
183 | ||
184 | + #ifdef SUPPORT_DSN | |
185 | + /* Set the regex to check for DSN support on remote MTA */ | |
186 | + if (regex_DSN == NULL) regex_DSN = | |
187 | + regex_must_compile(US"\\n250[\\s\\-]DSN(\\s|\\n|$)", FALSE, TRUE); | |
188 | + #endif | |
189 | + | |
190 | /* Now sort the addresses if required, and do the deliveries. The yield of | |
191 | do_remote_deliveries is FALSE when mua_wrapper is set and all addresses | |
192 | cannot be delivered in one transaction. */ | |
3a8fb3b3 | 193 | @@ -6085,6 +6120,179 @@ |
f2481dd7 AM |
194 | |
195 | else if (!dont_deliver) retry_update(&addr_defer, &addr_failed, &addr_succeed); | |
196 | ||
197 | +#ifdef SUPPORT_DSN | |
198 | +/* ********** philb - Send DSN for successful messages */ | |
199 | + | |
200 | +addr_dsntmp = addr_succeed; | |
201 | + | |
202 | +while(addr_dsntmp != NULL) | |
203 | +{ | |
204 | + BOOL dsn_sendmessage = FALSE; | |
205 | + uschar dsnmsgbuf[4096]; | |
206 | + | |
207 | + DEBUG(D_deliver) | |
208 | + debug_printf("DSN: processing router : %s\n", addr_dsntmp->router->name); | |
209 | + | |
210 | + DEBUG(D_deliver) | |
211 | + debug_printf("DSN: processing successful delivery address: %s\n", addr_dsntmp->address); | |
212 | + | |
213 | + if (testflag(addr_dsntmp, af_ignore_error)) | |
214 | + { | |
215 | + DEBUG(D_deliver) | |
216 | + debug_printf("DSN: Ignore error for: %s\n", addr_dsntmp->address); | |
217 | + } | |
218 | + else | |
219 | + { | |
220 | + DEBUG(D_deliver) debug_printf("DSN: Checking Flag\n"); | |
221 | + if (addr_dsntmp->dsn_aware == NULL) { | |
222 | + DEBUG(D_deliver) debug_printf("DSN: dsn_aware was NULL, setting to space at %s %d\n", __FILE__, __LINE__); | |
223 | + addr_dsntmp->dsn_aware = string_copy(" "); | |
224 | + } | |
225 | + DEBUG(D_deliver) debug_printf("DSN: Sender_address: %s\n", sender_address); | |
226 | + DEBUG(D_deliver) debug_printf("DSN: orcpt: %s flags: %d\n", addr_dsntmp->dsn_orcpt, addr_dsntmp->dsn_flags); | |
227 | + DEBUG(D_deliver) debug_printf("DSN: envid: %s ret: %d\n", dsn_envid, dsn_ret); | |
228 | + DEBUG(D_deliver) debug_printf("DSN: Remote SMTP server supports DSN: %s\n", addr_dsntmp->dsn_aware); | |
229 | + | |
230 | + /* Process the flags */ | |
231 | + if((addr_dsntmp->dsn_flags & rf_dsnflags) != 0) | |
232 | + { | |
233 | + /* We've got at least one flag set */ | |
234 | + | |
235 | + /* set flag so we don't send bounces */ | |
236 | + setflag(addr_dsntmp, af_ignore_error); | |
237 | + | |
238 | + if((addr_dsntmp->dsn_flags & rf_notify_never) != 0) | |
239 | + { | |
240 | + DEBUG(D_deliver) debug_printf("DSN: NEVER FLAG\n"); | |
241 | + | |
242 | + /* nothing to do here */ | |
243 | + } | |
244 | + | |
245 | + if((addr_dsntmp->dsn_flags & rf_notify_success) != 0) | |
246 | + { | |
247 | + DEBUG(D_deliver) debug_printf("DSN: SUCCESS FLAG\n"); | |
248 | + | |
249 | + dsn_sendmessage = TRUE; | |
250 | + } | |
251 | + | |
252 | + if((addr_dsntmp->dsn_flags & rf_notify_failure) != 0) | |
253 | + { | |
254 | + DEBUG(D_deliver) debug_printf("DSN: FAILURE FLAG\n"); | |
255 | + | |
256 | + /* allow bounce messages */ | |
257 | + clearflag(addr_dsntmp, af_ignore_error); | |
258 | + } | |
259 | + | |
260 | + if((addr_dsntmp->dsn_flags & rf_notify_delay) != 0) | |
261 | + { | |
262 | + DEBUG(D_deliver) debug_printf("DSN: DELAY FLAG\n"); | |
263 | + | |
264 | + /* hmm, what to do here? */ | |
265 | + } | |
266 | + } | |
267 | + | |
268 | + if ((addr_dsntmp->dsn_aware != 0) && (addr_dsntmp->dsn_aware[0] != 'Y') && (dsn_sendmessage == TRUE) && (addr_dsntmp->router->dsn_process == TRUE)) | |
269 | + { | |
270 | + pid_t pid; | |
271 | + int fd; | |
272 | + | |
273 | + /* remote MTA does not support DSN, so we need to send message */ | |
274 | + | |
275 | + /* create exim process to send message */ | |
276 | + pid = child_open_exim(&fd); | |
277 | + | |
278 | + DEBUG(D_deliver) debug_printf("DSN: child_open_exim returns: %d\n", pid); | |
279 | + | |
280 | + if (pid < 0) /* Creation of child failed */ | |
281 | + { | |
282 | + log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Process %d (parent %d) failed to " | |
283 | + "create child process to send failure message: %s", getpid(), | |
284 | + getppid(), strerror(errno)); | |
285 | + | |
286 | + DEBUG(D_deliver) debug_printf("DSN: child_open_exim failed\n"); | |
287 | + | |
288 | + } | |
289 | + else /* Creation of child succeeded */ | |
290 | + { | |
291 | + FILE *f = fdopen(fd, "wb"); | |
292 | + int topt = topt_add_return_path; | |
293 | + uschar boundaryStr[64]; | |
294 | + | |
295 | + DEBUG(D_deliver) debug_printf("sending error message to: %s\n", sender_address); | |
296 | + | |
297 | + /* build unique id for MIME boundary */ | |
298 | + snprintf(boundaryStr, 63, "%d-cwdsn-%d", pid, rand()); | |
299 | + DEBUG(D_deliver) debug_printf("DSN: MIME boundary: %s\n", boundaryStr); | |
300 | + | |
301 | + /* if the sender doesn't want the whole message returned, don't send the body */ | |
302 | + if (dsn_ret != dsn_ret_full) topt |= topt_no_body; | |
303 | + | |
304 | + if (errors_reply_to != NULL) fprintf(f,"Reply-To: %s\n", errors_reply_to); | |
305 | + | |
306 | + fprintf(f,"Auto-Submitted: auto-generated\n"); | |
307 | + fprintf(f,"From: Mail Delivery System <Mailer-Daemon@%s>\n", qualify_domain_sender); | |
308 | + fprintf(f,"To: %s\n", sender_address); | |
309 | + fprintf(f,"Subject: Delivery Status Notification\n"); | |
310 | + fprintf(f,"Content-Type: multipart/report; report-type=delivery-status; boundary=%s\n", boundaryStr); | |
311 | + fprintf(f,"MIME-Version: 1.0\n\n"); | |
312 | + | |
313 | + fprintf(f,"--%s\n", boundaryStr); | |
314 | + fprintf(f,"Content-type: text/plain; charset=us-ascii\n\n"); | |
315 | + | |
316 | + fprintf(f,"This message was created automatically by mail delivery software.\n"); | |
317 | + fprintf(f," ----- The following addresses had successful delivery notifications -----\n"); | |
318 | +/* AH: added specific message for non "Remote SMTP" situations */ | |
319 | + if (addr_dsntmp->dsn_aware[0] == 'N') { | |
320 | + fprintf(f,"<%s> (relayed to non-DSN-aware mailer)\n\n", addr_dsntmp->address); | |
321 | + } else { | |
322 | + fprintf(f,"<%s> (relayed via non \"Remote SMTP\" router)\n\n", addr_dsntmp->address); | |
323 | + } | |
324 | + | |
325 | + fprintf(f,"--%s\n", boundaryStr); | |
326 | + fprintf(f,"Content-type: message/delivery-status\n\n"); | |
327 | + | |
328 | + if (dsn_envid) { /* Test for NULL added by GC */ | |
329 | + fprintf(f,"Original-Envelope-Id: %s\n", dsn_envid); | |
330 | + } | |
331 | + fprintf(f,"Reporting-MTA: dns; %s\n", qualify_domain_sender); | |
332 | + if (addr_dsntmp->dsn_orcpt) { /* Test for NULL added by GC */ | |
333 | + fprintf(f,"Original-Recipient: %s\n", addr_dsntmp->dsn_orcpt); | |
334 | + } | |
335 | + fprintf(f,"Action: delivered\n\n"); | |
336 | + | |
337 | + fprintf(f,"--%s\n", boundaryStr); | |
338 | + fprintf(f,"Content-type: message/rfc822\n\n"); | |
339 | + | |
340 | + fflush(f); | |
341 | + transport_filter_argv = NULL; /* Just in case */ | |
342 | + return_path = sender_address; /* In case not previously set */ | |
343 | + | |
344 | + /* Write the original email out */ | |
345 | + transport_write_message(NULL, fileno(f), topt, 2048, NULL, NULL, NULL, NULL, NULL, 0); | |
346 | + fflush(f); | |
347 | + | |
348 | + fprintf(f,"\n"); | |
349 | + fprintf(f,"--%s--\n", boundaryStr); | |
350 | + | |
351 | + fflush(f); | |
352 | + fclose(f); | |
353 | + rc = child_close(pid, 0); /* Waits for child to close, no timeout */ | |
354 | + } | |
355 | + } | |
356 | + else | |
357 | + { if (addr_dsntmp->router->dsn_process == TRUE) | |
358 | + DEBUG(D_deliver) debug_printf("DSN: *** NOT SENDING DSN SUCCESS Message ***\n"); | |
359 | + if (addr_dsntmp->router->dsn_process == FALSE) | |
360 | + DEBUG(D_deliver) debug_printf("DSN: *** NOT SENDING DSN SUCCESS Message (gagged) ***\n"); | |
361 | + } | |
362 | + } | |
363 | + | |
364 | + addr_dsntmp = addr_dsntmp->next; | |
365 | +} | |
366 | + | |
367 | +/* ********** philb - end of mod */ | |
368 | +#endif | |
369 | + | |
370 | /* If any addresses failed, we must send a message to somebody, unless | |
371 | af_ignore_error is set, in which case no action is taken. It is possible for | |
372 | several messages to get sent if there are addresses with different | |
3a8fb3b3 AM |
373 | diff -urN exim-4.64.org/src/EDITME exim-4.64/src/EDITME |
374 | --- exim-4.64.org/src/EDITME 2006-12-20 10:46:04.000000000 +0100 | |
375 | +++ exim-4.64/src/EDITME 2006-12-21 16:43:20.812508500 +0100 | |
f2481dd7 AM |
376 | @@ -195,6 +195,8 @@ |
377 | # least one type of lookup. You should consider whether you want to build | |
378 | # the Exim monitor or not. | |
379 | ||
380 | +# Support DSN | |
381 | +SUPPORT_DSN=yes | |
382 | ||
383 | #------------------------------------------------------------------------------ | |
384 | # These settings determine which individual router drivers are included in the | |
3a8fb3b3 AM |
385 | diff -urN exim-4.64.org/src/exim.c exim-4.64/src/exim.c |
386 | --- exim-4.64.org/src/exim.c 2006-12-20 10:46:04.000000000 +0100 | |
387 | +++ exim-4.64/src/exim.c 2006-12-21 16:43:20.816508750 +0100 | |
f2481dd7 AM |
388 | @@ -920,6 +920,9 @@ |
389 | #ifdef EXPERIMENTAL_DOMAINKEYS | |
390 | fprintf(f, " Experimental_DomainKeys"); | |
391 | #endif | |
392 | +#ifdef SUPPORT_DSN | |
393 | + fprintf(f, " C&W_DSN_1.2"); | |
394 | +#endif | |
395 | fprintf(f, "\n"); | |
396 | ||
397 | fprintf(f, "Lookups:"); | |
3a8fb3b3 | 398 | @@ -2208,6 +2211,16 @@ |
f2481dd7 AM |
399 | break; |
400 | } | |
401 | ||
402 | + #ifdef SUPPORT_DSN | |
403 | + /* -MCD: set the smtp_use_dsn flag; this indicates that the host | |
404 | + that exim is connected to supports the esmtp extension DSN */ | |
405 | + else if (strcmp(argrest, "CD") == 0) | |
406 | + { | |
407 | + smtp_use_dsn = TRUE; | |
408 | + break; | |
409 | + } | |
410 | + #endif | |
411 | + | |
412 | /* -MCP: set the smtp_use_pipelining flag; this is useful only when | |
413 | it preceded -MC (see above) */ | |
414 | ||
3a8fb3b3 AM |
415 | diff -urN exim-4.64.org/src/globals.c exim-4.64/src/globals.c |
416 | --- exim-4.64.org/src/globals.c 2006-12-20 10:46:04.000000000 +0100 | |
417 | +++ exim-4.64/src/globals.c 2006-12-21 16:43:20.816508750 +0100 | |
418 | @@ -123,6 +123,13 @@ | |
f2481dd7 AM |
419 | uschar *tls_verify_hosts = NULL; |
420 | #endif | |
421 | ||
422 | +#ifdef SUPPORT_DSN | |
423 | +BOOL dsn = TRUE; | |
424 | +uschar *dsn_envid = NULL; | |
425 | +int dsn_ret = 0; | |
426 | +const pcre *regex_DSN = NULL; | |
427 | +BOOL smtp_use_dsn = FALSE; | |
428 | +#endif | |
429 | ||
430 | /* Input-reading functions for messages, so we can use special ones for | |
431 | incoming TCP/IP. The defaults use stdin. We never need these for any | |
3a8fb3b3 | 432 | @@ -273,6 +280,11 @@ |
f2481dd7 AM |
433 | NULL, /* cipher */ |
434 | NULL, /* peerdn */ | |
435 | #endif | |
436 | + #ifdef SUPPORT_DSN | |
437 | + NULL, /* dsn_orcpt */ | |
438 | + 0, /* dsn_flags */ | |
439 | + NULL, /* dsn_aware */ | |
440 | + #endif | |
441 | (uid_t)(-1), /* uid */ | |
442 | (gid_t)(-1), /* gid */ | |
443 | 0, /* flags */ | |
3a8fb3b3 | 444 | @@ -963,6 +975,9 @@ |
f2481dd7 AM |
445 | TRUE, /* verify_sender */ |
446 | FALSE, /* uid_set */ | |
447 | FALSE, /* unseen */ | |
448 | +#ifdef SUPPORT_DSN | |
449 | + FALSE, /* dsn_process */ | |
450 | +#endif | |
451 | ||
452 | self_freeze, /* self_code */ | |
453 | (uid_t)(-1), /* uid */ | |
3a8fb3b3 | 454 | @@ -972,6 +987,7 @@ |
f2481dd7 AM |
455 | NULL, /* transport instance */ |
456 | NULL, /* pass_router */ | |
457 | NULL /* redirect_router */ | |
458 | + | |
459 | }; | |
460 | ||
461 | ip_address_item *running_interfaces = NULL; | |
3a8fb3b3 AM |
462 | diff -urN exim-4.64.org/src/globals.h exim-4.64/src/globals.h |
463 | --- exim-4.64.org/src/globals.h 2006-12-20 10:46:04.000000000 +0100 | |
464 | +++ exim-4.64/src/globals.h 2006-12-21 16:43:20.816508750 +0100 | |
f2481dd7 AM |
465 | @@ -85,6 +85,13 @@ |
466 | extern uschar *tls_verify_hosts; /* Mandatory client verification */ | |
467 | #endif | |
468 | ||
469 | +#ifdef SUPPORT_DSN | |
470 | +extern BOOL dsn; /* FALSE if DSN not to be used */ | |
471 | +extern uschar *dsn_envid; /* DSN envid string */ | |
472 | +extern int dsn_ret; /* DSN ret type*/ | |
473 | +extern const pcre *regex_DSN; /* For recognizing DSN settings */ | |
474 | +extern BOOL smtp_use_dsn; /* Global for passed connections */ | |
475 | +#endif | |
476 | ||
477 | /* Input-reading functions for messages, so we can use special ones for | |
478 | incoming TCP/IP. */ | |
3a8fb3b3 AM |
479 | diff -urN exim-4.64.org/src/local_scan.h exim-4.64/src/local_scan.h |
480 | --- exim-4.64.org/src/local_scan.h 2006-12-20 10:46:04.000000000 +0100 | |
481 | +++ exim-4.64/src/local_scan.h 2006-12-21 16:43:20.816508750 +0100 | |
482 | @@ -125,9 +125,13 @@ | |
f2481dd7 AM |
483 | field is always NULL except for one_time aliases that had errors_to on the |
484 | routers that generated them. */ | |
485 | ||
486 | +/* Added the dsn attributes orcpt and dsn_flags for DSN support*/ | |
487 | + | |
488 | typedef struct recipient_item { | |
489 | uschar *address; /* the recipient address */ | |
490 | int pno; /* parent number for "one_time" alias, or -1 */ | |
491 | + uschar *orcpt; /* DSN orcpt */ | |
492 | + int dsn_flags; /* DSN flags */ | |
493 | uschar *errors_to; /* the errors_to address or NULL */ | |
494 | #ifdef EXPERIMENTAL_BRIGHTMAIL | |
495 | uschar *bmi_optin; | |
3a8fb3b3 AM |
496 | diff -urN exim-4.64.org/src/macros.h exim-4.64/src/macros.h |
497 | --- exim-4.64.org/src/macros.h 2006-12-20 10:46:04.000000000 +0100 | |
498 | +++ exim-4.64/src/macros.h 2006-12-21 16:43:20.816508750 +0100 | |
499 | @@ -735,6 +735,22 @@ | |
f2481dd7 AM |
500 | #define topt_no_body 0x040 /* Omit body */ |
501 | #define topt_escape_headers 0x080 /* Apply escape check to headers */ | |
502 | ||
503 | +/* Flags for recipient_block, used in DSN support */ | |
504 | + | |
505 | +#define rf_onetime 0x01 /* A one-time alias */ | |
506 | +#define rf_notify_never 0x02 /* NOTIFY= settings */ | |
507 | +#define rf_notify_success 0x04 | |
508 | +#define rf_notify_failure 0x08 | |
509 | +#define rf_notify_delay 0x10 | |
510 | + | |
511 | +#define rf_dsnflags (rf_notify_never | rf_notify_success | \ | |
512 | + rf_notify_failure | rf_notify_delay) | |
513 | + | |
514 | +/* DSN RET types */ | |
515 | + | |
516 | +#define dsn_ret_full 1 | |
517 | +#define dsn_ret_hdrs 2 | |
518 | + | |
75da18ae | 519 | /* Codes for the host_find_failed and host_all_ignored options. */ |
f2481dd7 AM |
520 | |
521 | #define hff_freeze 0 | |
3a8fb3b3 AM |
522 | diff -urN exim-4.64.org/src/readconf.c exim-4.64/src/readconf.c |
523 | --- exim-4.64.org/src/readconf.c 2006-12-20 10:46:04.000000000 +0100 | |
524 | +++ exim-4.64/src/readconf.c 2006-12-21 16:43:20.820509000 +0100 | |
f2481dd7 | 525 | @@ -203,6 +203,9 @@ |
f2481dd7 AM |
526 | { "dns_retrans", opt_time, &dns_retrans }, |
527 | { "dns_retry", opt_int, &dns_retry }, | |
cc5d99ce | 528 | { "dns_use_edns0", opt_int, &dns_use_edns0 }, |
f2481dd7 AM |
529 | +#ifdef SUPPORT_DSN |
530 | + { "dsn", opt_bool, &dsn }, | |
531 | +#endif | |
532 | /* This option is now a no-op, retained for compability */ | |
533 | { "drop_cr", opt_bool, &drop_cr }, | |
534 | /*********************************************************/ | |
3a8fb3b3 AM |
535 | diff -urN exim-4.64.org/src/receive.c exim-4.64/src/receive.c |
536 | --- exim-4.64.org/src/receive.c 2006-12-20 10:46:04.000000000 +0100 | |
537 | +++ exim-4.64/src/receive.c 2006-12-21 16:43:20.820509000 +0100 | |
f2481dd7 AM |
538 | @@ -474,6 +474,8 @@ |
539 | memcpy(recipients_list, oldlist, oldmax * sizeof(recipient_item)); | |
540 | } | |
541 | ||
542 | +/* memset added by GC to blank dsn records, etc. */ | |
543 | +memset(&recipients_list[recipients_count], 0, sizeof(recipient_item)); | |
544 | recipients_list[recipients_count].address = recipient; | |
545 | recipients_list[recipients_count].pno = pno; | |
546 | #ifdef EXPERIMENTAL_BRIGHTMAIL | |
3a8fb3b3 AM |
547 | diff -urN exim-4.64.org/src/route.c exim-4.64/src/route.c |
548 | --- exim-4.64.org/src/route.c 2006-12-20 10:46:04.000000000 +0100 | |
549 | +++ exim-4.64/src/route.c 2006-12-21 16:43:20.824509250 +0100 | |
f2481dd7 AM |
550 | @@ -60,6 +60,10 @@ |
551 | (void *)offsetof(router_instance, domains) }, | |
552 | { "driver", opt_stringptr|opt_public, | |
553 | (void *)offsetof(router_instance, driver_name) }, | |
554 | + #ifdef SUPPORT_DSN | |
555 | + { "dsn_process", opt_bool|opt_public, | |
556 | + (void *)offsetof(router_instance, dsn_process) }, | |
557 | + #endif | |
558 | { "errors_to", opt_stringptr|opt_public, | |
559 | (void *)(offsetof(router_instance, errors_to)) }, | |
560 | { "expn", opt_bool|opt_public, | |
561 | @@ -272,6 +276,13 @@ | |
562 | ||
563 | if (r->pass_router_name != NULL) | |
564 | set_router(r, r->pass_router_name, &(r->pass_router), TRUE); | |
565 | + | |
566 | + #ifdef SUPPORT_DSN | |
567 | + if (r->dsn_process == FALSE) | |
568 | + DEBUG(D_route) debug_printf("%s router skipping DSN - add dsn_process to router\n", r->name); | |
569 | + if (r->dsn_process == TRUE) | |
570 | + DEBUG(D_route) debug_printf("%s router performing DSN \n", r->name); | |
571 | + #endif | |
572 | } | |
573 | } | |
574 | ||
575 | @@ -1408,7 +1419,10 @@ | |
576 | ||
577 | copyflag(new, addr, af_propagate); | |
578 | new->p.address_data = addr->p.address_data; | |
579 | - | |
580 | +#ifdef SUPPORT_DSN | |
581 | + new->dsn_flags = addr->dsn_flags; | |
582 | + new->dsn_orcpt = addr->dsn_orcpt; | |
583 | +#endif | |
584 | ||
585 | /* As it has turned out, we haven't set headers_add or headers_remove for the | |
586 | * clone. Thinking about it, it isn't entirely clear whether they should be | |
3a8fb3b3 AM |
587 | diff -urN exim-4.64.org/src/smtp_in.c exim-4.64/src/smtp_in.c |
588 | --- exim-4.64.org/src/smtp_in.c 2006-12-20 10:46:04.000000000 +0100 | |
589 | +++ exim-4.64/src/smtp_in.c 2006-12-21 16:43:20.824509250 +0100 | |
590 | @@ -832,6 +832,13 @@ | |
f2481dd7 AM |
591 | sender_verified_list = NULL; /* No senders verified */ |
592 | memset(sender_address_cache, 0, sizeof(sender_address_cache)); | |
593 | memset(sender_domain_cache, 0, sizeof(sender_domain_cache)); | |
594 | + | |
595 | +#ifdef SUPPORT_DSN | |
596 | +/* Reset the DSN flags */ | |
597 | +dsn_ret = 0; | |
598 | +dsn_envid = NULL; | |
599 | +#endif | |
600 | + | |
601 | authenticated_sender = NULL; | |
602 | #ifdef EXPERIMENTAL_BRIGHTMAIL | |
603 | bmi_run = 0; | |
3a8fb3b3 | 604 | @@ -2317,6 +2324,10 @@ |
f2481dd7 AM |
605 | int ptr, size, rc; |
606 | int c, i; | |
607 | auth_instance *au; | |
608 | +#ifdef SUPPORT_DSN | |
609 | + uschar *orcpt = NULL; | |
610 | + int flags; | |
611 | +#endif | |
612 | ||
613 | switch(smtp_read_command(TRUE)) | |
614 | { | |
3a8fb3b3 AM |
615 | @@ -2735,6 +2746,12 @@ |
616 | s = string_cat(s, &size, &ptr, US"-8BITMIME\r\n", 11); | |
617 | } | |
f2481dd7 AM |
618 | |
619 | + #ifdef SUPPORT_DSN | |
620 | + /* Advertise DSN support if configured to do so. */ | |
621 | + if (dsn) | |
622 | + s = string_cat(s, &size, &ptr, US"250-DSN\r\n", 9); | |
623 | + #endif | |
624 | + | |
625 | /* Advertise ETRN if there's an ACL checking whether a host is | |
626 | permitted to issue it; a check is made when any host actually tries. */ | |
627 | ||
3a8fb3b3 | 628 | @@ -2946,6 +2963,43 @@ |
f2481dd7 AM |
629 | (strcmpic(value, US"8BITMIME") == 0 || |
630 | strcmpic(value, US"7BIT") == 0)) {} | |
631 | ||
632 | + #ifdef SUPPORT_DSN | |
633 | + | |
634 | + /* Handle the two DSN options, but only if configured to do so (which | |
635 | + will have caused "DSN" to be given in the EHLO response). The code itself | |
636 | + is included only if configured in at build time. */ | |
637 | + | |
638 | + else if (dsn && strcmpic(name, US"RET") == 0) | |
639 | + { | |
640 | + /* Check if RET has already been set */ | |
641 | + if (dsn_ret > 0) { | |
642 | + synprot_error(L_smtp_syntax_error, 501, NULL, | |
643 | + US"RET can be specified once only"); | |
644 | + goto COMMAND_LOOP; | |
645 | + } | |
646 | + dsn_ret = (strcmpic(value, US"HDRS") == 0)? dsn_ret_hdrs : | |
647 | + (strcmpic(value, US"FULL") == 0)? dsn_ret_full : 0; | |
648 | + DEBUG(D_receive) debug_printf("DSN_RET: %d\n", dsn_ret); | |
649 | + /* Check for invalid invalid value, and exit with error */ | |
650 | + if (dsn_ret == 0) { | |
651 | + synprot_error(L_smtp_syntax_error, 501, NULL, | |
652 | + US"Value for RET is invalid"); | |
653 | + goto COMMAND_LOOP; | |
654 | + } | |
655 | + } | |
656 | + else if (dsn && strcmpic(name, US"ENVID") == 0) | |
657 | + { | |
658 | + /* Check if the dsn envid has been already set */ | |
659 | + if (dsn_envid != NULL) { | |
660 | + synprot_error(L_smtp_syntax_error, 501, NULL, | |
661 | + US"ENVID can be specified once only"); | |
662 | + goto COMMAND_LOOP; | |
663 | + } | |
664 | + dsn_envid = string_copy(value); | |
665 | + DEBUG(D_receive) debug_printf("DSN_ENVID: %s\n", dsn_envid); | |
666 | + } | |
667 | + #endif | |
668 | + | |
669 | /* Handle the AUTH extension. If the value given is not "<>" and either | |
670 | the ACL says "yes" or there is no ACL but the sending host is | |
671 | authenticated, we set it up as the authenticated sender. However, if the | |
3a8fb3b3 | 672 | @@ -3193,6 +3247,89 @@ |
f2481dd7 AM |
673 | rcpt_fail_count++; |
674 | break; | |
675 | } | |
676 | + | |
677 | + #ifdef SUPPORT_DSN | |
678 | + /* Set the DSN flags orcpt and dsn_flags from the session*/ | |
679 | + orcpt = NULL; | |
680 | + flags = 0; | |
681 | + | |
682 | + if (esmtp) for(;;) | |
683 | + { | |
684 | + uschar *name, *value, *end; | |
685 | + int size; | |
686 | + | |
687 | + if (!extract_option(&name, &value)) | |
688 | + { | |
689 | + break; | |
690 | + } | |
691 | + | |
692 | + if (strcmpic(name, US"ORCPT") == 0) | |
693 | + { | |
694 | + /* Check whether orcpt has been already set */ | |
695 | + if (orcpt != NULL) { | |
696 | + synprot_error(L_smtp_syntax_error, 501, NULL, | |
697 | + US"ORCPT can be specified once only"); | |
698 | + goto COMMAND_LOOP; | |
699 | + } | |
700 | + orcpt = string_copy(value); | |
701 | + DEBUG(D_receive) debug_printf("DSN orcpt: %s\n", orcpt); | |
702 | + } | |
703 | + | |
704 | + else if (strcmpic(name, US"NOTIFY") == 0) | |
705 | + { | |
706 | + /* Check if the notify flags have been already set */ | |
707 | + if (flags > 0) | |
708 | + { | |
709 | + synprot_error(L_smtp_syntax_error, 501, NULL, | |
710 | + US"NOTIFY can be specified once only"); | |
711 | + goto COMMAND_LOOP; | |
712 | + } | |
713 | + if (strcmpic(value, US"NEVER") == 0) flags |= rf_notify_never; else | |
714 | + { | |
715 | + uschar *p = value; | |
716 | + while (*p != 0) | |
717 | + { | |
718 | + uschar *pp = p; | |
719 | + while (*pp != 0 && *pp != ',') pp++; | |
720 | + if (*pp == ',') *pp++ = 0; | |
721 | + if (strcmpic(p, US"SUCCESS") == 0) { | |
722 | + DEBUG(D_receive) debug_printf("GC: Setting notify success\n"); | |
723 | + flags |= rf_notify_success; | |
724 | + } | |
725 | + else if (strcmpic(p, US"FAILURE") == 0) { | |
726 | + DEBUG(D_receive) debug_printf("GC: Setting notify failure\n"); | |
727 | + flags |= rf_notify_failure; | |
728 | + } | |
729 | + else if (strcmpic(p, US"DELAY") == 0) { | |
730 | + DEBUG(D_receive) debug_printf("GC: Setting notify delay\n"); | |
731 | + flags |= rf_notify_delay; | |
732 | + } | |
733 | + else | |
734 | + { | |
735 | + /* Catch any strange values */ | |
736 | + synprot_error(L_smtp_syntax_error, 501, NULL, | |
737 | + US"Invalid value for NOTIFY parameter"); | |
738 | + goto COMMAND_LOOP; | |
739 | + } | |
740 | + p = pp; | |
741 | + } | |
742 | + DEBUG(D_receive) debug_printf("DSN Flags: %x\n", flags); | |
743 | + } | |
744 | + } | |
745 | + | |
746 | + /* Unknown option. Stick back the terminator characters and break | |
747 | + the loop. An error for a malformed address will occur. */ | |
748 | + | |
749 | + else | |
750 | + { | |
751 | + DEBUG(D_receive) debug_printf("Invalid dsn command: %s : %s\n", name, value); | |
752 | + name[-1] = ' '; | |
753 | + value[-1] = '='; | |
754 | + break; | |
755 | + } | |
756 | + } | |
757 | + #endif | |
758 | + | |
759 | ||
760 | /* Apply SMTP rewriting then extract the working address. Don't allow "<>" | |
761 | as a recipient address */ | |
3a8fb3b3 AM |
762 | @@ -3300,6 +3437,24 @@ |
763 | if (user_msg == NULL) smtp_printf("250 Accepted\r\n"); | |
764 | else smtp_user_msg(US"250", user_msg); | |
f2481dd7 AM |
765 | receive_add_recipient(recipient, -1); |
766 | + | |
767 | + #ifdef SUPPORT_DSN | |
768 | + | |
769 | + /* Set the dsn flags in the recipients_list */ | |
770 | + if (orcpt != NULL) | |
771 | + recipients_list[recipients_count-1].orcpt = orcpt; | |
772 | + else | |
773 | + recipients_list[recipients_count-1].orcpt = NULL; | |
774 | + | |
775 | + if (flags != 0) | |
776 | + recipients_list[recipients_count-1].dsn_flags = flags; | |
777 | + else | |
778 | + recipients_list[recipients_count-1].dsn_flags = 0; | |
779 | + debug_printf("DSN-AJ(smtp-in): orcpt: %s flags: %d\n", recipients_list[recipients_count-1].orcpt, recipients_list[recipients_count-1].dsn_flags); | |
780 | + | |
781 | + | |
782 | + #endif | |
783 | + | |
784 | } | |
785 | ||
786 | /* The recipient was discarded */ | |
3a8fb3b3 AM |
787 | diff -urN exim-4.64.org/src/spool_in.c exim-4.64/src/spool_in.c |
788 | --- exim-4.64.org/src/spool_in.c 2006-12-20 10:46:04.000000000 +0100 | |
789 | +++ exim-4.64/src/spool_in.c 2006-12-21 16:47:28.415982750 +0100 | |
790 | @@ -291,6 +291,13 @@ | |
f2481dd7 AM |
791 | spam_score_int = NULL; |
792 | #endif | |
793 | ||
794 | +#ifdef SUPPORT_DSN | |
795 | +#ifndef COMPILE_UTILITY | |
796 | +dsn_ret = 0; | |
797 | +dsn_envid = NULL; | |
798 | +#endif /* COMPILE_UTILITY */ | |
799 | +#endif | |
800 | + | |
801 | /* Generate the full name and open the file. If message_subdir is already | |
802 | set, just look in the given directory. Otherwise, look in both the split | |
803 | and unsplit directories, as for the data file above. */ | |
3a8fb3b3 AM |
804 | @@ -465,6 +472,19 @@ |
805 | case 'd': | |
806 | if (Ustrcmp(p, "eliver_firsttime") == 0) | |
807 | deliver_firsttime = TRUE; | |
808 | +#ifdef SUPPORT_DSN | |
809 | +#ifndef COMPILE_UTILITY | |
810 | + /* Check if the dsn flags have been set in the header file */ | |
811 | + else if (Ustrncmp(p, "sn_ret", 8) == 0) | |
812 | + { | |
813 | + dsn_ret = atoi(big_buffer + 8); | |
814 | + } | |
815 | + else if (Ustrncmp(p, "sn_envid", 10) == 0) | |
816 | + { | |
817 | + dsn_envid = string_copy(big_buffer + 11); | |
818 | + } | |
819 | +#endif /* COMPILE_UTILITY */ | |
820 | +#endif | |
821 | break; | |
f2481dd7 | 822 | |
3a8fb3b3 AM |
823 | case 'f': |
824 | @@ -598,6 +618,10 @@ | |
f2481dd7 AM |
825 | { |
826 | int nn; | |
827 | int pno = -1; | |
828 | + #ifdef SUPPORT_DSN | |
829 | + int dsn_flags = 0; | |
830 | + uschar *orcpt = NULL; | |
831 | + #endif | |
832 | uschar *errors_to = NULL; | |
833 | uschar *p; | |
834 | ||
3a8fb3b3 | 835 | @@ -666,10 +690,19 @@ |
f2481dd7 AM |
836 | } |
837 | ||
838 | /* Handle current format Exim 4 spool files */ | |
839 | + /* Spool file is modified if DSN is supported | |
840 | + Original was "address errors_to len(errors_to),pno | |
841 | + New for DSN support is now: | |
842 | + "address errors_to orcpt len(errors_to),len(orcpt),pno,dsn_flags */ | |
843 | ||
844 | else if (*p == '#') | |
845 | { | |
846 | int flags; | |
847 | + | |
848 | + #ifndef COMPILE_UTILITY | |
849 | + DEBUG(D_deliver) debug_printf("**** SPOOL_IN - Exim 4 standard format spoolfile\n"); | |
850 | + #endif /* COMPILE_UTILITY */ | |
851 | + | |
852 | (void)sscanf(CS p+1, "%d", &flags); | |
853 | ||
854 | if ((flags & 0x01) != 0) /* one_time data exists */ | |
3a8fb3b3 | 855 | @@ -682,15 +715,82 @@ |
f2481dd7 AM |
856 | { |
857 | p -= len; | |
858 | errors_to = string_copy(p); | |
859 | + } | |
860 | + } | |
861 | + | |
862 | + *(--p) = 0; /* Terminate address */ | |
863 | + } | |
864 | + #ifdef SUPPORT_DSN | |
865 | + else if (*p == '!') /* Handle Exim4 + DSN spool files */ | |
866 | + { | |
867 | + int flags; | |
868 | + int temp_dsn_flags; | |
869 | + | |
870 | + #ifndef COMPILE_UTILITY | |
871 | + DEBUG(D_deliver) debug_printf("**** SPOOL_IN - C&W DSN format spoolfile\n"); | |
872 | + #endif /* COMPILE_UTILITY */ | |
873 | + | |
874 | + sscanf(CS p+1, "%d,%d", &flags, &temp_dsn_flags); | |
875 | + | |
876 | + if (((flags & 0x01) != 0) || (temp_dsn_flags > 0)) /* one_time data or dsn_flags exist */ | |
877 | + { | |
878 | + int len; | |
879 | + int len_orcpt; | |
880 | + | |
881 | + #ifndef COMPILE_UTILITY | |
882 | + DEBUG(D_deliver) debug_printf("**** spool_in dsn_flags = 0\n"); | |
883 | + #endif /* COMPILE_UTILITY */ | |
884 | + | |
885 | + dsn_flags = 0; | |
886 | + | |
887 | + while (isdigit(*(--p)) || *p == ',' || *p == '-'); | |
888 | + sscanf(CS p+1, "%d,%d,%d,%d", &len, &len_orcpt, &pno, &dsn_flags); | |
889 | + | |
890 | + *p = 0; | |
891 | + if (len_orcpt > 0) | |
892 | + { | |
893 | + p -= len_orcpt; | |
894 | + orcpt = string_copy(p); | |
895 | } | |
896 | + *(--p) = 0; /* change the space to a NULL */ | |
897 | + | |
898 | + if (len > 0) | |
899 | + { | |
900 | + p -= len; | |
901 | + errors_to = string_copy(p); | |
902 | + } | |
903 | } | |
904 | ||
905 | *(--p) = 0; /* Terminate address */ | |
906 | } | |
907 | + #endif | |
908 | + #ifndef COMPILE_UTILITY | |
909 | + else | |
910 | + { | |
911 | + DEBUG(D_deliver) debug_printf("**** SPOOL_IN - No additional fields\n"); | |
912 | + } | |
913 | + #endif /* COMPILE_UTILITY */ | |
914 | + | |
915 | + #ifdef SUPPORT_DSN | |
916 | + #ifndef COMPILE_UTILITY | |
917 | + DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: |%s| errorsto: |%s| orcpt: |%s| dsn_flags: %d\n", | |
918 | + big_buffer, errors_to, orcpt, dsn_flags); | |
919 | + #endif /* COMPILE_UTILITY */ | |
920 | + #endif | |
921 | + #ifndef SUPPORT_DSN | |
922 | + #ifndef COMPILE_UTILITY | |
923 | + DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: |%s| errorsto: |%s|\n", | |
924 | + big_buffer, errors_to); | |
925 | + #endif /* COMPILE_UTILITY */ | |
926 | + #endif | |
927 | ||
928 | recipients_list[recipients_count].address = string_copy(big_buffer); | |
929 | recipients_list[recipients_count].pno = pno; | |
930 | recipients_list[recipients_count].errors_to = errors_to; | |
931 | + #ifdef SUPPORT_DSN | |
932 | + recipients_list[recipients_count].orcpt = orcpt; | |
933 | + recipients_list[recipients_count].dsn_flags = dsn_flags; | |
934 | + #endif | |
935 | } | |
936 | ||
937 | /* The remainder of the spool header file contains the headers for the message, | |
3a8fb3b3 AM |
938 | diff -urN exim-4.64.org/src/spool_out.c exim-4.64/src/spool_out.c |
939 | --- exim-4.64.org/src/spool_out.c 2006-12-20 10:46:04.000000000 +0100 | |
940 | +++ exim-4.64/src/spool_out.c 2006-12-21 16:43:20.828509500 +0100 | |
941 | @@ -232,6 +232,15 @@ | |
f2481dd7 AM |
942 | if (tls_peerdn != NULL) fprintf(f, "-tls_peerdn %s\n", tls_peerdn); |
943 | #endif | |
944 | ||
945 | +#ifdef SUPPORT_DSN | |
946 | +/* Write the dsn flags to the spool header file */ | |
947 | +DEBUG(D_deliver) debug_printf("DSN: Write SPOOL :-dsn_envid %s\n", dsn_envid); | |
948 | +if (dsn_envid != NULL) fprintf(f, "-dsn_envid %s\n", dsn_envid); | |
949 | +DEBUG(D_deliver) debug_printf("DSN: Write SPOOL :-dsn_ret %d\n", dsn_ret); | |
950 | +if (dsn_ret != 0) fprintf(f, "-dsn_ret %d\n", dsn_ret); | |
951 | +#endif | |
952 | + | |
953 | + | |
954 | /* To complete the envelope, write out the tree of non-recipients, followed by | |
955 | the list of recipients. These won't be disjoint the first time, when no | |
956 | checking has been done. If a recipient is a "one-time" alias, it is followed by | |
3a8fb3b3 | 957 | @@ -242,14 +251,36 @@ |
f2481dd7 AM |
958 | for (i = 0; i < recipients_count; i++) |
959 | { | |
960 | recipient_item *r = recipients_list + i; | |
961 | - if (r->pno < 0 && r->errors_to == NULL) | |
962 | +#ifdef SUPPORT_DSN | |
963 | +DEBUG(D_deliver) debug_printf("DSN: Flags :%d\n", r->dsn_flags); | |
964 | +#endif | |
965 | + if (r->pno < 0 && r->errors_to == NULL | |
966 | + #ifdef SUPPORT_DSN | |
967 | + && r->dsn_flags == 0 | |
968 | + #endif | |
969 | + ) | |
970 | fprintf(f, "%s\n", r->address); | |
971 | else | |
972 | { | |
973 | uschar *errors_to = (r->errors_to == NULL)? US"" : r->errors_to; | |
974 | + #ifdef SUPPORT_DSN | |
975 | + uschar *orcpt = (r->orcpt == NULL)? US"" : r->orcpt; | |
976 | + fprintf(f, "%s %s %s %d,%d,%d,%d!1\n", r->address, errors_to, orcpt, | |
977 | + Ustrlen(errors_to), Ustrlen(orcpt), r->pno, r->dsn_flags); | |
978 | + #else | |
979 | fprintf(f, "%s %s %d,%d#1\n", r->address, errors_to, | |
980 | Ustrlen(errors_to), r->pno); | |
981 | + #endif | |
982 | } | |
983 | + | |
984 | + #ifdef SUPPORT_DSN | |
985 | + DEBUG(D_deliver) debug_printf("DSN :**** SPOOL_OUT - address: |%s| errorsto: |%s| orcpt: |%s| dsn_flags: %d\n", | |
986 | + r->address, r->errors_to, r->orcpt, r->dsn_flags); | |
987 | + #endif | |
988 | + #ifndef SUPPORT_DSN | |
989 | + DEBUG(D_deliver) debug_printf("**** SPOOL_OUT - address: |%s| errorsto: |%s|\n", | |
990 | + r->address, r->errors_to); | |
991 | + #endif | |
992 | } | |
993 | ||
994 | /* Put a blank line before the headers */ | |
3a8fb3b3 AM |
995 | diff -urN exim-4.64.org/src/structs.h exim-4.64/src/structs.h |
996 | --- exim-4.64.org/src/structs.h 2006-12-20 10:46:04.000000000 +0100 | |
997 | +++ exim-4.64/src/structs.h 2006-12-21 16:43:20.828509500 +0100 | |
f2481dd7 AM |
998 | @@ -281,7 +281,9 @@ |
999 | BOOL verify_sender; /* Use this router when verifying a sender */ | |
1000 | BOOL uid_set; /* Flag to indicate uid is set */ | |
1001 | BOOL unseen; /* If TRUE carry on, even after success */ | |
1002 | - | |
1003 | +#ifdef SUPPORT_DSN | |
1004 | + BOOL dsn_process; /* If TRUE, activate DSN for this router */ | |
1005 | +#endif | |
1006 | int self_code; /* Encoded version of "self" */ | |
1007 | uid_t uid; /* Fixed uid value */ | |
1008 | gid_t gid; /* Fixed gid value */ | |
3a8fb3b3 | 1009 | @@ -561,6 +563,12 @@ |
f2481dd7 AM |
1010 | uschar *peerdn; /* DN of server's certificate */ |
1011 | #endif | |
1012 | ||
1013 | + #ifdef SUPPORT_DSN | |
1014 | + uschar *dsn_orcpt; /* DSN orcpt value */ | |
1015 | + int dsn_flags; /* DSN flags */ | |
1016 | + uschar *dsn_aware; /* DSN aware flag */ | |
1017 | + #endif | |
1018 | + | |
1019 | uid_t uid; /* uid for transporting */ | |
1020 | gid_t gid; /* gid for transporting */ | |
1021 | ||
3a8fb3b3 AM |
1022 | diff -urN exim-4.64.org/src/transport.c exim-4.64/src/transport.c |
1023 | --- exim-4.64.org/src/transport.c 2006-12-20 10:46:04.000000000 +0100 | |
1024 | +++ exim-4.64/src/transport.c 2006-12-21 16:43:20.832509750 +0100 | |
1025 | @@ -1786,6 +1786,11 @@ | |
f2481dd7 AM |
1026 | |
1027 | argv = child_exec_exim(CEE_RETURN_ARGV, TRUE, &i, FALSE, 0); | |
1028 | ||
1029 | + #ifdef SUPPORT_DSN | |
1030 | + /* Call with the dsn flag */ | |
1031 | + if (smtp_use_dsn) argv[i++] = US"-MCD"; | |
1032 | + #endif | |
1033 | + | |
1034 | if (smtp_authenticated) argv[i++] = US"-MCA"; | |
1035 | ||
1036 | #ifdef SUPPORT_TLS | |
3a8fb3b3 AM |
1037 | diff -urN exim-4.64.org/src/transports/smtp.c exim-4.64/src/transports/smtp.c |
1038 | --- exim-4.64.org/src/transports/smtp.c 2006-12-20 10:46:04.000000000 +0100 | |
1039 | +++ exim-4.64/src/transports/smtp.c 2006-12-21 16:43:20.832509750 +0100 | |
1040 | @@ -191,6 +191,16 @@ | |
1041 | #endif | |
1042 | }; | |
f2481dd7 AM |
1043 | |
1044 | +#ifdef SUPPORT_DSN | |
1045 | +/* some DSN flags for use later */ | |
1046 | + | |
1047 | +static int rf_list[] = {rf_notify_never, rf_notify_success, | |
1048 | + rf_notify_failure, rf_notify_delay }; | |
1049 | + | |
1050 | +static uschar *rf_names[] = { "NEVER", "SUCCESS", "FAILURE", "DELAY" }; | |
1051 | +#endif | |
1052 | + | |
1053 | + | |
1054 | ||
3a8fb3b3 AM |
1055 | /* Local statics */ |
1056 | ||
1057 | @@ -1152,6 +1162,14 @@ | |
f2481dd7 AM |
1058 | DEBUG(D_transport) debug_printf("%susing PIPELINING\n", |
1059 | smtp_use_pipelining? "" : "not "); | |
1060 | ||
1061 | + #ifdef SUPPORT_DSN | |
1062 | + /* Note if the server supports DSN */ | |
1063 | + smtp_use_dsn = dsn && | |
1064 | + esmtp && pcre_exec(regex_DSN, NULL, CS buffer, (int)Ustrlen(CS buffer), 0, | |
1065 | + PCRE_EOPT, NULL, 0) >= 0; | |
1066 | + DEBUG(D_transport) debug_printf("use_dsn=%d\n", smtp_use_dsn); | |
1067 | + #endif | |
1068 | + | |
1069 | /* Note if the response to EHLO specifies support for the AUTH extension. | |
1070 | If it has, check that this host is one we want to authenticate to, and do | |
1071 | the business. The host name and address must be available when the | |
3a8fb3b3 | 1072 | @@ -1339,6 +1357,26 @@ |
f2481dd7 AM |
1073 | while (*p) p++; |
1074 | } | |
1075 | ||
1076 | +#ifdef SUPPORT_DSN | |
1077 | +/* Add any DSN flags to the mail command */ | |
1078 | + | |
1079 | +if (smtp_use_dsn) | |
1080 | + { | |
1081 | + if (dsn_ret == dsn_ret_hdrs) | |
1082 | + { | |
1083 | + strcpy(p, " RET=HDRS"); | |
1084 | + while (*p) p++; | |
1085 | + } | |
1086 | + else if (dsn_ret == dsn_ret_full) | |
1087 | + { | |
1088 | + strcpy(p, " RET=FULL"); | |
1089 | + while (*p) p++; | |
1090 | + } | |
1091 | + if (dsn_envid != NULL) | |
1092 | + string_format(p, sizeof(buffer) - (p-buffer), " ENVID=%s", dsn_envid); | |
1093 | + } | |
1094 | +#endif | |
1095 | + | |
1096 | /* Add the authenticated sender address if present */ | |
1097 | ||
1098 | if ((smtp_authenticated || ob->authenticated_sender_force) && | |
3a8fb3b3 | 1099 | @@ -1401,18 +1439,66 @@ |
f2481dd7 AM |
1100 | int count; |
1101 | BOOL no_flush; | |
1102 | ||
1103 | + #ifdef SUPPORT_DSN | |
1104 | + /* philb - set dsn_aware flag for this recipient */ | |
1105 | + if(smtp_use_dsn) | |
1106 | + addr->dsn_aware = string_copy("Y"); | |
1107 | + else | |
1108 | + addr->dsn_aware = string_copy("N"); | |
1109 | + #endif | |
1110 | + | |
1111 | if (addr->transport_return != PENDING_DEFER) continue; | |
1112 | ||
1113 | address_count++; | |
1114 | no_flush = smtp_use_pipelining && (!mua_wrapper || addr->next != NULL); | |
1115 | ||
1116 | + #ifdef SUPPORT_DSN | |
1117 | + /* Add any DSN flags to the rcpt command and add to the sent string */ | |
1118 | + | |
1119 | + p = buffer; | |
1120 | + *p = 0; | |
1121 | + | |
1122 | + if (smtp_use_dsn) | |
1123 | + { | |
1124 | + if ((addr->dsn_flags & rf_dsnflags) != 0) | |
1125 | + { | |
1126 | + int i; | |
1127 | + BOOL first = TRUE; | |
1128 | + strcpy(p, " NOTIFY="); | |
1129 | + while (*p) p++; | |
1130 | + for (i = 0; i < 4; i++) | |
1131 | + { | |
1132 | + if ((addr->dsn_flags & rf_list[i]) != 0) | |
1133 | + { | |
1134 | + if (!first) *p++ = ','; | |
1135 | + first = FALSE; | |
1136 | + strcpy(p, rf_names[i]); | |
1137 | + while (*p) p++; | |
1138 | + } | |
1139 | + } | |
1140 | + } | |
1141 | + | |
1142 | + if (addr->dsn_orcpt != NULL) | |
1143 | + string_format(p, sizeof(buffer) - (p-buffer), " ORCPT=%s", | |
1144 | + addr->dsn_orcpt); | |
1145 | + } | |
1146 | + | |
1147 | + #endif | |
1148 | + | |
1149 | + | |
1150 | /* Now send the RCPT command, and process outstanding responses when | |
1151 | necessary. After a timeout on RCPT, we just end the function, leaving the | |
1152 | yield as OK, because this error can often mean that there is a problem with | |
1153 | just one address, so we don't want to delay the host. */ | |
1154 | ||
1155 | + #ifdef SUPPORT_DSN | |
1156 | + count = smtp_write_command(&outblock, no_flush, "RCPT TO:<%s>%s%s\r\n", | |
1157 | + transport_rcpt_address(addr, tblock->rcpt_include_affixes), igquotstr, buffer); | |
1158 | + #else | |
1159 | count = smtp_write_command(&outblock, no_flush, "RCPT TO:<%s>%s\r\n", | |
1160 | transport_rcpt_address(addr, tblock->rcpt_include_affixes), igquotstr); | |
1161 | + #endif | |
1162 | + | |
1163 | if (count < 0) goto SEND_FAILED; | |
1164 | if (count > 0) | |
1165 | { |