102 #include <sys/stat.h>
156 static QMGR_MESSAGE *qmgr_message_create(
const char *queue_name,
157 const char *queue_id,
int qflags)
241 static void qmgr_message_oldstyle_scan(
QMGR_MESSAGE *message)
244 long orig_offset, extra_offset;
275 msg_info(
"old-style scan record %c %s", rec_type, start);
282 if ((extra_offset = atol(start)) <= message->
data_offset)
318 const char *error_text;
326 int have_log_client_attr = 0;
339 msg_panic(
"%s: recipient list not empty on recipient reload",
376 if (curr_offset == message->
data_offset && curr_offset > 0) {
384 msg_info(
"record %c %s", rec_type, start);
392 msg_warn(
"%s: message rejected: missing end record",
408 if ((error_text =
split_nameval(start, &name, &value)) != 0) {
409 msg_warn(
"%s: ignoring bad attribute: %s: %.200s",
410 message->
queue_id, error_text, start);
425 #define FUDGE(x) ((x) * (var_qmgr_fudge / 100.0))
428 dsn_orcpt ? dsn_orcpt :
"",
429 dsn_notify ? dsn_notify : 0,
430 orig_rcpt ? orig_rcpt :
"", start);
483 if (dsn_orcpt != 0) {
484 msg_warn(
"%s: ignoring out-of-order DSN original recipient address <%.200s>",
495 if (dsn_notify != 0) {
496 msg_warn(
"%s: ignoring out-of-order DSN notify flags <%d>",
502 msg_warn(
"%s: ignoring malformed DSN notify flags <%.200s>",
511 if (orig_rcpt != 0) {
512 msg_warn(
"%s: ignoring out-of-order original recipient <%.200s>",
530 if ((count = sscanf(start,
"%ld %ld %d %d %ld %d",
537 msg_warn(
"%s: invalid size record: %.100s",
543 msg_warn(
"%s: invalid flags in size record: %.100s",
548 }
else if (count == 1) {
550 qmgr_message_oldstyle_scan(message);
553 msg_warn(
"%s: message rejected: weird size record",
563 msg_warn(
"%s: invalid size record: %.100s",
599 if (message->
sender == 0) {
616 msg_warn(
"%s: ignoring malformed DSN RET flags in queue file record:%.100s",
644 if (have_log_client_attr == 0 && message->
client_name == 0)
647 if (have_log_client_attr == 0 && message->
client_addr == 0)
650 if (have_log_client_attr == 0 && message->
client_port == 0)
653 if (have_log_client_attr == 0 && message->
client_proto == 0)
656 if (have_log_client_attr == 0 && message->
client_helo == 0)
664 have_log_client_attr = 1;
669 have_log_client_attr = 1;
674 have_log_client_attr = 1;
679 have_log_client_attr = 1;
684 have_log_client_attr = 1;
689 msg_warn(
"%s: ignoring multiple %s attribute: %s",
695 msg_warn(
"%s: ignoring multiple %s attribute: %s",
701 msg_warn(
"%s: ignoring multiple %s attribute: %s",
707 msg_warn(
"%s: ignoring multiple %s attribute: %s",
713 msg_warn(
"%s: ignoring multiple %s attribute: %s",
723 if (message->
tflags == 0) {
745 msg_warn(
"%s: ignoring VERP request for null sender",
748 msg_warn(
"%s: ignoring bad VERP request: \"%.100s\"",
752 msg_info(
"%s: enabling VERP for sender \"%.100s\"",
765 if (dsn_orcpt != 0) {
767 msg_warn(
"%s: ignoring out-of-order DSN original recipient <%.200s>",
771 if (orig_rcpt != 0) {
773 msg_warn(
"%s: ignoring out-of-order original recipient <%.200s>",
833 msg_warn(
"%s: message rejected: missing arrival time record",
835 }
else if (message->
sender == 0) {
836 msg_warn(
"%s: message rejected: missing sender record",
839 msg_warn(
"%s: message rejected: missing size record",
857 if (qmgr_message_open(message)
863 qmgr_message_close(message);
871 msg_panic(
"qmgr_message_kill_record: bad offset 0x%lx", offset);
872 if (qmgr_message_open(message)
876 qmgr_message_close(message);
881 static int qmgr_message_sort_compare(
const void *p1,
const void *p2)
899 if (queue1 != 0 && queue2 == 0)
901 if (queue1 == 0 && queue2 != 0)
903 if (queue1 != 0 && queue2 != 0) {
915 if ((result = strcmp(queue1->
name, queue2->
name)) != 0)
922 at1 = strrchr(rcpt1->
address,
'@');
923 at2 = strrchr(rcpt2->
address,
'@');
924 if (at1 == 0 && at2 != 0)
926 if (at1 != 0 && at2 == 0)
928 if (at1 != 0 && at2 != 0
943 sizeof(message->
rcpt_list.
info[0]), qmgr_message_sort_compare);
948 msg_info(
"start sorted recipient list");
949 for (rcpt = list.
info; rcpt < list.
info + list.
len; rcpt++)
951 msg_info(
"end sorted recipient list");
960 #define QMGR_REDIRECT(rp, tp, np) do { \
962 vstring_strcpy((rp)->transport, (tp)); \
963 vstring_strcpy((rp)->nexthop, (np)); \
972 "4.3.0 address resolver failure");
976 "5.1.3 bad address syntax");
987 static ARGV *defer_xport_argv;
1003 #define STREQ(x,y) (strcmp(x,y) == 0)
1004 #define STR vstring_str
1005 #define LEN VSTRING_LEN
1009 for (recipient = list.
info; recipient < list.
info + list.
len; recipient++) {
1017 if (recipient > list.
info) {
1025 if (qmgr_resolve_one(message, recipient,
1026 recipient->
address, &reply) < 0)
1040 #define FILTER_WITHOUT_NEXTHOP(filter, next) \
1041 (((next) = split_at((filter), ':')) == 0 || *(next) == 0)
1043 #define RCPT_WITHOUT_DOMAIN(rcpt, next) \
1044 ((next = strrchr(rcpt, '@')) == 0 || *++(next) == 0)
1063 if (qmgr_resolve_one(message, recipient,
1064 recipient->
address, &reply) < 0)
1075 if (recipient->
address[0] == 0) {
1077 "5.1.3 null recipient address");
1099 "undeliverable postmaster notification discarded"));
1104 msg_warn(
"%s: undeliverable postmaster notification discarded",
1108 message->
flags |= status;
1118 if (defer_xport_argv == 0)
1120 for (cpp = defer_xport_argv->
argv; *cpp; cpp++)
1125 "4.3.2 deferred transport");
1135 "4.3.2 Too many address verification requests");
1158 saved_dsn = transport->
dsn;
1224 if (queue == 0 || !
STREQ(queue->
name,
STR(queue_name))) {
1241 saved_dsn = queue->
dsn;
1251 recipient->
u.
queue = queue;
1275 #define LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit)))
1277 for (recipient = list.
info; recipient < list.
info + list.
len; recipient++) {
1278 if ((queue = recipient->
u.
queue) != 0) {
1301 msg_panic(
"qmgr_message_free: queue file is open");
1342 myfree((
void *) message);
1348 int qflags, mode_t mode)
1350 const char *myname =
"qmgr_message_alloc";
1354 msg_info(
"%s: %s %s", myname, queue_name, queue_id);
1359 message = qmgr_message_create(queue_name, queue_id, qflags);
1365 #define QMGR_LOCK_MODE (MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT)
1367 if (qmgr_message_open(message) < 0) {
1372 msg_info(
"%s: skipped, still being delivered", queue_id);
1373 qmgr_message_close(message);
1377 if (qmgr_message_read(message) < 0) {
1378 qmgr_message_close(message);
1402 msg_fatal(
"%s: %s: remove %s %s: %m", myname,
1404 qmgr_message_sort(message);
1405 qmgr_message_resolve(message);
1406 qmgr_message_sort(message);
1407 qmgr_message_assign(message);
1408 qmgr_message_close(message);
1417 const char *myname =
"qmgr_message_realloc";
1432 if (qmgr_message_open(message) < 0)
1434 if (qmgr_message_read(message) < 0) {
1435 qmgr_message_close(message);
1438 qmgr_message_sort(message);
1439 qmgr_message_resolve(message);
1440 qmgr_message_sort(message);
1441 qmgr_message_assign(message);
1442 qmgr_message_close(message);
#define LIMIT_OK(limit, count)
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)
#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
#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
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 FILTER_WITHOUT_NEXTHOP(filter, next)
#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_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
#define RESOLVE_FLAG_ERROR
QMGR_TRANSPORT * qmgr_transport_find(const char *)
#define REC_TYPE_DSN_ORCPT
void resolve_clnt_init(RESOLVE_REPLY *reply)
#define RCPT_WITHOUT_DOMAIN(rcpt, next)
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,...)
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 REC_TYPE_WARN_ARG(tv)
#define MAIL_ATTR_LOG_IDENT
#define MAIL_ATTR_LOG_CLIENT_ADDR
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_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 QMGR_REDIRECT(rp, tp, np)
#define vstream_fileno(vp)
#define resolve_clnt_query_from(f, a, r)
struct QMGR_QUEUE * queue
#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)
#define REC_TYPE_TIME_SCAN(cp, tv)
#define DEL_REQ_FLAG_REC_DLY_SENT
#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,...)