π€ Anish Shekh
- π GitHub: @anishhs-gh
- πΌ LinkedIn: @anishsh
- π§ Email: mail@anishhs.com (for feedback and support)
Current version: 1.0.5
- Installation
- TypeScript Support
- Configuration
- Basic Setup
- Core Methods
- Email Sending
- Template Support
- Middleware
- Email Triggering By Aliases
- CLI Usage
- Configuration Files
- Error Handling
- Development Mode
# Install as a dependency in your project
npm install @anishhs/postie
# Or install globally for CLI usage
npm install -g @anishhs/postiePostie comes with full TypeScript support out of the box. All features are properly typed and documented. Here's how to use Postie with TypeScript:
import {
Postie,
SMTPConfig,
PostieConfig,
EmailOptions,
AliasConfig,
TemplateEmailOptions,
TemplateEngine,
Middleware,
SendResult,
EmailAddress,
EmailAttachment,
Logger
} from '@anishhs/postie';
// Create a Postie instance
const postie = new Postie();const smtpConfig: SMTPConfig = {
host: 'smtp.example.com',
port: 587,
secure: false,
auth: {
user: 'sender@example.com',
pass: 'password'
},
debug: true,
logger: true
};
postie.setTransporter(smtpConfig);const postieConfig: PostieConfig = {
devMode: false,
retryAttempts: 3,
retryDelay: 1000
};
postie.configure(postieConfig);// Basic email with all available options
const emailOptions: EmailOptions = {
from: 'sender@example.com',
fromName: 'Project Team',
to: 'to@example.com',
toName: 'Recipient Name',
cc: 'cc@example.com',
ccName: 'CC Recipient',
bcc: 'bcc@example.com',
bccName: 'BCC Recipient',
subject: 'Test Email',
text: 'This is a test email',
html: '<p>This is a test email</p>',
attachments: [
{
filename: 'test.txt',
content: 'This is a test file content',
contentType: 'text/plain',
encoding: 'utf8'
}
],
headers: {
'X-Custom-Header': 'value'
}
};
// Multiple recipients with different formats
const multiRecipientEmail: EmailOptions = {
from: 'sender@example.com',
to: [
'to@example.com',
{ email: 'sender@example.com', name: 'Team Member' }
],
cc: [
'cc@example.com',
{ email: 'cc2@example.com', name: 'CC Recipient' }
],
bcc: [
'bcc@example.com',
{ email: 'bcc2@example.com', name: 'BCC Recipient' }
],
subject: 'Multi-recipient Email',
text: 'This email goes to multiple recipients'
};
const result: SendResult = await postie.send(emailOptions);// Template email with required fields
const templateEmail: TemplateEmailOptions = {
from: 'sender@example.com',
to: 'to@example.com',
subject: 'Welcome',
template: 'Hello {{name}}, welcome to {{company}}!',
data: {
name: 'John Doe',
company: 'Example Inc'
}
};
const templateResult: SendResult = await postie.sendTemplate(templateEmail);const templateEngine: TemplateEngine = {
compile: (template: string) => template,
render: (compiled: unknown, data: Record<string, any>) => {
return (compiled as string).replace(/\{\{(\w+)\}\}/g, (match: string, key: string) => data[key] || match);
}
};
postie.setTemplateEngine(templateEngine);const logMiddleware: Middleware = (options: EmailOptions, next: () => void) => {
console.log('Middleware: Preparing to send email to:', options.to);
next();
};
postie.use(logMiddleware);// Define an alias with all available options
const welcomeAlias: AliasConfig = {
type: 'notify',
from: 'sender@example.com',
fromName: 'Project Team',
to: 'to@example.com',
toName: 'Recipient Name',
cc: 'cc@example.com',
ccName: 'CC Recipient',
bcc: 'bcc@example.com',
bccName: 'BCC Recipient',
subject: 'Welcome',
text: 'This is a welcome email',
html: '<p>This is a welcome email</p>',
template: 'Hello {{name}}, welcome to {{company}}!',
data: {
company: 'Example Inc'
},
attachments: [
{
filename: 'welcome.pdf',
path: '/path/to/welcome.pdf',
contentType: 'application/pdf'
}
],
headers: {
'X-Custom-Header': 'value'
}
};
postie.define('welcome', welcomeAlias);
// Trigger with overrides
const result: SendResult = await postie.trigger('welcome', {
to: 'newuser@example.com',
data: {
name: 'John Doe'
}
});// Notification with all available options
const notificationResult: SendResult = await postie.notify({
from: 'sender@example.com',
fromName: 'System',
to: 'to@example.com',
toName: 'Admin',
subject: 'System Notification',
text: 'This is a notification',
html: '<p>This is a notification</p>',
attachments: [
{
filename: 'log.txt',
content: 'System logs',
contentType: 'text/plain'
}
],
headers: {
'X-Priority': '1'
}
});
// Alert with all available options
const alertResult: SendResult = await postie.alert({
from: 'sender@example.com',
fromName: 'Monitoring',
to: 'to@example.com',
toName: 'Admin',
subject: 'System Alert',
text: 'This is an alert',
html: '<p>This is an alert</p>',
attachments: [
{
filename: 'error.log',
content: 'Error logs',
contentType: 'text/plain'
}
],
headers: {
'X-Priority': '1'
}
});
// Ping with all available options
const pingResult: SendResult = await postie.ping({
from: 'sender@example.com',
fromName: 'System',
to: 'to@example.com',
toName: 'Admin',
subject: 'Ping Test',
text: 'Ping!',
html: '<p>Ping!</p>',
attachments: [
{
filename: 'ping.log',
content: 'Ping logs',
contentType: 'text/plain'
}
],
headers: {
'X-Priority': '1'
}
});try {
const result = await postie.send(emailOptions);
console.log('Email sent successfully:', result);
} catch (error) {
console.error('Failed to send email:', error);
// Error details include:
// - SMTP response
// - Connection status
// - Retry attempts
}// Configure for development
postie.configure({
devMode: true,
retryAttempts: 1,
retryDelay: 100
});
// Send test email
const devResult: SendResult = await postie.send({
to: 'test@example.com',
subject: 'Test Email',
text: 'This is a test email'
});
// Email will be logged but not sentPostie provides flexible configuration options that can be set globally or per instance.
// Configure global settings
postie.configure({
devMode: false, // Enable development mode
retryAttempts: 3, // Number of retry attempts
retryDelay: 1000 // Delay between retries in milliseconds
})// Configure SMTP settings
postie.setTransporter({
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: 'your-email@gmail.com',
pass: 'your-app-password'
}
})// Configure template engine
postie.setTemplateEngine({
render: (template, data) => {
// Custom template rendering logic
return renderedTemplate
}
})const Postie = require('@anishhs/postie')
const postie = new Postie()
// Configure SMTP
postie.setTransporter({
host: 'smtp.gmail.com',
port: 587,
secure: false, // Use STARTTLS
auth: {
user: 'your-email@gmail.com',
pass: 'your-app-password'
}
})
// Optional: Configure retry settings
postie.configure({
retryAttempts: 3,
retryDelay: 1000,
devMode: false
})Configures the SMTP transporter.
postie.setTransporter({
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: 'your-email@gmail.com',
pass: 'your-app-password'
}
})Sets global configuration options.
postie.configure({
devMode: false, // Enable development mode
retryAttempts: 3, // Number of retry attempts
retryDelay: 1000 // Delay between retries in milliseconds
})Tests the SMTP connection.
const success = await postie.testConnection()
if (success) {
console.log('SMTP connection successful')
}await postie.send({
from: 'sender@example.com',
fromName: 'John Doe', // Optional
to: 'recipient@example.com',
toName: 'Jane Smith', // Optional
subject: 'Hello',
text: 'This is a test email'
})await postie.send({
from: 'sender@example.com',
to: [
'recipient1@example.com',
{ email: 'recipient2@example.com', name: 'Recipient 2' }
],
subject: 'Hello',
text: 'This is a test email'
})await postie.send({
from: 'sender@example.com',
to: 'recipient@example.com',
subject: 'Hello',
html: '<h1>Hello</h1><p>This is an HTML email.</p>'
})await postie.send({
from: 'sender@example.com',
to: 'recipient@example.com',
subject: 'Hello',
text: 'This is a test email',
attachments: [
{
filename: 'document.pdf',
path: '/path/to/document.pdf'
}
]
})Sends a notification email with a "[NOTIFICATION]" prefix.
await postie.notify({
from: 'sender@example.com',
to: 'recipient@example.com',
subject: 'System Update',
text: 'The system has been updated'
})Sends an alert email with an "[ALERT]" prefix.
await postie.alert({
from: 'sender@example.com',
to: 'recipient@example.com',
subject: 'High CPU Usage',
text: 'CPU usage is above 90%'
})Sends a simple ping email.
await postie.ping({
from: 'sender@example.com',
to: 'recipient@example.com'
})Postie supports any template engine that follows the standard template engine interface. Here are examples for different template engines:
const Handlebars = require('handlebars')
const handlebarsEngine = {
compile: Handlebars.compile,
render: (compiled, data) => compiled(data)
}
postie.setTemplateEngine(handlebarsEngine)const ejs = require('ejs')
const ejsEngine = {
compile: (template) => ejs.compile(template),
render: (compiled, data) => compiled(data)
}
postie.setTemplateEngine(ejsEngine)You can create your own simple template engine:
const customEngine = {
render: (template, data) => {
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => data[key] || match)
}
}
postie.setTemplateEngine(customEngine)You can send template emails in two ways:
- Using a template string:
await postie.sendTemplate({
from: 'sender@example.com',
to: 'recipient@example.com',
subject: 'Welcome',
template: 'Hello {{name}}, Welcome to {{company}}!',
data: {
name: 'John Doe',
company: 'Our Company'
}
})- Using a template file:
await postie.sendTemplate({
from: 'sender@example.com',
to: 'recipient@example.com',
subject: 'Welcome',
template: path.join(__dirname, 'templates/welcome.hbs'),
data: {
name: 'John Doe',
company: 'Our Company',
role: 'Developer'
}
})To use a custom template engine, implement the following interface:
const customEngine = {
// Required: Function to render the template with data
render: (template, data) => {
// Return the rendered template string
return renderedTemplate
},
// Optional: Function to compile the template
compile: (template) => {
// Return a compiled template function
return compiledTemplate
}
}Add middleware functions to modify email options before sending.
// Add logging middleware
postie.use((emailOptions, next) => {
console.log('Sending email:', emailOptions)
next()
})
// Add custom header middleware
postie.use((emailOptions, next) => {
emailOptions.headers = {
...emailOptions.headers,
'X-Custom-Header': 'value'
}
next()
})Postie allows you to define reusable email configurations with aliases and trigger them with optional overrides. This is useful for setting up reusable email configurations.
// Define a welcome email alias
postie.define('user-welcome', {
from: 'welcome@example.com',
subject: 'Welcome to Our Platform',
template: 'Hello {{name}}, welcome to {{company}}!',
data: {
company: 'Example Inc'
}
})
// Define a notification alias
postie.define('system-update', {
type: 'notify',
from: 'system@example.com',
subject: 'System Update',
text: 'A new system update is available'
})
// Define an alert alias
postie.define('high-usage', {
type: 'alert',
from: 'monitoring@example.com',
subject: 'High Resource Usage',
text: 'CPU usage is above 90%'
})// Trigger welcome email with overrides
await postie.trigger('user-welcome', {
to: 'john@example.com',
data: {
name: 'John Doe'
}
})
// Trigger system update
await postie.trigger('system-update', {
to: 'admin@example.com'
})
// Trigger alert with custom message
await postie.trigger('high-usage', {
to: 'admin@example.com',
text: 'Memory usage is above 95%'
})You can use any of the following options in your alias configuration:
- Basic email options (
from,to,subject,text,html) - Template options (
template,data) - Special types (
type: 'notify',type: 'alert',type: 'ping') - Attachments
- Headers
- Any other options supported by the email sending methods
When triggering an alias, you can override any of these options by passing them in the overrides object.
postie configure \
--host smtp.gmail.com \
--port 587 \
--user your-email@gmail.com \
--pass your-app-password \
--secure false# Basic email
postie send \
--from sender@example.com \
--to recipient@example.com \
--subject "Hello" \
--text "This is a test email"
# Send with HTML
postie send \
--from sender@example.com \
--to recipient@example.com \
--subject "Hello" \
--html template.html
# Send with attachments
postie send \
--from sender@example.com \
--to recipient@example.com \
--subject "Hello" \
--text "This is a test email" \
--attachments file1.pdf,file2.pdfPostie supports predefined email configurations through CLI aliases in your .postierc file. These aliases use the event-based triggering system under the hood.
# Send a predefined notification
postie send --alias notify-admin
# Send a system alert
postie send --alias system-alertWhen you use a CLI alias:
- Postie looks up the alias configuration in your
.postiercfile - It uses the event-based triggering system to send the email
- The email is sent using the configured SMTP settings
You can override any alias configuration with command-line arguments:
# Override the recipient for a predefined notification
postie send --alias notify-admin --to "different-admin@example.com"
# Override the subject for a system alert
postie send --alias system-alert --subject "Custom Alert"{
"devMode": false,
"retryAttempts": 3,
"retryDelay": 1000,
"transporter": {
"host": "smtp.gmail.com",
"port": 587,
"secure": false,
"auth": {
"user": "your-email@gmail.com",
"pass": "your-app-password"
}
}
}You can create a .postierc file in your project root to specify default options for that project. This is useful when you have project-specific email settings. The settings in .postierc will override the global configuration from ~/.postie/config.json.
Example .postierc file:
{
"emailDefaults": {
// Basic email options
"from": "project@example.com",
"fromName": "Project Team",
"subject": "Default Subject",
"text": "Default email content",
"html": "<h1>Default HTML content</h1>",
// Recipients
"to": "team@example.com",
"toName": "Team Members",
"cc": "manager@example.com",
"ccName": "Project Manager",
"bcc": "archive@example.com",
"bccName": "Archive",
// Multiple recipients (array format)
"to": [
"team@example.com",
{ "email": "manager@example.com", "name": "Project Manager" }
],
"cc": [
"stakeholder@example.com",
{ "email": "reviewer@example.com", "name": "Code Reviewer" }
],
"bcc": [
"archive@example.com",
{ "email": "audit@example.com", "name": "Audit Team" }
],
// Attachments
"attachments": [
"docs/report.pdf",
"docs/status.xlsx"
]
},
// SMTP settings (overrides global config)
"smtp": {
"host": "smtp.project.com",
"port": 587,
"secure": false,
"auth": {
"user": "project@example.com",
"pass": "project-password"
},
"debug": true,
"logger": true
},
// Postie configuration (overrides global config)
"configure": {
"devMode": false,
"retryAttempts": 3,
"retryDelay": 1000
},
// CLI Aliases
"aliases": {
"notify-admin": {
"to": "admin@example.com",
"subject": "Alert!",
"text": "Something happened"
},
"welcome-user": {
"type": "notify",
"to": "{{email}}",
"subject": "Welcome {{name}}!",
"template": "Hello {{name}}, welcome to our platform!",
"data": {
"company": "Example Inc"
}
},
"system-alert": {
"type": "alert",
"to": "admin@example.com",
"subject": "System Alert",
"text": "{{message}}"
}
}
}Postie provides comprehensive error handling for various scenarios:
try {
await postie.testConnection()
} catch (error) {
console.error('SMTP connection failed:', error.message)
}try {
await postie.send(emailOptions)
} catch (error) {
console.error('Failed to send email:', error.message)
// Error details include:
// - SMTP response
// - Connection status
// - Retry attempts
}try {
postie.configure(invalidConfig)
} catch (error) {
console.error('Invalid configuration:', error.message)
}Postie automatically retries failed email sends based on configuration:
- Number of retry attempts
- Delay between retries
- Exponential backoff
Development mode provides additional features for testing and debugging:
postie.configure({
devMode: true
})- Email Preview: Emails are not actually sent
- Debug Logging: Detailed logs of email processing
- Template Testing: Easy testing of email templates
- Configuration Validation: Strict validation of settings
// Configure for development
postie.configure({
devMode: true,
retryAttempts: 1, // Fewer retries in development
retryDelay: 100 // Shorter delay in development
})
// Send test email
await postie.send({
to: 'test@example.com',
subject: 'Test Email',
text: 'This is a test email'
})
// Email will be logged but not sent