Compose beautiful multilingual emails with XHTML templates and Nodemailer
npm install composapassword-reset | β
| β
| Password reset emails |
account-creation | β
| β
| Welcome new users |
suspicious-login | β
| β
| Security alerts |
subscription-confirmation | β
| β
| Newsletter subscriptions |
newsletter-promotion | β
| β
| Marketing campaigns |
scheduled-maintenance | β
| β
| System notifications |
bash
npm install composa
`
$3
`javascript
import { EmailClient, defaultSubjects, createGmailConfig } from "composa";
const mailer = new EmailClient({
defaultLang: "fr",
subjects: defaultSubjects,
transport: createGmailConfig("your-email@gmail.com", "your-app-password"),
});
// New flow: compileMail β sendMail
const { html, subject } = mailer.compileMail("password-reset", {
lang: "fr",
variables: {
USER_NAME: "Jean Dupont",
USER_EMAIL: "user@example.com",
RESET_URL: "https://yourapp.com/reset/token123",
EXPIRATION_TIME: "24 heures",
},
});
const result = await mailer.sendMail({
to: "user@example.com",
html,
subject,
});
console.log("Email sent:", result);
`
$3
`typescript
import { EmailClient, createGmailConfig, type EmailClientOptions, type MailOptions } from "composa";
const options: EmailClientOptions = {
defaultLang: "fr",
defaultFrom: "noreply@myapp.com",
transport: createGmailConfig("your-email@gmail.com", "your-app-password"),
};
const mailer = new EmailClient(options);
const mailOptions: MailOptions = {
to: "user@example.com",
subject: "Welcome!",
html: "Welcome to our app!
"
};
const result = await mailer.send(mailOptions);
`
> TypeScript Support: Composa includes full TypeScript definitions with IntelliSense, compile-time checking, and type safety. See TYPESCRIPT.md for detailed TypeScript usage examples.
Component-based Flow
Composa uses a component-like approach where you can compose templates step by step:
$3
1. compileTemplate - Compile individual templates (like components)
2. compileMail - Combine templates into a complete email (HTML + subject)
3. sendMail - Send the final composed email
$3
`javascript
// Compile individual components
const headerHtml = mailer.compileTemplate("email-header", {
variables: { APP_NAME: "MyApp", USER_NAME: "John" },
});
const itemListHtml = items
.map((item) =>
mailer.compileTemplate("list-item", {
variables: { NAME: item.name, PRICE: item.price },
}),
)
.join("");
// Compose the main email
const { html, subject } = mailer.compileMail("newsletter", {
variables: {
HEADER: headerHtml,
ITEM_LIST: ,
FOOTER: mailer.compileTemplate("email-footer", {}),
},
});
// Send the composed email
await mailer.sendMail({ to: "user@example.com", html, subject });
`
Email Providers
Composa supports multiple email providers with easy configuration:
$3
`javascript
import { createGmailConfig } from "composa";
const gmailConfig = createGmailConfig("your-email@gmail.com", "your-app-password");
const mailer = new EmailClient({ transport: gmailConfig });
`
Setup Steps:
1. Enable 2-Factor Authentication on your Google account
2. Go to Google Account settings > Security > 2-Step Verification
3. Generate an 'App Password' for 'Mail'
4. Use your Gmail address and the App Password (not your regular password)
$3
`javascript
import {
createYahooConfig,
createOutlookConfig,
createSendGridConfig,
createMailgunConfig,
createAOLConfig,
createGMXConfig,
createZohoConfig,
createiCloudConfig
} from "composa";
// Yahoo (requires App Password)
const yahoo = createYahooConfig("your-email@yahoo.com", "your-app-password");
// Outlook
const outlook = createOutlookConfig("your-email@outlook.com", "your-password");
// SendGrid
const sendgrid = createSendGridConfig("your-sendgrid-api-key");
// Mailgun
const mailgun = createMailgunConfig("your-mailgun-api-key", "your-domain");
// AOL (requires App Password)
const aol = createAOLConfig("your-email@aol.com", "your-app-password");
// GMX
const gmx = createGMXConfig("your-email@gmx.com", "your-password");
// Zoho
const zoho = createZohoConfig("your-email@zoho.com", "your-password");
// iCloud (requires App Password)
const icloud = createiCloudConfig("your-email@icloud.com", "your-app-password");
`
Advanced Usage
$3
`javascript
const recipients = ["user1@example.com", "user2@example.com", "user3@example.com"];
const results = await mailer.sendBulk(recipients, {
subject: "Weekly Newsletter",
html: "Newsletter
Check out our latest updates!
"
});
results.forEach(result => {
if (result.success) {
console.log(β
Email sent to ${result.recipient});
} else {
console.log(β Failed to send to ${result.recipient}: ${result.error});
}
});
`
$3
`javascript
const result = await mailer.sendWithRetry({
to: "user@example.com",
subject: "Important Email",
html: "Important Information
"
}, 3); // Max 3 retries
if (result.success) {
console.log("Email sent successfully:", result.messageId);
} else {
console.log("Email failed after retries:", result.error);
}
`
$3
`javascript
// List available templates
const availableTemplates = mailer.listAvailableTemplates("fr");
console.log("Available templates:", availableTemplates);
// Check if template exists
const exists = mailer.templateExists("password-reset", "fr");
console.log("Template exists:", exists);
// Get template information
const info = mailer.getTemplateInfo("password-reset", "fr");
console.log("Template info:", info);
// Register custom template at runtime
const customTemplate =
Your favorite color is {{USER_COLOR}}.
;
mailer.registerTemplateString("user-welcome", customTemplate, "fr");
// Clear template cache
mailer.clearCache();
`
$3
`text
your-project/
βββ templates/
β βββ en-EN/
β β βββ welcome.xhtml
β β βββ invoice.xhtml
β βββ fr-FR/
β βββ welcome.xhtml
β βββ invoice.xhtml
`
$3
You can create your own templates by adding .xhtml files to the templates directory:
`javascript
// Set custom templates path
const mailer = new EmailClient({
templatesPath: "./my-custom-templates",
defaultLang: "en"
});
`
#### Template Variables
Use {{VARIABLE_NAME}} syntax in your templates:
`xhtml
Welcome to {{APP_NAME}}
Welcome {{USER_NAME}}!
Thank you for joining {{APP_NAME}}.
Your email: {{USER_EMAIL}}
Visit us at: {{APP_URL}}
Need help? Contact us at {{SUPPORT_EMAIL}}
`
#### Template Subjects
Register subjects for your custom templates:
`javascript
// Register subjects for custom templates
mailer.registerSubject("welcome", "en", "Welcome to {{APP_NAME}}, {{USER_NAME}}!");
mailer.registerSubject("welcome", "fr", "Bienvenue sur {{APP_NAME}}, {{USER_NAME}} !");
// Or register multiple subjects at once
mailer.registerSubjects("welcome", {
en: "Welcome to {{APP_NAME}}, {{USER_NAME}}!",
fr: "Bienvenue sur {{APP_NAME}}, {{USER_NAME}} !",
es: "Β‘Bienvenido a {{APP_NAME}}, {{USER_NAME}}!"
});
`
#### Dynamic Template Registration
Register templates at runtime without files:
`javascript
// Register a template string in memory
const customTemplate =
Your favorite color is {{USER_COLOR}}.
Account created: {{CREATION_DATE}}
;
mailer.registerTemplateString("user-welcome", customTemplate, "en");
// Use the registered template
const { html, subject } = mailer.compileMail("user-welcome", {
variables: {
USER_NAME: "John Doe",
USER_COLOR: "#007bff",
CREATION_DATE: new Date().toLocaleDateString()
}
});
`
#### Template Inheritance and Composition
Create reusable template components:
`javascript
// Base template: templates/en-EN/email-base.xhtml
const baseTemplate =
;
mailer.registerTemplateString("email-base", baseTemplate, "en");
// Content template: templates/en-EN/newsletter-content.xhtml
const contentTemplate =
{{NEWSLETTER_CONTENT}}
;
mailer.registerTemplateString("newsletter-content", contentTemplate, "en");
// Compose the final email
const content = mailer.compileTemplate("newsletter-content", {
variables: {
NEWSLETTER_TITLE: "Weekly Updates",
NEWSLETTER_CONTENT: "Here are this week's highlights:",
NEWSLETTER_ITEMS: items.map(item => ).join("")
}
});
const { html, subject } = mailer.compileMail("email-base", {
variables: {
PAGE_TITLE: "Weekly Newsletter",
CONTENT: content
}
});
`
#### Template Validation and Error Handling
`javascript
// Check if template exists before using
if (mailer.templateExists("custom-template", "en")) {
const { html, subject } = mailer.compileMail("custom-template", {
variables: { USER_NAME: "John" }
});
} else {
console.error("Template 'custom-template' not found for language 'en'");
}
// Get detailed template information
const templateInfo = mailer.getTemplateInfo("custom-template", "en");
console.log("Template info:", {
name: templateInfo.name,
language: templateInfo.lang,
exists: templateInfo.exists,
source: templateInfo.source, // 'memory', 'disk', or 'none'
cached: templateInfo.cached,
path: templateInfo.path
});
`
$3
`javascript
const config = await mailer.testConfiguration();
console.log("Configuration test results:");
console.log(SMTP: ${config.smtp ? 'β
Working' : 'β Failed'});
console.log(DKIM: ${config.dkim ? 'β
Enabled' : 'β Disabled'});
console.log(Host: ${config.host}:${config.port} (${config.secure ? 'Secure' : 'Insecure'}));
console.log(Sender: ${config.sender});
console.log(Default Language: ${config.defaultLang});
`
$3
You can configure Composa using environment variables:
`bash
SMTP Configuration
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
DKIM Configuration (optional)
DKIM_DOMAIN=yourdomain.com
DKIM_SELECTOR=default
DKIM_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----...
Default sender
SMTP_FROM=noreply@yourdomain.com
`
`javascript
// Use environment variables
const mailer = new EmailClient({
defaultLang: "en",
// Transport will be created from environment variables
});
`
CLI Tool
Composa includes an interactive CLI for easy setup:
`bash
npx composa setup
`
This will guide you through:
- Provider selection
- Credential configuration
- Template setup
- Testing your configuration
TypeScript Support
Composa includes comprehensive TypeScript definitions:
- IntelliSense - Full auto-completion in your IDE
- Type Safety - Compile-time error checking
- Documentation - Inline help and parameter hints
- Refactoring - Safe renaming and code changes
$3
`typescript
import {
EmailClient,
createGmailConfig,
type EmailClientOptions,
type MailOptions,
type SendResult,
type BulkSendResult
} from "composa";
// Type-safe configuration
const options: EmailClientOptions = {
defaultFrom: "noreply@myapp.com",
defaultLang: "en",
defaults: {
APP_NAME: "My App",
APP_URL: "https://myapp.com"
},
transporter: createGmailConfig("your-email@gmail.com", "your-app-password")
};
const client = new EmailClient(options);
// Type-safe email sending
const mailOptions: MailOptions = {
to: "user@example.com",
subject: "Welcome!",
html: "Welcome to our app!
"
};
const result: Promise = client.send(mailOptions);
`
See TYPESCRIPT.md for detailed TypeScript usage examples and advanced patterns.
Examples
Check out the examples directory for more usage patterns:
- Basic Examples - Simple usage patterns
- Advanced Examples - Complex scenarios
- TypeScript Examples - TypeScript-specific examples
Documentation
- TYPESCRIPT.md - Complete TypeScript guide
- TEMPLATES.md - Template documentation
- CHANGELOG.md - Version history
Contributing
1. Fork the repository
2. Create a feature branch (git checkout -b feature/amazing-feature)
3. Commit your changes (git commit -m 'Add amazing feature')
4. Push to the branch (git push origin feature/amazing-feature`)