A lightweight SMTP client for Deno. Built with native APIs, zero dependencies, simple setup.
- Installation
- Quick Start
- Configuration
- Basic Usage
- Advanced Features
- API Reference
- Examples
- Troubleshooting
- Contributing
- License
deno install @neabyte/deno-mailerimport mailer from '@neabyte/deno-mailer'
const transporter = mailer.transporter({
host: 'smtp.domain.com',
port: 587,
secure: false,
auth: {
user: '[email protected]',
pass: 'password'
}
})
await transporter.send({
from: '"John Doe" <[email protected]>',
to: '[email protected]',
subject: 'Test Email',
text: 'This is a test email',
html: '<b>This is a test email</b>'
})const config = {
host: 'smtp.gmail.com', // SMTP server hostname
port: 587, // SMTP server port
secure: false, // Use TLS (true for port 465, false for 587)
auth: {
user: '[email protected]',
pass: 'your-app-password'
}
}Deno-Mailer supports both LOGIN and PLAIN authentication methods:
// Basic authentication
auth: {
user: 'username',
pass: 'password'
}
// No authentication (for local SMTP servers)
// Simply omit the auth property// Port 587 with STARTTLS (recommended)
{
host: 'smtp.gmail.com',
port: 587,
secure: false // Will upgrade to TLS via STARTTLS
}
// Port 465 with direct TLS
{
host: 'smtp.gmail.com',
port: 465,
secure: true // Direct TLS connection
}await transporter.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Hello World',
text: 'This is a plain text email'
})await transporter.send({
from: '[email protected]',
to: '[email protected]',
subject: 'HTML Email',
html: '<h1>Hello!</h1><p>This is an <strong>HTML</strong> email.</p>'
})await transporter.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Mixed Content',
text: 'This is the plain text version',
html: '<h1>This is the HTML version</h1>'
})await transporter.send({
from: '[email protected]',
to: ['[email protected]', '[email protected]'],
cc: '[email protected]',
bcc: '[email protected]',
replyTo: '[email protected]',
subject: 'Email to Multiple Recipients',
text: 'This email goes to multiple people'
})// Mixed recipient formats
await transporter.send({
from: { name: 'John Doe', address: '[email protected]' },
to: [
'[email protected]',
{ name: 'Jane Smith', address: '[email protected]' },
'"Display Name" <[email protected]>'
],
cc: [
'[email protected]',
{ name: 'Team Lead', address: '[email protected]' }
],
bcc: '[email protected]',
replyTo: { name: 'Support Team', address: '[email protected]' },
subject: 'Advanced Recipient Formats',
text: 'Supports various recipient formats'
})// Single attachment
await transporter.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Email with Attachment',
text: 'Check the attached file',
attachments: [{
filename: 'document.pdf',
content: fileContent, // Uint8Array or base64 string
contentType: 'application/pdf',
encoding: 'base64' // 'base64', '7bit', or 'quoted-printable'
}]
})
// Multiple attachments with different encodings
await transporter.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Multiple Attachments',
text: 'Check the attached files',
attachments: [
{
filename: 'document.pdf',
content: pdfData,
contentType: 'application/pdf',
encoding: 'base64'
},
{
filename: 'image.jpg',
content: imgData,
contentType: 'image/jpeg',
encoding: 'base64'
},
{
filename: 'readme.txt',
content: 'Plain text content',
contentType: 'text/plain',
encoding: '7bit'
}
]
})await transporter.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Email with Image',
html: '<h1>Hello!</h1><img src="cid:logo">',
embeddedImages: [{
filename: 'logo.png',
content: imageContent,
contentType: 'image/png',
cid: '<[email protected]>',
disposition: 'inline' // 'inline' or 'attachment'
}]
})// Basic calendar event
await transporter.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Meeting Invitation',
text: 'You are invited to a meeting',
calendarEvent: {
uid: 'meeting-123',
summary: 'Team Meeting',
description: 'Weekly team sync',
location: 'Conference Room A',
startTime: '2024-01-15T10:00:00Z',
endTime: '2024-01-15T11:00:00Z',
organizer: '[email protected]',
attendees: ['[email protected]', '[email protected]']
}
})
// Complete calendar event with all options
await transporter.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Important Meeting',
text: 'Please attend this important meeting',
html: '<h1>Important Meeting</h1><p>Please attend this meeting.</p>',
calendarEvent: {
uid: 'important-meeting-456',
summary: 'Quarterly Review',
description: 'Q4 performance review and planning for next quarter',
location: 'Main Conference Room, Building A',
startTime: '2024-01-20T14:00:00Z',
endTime: '2024-01-20T16:00:00Z',
organizer: '[email protected]',
attendees: [
'[email protected]',
'[email protected]',
'[email protected]'
],
status: 'CONFIRMED'
}
})await transporter.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Custom Headers',
text: 'Email with custom headers',
headers: {
'X-Priority': '1',
'X-Custom-Header': 'Custom Value'
}
})| Method | Description | Parameters | Returns |
|---|---|---|---|
mailer.transporter(config) |
Creates email transporter | SmtpConnectionConfig |
EmailSender |
transporter.send(message) |
Sends email message | EmailMessage |
Promise<void> |
| Option | Type | Required | Description | Example |
|---|---|---|---|---|
host |
string | ✅ | SMTP server hostname | 'smtp.gmail.com' |
port |
number | ✅ | SMTP server port | 587, 465, 25 |
secure |
boolean | ❌ | Use TLS connection | true (port 465), false (port 587) |
auth.user |
string | ❌ | SMTP username | '[email protected]' |
auth.pass |
string | ❌ | SMTP password | 'your-password' |
| Property | Type | Required | Description | Examples |
|---|---|---|---|---|
from |
string/object | ✅ | Sender email address | '[email protected]', {name: 'John', address: '[email protected]'} |
to |
string/array | ✅ | Recipient email address(es) | '[email protected]', ['[email protected]', '[email protected]'] |
subject |
string | ✅ | Email subject line | 'Hello World' |
text |
string | ❌ | Plain text content | 'This is plain text' |
html |
string | ❌ | HTML content | '<h1>Hello</h1>' |
cc |
string/array | ❌ | Carbon copy recipients | '[email protected]' |
bcc |
string/array | ❌ | Blind carbon copy recipients | '[email protected]' |
replyTo |
string/object | ❌ | Reply-to address | '[email protected]' |
attachments |
array | ❌ | File attachments | [{filename: 'file.pdf', content: data}] |
embeddedImages |
array | ❌ | Embedded images | [{filename: 'img.png', content: data, cid: '<[email protected]>'}] |
calendarEvent |
object | ❌ | Calendar invitation | {uid: 'event-123', summary: 'Meeting', startTime: '2024-01-01T10:00:00Z'} |
headers |
object | ❌ | Custom email headers | {'X-Priority': '1'} |
try {
await transporter.send(message)
} catch (error) {
console.error('Email failed:', error.message)
// Handle specific error types
if (error.message.includes('authentication')) {
// Handle auth errors
} else if (error.message.includes('connection')) {
// Handle connection errors
}
}const transporter = mailer.transporter({
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: '[email protected]',
pass: 'your-app-password' // Use App Password, not regular password
}
})const transporter = mailer.transporter({
host: 'smtp-mail.outlook.com',
port: 587,
secure: false,
auth: {
user: '[email protected]',
pass: 'your-password'
}
})const transporter = mailer.transporter({
host: 'mail.yourcompany.com',
port: 587,
secure: false,
auth: {
user: '[email protected]',
pass: 'your-password'
}
})Authentication Failed
- Verify username/password are correct
- For Gmail, use App Passwords instead of regular passwords
- Check if 2FA is enabled and use App Password
Connection Timeout
- Verify SMTP server hostname and port
- Check firewall settings
- Try different ports (587, 465, 25)
TLS Errors
- Ensure
secure: falsefor port 587 (STARTTLS) - Use
secure: truefor port 465 (direct TLS) - Check server TLS certificate
// Add error logging
try {
await transporter.send(message)
console.log('Email sent successfully')
} catch (error) {
console.error('SMTP Error:', error.message)
}Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT license. See the LICENSE file for more info.