
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
A developer-first email service library for Node.js that simplifies sending emails with templates, multiple providers, and excellent developer experience.
npm install sendora
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: 'user@example.com',
subject: 'Welcome',
html: '<h1>Hello World!</h1>',
});
const mail = new Sendora({
provider: 'smtp',
smtp: {
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: 'your-email@gmail.com',
pass: 'your-app-password',
},
},
from: 'Your App <noreply@yourapp.com>',
});
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 <sender@example.com>',
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',
},
});
await mail.send({
from: 'Sender <sender@example.com>',
to: ['user1@example.com', 'user2@example.com'],
cc: 'cc@example.com',
bcc: 'bcc@example.com',
subject: 'Email Subject',
text: 'Plain text version',
html: '<h1>HTML version</h1>',
replyTo: 'reply@example.com',
attachments: [
{
filename: 'document.pdf',
path: '/path/to/file.pdf',
},
],
headers: {
'X-Custom-Header': 'value',
},
});
Create your templates in the configured templates directory:
{{!-- templates/welcome.hbs --}}
<h2>Hello {{name}}!</h2>
<p>Welcome to {{company}}.</p>
await mail.send({
to: 'user@example.com',
subject: 'Welcome!',
template: 'welcome',
data: {
name: 'John',
company: 'Acme Inc',
},
});
{{!-- templates/layouts/main.hbs --}}
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
{{{body}}}
</body>
</html>
{{!-- templates/partials/button.hbs --}}
<a href="{{url}}" class="btn">{{text}}</a>
{{!-- Usage in template --}}
{{> button url="https://example.com" text="Click Me" }}
const mail = new Sendora({
provider: 'smtp',
smtp: { /* ... */ },
templates: {
helpers: {
uppercase: (str: string) => str.toUpperCase(),
formatDate: (date: Date) => date.toLocaleDateString(),
},
},
});
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: 'user@example.com',
subject: 'Welcome',
template: 'welcome',
data: { name: 'John' },
});
console.log(mail.getQueueSize());
const mail = new Sendora({
provider: 'smtp',
smtp: { /* ... */ },
logger: {
enabled: true,
level: 'info',
prettyPrint: true,
},
});
Log levels: trace, debug, info, warn, error, fatal
import { Sendora, TemplateNotFoundError, ProviderError } from 'sendora';
try {
await mail.send({
to: 'user@example.com',
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);
}
}
interface WelcomeData {
name: string;
company: string;
}
await mail.send<WelcomeData>({
to: 'user@example.com',
template: 'welcome',
data: {
name: 'John',
company: 'Acme',
},
});
new Sendora(config)Creates a new Sendora instance.
Parameters:
config - Configuration objectmail.send(options)Sends an email.
Parameters:
options - Email optionsReturns: Promise<SendEmailResponse>
mail.sendBulk(emails)Sends multiple emails.
Parameters:
emails - Array of email optionsReturns: 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.
MIT © Nurul Islam Rimon
Contributions are welcome! This project is open source and we invite developers to contribute.
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)# Clone the repo
git clone https://github.com/nurulislamrimon/sendora.git
cd sendora
# Install dependencies
npm install
# Run tests
npm test
# Build
npm run build
We appreciate all contributions, no matter how small!
FAQs
A developer-first email service library for Node.js
We found that sendora demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.