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