mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 06:14:59 +00:00
SMTP Send Workflow Plugin - Phase 6
Sends emails via SMTP with full support for HTML/text alternatives, attachments, and credential integration.
Features
- Multi-format emails: Plain text, HTML, or both (MIME alternatives)
- Recipients: To, CC, BCC with comprehensive validation
- Attachments: Multiple files with MIME type detection and inline support
- Security: SMTP credential entity integration with encrypted passwords
- Error handling: Per-recipient delivery failure tracking with retry logic
- Delivery tracking: Message ID and queue ID from SMTP server
- Network resilience: Exponential backoff retry with configurable attempts
- Email headers: Custom headers, reply-to, delivery notifications
Configuration
Node Type: smtp-send
Category: email-integration
Inputs:
interface SMTPSendConfig {
// Either credentialId OR smtpConfig (not both)
credentialId?: string; // UUID of Credential entity with SMTP config
smtpConfig?: SMTPConfig; // Inline SMTP configuration
// SMTP Configuration (if using inline)
smtpConfig: {
host: string; // SMTP server (e.g., smtp.gmail.com)
port: number; // Port: 587 (TLS), 465 (SSL), 25 (plain)
username: string; // SMTP username
password: string; // SMTP password (encrypted in Credential)
encryption: 'tls' | 'ssl' | 'none'; // Connection encryption
timeout?: number; // Connection timeout ms (default: 30000)
retryAttempts?: number; // Retries on network failure (0-3, default: 2)
};
// Email Fields
from: string; // Sender email address (required)
fromName?: string; // Sender display name
to: string[]; // Recipients (required, at least 1)
cc?: string[]; // CC recipients
bcc?: string[]; // BCC recipients
replyTo?: string; // Reply-To address
// Content
subject: string; // Email subject (required)
textBody?: string; // Plain text body (or htmlBody required)
htmlBody?: string; // HTML body (or textBody required)
// Attachments
attachments?: EmailAttachment[]; // Array of files to attach
// Headers and Notifications
customHeaders?: Record<string, string>; // Custom email headers
requestDeliveryNotification?: boolean; // RFC 1891 DSN
requestReadReceipt?: boolean; // Request read receipt
}
interface EmailAttachment {
filename: string; // Filename for display
contentType: string; // MIME type (e.g., 'application/pdf')
data: string; // Base64-encoded content
contentId?: string; // Content-ID for inline images
inline?: boolean; // Whether to embed in HTML
}
Outputs:
interface SendResult {
status: 'sent' | 'partial' | 'failed'; // Delivery status
messageId?: string; // SMTP message ID
sentAt: number; // Timestamp
errors: DeliveryError[]; // Per-recipient failures
successCount: number; // Successfully delivered
failureCount: number; // Failed recipients
queueId?: string; // Mail server queue ID
smtpCode?: number; // SMTP response code
smtpResponse?: string; // SMTP response message
shouldRetry: boolean; // Whether workflow should retry
}
interface DeliveryError {
recipient: string;
errorType: 'invalid_address' | 'auth_failed' | 'network_error' | 'send_failed' | 'unknown';
message: string;
retryable: boolean;
}
Usage Examples
Simple Email with Text Body
{
"id": "send-notification",
"nodeType": "smtp-send",
"parameters": {
"from": "noreply@example.com",
"fromName": "MyApp",
"to": ["user@example.com"],
"subject": "Notification",
"textBody": "This is a notification",
"smtpConfig": {
"host": "smtp.gmail.com",
"port": 587,
"username": "bot@gmail.com",
"password": "app-password-here",
"encryption": "tls"
}
}
}
HTML Email with CC/BCC
{
"id": "send-report",
"nodeType": "smtp-send",
"parameters": {
"credentialId": "cred-smtp-prod",
"from": "reports@company.com",
"to": ["manager@company.com"],
"cc": ["team@company.com"],
"bcc": ["archive@company.com"],
"subject": "Weekly Report",
"textBody": "See HTML version below",
"htmlBody": "<html><body><h1>Weekly Report</h1><p>...</p></body></html>",
"replyTo": "support@company.com"
}
}
Email with Attachments
{
"id": "send-invoice",
"nodeType": "smtp-send",
"parameters": {
"credentialId": "cred-smtp-prod",
"from": "billing@company.com",
"to": ["customer@example.com"],
"subject": "Invoice #12345",
"textBody": "Please see attached invoice",
"attachments": [
{
"filename": "invoice-12345.pdf",
"contentType": "application/pdf",
"data": "JVBERi0xLjQKJeLj..."
},
{
"filename": "terms.txt",
"contentType": "text/plain",
"data": "VmFsdWUxCg=="
}
]
}
}
Email with Inline Image
{
"id": "send-welcome",
"nodeType": "smtp-send",
"parameters": {
"credentialId": "cred-smtp-prod",
"from": "welcome@company.com",
"to": ["newuser@example.com"],
"subject": "Welcome!",
"htmlBody": "<html><body><img src=\"cid:company-logo\" /><p>Welcome!</p></body></html>",
"attachments": [
{
"filename": "logo.png",
"contentType": "image/png",
"data": "iVBORw0KGgoAAAANSUhEUg...",
"contentId": "company-logo",
"inline": true
}
]
}
}
Using Credential Entity for SMTP Config
{
"id": "send-via-credential",
"nodeType": "smtp-send",
"parameters": {
"credentialId": "cred-smtp-gmail-prod",
"from": "notifications@myapp.com",
"to": ["{{ $json.email }}"],
"subject": "{{ $json.subject }}",
"textBody": "{{ $json.message }}",
"requestDeliveryNotification": true
}
}
Credential Entity Integration
SMTP Send uses the Credential entity for secure storage of SMTP credentials:
entity: Credential
fields:
type: smtp_relay
config:
host: smtp.gmail.com
port: 587
username: bot@gmail.com
password: "<encrypted-app-password>"
encryption: tls
timeout: 30000
retryAttempts: 2
Passwords are encrypted at rest and never returned in queries.
Email Address Validation
- RFC 5322 simplified validation
- Max 254 characters per address
- Formats supported:
simple@example.comuser+tag@example.co.ukfirst.last@example.comuser_name@example.com
Attachment Support
- Multiple attachments: Up to 50 files per email
- Size limits: Total attachments max 20MB (base64 encoded)
- MIME types: Automatic detection from contentType
- Inline images: Support for Content-ID based embedding
Error Handling
Per-Recipient Tracking
The plugin tracks delivery success/failure per recipient:
{
"status": "partial",
"successCount": 2,
"failureCount": 1,
"errors": [
{
"recipient": "invalid@user",
"errorType": "invalid_address",
"message": "Invalid email address format",
"retryable": false
}
]
}
Retryable Errors
Network-based errors are marked as retryable:
network_error: Connection failures, timeouts- Transient SMTP failures
Non-retryable errors:
invalid_address: Bad email formatauth_failed: Authentication failedsend_failed: Permanent rejection by server
Retry Strategy
Exponential backoff on transient failures:
- Attempt 1: Immediate
- Attempt 2: 100ms delay
- Attempt 3: 200ms delay
- Attempt 4: 400ms delay (max 3 retries by default)
Configure with retryAttempts (0-3).
Performance Considerations
- Batch sends: For high volume, consider separate workflow per recipient
- Attachment size: Compress PDFs/images to stay under 20MB total
- Connection reuse: SMTP connections are created per execution (consider pooling in production)
- Timeout: Default 30 seconds, adjust for slow networks
Building
cd smtp-send
npm run build
npm run test
Testing
Comprehensive test suite with 40+ test cases:
npm run test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
Tests cover:
- Email validation (format, length)
- Recipient handling (to, cc, bcc)
- Attachment processing
- Error scenarios (invalid config, network failures)
- Partial delivery with per-recipient tracking
- Retry logic and network resilience
- SMTP configuration options
Installation
Add to workflow package.json:
{
"devDependencies": {
"@metabuilder/workflow-plugin-smtp-send": "workspace:*"
}
}
See Also
- IMAP Sync:
/workflow/plugins/ts/integration/email/imap-sync/- Receive emails - Email Parser:
/workflow/plugins/ts/utility/email-parser/- Parse email content - Credential Entity:
dbal/shared/api/schema/entities/access/credential.yaml - Email Service:
services/email_service/src/smtp_send.py- Python backend - Plugin Registry:
/workflow/plugins/ts/email-plugins.ts
RFC Compliance
- RFC 5321: SMTP protocol and message submission
- RFC 5322: Internet Message Format (headers, multipart)
- RFC 1891: SMTP Service Extension for Delivery Status Notifications (DSN)
- RFC 2231: MIME Parameter Value and Encoded Word Extensions
- RFC 6531: SMTPUTF8 (Unicode email addresses - optional)
Security Notes
- Passwords stored encrypted in Credential entity
- TLS/SSL encryption supported for server connection
- No passwords logged or exposed in error messages
- Credentials fetched via secure DBAL API only
- BCC recipients hidden from other recipients