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

freely-email

v1.1.0

Published

This Library is designed to make it easy for developers to send automated emails to multiple recipients. Minimum Node version 18 is required.

Downloads

134

Readme

License Version Downloads

Version Requirement: Node.js >= 18.0.0 (Uses native fetch, 0 dependencies).

✨ Architecture Flow Diagram

sequenceDiagram
    participant App as Client App (Developer)
    participant SDK as FreelyEmail Client SDK
    participant NativeFetch as Node.js Native Fetch
    participant Router as API /src/routes
    participant Controller as API /src/controllers
    participant Service as API /src/services
    participant SMTP as Sendinblue SMTP
    participant DB as MongoDB

    App->>SDK: new FreelyEmailClient()
    Note over App,SDK: Developer initiates the SDK (TypeScript supported)
    
    App->>SDK: sendOTP({ sender: "auth", ... })
    SDK->>NativeFetch: RequestManager checks payload, sends HTTP POST to /api/v1/emails/otp/send
    
    NativeFetch->>Router: HTTP POST payload arrives
    Router->>Controller: Route matches, passes to sendOtp() layer
    
    Controller->>Controller: catchAsync & Validator check payload fields
    alt If Validation Fails
        Controller-->>SDK: 400 Bad Request
        SDK-->>App: throws FreelyEmailAPIError
    end
    
    Controller->>Service: payload valid, sendMail(...)
    Service->>SMTP: Connects via nodemailer & sends HTML email
    SMTP-->>Service: msgId returned
    
    Service->>DB: Log the transaction asynchronously (saveEmailRecord)
    
    Controller-->>NativeFetch: 200 OK { success: true, messageId: ... }
    NativeFetch-->>SDK: Parse JSON payload
    SDK-->>App: Return Successful APIResponse

🚀 Features

  • Created by Harshit: Maintainable open-source library explicitly crafted by Harshit107.
  • Object-Oriented Design: Instantiate the FreelyEmailClient and go.
  • Robust Error Handling: Distinct Custom Errors (FreelyEmailAPIError) for robust backend integrations.
  • TypeScript Support: Full code-completion and Type definitions included out-of-the-box.
  • No Dependencies: Relies completely on native Node.js fetch APIs!

📥 Installation

npm install freely-email

🛠 Basic Setup

Import and initialize the client. You can optionally pass a custom baseURL if you host the associated API yourself.

const { FreelyEmailClient } = require("freely-email");

// Default public API
const emailClient = new FreelyEmailClient(); 

// OR Custom Private API Server
// const emailClient = new FreelyEmailClient({ baseURL: "https://my-custom-email-api.com/api/v1/emails/" });

📖 Usage Examples

1. Send Normal Notification Email 📝

Send a customized email with optional HTML attachments.

async function notifyUser() {
  try {
    const response = await emailClient.sendEmail({
      sender: "support-bot",
      recipient: "[email protected]",
      replyTo: "[email protected]",
      app: "My Demo App",
      subject: "Welcome Aboard!",
      message: "This is a plain text message fallback.",
      HTMLfile: "<html><body><h1>Welcome to My Demo App</h1></body></html>"
    });
    console.log("Success:", response.data.messageId);
  } catch (error) {
    console.error("Failed to send email:", error.message);
  }
}
notifyUser();

2. Request OTP (Auto-Generated) 🔐

Ask the API to securely generate a 6-digit OTP and email it to the user with a beautiful, modern HTML template.

async function requestOTP() {
  const result = await emailClient.requestOTP({
    sender: "Example Auth",
    recipient: "[email protected]",
    app: "Demo App",
    subject: "Your Login Code",
    withValidTime: 10 // Validity displayed as 10 minutes in the UI
  });
  console.log("OTP Sent!", result.data.messageId, result.data.otp);
}

3. Send Check Health 🩺

Ping the backend server to ensure the email API is online.

emailClient.checkHealth()
  .then(res => console.log(res.message))
  .catch(err => console.error("API is down:", err));

🛡️ Error Handling

The SDK exposes two custom error classes for clean try/catch checks:

  • FreelyEmailAPIError: HTTP issues (e.g., 400 Bad Request if missing fields, 500 API Crash).
  • FreelyEmailValidationError: SDK-side malformed input errors.
const { FreelyEmailClient, FreelyEmailAPIError } = require("freely-email");

try {
  await emailClient.sendEmail({...});
} catch (err) {
  if (err instanceof FreelyEmailAPIError) {
    console.log("API Status Code:", err.status);
    console.log("Details:", err.details);
  }
}