JSPM

@bernierllc/smtp-analyzer

0.1.4
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q68174F
  • License PROPRIETARY

Pure atomic SMTP header analysis and email authentication parsing utilities

Package Exports

  • @bernierllc/smtp-analyzer
  • @bernierllc/smtp-analyzer/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@bernierllc/smtp-analyzer) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@bernierllc/smtp-analyzer

Pure atomic SMTP header analysis and email authentication parsing utilities. Analyze SMTP delivery paths, authentication results (SPF, DKIM, DMARC, ARC), bounce messages, and routing information without any external dependencies.

Installation

npm install @bernierllc/smtp-analyzer

Features

  • SMTP Header Parsing - Parse and validate SMTP headers with support for multi-line (folded) headers
  • Delivery Path Analysis - Extract complete delivery path with hop-by-hop analysis
  • Authentication Analysis - Parse SPF, DKIM, DMARC, and ARC authentication results
  • Bounce Message Detection - Detect and parse bounce messages with DSN (Delivery Status Notification) support
  • Routing Information - Analyze mail server routing, relays, and transport security (TLS)
  • Security Analysis - Extract and analyze security-related headers
  • Evidence-Rich Output - All analysis includes original header data for verification
  • Zero Dependencies - Completely self-contained with no external dependencies
  • TypeScript First - Full type safety with comprehensive type definitions

Usage

Quick Start

import { analyzeSMTPHeadersFromRaw } from '@bernierllc/smtp-analyzer';

// Analyze complete email headers
const rawHeaders = `
Received: from mail.sender.com by mx.google.com with ESMTPS;
  Tue, 8 Oct 2024 10:30:45 -0700
Authentication-Results: mx.google.com;
  spf=pass smtp.mailfrom=sender@example.com;
  dkim=pass header.d=example.com;
  dmarc=pass
From: sender@example.com
To: recipient@example.com
Subject: Important Message
`;

const result = analyzeSMTPHeadersFromRaw(rawHeaders);

if (result.success) {
  const analysis = result.data;

  console.log('Authentication:', analysis.authentication.spf.result); // 'pass'
  console.log('Delivery Hops:', analysis.routing.hopCount);
  console.log('Secure Transport:', analysis.routing.hasSecureTransport);
}

Analyzing Delivery Path

import { parseHeaders, parseDeliveryPath, extractRoutingInfo } from '@bernierllc/smtp-analyzer';

const headers = parseHeaders(rawHeaders);
const receivedHeaders = headers['received'];

// Parse delivery path (chronologically ordered)
const hops = parseDeliveryPath(Array.isArray(receivedHeaders) ? receivedHeaders : [receivedHeaders]);

hops.forEach((hop, index) => {
  console.log(`Hop ${index + 1}:`);
  console.log(`  Server: ${hop.server}`);
  console.log(`  From: ${hop.from}`);
  console.log(`  Protocol: ${hop.protocol}`);
  console.log(`  TLS: ${hop.tls ? 'Yes' : 'No'}`);
  console.log(`  Timestamp: ${hop.timestamp}`);
});

// Extract routing information
const routing = extractRoutingInfo(hops);
console.log('Originating IP:', routing.originatingIp);
console.log('Final Destination:', routing.finalDestination);
console.log('Total Hops:', routing.hopCount);
console.log('Has Secure Transport:', routing.hasSecureTransport);

Authentication Analysis

import { parseAuthenticationResults, isAuthenticationPassed } from '@bernierllc/smtp-analyzer';

const authHeader = 'mx.google.com; spf=pass smtp.mailfrom=sender@example.com; dkim=pass header.d=example.com; dmarc=pass';

const auth = parseAuthenticationResults(authHeader);

console.log('SPF Result:', auth.spf.result);
console.log('SPF Mechanism:', auth.spf.mechanism);
console.log('DKIM Result:', auth.dkim.result);
console.log('DKIM Domain:', auth.dkim.domain);
console.log('DMARC Result:', auth.dmarc.result);

// Check if all authentication passed
if (isAuthenticationPassed(auth)) {
  console.log('Email is fully authenticated');
}

Bounce Message Analysis

import { parseBounceMessage, isPermanentBounce } from '@bernierllc/smtp-analyzer';

const bounceContent = `
Delivery to the following recipient failed permanently:
     invalid@nonexistent.com

Technical details:
550-5.1.1 The email account that you tried to reach does not exist.

Final-Recipient: rfc822; invalid@nonexistent.com
Action: failed
Status: 5.1.1
`;

const bounce = parseBounceMessage(
  bounceContent,
  'Delivery Status Notification (Failure)',
  'mailer-daemon@googlemail.com'
);

if (bounce.isBounce) {
  console.log('Bounce Type:', bounce.bounceType); // 'hard'
  console.log('Original Recipient:', bounce.originalRecipient);
  console.log('Reason:', bounce.reason);

  if (bounce.dsn) {
    console.log('DSN Action:', bounce.dsn.action);
    console.log('DSN Status Code:', bounce.dsn.statusCode);
    console.log('Diagnostic Code:', bounce.dsn.diagnosticCode);
  }

  // Check if permanent bounce
  if (isPermanentBounce(bounce)) {
    console.log('This is a permanent bounce - remove recipient');
  }
}

Complete Analysis

import { analyzeSMTPHeaders, getSummary, isEmailAuthenticated } from '@bernierllc/smtp-analyzer';

const analysis = analyzeSMTPHeaders({
  'received': [
    'from mail.sender.com by mx.google.com with ESMTPS; Tue, 8 Oct 2024 10:30:45 -0700',
    'from localhost by mail.sender.com with SMTP; Tue, 8 Oct 2024 13:30:40 -0400',
  ],
  'authentication-results': 'mx.google.com; spf=pass; dkim=pass; dmarc=pass',
  'from': 'sender@example.com',
  'to': 'recipient@example.com',
  'message-id': '<abc123@example.com>',
  'date': 'Tue, 8 Oct 2024 13:30:40 -0400',
});

// Get human-readable summary
console.log(getSummary(analysis));
// Output:
// Delivery Path: 2 hops
// SPF: pass
// DKIM: pass
// DMARC: pass
// Secure Transport: Yes
// Delivery Time: 5s

// Check authentication
if (isEmailAuthenticated(analysis)) {
  console.log('Email is authenticated');
}

// Check for bounce
if (analysis.bounce?.isBounce) {
  console.log('This is a bounce message');
}

Security Analysis

import { detectSuspiciousPatterns, identifyRelays } from '@bernierllc/smtp-analyzer';

const hops = parseDeliveryPath(receivedHeaders);

// Detect suspicious patterns
const issues = detectSuspiciousPatterns(hops);
if (issues.length > 0) {
  console.log('Security concerns detected:');
  issues.forEach(issue => console.log(`  - ${issue}`));
}

// Identify relay servers
const relays = identifyRelays(hops);
console.log('Relay servers:', relays);

API Reference

Main Analyzer

analyzeSMTPHeaders(headers: ParsedHeaders): SMTPAnalysis

Analyze SMTP headers and extract all relevant information.

Parameters:

  • headers - Parsed headers object (use parseHeaders() to convert raw headers)

Returns: Complete SMTP analysis including:

  • deliveryPath - Array of SMTP hops
  • authentication - SPF, DKIM, DMARC, ARC results
  • routing - Routing and relay information
  • deliveryStatus - Delivery status and timing
  • securityHeaders - Security-related headers
  • bounce - Bounce information (if applicable)

analyzeSMTPHeadersFromRaw(rawHeaders: string): AnalysisResult<SMTPAnalysis>

Convenience wrapper that parses headers and performs analysis.

Parameters:

  • rawHeaders - Raw email headers as string

Returns: Result wrapper with success flag and data or error

Header Parsing

parseHeaders(rawHeaders: string): ParsedHeaders

Parse email headers from raw header string. Handles multi-line (folded) headers per RFC 5322.

getHeader(headers: ParsedHeaders, name: string): string | string[] | undefined

Get header value(s). Returns array if multiple values exist.

getHeaderArray(headers: ParsedHeaders, name: string): string[]

Get all values for a header as array (even if single value).

getHeaderFirst(headers: ParsedHeaders, name: string): string | undefined

Get first value for a header (useful for headers that should be unique).

extractEmailAddress(headerValue: string): string | null

Extract email address from header value (handles various formats).

parseHeaderDate(dateString: string): Date | null

Parse date from header value (RFC 5322 format).

Delivery Path Analysis

parseDeliveryPath(receivedHeaders: string[]): SMTPHop[]

Parse delivery path from Received headers. Returns hops in chronological order (oldest first).

extractRoutingInfo(hops: SMTPHop[]): RoutingInfo

Extract routing information from delivery path.

calculateDeliveryTime(hops: SMTPHop[]): number | null

Calculate delivery time from first to last hop. Returns time in milliseconds.

identifyRelays(hops: SMTPHop[]): string[]

Identify relay servers in the delivery path.

detectSuspiciousPatterns(hops: SMTPHop[]): string[]

Detect suspicious patterns in delivery path. Returns array of detected issues.

Authentication Parsing

parseAuthenticationResults(authHeader: string): AuthenticationResults

Parse Authentication-Results header.

parseReceivedSPF(receivedSpfHeader: string): SPFDetails

Parse Received-SPF header.

parseDKIMSignature(dkimSignature: string): DKIMDetails

Parse DKIM-Signature header.

isAuthenticationPassed(results: AuthenticationResults): boolean

Check if authentication passed all checks.

getAuthenticationSummary(results: AuthenticationResults): string

Get authentication status summary.

Bounce Message Parsing

detectBounce(subject: string, from: string, contentType?: string): boolean

Detect if email is a bounce message.

parseBounceMessage(emailContent: string, subject?: string, from?: string): BounceInfo

Parse bounce message to extract details.

parseDSN(content: string): DSNDetails | null

Parse DSN (Delivery Status Notification) from email content.

isPermanentBounce(bounceInfo: BounceInfo): boolean

Check if bounce is permanent (hard bounce).

isTemporaryBounce(bounceInfo: BounceInfo): boolean

Check if bounce is temporary (soft bounce).

Types

Core Types

interface SMTPAnalysis {
  deliveryPath: SMTPHop[];
  authentication: AuthenticationResults;
  routing: RoutingInfo;
  deliveryStatus: DeliveryInfo;
  securityHeaders: SecurityHeaders;
  bounce?: BounceInfo;
}

interface SMTPHop {
  server: string;
  timestamp: Date | null;
  protocol: string;
  from: string;
  for: string;
  id?: string;
  with?: string;
  tls?: boolean;
  raw: string;
}

interface AuthenticationResults {
  spf: SPFDetails;
  dkim: DKIMDetails;
  dmarc: DMARCDetails;
  arc: ARCDetails;
  rawHeader?: string;
}

interface RoutingInfo {
  originatingIp?: string;
  originatingServer?: string;
  finalDestination?: string;
  hopCount: number;
  totalHops: SMTPHop[];
  hasSecureTransport: boolean;
}

interface BounceInfo {
  isBounce: boolean;
  bounceType?: 'hard' | 'soft' | 'general' | 'unknown';
  dsn?: DSNDetails;
  originalRecipient?: string;
  reason?: string;
  diagnosticCode?: string;
}

Production Use Cases

  • Email Security Monitoring - Analyze authentication failures and detect spoofing
  • Deliverability Analytics - Track delivery path performance and identify issues
  • Compliance Auditing - Verify authentication compliance (SPF, DKIM, DMARC)
  • Spam Detection - Analyze sender reputation signals and delivery patterns
  • Email Forensics - Investigate email origin and routing for security analysis
  • Bounce Management - Parse and categorize bounce messages for list hygiene
  • Transport Security - Monitor TLS usage across delivery paths

Integration Status

  • Logger Integration: Not applicable - This is a pure utility package with no internal logging needs. Applications using this package can optionally integrate @bernierllc/logger for logging analysis results or errors at the application level.
  • Docs-Suite: Ready - Complete TypeDoc documentation with examples
  • NeverHub Integration: Not applicable - This is a core utility package with no orchestration needs. The package works independently and does not require @bernierllc/neverhub-adapter for service discovery or event communication.

License

Copyright (c) 2025 Bernier LLC. All rights reserved.

This package is licensed to the client under a limited-use license. The client may use and modify this code only within the scope of the project it was delivered for. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.