int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr) { const char *myname = "deliver_recipient"; VSTRING *folded; int rcpt_stat; /* * Make verbose logging easier to understand. */ state.level++; if (msg_verbose) MSG_LOG_STATE(myname, state); /* * Set up the recipient-specific attributes. The recipient's lookup * handle is the full address. */ if (state.msg_attr.delivered == 0) state.msg_attr.delivered = state.msg_attr.rcpt.address; folded = vstring_alloc(100); state.msg_attr.user = casefold(folded, state.msg_attr.rcpt.address); /* * Deliver */ if (msg_verbose) deliver_attr_dump(&state.msg_attr); if (deliver_mailbox(state, usr_attr, &rcpt_stat) == 0) rcpt_stat = deliver_unknown(state); /* * Cleanup. */ vstring_free(folded); return (rcpt_stat); }
int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr) { const char *myname = "deliver_recipient"; int rcpt_stat; /* * Make verbose logging easier to understand. */ state.level++; if (msg_verbose) MSG_LOG_STATE(myname, state); /* * Duplicate filter. */ if (been_here(state.dup_filter, "recipient %d %s", state.level, state.msg_attr.rcpt.address)) return (0); /* * With each level of recursion, detect and break external message * forwarding loops. * * If the looping recipient address has an owner- alias, send the error * report there instead. * * XXX A delivery agent cannot change the envelope sender address for * bouncing. As a workaround we use a one-recipient bounce procedure. * * The proper fix would be to record in the bounce logfile an error return * address for each individual recipient. This would also eliminate the * need for VERP specific bouncing code, at the cost of complicating the * normal bounce sending procedure, but would simplify the code below. */ if (delivered_hdr_find(state.loop_info, state.msg_attr.rcpt.address)) { dsb_simple(state.msg_attr.why, "5.4.6", "mail forwarding loop for %s", state.msg_attr.rcpt.address); /* Account for possible owner- sender address override. */ return (bounce_workaround(state)); } /* * Set up the recipient-specific attributes. If this is forwarded mail, * leave the delivered attribute alone, so that the forwarded message * will show the correct forwarding recipient. */ if (state.msg_attr.delivered == 0) state.msg_attr.delivered = state.msg_attr.rcpt.address; state.msg_attr.local = mystrdup(state.msg_attr.rcpt.address); lowercase(state.msg_attr.local); if ((state.msg_attr.domain = split_at_right(state.msg_attr.local, '@')) == 0) msg_warn("no @ in recipient address: %s", state.msg_attr.local); /* * Address extension management. */ state.msg_attr.user = mystrdup(state.msg_attr.local); if (*var_rcpt_delim) { state.msg_attr.extension = split_addr(state.msg_attr.user, *var_rcpt_delim); if (state.msg_attr.extension && strchr(state.msg_attr.extension, '/')) { msg_warn("%s: address with illegal extension: %s", state.msg_attr.queue_id, state.msg_attr.local); state.msg_attr.extension = 0; } } else state.msg_attr.extension = 0; state.msg_attr.unmatched = state.msg_attr.extension; /* * Do not allow null usernames. */ if (state.msg_attr.user[0] == 0) { dsb_simple(state.msg_attr.why, "5.1.3", "null username in \"%s\"", state.msg_attr.rcpt.address); return (bounce_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr))); } /* * Run the recipient through the delivery switch. */ if (msg_verbose) deliver_attr_dump(&state.msg_attr); rcpt_stat = deliver_switch(state, usr_attr); /* * Clean up. */ myfree(state.msg_attr.local); myfree(state.msg_attr.user); return (rcpt_stat); }