Quick SMTP Setup: From DNS to First Email in 10 Minutes | Brixus365 Blog
Back to Blog
Guides12 min read

Quick SMTP Setup: From DNS to First Email in 10 Minutes

A hands-on walkthrough of SMTP integration for Django, Rails, Node.js, and more — covering DNS records, credentials, code examples in four languages, common error codes, and production readiness.

Brixus365 TeamReviewed and edited by the Brixus365 team
On this page · 11

If your application or framework already speaks SMTP — Django, Rails, Express, WordPress, Postfix as a relay — adding transactional email is usually a 10-minute job. Verify a sending domain, create credentials, plug them into your config, and send a test. That’s it.

This guide is a hands-on walkthrough covering the four steps to a working setup, what each DNS record does, common error codes with their fixes, code examples in four languages, and a production-readiness checklist.

SMTP vs API: When to Use Which

SMTP and REST are two different on-ramps to the same email infrastructure. Each has its niche.

SMTP vs REST API

Choose the right on-ramp for your use case

Use SMTP when…
  • Framework already has SMTP support (Django, Rails, WordPress, Laravel)
  • Integrating a legacy system that does not speak REST
  • System-level relay via Postfix or Sendmail
  • Goal is working email in under 10 minutes
  • Zero new dependencies — just plug in host, port, credentials
Use the REST API when…
  • Need idempotency keys to prevent duplicate sends
  • Want fine-grained webhook-driven event handling
  • Building greenfield — no legacy SMTP baggage
  • Need bulk-batch operations at high volume
  • Want server-side templates referenced by ID
  • Need precise per-service API key scoping

The hybrid case is common. SMTP for legacy flows, REST for new ones. Both share the same verified sending domain, suppression list, and analytics — no parallel infrastructure.

If your goal is “first email in 10 minutes,” SMTP is usually the faster path. The hybrid case is also common — SMTP for the legacy parts of your stack, REST for new transactional flows. Both can run side by side on the same verified sending domain.

The 4-Step Flow

The whole SMTP setup boils down to four steps:

  1. Verify your sending domain — add DNS records so receiving servers trust your emails.
  2. Create SMTP credentials — a username and password from the Brixus365 dashboard.
  3. Configure your application — plug the host, port, and credentials into your framework.
  4. Send a test and check the headers — confirm DKIM, SPF, and DMARC all pass.

SMTP Setup at a Glance

Four steps from zero to authenticated sends

Step 1

Verify Sending Domain

Add SPF, DKIM, and DMARC DNS records at your registrar

~5 min + DNS wait
Step 2

Create SMTP Credentials

Dashboard → Settings → Developer → SMTP Credentials → New

< 1 min
Step 3

Configure Your App

Set SMTP host, port 587, username, and password from env vars

< 2 min
Step 4

Send Test & Verify Headers

Check DKIM, SPF, and DMARC all show "pass" in raw headers

< 1 min

10 min

total setup

587

recommended port

3

auth checks pass

Most of the time is spent waiting for DNS to propagate (typically minutes, occasionally up to an hour). Everything else takes seconds.

Step 1: Verify Your Sending Domain

Before you can send from you@yourdomain.com, you need to prove to the world that you control yourdomain.com. This is done with a few DNS records you add once and then forget.

DNS Records for SMTP

Brixus365 generates all values — just copy and paste into your registrar

RequiredRecommended
SPF1 record
Required

Record Type

TXT

Host / Name

@ (yourdomain.com)

Value

v=spf1 include:spf.brixus365.com -all

Declares which mail servers are authorised to send on behalf of your domain. The -all suffix means hard-fail for any unlisted server.

DKIM2 records
Required

Record Type

CNAME

Host / Name

brixus365._domainkey

Value

brixus365._domainkey.brixus365.com

Delegates DKIM key management to Brixus365 via CNAME. Two records required — the dashboard shows both with copy-to-clipboard buttons.

Domain Verification1 record
Required

Record Type

TXT

Host / Name

_amazonses.yourdomain.com

Value

brixus365-verify=<token>

One-time record that proves domain ownership to the sending infrastructure. Generated automatically by Brixus365.

DMARC
Recommended

Record Type

TXT

Host / Name

_dmarc.yourdomain.com

Value

v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com

Tells receiving servers what to do when SPF or DKIM fails, and enables aggregate reporting. Start with p=none, tighten after 30–60 days.

Tip: Brixus365 generates the exact record values with copy-to-clipboard buttons after you add your domain in Settings → Email Setup.

A note on SPF merging

SPF allows only one TXT record per domain. If you already have an SPF record for Google Workspace, Zoho, or another provider, do not create a second one — merge the includes:

v=spf1 include:_spf.google.com include:spf.brixus365.com -all

DMARC: start at p=none

Even though DMARC is recommended rather than required, set it up from day one. Start permissive:

v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com

p=none means failing mail is still delivered — you are monitoring, not enforcing. After 30–60 days of clean reports, advance to p=quarantine, then p=reject.

Step 2: Create SMTP Credentials

Navigate to Settings → Developer → SMTP Credentials → New Credential in the Brixus365 dashboard.

You will get back four values:

FieldValue
Hostsmtp.brixus365.com
Port587 (STARTTLS) or 465 (Implicit TLS)
UsernameYour domain’s user identifier
PasswordShown once at creation — copy it now

Port 587 vs 465

  • Port 587 (STARTTLS): the modern standard. The connection starts unencrypted, then upgrades to TLS. Most libraries default here.
  • Port 465 (Implicit TLS): TLS from the first byte. Older standard, still widely supported.

Use port 587 for new setups. If your library only supports 465, that is also fine — both ports terminate at the same backend.

Step 3: Configure Your Application

Here are minimum working configurations for the four most common environments. More languages in the Code Examples section below.

Framework Quick-Start

Minimum config to send your first email via SMTP

mailer.js
import nodemailer from "nodemailer";

const transporter = nodemailer.createTransport({
  host: "smtp.brixus365.com",
  port: 587,
  secure: false, // STARTTLS
  auth: {
    user: process.env.SMTP_USER,
    pass: process.env.SMTP_PASS,
  },
});

await transporter.sendMail({
  from: '"YourBrand Orders" <orders@yourdomain.com>',
  to: "customer@example.com",
  subject: "Your order is confirmed",
  text: "Hi Aarav, thanks for your order.",
  html: "<p>Hi Aarav, thanks for your order.</p>",
});

Pro tip (Node.js): Add pool: true and maxConnections: 5 for production throughput.

Postfix as a relay

For system-level email from a Linux server, configure Postfix in /etc/postfix/main.cf:

relayhost = [smtp.brixus365.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_use_tls = yes
smtp_tls_security_level = encrypt

Then create /etc/postfix/sasl_passwd:

[smtp.brixus365.com]:587   username:password

Run postmap /etc/postfix/sasl_passwd, then reload Postfix with systemctl reload postfix.

Step 4: Send a Test and Verify in Your Inbox

Send a message from your code to your own email address, then open it and check three things.

1. Check the authentication headers. In Gmail, click ⋮ → “Show original”. You should see:

Authentication-Results: mx.google.com;
       dkim=pass header.i=@yourdomain.com header.s=brixus365
       spf=pass smtp.mailfrom=bounces@brixus365.com
       dmarc=pass (p=NONE sp=NONE) header.from=yourdomain.com

All three must say pass. If any say fail or softfail, the DNS records are off — check propagation and re-verify.

2. Check delivery latency. A correctly configured transactional send arrives in under 5 seconds. Delays beyond 30 seconds indicate queuing problems — check the Brixus365 dashboard for message status.

3. Check the webhook event. If you have configured a webhook for email.delivered, you should see a matching event at your endpoint within seconds.

Common SMTP Errors

SMTP errors come back as status codes. The first digit tells you the broad meaning: 2xx = success, 4xx = temporary (retry), 5xx = permanent (fix something first).

SMTP Response Codes

The first digit tells you whether to retry, fix, or do nothing

2xx

Success

4xx

Temporary — retry

5xx

Permanent — fix first

2xxSuccess
Message accepted. No action needed.
250OKMessage accepted by the receiving server. Delivery is in progress.
220Service readyConnection accepted. Authentication and sending can proceed.
4xxTemporary — retry
Transient failure. Retry with exponential backoff.
421Service not availableUpstream temporary issue. Retry after 30–60 seconds.
450Mailbox temporarily unavailableRecipient server is throttling you. Retry in 5–10 minutes.
451Internal server errorTransient server error. Retry with backoff — usually resolves in minutes.
5xxPermanent — fix first
Do not retry without resolving the root cause.
535Authentication failedWrong username or password. Verify credentials in your config match what the dashboard shows.
550Mailbox unavailableRecipient address does not exist. The bounce lands in your suppression list automatically.
552Message size exceeds limitMessage too large (typical limit: 30 MB). Reduce attachment size or link to files instead.
554Message rejectedContent or sender reputation issue. Check for spam trigger words, or review Postmaster Tools.

TLS handshake failures present as connection errors before any SMTP response. Verify your library supports STARTTLS on port 587 and is not falling back to plaintext.

Code Examples

Beyond the framework integrations above, here are raw SMTP examples in Python and Go.

Python (smtplib):

import smtplib, os
from email.mime.text import MIMEText

msg = MIMEText("Hi Aarav, thanks for your order.")
msg["From"] = "orders@yourdomain.com"
msg["To"] = "customer@example.com"
msg["Subject"] = "Your order is confirmed"

with smtplib.SMTP("smtp.brixus365.com", 587) as s:
    s.starttls()
    s.login(os.environ["SMTP_USER"], os.environ["SMTP_PASS"])
    s.send_message(msg)

Go (net/smtp):

auth := smtp.PlainAuth("", os.Getenv("SMTP_USER"), os.Getenv("SMTP_PASS"), "smtp.brixus365.com")
to := []string{"customer@example.com"}
msg := []byte(
    "From: orders@yourdomain.com\r\n" +
    "To: customer@example.com\r\n" +
    "Subject: Your order is confirmed\r\n\r\n" +
    "Hi Aarav, thanks for your order.\r\n",
)
err := smtp.SendMail("smtp.brixus365.com:587", auth, "orders@yourdomain.com", to, msg)

Ruby (Mail gem):

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

Mail.deliver do
  from    "orders@yourdomain.com"
  to      "customer@example.com"
  subject "Your order is confirmed"
  body    "Hi Aarav, thanks for your order."
end

Production Readiness

The basic setup gets you working. Production-ready needs a few more things.

Production Readiness Checklist

Check off each item before going live at scale

0/13

complete

Connection Management
  • Connection pooling enabled

    Reuse TCP+TLS connections instead of opening one per message (saves 100–500 ms each).

  • maxConnections tuned for your volume

    Too few = bottleneck. Too many = rate-limited. Start with 5 and adjust based on throughput.

  • Idle connection timeout configured

    Stale connections cause silent send failures. Set idleTimeout to less than the server-side keepalive limit.

Retries & Error Handling
  • Exponential backoff for 4xx errors

    Schedule: 1s → 5s → 30s → 2min → 10min. Never retry 5xx without fixing the cause first.

  • Max retry cap (5 attempts)

    Infinite retries fill queues and mask bugs. Cap at 5, then dead-letter.

  • Dead-letter queue for permanent failures

    Failed messages must go somewhere visible, not silently drop. Route to a DLQ and alert.

Queueing & Throughput
  • Sends decoupled from HTTP request threads

    Enqueue the job in the HTTP request, send in a worker. Never block a web request on SMTP.

  • Queue depth monitored with alerting

    A growing queue means workers cannot keep up. Alert before the backlog becomes a delay for end-users.

  • Worker concurrency matches pool size

    One worker + maxConnections=1 bottlenecks. Scale workers proportionally to connection pool.

Observability
  • Logging: message ID, recipient, status, retry count

    Minimum structured log per send. This data resolves 90% of support escalations.

  • Alert on send success rate < 99%

    Something is wrong upstream. Page on-call before customers report missing emails.

  • Alert on elevated 4xx rate

    A spike means rate-limiting or a temporary backend issue. Investigate before retries exhaust.

  • Webhook events captured for delivered/bounced

    SMTP success ≠ inbox delivery. Subscribe to delivered and bounced events from the dashboard.

Connection pooling

Opening a fresh SMTP connection per message adds 100–500 ms per send (TCP + TLS + AUTH). Reuse connections:

  • Nodemailer: enable pool: true and tune maxConnections.
  • Python smtplib: keep the SMTP instance alive across multiple sends.
  • Postfix as relay: handled automatically.

Retries with exponential backoff

SMTP 4xx errors are temporary — retry with a schedule like 1s → 5s → 30s → 2min → 10min. Cap at 5 attempts; after that, route to a dead-letter queue and alert.

Queue and dead-letter handling

For high-volume systems, decouple the send from the HTTP request. The HTTP request enqueues a job; a worker dequeues and sends. Failed jobs after N retries go to a dead-letter queue for manual review.

When to Switch to the API

SMTP is the right choice for many use cases — forever. But there are signals you have outgrown it:

  • You need idempotency keys — SMTP has no native idempotency. Retries can duplicate sends.
  • You want fine-grained per-message webhooks — possible with SMTP but more setup than via the API.
  • You need high-volume batch operations — 10,000 transactional emails via SMTP one connection at a time is slower than a single API batch call.
  • You want server-side templates referenced by ID — cleaner via API than via SMTP X-Headers.
  • You want per-service key scoping — API keys can be scoped precisely; SMTP credentials are coarser.

The migration path is gradual: keep SMTP for legacy flows, route new flows through the API. The verified domain, suppression list, and webhook destinations are shared — there is no parallel infrastructure to maintain.

Key Takeaways

  1. SMTP gets you to first email in 10 minutes if your framework already supports it. Do not over-engineer with a custom API integration if SMTP works.
  2. Use port 587 with STARTTLS for new setups. Port 465 is fine but only default to it if your library requires it.
  3. Connection pooling and retries are not optional in production. Build them from day one, or debug them at 3 AM when your queue depth spikes.

FAQ

Should I use port 587 or 465 for SMTP?
Use port 587 with STARTTLS for new setups — it’s the modern standard. Port 465 (implicit TLS) also works and is fine to use if your library defaults to it; both are encrypted.
Should I use SMTP or the email API?
Use SMTP when your framework or platform already speaks it — it’s the fastest way to first email with no code changes beyond credentials. Reach for the REST API when you want template management, per-message tracking, and idempotent retries. Both share the same sending domain and analytics.
Which frameworks can send through Brixus365 SMTP?
Any framework or platform that supports standard SMTP — Django, Rails, Laravel, Node (Nodemailer), WordPress, and most ecommerce platforms. You only need the host, port, and credentials.
Is sending email through Brixus365 free?
Yes — the Free plan includes 9,000 emails a month with no credit card, over SMTP or the API. Pricing only scales as your volume grows.

Ready to send? Start free — 9,000 emails a month, no credit card — and point your app at SMTP in the next 10 minutes.

SharePost on XLinkedIn
Try it free

Send smarter emails with Brixus365

Campaigns and transactional API on one engine. 9,000 emails/month free, no credit card.

Start sending free
9,000 emails/month freeNo credit card required
All articles →
Stay in the loop

New guides, straight to your inbox

Field notes on deliverability, list hygiene, and transactional email — roughly once a month, no fluff.

No spam. Unsubscribe with one click. We respect your inbox.