Back to blog
SecurityJanuary 1, 2024· 16 min read

Email Security Headers (SPF, DKIM, DMARC): Protecting Your Domain from Abuse

A practical Fusebox guide to email security headers (spf, dkim, dmarc).

Email Security Headers (SPF, DKIM, DMARC): Protecting Your Domain from Abuse

Email security headers are DNS-based authentication methods that protect your domain from being used in phishing, spoofing, and spam campaigns. This guide explores how to analyze and implement SPF, DKIM, and DMARC records for comprehensive email security.

Run This Email Security Analyzer Now

// Copy and paste this into your browser console to analyze email security

class EmailSecurityAnalyzer {
    constructor() {
        this.domain = window.location.hostname;
        this.results = {
            spf: null,
            dkim: null,
            dmarc: null,
            mx: null,
            vulnerabilities: []
        };
        this.dnsAPI = 'https://dns.google/resolve';
    }
    
    async analyzeEmailSecurity() {
        console.log(`= Analyzing Email Security for ${this.domain}...\n`);
        
        // Check SPF records
        await this.checkSPF();
        
        // Check DMARC records
        await this.checkDMARC();
        
        // Check MX records
        await this.checkMX();
        
        // Analyze DKIM selectors
        await this.checkDKIM();
        
        // Check for common vulnerabilities
        this.checkVulnerabilities();
        
        // Generate comprehensive report
        this.generateReport();
    }
    
    async queryDNS(name, type) {
        try {
            const response = await fetch(`${this.dnsAPI}?name=${name}&type=${type}`);
            const data = await response.json();
            
            if (data.Status === 0 && data.Answer) {
                return data.Answer.map(record => ({
                    type: record.type,
                    data: record.data,
                    ttl: record.TTL
                }));
            }
            
            return null;
        } catch (error) {
            console.warn(`DNS query failed for ${name}:`, error);
            return null;
        }
    }
    
    async checkSPF() {
        console.log('=� Checking SPF Record...');
        
        const spfRecords = await this.queryDNS(this.domain, 'TXT');
        
        if (spfRecords) {
            const spfRecord = spfRecords.find(record => 
                record.data.startsWith('"v=spf1') || record.data.startsWith('v=spf1')
            );
            
            if (spfRecord) {
                this.results.spf = this.parseSPF(spfRecord.data.replace(/"/g, ''));
                console.log(' SPF record found');
            } else {
                this.results.spf = { exists: false };
                console.log('L No SPF record found');
                this.results.vulnerabilities.push({
                    type: 'missing-spf',
                    severity: 'high',
                    description: 'No SPF record found - domain vulnerable to spoofing'
                });
            }
        }
    }
    
    parseSPF(spfRecord) {
        const spf = {
            exists: true,
            record: spfRecord,
            mechanisms: [],
            modifiers: {},
            includes: [],
            ipv4: [],
            ipv6: [],
            all: null
        };
        
        const parts = spfRecord.split(' ');
        
        parts.forEach(part => {
            if (part.startsWith('include:')) {
                spf.includes.push(part.substring(8));
            } else if (part.startsWith('ip4:')) {
                spf.ipv4.push(part.substring(4));
            } else if (part.startsWith('ip6:')) {
                spf.ipv6.push(part.substring(4));
            } else if (part.startsWith('a') || part.startsWith('mx')) {
                spf.mechanisms.push(part);
            } else if (part.includes('=')) {
                const [key, value] = part.split('=');
                spf.modifiers[key] = value;
            } else if (part.startsWith('-all') || part.startsWith('~all') || part.startsWith('?all') || part.startsWith('+all')) {
                spf.all = part;
            }
        });
        
        // Analyze SPF configuration
        this.analyzeSPF(spf);
        
        return spf;
    }
    
    analyzeSPF(spf) {
        // Check for common SPF issues
        if (spf.all === '+all') {
            this.results.vulnerabilities.push({
                type: 'spf-all-pass',
                severity: 'critical',
                description: 'SPF +all allows any server to send email'
            });
        }
        
        if (spf.all === '?all') {
            this.results.vulnerabilities.push({
                type: 'spf-neutral',
                severity: 'medium',
                description: 'SPF ?all provides no protection'
            });
        }
        
        if (spf.includes.length > 10) {
            this.results.vulnerabilities.push({
                type: 'spf-too-many-includes',
                severity: 'medium',
                description: 'Too many includes can cause SPF lookup limit issues'
            });
        }
        
        if (spf.record.length > 255) {
            this.results.vulnerabilities.push({
                type: 'spf-too-long',
                severity: 'high',
                description: 'SPF record exceeds 255 character limit'
            });
        }
    }
    
    async checkDMARC() {
        console.log('=� Checking DMARC Record...');
        
        const dmarcRecords = await this.queryDNS(`_dmarc.${this.domain}`, 'TXT');
        
        if (dmarcRecords) {
            const dmarcRecord = dmarcRecords.find(record => 
                record.data.includes('v=DMARC1')
            );
            
            if (dmarcRecord) {
                this.results.dmarc = this.parseDMARC(dmarcRecord.data.replace(/"/g, ''));
                console.log(' DMARC record found');
            } else {
                this.results.dmarc = { exists: false };
                console.log('L No DMARC record found');
                this.results.vulnerabilities.push({
                    type: 'missing-dmarc',
                    severity: 'high',
                    description: 'No DMARC record found - no policy enforcement'
                });
            }
        }
    }
    
    parseDMARC(dmarcRecord) {
        const dmarc = {
            exists: true,
            record: dmarcRecord,
            tags: {}
        };
        
        // Parse DMARC tags
        const parts = dmarcRecord.split(';').map(p => p.trim());
        
        parts.forEach(part => {
            if (part.includes('=')) {
                const [key, value] = part.split('=');
                dmarc.tags[key] = value;
            }
        });
        
        // Analyze DMARC configuration
        this.analyzeDMARC(dmarc);
        
        return dmarc;
    }
    
    analyzeDMARC(dmarc) {
        // Check policy
        if (!dmarc.tags.p || dmarc.tags.p === 'none') {
            this.results.vulnerabilities.push({
                type: 'dmarc-policy-none',
                severity: 'medium',
                description: 'DMARC policy set to none - not enforcing'
            });
        }
        
        // Check subdomain policy
        if (!dmarc.tags.sp) {
            this.results.vulnerabilities.push({
                type: 'dmarc-no-subdomain-policy',
                severity: 'low',
                description: 'No subdomain policy specified'
            });
        }
        
        // Check percentage
        if (dmarc.tags.pct && parseInt(dmarc.tags.pct) < 100) {
            this.results.vulnerabilities.push({
                type: 'dmarc-partial-enforcement',
                severity: 'medium',
                description: `DMARC only enforced on ${dmarc.tags.pct}% of messages`
            });
        }
        
        // Check reporting
        if (!dmarc.tags.rua && !dmarc.tags.ruf) {
            this.results.vulnerabilities.push({
                type: 'dmarc-no-reporting',
                severity: 'low',
                description: 'No DMARC reporting configured'
            });
        }
    }
    
    async checkMX() {
        console.log('=� Checking MX Records...');
        
        const mxRecords = await this.queryDNS(this.domain, 'MX');
        
        if (mxRecords) {
            this.results.mx = mxRecords.map(record => {
                const [priority, server] = record.data.split(' ');
                return { priority: parseInt(priority), server };
            }).sort((a, b) => a.priority - b.priority);
            
            console.log(` Found ${this.results.mx.length} MX records`);
        } else {
            console.log('L No MX records found');
        }
    }
    
    async checkDKIM() {
        console.log('= Checking DKIM Selectors...');
        
        // Common DKIM selectors to check
        const commonSelectors = [
            'default', 'selector1', 'selector2', 'google', 'googlemail',
            'mail', 'email', 'dkim', 'k1', 'k2', 'mandrill', 'mailgun',
            'sendgrid', 'smtp', 'postmark', 'amazonses', 'pm', 'mc'
        ];
        
        const dkimResults = [];
        
        // Check each selector
        for (const selector of commonSelectors) {
            const dkimRecord = await this.queryDNS(`${selector}._domainkey.${this.domain}`, 'TXT');
            
            if (dkimRecord && dkimRecord.length > 0) {
                const keyData = dkimRecord[0].data.replace(/"/g, '');
                if (keyData.includes('v=DKIM1')) {
                    dkimResults.push({
                        selector,
                        record: keyData,
                        parsed: this.parseDKIM(keyData)
                    });
                    console.log(`   Found DKIM selector: ${selector}`);
                }
            }
        }
        
        this.results.dkim = {
            selectors: dkimResults,
            found: dkimResults.length > 0
        };
        
        if (dkimResults.length === 0) {
            console.log('  � No common DKIM selectors found');
            this.results.vulnerabilities.push({
                type: 'no-dkim-found',
                severity: 'medium',
                description: 'No DKIM selectors found - emails cannot be cryptographically verified'
            });
        }
    }
    
    parseDKIM(dkimRecord) {
        const dkim = {
            tags: {}
        };
        
        const parts = dkimRecord.split(';').map(p => p.trim());
        
        parts.forEach(part => {
            if (part.includes('=')) {
                const [key, value] = part.split('=');
                dkim.tags[key] = value;
            }
        });
        
        return dkim;
    }
    
    checkVulnerabilities() {
        // Check for email spoofing vulnerabilities
        if (!this.results.spf || !this.results.spf.exists) {
            if (!this.results.dmarc || !this.results.dmarc.exists) {
                this.results.vulnerabilities.push({
                    type: 'no-email-auth',
                    severity: 'critical',
                    description: 'No email authentication - domain highly vulnerable to spoofing'
                });
            }
        }
        
        // Check for subdomain takeover via MX
        if (this.results.mx && this.results.mx.length > 0) {
            this.results.mx.forEach(mx => {
                if (mx.server.includes('expired') || mx.server.includes('parked')) {
                    this.results.vulnerabilities.push({
                        type: 'mx-subdomain-takeover',
                        severity: 'critical',
                        description: `MX record points to potentially vulnerable domain: ${mx.server}`
                    });
                }
            });
        }
    }
    
    generateReport() {
        console.log('\n=� Email Security Report\n');
        
        // SPF Report
        console.log('=� SPF (Sender Policy Framework):');
        if (this.results.spf && this.results.spf.exists) {
            console.log(`   Record: ${this.results.spf.record}`);
            console.log(`  Policy: ${this.results.spf.all || 'Not specified'}`);
            console.log(`  Includes: ${this.results.spf.includes.length}`);
            
            if (this.results.spf.ipv4.length > 0) {
                console.log(`  IPv4 ranges: ${this.results.spf.ipv4.length}`);
            }
        } else {
            console.log('  L No SPF record found');
        }
        
        // DKIM Report
        console.log('\n= DKIM (DomainKeys Identified Mail):');
        if (this.results.dkim && this.results.dkim.found) {
            console.log(`   Found ${this.results.dkim.selectors.length} selector(s):`);
            this.results.dkim.selectors.forEach(selector => {
                console.log(`    - ${selector.selector}`);
            });
        } else {
            console.log('  � No DKIM selectors found');
        }
        
        // DMARC Report
        console.log('\n=� DMARC (Domain-based Message Authentication):');
        if (this.results.dmarc && this.results.dmarc.exists) {
            console.log(`   Record: ${this.results.dmarc.record}`);
            console.log(`  Policy: ${this.results.dmarc.tags.p || 'none'}`);
            console.log(`  Subdomain Policy: ${this.results.dmarc.tags.sp || 'inherited'}`);
            console.log(`  Percentage: ${this.results.dmarc.tags.pct || '100'}%`);
            
            if (this.results.dmarc.tags.rua) {
                console.log(`  Aggregate Reports: ${this.results.dmarc.tags.rua}`);
            }
        } else {
            console.log('  L No DMARC record found');
        }
        
        // MX Report
        console.log('\n=� MX Records:');
        if (this.results.mx && this.results.mx.length > 0) {
            this.results.mx.forEach(mx => {
                console.log(`  ${mx.priority}: ${mx.server}`);
            });
        } else {
            console.log('  L No MX records found');
        }
        
        // Vulnerabilities
        if (this.results.vulnerabilities.length > 0) {
            console.log('\n� Security Issues Found:');
            
            const grouped = {
                critical: [],
                high: [],
                medium: [],
                low: []
            };
            
            this.results.vulnerabilities.forEach(vuln => {
                grouped[vuln.severity].push(vuln);
            });
            
            Object.entries(grouped).forEach(([severity, vulns]) => {
                if (vulns.length > 0) {
                    console.log(`\n${severity.toUpperCase()}:`);
                    vulns.forEach(vuln => {
                        console.log(`  - ${vuln.description}`);
                    });
                }
            });
        } else {
            console.log('\n No major security issues found');
        }
        
        // Recommendations
        this.generateRecommendations();
    }
    
    generateRecommendations() {
        console.log('\n=� Recommendations:\n');
        
        const recommendations = [];
        
        if (!this.results.spf || !this.results.spf.exists) {
            recommendations.push('1. Implement SPF record: "v=spf1 include:_spf.google.com ~all"');
        } else if (this.results.spf.all === '?all' || this.results.spf.all === '+all') {
            recommendations.push('1. Strengthen SPF policy to use -all or ~all');
        }
        
        if (!this.results.dmarc || !this.results.dmarc.exists) {
            recommendations.push('2. Implement DMARC record: "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com"');
        } else if (this.results.dmarc.tags.p === 'none') {
            recommendations.push('2. Strengthen DMARC policy from "none" to "quarantine" or "reject"');
        }
        
        if (!this.results.dkim || !this.results.dkim.found) {
            recommendations.push('3. Configure DKIM signing with your email provider');
        }
        
        recommendations.push('4. Monitor DMARC reports regularly');
        recommendations.push('5. Use separate subdomains for marketing emails');
        
        recommendations.forEach(rec => console.log(rec));
    }
}

// Run the analyzer
const emailAnalyzer = new EmailSecurityAnalyzer();
emailAnalyzer.analyzeEmailSecurity();

Understanding Email Authentication

SPF (Sender Policy Framework)

SPF allows domain owners to specify which mail servers are authorized to send email on behalf of their domain.

DKIM (DomainKeys Identified Mail)

DKIM provides a cryptographic signature that verifies the email hasn't been tampered with during transit.

DMARC (Domain-based Message Authentication)

DMARC builds on SPF and DKIM, providing policy enforcement and reporting capabilities.

Advanced Email Security Validator

// Comprehensive email security validation tool

class EmailSecurityValidator {
    constructor() {
        this.validationResults = {
            spf: { valid: false, errors: [], warnings: [] },
            dkim: { valid: false, errors: [], warnings: [] },
            dmarc: { valid: false, errors: [], warnings: [] }
        };
    }
    
    validateSPF(spfRecord) {
        console.log('=
 Validating SPF Record...\n');
        
        if (!spfRecord || !spfRecord.startsWith('v=spf1')) {
            this.validationResults.spf.errors.push('Invalid SPF version');
            return;
        }
        
        // Check for syntax errors
        const mechanisms = ['all', 'include', 'a', 'mx', 'ptr', 'ip4', 'ip6', 'exists'];
        const modifiers = ['redirect', 'exp'];
        
        const parts = spfRecord.split(' ');
        let lookupCount = 0;
        
        parts.forEach(part => {
            // Count DNS lookups
            if (part.startsWith('include:') || part.startsWith('a') || 
                part.startsWith('mx') || part.startsWith('exists:')) {
                lookupCount++;
            }
            
            // Check for duplicate mechanisms
            const duplicates = parts.filter(p => p === part).length;
            if (duplicates > 1) {
                this.validationResults.spf.warnings.push(`Duplicate mechanism: ${part}`);
            }
        });
        
        // DNS lookup limit
        if (lookupCount > 10) {
            this.validationResults.spf.errors.push(
                `Too many DNS lookups (${lookupCount}/10) - SPF will fail`
            );
        }
        
        // Check all mechanism
        const allMechanism = parts.find(p => p.includes('all'));
        if (!allMechanism) {
            this.validationResults.spf.warnings.push('No "all" mechanism specified');
        } else if (allMechanism === '+all') {
            this.validationResults.spf.errors.push('"+all" allows anyone to send - defeats purpose of SPF');
        }
        
        // Check for IPv6
        if (!parts.some(p => p.startsWith('ip6:'))) {
            this.validationResults.spf.warnings.push('No IPv6 addresses specified');
        }
        
        // Validate IP ranges
        parts.filter(p => p.startsWith('ip4:') || p.startsWith('ip6:')).forEach(ip => {
            if (!this.validateIPRange(ip)) {
                this.validationResults.spf.errors.push(`Invalid IP range: ${ip}`);
            }
        });
        
        this.validationResults.spf.valid = this.validationResults.spf.errors.length === 0;
        this.generateSPFReport();
    }
    
    validateIPRange(ipRange) {
        // Basic IP validation
        const ipv4Pattern = /^ip4:(\d{1,3}\.){3}\d{1,3}(\/\d{1,2})?$/;
        const ipv6Pattern = /^ip6:([0-9a-fA-F:]+)(\/\d{1,3})?$/;
        
        return ipv4Pattern.test(ipRange) || ipv6Pattern.test(ipRange);
    }
    
    validateDKIM(selector, dkimRecord) {
        console.log(`=
 Validating DKIM Selector: ${selector}...\n`);
        
        if (!dkimRecord || !dkimRecord.includes('v=DKIM1')) {
            this.validationResults.dkim.errors.push(`Invalid DKIM version for selector ${selector}`);
            return;
        }
        
        const tags = this.parseTags(dkimRecord);
        
        // Check for required public key
        if (!tags.p) {
            this.validationResults.dkim.errors.push(`No public key found for selector ${selector}`);
        } else if (tags.p === '') {
            this.validationResults.dkim.warnings.push(`DKIM key revoked for selector ${selector}`);
        }
        
        // Check key type
        if (tags.k && tags.k !== 'rsa') {
            this.validationResults.dkim.warnings.push(`Non-RSA key type: ${tags.k}`);
        }
        
        // Check service type
        if (tags.s && !tags.s.includes('email') && tags.s !== '*') {
            this.validationResults.dkim.errors.push(`DKIM not authorized for email: s=${tags.s}`);
        }
        
        // Check key size (if we could decode the key)
        if (tags.p && tags.p.length < 200) {
            this.validationResults.dkim.warnings.push('DKIM key might be too short (recommend 2048 bits)');
        }
        
        // Check flags
        if (tags.t) {
            if (tags.t.includes('y')) {
                this.validationResults.dkim.warnings.push('DKIM in testing mode (t=y)');
            }
            if (tags.t.includes('s')) {
                console.log('   Strict mode enabled (t=s)');
            }
        }
        
        this.validationResults.dkim.valid = this.validationResults.dkim.errors.length === 0;
    }
    
    validateDMARC(dmarcRecord) {
        console.log('=
 Validating DMARC Record...\n');
        
        if (!dmarcRecord || !dmarcRecord.includes('v=DMARC1')) {
            this.validationResults.dmarc.errors.push('Invalid DMARC version');
            return;
        }
        
        const tags = this.parseTags(dmarcRecord);
        
        // Required tags
        if (!tags.p) {
            this.validationResults.dmarc.errors.push('Missing required policy tag (p=)');
        } else if (!['none', 'quarantine', 'reject'].includes(tags.p)) {
            this.validationResults.dmarc.errors.push(`Invalid policy: ${tags.p}`);
        }
        
        // Validate percentage
        if (tags.pct) {
            const pct = parseInt(tags.pct);
            if (isNaN(pct) || pct < 0 || pct > 100) {
                this.validationResults.dmarc.errors.push(`Invalid percentage: ${tags.pct}`);
            } else if (pct < 100) {
                this.validationResults.dmarc.warnings.push(`Only ${pct}% of mail subject to policy`);
            }
        }
        
        // Validate alignment
        if (tags.adkim && !['r', 's'].includes(tags.adkim)) {
            this.validationResults.dmarc.errors.push(`Invalid DKIM alignment: ${tags.adkim}`);
        }
        
        if (tags.aspf && !['r', 's'].includes(tags.aspf)) {
            this.validationResults.dmarc.errors.push(`Invalid SPF alignment: ${tags.aspf}`);
        }
        
        // Check reporting
        if (!tags.rua && !tags.ruf) {
            this.validationResults.dmarc.warnings.push('No reporting addresses configured');
        }
        
        if (tags.rua) {
            // Validate email format
            const emails = tags.rua.split(',');
            emails.forEach(email => {
                if (!email.includes('mailto:')) {
                    this.validationResults.dmarc.errors.push(`Invalid RUA format: ${email}`);
                }
            });
        }
        
        // Check for subdomain policy
        if (!tags.sp) {
            this.validationResults.dmarc.warnings.push('No subdomain policy (sp) specified');
        }
        
        this.validationResults.dmarc.valid = this.validationResults.dmarc.errors.length === 0;
        this.generateDMARCReport();
    }
    
    parseTags(record) {
        const tags = {};
        const parts = record.split(';').map(p => p.trim());
        
        parts.forEach(part => {
            if (part.includes('=')) {
                const [key, value] = part.split('=', 2);
                tags[key.trim()] = value.trim();
            }
        });
        
        return tags;
    }
    
    generateSPFReport() {
        console.log('=� SPF Validation Results:\n');
        
        if (this.validationResults.spf.valid) {
            console.log(' SPF record is valid');
        } else {
            console.log('L SPF record has errors:');
            this.validationResults.spf.errors.forEach(error => {
                console.log(`  - ${error}`);
            });
        }
        
        if (this.validationResults.spf.warnings.length > 0) {
            console.log('\n� SPF Warnings:');
            this.validationResults.spf.warnings.forEach(warning => {
                console.log(`  - ${warning}`);
            });
        }
    }
    
    generateDMARCReport() {
        console.log('\n=� DMARC Validation Results:\n');
        
        if (this.validationResults.dmarc.valid) {
            console.log(' DMARC record is valid');
        } else {
            console.log('L DMARC record has errors:');
            this.validationResults.dmarc.errors.forEach(error => {
                console.log(`  - ${error}`);
            });
        }
        
        if (this.validationResults.dmarc.warnings.length > 0) {
            console.log('\n� DMARC Warnings:');
            this.validationResults.dmarc.warnings.forEach(warning => {
                console.log(`  - ${warning}`);
            });
        }
    }
}

// Example usage:
const validator = new EmailSecurityValidator();
// validator.validateSPF('v=spf1 include:_spf.google.com ~all');
// validator.validateDMARC('v=DMARC1; p=reject; rua=mailto:dmarc@example.com');

Email Security Implementation Guide

1. SPF Implementation

// SPF record builder
class SPFBuilder {
    constructor(domain) {
        this.domain = domain;
        this.mechanisms = ['v=spf1'];
    }
    
    addInclude(domain) {
        this.mechanisms.push(`include:${domain}`);
        return this;
    }
    
    addIP4(ip, cidr = null) {
        this.mechanisms.push(`ip4:${ip}${cidr ? '/' + cidr : ''}`);
        return this;
    }
    
    addIP6(ip, cidr = null) {
        this.mechanisms.push(`ip6:${ip}${cidr ? '/' + cidr : ''}`);
        return this;
    }
    
    addA(domain = null) {
        this.mechanisms.push(domain ? `a:${domain}` : 'a');
        return this;
    }
    
    addMX(domain = null) {
        this.mechanisms.push(domain ? `mx:${domain}` : 'mx');
        return this;
    }
    
    setAll(qualifier) {
        // Remove any existing all mechanism
        this.mechanisms = this.mechanisms.filter(m => !m.includes('all'));
        this.mechanisms.push(`${qualifier}all`);
        return this;
    }
    
    build() {
        // Ensure we have an all mechanism
        if (!this.mechanisms.some(m => m.includes('all'))) {
            this.mechanisms.push('~all');
        }
        
        const record = this.mechanisms.join(' ');
        
        // Validate length
        if (record.length > 255) {
            console.warn('� SPF record exceeds 255 characters - may need to be split');
        }
        
        return record;
    }
    
    validate() {
        const record = this.build();
        const lookups = this.mechanisms.filter(m => 
            m.startsWith('include:') || 
            m === 'a' || m.startsWith('a:') ||
            m === 'mx' || m.startsWith('mx:') ||
            m.startsWith('exists:')
        ).length;
        
        console.log('SPF Validation:');
        console.log(`  Length: ${record.length}/255 characters`);
        console.log(`  DNS Lookups: ${lookups}/10`);
        console.log(`  Record: ${record}`);
        
        return lookups <= 10 && record.length <= 255;
    }
}

// Example SPF for common providers
const commonSPFIncludes = {
    google: 'include:_spf.google.com',
    microsoft: 'include:spf.protection.outlook.com',
    sendgrid: 'include:sendgrid.net',
    mailchimp: 'include:servers.mcsv.net',
    amazonSES: 'include:amazonses.com',
    mailgun: 'include:mailgun.org'
};

// Build SPF record
const spfBuilder = new SPFBuilder('example.com');
const spfRecord = spfBuilder
    .addInclude('_spf.google.com')
    .addInclude('spf.protection.outlook.com')
    .addIP4('192.168.1.1')
    .setAll('~')
    .build();

console.log('Generated SPF:', spfRecord);

2. DMARC Implementation

// DMARC policy builder
class DMARCBuilder {
    constructor() {
        this.tags = {
            v: 'DMARC1'
        };
    }
    
    setPolicy(policy) {
        if (!['none', 'quarantine', 'reject'].includes(policy)) {
            throw new Error('Invalid policy. Use: none, quarantine, or reject');
        }
        this.tags.p = policy;
        return this;
    }
    
    setSubdomainPolicy(policy) {
        if (!['none', 'quarantine', 'reject'].includes(policy)) {
            throw new Error('Invalid subdomain policy');
        }
        this.tags.sp = policy;
        return this;
    }
    
    setPercentage(pct) {
        if (pct < 0 || pct > 100) {
            throw new Error('Percentage must be between 0 and 100');
        }
        this.tags.pct = pct;
        return this;
    }
    
    addAggregateReporting(email) {
        if (!this.tags.rua) {
            this.tags.rua = '';
        }
        const mailto = email.startsWith('mailto:') ? email : `mailto:${email}`;
        this.tags.rua += (this.tags.rua ? ',' : '') + mailto;
        return this;
    }
    
    addForensicReporting(email) {
        if (!this.tags.ruf) {
            this.tags.ruf = '';
        }
        const mailto = email.startsWith('mailto:') ? email : `mailto:${email}`;
        this.tags.ruf += (this.tags.ruf ? ',' : '') + mailto;
        return this;
    }
    
    setAlignment(spf = 'r', dkim = 'r') {
        if (!['r', 's'].includes(spf)) {
            throw new Error('SPF alignment must be "r" (relaxed) or "s" (strict)');
        }
        if (!['r', 's'].includes(dkim)) {
            throw new Error('DKIM alignment must be "r" (relaxed) or "s" (strict)');
        }
        this.tags.aspf = spf;
        this.tags.adkim = dkim;
        return this;
    }
    
    setReportingOptions(options = []) {
        if (options.length > 0) {
            this.tags.fo = options.join(':');
        }
        return this;
    }
    
    build() {
        if (!this.tags.p) {
            throw new Error('Policy (p) is required');
        }
        
        const record = Object.entries(this.tags)
            .map(([key, value]) => `${key}=${value}`)
            .join('; ');
        
        return record;
    }
    
    generateImplementationPlan() {
        console.log('\n=� DMARC Implementation Plan:\n');
        
        console.log('Phase 1 - Monitor Mode (4 weeks):');
        console.log('  ' + new DMARCBuilder()
            .setPolicy('none')
            .addAggregateReporting('dmarc@yourdomain.com')
            .build());
        
        console.log('\nPhase 2 - Quarantine Mode (4 weeks):');
        console.log('  ' + new DMARCBuilder()
            .setPolicy('quarantine')
            .setPercentage(25)
            .addAggregateReporting('dmarc@yourdomain.com')
            .build());
        
        console.log('\nPhase 3 - Gradual Enforcement:');
        console.log('  Week 1-2: pct=50');
        console.log('  Week 3-4: pct=100');
        
        console.log('\nPhase 4 - Full Rejection:');
        console.log('  ' + new DMARCBuilder()
            .setPolicy('reject')
            .setSubdomainPolicy('reject')
            .addAggregateReporting('dmarc@yourdomain.com')
            .build());
    }
}

// Generate DMARC implementation plan
const dmarcBuilder = new DMARCBuilder();
dmarcBuilder.generateImplementationPlan();

Email Security Monitoring

// Monitor email authentication results
class EmailAuthMonitor {
    constructor() {
        this.results = {
            spf: { pass: 0, fail: 0, softfail: 0, neutral: 0 },
            dkim: { pass: 0, fail: 0 },
            dmarc: { pass: 0, fail: 0, quarantine: 0, reject: 0 }
        };
    }
    
    parseAuthenticationResults(headers) {
        // Parse Authentication-Results header
        const authResults = headers['Authentication-Results'];
        if (!authResults) return;
        
        // SPF results
        const spfMatch = authResults.match(/spf=(\w+)/);
        if (spfMatch) {
            const result = spfMatch[1];
            if (this.results.spf[result] !== undefined) {
                this.results.spf[result]++;
            }
        }
        
        // DKIM results
        const dkimMatch = authResults.match(/dkim=(\w+)/);
        if (dkimMatch) {
            const result = dkimMatch[1];
            if (this.results.dkim[result] !== undefined) {
                this.results.dkim[result]++;
            }
        }
        
        // DMARC results
        const dmarcMatch = authResults.match(/dmarc=(\w+)/);
        if (dmarcMatch) {
            const result = dmarcMatch[1];
            if (this.results.dmarc[result] !== undefined) {
                this.results.dmarc[result]++;
            }
        }
    }
    
    generateReport() {
        console.log('=� Email Authentication Monitoring Report\n');
        
        // SPF Results
        const spfTotal = Object.values(this.results.spf).reduce((a, b) => a + b, 0);
        console.log('SPF Results:');
        Object.entries(this.results.spf).forEach(([result, count]) => {
            const percentage = spfTotal > 0 ? ((count / spfTotal) * 100).toFixed(1) : 0;
            console.log(`  ${result}: ${count} (${percentage}%)`);
        });
        
        // DKIM Results
        const dkimTotal = Object.values(this.results.dkim).reduce((a, b) => a + b, 0);
        console.log('\nDKIM Results:');
        Object.entries(this.results.dkim).forEach(([result, count]) => {
            const percentage = dkimTotal > 0 ? ((count / dkimTotal) * 100).toFixed(1) : 0;
            console.log(`  ${result}: ${count} (${percentage}%)`);
        });
        
        // DMARC Results
        const dmarcTotal = Object.values(this.results.dmarc).reduce((a, b) => a + b, 0);
        console.log('\nDMARC Results:');
        Object.entries(this.results.dmarc).forEach(([result, count]) => {
            const percentage = dmarcTotal > 0 ? ((count / dmarcTotal) * 100).toFixed(1) : 0;
            console.log(`  ${result}: ${count} (${percentage}%)`);
        });
        
        // Overall health score
        const spfPassRate = spfTotal > 0 ? (this.results.spf.pass / spfTotal) : 0;
        const dkimPassRate = dkimTotal > 0 ? (this.results.dkim.pass / dkimTotal) : 0;
        const dmarcPassRate = dmarcTotal > 0 ? (this.results.dmarc.pass / dmarcTotal) : 0;
        
        const healthScore = ((spfPassRate + dkimPassRate + dmarcPassRate) / 3 * 100).toFixed(1);
        
        console.log(`\n<� Overall Email Authentication Health: ${healthScore}%`);
        
        if (healthScore < 90) {
            console.log('\n� Action Required:');
            if (spfPassRate < 0.9) console.log('  - Investigate SPF failures');
            if (dkimPassRate < 0.9) console.log('  - Check DKIM signing configuration');
            if (dmarcPassRate < 0.9) console.log('  - Review DMARC policy alignment');
        }
    }
}

Common Email Security Issues

1. SPF Lookup Limit

Maximum 10 DNS lookups allowed per SPF check.

2. DKIM Key Rotation

Regular key rotation prevents long-term key compromise.

3. DMARC Alignment

Ensure From domain aligns with SPF and DKIM domains.

Real-World Breach Examples

1. Business Email Compromise (2019)

Attackers spoofed CEO emails to request wire transfers, causing $1.7 billion in losses.

2. Phishing Campaign (2020)

Lack of DMARC allowed attackers to spoof major brands in COVID-19 phishing emails.

3. Domain Hijacking (2021)

Expired DKIM selectors were exploited to send authenticated spam.

Best Practices Implementation

// Email security best practices checker
const emailSecurityBestPractices = {
    spf: {
        'Use specific includes': 'Avoid broad includes that authorize too many servers',
        'Set strict policy': 'Use -all instead of ~all for production',
        'Monitor lookups': 'Stay under 10 DNS lookup limit',
        'Document includes': 'Maintain list of why each include is needed',
        'Regular audits': 'Review and remove unnecessary includes'
    },
    
    dkim: {
        'Key strength': 'Use 2048-bit RSA keys minimum',
        'Key rotation': 'Rotate keys every 6-12 months',
        'Multiple selectors': 'Use different selectors for different systems',
        'Revoke old keys': 'Set p= empty for revoked selectors',
        'Monitor signing': 'Ensure all outbound mail is signed'
    },
    
    dmarc: {
        'Gradual rollout': 'Start with p=none, then quarantine, then reject',
        'Monitor reports': 'Review aggregate reports weekly',
        'Subdomain policy': 'Set explicit sp= policy',
        'Forensic reports': 'Enable ruf= for detailed failure analysis',
        'Third-party authorization': 'Audit all authorized senders'
    },
    
    general: {
        'Separate subdomains': 'Use subdomains for marketing/transactional email',
        'Monitor deliverability': 'Track inbox placement rates',
        'Incident response': 'Have plan for domain abuse',
        'Documentation': 'Document all email sending sources',
        'Regular testing': 'Use tools to verify authentication'
    }
};

// Display best practices
Object.entries(emailSecurityBestPractices).forEach(([category, practices]) => {
    console.log(`\n${category.toUpperCase()} Best Practices:`);
    Object.entries(practices).forEach(([practice, description]) => {
        console.log(`   ${practice}: ${description}`);
    });
});

Conclusion

Email authentication using SPF, DKIM, and DMARC is essential for protecting your domain from abuse and ensuring email deliverability. Regular monitoring and gradual implementation of stricter policies helps maintain a balance between security and legitimate email delivery. Remember that email security is an ongoing process requiring regular audits and updates as your email infrastructure evolves.