UNPKG

free-email-domains

Version:

A comprehensive list of all free email domain providers

143 lines (131 loc) 3.07 kB
import { writeFile } from 'node:fs/promises' const SOURCES = [ { name: 'HubSpot blocked domains', url: 'https://f.hubspotusercontent40.net/hubfs/2832391/Marketing/Lead-Capture/free-domains-2.csv' }, { name: 'Castle disposable email domains', url: 'https://raw.githubusercontent.com/castle/disposable-email-domains/master/disposable-email-domains.txt' }, { name: 'Disposable email domains blocklist', url: 'https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/main/disposable_email_blocklist.conf' } ] /** Additional domains not present in the URL */ const DOMAINS = [ '2iij.net', 'asahi-net.or.jp', 'au.com', 'auone-net.jp', 'bbiq.jp', 'bbtec.net', 'biglobe.ne.jp', 'biz.ezweb.ne.jp', 'chol.com', 'chollian.net', 'commufa.jp', 'daum.net', 'dion.ne.jp', 'disney.ne.jp', 'docomo.ne.jp', 'dreamwiz.com', 'dti.ne.jp', 'emnet.ne.jp', 'emobile.ne.jp', 'eonet.ne.jp', 'ezweb.ne.jp', 'freechal.com', 'freemail.ne.jp', 'hanafos.com', 'hananet.net', 'hanmail2.net', 'hanmir.com', 'hi-ho.ne.jp', 'hitel.net', 'i.softbank.jp', 'iij4u.or.jp', 'infoseek.co.jp', 'infoseek.jp', 'infoweb.ne.jp', 'jcom.home.ne.jp', 'jcom.zaq.ne.jp', 'kakao.com', 'kcn.ne.jp', 'kornet.net', 'livedoor.com', 'mail.goo.ne.jp', 'mail.sony.jp', 'megaegg.ne.jp', 'mesh.ad.jp', 'mineo.jp', 'mopera.net', 'nate.com', 'netsgo.com', 'nifty.com', 'nifty.ne.jp', 'nownuri.net', 'ocn.ne.jp', 'odn.ad.jp', 'odn.ne.jp', 'panda.tnc.ne.jp', 'paran.com', 'pdx.ne.jp', 'pikara.ne.jp', 'plala.or.jp', 'pm.me', 'proton.me', 'protonmail.ch', 'rakumail.jp', 'rakuten.jp', 'sky.tkc.ne.jp', 'sky.tkk.ne.jp', 'sky.tu-ka.ne.jp', 'so-net.ne.jp', 'softbank.ne.jp', 'spaaqs.ne.jp', 'spambox.xyz', 't-com.ne.jp', 'tempmail.net', 'thrunet.com', 'tiki.ne.jp', 'tistory.com', 'tokai.or.jp', 'ucom.ne.jp', 'unitel.co.kr', 'uqmobile.jp', 'vodafone.ne.jp', 'wcm.ne.jp', 'willcom.com', 'ybb.ne.jp', 'ymail.ne.jp', 'ymobile.ne.jp', 'ymobile1.ne.jp', 'zaq.ne.jp' ] const trim = text => text.replace(/^\s+|\s+$/g, '') const sanitize = text => text .split(/[,\n]/g) .map(trim) .filter(domain => domain && !domain.startsWith('#')) async function fetchSource (source) { const res = await fetch(source.url) if (!res.ok) { throw new Error(`Unable to fetch ${source.name} (${res.status})`) } const text = await res.text() if (text.startsWith('<!DOCTYPE html') || text.includes('<html')) { throw new Error(`Received HTML instead of domain list for ${source.name}`) } return sanitize(text) } async function main () { const sourceDomains = await Promise.all(SOURCES.map(fetchSource)) const domains = new Set(sourceDomains.flat()) for (const domain of DOMAINS) domains.add(domain) const sorted = Array.from(domains).sort() await writeFile('domains.json', JSON.stringify(sorted, null, 2)) } main().catch(error => console.error(error) || process.exit(1))