From: Stephan Bosch Date: Sun, 17 Sep 2017 00:11:58 +0000 (+0200) Subject: lmtp: Moved cmd_rcpt_finish() from commands.c to lmtp-local.c. X-Git-Tag: 2.3.0.rc1~235 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d2e367e199368932c02a306ddedbc7566553a15;p=thirdparty%2Fdovecot%2Fcore.git lmtp: Moved cmd_rcpt_finish() from commands.c to lmtp-local.c. --- diff --git a/src/lmtp/commands.c b/src/lmtp/commands.c index 5af5a456f8..c924cd18f4 100644 --- a/src/lmtp/commands.c +++ b/src/lmtp/commands.c @@ -21,7 +21,6 @@ #include "master-service-ssl.h" #include "iostream-ssl.h" #include "rfc822-parser.h" -#include "smtp-address.h" #include "message-date.h" #include "message-address.h" #include "auth-master.h" @@ -31,6 +30,7 @@ #include "lda-settings.h" #include "lmtp-settings.h" #include "mail-autoexpunge.h" +#include "lmtp-local.h" #include "mail-namespace.h" #include "mail-deliver.h" #include "message-address.h" @@ -388,89 +388,6 @@ static bool client_proxy_rcpt(struct client *client, return TRUE; } -static void -client_send_line_overquota(struct client *client, - const struct mail_recipient *rcpt, const char *error) -{ - struct lda_settings *lda_set = - mail_storage_service_user_get_set(rcpt->service_user)[2]; - - client_send_line(client, "%s <%s> %s", - lda_set->quota_full_tempfail ? "452 4.2.2" : "552 5.2.2", - smtp_address_encode(rcpt->address), error); -} - -static int -lmtp_rcpt_to_is_over_quota(struct client *client, - const struct mail_recipient *rcpt) -{ - struct mail_user *user; - struct mail_namespace *ns; - struct mailbox *box; - struct mailbox_status status; - const char *errstr; - enum mail_error error; - int ret; - - if (!client->lmtp_set->lmtp_rcpt_check_quota) - return 0; - - /* mail user will be created second time when mail is saved, - so it's session_id needs to be different, - but second time session_id needs to be the same as rcpt session_id and - mail user session id for the first rcpt should not overlap with session id - of the second recipient, so add custom ":quota" suffix to the session_id without - session_id counter increment, so next time mail user will get - the same session id as rcpt */ - ret = mail_storage_service_next_with_session_suffix(storage_service, - rcpt->service_user, - "quota", - &user, &errstr); - - if (ret < 0) { - i_error("Failed to initialize user %s: %s", - smtp_address_encode(rcpt->address), errstr); - return -1; - } - - ns = mail_namespace_find_inbox(user->namespaces); - box = mailbox_alloc(ns->list, "INBOX", 0); - mailbox_set_reason(box, "over-quota check"); - ret = mailbox_get_status(box, STATUS_CHECK_OVER_QUOTA, &status); - if (ret < 0) { - errstr = mailbox_get_last_error(box, &error); - if (error == MAIL_ERROR_NOQUOTA) { - client_send_line_overquota(client, rcpt, errstr); - ret = 1; - } else { - i_error("mailbox_get_status(%s, STATUS_CHECK_OVER_QUOTA) " - "failed: %s", - mailbox_get_vname(box), - mailbox_get_last_internal_error(box, NULL)); - } - } - mailbox_free(&box); - mail_user_unref(&user); - return ret; -} - -static bool cmd_rcpt_finish(struct client *client, struct mail_recipient *rcpt) -{ - int ret; - - if ((ret = lmtp_rcpt_to_is_over_quota(client, rcpt)) != 0) { - if (ret < 0) { - client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL, - smtp_address_encode(rcpt->address)); - } - mail_storage_service_user_unref(&rcpt->service_user); - return FALSE; - } - array_append(&client->state.rcpt_to, &rcpt, 1); - client_send_line(client, "250 2.1.5 OK"); - return TRUE; -} - static void rcpt_anvil_lookup_callback(const char *reply, void *context) { struct mail_recipient *rcpt = context; diff --git a/src/lmtp/lmtp-local.c b/src/lmtp/lmtp-local.c index d5d926c07c..7b86925549 100644 --- a/src/lmtp/lmtp-local.c +++ b/src/lmtp/lmtp-local.c @@ -1,13 +1,20 @@ /* Copyright (c) 2009-2017 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "array.h" #include "hostpid.h" #include "mail-storage.h" #include "mail-storage-service.h" #include "master-service.h" +#include "smtp-address.h" +#include "lda-settings.h" +#include "lmtp-settings.h" #include "client.h" +#include "main.h" #include "lmtp-local.h" +#define ERRSTR_TEMP_MAILBOX_FAIL "451 4.3.0 <%s> Temporary internal error" + void client_rcpt_anvil_disconnect(const struct mail_recipient *rcpt) { const struct mail_storage_service_input *input; @@ -21,4 +28,84 @@ void client_rcpt_anvil_disconnect(const struct mail_recipient *rcpt) "/", input->username, "\n", NULL)); } +void client_send_line_overquota(struct client *client, + const struct mail_recipient *rcpt, const char *error) +{ + struct lda_settings *lda_set = + mail_storage_service_user_get_set(rcpt->service_user)[2]; + + client_send_line(client, "%s <%s> %s", + lda_set->quota_full_tempfail ? "452 4.2.2" : "552 5.2.2", + smtp_address_encode(rcpt->address), error); +} + +static int +lmtp_rcpt_to_is_over_quota(struct client *client, + const struct mail_recipient *rcpt) +{ + struct mail_user *user; + struct mail_namespace *ns; + struct mailbox *box; + struct mailbox_status status; + const char *errstr; + enum mail_error error; + int ret; + + if (!client->lmtp_set->lmtp_rcpt_check_quota) + return 0; + + /* mail user will be created second time when mail is saved, + so it's session_id needs to be different, + but second time session_id needs to be the same as rcpt session_id and + mail user session id for the first rcpt should not overlap with session id + of the second recipient, so add custom ":quota" suffix to the session_id without + session_id counter increment, so next time mail user will get + the same session id as rcpt */ + ret = mail_storage_service_next_with_session_suffix(storage_service, + rcpt->service_user, + "quota", + &user, &errstr); + + if (ret < 0) { + i_error("Failed to initialize user %s: %s", + smtp_address_encode(rcpt->address), errstr); + return -1; + } + + ns = mail_namespace_find_inbox(user->namespaces); + box = mailbox_alloc(ns->list, "INBOX", 0); + mailbox_set_reason(box, "over-quota check"); + ret = mailbox_get_status(box, STATUS_CHECK_OVER_QUOTA, &status); + if (ret < 0) { + errstr = mailbox_get_last_error(box, &error); + if (error == MAIL_ERROR_NOQUOTA) { + client_send_line_overquota(client, rcpt, errstr); + ret = 1; + } else { + i_error("mailbox_get_status(%s, STATUS_CHECK_OVER_QUOTA) " + "failed: %s", + mailbox_get_vname(box), + mailbox_get_last_internal_error(box, NULL)); + } + } + mailbox_free(&box); + mail_user_unref(&user); + return ret; +} + +bool cmd_rcpt_finish(struct client *client, struct mail_recipient *rcpt) +{ + int ret; + if ((ret = lmtp_rcpt_to_is_over_quota(client, rcpt)) != 0) { + if (ret < 0) { + client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL, + smtp_address_encode(rcpt->address)); + } + mail_storage_service_user_unref(&rcpt->service_user); + return FALSE; + } + array_append(&client->state.rcpt_to, &rcpt, 1); + client_send_line(client, "250 2.1.5 OK"); + return TRUE; +} diff --git a/src/lmtp/lmtp-local.h b/src/lmtp/lmtp-local.h index aee5a05e1a..2e172266cc 100644 --- a/src/lmtp/lmtp-local.h +++ b/src/lmtp/lmtp-local.h @@ -1,8 +1,14 @@ #ifndef LMTP_LOCAL_H #define LMTP_LOCAL_H +struct client; struct mail_recipient; void client_rcpt_anvil_disconnect(const struct mail_recipient *rcpt); +void client_send_line_overquota(struct client *client, + const struct mail_recipient *rcpt, const char *error); + +bool cmd_rcpt_finish(struct client *client, struct mail_recipient *rcpt); + #endif