SMTP Server
Send emails through Unsent using SMTP - the universal email protocol supported by all major email libraries and frameworks
Unsent provides a fully-featured SMTP server that allows you to send emails using the standard SMTP protocol. This is perfect for integrating with existing applications, legacy systems, or any email library that supports SMTP.
Why Use SMTP?
Universal Compatibility
Works with any programming language or framework that supports SMTP - no SDK required.
Drop-in Replacement
Migrate from other email services by simply changing your SMTP credentials.
Legacy System Support
Integrate with older applications that only support email via SMTP.
Enterprise Security
Full TLS/SSL support with secure authentication using your API key.
Features
Unsent's SMTP server provides comprehensive email sending capabilities:
- Standard SMTP Protocol: Full RFC 5321 compliance
- Multiple Security Options: STARTTLS on ports 587/2587 and implicit SSL/TLS on ports 465/2465
- Authentication: Secure auth using your Unsent API key
- Multipart Messages: Send HTML and plain text versions in one email
- Custom Headers: Add custom email headers including Reply-To
- Large Message Support: Up to 10MB per email
- Reliable Delivery: Built on Unsent's proven email infrastructure
Prerequisites
Before you begin, ensure you have:
- Unsent Account: Sign up at unsent.dev
- API Key: Generate one in your Unsent dashboard
- Verified Domain: Set up in the Domains section
SMTP Connection Details
Configure your SMTP client with these settings:
| Setting | Value |
|---|---|
| Host | smtp.unsent.dev |
| Ports | 465 (SSL/TLS), 587 (STARTTLS), 2465 (SSL Alternative), 2587 (TLS Alternative) |
| Username | unsent |
| Password | Your Unsent API Key (starts with un_) |
| Authentication | PLAIN or LOGIN |
| Encryption | SSL/TLS (port 465, 2465) or STARTTLS (port 587, 2587) |
Port Selection Guide
Recommended Ports:
- Port 465: Use this for implicit SSL/TLS (most secure, recommended for production)
- Port 587: Use this for STARTTLS (widely supported)
- Ports 2465/2587: Alternative ports if your hosting provider blocks standard SMTP ports
Quick Start Examples
Node.js with Nodemailer
Nodemailer is the most popular email library for Node.js.
npm install nodemailerimport nodemailer from "nodemailer";
// Create reusable transporter
const transporter = nodemailer.createTransport({
host: "smtp.unsent.dev",
port: 465,
secure: true, // true for port 465, false for 587
auth: {
user: "unsent",
pass: process.env.UNSENT_API_KEY, // Your API key
},
});
// Send email
async function sendEmail() {
const info = await transporter.sendMail({
from: '"Your Name" <hello@yourdomain.com>',
to: "recipient@example.com",
subject: "Welcome to Unsent",
text: "Hello! This email was sent via Unsent SMTP.",
html: "<h1>Hello!</h1><p>This email was sent via Unsent SMTP.</p>",
});
console.log("Message sent:", info.messageId);
}
sendEmail().catch(console.error);Python with smtplib
Python's built-in smtplib module provides SMTP support.
import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# SMTP configuration
smtp_host = "smtp.unsent.dev"
smtp_port = 465
smtp_user = "unsent"
smtp_password = os.getenv("UNSENT_API_KEY")
# Create message
message = MIMEMultipart("alternative")
message["Subject"] = "Welcome to Unsent"
message["From"] = "hello@yourdomain.com"
message["To"] = "recipient@example.com"
# Add text and HTML parts
text_part = MIMEText("Hello! This email was sent via Unsent SMTP.", "plain")
html_part = MIMEText("<h1>Hello!</h1><p>This email was sent via Unsent SMTP.</p>", "html")
message.attach(text_part)
message.attach(html_part)
# Send email
with smtplib.SMTP_SSL(smtp_host, smtp_port) as server:
server.login(smtp_user, smtp_password)
server.send_message(message)
print("Email sent successfully!")PHP with PHPMailer
composer require phpmailer/phpmailer<?php
require 'vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$mail = new PHPMailer(true);
try {
// Server settings
$mail->isSMTP();
$mail->Host = 'smtp.unsent.dev';
$mail->SMTPAuth = true;
$mail->Username = 'unsent';
$mail->Password = getenv('UNSENT_API_KEY');
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = 465;
// Recipients
$mail->setFrom('hello@yourdomain.com', 'Your Name');
$mail->addAddress('recipient@example.com');
// Content
$mail->isHTML(true);
$mail->Subject = 'Welcome to Unsent';
$mail->Body = '<h1>Hello!</h1><p>This email was sent via Unsent SMTP.</p>';
$mail->AltBody = 'Hello! This email was sent via Unsent SMTP.';
$mail->send();
echo 'Email sent successfully!';
} catch (Exception $e) {
echo "Error: {$mail->ErrorInfo}";
}
?>Framework Integrations
Next.js
Create an API route to send emails:
import { NextResponse } from "next/server";
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({
host: "smtp.unsent.dev",
port: 465,
secure: true,
auth: {
user: "unsent",
pass: process.env.UNSENT_API_KEY!,
},
});
export async function POST(request: Request) {
const { to, subject, html, text } = await request.json();
try {
const info = await transporter.sendMail({
from: process.env.FROM_EMAIL,
to,
subject,
html,
text,
});
return NextResponse.json({
success: true,
messageId: info.messageId
});
} catch (error) {
console.error("Email error:", error);
return NextResponse.json(
{ success: false, error: "Failed to send email" },
{ status: 500 }
);
}
}Laravel
Update your .env file:
MAIL_MAILER=smtp
MAIL_HOST=smtp.unsent.dev
MAIL_PORT=465
MAIL_USERNAME=unsent
MAIL_PASSWORD=your_unsent_api_key
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=hello@yourdomain.com
MAIL_FROM_NAME="Your App"Create a Mailable:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class WelcomeEmail extends Mailable
{
use Queueable, SerializesModels;
public function __construct(public $user) {}
public function build()
{
return $this->subject('Welcome to Our Platform')
->view('emails.welcome');
}
}Send the email:
use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;
Mail::to($user->email)->send(new WelcomeEmail($user));Flask (Python)
pip install Flask-Mailfrom flask import Flask
from flask_mail import Mail, Message
import os
app = Flask(__name__)
# Configure Flask-Mail
app.config['MAIL_SERVER'] = 'smtp.unsent.dev'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = 'unsent'
app.config['MAIL_PASSWORD'] = os.getenv('UNSENT_API_KEY')
app.config['MAIL_DEFAULT_SENDER'] = 'hello@yourdomain.com'
mail = Mail(app)
@app.route('/send-email')
def send_email():
msg = Message(
subject="Welcome to Our Platform",
recipients=["recipient@example.com"],
html="<h1>Hello!</h1><p>Welcome aboard!</p>",
body="Hello! Welcome aboard!"
)
mail.send(msg)
return {"success": True}Ruby on Rails
Configure Action Mailer in config/environments/production.rb:
Rails.application.configure do
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.unsent.dev',
port: 465,
user_name: 'unsent',
password: ENV['UNSENT_API_KEY'],
authentication: 'plain',
enable_starttls_auto: true,
ssl: true
}
config.action_mailer.default_url_options = { host: 'yourdomain.com' }
endCreate a mailer:
class UserMailer < ApplicationMailer
default from: 'hello@yourdomain.com'
def welcome_email(user)
@user = user
mail(to: @user.email, subject: 'Welcome to Our Platform')
end
endGo
package main
import (
"crypto/tls"
"fmt"
"net/smtp"
"os"
)
func sendEmail(to, subject, body string) error {
from := "hello@yourdomain.com"
password := os.Getenv("UNSENT_API_KEY")
// Setup message
msg := []byte("To: " + to + "\r\n" +
"From: " + from + "\r\n" +
"Subject: " + subject + "\r\n" +
"Content-Type: text/html; charset=UTF-8\r\n" +
"\r\n" + body + "\r\n")
// SMTP auth
auth := smtp.PlainAuth("", "unsent", password, "smtp.unsent.dev")
// TLS config
tlsConfig := &tls.Config{
ServerName: "smtp.unsent.dev",
}
// Connect to server
conn, err := tls.Dial("tcp", "smtp.unsent.dev:465", tlsConfig)
if err != nil {
return err
}
defer conn.Close()
client, err := smtp.NewClient(conn, "smtp.unsent.dev")
if err != nil {
return err
}
defer client.Quit()
// Authenticate
if err := client.Auth(auth); err != nil {
return err
}
// Send email
if err := client.Mail(from); err != nil {
return err
}
if err := client.Rcpt(to); err != nil {
return err
}
w, err := client.Data()
if err != nil {
return err
}
_, err = w.Write(msg)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
fmt.Println("Email sent successfully!")
return nil
}
func main() {
err := sendEmail(
"recipient@example.com",
"Welcome to Unsent",
"<h1>Hello!</h1><p>Welcome aboard!</p>",
)
if err != nil {
fmt.Printf("Error: %v\n", err)
}
}Advanced Usage
Sending with Custom Headers
Add custom headers like Reply-To, CC, BCC:
await transporter.sendMail({
from: '"Your Company" <hello@yourdomain.com>',
to: "recipient@example.com",
cc: "manager@yourdomain.com",
bcc: "archive@yourdomain.com",
replyTo: "support@yourdomain.com",
subject: "Your Order Confirmation",
html: "<h1>Order Confirmed</h1>",
text: "Order Confirmed",
headers: {
'X-Custom-Header': 'CustomValue',
'X-Priority': '1',
},
});Sending to Multiple Recipients
// Multiple recipients as comma-separated string
await transporter.sendMail({
from: "hello@yourdomain.com",
to: "user1@example.com, user2@example.com, user3@example.com",
subject: "Team Update",
html: "<p>Hello team!</p>",
});
// Or as an array
await transporter.sendMail({
from: "hello@yourdomain.com",
to: ["user1@example.com", "user2@example.com"],
subject: "Team Update",
html: "<p>Hello team!</p>",
});HTML Emails with Inline Images
await transporter.sendMail({
from: "hello@yourdomain.com",
to: "recipient@example.com",
subject: "Welcome!",
html: `
<html>
<body>
<h1>Welcome to Unsent!</h1>
<img src="cid:logo" alt="Logo" />
<p>We're glad to have you.</p>
</body>
</html>
`,
attachments: [{
filename: 'logo.png',
path: '/path/to/logo.png',
cid: 'logo' // Same as referenced in img src
}]
});Using Templates
Combine SMTP with your favorite templating engine:
import Handlebars from "handlebars";
import fs from "fs";
// Load and compile template
const templateSource = fs.readFileSync("./templates/welcome.hbs", "utf8");
const template = Handlebars.compile(templateSource);
// Render with data
const html = template({
name: "John Doe",
activationLink: "https://yourapp.com/activate/abc123"
});
// Send
await transporter.sendMail({
from: "hello@yourdomain.com",
to: "john@example.com",
subject: "Activate Your Account",
html,
});Testing Your Integration
1. Send a Test Email
Use your configured SMTP client to send a test email to yourself.
2. Verify in Dashboard
Check the Unsent dashboard to confirm the email was received and processed.
3. Monitor Delivery
Track delivery status, opens, and clicks in real-time through the dashboard.
Command-Line Testing with swaks
For quick testing, use swaks:
swaks --to recipient@example.com \
--from hello@yourdomain.com \
--server smtp.unsent.dev \
--port 465 \
--auth LOGIN \
--auth-user unsent \
--auth-password your_api_key \
--tlsImportant: Your sending domain must be verified in the Unsent dashboard before you can send emails. Unverified domains will result in failed deliveries.
Security Best Practices
1. Protect Your API Key
- Never commit API keys to version control
- Use environment variables to store credentials
- Rotate keys regularly in the dashboard
UNSENT_API_KEY=un_your_secret_key_here
FROM_EMAIL=hello@yourdomain.com2. Use TLS/SSL
Always use encrypted connections:
- ✅ Port 465 with SSL/TLS (secure from start)
- ✅ Port 587 with STARTTLS (upgrade to secure)
- ❌ Never send credentials over unencrypted connections
3. Verify Sender Domains
Only send from verified domains to ensure deliverability and prevent spoofing.
4. Implement Rate Limiting
Implement client-side rate limiting to stay within your plan limits and avoid overwhelming recipients.
Troubleshooting
Authentication Failed
Symptoms: 535 Authentication failed or similar error
Solutions:
- Verify you're using
unsentas the username (not your email address) - Ensure your API key is correct and hasn't been revoked
- Check for extra whitespace in your credentials
- Confirm your API key is active in the dashboard
Connection Timeout or Refused
Symptoms: ETIMEDOUT or ECONNREFUSED
Solutions:
- Check if your hosting provider blocks SMTP ports (try alternative ports 2465/2587)
- Verify firewall settings allow outbound SMTP connections
- Test connectivity:
telnet smtp.unsent.dev 465 - Try a different port (587 with STARTTLS)
TLS/SSL Errors
Symptoms: SSL routines or certificate errors
Solutions:
- Ensure your SMTP library supports TLS/SSL
- Update SSL libraries to the latest version
- For port 465, enable
secure: truein your configuration - For port 587, enable STARTTLS
Emails Not Delivering
Symptoms: Email sent successfully but not delivered
Solutions:
- Verify your sending domain in the Unsent dashboard
- Ensure the "from" address matches your verified domain
- Check the email logs in the dashboard for specific errors
- Review spam folder in recipient's inbox
- Verify you haven't exceeded your plan limits
"Must issue STARTTLS command first"
Symptoms: Authentication rejected on port 587
Solutions:
- Enable STARTTLS in your SMTP client configuration
- Or switch to port 465 with implicit SSL/TLS
Large Email Rejected
Symptoms: 552 Message size exceeds maximum
Solutions:
- Reduce email size (current limit: 10MB)
- Compress or resize images
- Host large files externally and link to them
- Consider splitting into multiple emails
Monitoring and Analytics
Email Dashboard
Monitor all SMTP-sent emails in your Unsent dashboard:
- Real-time delivery status
- Bounce and complaint tracking
- Open and click analytics
- Detailed error logs
Email Events
Track email lifecycle events:
- Queued: Email accepted by SMTP server
- Sent: Successfully delivered to recipient's mail server
- Delivered: Confirmed delivery
- Bounced: Delivery failed (see reason in logs)
- Opened: Recipient opened the email (if tracking enabled)
- Clicked: Recipient clicked a link
API Access
Retrieve email data programmatically using the Unsent REST API:
curl https://api.unsent.dev/v1/emails \
-H "Authorization: Bearer YOUR_API_KEY"Migration Guide
From SendGrid
Replace SendGrid SMTP credentials:
- host: "smtp.sendgrid.net"
+ host: "smtp.unsent.dev"
- port: 587
+ port: 465
- user: "apikey"
+ user: "unsent"
- pass: "SG.xxx"
+ pass: "un_xxx"
+ secure: trueFrom Mailgun
Replace Mailgun SMTP credentials:
- host: "smtp.mailgun.org"
+ host: "smtp.unsent.dev"
- port: 587
+ port: 465
- user: "postmaster@your-domain.mailgun.org"
+ user: "unsent"
- pass: "mailgun-password"
+ pass: "un_xxx"
+ secure: trueFrom AWS SES
Replace AWS SES SMTP credentials:
- host: "email-smtp.us-east-1.amazonaws.com"
+ host: "smtp.unsent.dev"
- port: 587
+ port: 465
- user: "AKIAIOSFODNN7EXAMPLE"
+ user: "unsent"
- pass: "aws-ses-smtp-password"
+ pass: "un_xxx"
+ secure: trueAfter migration, verify your domain in the Unsent dashboard and update any hardcoded email addresses to use your verified domain.
Need Help?
Pro Tip: For maximum deliverability, combine SMTP with proper email authentication (SPF, DKIM, DMARC) and maintain a good sender reputation.