delivera-sdk
v1.1.2
Published
Professional EmailJS SDK with advanced error handling, validation, and retry mechanisms. Supports CommonJS, ES Modules, and TypeScript.
Maintainers
Readme
Delivera SDK
Professional EmailJS SDK for sending emails from client-side and server-side applications with advanced error handling, validation, and retry mechanisms.
Features
- 🚀 Universal Support - CommonJS, ES Modules, and TypeScript
- 🔒 Secure - API key authentication and request validation
- 📧 Multiple Recipients - TO, CC, BCC support
- 🎨 Templates - Dynamic template support with parameter validation
- 🔄 Auto Retry - Exponential backoff retry mechanism
- 📊 Comprehensive Logging - Debug, info, warn, error levels
- ✅ Data Validation - Email format, content length, and parameter validation
- 🛡️ Error Handling - Detailed error codes and messages
- 📱 Framework Agnostic - Works with React, Vue, Angular, Express, Next.js, NestJS
Installation
npm install delivera-sdkQuick Start
ES Modules (Modern JavaScript/TypeScript)
import { Delivera } from "delivera-sdk";
const delivera = new Delivera({
apiKey: process.env.DELIVERA_API_KEY,
baseURL: process.env.DELIVERA_BASE_URL,
timeout: 30000,
retries: 3,
debug: process.env.NODE_ENV === "development",
});
// Send email
await delivera.send({
to: "[email protected]",
subject: "Hello World",
html: "<h1>Hello World!</h1>",
});CommonJS (Node.js/Express)
const { Delivera } = require("delivera-sdk");
const delivera = new Delivera({
apiKey: process.env.DELIVERA_API_KEY,
baseURL: process.env.DELIVERA_BASE_URL,
timeout: 30000,
retries: 3,
debug: process.env.NODE_ENV === "development",
});
// Send email
await delivera.send({
to: "[email protected]",
subject: "Hello World",
html: "<h1>Hello World!</h1>",
});TypeScript
import { Delivera, EmailOptions, ErrorCode } from "delivera-sdk";
const delivera = new Delivera({
apiKey: process.env.DELIVERA_API_KEY!,
baseURL: process.env.DELIVERA_BASE_URL!,
timeout: 30000,
retries: 3,
debug: process.env.NODE_ENV === "development",
});
const emailOptions: EmailOptions = {
to: "[email protected]",
subject: "Hello World",
html: "<h1>Hello World!</h1>",
};
try {
const result = await delivera.send(emailOptions);
console.log("Email sent:", result.messageId);
} catch (error) {
if (error.code === ErrorCode.TEMPLATE_NOT_FOUND) {
console.error("Template not found");
} else if (error.code === ErrorCode.RATE_LIMIT_EXCEEDED) {
console.error("Rate limit exceeded");
} else {
console.error("Email failed:", error.message);
}
}Configuration Options
interface DeliveraConfig {
apiKey: string; // Required: Your API key
baseURL: string; // Required: API base URL
timeout?: number; // Optional: Request timeout (default: 30000ms)
retries?: number; // Optional: Retry attempts (default: 3)
retryDelay?: number; // Optional: Initial retry delay (default: 1000ms)
debug?: boolean; // Optional: Enable debug logging (default: false)
userAgent?: string; // Optional: Custom user agent
}Advanced Email Options
interface EmailOptions {
to: string | string[]; // Recipient(s)
cc?: string | string[]; // CC recipient(s)
bcc?: string | string[]; // BCC recipient(s)
subject: string; // Email subject
html?: string; // HTML content
text?: string; // Text content
templateId?: string; // Template ID
templateParams?: Record<string, any>; // Template variables
replyTo?: string; // Reply-to email
from?: string; // From email
attachments?: Attachment[]; // File attachments
priority?: "low" | "normal" | "high"; // Email priority
headers?: Record<string, string>; // Custom headers
}Error Handling
import { DeliveraError, ErrorCode } from "delivera-sdk";
try {
await delivera.send(emailOptions);
} catch (error) {
if (error instanceof DeliveraError) {
switch (error.code) {
case ErrorCode.INVALID_API_KEY:
console.error("Invalid API key");
break;
case ErrorCode.TEMPLATE_NOT_FOUND:
console.error("Template not found");
break;
case ErrorCode.RATE_LIMIT_EXCEEDED:
console.error("Rate limit exceeded - retry later");
break;
case ErrorCode.QUOTA_EXCEEDED:
console.error("Service quota exceeded");
break;
case ErrorCode.VALIDATION_ERROR:
console.error("Validation failed:", error.details);
break;
case ErrorCode.NETWORK_ERROR:
console.error("Network error - check connection");
break;
case ErrorCode.TIMEOUT_ERROR:
console.error("Request timeout");
break;
default:
console.error("Unknown error:", error.message);
}
}
}Data Validation
// Validate email options before sending
const validation = delivera.validateTemplate("template_123", {
name: "John Doe",
email: "[email protected]",
});
if (!validation.isValid) {
console.error("Validation errors:", validation.errors);
console.warn("Validation warnings:", validation.warnings);
}
// Validate individual components
import { DeliveraValidator } from "delivera-sdk";
const emailValidation = DeliveraValidator.validateEmail("[email protected]");
const subjectValidation = DeliveraValidator.validateSubject("Hello World");Examples by Framework
Express.js (CommonJS)
const express = require("express");
const { Delivera, ErrorCode } = require("delivera-sdk");
const app = express();
app.use(express.json());
const delivera = new Delivera({
apiKey: process.env.DELIVERA_API_KEY,
baseURL: process.env.DELIVERA_BASE_URL,
timeout: 30000,
retries: 3,
debug: process.env.NODE_ENV === "development",
});
// Send welcome email
app.post("/send-welcome", async (req, res) => {
try {
const { email, name } = req.body;
await delivera.send({
to: email,
subject: "Welcome to Our Platform!",
templateId: "welcome_template",
templateParams: { name, email },
priority: "high",
});
res.json({ success: true, message: "Welcome email sent" });
} catch (error) {
if (error.code === ErrorCode.VALIDATION_ERROR) {
res.status(400).json({ error: "Invalid email address" });
} else if (error.code === ErrorCode.RATE_LIMIT_EXCEEDED) {
res.status(429).json({ error: "Too many requests" });
} else {
res.status(500).json({ error: "Failed to send email" });
}
}
});
// Send bulk emails
app.post("/send-bulk", async (req, res) => {
try {
const { recipients, subject, templateId, templateParams } = req.body;
const results = await Promise.allSettled(
recipients.map((email) =>
delivera.send({
to: email,
subject,
templateId,
templateParams,
})
)
);
const successful = results.filter((r) => r.status === "fulfilled").length;
const failed = results.filter((r) => r.status === "rejected").length;
res.json({
success: true,
sent: successful,
failed,
results,
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log("Server running on port 3000");
});Next.js (ES Modules)
// pages/api/send-email.js
import { Delivera, ErrorCode } from 'delivera-sdk'
const delivera = new Delivera({
apiKey: process.env.DELIVERA_API_KEY,
baseURL: process.env.DELIVERA_BASE_URL,
timeout: 30000,
retries: 3,
debug: process.env.NODE_ENV === 'development'
})
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' })
}
try {
const { email, name, templateId } = req.body
// Validate input
if (!email || !name) {
return res.status(400).json({ error: 'Email and name are required' })
}
const result = await delivera.send({
to: email,
subject: 'Welcome to Our Platform!',
templateId: templateId || 'default_welcome',
templateParams: { name, email },
priority: 'normal'
})
res.json({
success: true,
messageId: result.messageId,
timestamp: result.timestamp
})
} catch (error) {
console.error('Email sending failed:', error)
if (error.code === ErrorCode.VALIDATION_ERROR) {
res.status(400).json({ error: 'Invalid email address' })
} else if (error.code === ErrorCode.RATE_LIMIT_EXCEEDED) {
res.status(429).json({ error: 'Rate limit exceeded' })
} else if (error.code === ErrorCode.QUOTA_EXCEEDED) {
res.status(503).json({ error: 'Service quota exceeded' })
} else {
res.status(500).json({ error: 'Failed to send email' })
}
}
}
// pages/api/send-bulk.js
import { Delivera, ErrorCode } from 'delivera-sdk'
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' })
}
try {
const { recipients, subject, templateId, templateParams } = req.body
if (!recipients || !Array.isArray(recipients)) {
return res.status(400).json({ error: 'Recipients array is required' })
}
// Limit batch size
if (recipients.length > 100) {
return res.status(400).json({ error: 'Maximum 100 recipients per batch' })
}
const delivera = new Delivera({
apiKey: process.env.DELIVERA_API_KEY,
baseURL: process.env.DELIVERA_BASE_URL,
timeout: 60000, // Longer timeout for bulk operations
retries: 5
})
const results = await Promise.allSettled(
recipients.map(recipient =>
delivera.send({
to: recipient.email,
subject: subject || 'Bulk Email',
templateId,
templateParams: { ...templateParams, ...recipient }
})
)
)
const successful = results.filter(r => r.status === 'fulfilled').length
const failed = results.filter(r => r.status === 'rejected').length
res.json({
success: true,
total: recipients.length,
sent: successful,
failed,
results: results.map((result, index) => ({
recipient: recipients[index],
status: result.status,
error: result.status === 'rejected' ? result.reason.message : null
}))
})
} catch (error) {
console.error('Bulk email failed:', error)
res.status(500).json({ error: 'Bulk email operation failed' })
}
}NestJS (TypeScript)
// email.service.ts
import { Injectable, Logger } from "@nestjs/common";
import { Delivera, EmailOptions, ErrorCode, DeliveraError } from "delivera-sdk";
@Injectable()
export class EmailService {
private readonly logger = new Logger(EmailService.name);
private delivera: Delivera;
constructor() {
this.delivera = new Delivera({
apiKey: process.env.DELIVERA_API_KEY!,
baseURL: process.env.DELIVERA_BASE_URL!,
timeout: 30000,
retries: 3,
debug: process.env.NODE_ENV === "development",
});
}
async sendWelcomeEmail(email: string, name: string): Promise<void> {
try {
await this.delivera.send({
to: email,
subject: "Welcome to Our Platform!",
templateId: "welcome_template",
templateParams: { name, email },
priority: "high",
});
this.logger.log(`Welcome email sent to ${email}`);
} catch (error) {
this.logger.error(`Failed to send welcome email to ${email}:`, error);
throw error;
}
}
async sendPasswordReset(email: string, resetToken: string): Promise<void> {
try {
await this.delivera.send({
to: email,
subject: "Password Reset Request",
templateId: "password_reset",
templateParams: {
email,
resetLink: `${process.env.FRONTEND_URL}/reset-password?token=${resetToken}`,
expiryTime: "1 hour",
},
priority: "high",
});
this.logger.log(`Password reset email sent to ${email}`);
} catch (error) {
if (error instanceof DeliveraError) {
switch (error.code) {
case ErrorCode.TEMPLATE_NOT_FOUND:
this.logger.error("Password reset template not found");
break;
case ErrorCode.VALIDATION_ERROR:
this.logger.error("Invalid email for password reset:", email);
break;
default:
this.logger.error(
`Password reset email failed for ${email}:`,
error.message
);
}
}
throw error;
}
}
async sendBulkEmails(
recipients: Array<{ email: string; name: string }>,
templateId: string,
templateParams: Record<string, any>
): Promise<{ sent: number; failed: number }> {
let sent = 0;
let failed = 0;
const results = await Promise.allSettled(
recipients.map((recipient) =>
this.delivera.send({
to: recipient.email,
templateId,
templateParams: { ...templateParams, ...recipient },
})
)
);
results.forEach((result, index) => {
if (result.status === "fulfilled") {
sent++;
this.logger.log(`Email sent to ${recipients[index].email}`);
} else {
failed++;
this.logger.error(
`Email failed for ${recipients[index].email}:`,
result.reason
);
}
});
this.logger.log(`Bulk email completed: ${sent} sent, ${failed} failed`);
return { sent, failed };
}
}
// email.controller.ts
import {
Controller,
Post,
Body,
HttpException,
HttpStatus,
} from "@nestjs/common";
import { EmailService } from "./email.service";
@Controller("email")
export class EmailController {
constructor(private readonly emailService: EmailService) {}
@Post("welcome")
async sendWelcome(@Body() body: { email: string; name: string }) {
try {
await this.emailService.sendWelcomeEmail(body.email, body.name);
return { success: true, message: "Welcome email sent" };
} catch (error) {
throw new HttpException(
"Failed to send welcome email",
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
@Post("password-reset")
async sendPasswordReset(@Body() body: { email: string; resetToken: string }) {
try {
await this.emailService.sendPasswordReset(body.email, body.resetToken);
return { success: true, message: "Password reset email sent" };
} catch (error) {
throw new HttpException(
"Failed to send password reset email",
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
}React (Client-side)
import React, { useState } from "react";
import { Delivera, ErrorCode } from "delivera-sdk";
function ContactForm() {
const [isLoading, setIsLoading] = useState(false);
const [message, setMessage] = useState("");
const delivera = new Delivera({
apiKey: process.env.NEXT_PUBLIC_DELIVERA_API_KEY,
baseURL: process.env.NEXT_PUBLIC_DELIVERA_BASE_URL,
timeout: 30000,
retries: 3,
debug: process.env.NODE_ENV === "development",
});
const handleSubmit = async (e) => {
e.preventDefault();
setIsLoading(true);
setMessage("");
const formData = new FormData(e.target);
const data = {
name: formData.get("name"),
email: formData.get("email"),
message: formData.get("message"),
};
try {
await delivera.send({
to: "[email protected]",
subject: "New Contact Form Submission",
html: `
<h2>New Contact Form Submission</h2>
<p><strong>Name:</strong> ${data.name}</p>
<p><strong>Email:</strong> ${data.email}</p>
<p><strong>Message:</strong></p>
<p>${data.message.replace(/\n/g, "<br>")}</p>
`,
text: `
New Contact Form Submission
Name: ${data.name}
Email: ${data.email}
Message: ${data.message}
`,
priority: "normal",
});
setMessage("Message sent successfully!");
e.target.reset();
} catch (error) {
console.error("Contact form error:", error);
if (error.code === ErrorCode.VALIDATION_ERROR) {
setMessage("Please check your email address");
} else if (error.code === ErrorCode.RATE_LIMIT_EXCEEDED) {
setMessage("Too many requests. Please try again later.");
} else {
setMessage("Failed to send message. Please try again.");
}
} finally {
setIsLoading(false);
}
};
return (
<form onSubmit={handleSubmit} className="contact-form">
<div>
<label htmlFor="name">Name:</label>
<input
type="text"
id="name"
name="name"
required
disabled={isLoading}
/>
</div>
<div>
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
required
disabled={isLoading}
/>
</div>
<div>
<label htmlFor="message">Message:</label>
<textarea
id="message"
name="message"
rows="5"
required
disabled={isLoading}
/>
</div>
<button type="submit" disabled={isLoading}>
{isLoading ? "Sending..." : "Send Message"}
</button>
{message && (
<div
className={`message ${
message.includes("success") ? "success" : "error"
}`}
>
{message}
</div>
)}
</form>
);
}
export default ContactForm;Logging and Debugging
import { Delivera, LogLevel } from "delivera-sdk";
const delivera = new Delivera({
apiKey: process.env.DELIVERA_API_KEY,
baseURL: process.env.DELIVERA_BASE_URL,
debug: true, // Enable debug mode
timeout: 30000,
});
// Set log level
delivera.setLogLevel(LogLevel.DEBUG);
// Test connection
const isConnected = await delivera.testConnection();
console.log("Connected:", isConnected);
// Get detailed logs
delivera.setDebug(true);
// Monitor email sending
try {
const result = await delivera.send({
to: "[email protected]",
subject: "Test Email",
html: "<h1>Test</h1>",
});
console.log("Email sent:", result);
} catch (error) {
console.error("Email failed:", error);
}Monitoring and Analytics
// Get email statistics
const stats = await delivera.getStats();
console.log("Email stats:", stats);
// Get email logs
const logs = await delivera.getLogs(1, 50);
console.log("Recent emails:", logs.logs);
// Get available services
const services = await delivera.getServices();
console.log("Available services:", services);
// Get available templates
const templates = await delivera.getTemplates();
console.log("Available templates:", templates);API Reference
Delivera(config)
Creates a new Delivera instance.
Configuration:
apiKey(string, required): Your API keybaseURL(string, required): API base URLtimeout(number, optional): Request timeout in milliseconds (default: 30000)retries(number, optional): Retry attempts (default: 3)retryDelay(number, optional): Initial retry delay in milliseconds (default: 1000)debug(boolean, optional): Enable debug logging (default: false)userAgent(string, optional): Custom user agent
delivera.send(options)
Sends an email with comprehensive validation and error handling.
Options:
to(string | string[]): Recipient email(s)cc(string | string[], optional): CC recipient(s)bcc(string | string[], optional): BCC recipient(s)subject(string): Email subjecthtml(string, optional): HTML contenttext(string, optional): Text contenttemplateId(string, optional): Template IDtemplateParams(object, optional): Template variablesreplyTo(string, optional): Reply-to emailfrom(string, optional): From emailattachments(Attachment[], optional): File attachmentspriority('low' | 'normal' | 'high', optional): Email priorityheaders(object, optional): Custom headers
delivera.sendForm(form, options?)
Sends an email using form data.
Parameters:
form(HTMLFormElement | string): Form element or selectoroptions(object, optional): Additional email options
delivera.testConnection()
Tests the connection to the API server.
Returns: Promise
delivera.getServices()
Gets available email services.
Returns: Promise<EmailService[]>
delivera.getTemplates()
Gets available templates.
Returns: Promise<Template[]>
delivera.getLogs(page?, limit?)
Gets email logs with pagination.
Parameters:
page(number, optional): Page number (default: 1)limit(number, optional): Items per page (default: 20)
Returns: Promise<{logs: EmailLog[], pagination: object}>
delivera.getStats()
Gets email statistics.
Returns: Promise
delivera.validateTemplate(templateId, templateParams)
Validates template ID and parameters.
Parameters:
templateId(string): Template ID to validatetemplateParams(object): Template parameters to validate
Returns: ValidationResult
delivera.configure(newConfig)
Updates the SDK configuration.
Parameters:
newConfig(Partial): New configuration options
delivera.getConfig()
Gets current configuration (without sensitive data).
Returns: Omit<DeliveraConfig, 'apiKey'>
delivera.setLogLevel(level)
Sets the logging level.
Parameters:
level(LogLevel): Log level (debug, info, warn, error)
delivera.setDebug(debug)
Enables or disables debug mode.
Parameters:
debug(boolean): Enable debug mode
Error Codes
| Code | Description | HTTP Status |
| --------------------- | -------------------------- | ----------- |
| INVALID_API_KEY | Invalid or missing API key | 401 |
| TEMPLATE_NOT_FOUND | Template does not exist | 404 |
| SERVICE_NOT_FOUND | Email service not found | 404 |
| RATE_LIMIT_EXCEEDED | Too many requests | 429 |
| QUOTA_EXCEEDED | Service quota exceeded | 503 |
| INVALID_EMAIL | Invalid email format | 422 |
| VALIDATION_ERROR | Data validation failed | 422 |
| NETWORK_ERROR | Network connection error | - |
| TIMEOUT_ERROR | Request timeout | - |
| UNKNOWN_ERROR | Unknown error occurred | - |
Environment Variables
# Required
DELIVERA_API_KEY=your-api-key
DELIVERA_BASE_URL=https://api.delivera.site
# For client-side usage
NEXT_PUBLIC_DELIVERA_API_KEY=your-api-key
NEXT_PUBLIC_DELIVERA_BASE_URL=https://api.delivera.site
# Optional
NODE_ENV=development # Enable debug mode in developmentMigration Guide
From v1.0.0 to v1.1.0
The new version introduces breaking changes for better error handling and validation:
// Old way (v1.0.0)
const delivera = new Delivera({
publicKey: "your-key",
baseURL: "your-url",
});
// New way (v1.1.0)
const delivera = new Delivera({
apiKey: "your-key", // Changed from publicKey
baseURL: "your-url",
timeout: 30000, // New optional config
retries: 3, // New optional config
debug: false, // New optional config
});Compatibility
- ✅ Node.js 16+ (CommonJS + ES Modules)
- ✅ Express.js (CommonJS)
- ✅ Next.js 12+ (ES Modules)
- ✅ React 16+ (ES Modules)
- ✅ Vue.js 3+ (ES Modules)
- ✅ Angular 12+ (ES Modules)
- ✅ NestJS (TypeScript)
- ✅ TypeScript 4.5+ (Full support)
- ✅ Browser (ES Modules + UMD)
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see LICENSE file for details.
Support
- 📧 Email: [email protected]
- 📚 Documentation: https://docs.delivera.com
- 🐛 Issues: https://github.com/delivera/sdk/issues
- 💬 Discord: https://discord.gg/delivera
