---
title: "SMTP SSL vs TLS: Which to Pick, STARTTLS or Implicit TLS"
description: "For SMTP, use TLS: SSL is deprecated. Pick implicit TLS on port 465 when offered, or STARTTLS on 587. Ports, RFCs and client settings explained."
canonical: https://sendhq.cc/blog/smtp-ssl-vs-tls
last-updated: 2026-11-04
author: Dhrumil Barot
author_bio: Dhrumil is an email marketing expert. Dhrumil built SendHQ so developers and AI agents can send, receive and track email without fighting deliverability on their own.
published: 2026-11-04
updated: 2026-11-04
---
# SMTP SSL vs TLS: Which to Pick, STARTTLS or Implicit TLS

By [Dhrumil Barot](https://sendhq.cc/about.md#founder), Founder

For SMTP, use TLS: SSL is deprecated. Pick implicit TLS on port 465 when offered, or STARTTLS on 587. Ports, RFCs and client settings explained.

Published November 4, 2026 · Updated November 4, 2026

**TL;DR:** In SMTP, "SSL" almost always means implicit TLS on port 465, and "TLS" usually means STARTTLS on port 587. The actual SSL protocols are deprecated, so both settings should negotiate TLS 1.2 or 1.3. When your provider offers both, RFC 8314 recommends implicit TLS on 465; use STARTTLS on 587 with "require TLS" turned on when 465 is unavailable.

The SMTP SSL vs TLS question is really about *when* encryption starts, not which cipher protocol you get. With implicit TLS (the "SSL" or "SSL/TLS" checkbox in most mail clients), the TLS handshake starts the moment the TCP connection opens on port 465. With STARTTLS (the "TLS" checkbox), the client connects in plaintext on port 587 or 25, the server advertises the `STARTTLS` capability, and the connection is upgraded before any login. SSL 2.0 and SSL 3.0 themselves were retired by RFC 6176 (2011) and RFC 7568 (2015), and TLS 1.0 and 1.1 by RFC 8996 (2021), so a modern server negotiates TLS 1.2 or TLS 1.3 either way.

## Side by side: ports, standards and code settings

| Criterion | "SSL" setting (implicit TLS) | "TLS" setting (STARTTLS) |
| --- | --- | --- |
| Default submission port | 465 | 587 (also 25 for relay) |
| When encryption starts | Before the first SMTP byte | After `EHLO` and `STARTTLS` in plaintext |
| Defining standard | RFC 8314 (Jan 2018) | RFC 3207 (Feb 2002) |
| RFC 8314 preference | Preferred for submission | Supported during transition |
| Downgrade risk | None: no plaintext phase | Stripping attack if the client does not require TLS |
| Protocol actually negotiated | TLS 1.2 or 1.3 | TLS 1.2 or 1.3 |
| Nodemailer setting | `secure: true` | `secure: false` (+ `requireTLS: true`) |
| Python smtplib | `smtplib.SMTP_SSL` | `smtplib.SMTP` then `.starttls()` |
| Amazon SES ports | 465, 2465 ("TLS Wrapper") | 25, 587, 2587 |

![Implicit TLS encrypts from the first byte, STARTTLS upgrades after a plaintext greeting](https://cdn.sanity.io/images/l4lj7ros/production/9ee7fc96e59e75f117ec697937ccf39b404c90e5-1344x594.png?w=1280&auto=format)

The highlighted rows travel in plaintext and are what a stripping attack targets.

## Is SSL or TLS better for SMTP?

TLS is better, and it is the only option you should accept. SSL 2.0 is prohibited (RFC 6176) and SSL 3.0 is deprecated (RFC 7568) because of known breaks such as POODLE. TLS 1.0 and 1.1 followed in March 2021 (RFC 8996), and RFC 8314 says mail services still allowing SSL 2.x, SSL 3.0 or TLS 1.0 SHOULD move their users off them.

The confusion comes from labels. Many clients and providers still say "SSL" for port 465 because that port was first used with SSL in the 1990s. Google's SMTP relay help page, for example, tells you "For SSL, enter 465". Amazon SES calls the same mode "TLS Wrapper" and explicitly notes it is sometimes called SSL. Picking "SSL" in a modern client does not downgrade you to the SSL protocol; it picks implicit TLS. What you should check is the minimum protocol version: TLS 1.2, with TLS 1.3 (RFC 8446, August 2018) where both sides support it.

## What is the difference between STARTTLS and implicit TLS?

STARTTLS is an SMTP command that upgrades an already-open plaintext connection to TLS; implicit TLS opens the connection inside TLS from the start. The resulting encryption is the same. The difference is the plaintext phase before the upgrade.

That phase is where the attacks live. In the USENIX Security 2021 paper "Why TLS is better without STARTTLS", Poddebniak, Ising, Böck and Schinzel tested mail clients and servers and found:

- 15 of 28 clients were vulnerable to negotiation attacks, where a man in the middle strips the `STARTTLS` capability or injects an error so the client continues in plaintext.
- A command injection bug first reported in 2011, where commands sent before the handshake are executed after it, was present in 8 of 23 server products tested and in about 2% of mail servers in an internet scan.
- 16 of 28 clients accepted injected responses across the upgrade.

Their recommendation for users is to switch to implicit TLS and disable STARTTLS where possible. STARTTLS is still safe enough when the client *requires* the upgrade and refuses to continue without it; the danger is opportunistic STARTTLS, where a failed upgrade silently falls back to plaintext.

Video: [USENIX Security '21 - Why TLS is better without STARTTLS: A Security Analysis of STARTTLS](https://www.youtube.com/watch?v=cJhJdMC_PGI&t=56s) (USENIX)

Fabian Ising presents the USENIX Security 2021 research on STARTTLS. This part explains how STARTTLS adds a plaintext phase, how stripping and command injection attacks abuse it, and how many real clients and servers were affected.

1. [0:56](https://www.youtube.com/watch?v=cJhJdMC_PGI&t=56s) Attacker model and STARTTLS vs implicit TLS
2. [2:07](https://www.youtube.com/watch?v=cJhJdMC_PGI&t=127s) Microsoft and Apple submission support only STARTTLS
3. [3:40](https://www.youtube.com/watch?v=cJhJdMC_PGI&t=220s) Stripping the STARTTLS capability
4. [6:00](https://www.youtube.com/watch?v=cJhJdMC_PGI&t=360s) Command injection bug found in 8 of 23 servers

## Which port should I use, 465 or 587?

Use 465 with implicit TLS when your provider supports it, and 587 with STARTTLS when it does not. RFC 8314 says clients and servers SHOULD implement both for the transition period and that Implicit TLS servers SHOULD be advertised in preference to STARTTLS ones. In practice:

- **Port 465:** implicit TLS. Supported by Amazon SES (also 2465), Google (`smtp.gmail.com` and `smtp-relay.gmail.com`), and most transactional providers.
- **Port 587:** STARTTLS submission. Supported almost everywhere, and the only option on some large providers: the USENIX authors note Microsoft and Apple offered only STARTTLS for submission at the time.
- **Port 25:** server-to-server relay. Many cloud hosts block outbound 25, and STARTTLS on 25 is usually opportunistic. Do not use it for authenticated submission from an app.
- **Port 2525 / 2587 / 2465:** alternates some providers (including SES for 2587 and 2465) offer when a network blocks the standard ports.

Our [SMTP port 587 vs 465 vs 25 guide](https://sendhq.cc/blog/smtp-port-587-vs-465-vs-25) covers firewall and hosting restrictions per port, and the [SMTP port reference](https://sendhq.cc/guides/smtp-port.md) lists provider defaults.

![Choosing an SMTP encryption setting starts with whether port 465 is offered](https://cdn.sanity.io/images/l4lj7ros/production/eacd795da155a01acbdef0f2661cda45b22c4ff8-1344x326.png?w=1280&auto=format)

Never accept a setting that lets the client fall back to plaintext.

## How to configure each mode in code

Set the encryption mode to match the port; a mismatch is the most common cause of handshake timeouts and "wrong version number" errors.

**Nodemailer (Node.js).** `secure: true` means TLS from the first byte and defaults on for port 465. For 587, keep `secure: false`; Nodemailer upgrades with STARTTLS when offered, and `requireTLS: true` makes it fail instead of sending in plaintext.

```
// Implicit TLS on 465
const implicit = nodemailer.createTransport({
  host: "email-smtp.us-east-1.amazonaws.com",
  port: 465,
  secure: true,
  auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
});

// STARTTLS on 587, refuse plaintext fallback
const starttls = nodemailer.createTransport({
  host: "email-smtp.us-east-1.amazonaws.com",
  port: 587,
  secure: false,
  requireTLS: true,
  tls: { minVersion: "TLSv1.2" },
  auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
});
```

**Python smtplib.** `SMTP_SSL` wraps the socket in TLS immediately; `SMTP` plus `starttls()` upgrades. Pass a default context so the certificate and hostname are verified.

```
import smtplib, ssl

ctx = ssl.create_default_context()
ctx.minimum_version = ssl.TLSVersion.TLSv1_2

# Implicit TLS on 465
with smtplib.SMTP_SSL("smtp.example.com", 465, context=ctx) as s:
    s.login(user, password)
    s.send_message(msg)

# STARTTLS on 587
with smtplib.SMTP("smtp.example.com", 587) as s:
    s.starttls(context=ctx)  # raises if the server does not offer STARTTLS
    s.login(user, password)
    s.send_message(msg)
```

**Check a server from the shell.** OpenSSL shows the negotiated protocol for either mode:

```
# implicit TLS
openssl s_client -connect smtp.example.com:465 -brief
# STARTTLS
openssl s_client -connect smtp.example.com:587 -starttls smtp -brief
```

The `Protocol version:` line should read TLSv1.2 or TLSv1.3. Our [Python SMTP guide](https://sendhq.cc/guides/smtp-python.md) has full send examples, and [common SMTP errors](https://sendhq.cc/blog/smtp-errors) covers the codes you see when the handshake succeeds but delivery fails.

## Do I need an SSL certificate to send email?

No, not as a sender connecting to a provider. The *server* presents the certificate; your client only verifies it. You need your own certificate only if you run the receiving or submission server, where it must match the hostname clients connect to (for example `smtp.yourdomain.com`). What senders do need is domain authentication: SPF, DKIM and DMARC, which prove the mail is yours and are separate from transport encryption. See [DKIM, SPF and DMARC explained](https://sendhq.cc/guides/email-dkim-spf-dmarc.md).

## Decision rules for a new app

Choose implicit TLS (465) if:

- your provider offers it, which most transactional providers and Amazon SES do;
- you want no plaintext phase and no possibility of a stripping downgrade;
- you are configuring a new app and want the RFC 8314 recommended default.

Choose STARTTLS (587) if:

- the provider supports only 587, as some large mailbox providers do;
- a network or host blocks 465;
- you can set the client to require TLS (`requireTLS`, "Require STARTTLS", `starttls()` that raises) so it never falls back.

## Skipping SMTP entirely

For application email, SMTP encryption settings are one more thing to get wrong in each service and environment. An HTTPS email API removes the choice: every request is TLS by default, authentication is an API key rather than an SMTP password, and the response tells you whether the message was accepted. If that is your next step, [SendHQ](https://sendhq.cc/index.md) offers a Resend-compatible REST API for sending and receiving email from verified domains, with delivery and bounce events you can inspect per message.

## FAQ

### Is port 465 deprecated?

No. Port 465 was briefly reassigned in the late 1990s, which is why older guides call it deprecated, but RFC 8314 (2018) formally registered it for implicit TLS submission and prefers it over STARTTLS.

### Is STARTTLS secure?

STARTTLS gives the same encryption as implicit TLS once the upgrade happens. It is secure when the client requires the upgrade; it is weak when the client silently continues in plaintext if `STARTTLS` is missing or fails.

### What does "SSL/TLS" mean in my email client?

It means implicit TLS, usually on port 465. "STARTTLS" or plain "TLS" usually means the upgrade method on port 587. Both negotiate a TLS protocol version, not SSL.

### Why do I get "wrong version number" or a timeout?

The encryption mode does not match the port: `secure: true` against 587 tries a TLS handshake on a plaintext greeting, and `secure: false` against 465 waits for a greeting that only arrives inside TLS. Match 465 to implicit TLS and 587 to STARTTLS.

### Which TLS version should SMTP use?

TLS 1.2 at minimum and TLS 1.3 where available. TLS 1.0 and 1.1 were deprecated by RFC 8996 in March 2021.

### Does SMTP TLS encrypt the email end to end?

No. Submission TLS protects the hop from your app to the provider. Server-to-server hops use their own, often opportunistic, STARTTLS on port 25. End-to-end encryption needs S/MIME or OpenPGP.

Sources: [RFC 8314](https://www.rfc-editor.org/rfc/rfc8314), [RFC 3207](https://www.rfc-editor.org/rfc/rfc3207), [RFC 8996](https://www.rfc-editor.org/rfc/rfc8996), [RFC 7568](https://www.rfc-editor.org/rfc/rfc7568), [Amazon SES SMTP connection docs](https://docs.aws.amazon.com/ses/latest/dg/smtp-connect.html), [Nodemailer SMTP transport](https://nodemailer.com/smtp/), [Python smtplib](https://docs.python.org/3/library/smtplib.html).

## Keep reading

- [DMARC aspf Explained: Strict vs Relaxed SPF Alignment](https://sendhq.cc/blog/dmarc-aspf): DMARC aspf sets SPF alignment: r (relaxed, the default) accepts any subdomain of your From domain, s (strict) needs an exact match. Worked e Read article →
- [SMTP Code 550: How to Fix Every 550 Error Variant](https://sendhq.cc/blog/smtp-code-550): SMTP code 550 is a permanent rejection: the server refused the message. Read the enhanced code (5.1.1, 5.7.1, 5.7.26) to find the exact fix. Read article →
- [SMTP Errors: Reply Codes and Status Codes Reference](https://sendhq.cc/blog/smtp-errors): SMTP errors are 3-digit reply codes: 4xx is temporary and safe to retry, 5xx is permanent. Full table with enhanced codes and fixes. Read article →
