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

@mohamedelsaady/mail-ms

v1.2.0

Published

Typed HTTP client SDK for the Gabster mail-ms microservice

Readme

@mohamedelsaady/mail-ms

Typed HTTP client SDK for the Gabster mail microservice.

Installation

npm install @mohamedelsaady/mail-ms

What's New in v1.2.0

Batch Sending: Send to multiple recipients with a single API call via BCC
📮 CC Support: Group emails where recipients can see each other
↩️ Reply-To Field: Direct replies to monitored addresses
📊 Enhanced Types: Full TypeScript support for all operations
🔒 Privacy Focused: Flexible visibility options (BCC for privacy, CC for transparency)

Quick Start

import Mailer from "@mohamedelsaady/mail-ms";

const mail = new Mailer({
  host: process.env.GABSTER_MAIL_HOST,
  apiKey: process.env.GABSTER_MAIL_API_KEY,
});

Sending Emails

Raw HTML

const result = await mail.send.raw({
  to: "[email protected]",
  subject: "Welcome aboard",
  html: "<h1>Hello!</h1><p>Welcome to our platform.</p>",
  text: "Hello! Welcome to our platform.",       // optional plain-text fallback
  tags: ["onboarding"],                          // optional tags
  metadata: { userId: "abc123" },                // optional metadata (stored in logs)
});

console.log(result);
// { success: true, emailLogId: "664f...", messageId: "msg_..." }

Templated (server-side templates)

await mail.send.templated({
  template: "welcome",
  to: "[email protected]",
  subject: "You're invited!",                    // optional (uses template default)
  variables: {
    recipientEmail: "[email protected]",
    orgName: "Your Organization",
    invitationId: "inv_123",
    link: "https://app.example.com/invite/inv_123",
    isNewUser: true,
  },
});

Available templates: welcome, notification, ticket, otp, expiration, usage-limit, custom.

Dynamic (block-based)

Build emails on the fly using content blocks:

await mail.send.dynamic({
  to: "[email protected]",
  subject: "Your Weekly Report",
  styles: {
    primaryColor: "#2563eb",
    backgroundColor: "#f3f4f6",
    fontFamily: "Arial, sans-serif",
  },
  blocks: [
    { type: "heading", text: "Hello {{name}}", level: 1, align: "center" },
    { type: "text", text: "Here is your weekly summary." },
    { type: "divider" },
    { type: "text", text: "You completed {{tasks}} tasks this week." },
    { type: "button", text: "View Dashboard", link: "https://app.example.com/dashboard" },
    { type: "image", src: "https://cdn.example.com/banner.png", alt: "Banner", width: "100%" },
  ],
  variables: { name: "John", tasks: "12" },      // replaces {{name}}, {{tasks}} in blocks
});

Block types:

| Type | Required fields | Optional fields | |-------------|----------------------|--------------------------------------| | heading | text | level (1-3), color, align | | text | text | color, align | | button | text, link | color, bgColor, align | | image | src | alt, width, align | | divider | -- | color, thickness |

Reply-To Support

Control where replies are sent using the optional replyTo field. Useful when sending from no-reply addresses but wanting replies to go to a monitored inbox.

await mail.send.raw({
  to: "[email protected]",
  replyTo: "[email protected]",  // replies go here instead of 'from'
  subject: "Order Confirmation",
  html: "<h1>Thank you for your order!</h1><p>Questions? Just reply to this email.</p>"
});

Without replyTo: Replies go to the from address (or default sender)
With replyTo: Replies go to the specified address, regardless of from

Available on all send methods (single, batch, and CC).

Batch Sending

Send to multiple recipients efficiently with a single API call. All recipients receive the email privately via BCC, ensuring recipient privacy.

Key Features

  • Privacy First: Recipients cannot see other email addresses (BCC delivery)
  • Efficient: Single API call for multiple recipients (up to 50 per request)
  • Unified Tracking: One email log and message ID for the entire batch
  • Cost Effective: Single provider charge regardless of recipient count

Usage

All three sending methods support batch mode:

// Templated batch send
await mail.send.templatedBatch({
  template: "notification",
  to: ["[email protected]", "[email protected]", "[email protected]"],
  variables: {
    recipientName: "Team",
    senderName: "Support",
    message: "System maintenance scheduled for Sunday.",
    link: "https://status.example.com"
  }
});

// Raw HTML batch send
await mail.send.rawBatch({
  to: ["[email protected]", "[email protected]"],
  subject: "Weekly Update",
  html: "<h1>Team Update</h1><p>This week's highlights...</p>"
});

// Dynamic blocks batch send
await mail.send.dynamicBatch({
  to: ["[email protected]", "[email protected]"],
  subject: "New Feature",
  blocks: [
    { type: "heading", text: "New Feature Launch", level: 1 },
    { type: "text", text: "Check out our latest updates." },
    { type: "button", text: "Learn More", link: "https://example.com" }
  ]
});

Limits: Maximum 50 recipients per batch request.

CC Sending (Visible Recipients)

Send to multiple recipients where everyone can see each other's email addresses. Ideal for group discussions and team communications.

Key Features

  • Transparent: All recipients see each other (CC visibility)
  • Group Communication: Perfect for team discussions
  • Primary + CC: One main recipient plus CC'd participants
  • Efficient: Single API call (up to 50 CC recipients)

Usage

// Templated CC send
await mail.send.templatedCC({
  template: "notification",
  to: "[email protected]",
  cc: ["[email protected]", "[email protected]", "[email protected]"],
  variables: {
    recipientName: "Team",
    message: "Meeting notes - everyone is CC'd for visibility."
  }
});

// Raw HTML CC send
await mail.send.rawCC({
  to: "[email protected]",
  cc: ["[email protected]", "[email protected]"],
  subject: "Project Update",
  html: "<h1>Team Update</h1><p>All stakeholders are CC'd.</p>"
});

// Dynamic blocks CC send
await mail.send.dynamicCC({
  to: "[email protected]",
  cc: ["[email protected]", "[email protected]"],
  subject: "Q4 Planning",
  blocks: [
    { type: "heading", text: "Planning Discussion", level: 1 },
    { type: "text", text: "All stakeholders are CC'd for transparency." }
  ]
});

Limits: Maximum 50 CC recipients per request.

Email Logs

// Query logs with filters
const logs = await mail.logs.query({
  status: "failed",     // "pending" | "sent" | "failed" | "retrying"
  template: "welcome",  // filter by template name
  to: "[email protected]",
  page: 1,
  limit: 20,
});

console.log(logs.data);       // EmailLog[]
console.log(logs.total);      // total matching records
console.log(logs.totalPages); // total pages

// Get a single log by ID
const log = await mail.logs.getById("664fa1b2c3d4e5f6a7b8c9d0");
console.log(log.data.status); // "sent"

Health Check

const status = await mail.health();

console.log(status);
// {
//   success: true,
//   service: "mail-ms",
//   uptime: 3600.5,
//   mongo: "connected",
//   timestamp: "2026-04-05T23:00:00.000Z"
// }

Configuration

| Parameter | Required | Description | |-----------|----------|------------------------------------------| | host | Yes | Base URL of the mail-ms service | | apiKey | Yes | Per-service API key (from /v1/api-keys)|

Environment Variables

GABSTER_MAIL_HOST=https://your-mail-service-url
GABSTER_MAIL_API_KEY=your_api_key_here

API Reference

new Mailer(config)

Creates a new client instance.

mail.send.raw(params): Promise<SendResult>

Send an email with raw HTML content.

mail.send.templated(params): Promise<SendResult>

Send an email using a server-side template.

mail.send.dynamic(params): Promise<SendResult>

Send an email built from dynamic content blocks.

mail.send.templatedBatch(params): Promise<SendResult>

Send a templated email to multiple recipients via BCC (up to 50 recipients).

mail.send.rawBatch(params): Promise<SendResult>

Send a raw HTML email to multiple recipients via BCC (up to 50 recipients).

mail.send.dynamicBatch(params): Promise<SendResult>

Send a dynamic block-based email to multiple recipients via BCC (up to 50 recipients).

mail.send.templatedCC(params): Promise<SendResult>

Send a templated email with CC recipients (up to 50). All recipients see each other.

mail.send.rawCC(params): Promise<SendResult>

Send a raw HTML email with CC recipients (up to 50). All recipients see each other.

mail.send.dynamicCC(params): Promise<SendResult>

Send a dynamic block-based email with CC recipients (up to 50). All recipients see each other.

mail.logs.query(params?): Promise<PaginatedLogs>

Query email logs with optional filters and pagination.

mail.logs.getById(id): Promise<LogDetailResponse>

Get a single email log entry by its ID.

mail.health(): Promise<HealthStatus>

Check the health of the mail-ms service.

Types

All TypeScript interfaces are exported for full autocomplete:

import Mailer, {
  MailerConfig,
  SendRawParams,
  SendTemplatedParams,
  SendDynamicParams,
  SendRawBatchParams,
  SendTemplatedBatchParams,
  SendDynamicBatchParams,
  SendResult,
  DynamicBlock,
  DynamicStyles,
  HeadingBlock,
  TextBlock,
  ButtonBlock,
  ImageBlock,
  DividerBlock,
  EmailLog,
  PaginatedLogs,
  LogQueryParams,
  HealthStatus,
  TemplateName,
  EmailStatus,
} from "@mohamedelsaady/mail-ms";

License

UNLICENSED -- Internal use only.