Ejemplo n.º 1
0
int     bounce_workaround(LOCAL_STATE state)
{
    const char *myname = "bounce_workaround";
    VSTRING *canon_owner = 0;
    int     rcpt_stat;

    /*
     * Look up the substitute sender address.
     */
    if (var_ownreq_special) {
	char   *stripped_recipient;
	char   *owner_alias;
	const char *owner_expansion;

#define FIND_OWNER(lhs, rhs, addr) { \
	lhs = concatenate("owner-", addr, (char *) 0); \
	(void) split_at_right(lhs, '@'); \
	rhs = maps_find(alias_maps, lhs, DICT_FLAG_NONE); \
    }

	FIND_OWNER(owner_alias, owner_expansion, state.msg_attr.rcpt.address);
	if (alias_maps->error == 0 && owner_expansion == 0
	    && (stripped_recipient = strip_addr(state.msg_attr.rcpt.address,
						(char **) 0,
						var_rcpt_delim)) != 0) {
	    myfree(owner_alias);
	    FIND_OWNER(owner_alias, owner_expansion, stripped_recipient);
	    myfree(stripped_recipient);
	}
	if (alias_maps->error == 0 && owner_expansion != 0) {
	    canon_owner = canon_addr_internal(vstring_alloc(10),
					      var_exp_own_alias ?
					      owner_expansion : owner_alias);
	    SET_OWNER_ATTR(state.msg_attr, STR(canon_owner), state.level);
	}
	myfree(owner_alias);
	if (alias_maps->error != 0)
	    /* At this point, canon_owner == 0. */
	    return (defer_append(BOUNCE_FLAGS(state.request),
				 BOUNCE_ATTR(state.msg_attr)));
    }

    /*
     * Send a delivery status notification with a single recipient to the
     * substitute sender address, before completion of the delivery request.
     */
    if (canon_owner) {
	rcpt_stat = bounce_one(BOUNCE_FLAGS(state.request),
			       BOUNCE_ONE_ATTR(state.msg_attr));
	vstring_free(canon_owner);
    }

    /*
     * Send a regular delivery status notification, after completion of the
     * delivery request.
     */
    else {
	rcpt_stat = bounce_append(BOUNCE_FLAGS(state.request),
				  BOUNCE_ATTR(state.msg_attr));
    }
    return (rcpt_stat);
}
Ejemplo n.º 2
0
const char *mail_addr_find(MAPS *path, const char *address, char **extp)
{
    const char *myname = "mail_addr_find";
    const char *result;
    char   *ratsign = 0;
    char   *full_key;
    char   *bare_key;
    char   *saved_ext;
    int     rc = 0;

    /*
     * Initialize.
     */
    full_key = mystrdup(address);
    if (*var_rcpt_delim == 0) {
	bare_key = saved_ext = 0;
    } else {
	bare_key = strip_addr(full_key, &saved_ext, *var_rcpt_delim);
    }

    /*
     * Try user+foo@domain and user@domain.
     * 
     * Specify what keys are partial or full, to avoid matching partial
     * addresses with regular expressions.
     */
#define FULL	0
#define PARTIAL	DICT_FLAG_FIXED

    if ((result = maps_find(path, full_key, FULL)) == 0 && path->error == 0
      && bare_key != 0 && (result = maps_find(path, bare_key, PARTIAL)) != 0
	&& extp != 0) {
	*extp = saved_ext;
	saved_ext = 0;
    }

    /*
     * Try user+foo@$myorigin, user+foo@$mydestination or
     * user+foo@[${proxy,inet}_interfaces]. Then try with +foo stripped off.
     */
    if (result == 0 && path->error == 0
	&& (ratsign = strrchr(full_key, '@')) != 0
	&& (strcasecmp(ratsign + 1, var_myorigin) == 0
	    || (rc = resolve_local(ratsign + 1)) > 0)) {
	*ratsign = 0;
	result = maps_find(path, full_key, PARTIAL);
	if (result == 0 && path->error == 0 && bare_key != 0) {
	    if ((ratsign = strrchr(bare_key, '@')) == 0)
		msg_panic("%s: bare key botch", myname);
	    *ratsign = 0;
	    if ((result = maps_find(path, bare_key, PARTIAL)) != 0 && extp != 0) {
		*extp = saved_ext;
		saved_ext = 0;
	    }
	}
	*ratsign = '@';
    } else if (rc < 0)
	path->error = rc;

    /*
     * Try @domain.
     */
    if (result == 0 && path->error == 0 && ratsign)
	result = maps_find(path, ratsign, PARTIAL);

    /*
     * Clean up.
     */
    if (msg_verbose)
	msg_info("%s: %s -> %s", myname, address,
		 result ? result :
		 path->error ? "(try again)" :
		 "(not found)");
    myfree(full_key);
    if (bare_key)
	myfree(bare_key);
    if (saved_ext)
	myfree(saved_ext);

    return (result);
}
Ejemplo n.º 3
0
int     transport_lookup(TRANSPORT_INFO *tp, const char *addr,
			         const char *rcpt_domain,
			         VSTRING *channel, VSTRING *nexthop)
{
    char   *stripped_addr;
    char   *ratsign = 0;
    const char *name;
    const char *next;
    int     found;

#define STREQ(x,y)	(strcmp((x), (y)) == 0)
#define DISCARD_EXTENSION ((char **) 0)

    /*
     * The null recipient is rewritten to the local mailer daemon address.
     */
    if (*addr == 0) {
	msg_warn("transport_lookup: null address - skipping table lookup");
	return (NOTFOUND);
    }

    /*
     * Look up the full address with the FULL flag to include regexp maps in
     * the query.
     */
    if ((ratsign = strrchr(addr, '@')) == 0 || ratsign[1] == 0)
	msg_panic("transport_lookup: bad address: \"%s\"", addr);

    if (find_transport_entry(tp, addr, rcpt_domain, FULL, channel, nexthop))
	return (FOUND);
    if (tp->transport_path->error != 0)
	return (NOTFOUND);

    /*
     * If the full address did not match, and there is an address extension,
     * look up the stripped address with the PARTIAL flag to avoid matching
     * partial lookup keys with regular expressions.
     */
    if ((stripped_addr = strip_addr(addr, DISCARD_EXTENSION,
				    var_rcpt_delim)) != 0) {
	found = find_transport_entry(tp, stripped_addr, rcpt_domain, PARTIAL,
				     channel, nexthop);

	myfree(stripped_addr);
	if (found)
	    return (FOUND);
	if (tp->transport_path->error != 0)
	    return (NOTFOUND);
    }

    /*
     * If the full and stripped address lookup fails, try domain name lookup.
     * 
     * Keep stripping domain components until nothing is left or until a
     * matching entry is found.
     * 
     * After checking the full domain name, check for .upper.domain, to
     * distinguish between the parent domain and it's decendants, a la
     * sendmail and tcp wrappers.
     * 
     * Before changing the DB lookup result, make a copy first, in order to
     * avoid DB cache corruption.
     * 
     * Specify that the lookup key is partial, to avoid matching partial keys
     * with regular expressions.
     */
    for (name = ratsign + 1; *name != 0; name = next) {
	if (find_transport_entry(tp, name, rcpt_domain, PARTIAL, channel, nexthop))
	    return (FOUND);
	if (tp->transport_path->error != 0)
	    return (NOTFOUND);
	if ((next = strchr(name + 1, '.')) == 0)
	    break;
	if (transport_match_parent_style == MATCH_FLAG_PARENT)
	    next++;
    }

    /*
     * Fall back to the wild-card entry.
     */
    if (tp->wildcard_errno || event_time() > tp->expire)
	transport_wildcard_init(tp);
    if (tp->wildcard_errno) {
	tp->transport_path->error = tp->wildcard_errno;
	return (NOTFOUND);
    } else if (tp->wildcard_channel) {
	update_entry(STR(tp->wildcard_channel), STR(tp->wildcard_nexthop),
		     rcpt_domain, channel, nexthop);
	return (FOUND);
    }

    /*
     * We really did not find it.
     */
    return (NOTFOUND);
}