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

msgraph-shared-mailbox

v1.2.0

Published

Email Node.js library compatible with Microsoft Graph API

Readme

msgraph-shared-mailbox

build-status npm license

English | 简体中文

Email library for Node.js that sends mail from an Exchange Online shared mailbox via Microsoft Graph. It supports text or HTML bodies, small and large attachments (buffer, local file path, or remote URL), and fetching mail by ID.

Features

  • Send email from a shared mailbox using Microsoft Graph.
  • Text or HTML body with to, cc, bcc recipients.
  • Attachments from memory (content), local path (path), or URL (href).
  • Automatic large file upload via Graph Upload Session when over threshold.
  • Recipient parsing for strings or arrays; deduplicates comma/semicolon-separated addresses.
  • Fetch message by ID with optional attachments.
  • Minimal logging hook for error reporting.

Installation

pnpm add msgraph-shared-mailbox
# or
npm install msgraph-shared-mailbox

Requires Node.js 18+.

Prerequisites

  • Azure AD App Registration with a Client Secret (Client Credentials flow).
  • Application permissions granted and consented:
    • Mail.Send for sending emails.
    • Mail.Read if you will read messages or attachments.
  • A valid shared mailbox address in your tenant, e.g. [email protected].

Quickstart

import { MailClient } from 'msgraph-shared-mailbox'

const mailClient = new MailClient({
  tenantId: process.env.TENANT_ID!,
  clientId: process.env.CLIENT_ID!,
  clientSecret: process.env.CLIENT_SECRET!,
  sharedMailbox: process.env.SHARED_MAILBOX!,
  // Large upload settings (defaults shown)
  attachmentUploadOptions: {
    largeFileThreshold: 3 * 1024 * 1024, // 3MB
    chunkSize: 320 * 1024 // 320KB (must be 320KB multiple)
  }
})

await mailClient.sendMail({
  subject: 'Hello from msgraph-shared-mailbox',
  to: '[email protected]', // string with comma/semicolon or an array
  text: 'This is a text body. You can also use HTML.'
})

Singleton alternative:

// Initialize once at app startup
import { MailClient } from 'msgraph-shared-mailbox'

export const mailClient = MailClient.getInstance({
  tenantId: process.env.TENANT_ID!,
  clientId: process.env.CLIENT_ID!,
  clientSecret: process.env.CLIENT_SECRET!,
  sharedMailbox: process.env.SHARED_MAILBOX!,
  attachmentUploadOptions: {
    largeFileThreshold: 3 * 1024 * 1024,
    chunkSize: 320 * 1024
  }
})

// Use anywhere else
await mailClient.sendMail({ subject: '...', to: '[email protected]', text: '...' })

Attachments

Provide attachments via any of the following fields:

  • content: Buffer | string kept in memory (small files)
  • path: local file path
  • href: remote file URL (http/https)

Example:

await mailClient.sendMail({
  subject: 'Email with attachments',
  to: '[email protected]',
  text: 'Attachments from content, path and href',
  attachments: [
    { filename: 'note.txt', content: Buffer.from('Hello attachment content') },
    { filename: 'sample.txt', path: '/absolute/path/to/sample.txt' },
    { filename: 'bytes.bin', href: 'https://httpbin.org/bytes/1024' }
  ]
})

Limits:

  • Single attachment size must be ≤ 150MB (Graph upload session limit).
  • Attachments larger than largeFileThreshold use an upload session with chunkSize that must be a multiple of 320KB.

Fetch a Message by ID

const message = await mailClient.getMailById('<MESSAGE_ID>', {
  includeAttachments: true
  // choose fields if needed
  // select: ['id', 'subject']
})

You can also fetch by the RFC822 Internet Message ID (internetMessageId), which typically includes angle brackets like '<...@...>':

// Option A: auto-detection when the ID looks like <...@...>
const msg1 = await mailClient.getMailById('<[email protected]>', {
  includeAttachments: true
})

// Option B: explicitly specify idType
const msg2 = await mailClient.getMailById('<[email protected]>', {
  idType: 'internetMessageId',
  includeAttachments: true,
  select: ['id', 'subject']
})

API

MailClient(options: CredentialOptions)

Options:

  • tenantId: Azure AD tenant ID.
  • clientId: App registration (client) ID.
  • clientSecret: Client secret for the app.
  • sharedMailbox: Shared mailbox email address.
  • attachmentUploadOptions?: (optional) Large upload settings.
    • largeFileThreshold?: number (default 3MB).
    • chunkSize?: number (default 320KB, must be 320KB multiple).
  • logger?: { error?: (...args: any[]) => void } (optional).

Singleton Mode

Use MailClient.getInstance(options) to create a process-wide singleton:

const mc = MailClient.getInstance({
  tenantId: '...',
  clientId: '...',
  clientSecret: '...',
  sharedMailbox: '...',
  attachmentUploadOptions: { largeFileThreshold: 3 * 1024 * 1024, chunkSize: 320 * 1024 }
})

Notes:

  • Only the first call initializes the instance; later calls return the same instance and ignore new options.
  • Prefer singleton for single-tenant apps. If you need different credentials/mailboxes per request, create separate new MailClient(options) instances instead.

sendMail(mail: MailOptions): Promise

Sends and returns the new message ID.

Return value details:

  • Returns the Graph message id as a string and internetMessageId as a string.
  • Implementation: creates a draft (POST /users/{mailbox}/messages), uploads attachments, then sends (POST /users/{mailbox}/messages/{id}/send). The returned id is the sent message ID.
  • Use this id with getMailById(id, { includeAttachments: true }) to retrieve message details or attachments.
  • If you need the RFC822 internetMessageId, query the message and read internetMessageId, or later fetch by it using getMailById('<...@...>', { idType: 'internetMessageId' }).

MailOptions:

  • subject: string
  • to: string | string[] (supports comma/semicolon; deduplicated)
  • cc?: string | string[]
  • bcc?: string | string[]
  • One of:
    • { text: string }
    • { html: string }
  • attachments?: Array of { filename?, content?, path?, href? }

getMailById(id: string, options?: { select?: string[]; includeAttachments?: boolean }): Promise

Fetches a message by ID. When includeAttachments is true, attachments are queried and merged into the result.

Run the Examples

pnpm i

# Set required environment variables
export TENANT_ID=...
export CLIENT_ID=...
export CLIENT_SECRET=...
export [email protected]

# Basic send
pnpm ts-node examples/basic-send.ts

# Send with attachments
pnpm ts-node examples/attachments.ts

# Fetch a message by ID
export MESSAGE_ID=...
pnpm ts-node examples/get-mail-by-id.ts

Troubleshooting

  • insufficient privileges: ensure the app has Mail.Send (and Mail.Read if reading) application permissions with admin consent.
  • Shared mailbox not found: verify sharedMailbox address and that the mailbox exists in your tenant.
  • Large attachments failing: set chunkSize to a multiple of 320KB and keep each attachment ≤ 150MB.
  • Rate limits (HTTP 429): consider retry/backoff; this library does not implement automatic retries.

License

MIT © Chakhsu.Lau