Home / Alt manpages / dovecot-lda(1)

  • dovecot-lda(1)
  • User command
  • linux

Deliver a Test Message Safely with Dovecot LDA

You will deliver one RFC 5322 message to a Dovecot mailbox with dovecot-lda, confirm the result from its exit status, and know where to look when delivery is rejected or falls back to INBOX. The commands target the Dovecot 2.3 command shipped by Ubuntu's dovecot-core package, version 1:2.3.21+dfsg1-2ubuntu6.5 in the checked environment. Allow about 10 minutes if Dovecot and the mailbox already work, longer if you are wiring an MTA transport.

Before you start

Dovecot LDA is a delivery component, not an SMTP server. An MTA normally passes a complete message on standard input and supplies the destination user. A shell test can do the same, but it changes mailbox state immediately. Do not run the examples against a real recipient until you have replaced every placeholder and checked the effective configuration.

You need the dovecot-core package, a configured mailbox location, and permission to deliver as the account or virtual user. On this installation the executable is /usr/lib/dovecot/dovecot-lda; the alias name deliver refers to the same LDA interface in the installed manual, but it is not the path to use here.

1. Check the executable and configuration

Start with a read-only check. The command's built-in usage output is useful because distributions may install the binary outside PATH:

$ command -v /usr/lib/dovecot/dovecot-lda
/usr/lib/dovecot/dovecot-lda
$ /usr/lib/dovecot/dovecot-lda --help
/usr/lib/dovecot/dovecot-lda: invalid option -- '-'
Usage: dovecot-lda [-c <config file>] [-d <username>] [-p <path>]
                   [-m <mailbox>] [-e] [-k] [-f <envelope sender>]
                   [-a <original envelope recipient>]
                   [-r <final envelope recipient>]

This program does not provide a conventional --help option, so the diagnostic above is expected on the checked 2.3.21 binary. For the effective settings, use Dovecot's configuration tool as an administrator:

# doveconf -n
mail_location = maildir:~/Maildir

Check especially mail_location, the user database, and the LDA settings in /etc/dovecot/conf.d/15-lda.conf. The sample configuration uses maildir:~/Maildir, but your system may use mbox, a virtual-user path, or another namespace.

2. Prepare a message without sending it elsewhere

Use a temporary file so the message is visible before delivery. This file is data for LDA, not an SMTP submission, so include the headers and the blank line before the body:

$ umask 077
$ test_mail=$(mktemp)
$ cat > "$test_mail" <<'EOF'
From: [email protected]
To: [email protected]
Subject: Dovecot LDA test
Date: Thu, 01 Jan 1970 00:00:00 +0000
Message-ID: <[email protected]>

This is a local delivery test.
EOF
$ sed -n '1,12p' "$test_mail"
From: [email protected]
To: [email protected]
Subject: Dovecot LDA test
Date: Thu, 01 Jan 1970 00:00:00 +0000
Message-ID: <[email protected]>

This is a local delivery test.

Replace [email protected] with the address your Dovecot user database understands. The .invalid domain is deliberately non-routable; it is safe as a test header, but it is not a substitute for the real local recipient.

3. Deliver to the user's default mailbox

Checkpoint

This is the first state-changing command. It consumes the message into the selected user's mailbox. Run it only after checking the recipient and configuration:

$ /usr/lib/dovecot/dovecot-lda \
    -d '[email protected]' \
    -f '[email protected]' < "$test_mail"
$ status=$?
$ printf 'dovecot-lda exit status: %s\n' "$status"
dovecot-lda exit status: 0

The default destination is INBOX. The -d option asks the user database for the destination user, which is normally needed for virtual users. The -f value is the envelope sender, used when Dovecot needs to construct a rejection message or related delivery metadata. It is not the visible From: header.

Exit status 0 means that LDA accepted the message for delivery. It does not mean that an SMTP conversation occurred. Dovecot updates its mailbox indexes during delivery, which is why delivery should go through LDA rather than writing directly into a Maildir.

4. Select a mailbox deliberately

Use -m when the message belongs somewhere other than INBOX. The name is the mailbox name visible through the configured namespace:

$ /usr/lib/dovecot/dovecot-lda \
    -d '[email protected]' \
    -a '[email protected]' \
    -m 'Alerts' \
    -f '[email protected]' < "$test_mail"
$ printf 'dovecot-lda exit status: %s\n' "$?"
dovecot-lda exit status: 0

Here -a records the destination address, including a plus detail. If Alerts does not exist, LDA does not create it unless lda_mailbox_autocreate = yes is enabled. If saving to the requested mailbox fails for another reason, the installed manual says that LDA delivers to INBOX instead. That fallback can make a superficially successful test look wrong, so verify the actual mailbox in an IMAP client or with a mailbox-aware Dovecot tool.

For a namespace such as INBOX/, use the same separator and visible name that the IMAP client uses. Do not guess filesystem directory names from a Maildir listing.

5. Read failures from the exit status

Capture the status immediately, before another command replaces it. The useful values for this Dovecot 2.3 interface are:

StatusMeaningNext check
0Delivery succeeded.Confirm the message is in the intended mailbox.
64An argument or other parameter was invalid.Compare the command with the usage output and quote values.
75Temporary failure.Read the Dovecot log and check mailbox permissions, storage and indexes.
77Rejection when -e was used.Read stderr and investigate quota or policy before retrying.

For an MTA integration, status 75 normally tells the MTA to retry. Do not turn every non-zero status into a permanent bounce without checking the MTA's delivery contract. The default rejection behaviour is to send a rejection mail; adding -e instead writes the reason to stderr and returns 77. That choice affects how the calling MTA handles policy and quota failures:

$ /usr/lib/dovecot/dovecot-lda -e -d '[email protected]' \
    -f '[email protected]' < "$test_mail"
$ printf 'dovecot-lda exit status: %s\n' "$?"
dovecot-lda exit status: 77

The status and exact rejection text depend on the configured user, quota and plugins. Treat the example's 77 as the expected shape of a rejected delivery, not as a result to force on a healthy mailbox.

6. Use a saved message only when needed

The -p option makes LDA read a path instead of standard input:

$ /usr/lib/dovecot/dovecot-lda \
    -d '[email protected]' \
    -p "$test_mail"
$ printf 'dovecot-lda exit status: %s\n' "$?"
dovecot-lda exit status: 0

With Maildir, Dovecot may hard-link this file into the destination. The installed manual warns that this path currently prevents cache updates, so standard input is the safer default for normal MTA delivery. A hard link also means cleaning up the original file too early can remove an inode reference you still expect to inspect.

Recovery

The examples intentionally create a temporary file and add messages to a mailbox. Remove only the named temporary file when you are finished, and delete the test message through the normal IMAP client or mailbox administration procedure. Do not remove Maildir files by broad wildcard, and do not edit index files by hand.

$ rm -- "$test_mail"
$ test ! -e "$test_mail" && echo 'temporary input removed'
temporary input removed

Done means

  • doveconf -n shows the mailbox location and user lookup you intended.
  • The message was passed as complete input to dovecot-lda, not copied directly into a Maildir.
  • The command returned 0 and the message is visible in the intended mailbox, not merely INBOX.
  • Your MTA integration preserves temporary failures and records LDA stderr in its logs.
  • You understand whether -e is compatible with the MTA's rejection handling before enabling it.