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.