# Can testssl.sh Test Non-HTTP Services with STARTTLS? Protocol Support Guide

> Discover how testssl.sh tests non-HTTP services like SMTP FTP and XMPP with STARTTLS. Learn to perform complete TLS handshakes using the t flag for comprehensive security checks.

- Repository: [Dirk Wetter/testssl.sh](https://github.com/drwetter/testssl.sh)
- Tags: deep-dive
- Published: 2026-03-01

---

**Yes, testssl.sh fully supports testing non-HTTP services like SMTP, FTP, and XMPP via STARTTLS, performing complete TLS handshakes after protocol-specific upgrades using the `-t` flag.**

The **drwetter/testssl.sh** repository extends its HTTPS auditing capabilities to any service that upgrades plaintext connections to TLS through the STARTTLS mechanism. This allows security teams to evaluate cipher suites, certificate validity, and vulnerabilities across mail servers, file transfers, and databases using the same comprehensive test suite applied to web servers.

## How STARTTLS Works in testssl.sh

The STARTTLS implementation spans multiple components within the codebase, coordinating command-line parsing, protocol translation, and OpenSSL invocation.

### Command-Line Parsing and Protocol Detection

In [`testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/testssl.sh) at lines **21540‑21545**, the `-t` (or `--starttls`) option triggers the STARTTLS workflow. When detected, the tool stores the chosen protocol in the `STARTTLS_PROTOCOL` variable and sets internal flags to initiate the plaintext-to-TLS upgrade sequence.

### Protocol-to-OpenSSL Translation

At lines **12373‑12386** in [`testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/testssl.sh), a `case "$STARTTLS_PROTOCOL"` block translates user-friendly protocol names into OpenSSL `-starttls` arguments. For example, `smtp` becomes `-starttls smtp`, while XMPP handling includes special logic for the `--xmpphost` parameter required for XMPP domain specification.

### OpenSSL Client Invocation

The actual TLS handshake execution occurs in [`utils/checkcert.sh`](https://github.com/drwetter/testssl.sh/blob/main/utils/checkcert.sh) at lines **5‑7**, where the tool invokes `openssl s_client $STARTTLS -connect $HOST:$PORT`. The `$STARTTLS` variable expands to the appropriate `-starttls <protocol>` flag when testing non-HTTP services, or remains empty for native TLS ports like 443 or 465.

## Supported STARTTLS Protocols

testssl.sh recognizes the following protocols for STARTTLS testing:

- **ftp** – File Transfer Protocol (explicit TLS on port 21)
- **smtp** – Simple Mail Transfer Protocol (port 25)
- **pop3** – Post Office Protocol v3 (port 110)
- **imap** – Internet Message Access Protocol (port 143)
- **xmpp** – Extensible Messaging and Presence Protocol client-to-server (port 5222)
- **xmpp-server** – XMPP server-to-server federation (port 5269)
- **sieve** – Mail filtering protocol
- **telnet** – Telnet with TLS option
- **ldap** – Lightweight Directory Access Protocol (port 389)
- **irc** – Internet Relay Chat
- **lmtp** – Local Mail Transfer Protocol
- **nntp** – Network News Transfer Protocol
- **postgres** – PostgreSQL database connections
- **mysql** – MySQL database connections

## Testing Non-HTTP Services: Practical Examples

Use the `-t` flag followed by the protocol name to test non-HTTP services. All examples produce the same detailed output as HTTPS scans, including cipher grades, protocol versions, and vulnerability assessments.

### SMTP Mail Servers

Test SMTP STARTTLS on the standard port 25:

```bash
testssl.sh -t smtp smtp.example.com:25

```

### FTP with Explicit TLS

Test FTP STARTTLS on port 21 (distinct from implicit TLS on port 990):

```bash
testssl.sh -t ftp ftp.example.com:21

```

### XMPP with Domain Specification

XMPP testing requires the `--xmpphost` flag to specify the domain for the STARTTLS flow:

```bash
testssl.sh -t xmpp xmpp.example.com:5222 --xmpphost example.com

```

### Automated MX Record Testing

Scan all Mail Exchange records for a domain automatically using the `--mx` flag, which implicitly applies SMTP STARTTLS testing:

```bash
testssl.sh --mx example.org

```

## STARTTLS Grading and Detection Logic

When testssl.sh detects a plain TLS port (such as 465 for SMTPS or 990 for FTPS), it skips the STARTTLS handshake and tests native TLS directly. For services requiring STARTTLS, the tool attempts the protocol-specific upgrade and falls back to plaintext detection if the handshake fails.

According to the documentation in [`doc/testssl.1.md`](https://github.com/drwetter/testssl.sh/blob/main/doc/testssl.1.md), STARTTLS-specific scans receive a maximum grade cap of **T** (as opposed to A+ for pure TLS services), reflecting the additional attack surface introduced by the plaintext upgrade mechanism. However, all standard tests—including cipher suite evaluation, Heartbleed detection, and client simulation—execute normally after the TLS upgrade completes.

## Summary

- **testssl.sh** supports **14 non-HTTP protocols** via STARTTLS, including SMTP, FTP, XMPP, LDAP, and databases like PostgreSQL and MySQL.
- The `-t` flag (or `--starttls`) activates protocol-specific handling defined in [`testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/testssl.sh) lines **21540‑21545** and **12373‑12386**.
- OpenSSL invocation with the correct `-starttls` argument occurs in [`utils/checkcert.sh`](https://github.com/drwetter/testssl.sh/blob/main/utils/checkcert.sh) using the `$STARTTLS` variable expansion.
- **All standard TLS tests** apply to STARTTLS services after the handshake upgrade, though grades are capped at **T** to account for plaintext upgrade risks.
- Special flags like `--mx` (for mail servers) and `--xmpphost` (for XMPP) automate protocol-specific configuration requirements.

## Frequently Asked Questions

### What STARTTLS protocols does testssl.sh support?

testssl.sh supports **ftp, smtp, pop3, imap, xmpp, xmpp-server, sieve, telnet, ldap, irc, lmtp, nntp, postgres, and mysql**. According to the source code in [`testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/testssl.sh) around line 12373, each protocol maps to a specific OpenSSL `-starttls` argument or custom handling logic for the handshake sequence.

### How do I test an XMPP server with STARTTLS using testssl.sh?

Use the `-t xmpp` flag combined with `--xmpphost` to specify the domain. For example: `testssl.sh -t xmpp server.example.com:5222 --xmpphost example.com`. The `--xmpphost` parameter is required because XMPP STARTTLS negotiations depend on the domain name for proper stream initialization, as implemented in the protocol-specific case block at lines 12373‑12386.

### Does testssl.sh support STARTTLS for databases like MySQL and PostgreSQL?

Yes. Both **postgres** and **mysql** are valid arguments for the `-t` flag. The tool sends the appropriate STARTTLS commands for these database protocols and then performs the standard TLS cipher suite and certificate validation tests, allowing database administrators to audit encryption configurations without dedicated database security tools.

### What is the difference between using `-t smtp` and scanning port 465 directly?

Port 465 typically uses **implicit TLS** (TLS from connection start), while port 25 with `-t smtp` uses **STARTTLS** (plaintext upgraded to TLS). When you specify `-t smtp`, testssl.sh sends the `STARTTLS` command before the TLS handshake. Direct port 465 scans skip this step. The tool automatically detects native TLS ports and adjusts behavior, but explicit `-t` usage ensures the correct protocol sequence for ports running plaintext services.