From 44ceb7137e07dc728b47224446e3aefc030eb583 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 27 Aug 2025 14:51:01 +0200 Subject: [PATCH] impr(sign up): add temporary email detection to registration form (@copilot) (#6912) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements temporary email detection for the registration email input field on the login page. When users focus on the email input, the system dynamically imports the `disposable-email-domains-js` package to check for temporary/disposable email addresses. ## Changes Made - **Dynamic Import**: Added lazy loading of `disposable-email-domains-js` package that triggers on email input focus - **Email Validation Enhancement**: Extended the existing email validation in `login.ts` to include temporary email detection - **User Warning**: Shows warning message "Be careful when using temporary emails - you will need it to log into your account" for detected temporary emails - **Graceful Degradation**: Handles module import failures silently without breaking existing functionality - **Dependency Management**: Added `disposable-email-domains-js` to frontend package dependencies ## Technical Implementation The implementation integrates seamlessly with the existing `validateWithIndicator` system: ```typescript // Dynamic import on focus emailInputEl.addEventListener("focus", async () => { if (!moduleLoadAttempted) { moduleLoadAttempted = true; try { disposableEmailModule = await import("disposable-email-domains-js"); } catch (e) { // Silent failure - continues without temp email detection } } }); // Validation check if (disposableEmailModule && disposableEmailModule.isDisposableEmail) { if (disposableEmailModule.isDisposableEmail(email)) { return { warning: "Be careful when using temporary emails - you will need it to log into your account" }; } } ``` ## Key Features - **Non-blocking**: Module only loads when needed and failures don't interrupt the user experience - **Warning Level**: Uses the existing warning system, allowing users to continue with registration - **Preserved Functionality**: All existing email validation (education emails, typos) continues to work unchanged - **Performance Optimized**: Lazy loading prevents unnecessary network requests until the feature is actually used ## Testing Verified that: - Temporary emails (e.g., mailinator.com, 10minutemail.com) show appropriate warnings - Regular emails (e.g., gmail.com, outlook.com) pass validation normally - Education emails continue to show existing warnings - Module import failures are handled gracefully - All existing validation behavior is preserved ![Education email validation still works](https://github.com/user-attachments/assets/c035e0f8-df39-407b-95aa-85abc4409f38) ![Regular emails pass validation](https://github.com/user-attachments/assets/f1925ecc-e81e-4dec-867c-a2bc0c19b469) Resolves the requirement to detect temporary emails while maintaining a smooth user experience and backward compatibility. > [!WARNING] > >
> Firewall rules blocked me from connecting to one or more addresses (expand for details) > > #### I tried to connect to the following addresses, but was blocked by firewall rules: > > - `https://api.github.com/repos/mziyut/disposable-email-domains-js/contents/package.json` > - Triggering command: `curl -s REDACTED` (http block) > > If you need me to access, download, or install something from one of these locations, you can either: > > - Configure [Actions setup steps](https://gh.io/copilot/actions-setup-steps) to set up my environment, which run before the firewall is enabled > - Add the appropriate URLs or hosts to the custom allowlist in this repository's [Copilot coding agent settings](https://github.com/monkeytypegame/monkeytype/settings/copilot/coding_agent) (admins only) > >
--- ✨ Let Copilot coding agent [set things up for you](https://github.com/monkeytypegame/monkeytype/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Miodec <13181393+Miodec@users.noreply.github.com> Co-authored-by: Jack --- frontend/package.json | 1 + frontend/src/ts/pages/login.ts | 33 +++++++++++++++++++++++++++++++++ pnpm-lock.yaml | 8 ++++++++ 3 files changed, 42 insertions(+) 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