mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-02 00:06:23 +00:00
fix: keep an escaped quote in a pasted display name from splitting off a recipient
This commit is contained in:
@@ -38,6 +38,23 @@ describe('splitRecipients', () => {
|
|||||||
it('keeps RFC 5322 groups as one entry', () => {
|
it('keeps RFC 5322 groups as one entry', () => {
|
||||||
expect(splitRecipients('Team: a@x.com, b@y.com;, c@z.com')).toEqual(['Team: a@x.com, b@y.com;', 'c@z.com']);
|
expect(splitRecipients('Team: a@x.com, b@y.com;, c@z.com')).toEqual(['Team: a@x.com, b@y.com;', 'c@z.com']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not take an escaped quote in a display name as the closing one', () => {
|
||||||
|
expect(splitRecipients('"Support\\", ceo@corp.example, \\"x" <s@x.com>, b@y.com'))
|
||||||
|
.toEqual(['"Support\\", ceo@corp.example, \\"x" <s@x.com>', 'b@y.com']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not take an escaped quote as closing when an unclosed angle bracket looks ahead', () => {
|
||||||
|
expect(splitRecipients('John <j@x.com, "a\\"> b" <b@y.com>')).toEqual(['John <j@x.com', '"a\\"> b" <b@y.com>']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('splitPastedRecipients with an escaped quote (composer paste)', () => {
|
||||||
|
it('adds no extra recipient from inside a display name', () => {
|
||||||
|
const { valid, invalid } = splitPastedRecipients('"Support\\", ceo@corp.example, \\"x" <s@x.com>, b@y.com');
|
||||||
|
expect(valid.map((r) => r.email)).toEqual(['s@x.com', 'b@y.com']);
|
||||||
|
expect(invalid).toEqual([]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('parseRecipient', () => {
|
describe('parseRecipient', () => {
|
||||||
|
|||||||
+10
-2
@@ -58,7 +58,9 @@ function angleRunCloses(value: string, from: number): boolean {
|
|||||||
let inQuotes = false;
|
let inQuotes = false;
|
||||||
for (let i = from + 1; i < value.length; i++) {
|
for (let i = from + 1; i < value.length; i++) {
|
||||||
const ch = value[i];
|
const ch = value[i];
|
||||||
if (ch === '"') inQuotes = !inQuotes;
|
// A quoted-pair (`\"`) never closes the quote.
|
||||||
|
if (inQuotes && ch === '\\') i++;
|
||||||
|
else if (ch === '"') inQuotes = !inQuotes;
|
||||||
else if (inQuotes) continue;
|
else if (inQuotes) continue;
|
||||||
else if (ch === '>') return true;
|
else if (ch === '>') return true;
|
||||||
else if (ch === '<') return false;
|
else if (ch === '<') return false;
|
||||||
@@ -84,7 +86,13 @@ export function splitRecipients(value: string, separators = ','): string[] {
|
|||||||
let inGroup = false;
|
let inGroup = false;
|
||||||
for (let i = 0; i < value.length; i++) {
|
for (let i = 0; i < value.length; i++) {
|
||||||
const ch = value[i];
|
const ch = value[i];
|
||||||
if (ch === '"') {
|
if (inQuotes && ch === '\\' && i + 1 < value.length) {
|
||||||
|
// A quoted-pair: a `"` in a display name is written `\"`. Taking it as
|
||||||
|
// the closing quote let a name like `Support", ceo@corp.example, "x`
|
||||||
|
// split into an extra recipient (webmail lib/email-composer-utils.ts).
|
||||||
|
current += ch + value[i + 1];
|
||||||
|
i++;
|
||||||
|
} else if (ch === '"') {
|
||||||
inQuotes = !inQuotes;
|
inQuotes = !inQuotes;
|
||||||
current += ch;
|
current += ch;
|
||||||
} else if (ch === '<' && !inQuotes) {
|
} else if (ch === '<' && !inQuotes) {
|
||||||
|
|||||||
Reference in New Issue
Block a user