/documentation

Point, authenticate, send.

justsmtp is a drop-in SMTP relay in front of Amazon SES. Point your existing mailer at smtp.justsmtp.com, authenticate with a credential pair generated in the dashboard, and send. No AWS account, no IAM policies.

  1. Add your domain and publish the DNS records we show you — three DKIM CNAMEs.
  2. Generate an SMTP credential. The password is shown once, so put it in your secrets manager as you copy it.
  3. Point your mail config at smtp.justsmtp.com:587 and send.

Connection settings

These don't change — safe to hard-code or drop straight into an env file.

settingvaluenotes
hostsmtp.justsmtp.comnearest region answers
port587STARTTLS required
fallback port2525if your host blocks 587 outbound
auth mechanismsAUTH LOGIN, AUTH PLAINonly after STARTTLS
username / passwordjustsmtp_******from Credentials, shown once at creation
from addressanything@your-verified-domainthe domain must be verified

Port 25 is not offered. It is for server-to-server relay and is blocked outbound from practically every application host anyway.

How it works

01

Your application connects to smtp.justsmtp.com over STARTTLS and authenticates with the username and password from a credential pair.

02

We accept the message over SMTP, check the sending domain is one you have verified, and hand it off to Amazon SES for delivery.

03

Every attempt — sent, deferred, bounced, dropped — lands in your activity log with the real upstream SMTP response. We don't retain message bodies; the log keeps metadata and the subject line only.

your app ──SMTP──▶ smtp.justsmtp.com ──▶ Amazon SES ──▶ recipient
                        │                     │
                        └── quota, auth       └── events ──▶ activity log

Integrations

justsmtp works with any SMTP client. Swap the host, port and credentials into your existing mailer — nothing else changes.

Node.js nodemailer
// npm install nodemailer
import nodemailer from 'nodemailer';

const transport = nodemailer.createTransport({
  host: 'smtp.justsmtp.com',
  port: 587,
  secure: false,
  auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
});

await transport.sendMail({
  from: '"Acme" <hello@mail.acme.io>',
  to: 'sarah@example.com',
  subject: 'Welcome to Acme',
  html: '<b>You are in.</b>',
});
Python smtplib — stdlib, no install
import os, smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg["From"] = "Acme <hello@mail.acme.io>"
msg["To"] = "sarah@example.com"
msg["Subject"] = "Welcome to Acme"
msg.set_content("You are in.")

with smtplib.SMTP("smtp.justsmtp.com", 587) as server:
    server.starttls()
    server.login(os.environ["SMTP_USER"], os.environ["SMTP_PASS"])
    server.send_message(msg)
Ruby mail
# gem install mail
require 'mail'

Mail.defaults do
  delivery_method :smtp, {
    address:              'smtp.justsmtp.com',
    port:                 587,
    user_name:            ENV['SMTP_USER'],
    password:             ENV['SMTP_PASS'],
    authentication:       :plain,
    enable_starttls_auto: true,
  }
end

Mail.deliver do
  from    'hello@mail.acme.io'
  to      'sarah@example.com'
  subject 'Welcome to Acme'
  body    'You are in.'
end
PHP symfony/mailer
// composer require symfony/mailer
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mime\Email;

$transport = Transport::fromDsn(
  'smtp://'.getenv('SMTP_USER').':'.getenv('SMTP_PASS').'@smtp.justsmtp.com:587'
);
$mailer = new Mailer($transport);

$mailer->send((new Email())
  ->from('hello@mail.acme.io')
  ->to('sarah@example.com')
  ->subject('Welcome to Acme')
  ->html('<b>You are in.</b>'));

Using something else? If it has a host field and a port field, it already works. help@justsmtp.com if it does not.

HTML forms

A contact form on a static site with no backend of yours and no JavaScript. Paste the snippet, and a visitor's submission arrives as email from your own verified domain, with their address as the reply-to. It counts as one message against your plan and lands in your activity log like any other send.

Bots find public form actions within hours, so the defence is on by default: a signed token, a beacon that measures how long the form was open, two hidden decoy fields, and rate limits. A dropped submission gets exactly the answer a real one gets — the counters on the form's page are where you see what happened.

HTML copy it whole — every line does something
<form method="POST" action="https://api.justsmtp.com/f/PUBLIC_ID" accept-charset="UTF-8">
  <input type="hidden" name="_ftk" value="TOKEN">
  <img src="https://api.justsmtp.com/f/PUBLIC_ID/start" width="1" height="1" alt="" class="jsf-hp">
  <input type="text" name="company" tabindex="-1" autocomplete="off" aria-hidden="true" class="jsf-hp">
  <input type="text" name="website" tabindex="-1" autocomplete="off" aria-hidden="true" class="jsf-hp">
  <label>Name <input type="text" name="name" required></label>
  <label>Email <input type="email" name="email" required></label>
  <label>Message <textarea name="message" required></textarea></label>
  <button type="submit">Send</button>
</form>
<style>.jsf-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}</style>
bound or limitvaluenotes
forms per account1 / 5 / 25hobby / starter / pro
submissions per form per day50 / 250 / 1,000on top of your monthly quota, so a flood cannot spend it
fields per submission5064 values each, 10,000 characters per value, 64-character names
request body128 KBover a bound is a 400; file parts are refused
per visitor, per form4 / 10 min30 per form per hour, 10 per destination address per hour
success303 or 200redirect to your URL if set, else a thank-you page; {"ok":true} with Accept: application/json

A field named email becomes the reply-to. Nothing a visitor typed is stored on our side — the email is the record. Create a form, copy its snippet and read its counters on Forms.