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 🙏

© 2026 – Pkg Stats / Ryan Hefner

ddw-mail-js

v1.0.6

Published

JavaScript client for Direct Digital Mailer

Readme

DDW Mail JS - Direct Digital Mailer JavaScript Client

A lightweight, type-safe JavaScript client for sending emails through the Direct Digital Mailer service. Supports both CommonJS and ES modules with full TypeScript support.

Table of Contents

Installation

npm install ddw-mail-js

Or with yarn:

yarn add ddw-mail-js

Or with pnpm:

pnpm add ddw-mail-js

Quick Start

import DirectDigitalMailer from "ddw-mail-js";

// Initialize with your API key
DirectDigitalMailer.init("your-api-key");

// Send an email
const response = await DirectDigitalMailer.send(
  "service-id",
  "template-id",
  ["[email protected]"],
  { name: "John", subject: "Welcome" }
);

console.log("Email sent:", response.status);

Getting Your API Key

⚠️ CRITICAL: Account Setup Required

Before you can use this package, you must create an account and retrieve your API key:

  1. Visit the Dashboard: Go to https://mailer.directdigitalworld.com
  2. Create an Account: Sign up with your email and password
  3. Navigate to Profile Settings:
    • Log in to your account
    • Click on your profile icon (top right corner)
    • Select "Settings" or "Profile Settings"
  4. Copy Your API Key:
    • Look for the "API Key" section
    • Click the copy button to copy your API key
    • Keep this key secure - treat it like a password

Secure API Key Management

Never hardcode your API key in source code. Use environment variables:

// ✅ GOOD - Using environment variables
const apiKey = process.env.DDW_MAIL_API_KEY;
DirectDigitalMailer.init(apiKey);

// ❌ BAD - Never do this
DirectDigitalMailer.init("sk_live_abcd1234...");

For Browser Applications:

For client-side applications, consider using a backend proxy instead of exposing your API key:

// Frontend - Call your backend endpoint
const response = await fetch("/api/send-email", {
  method: "POST",
  body: JSON.stringify({
    serviceId: "service-123",
    templateId: "template-456",
    recipients: ["[email protected]"],
    variables: { name: "John" },
  }),
});

// Backend (Node.js) - Keeps API key secure
import DirectDigitalMailer from "ddw-mail-js";

DirectDigitalMailer.init(process.env.DDW_MAIL_API_KEY);

app.post("/api/send-email", async (req, res) => {
  try {
    const result = await DirectDigitalMailer.send(
      req.body.serviceId,
      req.body.templateId,
      req.body.recipients,
      req.body.variables
    );
    res.json(result);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Configuration

Initialization

import DirectDigitalMailer from "ddw-mail-js";

// Initialize with API key
DirectDigitalMailer.init("your-api-key-from-profile-settings");

Environment-Based Configuration

// Node.js with .env file
import dotenv from "dotenv";

dotenv.config();

const apiKey = process.env.DDW_MAIL_API_KEY;
if (!apiKey) {
  throw new Error("DDW_MAIL_API_KEY environment variable is not set");
}

DirectDigitalMailer.init(apiKey);

Usage

Initializing the Client

Before calling any send methods, you must initialize the client with your API key:

DirectDigitalMailer.init("your-api-key");

If you don't initialize first, you'll get an error:

Error: DirectDigitalMailer is not initialized. Call init() first.

Sending Emails

Basic Email Send

const response = await DirectDigitalMailer.send(
  "service-123", // serviceId
  "template-456", // templateId
  ["[email protected]"], // recipients array
  {
    // variables (optional)
    name: "John",
    subject: "Welcome to our service",
    confirmationLink: "https://example.com/confirm?token=abc123",
  }
);

console.log("Status:", response.status);
console.log("Response:", response.text);

Multiple Recipients

const recipients = [
  "[email protected]",
  "[email protected]",
  "[email protected]",
];

const response = await DirectDigitalMailer.send(
  "service-id",
  "template-id",
  recipients,
  { subject: "Bulk email" }
);

With Template Variables

const response = await DirectDigitalMailer.send(
  "service-id",
  "welcome-template",
  ["[email protected]"],
  {
    firstName: "Jane",
    lastName: "Doe",
    activationLink: "https://example.com/activate?token=xyz",
    expiresIn: "24 hours",
  }
);

Sending with HTML Forms

The client can automatically extract form data and send it as email variables:

HTML Form

<form id="contactForm">
  <input type="text" name="name" placeholder="Your name" required />
  <input type="email" name="email" placeholder="Your email" required />
  <textarea name="message" placeholder="Your message" required></textarea>
  <button type="submit">Send</button>
</form>

JavaScript

document.getElementById("contactForm").addEventListener("submit", async (e) => {
  e.preventDefault();

  try {
    const response = await DirectDigitalMailer.sendForm(
      "service-id",
      "contact-template",
      ["[email protected]"],
      "contactForm" // Form ID
    );

    console.log("Email sent successfully:", response.status);
    alert("Message sent!");
  } catch (error) {
    console.error("Failed to send email:", error);
    alert("Failed to send message. Please try again.");
  }
});

Using Form Element Reference

const form = document.querySelector("form");

const response = await DirectDigitalMailer.sendForm(
  "service-id",
  "template-id",
  ["[email protected]"],
  form // Pass the form element directly
);

API Reference

init(apiKey: string): void

Initializes the DirectDigitalMailer client with your API key.

Parameters:

  • apiKey (string, required): Your API key from the dashboard profile settings

Throws:

  • Error if initialization fails

Example:

DirectDigitalMailer.init(process.env.DDW_MAIL_API_KEY);

send(serviceId: string, templateId: string, recipients: string[], variables?: Record<string, any>): Promise<SendResponse>

Sends an email using a template.

Parameters:

  • serviceId (string, required): Your service ID from the dashboard
  • templateId (string, required): The email template ID
  • recipients (string[], required): Array of recipient email addresses
  • variables (object, optional): Template variables to populate the email

Returns:

  • Promise<SendResponse>: Response object with status and content

Throws:

  • Error if client is not initialized
  • Error if API request fails

Example:

const response = await DirectDigitalMailer.send(
  "service-123",
  "template-456",
  ["[email protected]"],
  { name: "John", orderNumber: "12345" }
);

sendForm(serviceId: string, templateId: string, recipients: string[], form: HTMLFormElement | string): Promise<SendResponse>

Sends an email with form data as variables.

Parameters:

  • serviceId (string, required): Your service ID from the dashboard
  • templateId (string, required): The email template ID
  • recipients (string[], required): Array of recipient email addresses
  • form (HTMLFormElement | string, required): Form element or form ID

Returns:

  • Promise<SendResponse>: Response object with status and content

Throws:

  • Error if client is not initialized
  • Error if form is not found
  • Error if API request fails

Example:

const response = await DirectDigitalMailer.sendForm(
  "service-id",
  "template-id",
  ["[email protected]"],
  "contactForm"
);

Type Definitions

SendResponse

interface SendResponse {
  status: number; // HTTP status code
  text: string; // Response body as text
  json?: () => Promise<any>; // Parse response as JSON
}

SendOptions

interface SendOptions {
  serviceId: string;
  templateId: string;
  variables?: Record<string, any>;
  userId?: string;
  recipients?: string[];
  accessToken?: string;
}

DirectDigitalMailerAPI

interface DirectDigitalMailerAPI {
  init: (apiKey: string) => void;
  send: (
    serviceId: string,
    templateId: string,
    recipients: string[],
    variables?: Record<string, any>
  ) => Promise<SendResponse>;
  sendForm: (
    serviceId: string,
    templateId: string,
    recipients: string[],
    form: HTMLFormElement | string
  ) => Promise<SendResponse>;
}

Examples

React Component Example

import { useState } from "react";
import DirectDigitalMailer from "ddw-mail-js";

export function NewsletterSignup() {
  const [email, setEmail] = useState("");
  const [status, setStatus] = useState<
    "idle" | "loading" | "success" | "error"
  >("idle");
  const [message, setMessage] = useState("");

  // Initialize once on component mount
  React.useEffect(() => {
    DirectDigitalMailer.init(process.env.REACT_APP_DDW_MAIL_API_KEY);
  }, []);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setStatus("loading");

    try {
      const response = await DirectDigitalMailer.send(
        "newsletter-service",
        "welcome-email",
        [email],
        {
          email,
          timestamp: new Date().toISOString(),
        }
      );

      setStatus("success");
      setMessage("Welcome email sent! Check your inbox.");
      setEmail("");
    } catch (error) {
      setStatus("error");
      setMessage(
        `Error: ${error instanceof Error ? error.message : "Unknown error"}`
      );
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Enter your email"
        required
        disabled={status === "loading"}
      />
      <button type="submit" disabled={status === "loading"}>
        {status === "loading" ? "Signing up..." : "Sign Up"}
      </button>
      {message && <p className={status}>{message}</p>}
    </form>
  );
}

Node.js Express Server Example

import express from "express";
import DirectDigitalMailer from "ddw-mail-js";
import dotenv from "dotenv";

dotenv.config();

const app = express();
app.use(express.json());

// Initialize on server startup
DirectDigitalMailer.init(process.env.DDW_MAIL_API_KEY);

// Send welcome email
app.post("/api/users/register", async (req, res) => {
  try {
    const { email, name } = req.body;

    // Validate input
    if (!email || !name) {
      return res.status(400).json({ error: "Email and name are required" });
    }

    // Send welcome email
    const response = await DirectDigitalMailer.send(
      "user-service",
      "registration-welcome",
      [email],
      {
        name,
        email,
        activationLink: `https://example.com/activate?email=${encodeURIComponent(
          email
        )}`,
      }
    );

    res.json({
      success: true,
      message: "Registration email sent",
      status: response.status,
    });
  } catch (error) {
    console.error("Registration email failed:", error);
    res.status(500).json({
      error: "Failed to send registration email",
      details: error instanceof Error ? error.message : "Unknown error",
    });
  }
});

// Send password reset email
app.post("/api/password-reset", async (req, res) => {
  try {
    const { email, resetToken } = req.body;

    const response = await DirectDigitalMailer.send(
      "user-service",
      "password-reset",
      [email],
      {
        email,
        resetLink: `https://example.com/reset?token=${resetToken}`,
        expiresIn: "1 hour",
      }
    );

    res.json({ success: true, status: response.status });
  } catch (error) {
    res.status(500).json({ error: "Failed to send reset email" });
  }
});

app.listen(3000, () => {
  console.log("Server running on port 3000");
  console.log("DDW Mail JS initialized");
});

Svelte Example

<script lang="ts">
  import DirectDigitalMailer from 'ddw-mail-js';
  import { onMount } from 'svelte';

  let email = '';
  let loading = false;
  let message = '';
  let isSuccess = false;

  onMount(() => {
    DirectDigitalMailer.init(import.meta.env.VITE_DDW_MAIL_API_KEY);
  });

  async function handleSubscribe() {
    if (!email) return;

    loading = true;
    message = '';

    try {
      await DirectDigitalMailer.send(
        'newsletter',
        'subscription',
        [email],
        { email }
      );

      isSuccess = true;
      message = 'Subscription confirmed! Check your email.';
      email = '';
    } catch (error) {
      isSuccess = false;
      message = `Error: ${error instanceof Error ? error.message : 'Failed to subscribe'}`;
    } finally {
      loading = false;
    }
  }
</script>

<div>
  <input
    type="email"
    bind:value={email}
    placeholder="Enter your email"
    disabled={loading}
  />
  <button on:click={handleSubscribe} disabled={loading || !email}>
    {loading ? 'Subscribing...' : 'Subscribe'}
  </button>

  {#if message}
    <p class={isSuccess ? 'success' : 'error'}>{message}</p>
  {/if}
</div>

<style>
  .success {
    color: green;
  }
  .error {
    color: red;
  }
</style>

Troubleshooting

"DirectDigitalMailer is not initialized. Call init() first."

Problem: You're trying to send an email before initializing the client.

Solution: Call DirectDigitalMailer.init(apiKey) before any send() or sendForm() calls.

// ❌ Wrong
DirectDigitalMailer.send("service-id", "template-id", ["[email protected]"]);

// ✅ Correct
DirectDigitalMailer.init("your-api-key");
DirectDigitalMailer.send("service-id", "template-id", ["[email protected]"]);

"Form with ID 'xyz' not found"

Problem: The form ID you passed doesn't exist in the DOM.

Solution: Verify the form ID matches exactly and exists in your HTML.

// ❌ Wrong - Form doesn't exist or ID doesn't match
DirectDigitalMailer.sendForm('service-id', 'template-id', ['[email protected]'], 'contactForm');

// ✅ Correct - Verify form exists
<form id="contactForm">
  <!-- form fields -->
</form>

// Then use it
DirectDigitalMailer.sendForm('service-id', 'template-id', ['[email protected]'], 'contactForm');

"API request failed with status 401"

Problem: Your API key is invalid, expired, or not properly set.

Solution:

  1. Verify your API key is correct from the dashboard
  2. Check if the API key has been revoked
  3. Make sure you're using the correct environment variable
// Check if API key is loaded
console.log("API Key exists:", !!process.env.DDW_MAIL_API_KEY);
DirectDigitalMailer.init(process.env.DDW_MAIL_API_KEY);

"API request failed with status 400"

Problem: Invalid service ID, template ID, or malformed variables.

Solution:

  1. Verify serviceId and templateId are correct
  2. Check template variables match the template requirements
  3. Ensure recipient emails are valid
// Validate before sending
if (!serviceId || !templateId) {
  throw new Error("serviceId and templateId are required");
}

if (!recipients.every((email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email))) {
  throw new Error("Invalid email addresses in recipients");
}

const response = await DirectDigitalMailer.send(
  serviceId,
  templateId,
  recipients,
  variables
);

"CORS error in browser"

Problem: Sending emails directly from the browser is blocked by CORS.

Solution: Use a backend proxy instead of calling the API from the browser.

// ❌ Don't do this in browser
DirectDigitalMailer.init('api-key'); // Never expose API key!
DirectDigitalMailer.send(...);

// ✅ Do this instead
// Frontend
const response = await fetch('/api/send-email', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ serviceId, templateId, recipients, variables })
});

// Backend keeps API key secure

Network Timeouts

Problem: API requests are timing out.

Solution:

  1. Check your internet connection
  2. Verify the API endpoint is accessible (https://mailer.directdigitalworld.com)
  3. Retry with exponential backoff
async function sendWithRetry(
  serviceId: string,
  templateId: string,
  recipients: string[],
  variables: Record<string, any>,
  maxRetries = 3
) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await DirectDigitalMailer.send(
        serviceId,
        templateId,
        recipients,
        variables
      );
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      // Exponential backoff: 1s, 2s, 4s
      await new Promise((resolve) =>
        setTimeout(resolve, Math.pow(2, i) * 1000)
      );
    }
  }
}

Best Practices

1. Always Initialize Early

Initialize the client as soon as possible in your application lifecycle:

// App.tsx (React)
useEffect(() => {
  DirectDigitalMailer.init(process.env.REACT_APP_DDW_MAIL_API_KEY);
}, []);

// main.ts (Vue)
app.config.globalProperties.$init = DirectDigitalMailer.init;
DirectDigitalMailer.init(import.meta.env.VITE_DDW_MAIL_API_KEY);

// app.ts (Svelte)
onMount(() => {
  DirectDigitalMailer.init(import.meta.env.VITE_DDW_MAIL_API_KEY);
});

2. Protect Your API Key

  • Use environment variables, never hardcode
  • Don't commit .env files to version control
  • Rotate your API key regularly from the dashboard
  • Use different keys for different environments

3. Use Backend Proxies for Client-Side Apps

Never expose your API key in browser code:

// ❌ Never do this
const apiKey = "sk_live_xyz..."; // Browser JavaScript
DirectDigitalMailer.init(apiKey);

// ✅ Always do this
// Frontend: Call your backend
// Backend: Keep API key secure in environment variables

4. Validate Input Data

Always validate before sending:

function validateAndSend(
  serviceId: string,
  templateId: string,
  recipients: string[],
  variables?: Record<string, any>
) {
  // Validate service and template IDs
  if (!serviceId || typeof serviceId !== "string") {
    throw new Error("Invalid serviceId");
  }
  if (!templateId || typeof templateId !== "string") {
    throw new Error("Invalid templateId");
  }

  // Validate recipients
  if (!Array.isArray(recipients) || recipients.length === 0) {
    throw new Error("Recipients must be a non-empty array");
  }

  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (!recipients.every((email) => emailRegex.test(email))) {
    throw new Error("Invalid email address in recipients");
  }

  // Send the email
  return DirectDigitalMailer.send(serviceId, templateId, recipients, variables);
}

5. Handle Errors Gracefully

Always catch and handle errors:

try {
  const response = await DirectDigitalMailer.send(
    "service-id",
    "template-id",
    ["[email protected]"],
    variables
  );
  console.log("Email sent successfully");
} catch (error) {
  console.error("Failed to send email:", error);
  // Show user-friendly error message
  // Log error for debugging
  // Retry with exponential backoff if appropriate
}

6. Log Important Information

Keep logs for debugging and monitoring:

async function sendEmailWithLogging(
  serviceId: string,
  templateId: string,
  recipients: string[],
  variables: Record<string, any>
) {
  const startTime = Date.now();

  console.log("Sending email...", {
    serviceId,
    templateId,
    recipientCount: recipients.length,
    timestamp: new Date().toISOString(),
  });

  try {
    const response = await DirectDigitalMailer.send(
      serviceId,
      templateId,
      recipients,
      variables
    );

    const duration = Date.now() - startTime;
    console.log("Email sent successfully", {
      status: response.status,
      duration: `${duration}ms`,
      timestamp: new Date().toISOString(),
    });

    return response;
  } catch (error) {
    const duration = Date.now() - startTime;
    console.error("Email send failed", {
      error: error instanceof Error ? error.message : "Unknown error",
      duration: `${duration}ms`,
      timestamp: new Date().toISOString(),
    });
    throw error;
  }
}

7. Use TypeScript for Type Safety

Leverage the included TypeScript types:

import DirectDigitalMailer, {
  SendResponse,
  SendOptions,
  DirectDigitalMailerAPI,
} from "ddw-mail-js";

// Use types for better IDE support and type checking
const sendEmail = async (options: SendOptions): Promise<SendResponse> => {
  return DirectDigitalMailer.send(
    options.serviceId,
    options.templateId,
    options.recipients || [],
    options.variables
  );
};

8. Test Before Production

Always test in development first:

// Use test service/template IDs in development
const config = {
  development: {
    serviceId: "test-service",
    templateId: "test-template",
  },
  production: {
    serviceId: "prod-service",
    templateId: "prod-template",
  },
};

const env = process.env.NODE_ENV || "development";
const { serviceId, templateId } = config[env];

Support

For issues, questions, or feature requests, please visit the dashboard at https://mailer.directdigitalworld.com or contact support.

License

MIT


Version: 1.0.6
Last Updated: December 2025