Description
In the composer's recipient field, pressing Space commits whatever is currently typed as
a recipient chip. When searching a contact by name, this breaks any name containing a space:
typing John and pressing space commits John as a (bogus) recipient and clears the input,
instead of continuing the search toward John Doe.
Because a partial name has no @, the committed chip ends up with an invalid email
({ email: "John" }), and the autocomplete suggestion for the real contact is lost even though
it was showing in the dropdown.
Steps to Reproduce
- Have a contact whose display name contains a space, e.g. "John Doe".
- In the composer's To field, type John.
- The autocomplete dropdown shows John Doe.
- Press Space (intending to continue typing John Doe).
Expected Behavior
- Pressing Space while typing a partial name should insert a normal space and continue thesearch (John -> John Doe), so the contact can be matched.
- Space should only commit the input when it is already a complete, valid email address, preserving the fast "type email, space, next email" entry flow.
Actual Behavior
- The input John is immediately committed as a recipient chip.
- Since John is not a valid email, the chip is created with email: "John" (invalid).
- The input is cleared and the search is lost; the "John Doe" suggestion is never
Bulwark Version
1.7.6
Stalwart Mail Server Version
0.16.4
Browser
No response
Operating System
None
Screenshots / Screen Recording
No response
Relevant Logs or Error Output
Additional Context
Root cause (code pointer)
components/email/email-composer.tsx (recipient handleKeyDown, ~L2918):
jsif ((e.key === ' ' || e.key === 'Enter' || e.key === 'Tab') && inputText.trim()) {
if (e.key !== 'Tab') e.preventDefault();
commitCurrentInput();
...
}
commitCurrentInput() (~L2888) calls parseRecipient(inputText), which for input without <>
returns { email: trimmed } — so a partial name like John becomes a chip with an invalid
email. Space is treated identically to Enter/Tab, so it commits mid-search.
Suggested fix
Gate the Space commit on the input already being a valid email; otherwise let Space be a
normal character so the search continues. The project already has isValidEmail in
lib/validation.ts.
Roughly:
jsconst trimmed = inputText.trim();
// Enter / Tab: commit or accept the highlighted suggestion (unchanged)
if ((e.key === 'Enter' || e.key === 'Tab') && trimmed) {
...
}
// Space: only commit when the input is already a complete email address
if (e.key === ' ' && trimmed && isValidEmail(trimmed)) {
e.preventDefault();
commitCurrentInput();
...
}
// otherwise fall through -> Space is typed normally, search continues
Related note
The same commit path also turns partial text into an invalid chip on Enter/Tab when no
autocomplete suggestion is highlighted. It may be worth validating in commitCurrentInput()
(e.g. don't create a chip when the input is neither a valid email nor a resolved contact), so
partial names never become invalid recipients regardless of the key used.
Description
In the composer's recipient field, pressing Space commits whatever is currently typed as
a recipient chip. When searching a contact by name, this breaks any name containing a space:
typing John and pressing space commits John as a (bogus) recipient and clears the input,
instead of continuing the search toward John Doe.
Because a partial name has no @, the committed chip ends up with an invalid email
({ email: "John" }), and the autocomplete suggestion for the real contact is lost even though
it was showing in the dropdown.
Steps to Reproduce
Expected Behavior
Actual Behavior
Bulwark Version
1.7.6
Stalwart Mail Server Version
0.16.4
Browser
No response
Operating System
None
Screenshots / Screen Recording
No response
Relevant Logs or Error Output
Additional Context
Root cause (code pointer)
components/email/email-composer.tsx (recipient handleKeyDown, ~L2918):
jsif ((e.key === ' ' || e.key === 'Enter' || e.key === 'Tab') && inputText.trim()) {
if (e.key !== 'Tab') e.preventDefault();
commitCurrentInput();
...
}
commitCurrentInput() (~L2888) calls parseRecipient(inputText), which for input without <>
returns { email: trimmed } — so a partial name like John becomes a chip with an invalid
email. Space is treated identically to Enter/Tab, so it commits mid-search.
Suggested fix
Gate the Space commit on the input already being a valid email; otherwise let Space be a
normal character so the search continues. The project already has isValidEmail in
lib/validation.ts.
Roughly:
jsconst trimmed = inputText.trim();
// Enter / Tab: commit or accept the highlighted suggestion (unchanged)
if ((e.key === 'Enter' || e.key === 'Tab') && trimmed) {
...
}
// Space: only commit when the input is already a complete email address
if (e.key === ' ' && trimmed && isValidEmail(trimmed)) {
e.preventDefault();
commitCurrentInput();
...
}
// otherwise fall through -> Space is typed normally, search continues
Related note
The same commit path also turns partial text into an invalid chip on Enter/Tab when no
autocomplete suggestion is highlighted. It may be worth validating in commitCurrentInput()
(e.g. don't create a chip when the input is neither a valid email nor a resolved contact), so
partial names never become invalid recipients regardless of the key used.