@bernierllc/validators-email
TypeScript icon, indicating that this package has built-in type declarations

0.7.0 • Public • Published

@bernierllc/validators-email

Email content validation - composite domain validator for email campaigns

Overview

@bernierllc/validators-email is a comprehensive domain-level validator that orchestrates multiple primitive validators to provide complete email validation. It validates HTML syntax, MIME structure, link integrity, image assets, tracking parameters, and URL normalization for email campaigns.

Installation

npm install @bernierllc/validators-email

Features

  • HTML Syntax Validation - Validates email HTML for well-formedness
  • MIME Structure Validation - Validates multipart email structure
  • Link Integrity - Validates all links in email content
  • Image Asset Validation - Validates image sources, alt text, and dimensions
  • Tracking Parameter Validation - Validates UTM and custom tracking parameters
  • URL Normalization - Normalizes URLs for consistency
  • Composite Architecture - Orchestrates multiple primitive validators
  • Configurable Rules - Enable/disable specific validation rules
  • Detailed Problem Reporting - Returns detailed validation problems with locations

Usage

Basic Usage

import { validateEmail } from '@bernierllc/validators-email';
import { createSharedUtils } from '@bernierllc/validators-utils';

const utils = createSharedUtils();

const email = {
  html: `
    <!DOCTYPE html>
    <html>
      <body>
        <h1>Welcome!</h1>
        <p>Thank you for subscribing to our newsletter.</p>
        <a href="https://example.com?utm_source=email&utm_campaign=welcome">
          Visit our website
        </a>
        <img src="https://example.com/logo.png" alt="Company Logo" width="200" />
      </body>
    </html>
  `,
  subject: 'Welcome to Our Newsletter',
  text: 'Welcome! Thank you for subscribing.',
};

const result = await validateEmail(email, {}, utils);

if (result.problems.length === 0) {
  console.log('✓ Email is valid!');
} else {
  console.log('Email validation issues:');
  result.problems.forEach(problem => {
    console.log(`- ${problem.message} (${problem.ruleId})`);
  });
}

console.log(`Validation completed in ${result.stats.durationMs}ms`);
console.log(`Rules applied: ${result.stats.rulesApplied.join(', ')}`);

Creating a Configured Validator

import { createEmailValidator } from '@bernierllc/validators-email';
import { createSharedUtils } from '@bernierllc/validators-utils';

const utils = createSharedUtils();

// Create validator with custom options
const validator = createEmailValidator({
  validateHtml: true,
  validateLinks: true,
  validateImages: true,
  validateTracking: true,
  normalizeUrls: true,
  validateMime: false, // Skip MIME validation
  severity: 'warning',
});

// Get validator metadata
const meta = validator.getMeta();
console.log('Validator:', meta.name);
console.log('Enabled rules:', meta.enabledRules);

// Validate email
const email = {
  html: '<html><body><h1>Test Email</h1></body></html>',
  subject: 'Test',
};

const result = await validator.validate(email, utils);

Selective Validation

import { validateEmail } from '@bernierllc/validators-email';
import { createSharedUtils } from '@bernierllc/validators-utils';

const utils = createSharedUtils();

// Only validate HTML and links, skip images and tracking
const result = await validateEmail(
  {
    html: '<html><body><a href="https://example.com">Link</a></body></html>',
  },
  {
    validateHtml: true,
    validateLinks: true,
    validateImages: false,
    validateTracking: false,
    validateMime: false,
  },
  utils
);

MIME Structure Validation

import { validateEmail } from '@bernierllc/validators-email';
import { createSharedUtils } from '@bernierllc/validators-utils';

const utils = createSharedUtils();

const email = {
  html: '<html><body><p>HTML version</p></body></html>',
  mime: `Content-Type: multipart/alternative; boundary="boundary123"

--boundary123
Content-Type: text/plain

Plain text version

--boundary123
Content-Type: text/html

<html><body><p>HTML version</p></body></html>

--boundary123--`,
};

const result = await validateEmail(
  email,
  { validateMime: true },
  utils
);

Campaign Email Validation

import { validateEmail } from '@bernierllc/validators-email';
import { createSharedUtils } from '@bernierllc/validators-utils';

const utils = createSharedUtils();

const campaignEmail = {
  html: `
    <!DOCTYPE html>
    <html>
      <head>
        <title>Summer Sale 2025</title>
      </head>
      <body>
        <h1>Summer Sale - 50% Off!</h1>
        <p>Don't miss our biggest sale of the year.</p>

        <a href="https://example.com/sale?utm_source=email&utm_medium=newsletter&utm_campaign=summer_sale">
          Shop Now
        </a>

        <img
          src="https://example.com/images/summer-banner.jpg"
          alt="Summer Sale Banner"
          width="600"
          height="200"
        />

        <p>
          <a href="https://example.com/unsubscribe?email={{email}}&token={{token}}">
            Unsubscribe
          </a>
        </p>
      </body>
    </html>
  `,
  subject: 'Summer Sale - 50% Off Everything!',
  text: 'Summer Sale - 50% Off! Visit https://example.com/sale',
  metadata: {
    from: 'sales@example.com',
    to: ['subscriber@example.com'],
  },
};

const result = await validateEmail(
  campaignEmail,
  {
    validateHtml: true,
    validateLinks: true,
    validateImages: true,
    validateTracking: true,
    normalizeUrls: true,
  },
  utils
);

// Check specific validation results
const htmlProblems = result.problems.filter(p => p.ruleId?.includes('html'));
const linkProblems = result.problems.filter(p => p.ruleId?.includes('link'));
const trackingProblems = result.problems.filter(p => p.ruleId?.includes('tracking'));

console.log(`HTML issues: ${htmlProblems.length}`);
console.log(`Link issues: ${linkProblems.length}`);
console.log(`Tracking issues: ${trackingProblems.length}`);

API Reference

validateEmail(email, options, utils)

Validates email content using composed primitive validators.

Parameters:

  • email: EmailContent - Email content to validate
  • options: EmailValidationOptions - Validation options (optional)
  • utils: SharedUtils - Shared utilities from validators-utils

Returns: Promise<ValidationResult>

createEmailValidator(options)

Creates a configured email validator instance.

Parameters:

  • options: EmailValidationOptions - Validation options (optional)

Returns: Object with validate() and getMeta() methods

Types

EmailContent

interface EmailContent {
  html: string;                    // HTML body content (required)
  text?: string;                   // Plain text alternative
  subject?: string;                // Email subject line
  mime?: string;                   // Raw MIME content for multipart validation
  metadata?: {                     // Email metadata
    from?: string;
    to?: string[];
    cc?: string[];
    bcc?: string[];
    headers?: Record<string, string>;
  };
}

EmailValidationOptions

interface EmailValidationOptions {
  validateHtml?: boolean;          // Validate HTML syntax (default: true)
  validateMime?: boolean;          // Validate MIME structure (default: true)
  validateLinks?: boolean;         // Validate links (default: true)
  validateImages?: boolean;        // Validate images (default: true)
  validateTracking?: boolean;      // Validate tracking params (default: true)
  normalizeUrls?: boolean;         // Normalize URLs (default: true)
  severity?: 'error' | 'warning' | 'info'; // Problem severity (default: 'error')
}

Validation Rules

HTML Syntax (email/html-syntax)

  • Malformed tags
  • Unclosed tags
  • Invalid nesting
  • Duplicate IDs
  • Malformed attributes

MIME Structure (email/mime-structure)

  • Valid multipart boundaries
  • Proper content-type headers
  • Correct MIME part structure

Link Integrity (email/link-integrity)

  • Valid URL format
  • Reachable links (when network checking enabled)
  • Proper protocol (http/https)
  • No broken anchors

Image Assets (email/image-assets)

  • Valid image source URLs
  • Alt text presence
  • Dimension attributes
  • Proper image formats

Tracking Parameters (email/tracking-params)

  • Valid UTM parameters (utm_source, utm_medium, utm_campaign, etc.)
  • Custom tracking parameters (mc_, track_)
  • Parameter value validation

URL Normalization (email/url-normalization)

  • Consistent URL formatting
  • Protocol normalization
  • Domain case normalization
  • Path normalization

Composed Primitives

This domain validator orchestrates the following primitive validators:

  • @bernierllc/validators-html-syntax - HTML syntax validation
  • @bernierllc/validators-mime-structure - MIME structure validation
  • @bernierllc/validators-link-integrity - Link validation
  • @bernierllc/validators-image-asset - Image validation
  • @bernierllc/validators-tracking-params - Tracking parameter validation
  • @bernierllc/validators-url-normalization - URL normalization

Integration Status

  • Logger integration: not-applicable - Validators use @bernierllc/validators-reporters for output and problem reporting. Validators are pure functions that return structured results rather than logging directly.
  • Docs-Suite: ready - Full TypeDoc documentation with examples
  • NeverHub integration: not-applicable - Validators are pure, stateless functions with no need for service discovery. The @bernierllc/neverhub-adapter is not needed for this package type. Validators return structured validation results that can be consumed by any system.

Dependencies

Runtime

  • @bernierllc/validators-core - Core validation framework
  • @bernierllc/validators-runner - Validation runner
  • @bernierllc/validators-html-syntax - HTML syntax primitive
  • @bernierllc/validators-mime-structure - MIME structure primitive
  • @bernierllc/validators-link-integrity - Link integrity primitive
  • @bernierllc/validators-image-asset - Image asset primitive
  • @bernierllc/validators-tracking-params - Tracking params primitive
  • @bernierllc/validators-url-normalization - URL normalization primitive

Development

  • TypeScript 5.0+
  • Jest for testing (comprehensive test suite present - ESM compatibility in progress)
  • ESLint for linting

MECE Architecture

This package follows MECE (Mutually Exclusive, Collectively Exhaustive) principles as a domain validator:

  • Domain Level - Orchestrates multiple primitive validators for email validation
  • Composite Pattern - Combines atomic validators for comprehensive validation
  • Single Responsibility - Focused on email content validation
  • Pure Functions - No side effects, deterministic validation
  • Type Safety - Strict TypeScript with full type coverage

See Also

License

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

This file 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.