}
+#ifdef EXPERIMENTAL_DSN
+/***********************************************************
+* Print Diagnostic-Code for an address *
+************************************************************/
+
+/* This function is called to print the error information out of an address for
+a bounce or a warning message. It tries to format the message reasonably as
+required by RFC 3461 by adding a space after each newline
+
+we assume that this function is only called if addr->host_used is set and if so
+a useable addr->message is available containing some Exim description with ": \n"
+ending, followed by the L/SMTP error message.
+
+Arguments:
+ addr the address
+ f the FILE to print on
+
+Returns: nothing
+*/
+
+static void
+print_dsn_diagnostic_code(const address_item *addr, FILE *f)
+{
+uschar * s;
+/* check host_used, af_pass_message flag and addr->message for safety reasons */
+if (!addr->host_used && testflag(addr, af_pass_message) && addr->message)
+ return;
+
+/* search first ": ". we assume to find the remote-MTA answer there */
+DEBUG(D_deliver)
+ debug_printf("DSN Diagnostic-Code: addr->dsn_message = %s\n", addr->message);
+if (!(s = Ustrstr(addr->message, ": ")))
+ return; /* not found, bail out */
+fprintf(f, "Diagnostic-Code: smtp; ");
+
+s += 2; /* skip ": " */
+while (*s)
+ if (*s == '\\' && s[1] == 'n')
+ {
+ fputs("\n ", f); /* as defined in RFC 3461 */
+ s += 2;
+ }
+ else
+ fputc(*s++, f);
+
+fputc('\n', f);
+}
+#endif /* EXPERIMENTAL_DSN */
/*************************************************
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];
+ uschar * bound;
DEBUG(D_deliver) debug_printf("sending error message to: %s\n", sender_address);
/* build unique id for MIME boundary */
- snprintf(boundaryStr, sizeof(boundaryStr)-1, TIME_T_FMT "-eximdsn-%d",
- time(NULL), rand());
- DEBUG(D_deliver) debug_printf("DSN: MIME boundary: %s\n", boundaryStr);
+ bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
+ DEBUG(D_deliver) debug_printf("DSN: MIME boundary: %s\n", bound);
if (errors_reply_to)
fprintf(f, "Reply-To: %s\n", errors_reply_to);
"This message was created automatically by mail delivery software.\n"
" ----- The following addresses had successful delivery notifications -----\n",
- qualify_domain_sender, sender_address, boundaryStr, boundaryStr);
+ qualify_domain_sender, sender_address, bound, bound);
addr_dsntmp = addr_senddsn;
while(addr_dsntmp)
fprintf(f, "--%s\n"
"Content-type: message/delivery-status\n\n"
"Reporting-MTA: dns; %s\n",
- boundaryStr, smtp_active_hostname);
+ bound, smtp_active_hostname);
if (dsn_envid != NULL) {
/* must be decoded from xtext: see RFC 3461:6.3a */
fputc('\n', f);
}
- fprintf(f, "--%s\nContent-type: text/rfc822-headers\n\n", boundaryStr);
+ fprintf(f, "--%s\nContent-type: text/rfc822-headers\n\n", bound);
fflush(f);
transport_filter_argv = NULL; /* Just in case */
transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0);
fflush(f);
- fprintf(f,"\n");
- fprintf(f,"--%s--\n", boundaryStr);
+ fprintf(f,"\n--%s--\n", bound);
fflush(f);
fclose(f);
int max = (bounce_return_size_limit/DELIVER_IN_BUFFER_SIZE + 1) *
DELIVER_IN_BUFFER_SIZE;
#ifdef EXPERIMENTAL_DSN
- uschar boundaryStr[64];
+ uschar * bound;
uschar *dsnlimitmsg;
uschar *dsnnotifyhdr;
int topt;
#ifdef EXPERIMENTAL_DSN
/* generate boundary string and output MIME-Headers */
- snprintf(boundaryStr, sizeof(boundaryStr)-1, TIME_T_FMT "-eximdsn-%d",
- time(NULL), rand());
+ bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
fprintf(f, "Content-Type: multipart/report;"
" report-type=delivery-status; boundary=%s\n"
"MIME-Version: 1.0\n",
- boundaryStr);
+ bound);
#endif
/* Open a template file if one is provided. Log failure to open, but
/* output human readable part as text/plain section */
fprintf(f, "--%s\n"
"Content-type: text/plain; charset=us-ascii\n\n",
- boundaryStr);
+ bound);
#endif
if ((emf_text = next_emf(emf, US"intro")))
fprintf(f, "--%s\n"
"Content-type: message/delivery-status\n\n"
"Reporting-MTA: dns; %s\n",
- boundaryStr, smtp_active_hostname);
+ bound, smtp_active_hostname);
if (dsn_envid)
{
"Status: 5.0.0\n",
addr->address);
if (addr->host_used && addr->host_used->name)
- fprintf(f, "Remote-MTA: dns; %s\nDiagnostic-Code: smtp; %d\n",
- addr->host_used->name, addr->basic_errno);
+ {
+ fprintf(f, "Remote-MTA: dns; %s\n",
+ addr->host_used->name);
+ print_dsn_diagnostic_code(addr, f);
+ }
}
#endif
bounce_return_size_limit is always honored.
*/
- fprintf(f, "\n--%s\n", boundaryStr);
+ fprintf(f, "\n--%s\n", bound);
dsnlimitmsg = US"X-Exim-DSN-Information: Due to administrative limits only headers are returned";
dsnnotifyhdr = NULL;
if (emf)
(void)fclose(emf);
- fprintf(f, "\n--%s--\n", boundaryStr);
+ fprintf(f, "\n--%s--\n", bound);
#endif /*EXPERIMENTAL_DSN*/
/* Close the file, which should send an EOF to the child process
FILE *wmf = NULL;
FILE *f = fdopen(fd, "wb");
#ifdef EXPERIMENTAL_DSN
- uschar boundaryStr[64];
+ uschar * bound;
#endif
if (warn_message_file)
#ifdef EXPERIMENTAL_DSN
/* generated boundary string and output MIME-Headers */
- snprintf(boundaryStr, sizeof(boundaryStr)-1,
- TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
+ bound = string_sprintf(TIME_T_FMT "-eximdsn-%d", time(NULL), rand());
fprintf(f, "Content-Type: multipart/report;"
" report-type=delivery-status; boundary=%s\n"
"MIME-Version: 1.0\n",
- boundaryStr);
+ bound);
#endif
if ((wmf_text = next_emf(wmf, US"header")))
/* output human readable part as text/plain section */
fprintf(f, "--%s\n"
"Content-type: text/plain; charset=us-ascii\n\n",
- boundaryStr);
+ bound);
#endif
if ((wmf_text = next_emf(wmf, US"intro")))
fprintf(f, "\n--%s\n"
"Content-type: message/delivery-status\n\n"
"Reporting-MTA: dns; %s\n",
- boundaryStr,
+ bound,
smtp_active_hostname);
fprintf(f,"Final-Recipient: rfc822;%s\n", addr_dsndefer->address);
fprintf(f,"Status: 4.0.0\n");
if (addr_dsndefer->host_used && addr_dsndefer->host_used->name)
- fprintf(f,"Remote-MTA: dns; %s\nDiagnostic-Code: smtp; %d\n",
- addr_dsndefer->host_used->name, addr_dsndefer->basic_errno);
+ {
+ fprintf(f,"Remote-MTA: dns; %s\n",
+ addr_dsndefer->host_used->name);
+ print_dsn_diagnostic_code(addr_dsndefer, f);
+ }
addr_dsndefer = addr_dsndefer->next;
}
fprintf(f, "\n--%s\n"
"Content-type: text/rfc822-headers\n\n",
- boundaryStr);
+ bound);
fflush(f);
/* header only as required by RFC. only failure DSN needs to honor RET=FULL */
transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0);
fflush(f);
- fprintf(f,"\n--%s--\n", boundaryStr);
+ fprintf(f,"\n--%s--\n", bound);
fflush(f);
#endif /*EXPERIMENTAL_DSN*/