]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-lda: mail-deliver - Move common part of the error handling to mail_deliver()...
authorStephan Bosch <stephan.bosch@open-xchange.com>
Wed, 15 Apr 2020 18:43:13 +0000 (20:43 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Mon, 4 May 2020 13:11:49 +0000 (13:11 +0000)
Before, much of that was handled by the respective callers (LDA and LMTP).

src/lda/main.c
src/lib-lda/mail-deliver.c
src/lib-lda/mail-deliver.h
src/lmtp/lmtp-local.c

index 12cdc559eb7be376704c2ad8f6d20b0d1e417340..1fa2152c68b42a4035c4f7b1476f853d834ea53f 100644 (file)
@@ -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 */
index 68a98123e3f40b78d2f8388083fb3c576d67412f..52f28627d090d53fd3b1a75c50837d9027fe4226 100644 (file)
@@ -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;
 }
 
index 84e7f95ac6ea5d8240550837cbb3ba1c3c40efb5..066287f13d68c8e13d528d3a55a622d50250afd7 100644 (file)
@@ -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. */
index cea2c06fc0d792e443bd002a3e0b456c001d69b8..bebb60469b4dbd8f59102f626ec8952a8edf137a 100644 (file)
@@ -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;
 }