From: Stephan Bosch Date: Wed, 15 Apr 2020 18:43:13 +0000 (+0200) Subject: lib-lda: mail-deliver - Move common part of the error handling to mail_deliver()... X-Git-Tag: 2.3.11.2~131 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6dbe714b27535eb873172205fd5635574ac5b524;p=thirdparty%2Fdovecot%2Fcore.git lib-lda: mail-deliver - Move common part of the error handling to mail_deliver() itself. Before, much of that was handled by the respective callers (LDA and LMTP). --- diff --git a/src/lda/main.c b/src/lda/main.c index 12cdc559eb..1fa2152c68 100644 --- a/src/lda/main.c +++ b/src/lda/main.c @@ -226,22 +226,15 @@ lda_set_rcpt_to(struct mail_deliver_input *dinput, static int lda_do_deliver(struct mail_deliver_context *ctx, bool stderr_rejection) { - struct mail_storage *storage; - enum mail_error error_code; + enum mail_deliver_error error_code; const char *error; int ret; - if (mail_deliver(ctx, &storage) >= 0) + if (mail_deliver(ctx, &error_code, &error) >= 0) return EX_OK; - if (ctx->tempfail_error != NULL) { - error = ctx->tempfail_error; - error_code = MAIL_ERROR_TEMP; - } else if (storage != NULL) { - error = mail_storage_get_last_error(storage, &error_code); - } else { + if (error_code == MAIL_DELIVER_ERROR_INTERNAL) { /* This shouldn't happen */ - i_error("BUG: Saving failed to unknown storage"); return EX_TEMPFAIL; } @@ -251,14 +244,22 @@ lda_do_deliver(struct mail_deliver_context *ctx, bool stderr_rejection) fprintf(stderr, "%s\n", error); } - if (error_code != MAIL_ERROR_NOQUOTA || - ctx->set->quota_full_tempfail) { - /* Saving to INBOX should always work unless - we're over quota. If it didn't, it's probably a - configuration problem. */ + switch (error_code) { + case MAIL_DELIVER_ERROR_NONE: + i_unreached(); + case MAIL_DELIVER_ERROR_TEMPORARY: return EX_TEMPFAIL; + case MAIL_DELIVER_ERROR_NOQUOTA: + if (ctx->set->quota_full_tempfail) + return EX_TEMPFAIL; + ctx->mailbox_full = TRUE; + break; + case MAIL_DELIVER_ERROR_INTERNAL: + i_unreached(); } - ctx->mailbox_full = TRUE; + + /* Rejected */ + ctx->dsn = TRUE; /* we'll have to reply with permanent failure */ diff --git a/src/lib-lda/mail-deliver.c b/src/lib-lda/mail-deliver.c index 68a98123e3..52f28627d0 100644 --- a/src/lib-lda/mail-deliver.c +++ b/src/lib-lda/mail-deliver.c @@ -568,11 +568,15 @@ mail_do_deliver(struct mail_deliver_context *ctx, } int mail_deliver(struct mail_deliver_context *ctx, - struct mail_storage **storage_r) + enum mail_deliver_error *error_code_r, + const char **error_r) { struct mail_deliver_user *muser = MAIL_DELIVER_USER_CONTEXT(ctx->rcpt_user); struct event_passthrough *e; + struct mail_storage *storage = NULL; + enum mail_deliver_error error_code = MAIL_DELIVER_ERROR_NONE; + const char *error = NULL; int ret; i_assert(muser->deliver_ctx == NULL); @@ -589,7 +593,28 @@ int mail_deliver(struct mail_deliver_context *ctx, set_name("mail_delivery_started"); e_debug(e->event(), "Local delivery started"); - ret = mail_do_deliver(ctx, storage_r); + ret = mail_do_deliver(ctx, &storage); + + if (ret >= 0) + i_assert(ret == 0); /* ret > 0 has no defined meaning */ + else if (ctx->tempfail_error != NULL) { + error = ctx->tempfail_error; + error_code = MAIL_DELIVER_ERROR_TEMPORARY; + } else if (storage != NULL) { + enum mail_error mail_error; + + error = mail_storage_get_last_error(storage, &mail_error); + if (mail_error == MAIL_ERROR_NOQUOTA) { + error_code = MAIL_DELIVER_ERROR_NOQUOTA; + } else { + error_code = MAIL_DELIVER_ERROR_TEMPORARY; + } + } else { + /* This shouldn't happen */ + e_error(ctx->event, "BUG: Saving failed to unknown storage"); + error = "Temporary internal error"; + error_code = MAIL_DELIVER_ERROR_INTERNAL; + } e = event_create_passthrough(ctx->event)-> set_name("mail_delivery_finished"); @@ -597,6 +622,8 @@ int mail_deliver(struct mail_deliver_context *ctx, muser->deliver_ctx = NULL; + *error_code_r = error_code; + *error_r = error; return ret; } diff --git a/src/lib-lda/mail-deliver.h b/src/lib-lda/mail-deliver.h index 84e7f95ac6..066287f13d 100644 --- a/src/lib-lda/mail-deliver.h +++ b/src/lib-lda/mail-deliver.h @@ -13,6 +13,17 @@ struct mail_storage; struct mail_save_context; struct mailbox; +enum mail_deliver_error { + MAIL_DELIVER_ERROR_NONE = 0, + + /* Temporary error */ + MAIL_DELIVER_ERROR_TEMPORARY, + /* Out of storage quota for mailbox or user */ + MAIL_DELIVER_ERROR_NOQUOTA, + /* Internal error (BUG) */ + MAIL_DELIVER_ERROR_INTERNAL, +}; + struct mail_deliver_session { pool_t pool; @@ -159,7 +170,8 @@ void mail_deliver_deduplicate_guid_if_needed(struct mail_deliver_session *sessio struct mail_save_context *save_ctx); int mail_deliver(struct mail_deliver_context *ctx, - struct mail_storage **storage_r); + enum mail_deliver_error *error_code_r, + const char **error_r); /* Sets the deliver_mail hook and returns the previous hook, which the new_hook should call if it's non-NULL. */ diff --git a/src/lmtp/lmtp-local.c b/src/lmtp/lmtp-local.c index cea2c06fc0..bebb60469b 100644 --- a/src/lmtp/lmtp-local.c +++ b/src/lmtp/lmtp-local.c @@ -540,11 +540,10 @@ lmtp_local_default_do_deliver(struct lmtp_local *local, struct mail_deliver_context *dctx) { struct smtp_server_recipient *rcpt = llrcpt->rcpt->rcpt; - struct mail_storage *storage; - enum mail_error mail_error; + enum mail_deliver_error error_code; const char *error; - if (mail_deliver(dctx, &storage) == 0) { + if (mail_deliver(dctx, &error_code, &error) == 0) { if (dctx->dest_mail != NULL) { i_assert(local->first_saved_mail == NULL); local->first_saved_mail = dctx->dest_mail; @@ -554,23 +553,21 @@ lmtp_local_default_do_deliver(struct lmtp_local *local, return 0; } - if (dctx->tempfail_error != NULL) { - smtp_server_recipient_reply(rcpt, 451, "4.2.0", "%s", - dctx->tempfail_error); - } else if (storage != NULL) { - error = mail_storage_get_last_error(storage, &mail_error); - if (mail_error == MAIL_ERROR_NOQUOTA) { - lmtp_local_rcpt_reply_overquota(llrcpt, error); - } else { - smtp_server_recipient_reply(rcpt, 451, "4.2.0", "%s", - error); - } - } else { + switch (error_code) { + case MAIL_DELIVER_ERROR_NONE: + i_unreached(); + case MAIL_DELIVER_ERROR_TEMPORARY: + smtp_server_recipient_reply(rcpt, 451, "4.2.0", "%s", error); + break; + case MAIL_DELIVER_ERROR_NOQUOTA: + lmtp_local_rcpt_reply_overquota(llrcpt, error); + break; + case MAIL_DELIVER_ERROR_INTERNAL: /* This shouldn't happen */ - e_error(rcpt->event, "BUG: Saving failed to unknown storage"); - smtp_server_recipient_reply(rcpt, 451, "4.3.0", - "Temporary internal error"); + smtp_server_recipient_reply(rcpt, 451, "4.3.0", "%s", error); + break; } + return -1; }