npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bernierllc/validators-email

v0.1.2

Published

Email content validation - composite validator for email campaigns combining HTML syntax, MIME structure, link integrity, and tracking validation

Readme

@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: '[email protected]',
    to: ['[email protected]'],
  },
};

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.