universal-mailer-lib
v2.0.4
Published
Universal email client. Supports SMTP and Gmail API.
Maintainers
Readme
universal-mailer-lib
Universal email client. Supports SMTP and Gmail API.
Install
npm install universal-mailer-libRequires peer dependencies: googleapis, nodemailer, handlebars, imapflow, mailparser
npm install universal-mailer-lib googleapis nodemailer handlebars imapflow mailparserQuick Start
import { UniversalMailer } from 'universal-mailer-lib'
const mailer = new UniversalMailer({
transport: 'smtp',
smtp: {
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: '[email protected]',
pass: 'your-app-password',
},
},
})
const result = await mailer.sendEmail({
from: '[email protected]',
to: '[email protected]',
subject: 'Hello from gmail-mailer',
html: '<h1>Hello World</h1><p>This is a test email.</p>',
})
console.log(result.messageId) // Gmail message IDOAuth2 Setup
- Go to Google Cloud Console
- Create a project and enable the Gmail API
- Create OAuth 2.0 credentials (Desktop app type)
- Get your
clientIdandclientSecret - Obtain a
refreshTokenusing OAuth 2.0 Playground- Select scope:
https://www.googleapis.com/auth/gmail.send - Authorize and exchange for tokens
- Select scope:
Gmail API Usage
import { UniversalMailer } from 'universal-mailer-lib'
const mailer = new UniversalMailer({
transport: 'gmail-api', // ⚠️ Use 'gmail-api', NOT 'gmail'
gmailApi: {
clientId: 'your-client-id.apps.googleusercontent.com',
clientSecret: 'your-client-secret',
refreshToken: 'your-refresh-token'
}
})
const result = await mailer.sendEmail({
from: '[email protected]',
to: '[email protected]',
subject: 'Hello from UniversalMailer',
html: '<h1>Hello World</h1><p>This is a test email.</p>',
})
console.log(result.messageId) // Gmail message ID⚠️ Important: Use gmail-api, not gmail
// ✅ Correct
transport: 'gmail-api'
// ❌ Wrong - this will fail
transport: 'gmail'Features
HTML Email
await mailer.sendEmail({
from: '[email protected]',
to: '[email protected]',
subject: 'HTML Email',
html: `
<html>
<body>
<h1>Welcome!</h1>
<p>This is an <strong>HTML</strong> email.</p>
</body>
</html>
`,
})Plain Text Email
await mailer.sendEmail({
from: '[email protected]',
to: '[email protected]',
subject: 'Text Email',
text: 'This is a plain text email.',
})Template Email (Handlebars)
import { GmailMailer } from 'gmail-mailer'
const mailer = new GmailMailer({ clientId, clientSecret, refreshToken })
const result = await mailer.sendEmail({
from: '[email protected]',
to: '[email protected]',
subject: 'Welcome, {{name}}!',
template: `
<h1>Hello {{name}}</h1>
<p>Your account has been created.</p>
<p>Verification code: <strong>{{code}}</strong></p>
`,
context: {
name: '王小明',
code: 'ABC123',
},
})Email with Attachments
import { GmailMailer } from 'gmail-mailer'
import { readFileSync } from 'node:fs'
const mailer = new GmailMailer({ clientId, clientSecret, refreshToken })
await mailer.sendEmail({
from: '[email protected]',
to: '[email protected]',
subject: 'Report Attached',
html: '<p>Please find the attached report.</p>',
attachments: [
{
filename: 'report.pdf',
content: readFileSync('./report.pdf'),
},
{
filename: 'data.json',
content: JSON.stringify({ key: 'value' }),
contentType: 'application/json',
},
],
})CC, BCC, Reply-To
await mailer.sendEmail({
from: '[email protected]',
to: '[email protected]',
cc: '[email protected]',
bcc: '[email protected]',
replyTo: '[email protected]',
subject: 'Important Update',
html: '<p>Please review the attached document.</p>',
})Verify Connection
const email = await mailer.verifyConnection()
console.log(`Connected as: ${email}`) // [email protected]API Reference
GmailMailer
Constructor
new GmailMailer(config: OAuth2Config)| Option | Type | Required | Description |
|--------|------|----------|-------------|
| clientId | string | ✅ | Google OAuth2 client ID |
| clientSecret | string | ✅ | Google OAuth2 client secret |
| refreshToken | string | ✅ | OAuth2 refresh token |
| accessToken | string | ❌ | Optional access token |
sendEmail(options) → Promise<SendResult>
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| from | string | ✅ | Sender email |
| to | string | ✅ | Recipient email |
| cc | string | ❌ | CC recipient |
| bcc | string | ❌ | BCC recipient |
| replyTo | string | ❌ | Reply-to address |
| subject | string | ✅ | Email subject |
| text | string | ❌ | Plain text body |
| html | string | ❌ | HTML body |
| template | string | ❌ | Handlebars template string |
| context | object | ❌ | Template variables |
| attachments | Attachment[] | ❌ | File attachments |
Returns:
{
messageId: string
threadId?: string
labelIds?: string[]
}verifyConnection() → Promise<string>
Returns the authenticated user's email address.
getAccessToken() → Promise<string>
Returns the current OAuth2 access token (auto-refreshes if expired).
Utility Functions
import { renderTemplate, registerTemplate, registerHelper } from 'gmail-mailer'
// Render a Handlebars template
const html = renderTemplate('<h1>Hello {{name}}</h1>', { name: 'World' })
// Register a reusable partial
registerTemplate('footer', '<footer>© 2026</footer>')
// Register a custom helper
registerHelper('upper', (text: string) => text.toUpperCase())MIME Builder
import { buildRawMessage, buildMimeMessage } from 'gmail-mailer'
// Build base64url encoded message (for Gmail API)
const raw = await buildRawMessage({ from, to, subject, html })
// Build raw Buffer (for SMTP or other transports)
const buffer = await buildMimeMessage({ from, to, subject, html })Design
| Feature | Why |
|---------|-----|
| Gmail API only | No SMTP needed, better security with OAuth2 |
| OAuth2 auto-refresh | google-auth-library handles token refresh automatically |
| Handlebars templates | Industry standard for email templating |
| nodemailer MailComposer | Battle-tested MIME generation, no reinventing the wheel |
| Zero SMTP | Bypasses SMTP entirely, uses Gmail REST API directly |
License
MIT
