void smtp_chat_notify(SMTP_SESSION *session) { const char *myname = "smtp_chat_notify"; VSTREAM *notice; char **cpp; /* * Sanity checks. */ if (session->history == 0) msg_panic("%s: no conversation history", myname); if (msg_verbose) msg_info("%s: notify postmaster", myname); /* * Construct a message for the postmaster, explaining what this is all * about. This is junk mail: don't send it when the mail posting service * is unavailable, and use the double bounce sender address, to prevent * mail bounce wars. Always prepend one space to message content that we * generate from untrusted data. */ #define NULL_TRACE_FLAGS 0 #define NO_QUEUE_ID ((VSTRING *) 0) #define LENGTH 78 #define INDENT 4 notice = post_mail_fopen_nowait(mail_addr_double_bounce(), var_error_rcpt, MAIL_SRC_MASK_NOTIFY, NULL_TRACE_FLAGS, SMTPUTF8_FLAG_NONE, NO_QUEUE_ID); if (notice == 0) { msg_warn("postmaster notify: %m"); return; } post_mail_fprintf(notice, "From: %s (Mail Delivery System)", mail_addr_mail_daemon()); post_mail_fprintf(notice, "To: %s (Postmaster)", var_error_rcpt); post_mail_fprintf(notice, "Subject: %s %s client: errors from %s", var_mail_name, smtp_mode ? "SMTP" : "LMTP", session->namaddrport); post_mail_fputs(notice, ""); post_mail_fprintf(notice, "Unexpected response from %s.", session->namaddrport); post_mail_fputs(notice, ""); post_mail_fputs(notice, "Transcript of session follows."); post_mail_fputs(notice, ""); argv_terminate(session->history); for (cpp = session->history->argv; *cpp; cpp++) line_wrap(printable(*cpp, '?'), LENGTH, INDENT, print_line, (void *) notice); post_mail_fputs(notice, ""); post_mail_fprintf(notice, "For other details, see the local mail logfile"); (void) post_mail_fclose(notice); }
static void post_mail_init(VSTREAM *stream, const char *sender, const char *recipient, int filter_class, int trace_flags, VSTRING *queue_id) { VSTRING *id = queue_id ? queue_id : vstring_alloc(100); struct timeval now; const char *date; int cleanup_flags = int_filt_flags(filter_class) | CLEANUP_FLAG_MASK_INTERNAL; GETTIMEOFDAY(&now); date = mail_date(now.tv_sec); /* * Negotiate with the cleanup service. Give up if we can't agree. */ if (attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_END) != 1 || attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, cleanup_flags, ATTR_TYPE_END) != 0) msg_fatal("unable to contact the %s service", var_cleanup_service); /* * Generate a minimal envelope section. The cleanup service will add a * size record. */ rec_fprintf(stream, REC_TYPE_TIME, REC_TYPE_TIME_FORMAT, REC_TYPE_TIME_ARG(now)); rec_fprintf(stream, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_LOG_ORIGIN, MAIL_ATTR_ORG_LOCAL); rec_fprintf(stream, REC_TYPE_ATTR, "%s=%d", MAIL_ATTR_TRACE_FLAGS, trace_flags); rec_fputs(stream, REC_TYPE_FROM, sender); rec_fputs(stream, REC_TYPE_RCPT, recipient); rec_fputs(stream, REC_TYPE_MESG, ""); /* * Do the Received: and Date: header lines. This allows us to shave a few * cycles by using the expensive date conversion result for both. */ post_mail_fprintf(stream, "Received: by %s (%s)", var_myhostname, var_mail_name); post_mail_fprintf(stream, "\tid %s; %s", vstring_str(id), date); post_mail_fprintf(stream, "Date: %s", date); if (queue_id == 0) vstring_free(id); }
void smtpd_chat_notify(SMTPD_STATE *state) { char *myname = "smtpd_chat_notify"; VSTREAM *notice; char **cpp; /* * Sanity checks. */ if (state->history == 0) msg_panic("%s: no conversation history", myname); if (msg_verbose) msg_info("%s: notify postmaster", myname); /* * Construct a message for the postmaster, explaining what this is all * about. This is junk mail: don't send it when the mail posting service * is unavailable, and use the double bounce sender address to prevent * mail bounce wars. Always prepend one space to message content that we * generate from untrusted data. */ #define NULL_TRACE_FLAGS 0 #define LENGTH 78 #define INDENT 4 notice = post_mail_fopen_nowait(mail_addr_double_bounce(), var_error_rcpt, CLEANUP_FLAG_MASK_INTERNAL, NULL_TRACE_FLAGS); if (notice == 0) { msg_warn("postmaster notify: %m"); return; } post_mail_fprintf(notice, "From: %s (Mail Delivery System)", mail_addr_mail_daemon()); post_mail_fprintf(notice, "To: %s (Postmaster)", var_error_rcpt); post_mail_fprintf(notice, "Subject: %s SMTP server: errors from %s[%s]", var_mail_name, state->name, state->addr); post_mail_fputs(notice, ""); post_mail_fputs(notice, "Transcript of session follows."); post_mail_fputs(notice, ""); argv_terminate(state->history); for (cpp = state->history->argv; *cpp; cpp++) line_wrap(printable(*cpp, '?'), LENGTH, INDENT, print_line, (char *) notice); post_mail_fputs(notice, ""); if (state->reason) post_mail_fprintf(notice, "Session aborted, reason: %s", state->reason); (void) post_mail_fclose(notice); }
static void print_line(const char *str, int len, int indent, void *context) { VSTREAM *notice = (VSTREAM *) context; post_mail_fprintf(notice, " %*s%.*s", indent, "", len, str); }