]> git.pld-linux.org Git - packages/exim.git/blob - exim_463_dsn_1_3.patch
- new
[packages/exim.git] / exim_463_dsn_1_3.patch
1 diff -urN exim-4.63-orig/README.DSN exim-4.63-dsn/README.DSN
2 --- exim-4.63-orig/README.DSN   1970-01-01 01:00:00.000000000 +0100
3 +++ exim-4.63-dsn/README.DSN    2006-09-12 11:47:24.000000000 +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.63-orig/src/config.h.defaults exim-4.63-dsn/src/config.h.defaults
110 --- exim-4.63-orig/src/config.h.defaults        2006-07-31 15:19:48.000000000 +0100
111 +++ exim-4.63-dsn/src/config.h.defaults 2006-09-12 11:47:24.000000000 +0100
112 @@ -123,6 +123,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.63-orig/src/deliver.c exim-4.63-dsn/src/deliver.c
121 --- exim-4.63-orig/src/deliver.c        2006-07-31 15:19:48.000000000 +0100
122 +++ exim-4.63-dsn/src/deliver.c 2006-09-12 11:47:24.000000000 +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 @@ -5959,6 +5988,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 @@ -6063,6 +6098,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.63-orig/src/EDITME exim-4.63-dsn/src/EDITME
374 --- exim-4.63-orig/src/EDITME   2006-07-31 15:19:48.000000000 +0100
375 +++ exim-4.63-dsn/src/EDITME    2006-09-12 11:47:24.000000000 +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.63-orig/src/exim.c exim-4.63-dsn/src/exim.c
386 --- exim-4.63-orig/src/exim.c   2006-07-31 15:19:48.000000000 +0100
387 +++ exim-4.63-dsn/src/exim.c    2006-09-12 11:47:24.000000000 +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 @@ -2192,6 +2195,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.63-orig/src/globals.c exim-4.63-dsn/src/globals.c
416 --- exim-4.63-orig/src/globals.c        2006-07-31 15:19:48.000000000 +0100
417 +++ exim-4.63-dsn/src/globals.c 2006-09-12 11:47:24.000000000 +0100
418 @@ -121,6 +121,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 @@ -270,6 +277,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 @@ -958,6 +970,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 @@ -967,6 +982,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.63-orig/src/globals.h exim-4.63-dsn/src/globals.h
463 --- exim-4.63-orig/src/globals.h        2006-07-31 15:19:48.000000000 +0100
464 +++ exim-4.63-dsn/src/globals.h 2006-09-12 11:47:24.000000000 +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.63-orig/src/local_scan.h exim-4.63-dsn/src/local_scan.h
480 --- exim-4.63-orig/src/local_scan.h     2006-07-31 15:19:48.000000000 +0100
481 +++ exim-4.63-dsn/src/local_scan.h      2006-09-12 11:47:24.000000000 +0100
482 @@ -123,9 +123,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.63-orig/src/macros.h exim-4.63-dsn/src/macros.h
497 --- exim-4.63-orig/src/macros.h 2006-07-31 15:19:48.000000000 +0100
498 +++ exim-4.63-dsn/src/macros.h  2006-09-12 11:47:24.000000000 +0100
499 @@ -734,6 +734,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 option. */
520  
521  #define hff_freeze   0
522 diff -urN exim-4.63-orig/src/readconf.c exim-4.63-dsn/src/readconf.c
523 --- exim-4.63-orig/src/readconf.c       2006-07-31 15:19:48.000000000 +0100
524 +++ exim-4.63-dsn/src/readconf.c        2006-09-12 11:47:24.000000000 +0100
525 @@ -203,6 +203,9 @@
526    { "dns_ipv4_lookup",          opt_stringptr,   &dns_ipv4_lookup },
527    { "dns_retrans",              opt_time,        &dns_retrans },
528    { "dns_retry",                opt_int,         &dns_retry },
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.63-orig/src/receive.c exim-4.63-dsn/src/receive.c
536 --- exim-4.63-orig/src/receive.c        2006-07-31 15:19:48.000000000 +0100
537 +++ exim-4.63-dsn/src/receive.c 2006-09-12 11:47:24.000000000 +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.63-orig/src/route.c exim-4.63-dsn/src/route.c
548 --- exim-4.63-orig/src/route.c  2006-07-31 15:19:48.000000000 +0100
549 +++ exim-4.63-dsn/src/route.c   2006-09-12 11:47:24.000000000 +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.63-orig/src/smtp_in.c exim-4.63-dsn/src/smtp_in.c
588 --- exim-4.63-orig/src/smtp_in.c        2006-07-31 15:19:48.000000000 +0100
589 +++ exim-4.63-dsn/src/smtp_in.c 2006-09-12 11:47:24.000000000 +0100
590 @@ -835,6 +835,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 @@ -2229,6 +2236,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 @@ -2632,6 +2643,12 @@
616        if (accept_8bitmime)
617          s = string_cat(s, &size, &ptr, US"250-8BITMIME\r\n", 14);
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 @@ -2823,6 +2840,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 @@ -3070,6 +3124,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 @@ -3176,6 +3313,24 @@
763        {
764        smtp_printf("250 Accepted\r\n");
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.63-orig/src/spool_in.c exim-4.63-dsn/src/spool_in.c
788 --- exim-4.63-orig/src/spool_in.c       2006-07-31 15:19:48.000000000 +0100
789 +++ exim-4.63-dsn/src/spool_in.c        2006-09-12 11:47:24.000000000 +0100
790 @@ -292,6 +292,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 @@ -474,6 +481,21 @@
805      tls_peerdn = string_copy(big_buffer + 12);
806    #endif
807  
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(big_buffer, "-dsn_ret", 8) == 0)
812 +  {
813 +   dsn_ret= atoi(big_buffer + 8);
814 +  }
815 +  else if (Ustrncmp(big_buffer, "-dsn_envid", 10) == 0)
816 +  {
817 +    dsn_envid = string_copy(big_buffer + 11);
818 +  }
819 +  #endif  /* COMPILE_UTILITY */
820 +  #endif
821 +
822 +
823    /* We now record the port number after the address, separated by a
824    dot. For compatibility during upgrading, do nothing if there
825    isn't a value (it gets left at zero). */
826 @@ -558,6 +580,10 @@
827    {
828    int nn;
829    int pno = -1;
830 +  #ifdef SUPPORT_DSN
831 +  int dsn_flags = 0;
832 +  uschar *orcpt = NULL;
833 +  #endif
834    uschar *errors_to = NULL;
835    uschar *p;
836  
837 @@ -626,10 +652,19 @@
838      }
839  
840    /* Handle current format Exim 4 spool files */
841 +  /* Spool file is modified if DSN is supported
842 +     Original was "address errors_to len(errors_to),pno
843 +     New for DSN support is now:
844 +     "address errors_to orcpt len(errors_to),len(orcpt),pno,dsn_flags */
845  
846    else if (*p == '#')
847      {
848      int flags;
849 +
850 +    #ifndef COMPILE_UTILITY
851 +      DEBUG(D_deliver) debug_printf("**** SPOOL_IN - Exim 4 standard format spoolfile\n");
852 +    #endif  /* COMPILE_UTILITY */
853 +
854      (void)sscanf(CS p+1, "%d", &flags);
855  
856      if ((flags & 0x01) != 0)      /* one_time data exists */
857 @@ -642,15 +677,82 @@
858          {
859          p -= len;
860          errors_to = string_copy(p);
861 +        }      
862 +      }
863 +
864 +    *(--p) = 0;   /* Terminate address */
865 +    }
866 +    #ifdef SUPPORT_DSN
867 +    else if (*p == '!') /* Handle Exim4 + DSN spool files */
868 +    {
869 +    int flags;
870 +    int temp_dsn_flags;
871 +
872 +    #ifndef COMPILE_UTILITY
873 +      DEBUG(D_deliver) debug_printf("**** SPOOL_IN - C&W DSN format spoolfile\n");
874 +    #endif  /* COMPILE_UTILITY */
875 +    
876 +    sscanf(CS p+1, "%d,%d", &flags, &temp_dsn_flags);
877 +    
878 +    if (((flags & 0x01) != 0) || (temp_dsn_flags > 0)) /* one_time data or dsn_flags exist */  
879 +      {
880 +      int len;
881 +      int len_orcpt;
882 +
883 +      #ifndef COMPILE_UTILITY
884 +        DEBUG(D_deliver) debug_printf("**** spool_in dsn_flags = 0\n");
885 +      #endif  /* COMPILE_UTILITY */
886 +
887 +      dsn_flags = 0;
888 +      
889 +      while (isdigit(*(--p)) || *p == ',' || *p == '-');
890 +      sscanf(CS p+1, "%d,%d,%d,%d", &len, &len_orcpt, &pno, &dsn_flags);
891 +       
892 +      *p = 0;
893 +      if (len_orcpt > 0)
894 +        {
895 +          p -= len_orcpt;
896 +          orcpt = string_copy(p);
897          }
898 +      *(--p) = 0; /* change the space to a NULL */
899 +
900 +      if (len > 0)
901 +        {
902 +        p -= len;
903 +        errors_to = string_copy(p);
904 +        }      
905        }
906  
907      *(--p) = 0;   /* Terminate address */
908      }
909 +    #endif
910 +    #ifndef COMPILE_UTILITY
911 +    else
912 +    {
913 +       DEBUG(D_deliver) debug_printf("**** SPOOL_IN - No additional fields\n");
914 +    }
915 +    #endif  /* COMPILE_UTILITY */
916 +  
917 +  #ifdef SUPPORT_DSN
918 +    #ifndef COMPILE_UTILITY
919 +      DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: |%s| errorsto: |%s| orcpt: |%s| dsn_flags: %d\n",
920 +      big_buffer, errors_to, orcpt, dsn_flags);
921 +    #endif  /* COMPILE_UTILITY */
922 +  #endif
923 +  #ifndef SUPPORT_DSN
924 +    #ifndef COMPILE_UTILITY
925 +      DEBUG(D_deliver) debug_printf("**** SPOOL_IN - address: |%s| errorsto: |%s|\n",
926 +      big_buffer, errors_to);
927 +    #endif  /* COMPILE_UTILITY */
928 +  #endif
929  
930    recipients_list[recipients_count].address = string_copy(big_buffer);
931    recipients_list[recipients_count].pno = pno;
932    recipients_list[recipients_count].errors_to = errors_to;
933 +  #ifdef SUPPORT_DSN
934 +  recipients_list[recipients_count].orcpt = orcpt;
935 +  recipients_list[recipients_count].dsn_flags = dsn_flags;
936 +  #endif
937    }
938  
939  /* The remainder of the spool header file contains the headers for the message,
940 diff -urN exim-4.63-orig/src/spool_out.c exim-4.63-dsn/src/spool_out.c
941 --- exim-4.63-orig/src/spool_out.c      2006-07-31 15:19:48.000000000 +0100
942 +++ exim-4.63-dsn/src/spool_out.c       2006-09-12 11:47:24.000000000 +0100
943 @@ -243,6 +243,15 @@
944  if (tls_peerdn != NULL) fprintf(f, "-tls_peerdn %s\n", tls_peerdn);
945  #endif
946  
947 +#ifdef SUPPORT_DSN
948 +/* Write the dsn flags to the spool header file */
949 +DEBUG(D_deliver) debug_printf("DSN: Write SPOOL :-dsn_envid %s\n", dsn_envid);
950 +if (dsn_envid != NULL) fprintf(f, "-dsn_envid %s\n", dsn_envid);
951 +DEBUG(D_deliver) debug_printf("DSN: Write SPOOL :-dsn_ret %d\n", dsn_ret);
952 +if (dsn_ret != 0) fprintf(f, "-dsn_ret %d\n", dsn_ret);
953 +#endif
954 +
955 +
956  /* To complete the envelope, write out the tree of non-recipients, followed by
957  the list of recipients. These won't be disjoint the first time, when no
958  checking has been done. If a recipient is a "one-time" alias, it is followed by
959 @@ -253,14 +262,36 @@
960  for (i = 0; i < recipients_count; i++)
961    {
962    recipient_item *r = recipients_list + i;
963 -  if (r->pno < 0 && r->errors_to == NULL)
964 +#ifdef SUPPORT_DSN
965 +DEBUG(D_deliver) debug_printf("DSN: Flags :%d\n", r->dsn_flags);
966 +#endif
967 +  if (r->pno < 0 && r->errors_to == NULL
968 +    #ifdef SUPPORT_DSN
969 +     && r->dsn_flags == 0
970 +    #endif
971 +    )
972      fprintf(f, "%s\n", r->address);
973    else
974      {
975      uschar *errors_to = (r->errors_to == NULL)? US"" : r->errors_to;
976 +    #ifdef SUPPORT_DSN
977 +    uschar *orcpt = (r->orcpt == NULL)? US"" : r->orcpt;
978 +    fprintf(f, "%s %s %s %d,%d,%d,%d!1\n", r->address, errors_to, orcpt, 
979 +      Ustrlen(errors_to), Ustrlen(orcpt), r->pno, r->dsn_flags);
980 +    #else
981      fprintf(f, "%s %s %d,%d#1\n", r->address, errors_to,
982        Ustrlen(errors_to), r->pno);
983 +    #endif
984      }
985 +    
986 +    #ifdef SUPPORT_DSN
987 +      DEBUG(D_deliver) debug_printf("DSN :**** SPOOL_OUT - address: |%s| errorsto: |%s| orcpt: |%s| dsn_flags: %d\n",
988 +         r->address, r->errors_to, r->orcpt, r->dsn_flags);
989 +    #endif
990 +    #ifndef SUPPORT_DSN
991 +      DEBUG(D_deliver) debug_printf("**** SPOOL_OUT - address: |%s| errorsto: |%s|\n",
992 +         r->address, r->errors_to);
993 +    #endif
994    }
995  
996  /* Put a blank line before the headers */
997 diff -urN exim-4.63-orig/src/structs.h exim-4.63-dsn/src/structs.h
998 --- exim-4.63-orig/src/structs.h        2006-07-31 15:19:48.000000000 +0100
999 +++ exim-4.63-dsn/src/structs.h 2006-09-12 11:47:24.000000000 +0100
1000 @@ -281,7 +281,9 @@
1001    BOOL    verify_sender;          /* Use this router when verifying a sender */
1002    BOOL    uid_set;                /* Flag to indicate uid is set */
1003    BOOL    unseen;                 /* If TRUE carry on, even after success */
1004 -
1005 +#ifdef SUPPORT_DSN
1006 +  BOOL    dsn_process;            /* If TRUE, activate DSN for this router */
1007 +#endif
1008    int     self_code;              /* Encoded version of "self" */
1009    uid_t   uid;                    /* Fixed uid value */
1010    gid_t   gid;                    /* Fixed gid value */
1011 @@ -560,6 +562,12 @@
1012    uschar *peerdn;                 /* DN of server's certificate */
1013    #endif
1014  
1015 +  #ifdef SUPPORT_DSN
1016 +  uschar *dsn_orcpt;              /* DSN orcpt value */
1017 +  int  dsn_flags;                 /* DSN flags */
1018 +  uschar *dsn_aware;              /* DSN aware flag */
1019 +  #endif
1020 +
1021    uid_t   uid;                    /* uid for transporting */
1022    gid_t   gid;                    /* gid for transporting */
1023  
1024 diff -urN exim-4.63-orig/src/transport.c exim-4.63-dsn/src/transport.c
1025 --- exim-4.63-orig/src/transport.c      2006-07-31 15:19:48.000000000 +0100
1026 +++ exim-4.63-dsn/src/transport.c       2006-09-12 11:47:24.000000000 +0100
1027 @@ -1756,6 +1756,11 @@
1028  
1029    argv = child_exec_exim(CEE_RETURN_ARGV, TRUE, &i, FALSE, 0);
1030  
1031 +  #ifdef SUPPORT_DSN
1032 +  /* Call with the dsn flag */
1033 +  if (smtp_use_dsn) argv[i++] = US"-MCD";
1034 +  #endif
1035 +
1036    if (smtp_authenticated) argv[i++] = US"-MCA";
1037  
1038    #ifdef SUPPORT_TLS
1039 diff -urN exim-4.63-orig/src/transports/smtp.c exim-4.63-dsn/src/transports/smtp.c
1040 --- exim-4.63-orig/src/transports/smtp.c        2006-07-31 15:19:48.000000000 +0100
1041 +++ exim-4.63-dsn/src/transports/smtp.c 2006-09-12 11:47:24.000000000 +0100
1042 @@ -194,6 +194,16 @@
1043  static uschar *smtp_command;   /* Points to last cmd for error messages */
1044  static uschar *mail_command;   /* Points to MAIL cmd for error messages */
1045  
1046 +#ifdef SUPPORT_DSN
1047 +/* some DSN flags for use later */
1048 +
1049 +static int   rf_list[] = {rf_notify_never, rf_notify_success,
1050 +  rf_notify_failure, rf_notify_delay };
1051 +
1052 +static uschar *rf_names[] = { "NEVER", "SUCCESS", "FAILURE", "DELAY" };
1053 +#endif
1054 +
1055 +
1056  
1057  /*************************************************
1058  *             Setup entry point                  *
1059 @@ -1137,6 +1147,14 @@
1060    DEBUG(D_transport) debug_printf("%susing PIPELINING\n",
1061      smtp_use_pipelining? "" : "not ");
1062  
1063 +  #ifdef SUPPORT_DSN
1064 +  /* Note if the server supports DSN */
1065 +  smtp_use_dsn = dsn &&
1066 +    esmtp && pcre_exec(regex_DSN, NULL, CS buffer, (int)Ustrlen(CS buffer), 0,
1067 +       PCRE_EOPT, NULL, 0) >= 0;
1068 +  DEBUG(D_transport) debug_printf("use_dsn=%d\n", smtp_use_dsn);
1069 +  #endif
1070 +
1071    /* Note if the response to EHLO specifies support for the AUTH extension.
1072    If it has, check that this host is one we want to authenticate to, and do
1073    the business. The host name and address must be available when the
1074 @@ -1324,6 +1342,26 @@
1075    while (*p) p++;
1076    }
1077  
1078 +#ifdef SUPPORT_DSN
1079 +/* Add any DSN flags to the mail command */
1080 +
1081 +if (smtp_use_dsn)
1082 +  {
1083 +  if (dsn_ret == dsn_ret_hdrs)
1084 +    {
1085 +    strcpy(p, " RET=HDRS");
1086 +    while (*p) p++;
1087 +    }
1088 +  else if (dsn_ret == dsn_ret_full)
1089 +    {
1090 +    strcpy(p, " RET=FULL");
1091 +    while (*p) p++;
1092 +    }
1093 +  if (dsn_envid != NULL)
1094 +    string_format(p, sizeof(buffer) - (p-buffer), " ENVID=%s", dsn_envid);
1095 +  }
1096 +#endif
1097 +
1098  /* Add the authenticated sender address if present */
1099  
1100  if ((smtp_authenticated || ob->authenticated_sender_force) &&
1101 @@ -1386,18 +1424,66 @@
1102    int count;
1103    BOOL no_flush;
1104  
1105 +  #ifdef SUPPORT_DSN
1106 +  /* philb - set dsn_aware flag for this recipient */
1107 +  if(smtp_use_dsn)
1108 +     addr->dsn_aware = string_copy("Y");
1109 +  else
1110 +     addr->dsn_aware = string_copy("N");
1111 +  #endif
1112 +
1113    if (addr->transport_return != PENDING_DEFER) continue;
1114  
1115    address_count++;
1116    no_flush = smtp_use_pipelining && (!mua_wrapper || addr->next != NULL);
1117  
1118 +   #ifdef SUPPORT_DSN
1119 +   /* Add any DSN flags to the rcpt command and add to the sent string */
1120 +
1121 +   p = buffer;
1122 +   *p = 0;
1123 +
1124 +   if (smtp_use_dsn)
1125 +     {
1126 +     if ((addr->dsn_flags & rf_dsnflags) != 0)
1127 +       {
1128 +       int i;
1129 +       BOOL first = TRUE;
1130 +       strcpy(p, " NOTIFY=");
1131 +       while (*p) p++;
1132 +       for (i = 0; i < 4; i++)
1133 +         {
1134 +         if ((addr->dsn_flags & rf_list[i]) != 0)
1135 +           {
1136 +           if (!first) *p++ = ',';
1137 +           first = FALSE;
1138 +           strcpy(p, rf_names[i]);
1139 +           while (*p) p++;
1140 +           }
1141 +         }
1142 +       }
1143 +
1144 +     if (addr->dsn_orcpt != NULL)
1145 +       string_format(p, sizeof(buffer) - (p-buffer), " ORCPT=%s",
1146 +         addr->dsn_orcpt);
1147 +     }
1148 +
1149 +   #endif
1150 +
1151 +
1152    /* Now send the RCPT command, and process outstanding responses when
1153    necessary. After a timeout on RCPT, we just end the function, leaving the
1154    yield as OK, because this error can often mean that there is a problem with
1155    just one address, so we don't want to delay the host. */
1156  
1157 + #ifdef SUPPORT_DSN
1158 +  count = smtp_write_command(&outblock, no_flush, "RCPT TO:<%s>%s%s\r\n",
1159 +    transport_rcpt_address(addr, tblock->rcpt_include_affixes), igquotstr, buffer);
1160 + #else
1161    count = smtp_write_command(&outblock, no_flush, "RCPT TO:<%s>%s\r\n",
1162      transport_rcpt_address(addr, tblock->rcpt_include_affixes), igquotstr);
1163 + #endif
1164 +
1165    if (count < 0) goto SEND_FAILED;
1166    if (count > 0)
1167      {
This page took 0.206204 seconds and 4 git commands to generate.