Skip to content

Commit

Permalink
lmtp: commands: Moved RCPT command handling relating to local recipie…
Browse files Browse the repository at this point in the history
…nts to lmtp-local.c.
  • Loading branch information
stephanbosch committed Dec 7, 2017
1 parent 70dfae6 commit bc1306f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 75 deletions.
71 changes: 1 addition & 70 deletions src/lmtp/commands.c
Expand Up @@ -4,7 +4,6 @@
#include "ioloop.h"
#include "array.h"
#include "str.h"
#include "strescape.h"
#include "istream.h"
#include "istream-concat.h"
#include "ostream.h"
Expand Down Expand Up @@ -186,13 +185,11 @@ int cmd_mail(struct client *client, const char *args)
int cmd_rcpt(struct client *client, const char *args)
{
struct lmtp_recipient *rcpt;
struct mail_storage_service_input input;
struct smtp_address *address;
const char *username, *detail;
enum smtp_param_parse_error pperror;
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");
Expand Down Expand Up @@ -250,73 +247,7 @@ int cmd_rcpt(struct client *client, const char *args)
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);
}

i_zero(&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) {
i_error("Failed to lookup user %s: %s", username, error);
client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL,
smtp_address_encode(address));
return 0;
}
if (ret == 0) {
client_send_line(client,
"550 5.1.1 <%s> User doesn't exist: %s",
smtp_address_encode(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",
smtp_address_encode(address));
mail_storage_service_user_unref(&rcpt->service_user);
return 0;
}

rcpt->address = smtp_address_clone(client->state_pool, address);
rcpt->detail = p_strdup(client->state_pool, detail);

if (client->lmtp_set->lmtp_user_concurrency_limit == 0) {
(void)cmd_rcpt_finish(client, rcpt);
return 0;
} else {
/* NOTE: username may change as the result of the userdb
lookup. Look up the new one via service_user. */
const struct mail_storage_service_input *input =
mail_storage_service_user_get_input(rcpt->service_user);
const char *query = t_strconcat("LOOKUP\t",
master_service_get_name(master_service),
"/", str_tabescape(input->username), NULL);
io_remove(&client->io);
rcpt->anvil_query = anvil_client_query(anvil, query,
rcpt_anvil_lookup_callback, rcpt);
/* stop processing further commands while anvil query is
pending */
return rcpt->anvil_query == NULL ? 0 : -1;
}
return lmtp_local_rcpt(client, rcpt, address, username, detail);
}

/*
Expand Down
85 changes: 83 additions & 2 deletions src/lmtp/lmtp-local.c
Expand Up @@ -2,6 +2,7 @@

#include "lib.h"
#include "str.h"
#include "strescape.h"
#include "array.h"
#include "time-util.h"
#include "hostpid.h"
Expand Down Expand Up @@ -139,7 +140,8 @@ lmtp_local_rcpt_check_quota(struct client *client,
return ret;
}

bool cmd_rcpt_finish(struct client *client, struct lmtp_recipient *rcpt)
static bool
cmd_rcpt_finish(struct client *client, struct lmtp_recipient *rcpt)
{
int ret;

Expand All @@ -156,7 +158,8 @@ bool cmd_rcpt_finish(struct client *client, struct lmtp_recipient *rcpt)
return TRUE;
}

void rcpt_anvil_lookup_callback(const char *reply, void *context)
static void
rcpt_anvil_lookup_callback(const char *reply, void *context)
{
struct lmtp_recipient *rcpt = context;
struct client *client = rcpt->client;
Expand Down Expand Up @@ -187,6 +190,84 @@ void rcpt_anvil_lookup_callback(const char *reply, void *context)
client_input_handle(client);
}

int lmtp_local_rcpt(struct client *client,
struct lmtp_recipient *rcpt,
struct smtp_address *address,
const char *username, const char *detail)
{
struct mail_storage_service_input input;
const char *error = NULL;
int ret;

/* 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);
}

i_zero(&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) {
i_error("Failed to lookup user %s: %s", username, error);
client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL,
smtp_address_encode(address));
return 0;
}
if (ret == 0) {
client_send_line(client,
"550 5.1.1 <%s> User doesn't exist: %s",
smtp_address_encode(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",
smtp_address_encode(address));
mail_storage_service_user_unref(&rcpt->service_user);
return 0;
}

rcpt->address = smtp_address_clone(client->state_pool, address);
rcpt->detail = p_strdup(client->state_pool, detail);

if (client->lmtp_set->lmtp_user_concurrency_limit == 0) {
(void)cmd_rcpt_finish(client, rcpt);
return 0;
} else {
/* NOTE: username may change as the result of the userdb
lookup. Look up the new one via service_user. */
const struct mail_storage_service_input *input =
mail_storage_service_user_get_input(rcpt->service_user);
const char *query = t_strconcat("LOOKUP\t",
master_service_get_name(master_service),
"/", str_tabescape(input->username), NULL);
io_remove(&client->io);
rcpt->anvil_query = anvil_client_query(anvil, query,
rcpt_anvil_lookup_callback, rcpt);
/* stop processing further commands while anvil query is
pending */
return rcpt->anvil_query == NULL ? 0 : -1;
}
}

/*
* DATA command
*/
Expand Down
8 changes: 5 additions & 3 deletions src/lmtp/lmtp-local.h
@@ -1,15 +1,17 @@
#ifndef LMTP_LOCAL_H
#define LMTP_LOCAL_H

struct smtp_address;
struct client;
struct lmtp_recipient;
struct mail_deliver_session;

void lmtp_local_rcpt_deinit(struct lmtp_recipient *rcpt);

bool cmd_rcpt_finish(struct client *client, struct lmtp_recipient *rcpt);

void rcpt_anvil_lookup_callback(const char *reply, void *context);
int lmtp_local_rcpt(struct client *client,
struct lmtp_recipient *rcpt,
struct smtp_address *address,
const char *username, const char *detail);

void lmtp_local_data(struct client *client, struct istream *input);

Expand Down

0 comments on commit bc1306f

Please sign in to comment.