+#ifdef EXPERIMENTAL_DSN
+/* Send DSN for successful messages */
+addr_dsntmp = addr_succeed;
+addr_senddsn = NULL;
+
+while(addr_dsntmp != NULL)
+ {
+ DEBUG(D_deliver)
+ debug_printf("DSN: processing router : %s\n", addr_dsntmp->router->name);
+
+ DEBUG(D_deliver)
+ debug_printf("DSN: processing successful delivery address: %s\n", addr_dsntmp->address);
+
+ /* af_ignore_error not honored here. it's not an error */
+
+ DEBUG(D_deliver) debug_printf("DSN: Sender_address: %s\n", sender_address);
+ DEBUG(D_deliver) debug_printf("DSN: orcpt: %s flags: %d\n", addr_dsntmp->dsn_orcpt, addr_dsntmp->dsn_flags);
+ DEBUG(D_deliver) debug_printf("DSN: envid: %s ret: %d\n", dsn_envid, dsn_ret);
+ DEBUG(D_deliver) debug_printf("DSN: Final recipient: %s\n", addr_dsntmp->address);
+ DEBUG(D_deliver) debug_printf("DSN: Remote SMTP server supports DSN: %d\n", addr_dsntmp->dsn_aware);
+
+ /* send report if next hop not DSN aware or a router flagged "last DSN hop"
+ and a report was requested */
+ if (((addr_dsntmp->dsn_aware != dsn_support_yes) ||
+ ((addr_dsntmp->dsn_flags & rf_dsnlasthop) != 0))
+ &&
+ (((addr_dsntmp->dsn_flags & rf_dsnflags) != 0) &&
+ ((addr_dsntmp->dsn_flags & rf_notify_success) != 0)))
+ {
+ /* copy and relink address_item and send report with all of them at once later */
+ address_item *addr_next;
+ addr_next = addr_senddsn;
+ addr_senddsn = store_get(sizeof(address_item));
+ memcpy(addr_senddsn, addr_dsntmp, sizeof(address_item));
+ addr_senddsn->next = addr_next;
+ }
+ else
+ {
+ DEBUG(D_deliver) debug_printf("DSN: *** NOT SENDING DSN SUCCESS Message ***\n");
+ }
+
+ addr_dsntmp = addr_dsntmp->next;
+ }
+
+if (addr_senddsn != NULL)
+ {
+ pid_t pid;
+ int fd;
+
+ /* create exim process to send message */
+ pid = child_open_exim(&fd);
+
+ DEBUG(D_deliver) debug_printf("DSN: child_open_exim returns: %d\n", pid);
+
+ if (pid < 0) /* Creation of child failed */
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Process %d (parent %d) failed to "
+ "create child process to send failure message: %s", getpid(),
+ getppid(), strerror(errno));
+
+ DEBUG(D_deliver) debug_printf("DSN: child_open_exim failed\n");
+
+ }
+ else /* Creation of child succeeded */
+ {
+ FILE *f = fdopen(fd, "wb");
+ /* header only as required by RFC. only failure DSN needs to honor RET=FULL */
+ int topt = topt_add_return_path | topt_no_body;
+ uschar boundaryStr[64];
+
+ DEBUG(D_deliver) debug_printf("sending error message to: %s\n", sender_address);
+
+ /* build unique id for MIME boundary */
+ snprintf(boundaryStr, 63, "%d-eximdsn-%d", time(NULL), rand());
+ DEBUG(D_deliver) debug_printf("DSN: MIME boundary: %s\n", boundaryStr);
+
+ if (errors_reply_to != NULL) fprintf(f,"Reply-To: %s\n", errors_reply_to);
+
+ fprintf(f,"Auto-Submitted: auto-generated\n");
+ fprintf(f,"From: Mail Delivery System <Mailer-Daemon@%s>\n", qualify_domain_sender);
+ fprintf(f,"To: %s\n", sender_address);
+ fprintf(f,"Subject: Delivery Status Notification\n");
+ fprintf(f,"Content-Type: multipart/report; report-type=delivery-status; boundary=%s\n", boundaryStr);
+ fprintf(f,"MIME-Version: 1.0\n\n");
+
+ fprintf(f,"--%s\n", boundaryStr);
+ fprintf(f,"Content-type: text/plain; charset=us-ascii\n\n");
+
+ fprintf(f,"This message was created automatically by mail delivery software.\n");
+ fprintf(f," ----- The following addresses had successful delivery notifications -----\n");
+
+ addr_dsntmp = addr_senddsn;
+ while(addr_dsntmp != NULL)
+ {
+ if ((addr_dsntmp->dsn_flags & rf_dsnlasthop) == 1) {
+ fprintf(f,"<%s> (relayed via non DSN router)\n\n", addr_dsntmp->address);
+ }
+ else if (addr_dsntmp->dsn_aware == dsn_support_no) {
+ fprintf(f,"<%s> (relayed to non-DSN-aware mailer)\n\n", addr_dsntmp->address);
+ }
+ else {
+ fprintf(f,"<%s> (relayed via non \"Remote SMTP\" router)\n\n", addr_dsntmp->address);
+ }
+ addr_dsntmp = addr_dsntmp->next;
+ }
+ fprintf(f,"--%s\n", boundaryStr);
+ fprintf(f,"Content-type: message/delivery-status\n\n");
+
+ fprintf(f,"Reporting-MTA: dns; %s\n", smtp_active_hostname);
+ if (dsn_envid != NULL) {
+ /* must be decoded from xtext: see RFC 3461:6.3a */
+ uschar *xdec_envid;
+ if (auth_xtextdecode(dsn_envid, &xdec_envid) > 0)
+ fprintf(f,"Original-Envelope-ID: %s\n", dsn_envid);
+ else
+ fprintf(f,"X-Original-Envelope-ID: error decoding xtext formated ENVID\n");
+ }
+ fprintf(f,"\n");
+
+ addr_dsntmp = addr_senddsn;
+ while(addr_dsntmp != NULL)
+ {
+ if (addr_dsntmp->dsn_orcpt != NULL) {
+ fprintf(f,"Original-Recipient: %s\n", addr_dsntmp->dsn_orcpt);
+ }
+ fprintf(f,"Action: delivered\n");
+ fprintf(f,"Final-Recipient: rfc822;%s\n", addr_dsntmp->address);
+ fprintf(f,"Status: 2.0.0\n");
+ if ((addr_dsntmp->host_used != NULL) && (addr_dsntmp->host_used->name != NULL))
+ fprintf(f,"Remote-MTA: dns; %s\nDiagnostic-Code: smtp; 250 Ok\n", addr_dsntmp->host_used->name);
+ else
+ if ((addr_dsntmp->dsn_flags & rf_dsnlasthop) == 1)
+ fprintf(f,"Diagnostic-Code: X-Exim; relayed via non DSN router\n");
+ else
+ fprintf(f,"Diagnostic-Code: X-Exim; relayed via non SMTP router\n");
+ fprintf(f,"\n");
+ addr_dsntmp = addr_dsntmp->next;
+ }
+
+ fprintf(f,"--%s\n", boundaryStr);
+ fprintf(f,"Content-type: text/rfc822-headers\n\n");
+
+ fflush(f);
+ transport_filter_argv = NULL; /* Just in case */
+ return_path = sender_address; /* In case not previously set */
+
+ /* Write the original email out */
+ transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0);
+ fflush(f);
+
+ fprintf(f,"\n");
+ fprintf(f,"--%s--\n", boundaryStr);
+
+ fflush(f);
+ fclose(f);
+ rc = child_close(pid, 0); /* Waits for child to close, no timeout */
+ }
+ }
+#endif
+