cleanup_envelope.c [plain text]
#include <sys_defs.h>
#include <string.h>
#include <stdlib.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
#include <msg.h>
#include <vstring.h>
#include <vstream.h>
#include <mymalloc.h>
#include <stringops.h>
#include <nvtable.h>
#include <record.h>
#include <rec_type.h>
#include <cleanup_user.h>
#include <qmgr_user.h>
#include <mail_params.h>
#include <verp_sender.h>
#include "cleanup.h"
#define STR vstring_str
static void cleanup_envelope_process(CLEANUP_STATE *, int, const char *, int);
void cleanup_envelope(CLEANUP_STATE *state, int type,
const char *str, int len)
{
cleanup_out_format(state, REC_TYPE_SIZE, REC_TYPE_SIZE_FORMAT,
(REC_TYPE_SIZE_CAST1) 0,
(REC_TYPE_SIZE_CAST2) 0,
(REC_TYPE_SIZE_CAST3) 0,
(REC_TYPE_SIZE_CAST4) 0);
state->action = cleanup_envelope_process;
cleanup_envelope_process(state, type, str, len);
}
static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
const char *buf, int len)
{
char *attr_name;
char *attr_value;
const char *error_text;
int extra_opts;
if (msg_verbose)
msg_info("initial envelope %c %.*s", type, len, buf);
if (type == REC_TYPE_FLGS) {
extra_opts = atol(buf);
if (extra_opts & ~CLEANUP_FLAG_MASK_EXTRA)
msg_warn("%s: ignoring bad extra flags: 0x%x",
state->queue_id, extra_opts);
else
state->flags |= extra_opts;
return;
}
if (strchr(REC_TYPE_ENVELOPE, type) == 0) {
msg_warn("%s: message rejected: unexpected record type %d in envelope",
state->queue_id, type);
state->errs |= CLEANUP_STAT_BAD;
return;
}
if ((state->flags & CLEANUP_FLAG_INRCPT) == 0
&& strchr(REC_TYPE_ENV_RECIPIENT, type) != 0) {
if (state->sender == 0) {
msg_warn("%s: message rejected: missing sender envelope record",
state->queue_id);
state->errs |= CLEANUP_STAT_BAD;
return;
}
if (state->time == 0) {
msg_warn("%s: message rejected: missing time envelope record",
state->queue_id);
state->errs |= CLEANUP_STAT_BAD;
return;
}
if ((state->flags & CLEANUP_FLAG_WARN_SEEN) == 0
&& var_delay_warn_time > 0) {
cleanup_out_format(state, REC_TYPE_WARN, REC_TYPE_WARN_FORMAT,
(long) state->time + var_delay_warn_time);
}
state->flags |= CLEANUP_FLAG_INRCPT;
}
if (type == REC_TYPE_RCPT) {
if (state->sender == 0) {
msg_warn("%s: message rejected: envelope recipient precedes sender",
state->queue_id);
state->errs |= CLEANUP_STAT_BAD;
return;
}
if (state->orig_rcpt == 0)
state->orig_rcpt = mystrdup(buf);
cleanup_addr_recipient(state, buf);
myfree(state->orig_rcpt);
state->orig_rcpt = 0;
return;
}
if (type == REC_TYPE_DONE) {
if (state->orig_rcpt != 0) {
myfree(state->orig_rcpt);
state->orig_rcpt = 0;
}
return;
}
if (state->orig_rcpt != 0) {
msg_warn("%s: ignoring out-of-order original recipient record <%.200s>",
state->queue_id, state->orig_rcpt);
myfree(state->orig_rcpt);
state->orig_rcpt = 0;
}
if (type == REC_TYPE_ORCP) {
state->orig_rcpt = mystrdup(buf);
return;
}
if (type == REC_TYPE_MESG) {
state->action = cleanup_message;
state->flags &= ~CLEANUP_FLAG_INRCPT;
return;
}
if (state->flags & CLEANUP_FLAG_INRCPT)
state->qmgr_opts |= QMGR_READ_FLAG_MIXED_RCPT_OTHER;
if (type == REC_TYPE_SIZE)
return;
if (type == REC_TYPE_TIME) {
if (state->time == 0) {
state->time = atol(buf);
cleanup_out(state, type, buf, len);
}
return;
}
if (type == REC_TYPE_FULL) {
if (state->fullname == 0) {
state->fullname = mystrdup(buf);
cleanup_out(state, type, buf, len);
}
return;
}
if (type == REC_TYPE_FROM) {
if (state->sender != 0) {
msg_warn("%s: message rejected: multiple envelope sender records",
state->queue_id);
state->errs |= CLEANUP_STAT_BAD;
return;
}
cleanup_addr_sender(state, buf);
return;
}
if (type == REC_TYPE_WARN) {
if ((state->flags & CLEANUP_FLAG_WARN_SEEN) == 0) {
state->flags |= CLEANUP_FLAG_WARN_SEEN;
cleanup_out(state, type, buf, len);
}
return;
}
if (type == REC_TYPE_ATTR) {
char *sbuf;
if (state->attr->used >= var_qattr_count_limit) {
msg_warn("%s: message rejected: attribute count exceeds limit %d",
state->queue_id, var_qattr_count_limit);
state->errs |= CLEANUP_STAT_BAD;
return;
}
sbuf = mystrdup(buf);
if ((error_text = split_nameval(sbuf, &attr_name, &attr_value)) != 0) {
msg_warn("%s: message rejected: malformed attribute: %s: %.100s",
state->queue_id, error_text, buf);
state->errs |= CLEANUP_STAT_BAD;
myfree(sbuf);
return;
}
nvtable_update(state->attr, attr_name, attr_value);
myfree(sbuf);
cleanup_out(state, type, buf, len);
return;
} else {
cleanup_out(state, type, buf, len);
return;
}
}