]> git.pld-linux.org Git - packages/exim.git/blob - exim_463_dsn_1_3.patch
Rel 14; fix segfault in srs
[packages/exim.git] / exim_463_dsn_1_3.patch
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
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
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 @@
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
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
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. */
180 @@ -5981,6 +6010,12 @@
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. */
193 @@ -6085,6 +6120,179 @@
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
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
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
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
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:");
398 @@ -2208,6 +2211,16 @@
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  
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 @@
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
432 @@ -273,6 +280,11 @@
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 */
444 @@ -963,6 +975,9 @@
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 */
454 @@ -972,6 +987,7 @@
455      NULL,                      /* transport instance */
456      NULL,                      /* pass_router */
457      NULL                       /* redirect_router */
458 +
459  };
460  
461  ip_address_item *running_interfaces = NULL;
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
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. */
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 @@
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;
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 @@
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 +
519  /* Codes for the host_find_failed and host_all_ignored options. */
520  
521  #define hff_freeze   0
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
525 @@ -203,6 +203,9 @@
526    { "dns_retrans",              opt_time,        &dns_retrans },
527    { "dns_retry",                opt_int,         &dns_retry },
528    { "dns_use_edns0",            opt_int,         &dns_use_edns0 },
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  /*********************************************************/
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
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
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
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
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 @@
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;
604 @@ -2317,6 +2324,10 @@
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      {
615 @@ -2735,6 +2746,12 @@
616          s = string_cat(s, &size, &ptr, US"-8BITMIME\r\n", 11);
617          }
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  
628 @@ -2946,6 +2963,43 @@
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
672 @@ -3193,6 +3247,89 @@
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 */
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);
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 */
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 @@
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. */
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;
822  
823      case 'f':
824 @@ -598,6 +618,10 @@
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  
835 @@ -666,10 +690,19 @@
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 */
855 @@ -682,15 +715,82 @@
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,
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 @@
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
957 @@ -242,14 +251,36 @@
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 */
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
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 */
1009 @@ -561,6 +563,12 @@
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  
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 @@
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
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  };
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  
1055  /* Local statics */
1056  
1057 @@ -1152,6 +1162,14 @@
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
1072 @@ -1339,6 +1357,26 @@
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) &&
1099 @@ -1401,18 +1439,66 @@
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      {
This page took 0.205131 seconds and 3 git commands to generate.