110 #include <sys/stat.h>
165 static QMGR_MESSAGE *qmgr_message_create(
const char *queue_name,
166 const char *queue_id,
int qflags)
256 static void qmgr_message_oldstyle_scan(
QMGR_MESSAGE *message)
259 long orig_offset, extra_offset;
291 msg_info(
"old-style scan record %c %s", rec_type, start);
304 if ((extra_offset = atol(start)) <= message->
data_offset)
341 const char *error_text;
349 int have_log_client_attr = 0;
371 msg_panic(
"%s: recipient list not empty on recipient reload",
379 if (recipient_limit < message->rcpt_limit)
383 if (recipient_limit > 5000)
384 recipient_limit = 5000;
385 if (recipient_limit <= 0)
416 if (curr_offset == message->
data_offset && curr_offset > 0) {
424 msg_info(
"record %c %s", rec_type, start);
432 msg_warn(
"%s: message rejected: missing end record",
448 if ((error_text =
split_nameval(start, &name, &value)) != 0) {
449 msg_warn(
"%s: ignoring bad attribute: %s: %.200s",
450 message->
queue_id, error_text, start);
468 dsn_orcpt ? dsn_orcpt :
"",
469 dsn_notify ? dsn_notify : 0,
470 orig_rcpt ? orig_rcpt :
"", start);
524 if (dsn_orcpt != 0) {
525 msg_warn(
"%s: ignoring out-of-order DSN original recipient address <%.200s>",
536 if (dsn_notify != 0) {
537 msg_warn(
"%s: ignoring out-of-order DSN notify flags <%d>",
543 msg_warn(
"%s: ignoring malformed DSN notify flags <%.200s>",
552 if (orig_rcpt != 0) {
553 msg_warn(
"%s: ignoring out-of-order original recipient <%.200s>",
571 if ((count = sscanf(start,
"%ld %ld %d %d %ld %d",
578 msg_warn(
"%s: invalid size record: %.100s",
584 msg_warn(
"%s: invalid flags in size record: %.100s",
589 }
else if (count == 1) {
591 qmgr_message_oldstyle_scan(message);
594 msg_warn(
"%s: message rejected: weird size record",
604 msg_warn(
"%s: invalid size record: %.100s",
640 if (message->
sender == 0) {
657 msg_warn(
"%s: ignoring malformed DSN RET flags in queue file record:%.100s",
685 if (have_log_client_attr == 0 && message->
client_name == 0)
688 if (have_log_client_attr == 0 && message->
client_addr == 0)
691 if (have_log_client_attr == 0 && message->
client_port == 0)
694 if (have_log_client_attr == 0 && message->
client_proto == 0)
697 if (have_log_client_attr == 0 && message->
client_helo == 0)
705 have_log_client_attr = 1;
710 have_log_client_attr = 1;
715 have_log_client_attr = 1;
720 have_log_client_attr = 1;
725 have_log_client_attr = 1;
730 msg_warn(
"%s: ignoring multiple %s attribute: %s",
736 msg_warn(
"%s: ignoring multiple %s attribute: %s",
742 msg_warn(
"%s: ignoring multiple %s attribute: %s",
748 msg_warn(
"%s: ignoring multiple %s attribute: %s",
754 msg_warn(
"%s: ignoring multiple %s attribute: %s",
764 if (message->
tflags == 0) {
786 msg_warn(
"%s: ignoring VERP request for null sender",
789 msg_warn(
"%s: ignoring bad VERP request: \"%.100s\"",
793 msg_info(
"%s: enabling VERP for sender \"%.100s\"",
806 if (dsn_orcpt != 0) {
808 msg_warn(
"%s: ignoring out-of-order DSN original recipient <%.200s>",
812 if (orig_rcpt != 0) {
814 msg_warn(
"%s: ignoring out-of-order original recipient <%.200s>",
880 msg_warn(
"%s: rcpt count mismatch (%d)",
887 msg_warn(
"%s: message rejected: missing arrival time record",
889 }
else if (message->
sender == 0) {
890 msg_warn(
"%s: message rejected: missing sender record",
893 msg_warn(
"%s: message rejected: missing size record",
914 if (qmgr_message_open(message)
920 qmgr_message_close(message);
928 msg_panic(
"qmgr_message_kill_record: bad offset 0x%lx", offset);
929 if (qmgr_message_open(message)
933 qmgr_message_close(message);
938 static int qmgr_message_sort_compare(
const void *p1,
const void *p2)
956 if (queue1 != 0 && queue2 == 0)
958 if (queue1 == 0 && queue2 != 0)
960 if (queue1 != 0 && queue2 != 0) {
972 if ((result = strcmp(queue1->
name, queue2->
name)) != 0)
979 at1 = strrchr(rcpt1->
address,
'@');
980 at2 = strrchr(rcpt2->
address,
'@');
981 if (at1 == 0 && at2 != 0)
983 if (at1 != 0 && at2 == 0)
985 if (at1 != 0 && at2 != 0
1000 sizeof(message->
rcpt_list.
info[0]), qmgr_message_sort_compare);
1005 msg_info(
"start sorted recipient list");
1006 for (rcpt = list.
info; rcpt < list.
info + list.
len; rcpt++)
1008 msg_info(
"end sorted recipient list");
1017 #define QMGR_REDIRECT(rp, tp, np) do { \
1019 vstring_strcpy((rp)->transport, (tp)); \
1020 vstring_strcpy((rp)->nexthop, (np)); \
1029 "4.3.0 address resolver failure");
1033 "5.1.3 bad address syntax");
1042 static void qmgr_message_resolve(
QMGR_MESSAGE *message)
1044 static ARGV *defer_xport_argv;
1060 #define STREQ(x,y) (strcmp(x,y) == 0)
1061 #define STR vstring_str
1062 #define LEN VSTRING_LEN
1066 for (recipient = list.
info; recipient < list.
info + list.
len; recipient++) {
1074 if (recipient > list.
info) {
1084 if (qmgr_resolve_one(message, recipient,
1085 recipient->
address, &reply) < 0)
1099 #define FILTER_WITHOUT_NEXTHOP(filter, next) \
1100 (((next) = split_at((filter), ':')) == 0 || *(next) == 0)
1102 #define RCPT_WITHOUT_DOMAIN(rcpt, next) \
1103 ((next = strrchr(rcpt, '@')) == 0 || *++(next) == 0)
1122 if (qmgr_resolve_one(message, recipient,
1123 recipient->
address, &reply) < 0)
1134 if (recipient->
address[0] == 0) {
1136 "5.1.3 null recipient address");
1158 "undeliverable postmaster notification discarded"));
1163 msg_warn(
"%s: undeliverable postmaster notification discarded",
1167 message->
flags |= status;
1177 if (defer_xport_argv == 0)
1179 for (cpp = defer_xport_argv->
argv; *cpp; cpp++)
1184 "4.3.2 deferred transport");
1194 "4.3.2 Too many address verification requests");
1217 saved_dsn = transport->
dsn;
1283 if (queue == 0 || !
STREQ(queue->
name,
STR(queue_name))) {
1300 saved_dsn = queue->
dsn;
1310 recipient->
u.
queue = queue;
1335 #define LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit)))
1337 for (recipient = list.
info; recipient < list.
info + list.
len; recipient++) {
1342 if ((queue = recipient->
u.
queue) == 0)
1356 if (peer == 0 || queue != peer->
queue)
1377 qmgr_recipient_count++;
1403 static void qmgr_message_move_limits(
QMGR_MESSAGE *message)
1420 msg_panic(
"qmgr_message_free: queue file is open");
1463 myfree((
void *) message);
1469 int qflags, mode_t mode)
1471 const char *myname =
"qmgr_message_alloc";
1475 msg_info(
"%s: %s %s", myname, queue_name, queue_id);
1480 message = qmgr_message_create(queue_name, queue_id, qflags);
1486 #define QMGR_LOCK_MODE (MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT)
1488 if (qmgr_message_open(message) < 0) {
1493 msg_info(
"%s: skipped, still being delivered", queue_id);
1494 qmgr_message_close(message);
1498 if (qmgr_message_read(message) < 0) {
1499 qmgr_message_close(message);
1523 msg_fatal(
"%s: %s: remove %s %s: %m", myname,
1525 qmgr_message_sort(message);
1526 qmgr_message_resolve(message);
1527 qmgr_message_sort(message);
1528 qmgr_message_assign(message);
1529 qmgr_message_close(message);
1531 qmgr_message_move_limits(message);
1540 const char *myname =
"qmgr_message_realloc";
1555 if (qmgr_message_open(message) < 0)
1557 if (qmgr_message_read(message) < 0) {
1558 qmgr_message_close(message);
1561 qmgr_message_sort(message);
1562 qmgr_message_resolve(message);
1563 qmgr_message_sort(message);
1564 qmgr_message_assign(message);
1565 qmgr_message_close(message);
1567 qmgr_message_move_limits(message);
void qmgr_message_free(QMGR_MESSAGE *message)
QMGR_QUEUE * qmgr_error_queue(const char *, DSN *)
#define MAIL_ATTR_ACT_HELO_NAME
#define RESOLVE_FLAG_FAIL
int rec_put_type(VSTREAM *stream, int type, off_t offset)
void qmgr_job_free(QMGR_JOB *)
#define QMGR_READ_FLAG_MIXED_RCPT_OTHER
#define MAIL_ATTR_TRACE_FLAGS
char * mystrdup(const char *str)
#define MAIL_ATTR_ENCODING
#define MAIL_SERVICE_ERROR
QMGR_JOB_LIST message_peers
#define DSN_SIMPLE(dsn, _status, _reason)
NORETURN msg_panic(const char *fmt,...)
off_t vstream_ftell(VSTREAM *stream)
QMGR_TRANSPORT * qmgr_transport_create(const char *)
struct timeval active_time
#define FILTER_WITHOUT_NEXTHOP(filter, next)
void deliver_completed(VSTREAM *stream, long offset)
VSTRING * rewrite_clnt_internal(const char *ruleset, const char *addr, VSTRING *result)
int rec_goto(VSTREAM *stream, const char *buf)
QMGR_TRANSPORT * qmgr_error_transport(const char *)
#define MAIL_ATTR_RWR_CONTEXT
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
QMGR_MESSAGE * qmgr_message_alloc(const char *queue_name, const char *queue_id, int qflags, mode_t mode)
void resolve_clnt_free(RESOLVE_REPLY *reply)
#define MAIL_ATTR_RWR_LOCAL
#define MAIL_ATTR_ACT_CLIENT_ADDR
#define QMGR_TRANSPORT_THROTTLED(t)
#define REC_TYPE_DSN_ENVID
QMGR_QUEUE * qmgr_queue_create(QMGR_TRANSPORT *, const char *, const char *)
#define MAIL_ATTR_SASL_METHOD
#define strcasecmp_utf8(s1, s2)
int alldig(const char *string)
QMGR_MESSAGE * qmgr_message_realloc(QMGR_MESSAGE *message)
#define MAIL_ATTR_LOG_HELO_NAME
const char * split_nameval(char *buf, char **name, char **value)
#define REC_TYPE_DSN_NOTIFY
#define MAIL_ATTR_LOG_PROTO_NAME
#define DEL_REQ_TRACE_FLAGS(f)
#define QMGR_LIST_INIT(head)
#define QMGR_READ_FLAG_SEEN_ALL_NON_RCPT
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
#define RESOLVE_CLASS_LOCAL
void qmgr_queue_unthrottle(QMGR_QUEUE *)
int rec_get_raw(VSTREAM *stream, VSTRING *buf, ssize_t maxsize, int flags)
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
struct timeval arrival_time
#define MAIL_ATTR_ACT_CLIENT_PORT
#define MAIL_ATTR_ENC_NONE
QMGR_JOB * qmgr_job_obtain(QMGR_MESSAGE *, QMGR_TRANSPORT *)
#define RESOLVE_FLAG_ERROR
QMGR_TRANSPORT * qmgr_transport_find(const char *)
#define REC_TYPE_DSN_ORCPT
void resolve_clnt_init(RESOLVE_REPLY *reply)
int var_qmgr_msg_rcpt_limit
char * var_double_bounce_sender
int vstream_fclose(VSTREAM *stream)
void opened(const char *queue_id, const char *sender, long size, int nrcpt, const char *fmt,...)
QMGR_PEER * qmgr_peer_obtain(QMGR_JOB *, QMGR_QUEUE *)
VSTREAM * mail_queue_open(const char *queue_name, const char *queue_id, int flags, mode_t mode)
#define MAIL_ATTR_SASL_SENDER
QMGR_QUEUE * qmgr_queue_find(QMGR_TRANSPORT *, const char *)
QMGR_ENTRY * qmgr_entry_create(QMGR_QUEUE *, QMGR_MESSAGE *)
void msg_warn(const char *fmt,...)
#define MAIL_ATTR_ACT_CLIENT_NAME
VSTRING * vstring_alloc(ssize_t len)
int myflock(int fd, int lock_style, int operation)
#define RCPT_LIST_INIT_QUEUE
#define RCPT_WITHOUT_DOMAIN(rcpt, next)
#define REC_TYPE_WARN_ARG(tv)
#define MAIL_ATTR_LOG_IDENT
#define MAIL_ATTR_LOG_CLIENT_ADDR
QMGR_TRANSPORT * transport
char * lowercase(char *string)
int rec_attr_map(const char *attr_name)
#define REC_TYPE_WARN_SCAN(cp, tv)
const char * verp_delims_verify(const char *delims)
#define QMGR_MSG_STATS(stats, message)
NORETURN msg_fatal(const char *fmt,...)
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
#define REC_TYPE_WARN_FORMAT
void qmgr_defer_recipient(QMGR_MESSAGE *, RECIPIENT *, DSN *)
QMGR_TRANSPORT * transport
int vstream_fflush(VSTREAM *stream)
void qmgr_transport_unthrottle(QMGR_TRANSPORT *)
char * var_def_filter_nexthop
#define MAIL_SERVICE_RETRY
int mail_queue_remove(const char *queue_name, const char *queue_id)
void recipient_list_init(RECIPIENT_LIST *list, int variant)
ARGV * argv_split(const char *, const char *)
void qmgr_message_kill_record(QMGR_MESSAGE *message, long offset)
#define MAIL_ATTR_SASL_USERNAME
#define QMGR_REDIRECT(rp, tp, np)
#define QMGR_READ_FLAG_DEFAULT
#define RECIPIENT_UPDATE(ptr, new)
#define QMGR_READ_FLAG_USER
#define resolve_clnt_verify_from(f, a, r)
#define strncasecmp_utf8(s1, s2, l)
#define MAIL_ATTR_LOG_CLIENT_NAME
VSTRING * vstring_free(VSTRING *vp)
void recipient_list_free(RECIPIENT_LIST *list)
char * qmgr_error_nexthop(DSN *)
void qmgr_message_update_warn(QMGR_MESSAGE *message)
#define vstream_fileno(vp)
#define resolve_clnt_query_from(f, a, r)
struct QMGR_QUEUE * queue
QMGR_JOB * candidate_cache_current
#define QMGR_MESSAGE_LOCKED
#define MAIL_ATTR_ACT_PROTO_NAME
int sent(int flags, const char *id, MSG_STATS *stats, RECIPIENT *recipient, const char *relay, DSN *dsn)
#define rec_get(fp, buf, limit)
void recipient_list_add(RECIPIENT_LIST *list, long offset, const char *dsn_orcpt, int dsn_notify, const char *orig_rcpt, const char *rcpt)
int rec_fprintf(VSTREAM *stream, int type, const char *format,...)
VSTRING * vstring_strncpy(VSTRING *vp, const char *src, ssize_t len)
QMGR_ENTRY_LIST entry_list
#define REC_TYPE_TIME_SCAN(cp, tv)
#define LIMIT_OK(limit, count)
#define DEL_REQ_FLAG_REC_DLY_SENT
void qmgr_job_move_limits(QMGR_JOB *)
#define DEL_REQ_FLAG_MTA_VRFY
int var_dsn_delay_cleared
#define MAIL_ATTR_LOG_CLIENT_PORT
#define QMGR_QUEUE_THROTTLED(q)
void * mymalloc(ssize_t len)
#define DEL_REQ_TRACE_ONLY_MASK
#define DEL_REQ_FLAG_RECORD
void msg_info(const char *fmt,...)