Context
Message Service
The Messaging provides a unified API for sending messages through different transport channels. It abstracts the complexity of various messaging systems and provides a consistent interface for sending emails, SMS, webhooks, and other types of messages.
Configuration
SMTP Transport
The SMTP transport enables sending emails through any SMTP server:
[messaging.transports.smtp]
# SMTP server endpoint (required)
endpoint = "smtp://smtp.example.com:587"
# Use smtps:// for secure connections: "smtps://smtp.gmail.com:465"
# Authentication (optional for servers that require auth)
username = "your-username"
credentials = "your-password"
# Default sender address (optional)
defaultFrom = "[email protected]"
# Connection timeout in milliseconds (default: 60000)
timeout = 60000
# Force secure connection (optional, overridden by endpoint protocol)
secure = true
# TLS options (optional)
[message.transports.smtp.tls]
rejectUnauthorized = true
Configuration Examples
Gmail with App Password:
[messaging.transports.smtp]
endpoint = "smtps://smtp.gmail.com:465"
username = "[email protected]"
credentials = "your-app-password"
defaultFrom = "Your Company <[email protected]>"
Local Development (Mailhog/MailCatcher):
[messaging.transports.smtp]
endpoint = "smtp://localhost:1025"
# No auth required for local development servers
Usage
Basic Email
export const sendWelcomeEmail = async (source, args, context) => {
const { userId } = args;
const user = await context.ldap.findUserById(userId);
const result = await context.messaging.send({
transport: 'smtp',
to: user.mail,
subject: 'Welcome to our platform!',
html: '<h1>Welcome!</h1><p>Thank you for joining us.</p>',
text: 'Welcome! Thank you for joining us.', // Optional fallback
});
if (!result.success) {
throw new Error(`Failed to send email: ${result.error}`);
}
return { success: true, messageId: result.messageId };
};
Multiple Recipients
const result = await context.messaging.send({
transport: 'smtp',
to: ['[email protected]', '[email protected]'],
cc: '[email protected]',
bcc: ['[email protected]', '[email protected]'],
subject: 'Team Notification',
html: '<p>Important team update...</p>',
});
Named Email Addresses
const result = await context.messaging.send({
transport: 'smtp',
to: '"John Doe" <[email protected]>',
from: '"Support Team" <[email protected]>',
subject: 'Personal Message',
html: '<p>Hello John!</p>',
});
Email with Attachments
const result = await context.messaging.send({
transport: 'smtp',
to: '[email protected]',
subject: 'Document Delivery',
html: '<p>Please find the attached documents.</p>',
attachments: [
{
filename: 'report.pdf',
content: reportBuffer, // Buffer or base64 string
contentType: 'application/pdf',
},
{
filename: 'data.json',
content: JSON.stringify(data),
contentType: 'application/json',
},
],
});
Automatic HTML-to-Text Conversion
When you provide only HTML content, the service automatically generates a plain text version:
const result = await context.messaging.send({
transport: 'smtp',
to: '[email protected]',
subject: 'Rich Content Email',
html: `
<h1>Welcome!</h1>
<p>Visit our <a href="https://example.com">website</a></p>
<ul>
<li>Feature 1</li>
<li>Feature 2</li>
</ul>
`,
// No text field - automatically generated as:
// "WELCOME!\n\nVisit our website [https://example.com]\n\n* Feature 1\n* Feature 2"
});
API Reference
Messaging Methods
send(message: Message): Promise<MessageResult>
Sends a message through the specified transport.
Parameters:
message: Message object with transport-specific properties
Returns:
MessageResult: Object containing success status, timestamp, messageId, and optional error
getAvailableTransports(): Transport[]
Returns a list of configured transports (without sensitive configuration data).
Returns:
- Array of
Transportobjects with name and sanitized config
Message Types
SMTP Message
interface SMTPMessage {
transport: 'smtp';
to: string | string[]; // Recipients
from?: string; // Sender (uses defaultFrom if not provided)
subject: string; // Email subject
text?: string; // Plain text content
html?: string; // HTML content
cc?: string | string[]; // Carbon copy recipients
bcc?: string | string[]; // Blind carbon copy recipients
attachments?: Array<{
filename: string;
content: string | Buffer;
contentType?: string;
}>;
}
Message Result
interface MessageResult {
transport: string; // Transport used
success: boolean; // Whether message was sent successfully
sentAt?: Date; // Date object of send attempt if successful
messageId?: string; // Unique message identifier (if successful)
error?: string; // Error description (if failed)
}
Error Handling
The Messaging provides consistent error handling across all transports:
const result = await context.messaging.send(message);
if (!result.success) {
console.error(`Message failed: ${result.error}`);
// Handle error appropriately
throw new Error(`Failed to send notification: ${result.error}`);
}
console.log(`Message sent successfully with ID: ${result.messageId}`);
Common Error Scenarios
- Transport not configured: Returns error when specified transport is not available
- Authentication failure: SMTP authentication errors
- Network issues: Connection timeouts or server unavailability
- Validation errors: Invalid email addresses or missing required fields
Best Practices
1. Configuration Management
Store sensitive credentials securely and use environment variables:
[messaging.transports.smtp]
endpoint = "smtp://smtp.example.com:587"
username = "${SMTP_USERNAME}"
credentials = "${SMTP_PASSWORD}"
2. Error Handling
Always check the result and handle failures appropriately:
const result = await context.messaging.send(message);
if (!result.success) {
// Log error for debugging
console.error('Failed to send message:', result.error);
// Decide whether to throw or handle gracefully
if (isRequired) {
throw new Error(`Critical notification failed: ${result.error}`);
}
}
3. Content Formatting
Provide both HTML and text versions for better compatibility:
const message = {
transport: 'smtp',
to: user.email,
subject: 'Notification',
html: '<h1>Hello!</h1><p>This is a <strong>rich</strong> message.</p>',
text: 'Hello!\n\nThis is a rich message.',
};
4. Performance Considerations
For bulk messaging, consider queuing or rate limiting:
// For multiple recipients, consider sending individual messages
// to avoid delivery issues affecting all recipients
for (const recipient of recipients) {
const result = await context.messaging.send({
transport: 'smtp',
to: recipient.email,
subject: `Personal message for ${recipient.name}`,
html: generatePersonalizedContent(recipient),
});
if (!result.success) {
console.warn(`Failed to send to ${recipient.email}: ${result.error}`);
}
}
Future Transports
The Messaging is designed to support additional transports:
- SMS: Text messaging via Twilio, AWS SNS, etc.
- Webhooks: HTTP POST notifications to external systems
- Slack/Teams: Direct integration with chat platforms
- Push Notifications: Mobile and web push notifications
Each transport will follow the same consistent API pattern while providing transport-specific configuration options.