168 #include <sys/stat.h>
176 #ifdef STRCASECMP_IN_STRINGS_H
214 #define STR vstring_str
218 static BOUNCE_INFO *bounce_mail_alloc(
const char *service,
219 const char *queue_name,
220 const char *queue_id,
221 const char *encoding,
223 const char *dsn_envid,
241 bounce_info->
service = service;
255 msg_warn(
"%s: unknown encoding: %.200s",
259 if (dsn_envid && *dsn_envid)
270 bounce_info->
dsn_buf = dsn_buf;
279 "-----------------");
301 msg_fatal(
"open %s %s: %m", service, queue_id);
311 #define DELIVER_LOCK_MODE (MYFLOCK_OP_SHARED | MYFLOCK_OP_NOWAIT)
313 if (bounce_info->
orig_fp != 0) {
316 msg_fatal(
"cannot get shared lock on %s: %m",
319 bounce_info->
buf, 0)) > 0) {
326 sscanf(
STR(bounce_info->
buf),
"%ld %ld",
360 msg_warn(
"%s: no sender before message content record",
371 return (bounce_info);
377 const char *queue_name,
378 const char *queue_id,
379 const char *encoding,
381 const char *dsn_envid,
397 if ((log_handle =
bounce_log_open(service, queue_id, O_RDONLY, 0)) == 0) {
399 msg_fatal(
"open %s %s: %m", service, queue_id);
406 bounce_info = bounce_mail_alloc(service, queue_name, queue_id, encoding,
407 smtputf8, dsn_envid, rcpt_buf, dsn_buf,
408 template, log_handle);
409 return (bounce_info);
415 const char *queue_id,
416 const char *encoding,
418 const char *dsn_envid,
428 bounce_info = bounce_mail_alloc(
"none", queue_name, queue_id, encoding,
429 smtputf8, dsn_envid, rcpt_buf, dsn_buf,
431 return (bounce_info);
440 msg_warn(
"%s: read bounce log %s: %m",
446 msg_warn(
"%s: read message file %s %s: %m",
453 myfree((
void *) bounce_info);
459 const char *dest,
int postmaster_copy)
467 #define STREQ(a, b) (strcasecmp((a), (b)) == 0)
468 #define STRNE(a, b) (strcasecmp((a), (b)) != 0)
481 "auto-generated" :
"auto-replied");
489 "multipart/report",
"delivery-status");
502 #define NOT_US_ASCII(tp) \
503 STRNE(bounce_template_charset(template), "us-ascii")
505 #define NOT_7BIT_MIME(bp) \
506 (bp->mime_encoding && STRNE(bp->mime_encoding, MAIL_ATTR_ENC_7BIT))
516 "utf-8" :
"us-ascii");
540 static void bounce_print(
const char *str,
int len,
int indent,
void *context)
550 const char *format,...)
557 va_start(ap, format);
561 bounce_print, (
void *) bounce);
577 #define NON_NULL_EMPTY(s) ((s) && *(s))
581 bounce_print_wrap(bounce, bounce_info,
"<%s> (expanded from <%s>): %s",
584 bounce_print_wrap(bounce, bounce_info,
"<%s>: %s",
669 #define IS_UTF8_ADDRESS(str, len) \
670 ((str)[0] != 0 && !allascii(str) && valid_utf8_string((str), (len)))
678 "utf-8" :
"rfc822",
STR(bounce_info->
sender));
698 "utf-8" :
"rfc822", rcpt->
address);
734 bounce_print_wrap(bounce, bounce_info,
"Remote-MTA: %s; %s",
737 bounce_print_wrap(bounce, bounce_info,
"Diagnostic-Code: %s; %s",
740 bounce_print_wrap(bounce, bounce_info,
"Diagnostic-Code: X-%s; %s",
809 #define IS_UNDELIVERED_TEMPLATE(template) \
810 (IS_FAILURE_TEMPLATE(template) || IS_DELAY_TEMPLATE(template))
818 "Message Headers" :
"Message");
823 "global-headers" :
"global");
827 "text/rfc822-headers" :
"message/rfc822");
856 #define IS_HEADER(s) (IS_SPACE_TAB(*(s)) || is_header(s))
858 while (status == 0 && (rec_type =
rec_get(bounce_info->
orig_fp, bounce_info->
buf, 0)) > 0) {
864 status = (
REC_PUT_BUF(bounce, rec_type, bounce_info->
buf) != rec_type);
int post_mail_fprintf(VSTREAM *cleanup, const char *format,...)
DSN_BUF * dsb_create(void)
char * mystrdup(const char *str)
const char * mime_encoding
const char * mail_date(time_t when)
int bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info, int headers_only)
void line_wrap(const char *str, int len, int indent, LINE_WRAP_FN output_fn, void *context)
off_t vstream_ftell(VSTREAM *stream)
#define IS_UTF8_ADDRESS(str, len)
void deliver_completed(VSTREAM *stream, long offset)
int bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info, const char *dest, int postmaster_copy)
const char * mail_addr_mail_daemon(void)
void dsb_free(DSN_BUF *dsb)
BOUNCE_TEMPLATE * template
char * translit(char *, const char *, const char *)
#define IS_UNDELIVERED_TEMPLATE(template)
int bounce_diagnostic_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info, int notify_filter)
VSTRING * quote_822_local_flags(VSTRING *dst, const char *mbox, int flags)
#define SMTPUTF8_FLAG_REQUESTED
#define REC_PUT_BUF(v, t, b)
RCPT_BUF * rcpb_create(void)
VSTRING * vstring_vsprintf(VSTRING *vp, const char *format, va_list ap)
#define MAIL_ATTR_ENC_NONE
void rcpb_free(RCPT_BUF *rcpt)
int vstream_fclose(VSTREAM *stream)
VSTREAM * mail_queue_open(const char *queue_name, const char *queue_id, int flags, mode_t mode)
#define bounce_template_encoding(t)
int bounce_log_close(BOUNCE_LOG *bp)
#define DELIVER_LOCK_MODE
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
int myflock(int fd, int lock_style, int operation)
int bounce_recipient_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
#define NOT_7BIT_MIME(bp)
const char * mime_boundary
#define bounce_log_rewind(bp)
#define bounce_template_charset(t)
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
void bounce_template_expand(BOUNCE_XP_PUT_FN out_fn, VSTREAM *fp, BOUNCE_TEMPLATE *tp)
#define IS_DELAY_TEMPLATE(t)
int bounce_boilerplate(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
#define IS_FAILURE_TEMPLATE(t)
NORETURN msg_fatal(const char *fmt,...)
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
int bounce_diagnostic_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info, int notify_filter)
int post_mail_fputs(VSTREAM *cleanup, const char *str)
BOUNCE_INFO * bounce_mail_init(const char *service, const char *queue_name, const char *queue_id, const char *encoding, int smtputf8, const char *dsn_envid, BOUNCE_TEMPLATE *template)
#define quote_822_local(dst, src)
int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
VSTRING * vstring_free(VSTRING *vp)
#define vstream_fileno(vp)
BOUNCE_LOG * bounce_log_open(const char *queue_name, const char *queue_id, int flags, mode_t mode)
void bounce_mail_free(BOUNCE_INFO *bounce_info)
BOUNCE_INFO * bounce_mail_one_init(const char *queue_name, const char *queue_id, const char *encoding, int smtputf8, const char *dsn_envid, RCPT_BUF *rcpt_buf, DSN_BUF *dsn_buf, BOUNCE_TEMPLATE *template)
#define MAIL_ATTR_ENC_8BIT
#define rec_get(fp, buf, limit)
#define vstream_ferror(vp)
int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
void bounce_template_headers(BOUNCE_XP_PRN_FN out_fn, VSTREAM *fp, BOUNCE_TEMPLATE *tp, const char *rcpt, int postmaster_copy)
void bounce_delrcpt_one(BOUNCE_INFO *bounce_info)
#define NON_NULL_EMPTY(s)
BOUNCE_LOG * bounce_log_read(BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf, DSN_BUF *dsn_buf)
#define MAIL_ATTR_ENC_7BIT
void * mymalloc(ssize_t len)
void bounce_delrcpt(BOUNCE_INFO *bounce_info)