Email Verifier: NeoVerify

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>NEOVERIFY - Email Validation</title>

    <style>

        :root {

            --dark-bg: #0a0a12;

            --neon-blue: #00f9ff;

            --neon-pink: #ff0066;

            --cyber-green: #00ff9d;

            --light-bg: #f5f5f7;

            --light-text: #333;

            --light-accent: #3366ff;

        }


        body {

            background: var(--dark-bg);

            color: white;

            font-family: 'Courier New', monospace;

            margin: 0;

            padding: 20px;

            transition: background 0.3s, color 0.3s;

        }


        body.light-mode {

            background: var(--light-bg);

            color: var(--light-text);

        }


        .container {

            max-width: 1000px;

            margin: 0 auto;

        }


        h1 {

            color: var(--neon-blue);

            text-align: center;

        }


        .light-mode h1 {

            color: var(--light-accent);

        }


        textarea {

            width: 100%;

            height: 150px;

            background: rgba(255, 255, 255, 0.1);

            color: white;

            border: 1px solid var(--neon-blue);

            padding: 10px;

            border-radius: 4px;

            font-family: 'Courier New', monospace;

            margin-bottom: 10px;

        }


        .light-mode textarea {

            background: var(--light-bg);

            border: 1px solid var(--light-accent);

            color: var(--light-text);

        }


        button {

            background: var(--neon-blue);

            color: var(--dark-bg);

            border: none;

            padding: 10px 20px;

            border-radius: 4px;

            cursor: pointer;

            margin-right: 10px;

            margin-bottom: 10px;

        }


        .light-mode button {

            background: var(--light-accent);

            color: white;

        }


        button:hover {

            background: var(--neon-pink);

        }


        .light-mode button:hover {

            background: #ff3366;

        }


        #results-container {

            display: none;

            margin-top: 20px;

        }


        table {

            width: 100%;

            border-collapse: collapse;

            color: white;

        }


        .light-mode table {

            color: var(--light-text);

        }


        th, td {

            padding: 10px;

            border-bottom: 1px solid rgba(255, 255, 255, 0.1);

            text-align: left;

        }


        .light-mode th, .light-mode td {

            border-bottom: 1px solid rgba(0, 0, 0, 0.1);

        }


        th {

            background: rgba(255, 0, 102, 0.2);

        }


        .valid { color: var(--cyber-green); }

        .invalid { color: var(--neon-pink); }

        .suggestion { color: #ffea00; }


        #loader {

            display: none;

            text-align: center;

            margin: 20px 0;

            color: var(--neon-blue);

        }


        .theme-toggle {

            position: fixed;

            top: 20px;

            right: 20px;

            background: none;

            border: none;

            font-size: 1.5rem;

            cursor: pointer;

            color: var(--neon-blue);

        }


        .light-mode .theme-toggle {

            color: var(--light-accent);

        }


        #email-count {

            font-size: 0.9rem;

            color: var(--neon-blue);

            margin-bottom: 10px;

        }


        .light-mode #email-count {

            color: var(--light-accent);

        }

    </style>

</head>

<body>

    <button id="theme-toggle" class="theme-toggle">☀️</button>

    <div class="container">

        <h1>NEOVERIFY - Email Validation</h1>

        <textarea id="emails" placeholder="Enter up to 100 emails (one per line or comma-separated)"></textarea>

        <div id="email-count">Emails: 0 (Max: 100)</div>

        <div>

            <button id="verify-button">🔍 Verify Emails</button>

            <button id="export-button">💾 Export CSV</button>

            <button id="reset-button">🗑️ Clear</button>

        </div>

        <div id="loader">Validating Emails...</div>

        <div id="results-container">

            <h2>Validation Results</h2>

            <table>

                <thead>

                    <tr>

                        <th>Email</th>

                        <th>Status</th>

                        <th>Quality</th>

                        <th>Domain</th>

                        <th>Spam Risk</th>

                        <th>Suggestion</th>

                    </tr>

                </thead>

                <tbody id="results-body"></tbody>

            </table>

        </div>

    </div>


    <script>

        const CONFIG = { maxEmails: 100, dnsDelay: 300, dnsTimeout: 5000 };


        class EmailValidator {

            constructor() {

                this.typoDB = {

                    'gmail.com': ['gamil.com', 'gmial.com', 'gmal.com', 'gmali.com'],

                    'yahoo.com': ['yaho.com', 'yaoo.com', 'yahooo.com'],

                    'outlook.com': ['outlok.com', 'outook.com', 'otulook.com'],

                    'hotmail.com': ['hotmal.com', 'hotmai.com', 'hotmial.com'],

                    'aol.com': ['ao1.com', 'aol.co'],

                    'icloud.com': ['iclod.com', 'icould.com']

                };

                this.disposableDomains = [

                    'mailinator.com', 'tempmail.com', '10minutemail.com', 'yopmail.com',

                    'guerrillamail.com', 'sharklasers.com', 'dispostable.com', 'maildrop.cc',

                    'throwawaymail.com', 'temp-mail.org'

                ];

                this.roleAccounts = [

                    'admin', 'support', 'info', 'contact', 'help', 'sales', 'marketing',

                    'billing', 'webmaster', 'noreply', 'no-reply', 'team'

                ];

                this.validTLDs = [

                    'com', 'net', 'org', 'edu', 'gov', 'mil', 'io', 'co', 'ai', 'app',

                    'dev', 'me', 'info', 'online', 'biz', 'uk', 'de', 'fr', 'jp', 'ca',

                    'au', 'ru', 'ch', 'it', 'nl', 'se', 'no', 'es', 'cn', 'in', 'br'

                ];

                this.dnsCache = new Map();

                ['gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com', 'aol.com', 'icloud.com']

                    .forEach(d => this.dnsCache.set(d, true));

            }


            async checkMxRecords(domain) {

                if (this.dnsCache.has(domain)) return this.dnsCache.get(domain);


                await new Promise(resolve => setTimeout(resolve, CONFIG.dnsDelay));


                const controllers = [];

                const timeoutPromise = new Promise((_, reject) => {

                    setTimeout(() => reject(new Error('DNS timeout')), CONFIG.dnsTimeout);

                });


                // Try Google DNS

                let googleController = new AbortController();

                controllers.push(googleController);

                const googlePromise = fetch(`https://dns.google/resolve?name=${domain}&type=MX`, {

                    headers: { 'Accept': 'application/dns-json' },

                    signal: googleController.signal

                })

                    .then(response => response.ok ? response.json() : Promise.reject())

                    .then(data => {

                        const hasMx = data.Answer && data.Answer.length > 0;

                        this.dnsCache.set(domain, hasMx);

                        return hasMx;

                    })

                    .catch(() => null);


                // Try Cloudflare DNS

                let cloudflareController = new AbortController();

                controllers.push(cloudflareController);

                const cloudflarePromise = fetch(`https://cloudflare-dns.com/dns-query?name=${domain}&type=MX`, {

                    headers: { 'Accept': 'application/dns-json' },

                    signal: cloudflareController.signal

                })

                    .then(response => response.ok ? response.json() : Promise.reject())

                    .then(data => {

                        const hasMx = data.Answer && data.Answer.length > 0;

                        this.dnsCache.set(domain, hasMx);

                        return hasMx;

                    })

                    .catch(() => null);


                try {

                    const result = await Promise.race([

                        Promise.any([googlePromise, cloudflarePromise]),

                        timeoutPromise

                    ]);

                    controllers.forEach(c => c.abort());

                    if (result !== null) return result;

                } catch (err) {

                    controllers.forEach(c => c.abort());

                }


                this.dnsCache.set(domain, false);

                return false;

            }


            checkForTypos(user, domain) {

                for (const [correct, typos] of Object.entries(this.typoDB)) {

                    if (typos.includes(domain)) return `${user}@${correct}`;

                }

                return null;

            }


            async validateEmail(email) {

                const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;

                if (!emailRegex.test(email)) {

                    return { email, valid: false, reason: "Invalid format", quality: "invalid" };

                }


                const [user, domain] = email.split('@');

                if (user.length < 2 || user.startsWith('.') || user.endsWith('.') || user.includes('..')) {

                    return { email, valid: false, reason: "Invalid username", quality: "invalid" };

                }


                const tld = domain.split('.').pop().toLowerCase();

                const hasTLD = this.validTLDs.includes(tld);

                if (!hasTLD) {

                    return { email, valid: false, reason: "Invalid TLD", quality: "invalid" };

                }


                const hasMx = await this.checkMxRecords(domain);

                const suggestion = this.checkForTypos(user, domain);

                const isDisposable = this.disposableDomains.includes(domain);

                const isRole = this.roleAccounts.some(r => user.toLowerCase().startsWith(r) || user.toLowerCase() === r);

                const isRandom = /^\d+$/.test(user) || (user.match(/\d/g)?.length > user.length / 2 && user.length > 8);


                let quality = "invalid";

                let spamRisk = "Low";

                if (hasMx && hasTLD) {

                    if (isDisposable || isRandom) {

                        quality = "risky";

                        spamRisk = "High";

                    } else if (isRole) {

                        quality = "standard";

                        spamRisk = "Medium";

                    } else {

                        quality = "premium";

                    }

                }


                return {

                    email,

                    valid: hasMx && hasTLD,

                    quality,

                    domain,

                    spamRisk,

                    suggestion,

                    reason: !hasTLD ? "Invalid TLD" : !hasMx ? "No MX Records" : null

                };

            }


            async validateBatch(emails, onProgress) {

                const results = [];

                const batchSize = Math.min(emails.length, CONFIG.maxEmails);

                const chunkSize = 5;


                for (let i = 0; i < batchSize; i += chunkSize) {

                    const chunk = emails.slice(i, Math.min(i + chunkSize, batchSize));

                    const chunkResults = await Promise.all(chunk.map(email => this.validateEmail(email)));

                    results.push(...chunkResults);

                    if (onProgress) onProgress(Math.min(i + chunkSize, batchSize), batchSize);

                    await new Promise(resolve => setTimeout(resolve, 10));

                }


                return results;

            }

        }


        class App {

            constructor() {

                this.validator = new EmailValidator();

                this.results = [];

                this.isLightMode = false;

            }


            init() {

                document.getElementById('verify-button').addEventListener('click', () => this.runValidation());

                document.getElementById('reset-button').addEventListener('click', () => this.clearAll());

                document.getElementById('export-button').addEventListener('click', () => this.exportResults());

                document.getElementById('theme-toggle').addEventListener('click', () => this.toggleTheme());

                document.getElementById('emails').addEventListener('input', () => this.countEmails());

                if (localStorage.getItem('theme') === 'light') this.toggleTheme();

                this.countEmails();

            }


            toggleTheme() {

                document.body.classList.toggle('light-mode');

                this.isLightMode = document.body.classList.contains('light-mode');

                document.getElementById('theme-toggle').textContent = this.isLightMode ? '🌙' : '☀️';

                localStorage.setItem('theme', this.isLightMode ? 'light' : 'dark');

            }


            getEmails() {

                return document.getElementById('emails').value

                    .split(/[\n,;]+/)

                    .map(e => e.trim())

                    .filter(e => e && e.includes('@'));

            }


            countEmails() {

                const emails = this.getEmails();

                document.getElementById('email-count').textContent = `Emails: ${emails.length} (Max: ${CONFIG.maxEmails})`;

                return emails;

            }


            async runValidation() {

                const emails = this.countEmails();

                if (!emails.length) {

                    alert('Please enter at least one email!');

                    return;

                }

                if (emails.length > CONFIG.maxEmails) {

                    alert(`Validation limited to ${CONFIG.maxEmails} emails.`);

                    emails.splice(CONFIG.maxEmails);

                }


                this.showLoading(true);

                this.results = await this.validator.validateBatch(emails, (processed, total) => {

                    document.getElementById('loader').textContent = `Validating ${processed}/${total} Emails...`;

                });

                this.displayResults();

                this.showLoading(false);

            }


            showLoading(show) {

                document.getElementById('loader').style.display = show ? 'block' : 'none';

                document.getElementById('verify-button').disabled = show;

            }


            displayResults() {

                const tbody = document.getElementById('results-body');

                tbody.innerHTML = this.results.map(r => `

                    <tr>

                        <td>${r.email}</td>

                        <td class="${r.valid ? 'valid' : 'invalid'}">${r.valid ? 'Valid' : 'Invalid'}${r.reason ? ` (${r.reason})` : ''}</td>

                        <td>${r.quality}</td>

                        <td>${r.domain}</td>

                        <td>${r.spamRisk}</td>

                        <td class="${r.suggestion ? 'suggestion' : ''}">${r.suggestion || '—'}</td>

                    </tr>

                `).join('');

                document.getElementById('results-container').style.display = 'block';

            }


            exportResults() {

                if (!this.results.length) {

                    alert('No results to export!');

                    return;

                }

                const headers = ['Email', 'Status', 'Quality', 'Domain', 'Spam Risk', 'Suggestion'];

                let csv = headers.join(',') + '\n';

                this.results.forEach(r => {

                    csv += [

                        `"${r.email}"`,

                        r.valid ? 'Valid' : `Invalid${r.reason ? ` (${r.reason})` : ''}`,

                        r.quality,

                        r.domain,

                        r.spamRisk,

                        r.suggestion || ''

                    ].join(',') + '\n';

                });

                const blob = new Blob([csv], { type: 'text/csv' });

                const url = URL.createObjectURL(blob);

                const a = document.createElement('a');

                a.href = url;

                a.download = 'email_validation_results.csv';

                document.body.appendChild(a);

                a.click();

                document.body.removeChild(a);

            }


            clearAll() {

                document.getElementById('emails').value = '';

                document.getElementById('results-container').style.display = 'none';

                this.results = [];

                this.countEmails();

            }

        }


        const app = new App();

        document.addEventListener('DOMContentLoaded', () => app.init());

    </script>

</body>

</html>

Comments

Popular posts from this blog

🔥 NeoVerify: The Email Verification Revolution You've Been Waiting For! 🔥