Skip to content
This repository was archived by the owner on Apr 19, 2023. It is now read-only.

Commit 9405d53

Browse files
✨ Check for disposable emails (#114)
1 parent e5e3dbf commit 9405d53

File tree

8 files changed

+52
-12
lines changed

8 files changed

+52
-12
lines changed

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "staart-manager",
3-
"version": "1.0.51",
3+
"version": "1.0.52",
44
"main": "index.js",
55
"repository": "git@github.com:AnandChowdhary/staart.git",
66
"author": "Anand Chowdhary <mail@anandchowdhary.com>",
@@ -88,6 +88,7 @@
8888
"cors": "^2.8.5",
8989
"cron": "^1.7.1",
9090
"crypto-random-string": "^3.0.1",
91+
"disposable-email-domains": "^1.0.46",
9192
"express": "^4.17.0",
9293
"express-async-handler": "^1.1.4",
9394
"express-brute": "^1.0.1",
@@ -118,8 +119,8 @@
118119
"response-time": "^2.3.2",
119120
"rotating-file-stream": "^1.4.2",
120121
"slugify": "^1.3.4",
121-
"stripe": "^7.4.0",
122-
"snyk": "^1.192.3"
122+
"snyk": "^1.192.3",
123+
"stripe": "^7.4.0"
123124
},
124125
"files": [
125126
"setup"

src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export const SES_EMAIL = process.env.SES_EMAIL || "";
5858
export const SES_REGION = process.env.SES_REGION || "eu-west-1";
5959
export const SES_ACCESS = process.env.SES_ACCESS || "";
6060
export const SES_SECRET = process.env.SES_SECRET || "";
61+
export const ALLOW_DISPOSABLE_EMAILS = !!process.env.DISPOSABLE_EMAIL;
6162

6263
// Auth and tokens
6364
export const JWT_SECRET = process.env.JWT_SECRET || "staart";

src/helpers/mail.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ import { readFile } from "fs-extra";
1212
import { join } from "path";
1313
import { render } from "mustache";
1414
import marked from "marked";
15+
import { isMatch } from "matcher";
16+
import disposableDomains from "disposable-email-domains/index.json";
17+
import wildcardDomains from "disposable-email-domains/wildcard.json";
1518
import i18n from "../i18n";
19+
import Joi from "@hapi/joi";
20+
import { joiValidate } from "./utils";
21+
import { ErrorCode } from "../interfaces/enum";
1622

1723
const client = createClient({
1824
key: SES_ACCESS,
@@ -57,3 +63,24 @@ export const mail = async (
5763
altText
5864
});
5965
};
66+
67+
export const checkIfDisposableEmail = (email: string) => {
68+
let isDisposable = false;
69+
joiValidate(
70+
{
71+
email: Joi.string()
72+
.email()
73+
.required()
74+
},
75+
{ email }
76+
);
77+
const domain = email.split("@")[1];
78+
if (disposableDomains.includes(domain))
79+
throw new Error(ErrorCode.DISPOSABLE_EMAIL);
80+
const potentialMatches = wildcardDomains.filter(w => domain.includes(w));
81+
potentialMatches.forEach(
82+
d => (isDisposable = isDisposable || isMatch(email, `*.${d}`))
83+
);
84+
if (isDisposable) throw new Error(ErrorCode.DISPOSABLE_EMAIL);
85+
return;
86+
};

src/interfaces/enum.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ export enum ErrorCode {
8585
OAUTH_NO_EMAIL = "404/oauth-no-email",
8686
INVALID_API_KEY_SECRET = "401/invalid-api-key-secret",
8787
IP_RANGE_CHECK_FAIL = "401/ip-range-check-fail",
88-
REFERRER_CHECK_FAIL = "401/referrer-check-fail"
88+
REFERRER_CHECK_FAIL = "401/referrer-check-fail",
89+
DISPOSABLE_EMAIL = "422/disposable-email"
8990
}
9091

9192
export enum Templates {

src/internal/staart-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.51
1+
1.0.52

src/rest/auth.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
getEmail,
1717
checkIfNewEmail
1818
} from "../crud/email";
19-
import { mail } from "../helpers/mail";
19+
import { mail, checkIfDisposableEmail } from "../helpers/mail";
2020
import {
2121
verifyToken,
2222
passwordResetToken,
@@ -52,7 +52,8 @@ import {
5252
FACEBOOK_CLIENT_ID,
5353
FACEBOOK_CLIENT_SECRET,
5454
SALESFORCE_CLIENT_ID,
55-
SALESFORCE_CLIENT_SECRET
55+
SALESFORCE_CLIENT_SECRET,
56+
ALLOW_DISPOSABLE_EMAILS
5657
} from "../config";
5758
import axios from "axios";
5859
import { GitHubEmail } from "../interfaces/oauth";
@@ -103,7 +104,10 @@ export const register = async (
103104
role?: MembershipRole,
104105
emailVerified?: boolean
105106
) => {
106-
if (email) await checkIfNewEmail(email);
107+
if (email) {
108+
await checkIfNewEmail(email);
109+
if (!ALLOW_DISPOSABLE_EMAILS) checkIfDisposableEmail(email);
110+
}
107111
if (!user.username) user.username = createSlug(user.name);
108112
if (!(await checkUsernameAvailability(user.username)))
109113
throw new Error(ErrorCode.USERNAME_EXISTS);

tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"esModuleInterop": true,
1111
"allowSyntheticDefaultImports": true,
1212
"experimentalDecorators": true,
13+
"resolveJsonModule": true,
1314
"emitDecoratorMetadata": true,
1415
"declarationDir": "./dist",
1516
"outDir": "./dist",

yarn.lock

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,6 +2540,11 @@ dijkstrajs@^1.0.1:
25402540
resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.1.tgz#d3cd81221e3ea40742cfcde556d4e99e98ddc71b"
25412541
integrity sha1-082BIh4+pAdCz83lVtTpnpjdxxs=
25422542

2543+
disposable-email-domains@^1.0.46:
2544+
version "1.0.46"
2545+
resolved "https://registry.yarnpkg.com/disposable-email-domains/-/disposable-email-domains-1.0.46.tgz#6f8c777bf56c8926f480b53986547a40a5ff3416"
2546+
integrity sha512-Nk8tDHrAqysWS3J0scrxPfIXeMT50iy+1zfqWrLbKg/q1x8qgWYW31gggVOUbC/YndDLalOaZk5JpnTv7A2Q0A==
2547+
25432548
dns-prefetch-control@0.1.0:
25442549
version "0.1.0"
25452550
resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz#60ddb457774e178f1f9415f0cabb0e85b0b300b2"
@@ -6769,10 +6774,10 @@ snyk-try-require@1.3.1, snyk-try-require@^1.1.1, snyk-try-require@^1.3.1:
67696774
lru-cache "^4.0.0"
67706775
then-fs "^2.0.0"
67716776

6772-
snyk@^1.192.2:
6773-
version "1.192.2"
6774-
resolved "https://registry.yarnpkg.com/snyk/-/snyk-1.192.2.tgz#7fd4cc630301cb7f288d9b1412b2dd346056df05"
6775-
integrity sha512-4qGp7FE+Kqy3CuvxywnaBOuFY4iADc/poc6oPT00adVz61hP9Q+VnQr5Ztq+V/LCQwTMJqKSk0EuODEGSJbVXA==
6777+
snyk@^1.192.3:
6778+
version "1.192.3"
6779+
resolved "https://registry.yarnpkg.com/snyk/-/snyk-1.192.3.tgz#2aba981b3068aaaf8a3fafd6b8f8e29cb4629b3c"
6780+
integrity sha512-Rm/qr7qxuCT324GSiKGWq/VzssG7DqeF2hQp7Odu/UPVDZ6JdBKQmL0uXe8SVSrRfbx7Pmy0GFK4ya1Fgy5Aaw==
67766781
dependencies:
67776782
"@snyk/dep-graph" "1.8.1"
67786783
"@snyk/gemfile" "1.2.0"

0 commit comments

Comments
 (0)