Beispiel #1
0
void    cleanup_extracted_process(CLEANUP_STATE *state, int type,
				          const char *buf, ssize_t len)
{
    const char *myname = "cleanup_extracted_process";
    const char *encoding;
    char   *attr_name;
    char   *attr_value;
    const char *error_text;
    int     extra_opts;
    int     junk;

#ifdef DELAY_ACTION
    int     defer_delay;

#endif

    if (msg_verbose)
	msg_info("extracted envelope %c %.*s", type, (int) len, buf);

    if (type == REC_TYPE_FLGS) {
	/* Not part of queue file format. */
	extra_opts = atoi(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;
    }
#ifdef DELAY_ACTION
    if (type == REC_TYPE_DELAY) {
	/* Not part of queue file format. */
	defer_delay = atoi(buf);
	if (defer_delay <= 0)
	    msg_warn("%s: ignoring bad delay time: %s", state->queue_id, buf);
	else
	    state->defer_delay = defer_delay;
	return;
    }
#endif

    if (strchr(REC_TYPE_EXTRACT, type) == 0) {
	msg_warn("%s: message rejected: "
		 "unexpected record type %d in extracted envelope",
		 state->queue_id, type);
	state->errs |= CLEANUP_STAT_BAD;
	return;
    }

    /*
     * Map DSN attribute name to pseudo record type so that we don't have to
     * pollute the queue file with records that are incompatible with past
     * Postfix versions. Preferably, people should be able to back out from
     * an upgrade without losing mail.
     */
    if (type == REC_TYPE_ATTR) {
	vstring_strcpy(state->attr_buf, buf);
	error_text = split_nameval(STR(state->attr_buf), &attr_name, &attr_value);
	if (error_text != 0) {
	    msg_warn("%s: message rejected: malformed attribute: %s: %.100s",
		     state->queue_id, error_text, buf);
	    state->errs |= CLEANUP_STAT_BAD;
	    return;
	}
	/* Zero-length values are place holders for unavailable values. */
	if (*attr_value == 0) {
	    msg_warn("%s: spurious null attribute value for \"%s\" -- ignored",
		     state->queue_id, attr_name);
	    return;
	}
	if ((junk = rec_attr_map(attr_name)) != 0) {
	    buf = attr_value;
	    type = junk;
	}
    }

    /*
     * On the transition from non-recipient records to recipient records,
     * emit optional information from header/body content.
     */
    if ((state->flags & CLEANUP_FLAG_INRCPT) == 0
	&& strchr(REC_TYPE_EXT_RECIPIENT, type) != 0) {
	if (state->filter != 0)
	    cleanup_out_string(state, REC_TYPE_FILT, state->filter);
	if (state->redirect != 0)
	    cleanup_out_string(state, REC_TYPE_RDR, state->redirect);
	if ((encoding = nvtable_find(state->attr, MAIL_ATTR_ENCODING)) != 0)
	    cleanup_out_format(state, REC_TYPE_ATTR, "%s=%s",
			       MAIL_ATTR_ENCODING, encoding);
	state->flags |= CLEANUP_FLAG_INRCPT;
	/* Make room to append more meta records. */
	if (state->milters || cleanup_milters) {
	    if ((state->append_meta_pt_offset = vstream_ftell(state->dst)) < 0)
		msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path);
	    cleanup_out_format(state, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT, 0L);
	    if ((state->append_meta_pt_target = vstream_ftell(state->dst)) < 0)
		msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path);
	}
    }

    /*
     * Extracted envelope recipient record processing.
     */
    if (type == REC_TYPE_RCPT) {
	if (state->sender == 0) {		/* protect showq */
	    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);
	if (cleanup_milters != 0
	    && state->milters == 0
	    && CLEANUP_MILTER_OK(state))
	    cleanup_milter_emul_rcpt(state, cleanup_milters, state->recip);
	myfree(state->orig_rcpt);
	state->orig_rcpt = 0;
	if (state->dsn_orcpt != 0) {
	    myfree(state->dsn_orcpt);
	    state->dsn_orcpt = 0;
	}
	state->dsn_notify = 0;
	return;
    }
    if (type == REC_TYPE_DONE || type == REC_TYPE_DRCP) {
	if (state->orig_rcpt != 0) {
	    myfree(state->orig_rcpt);
	    state->orig_rcpt = 0;
	}
	if (state->dsn_orcpt != 0) {
	    myfree(state->dsn_orcpt);
	    state->dsn_orcpt = 0;
	}
	state->dsn_notify = 0;
	return;
    }
    if (type == REC_TYPE_DSN_ORCPT) {
	if (state->dsn_orcpt) {
	    msg_warn("%s: ignoring out-of-order DSN original recipient record <%.200s>",
		     state->queue_id, state->dsn_orcpt);
	    myfree(state->dsn_orcpt);
	}
	state->dsn_orcpt = mystrdup(buf);
	return;
    }
    if (type == REC_TYPE_DSN_NOTIFY) {
	if (state->dsn_notify) {
	    msg_warn("%s: ignoring out-of-order DSN notify record <%d>",
		     state->queue_id, state->dsn_notify);
	    state->dsn_notify = 0;
	}
	if (!alldig(buf) || (junk = atoi(buf)) == 0 || DSN_NOTIFY_OK(junk) == 0)
	    msg_warn("%s: ignoring malformed dsn notify record <%.200s>",
		     state->queue_id, buf);
	else
	    state->qmgr_opts |=
		QMGR_READ_FLAG_FROM_DSN(state->dsn_notify = junk);
	return;
    }
    if (type == REC_TYPE_ORCP) {
	if (state->orig_rcpt != 0) {
	    msg_warn("%s: ignoring out-of-order original recipient record <%.200s>",
		     state->queue_id, buf);
	    myfree(state->orig_rcpt);
	}
	state->orig_rcpt = mystrdup(buf);
	return;
    }
    if (type == REC_TYPE_END) {
	/* Make room to append recipient. */
	if ((state->milters || cleanup_milters)
	    && state->append_rcpt_pt_offset < 0) {
	    if ((state->append_rcpt_pt_offset = vstream_ftell(state->dst)) < 0)
		msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path);
	    cleanup_out_format(state, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT, 0L);
	    if ((state->append_rcpt_pt_target = vstream_ftell(state->dst)) < 0)
		msg_fatal("%s: vstream_ftell %s: %m:", myname, cleanup_path);
	}
	state->flags &= ~CLEANUP_FLAG_INRCPT;
	state->flags |= CLEANUP_FLAG_END_SEEN;
	cleanup_extracted_finish(state);
	return;
    }

    /*
     * Extracted envelope non-recipient record processing.
     */
    if (state->flags & CLEANUP_FLAG_INRCPT)
	/* Tell qmgr that recipient records are mixed with other information. */
	state->qmgr_opts |= QMGR_READ_FLAG_MIXED_RCPT_OTHER;
    cleanup_out(state, type, buf, len);
    return;
}
Beispiel #2
0
void    cleanup_extracted_process(CLEANUP_STATE *state, int type,
				          const char *buf, int len)
{
    const char *encoding;
    const char generated_by_cleanup[] = {
	REC_TYPE_FILT, REC_TYPE_RDR, REC_TYPE_ATTR,
	REC_TYPE_RRTO, REC_TYPE_ERTO, 0,
    };

    if (msg_verbose)
	msg_info("extracted envelope %c %.*s", type, len, buf);

    if (strchr(REC_TYPE_EXTRACT, type) == 0) {
	msg_warn("%s: message rejected: "
		 "unexpected record type %d in extracted envelope",
		 state->queue_id, type);
	state->errs |= CLEANUP_STAT_BAD;
	return;
    }

    /*
     * On the transition from non-recipient records to recipient records,
     * emit optional information from header/body content.
     */
    if ((state->flags & CLEANUP_FLAG_INRCPT) == 0
	&& strchr(REC_TYPE_EXT_RECIPIENT, type) != 0) {
	if (state->filter != 0)
	    cleanup_out_string(state, REC_TYPE_FILT, state->filter);
	if (state->redirect != 0)
	    cleanup_out_string(state, REC_TYPE_RDR, state->redirect);
	if ((encoding = nvtable_find(state->attr, MAIL_ATTR_ENCODING)) != 0)
	    cleanup_out_format(state, REC_TYPE_ATTR, "%s=%s",
			       MAIL_ATTR_ENCODING, encoding);
	if (state->return_receipt)
	    cleanup_out_string(state, REC_TYPE_RRTO, state->return_receipt);
	if (state->errors_to)
	    cleanup_out_string(state, REC_TYPE_ERTO, state->errors_to);
	state->flags |= CLEANUP_FLAG_INRCPT;
    }

    /*
     * Extracted envelope recipient record processing.
     */
    if (type == REC_TYPE_RCPT) {
	if (state->sender == 0) {		/* protect showq */
	    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) {
	/* REC_TYPE_ORCP must be followed by REC_TYPE_RCPT or REC_TYPE DONE. */
	msg_warn("%s: ignoring out-of-order original recipient record <%.200s>",
		 state->queue_id, buf);
	myfree(state->orig_rcpt);
	state->orig_rcpt = 0;
    }
    if (type == REC_TYPE_ORCP) {
	state->orig_rcpt = mystrdup(buf);
	return;
    }
    if (type == REC_TYPE_END) {
	state->flags &= ~CLEANUP_FLAG_INRCPT;
	state->flags |= CLEANUP_FLAG_END_SEEN;
	cleanup_extracted_finish(state);
	return;
    }

    /*
     * Extracted envelope non-recipient record processing.
     */
    if (state->flags & CLEANUP_FLAG_INRCPT)
	/* Tell qmgr that recipient records are mixed with other information. */
	state->qmgr_opts |= QMGR_READ_FLAG_MIXED_RCPT_OTHER;
    if (strchr(generated_by_cleanup, type) != 0) {
	/* Use our own header/body info instead. */
	return;
    } else {
	/* Pass on other non-recipient record. */
	cleanup_out(state, type, buf, len);
	return;
    }
}