Пример #1
0
int cmd_rcpt(struct client *client, const char *args)
{
	struct mail_recipient rcpt;
	struct mail_storage_service_input input;
	const char *address, *username, *detail, *prefix;
	const char *error = NULL;
	int ret = 0;

	client_state_set(client, "RCPT TO");

	if (client->state.mail_from == NULL) {
		client_send_line(client, "503 5.5.1 MAIL needed first");
		return 0;
	}

	if (strncasecmp(args, "TO:", 3) != 0 ||
	    parse_address(args + 3, &address, &args) < 0) {
		client_send_line(client, "501 5.5.4 Invalid parameters");
		return 0;
	}

	memset(&rcpt, 0, sizeof(rcpt));
	address = lmtp_unescape_address(address);

	if (*args != '\0') {
		client_send_line(client, "501 5.5.4 Unsupported options");
		return 0;
	}
	rcpt_address_parse(client, address, &username, &detail);

	if (client->lmtp_set->lmtp_proxy) {
		if (client_proxy_rcpt(client, address, username, detail))
			return 0;
	}

	memset(&input, 0, sizeof(input));
	input.module = input.service = "lmtp";
	input.username = username;
	input.local_ip = client->local_ip;
	input.remote_ip = client->remote_ip;
	input.local_port = client->local_port;
	input.remote_port = client->remote_port;

	ret = mail_storage_service_lookup(storage_service, &input,
					  &rcpt.service_user, &error);

	if (ret < 0) {
		prefix = t_strdup_printf(ERRSTR_TEMP_USERDB_FAIL_PREFIX,
					 username);
		client_send_line(client, "%s%s", prefix, error);
		return 0;
	}
	if (ret == 0) {
		client_send_line(client,
				 "550 5.1.1 <%s> User doesn't exist: %s",
				 address, username);
		return 0;
	}
	if (client->proxy != NULL) {
		/* NOTE: if this restriction is ever removed, we'll also need
		   to send different message bodies to local and proxy
		   (with and without Return-Path: header) */
		client_send_line(client, "451 4.3.0 <%s> "
			"Can't handle mixed proxy/non-proxy destinations",
			address);
		return 0;
	}

	lmtp_address_translate(client, &address);

	rcpt.address = p_strdup(client->state_pool, address);
	rcpt.detail = p_strdup(client->state_pool, detail);
	if ((ret = lmtp_rcpt_to_is_over_quota(client, &rcpt)) < 0) {
		client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL,
				 rcpt.address);
		return 0;
	}
	if (ret == 0) {
		array_append(&client->state.rcpt_to, &rcpt, 1);
		client_send_line(client, "250 2.1.5 OK");
	}
	return 0;
}
Пример #2
0
int cmd_rcpt(struct client *client, const char *args)
{
	struct mail_recipient *rcpt;
	struct mail_storage_service_input input;
	const char *params, *address, *username, *detail, *prefix;
	const char *const *argv;
	const char *error = NULL;
	char delim = '\0';
	int ret = 0;

	if (client->state.mail_from == NULL) {
		client_send_line(client, "503 5.5.1 MAIL needed first");
		return 0;
	}

	if (strncasecmp(args, "TO:", 3) != 0 ||
	    parse_address(args + 3, &address, &params) < 0) {
		client_send_line(client, "501 5.5.4 Invalid parameters");
		return 0;
	}

	rcpt = p_new(client->state_pool, struct mail_recipient, 1);
	rcpt->client = client;
	address = lmtp_unescape_address(address);

	argv = t_strsplit(params, " ");
	for (; *argv != NULL; argv++) {
		if (strncasecmp(*argv, "ORCPT=", 6) == 0) {
			rcpt->params.dsn_orcpt = parse_xtext(client, *argv + 6);
		} else {
			client_send_line(client, "501 5.5.4 Unsupported options");
			return 0;
		}
	}
	rcpt_address_parse(client, address, &username, &delim, &detail);

	client_state_set(client, "RCPT TO", address);

	if (client->lmtp_set->lmtp_proxy) {
		if (client_proxy_rcpt(client, address, username, detail, delim,
				      &rcpt->params))
			return 0;
	}

	/* Use a unique session_id for each mail delivery. This is especially
	   important for stats process to not see duplicate sessions. */
	if (array_count(&client->state.rcpt_to) == 0)
		rcpt->session_id = client->state.session_id;
	else {
		rcpt->session_id =
			p_strdup_printf(client->state_pool, "%s:%u",
					client->state.session_id,
					array_count(&client->state.rcpt_to)+1);
	}

	memset(&input, 0, sizeof(input));
	input.module = input.service = "lmtp";
	input.username = username;
	input.local_ip = client->local_ip;
	input.remote_ip = client->remote_ip;
	input.local_port = client->local_port;
	input.remote_port = client->remote_port;
	input.session_id = rcpt->session_id;

	ret = mail_storage_service_lookup(storage_service, &input,
					  &rcpt->service_user, &error);

	if (ret < 0) {
		prefix = t_strdup_printf(ERRSTR_TEMP_USERDB_FAIL_PREFIX,
					 username);
		client_send_line(client, "%s%s", prefix, error);
		return 0;
	}
	if (ret == 0) {
		client_send_line(client,
				 "550 5.1.1 <%s> User doesn't exist: %s",
				 address, username);
		return 0;
	}
	if (client->proxy != NULL) {
		/* NOTE: if this restriction is ever removed, we'll also need
		   to send different message bodies to local and proxy
		   (with and without Return-Path: header) */
		client_send_line(client, "451 4.3.0 <%s> "
			"Can't handle mixed proxy/non-proxy destinations",
			address);
		mail_storage_service_user_free(&rcpt->service_user);
		return 0;
	}

	lmtp_address_translate(client, &address);

	rcpt->address = p_strdup(client->state_pool, address);
	rcpt->detail = p_strdup(client->state_pool, detail);
	if ((ret = lmtp_rcpt_to_is_over_quota(client, rcpt)) != 0) {
		if (ret < 0) {
			client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL,
					 rcpt->address);
		}
		mail_storage_service_user_free(&rcpt->service_user);
		return 0;
	}
	array_append(&client->state.rcpt_to, &rcpt, 1);
	client_send_line(client, "250 2.1.5 OK");

	if (client->lmtp_set->lmtp_user_concurrency_limit > 0) {
		const char *query = t_strconcat("LOOKUP\t",
			master_service_get_name(master_service),
			"/", str_tabescape(username), NULL);
		client->state.anvil_queries++;
		rcpt->anvil_query = anvil_client_query(anvil, query,
					rcpt_anvil_lookup_callback, rcpt);
	}
	return 0;
}