diff --git a/frontend/package.json b/frontend/package.json index bc36fed58..779c6f2ea 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -94,6 +94,7 @@ "color-blend": "4.0.0", "damerau-levenshtein": "1.0.8", "date-fns": "3.6.0", + "disposable-email-domains-js": "^1.0.35", "firebase": "12.0.0", "hangul-js": "0.2.6", "howler": "2.2.3", diff --git a/frontend/src/ts/pages/login.ts b/frontend/src/ts/pages/login.ts index 44cc80178..5d1d0b84f 100644 --- a/frontend/src/ts/pages/login.ts +++ b/frontend/src/ts/pages/login.ts @@ -80,9 +80,25 @@ validateWithIndicator(nameInputEl, { }, }); +let disposableEmailModule: typeof import("disposable-email-domains-js") | null = + null; +let moduleLoadAttempted = false; + const emailInputEl = document.querySelector( ".page.pageLogin .register.side input.emailInput" ) as HTMLInputElement; + +emailInputEl.addEventListener("focus", async () => { + if (!moduleLoadAttempted) { + moduleLoadAttempted = true; + try { + disposableEmailModule = await import("disposable-email-domains-js"); + } catch (e) { + // Silent failure + } + } +}); + validateWithIndicator(emailInputEl, { schema: UserEmailSchema, isValid: async (email: string) => { @@ -103,6 +119,23 @@ validateWithIndicator(emailInputEl, { warning: "Please check your email address, it may contain a typo.", }; } + + if ( + disposableEmailModule && + disposableEmailModule.isDisposableEmail !== undefined + ) { + try { + if (disposableEmailModule.isDisposableEmail(email)) { + return { + warning: + "Using a temporary email may cause issues with logging in, password resets and support. Consider using a permanent email address. Don't worry, we don't send spam.", + }; + } + } catch (e) { + // Silent failure + } + } + return true; }, debounceDelay: 0, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 388991d25..6a46dd27a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -312,6 +312,9 @@ importers: date-fns: specifier: 3.6.0 version: 3.6.0 + disposable-email-domains-js: + specifier: ^1.0.35 + version: 1.16.0 firebase: specifier: 12.0.0 version: 12.0.0 @@ -4627,6 +4630,9 @@ packages: discontinuous-range@1.0.0: resolution: {integrity: sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==} + disposable-email-domains-js@1.16.0: + resolution: {integrity: sha512-5BTVWEfUO1xeJ/jQdt+bIeOFYlgKuN5wGUtiMlkj0rqqpeO8LwiIH+7sKYvob87yMBjDKJWD8eqSSHFVM0g2pQ==} + docker-compose@1.2.0: resolution: {integrity: sha512-wIU1eHk3Op7dFgELRdmOYlPYS4gP8HhH1ZmZa13QZF59y0fblzFDFmKPhyc05phCy2hze9OEvNZAsoljrs+72w==} engines: {node: '>= 6.0.0'} @@ -14221,6 +14227,8 @@ snapshots: discontinuous-range@1.0.0: {} + disposable-email-domains-js@1.16.0: {} + docker-compose@1.2.0: dependencies: yaml: 2.5.0