Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/lib/spam-check.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,21 @@ describe("checkEmail", () => {
expect(checkEmail(email).spam).toBe(false);
});

// Initials followed by digits is one of the most ordinary shapes a real
// address takes, and it used to be a hard block with no appeal: a reporter's
// years-old personal address was refused as "Email matches spam pattern".
// An address is not something a blocked signup can just pick differently.
it.each([
["abc123456789@example.com", "the shape reported as blocked"],
["ab123456@example.com", "two initials and a digit run"],
["jsm19850612@example.com", "initials and a date of birth"],
["kp4155550143@example.com", "initials and a phone fragment"],
["xy31415926535@example.com", "initials and digits of pi"],
])("allows email: %s (%s)", (email) => {
expect(checkEmail(email).spam).toBe(false);
});

it.each([
["ab123456@example.com", "letters then a long digit run"],
["x7f2q9k1m4z8p3w6r5t0@example.com", "long random local part"],
["someone+x7f2q9k1m4z8@gmail.com", "generated-looking tag"],
["someone@mailinator.com", "disposable domain"],
Expand Down
18 changes: 17 additions & 1 deletion src/lib/spam-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,24 @@ const DISPOSABLE_DOMAINS = new Set([
"guerrillamail.org", "harakirimail.com", "mailforspam.com",
]);

/**
* Local parts that are random rather than chosen.
*
* There used to be a second rule here, `/^[a-z]{2,3}\d{6,}@/i`, meant to catch
* `ab123456@`. It caught people instead. Initials followed by digits is one of
* the most ordinary ways a real address is formed — a birth year, a phone
* fragment, digits of pi — and the shape alone says nothing about who typed it.
* It blocked a reporter's long-established personal Gmail address with nothing
* but "Email matches spam pattern" and no route back in.
*
* Unlike a username, an email address is not something a blocked signup can
* simply pick differently, so a false positive here is a closed door rather than
* an inconvenience. The same reasoning retired the plus-tag length rule below,
* and corroboration replaced shape in checkSpam (#531): what marks a generated
* address is randomness, which the length rule already covers, not the presence
* of digits after letters.
*/
const SPAM_EMAIL_PATTERNS = [
/^[a-z]{2,3}\d{6,}@/i, // ab123456@...
/^[a-z0-9]{20,}@/i, // long random local part
];

Expand Down
Loading