Skip to content

[Bug]: A recipient list with unclosed angle brackets collapses into one invalid address #794

Description

@brambuijs

What happens

splitRecipients (lib/email-composer-utils.ts) tracks inAngle as a latch: < sets it, only > clears it. A recipient string that opens an angle bracket without closing it stays "inside an address" for the rest of the string, so every separator after that point is kept literal and the whole list collapses into a single entry.

Reproduce

Paste this into the To field:

Ap Reinders <ap@x.com, Erwin Beets <erwin@x.com, jaco@x.com

splitPastedRecipients returns:

valid:   [{ email: "jaco@x.com" }]
invalid: ["Ap", "Reinders", "<ap@x.com,", "Erwin", "Beets", "<erwin@x.com,"]

ap@ and erwin@ are dropped silently. The whitespace fallback tokenizes them with a trailing comma still attached, so isValidEmail rejects them.

Why it reaches the wire

The invalid leftovers are joined back into the input field. commitCurrentInput (components/email/email-composer.tsx) then accepts whatever parseRecipient returns without validating it, so a chip whose email is the entire pasted list goes into Email/set. The server writes it as one mailbox:

To: <Ap Reinders <ap@x.com, Erwin Beets <erwin@x.com, jaco@x.com>, "Erwin Beets" <erwin@x.com>, ...

The envelope recipients are well formed, so RCPT TO succeeds and the relay only rejects at DATA:

host 'smtp.lettermint.co' rejected command 'DATA' with code 550 (0.0.0) 'Invalid To email address'

Every recipient bounces, with an error message that points at the addresses rather than at the header. The addresses are all valid and deliverable.

Environment

Bulwark 1.7.7, Stalwart 0.16.13, Lettermint as outbound relay. Verified still present on current main (1.8.1).

Related

#672 fixed the mailbox-level parsing so splitMailbox tolerates a missing >. This is the list-level tokenizer one layer up, which still folds on the same input.

A separate defect makes this reach the server at all: the composer commits and sends an unvalidated recipient. Filed separately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions