Amazon Simple Email Service (SES) SMTP lets you send email through AWS’s mail infrastructure using standard SMTP credentials. The server address varies by AWS region — for example, email-smtp.us-east-1.amazonaws.com for US East (N. Virginia). It uses port 587 with STARTTLS or port 465 with SSL. Authentication uses SES-specific SMTP credentials that you generate from an IAM user — not your AWS console login or access keys. New accounts start in sandbox mode, which limits who you can send to. This guide covers the full setup: SMTP credentials, sandbox exit, and working code in PHP, Python, and Node.js.
:::note[TL;DR]
- SMTP server:
email-smtp.[region].amazonaws.com(e.g.email-smtp.us-east-1.amazonaws.com) - Port 587 (STARTTLS) or 465 (SSL)
- Credentials: SES SMTP username/password — generated from IAM, not your AWS keys
- New accounts: sandbox mode limits sending to verified addresses only
- Cost: $0.10 per 1,000 emails; 62,000/month free if sending from EC2 :::
What are the Amazon SES SMTP server settings?
The server address depends on your AWS region. Use the region where you’ve configured SES:
| Region | SMTP Server |
|---|---|
| US East (N. Virginia) | email-smtp.us-east-1.amazonaws.com |
| US West (Oregon) | email-smtp.us-west-2.amazonaws.com |
| EU (Ireland) | email-smtp.eu-west-1.amazonaws.com |
| EU (Frankfurt) | email-smtp.eu-central-1.amazonaws.com |
| AP (Mumbai) | email-smtp.ap-south-1.amazonaws.com |
| AP (Singapore) | email-smtp.ap-southeast-1.amazonaws.com |
| AP (Sydney) | email-smtp.ap-southeast-2.amazonaws.com |
Full list of supported regions in the AWS SES documentation.
Port settings (same for all regions):
| Setting | Value |
|---|---|
| Port (STARTTLS) | 587 |
| Port (SSL/TLS) | 465 |
| Encryption | STARTTLS (recommended) |
| Authentication | Required |
| Username | SES SMTP username (from IAM) |
| Password | SES SMTP password (from IAM) |
:::warning Your AWS access key ID and secret access key are not the SMTP credentials. You must generate dedicated SMTP credentials from the SES console or IAM. Using raw AWS credentials for SMTP will fail. :::
How do I generate Amazon SES SMTP credentials?
SES SMTP credentials are derived from an IAM user. There are two ways to create them.
Method 1 — From the SES Console (easiest):
- Go to the Amazon SES console
- In the left sidebar, click SMTP Settings
- Click Create SMTP Credentials
- IAM auto-creates a user named something like
ses-smtp-user.20260324-xxxxxx - Download or copy the credentials — SMTP Username and SMTP Password
That’s it. The credentials are shown only once. Store them immediately.
Method 2 — From an existing IAM user:
If you already have an IAM user with ses:SendRawEmail permission, you can generate SMTP credentials from their access key:
# AWS CLI — convert an IAM access key to SES SMTP credentials
python3 -c "
import hmac, hashlib, base64
AWS_SECRET_KEY = 'YOUR_IAM_SECRET_ACCESS_KEY'
DATE = '11111111'
SERVICE = 'ses'
REGION = 'us-east-1'
TERMINAL = 'aws4_request'
MESSAGE = 'SendRawEmail'
VERSION = 0x04
def sign(key, msg):
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
signature = sign(sign(sign(sign(sign(
('AWS4' + AWS_SECRET_KEY).encode('utf-8'),
DATE), SERVICE), REGION), TERMINAL), MESSAGE)
credentials = base64.b64encode(bytes([VERSION]) + signature).decode('utf-8')
print('SMTP Password:', credentials)
"
The SMTP username for Method 2 is the IAM user’s access key ID. This approach is useful when you need to rotate credentials programmatically.
The Scenario: You’re migrating a legacy PHP app from shared hosting to EC2. The old app used Gmail SMTP and hit the 500/day limit constantly. You switch to SES, and the first time you test, all the emails are failing. You’re 100% sure the credentials are right. Then you realize you pasted the IAM access key into the SMTP password field instead of running the conversion. SES SMTP credentials are not the same as IAM keys.
What is SES Sandbox Mode and how do I get out of it?
Every new AWS account starts in SES sandbox mode. In sandbox mode:
- You can only send emails to verified email addresses or domains
- Sending to any unverified address is rejected
- Daily sending quota is 200 messages/day, with a max rate of 1 per second
Sandbox is fine for development. For production, you need to request production access.
How to exit sandbox mode:
- In the SES console, click Account Dashboard
- Under “Sending limits”, click Request production access
- Fill in the request form — describe your use case, estimated volume, how you handle bounces and complaints
- AWS typically responds within 24–48 hours
Be honest and specific. Vague requests like “I want to send marketing emails” get rejected or delayed. “Transactional emails for account notifications from a SaaS application, expected volume 500/day, bounce handling via SES SNS notifications” gets approved.
How do I verify a sender identity in SES?
Before you can send any email (even in sandbox), the From address or domain must be verified.
Verify a single email address:
- SES console → Verified Identities → Create Identity
- Choose “Email address”, enter the address, click Create
- Click the verification link in the email that arrives
Verify a domain (recommended for production):
- SES console → Verified Identities → Create Identity
- Choose “Domain”, enter your domain
- Add the DKIM DNS records SES provides to your domain’s DNS
- Wait for propagation (usually 15–30 minutes), then verify
Domain verification enables DKIM signing and allows you to send from any address at that domain without individual verification.
How do I send email via Amazon SES SMTP in code?
PHP with PHPMailer
composer require phpmailer/phpmailer
<?php
use PHPMailer\PHPMailer\PHPMailer;
require 'vendor/autoload.php';
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'email-smtp.us-east-1.amazonaws.com'; // Your SES region
$mail->SMTPAuth = true;
$mail->Username = 'AKIAIOSFODNN7EXAMPLE'; // SES SMTP username (from IAM)
$mail->Password = 'wJalrXUtnFEMI/K7MDENG/SMTPPASSWORD'; // SES SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom('you@yourdomain.com', 'Your Name'); // Verified sender
$mail->addAddress('recipient@example.com');
$mail->Subject = 'Test via Amazon SES SMTP';
$mail->Body = 'Sent through Amazon SES SMTP with PHPMailer.';
$mail->send();
echo 'Message sent.';
Python with smtplib
import smtplib
from email.mime.text import MIMEText
smtp_server = "email-smtp.us-east-1.amazonaws.com" # Your SES region
port = 587
username = "AKIAIOSFODNN7EXAMPLE" # SES SMTP username
password = "wJalrXUtnFEMI/K7MDENG/SMTPPASSWORD" # SES SMTP password
msg = MIMEText("Sent through Amazon SES SMTP.")
msg["Subject"] = "Test via Amazon SES SMTP"
msg["From"] = "you@yourdomain.com" # Verified sender or domain
msg["To"] = "recipient@example.com"
with smtplib.SMTP(smtp_server, port) as server:
server.ehlo()
server.starttls()
server.login(username, password)
server.sendmail("you@yourdomain.com", "recipient@example.com", msg.as_string())
print("Email sent.")
Node.js with Nodemailer
npm install nodemailer
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
host: "email-smtp.us-east-1.amazonaws.com", // Your SES region
port: 587,
secure: false, // STARTTLS
auth: {
user: "AKIAIOSFODNN7EXAMPLE", // SES SMTP username
pass: "wJalrXUtnFEMI/K7MDENG/SMTPPASSWORD", // SES SMTP password
},
});
async function sendMail() {
await transporter.sendMail({
from: '"Your Name" <you@yourdomain.com>', // Verified sender
to: "recipient@example.com",
subject: "Test via Amazon SES SMTP",
text: "Sent through Amazon SES SMTP with Nodemailer.",
});
console.log("Email sent.");
}
sendMail().catch(console.error);
What does Amazon SES cost?
| Context | Price |
|---|---|
| Sending from EC2 / Lambda | 62,000 emails/month free, then $0.10/1,000 |
| Sending from outside AWS | $0.10 per 1,000 emails (no free tier) |
| Attachments | $0.12 per GB of attachments |
At $0.10/1,000 emails, SES is among the cheapest transactional email options available. For an app that sends 100,000 emails/month, that’s $10. SendGrid SMTP at that volume would cost $15–$20/month. The math gets more favorable for SES the higher your volume.
Common Amazon SES SMTP errors and how to fix them
454 Throttling failure: Maximum sending rate exceeded You’ve hit your per-second sending rate limit (starts at 1 email/second in sandbox, increases after production access). Add delays between sends or use the SES Sending Queue.
535 Authentication Credentials Invalid You’re using IAM access keys instead of SES SMTP credentials, or the SES SMTP credentials were created in a different region. Regenerate credentials from the correct region’s SES console.
554 Message rejected: Email address is not verified You’re in sandbox mode and the recipient address isn’t verified, or the sender isn’t verified. Either verify the address or exit sandbox mode.
Connection refused / timeout Make sure your EC2 security group allows outbound on port 587. AWS previously blocked port 25 by default; port 587 should be open, but verify in your security group rules.
FAQ
Do I need an IAM user dedicated to SES SMTP?
Best practice, yes. Create a minimal IAM user with only ses:SendRawEmail permission, generate SMTP credentials from it, and don’t use it for anything else. This limits the blast radius if the credentials are ever compromised.
Can I use Amazon SES SMTP from outside AWS?
Yes, but the free tier only applies when sending from EC2. From your laptop, a non-AWS server, or shared hosting, you pay $0.10/1,000 from the first email. The pricing is still very competitive.
What’s the difference between SES SMTP and the SES API (SDK)?
Both send the same email through SES infrastructure. The AWS SDK (Boto3 for Python, AWS SDK for Node.js, etc.) uses the SES HTTP API and supports additional features like bulk sending, event publishing to SNS, and suppression list management. SMTP integration is simpler for apps that already support SMTP configuration.
How long does it take to get out of SES sandbox?
Usually 24–48 hours after submitting the production access request. AWS reviews requests manually. Having clear, specific answers in the request form speeds things up.
Does SES support DKIM and SPF automatically?
DKIM: Yes, when you verify a domain (not just a single email address), SES provides DKIM DNS records to add. Once active, all outgoing email from that domain is DKIM-signed automatically. SPF: you’ll need to add SES to your domain’s SPF record manually (e.g. include:amazonses.com).
What to Read Next
- How to Use SendGrid SMTP Server for Sending Email — easier initial setup; better free tier for non-AWS apps
- How to Use Mailgun SMTP Server for Sending Email — good sandbox environment for development testing
- How to Use Gmail SMTP Server for Sending Email — for simple personal projects without AWS infrastructure