sendora
v1.0.0
Published
A developer-first email service library for Node.js
Maintainers
Readme
sendora
A developer-first email service library for Node.js that simplifies sending emails with templates, multiple providers, and excellent developer experience.
Features
- Simple API - Intuitive interface for sending emails
- Multiple Providers - SMTP support with Nodemailer (SendGrid, Resend, Mailgun coming soon)
- Template Engine - Handlebars-based templates with layouts and partials
- Type-safe - Full TypeScript support with strong typing
- Queue Support - Built-in queue for background email processing
- Developer-friendly Logging - Powered by pino
- Configuration Validation - Zod-powered validation
Installation
npm install sendoraQuick Start
import { Sendora } from 'sendora';
const mail = new Sendora({
provider: 'smtp',
smtp: {
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS,
},
},
});
await mail.initialize();
await mail.send({
to: '[email protected]',
subject: 'Welcome',
html: '<h1>Hello World!</h1>',
});Configuration
SMTP Configuration
const mail = new Sendora({
provider: 'smtp',
smtp: {
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: '[email protected]',
pass: 'your-app-password',
},
},
from: 'Your App <[email protected]>',
});Full Configuration Options
const mail = new Sendora({
provider: 'smtp',
smtp: {
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS,
},
},
from: 'Sender <[email protected]>',
templates: {
dir: './templates',
ext: '.hbs',
layouts: {
dir: './templates/layouts',
default: 'main',
},
partials: {
dir: './templates/partials',
},
defaultData: {
company: 'My Company',
year: new Date().getFullYear(),
},
},
queue: {
enabled: true,
concurrency: 5,
delay: 1000,
},
logger: {
enabled: true,
level: 'debug',
prettyPrint: true,
},
defaultHeaders: {
'X-Mailer': 'Sendora',
},
});Email Options
await mail.send({
from: 'Sender <[email protected]>',
to: ['[email protected]', '[email protected]'],
cc: '[email protected]',
bcc: '[email protected]',
subject: 'Email Subject',
text: 'Plain text version',
html: '<h1>HTML version</h1>',
replyTo: '[email protected]',
attachments: [
{
filename: 'document.pdf',
path: '/path/to/file.pdf',
},
],
headers: {
'X-Custom-Header': 'value',
},
});Templates
Creating Templates
Create your templates in the configured templates directory:
{{!-- templates/welcome.hbs --}}
<h2>Hello {{name}}!</h2>
<p>Welcome to {{company}}.</p>Using Templates
await mail.send({
to: '[email protected]',
subject: 'Welcome!',
template: 'welcome',
data: {
name: 'John',
company: 'Acme Inc',
},
});Layouts
{{!-- templates/layouts/main.hbs --}}
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
{{{body}}}
</body>
</html>Partials
{{!-- templates/partials/button.hbs --}}
<a href="{{url}}" class="btn">{{text}}</a>{{!-- Usage in template --}}
{{> button url="https://example.com" text="Click Me" }}Custom Helpers
const mail = new Sendora({
provider: 'smtp',
smtp: { /* ... */ },
templates: {
helpers: {
uppercase: (str: string) => str.toUpperCase(),
formatDate: (date: Date) => date.toLocaleDateString(),
},
},
});Queue Support
Enable the built-in queue for background email processing:
const mail = new Sendora({
provider: 'smtp',
smtp: { /* ... */ },
queue: true,
});
await mail.initialize();
await mail.send({
to: '[email protected]',
subject: 'Welcome',
template: 'welcome',
data: { name: 'John' },
});
console.log(mail.getQueueSize());Logging
const mail = new Sendora({
provider: 'smtp',
smtp: { /* ... */ },
logger: {
enabled: true,
level: 'info',
prettyPrint: true,
},
});Log levels: trace, debug, info, warn, error, fatal
Error Handling
import { Sendora, TemplateNotFoundError, ProviderError } from 'sendora';
try {
await mail.send({
to: '[email protected]',
template: 'nonexistent',
});
} catch (error) {
if (error instanceof TemplateNotFoundError) {
console.error('Template not found:', error.message);
} else if (error instanceof ProviderError) {
console.error('Provider error:', error.message);
}
}Type Safety
interface WelcomeData {
name: string;
company: string;
}
await mail.send<WelcomeData>({
to: '[email protected]',
template: 'welcome',
data: {
name: 'John',
company: 'Acme',
},
});API Reference
new Sendora(config)
Creates a new Sendora instance.
Parameters:
config- Configuration object
mail.send(options)
Sends an email.
Parameters:
options- Email options
Returns: Promise<SendEmailResponse>
mail.sendBulk(emails)
Sends multiple emails.
Parameters:
emails- Array of email options
Returns: Promise<SendEmailResponse[]>
mail.initialize()
Initializes the template engine.
Returns: Promise<void>
mail.close()
Closes the provider connection.
Returns: Promise<void>
mail.getQueueSize()
Returns the number of queued emails.
Returns: number
mail.clearQueue()
Clears all queued emails.
License
MIT © Nurul Islam Rimon
Contributing
Contributions are welcome! This project is open source and we invite developers to contribute.
Ways to Contribute
- Bug Reports - Open an issue with clear steps to reproduce
- Feature Requests - Suggest new features or improvements
- Pull Requests - Submit patches or new features
- Documentation - Improve docs, examples, or add translations
- Testing - Add more test cases
Getting Started
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Setup
# Clone the repo
git clone https://github.com/nurulislamrimon/sendora.git
cd sendora
# Install dependencies
npm install
# Run tests
npm test
# Build
npm run buildWe appreciate all contributions, no matter how small!
