How to Test an SMTP Server with Telnet, OpenSSL or Swaks
Connect to the server with telnet on port 25 or openssl s_client on 587 or 465, check for a 220 greeting and 250 replies to EHLO, MAIL FROM and RCPT TO, and stop before DATA if you don't want anything delivered.
Philippe Kam, founder of Emailens · Published 28 Oct 2026
@emailens/engine 0.17.2 · data last changed 27 Oct 2026
Part of the HTML email guide · all guides
When mail stops arriving, the fastest way to find out whose fault it is is to talk to the mail server yourself. SMTP is plain text: you can type a whole session by hand, see exactly where the server says no, and stop before anything reaches a real inbox.
Find the server
To test the server that receives mail for a domain, look up its MX records. Each one names a host and a preference; the lowest preference is tried first, and the others are there for load balancing and fallback.
# macOS and Linux
dig example.net MX +short
# Windows
nslookup
> set type=mx
> example.net.
> exitThe trailing period in the Windows example stops nslookup from appending your local DNS suffix. If you would rather not use a terminal, the deliverability checker lists a domain's MX records alongside its authentication records. To test the server your own app sends through, skip this step: use the host your provider gave you.
Test SMTP with telnet on port 25
Open a connection to the MX host on port 25 and type the commands yourself. The transcript below follows the example session in RFC 5321: lines starting S: come from the server, C: lines are what you type (without the prefix). The reply codes are fixed by the RFC; the text after them varies from server to server.
$ telnet mx.example.net 25
S: 220 mx.example.net ESMTP ready greeting: you are connected
C: EHLO laptop.example.com say who you are
S: 250-mx.example.net greets laptop.example.com
S: 250-8BITMIME a hyphen after the code:
S: 250-SIZE more lines follow
S: 250-STARTTLS
S: 250 HELP a space: this is the last line
C: MAIL FROM:<me@example.com> envelope sender
S: 250 OK
C: RCPT TO:<someone@example.net> envelope recipient
S: 250 OK the server will take mail for it
C: DATA
S: 354 Start mail input; end with <CRLF>.<CRLF>
C: Subject: SMTP test
C: blank line ends the headers
C: Sent by hand.
C: . a lone period ends the message
S: 250 OK accepted for delivery
C: QUIT
S: 221 mx.example.net Service closing transmission channelFour things to know before you start. First, in the Windows Telnet Client the backspace key does not work once connected: if you mistype, press Enter and type the command again (run set localecho at the Microsoft Telnet> prompt first if you cannot see what you type). Second, if a server does not support EHLO, use the older HELO instead. Third, a line of message text that begins with a period has to be sent with a second period in front, or the server reads it as the end of the message.
Fourth, and most useful: nothing is accepted for delivery until the server answers the final period with 250. To check whether a server would take mail for an address without sending anything, stop after RCPT TO and type QUIT. If a command is refused, the code tells you why: 550 5.1.1 after RCPT TO is an address that does not exist, 530 after MAIL FROM means the server wants you to log in first. What each code means for your sending is covered in hard vs soft bounces.
If telnet is not installed, nc mx.example.net 25 opens the same connection. One difference: SMTP lines end in a carriage return and line feed, and nc sends only the line feed when you press Enter, which a strict server may refuse. If that happens, use telnet or the OpenSSL commands below with -crlf.
Ports 587 and 465: test with OpenSSL
Port 25 is for servers relaying to each other. Apps and mail clients submit mail on port 587, where RFC 6409 has the server refuse MAIL FROM until you have authenticated, or on port 465, where the connection is encrypted from the first byte. RFC 8314 recommends implicit TLS on 465 over STARTTLS but asks servers to support both, and says the two are equally secure when both sides require TLS. telnet cannot speak TLS, so use openssl s_client:
# Port 587: connect in plain text, then upgrade with STARTTLS
openssl s_client -starttls smtp -connect smtp.example.com:587 -crlf -quiet
# Port 465: TLS from the first byte (implicit TLS)
openssl s_client -connect smtp.example.com:465 -crlf -quietWith -starttls smtp, OpenSSL does the plain-text part for you: it reads the greeting, sends EHLO and STARTTLS, then negotiates TLS. RFC 3207 makes the client forget everything the server said before the upgrade, so the first thing you type is a new EHLO; the capability list often changes, and AUTH commonly appears only now. On port 465 there is no upgrade step: you get the 220 greeting inside the encrypted connection and carry on exactly as with telnet.
The two flags matter. -crlf turns your Enter key into the CR LF that SMTP expects. -quiet trims the certificate output and also switches off OpenSSL's interactive command letters: without it, a line starting with R renegotiates the session and one starting with Q quits, so typing RCPT TO never reaches the server. If you drop -quiet to see the certificate, add -nocommands in its place.
Test SMTP authentication
AUTH PLAIN takes one base64 string: a null byte, the username, a null byte, the password (RFC 4616). The server answers 235 if the credentials work and 535 if not (RFC 4954). AUTH LOGIN is the older variant: the server prompts with 334 and you send the username and then the password, each base64-encoded on its own line. The specification for LOGIN calls it obsolete in favor of PLAIN.
# Build the AUTH PLAIN string: NUL, username, NUL, password
printf '\0%s\0%s' 'test-user@example.com' 'test-password' | base64
# Then, inside the encrypted session:
C: EHLO laptop.example.com
S: 250-smtp.example.com
S: 250 AUTH PLAIN LOGIN
C: AUTH PLAIN <the base64 string>
S: 235 2.7.0 Authentication successful or 535 5.7.8 if refusedBase64 is not encryption. Anyone who sees that string has your password: decoding it takes one command. Only send AUTH inside a TLS session (RFC 4954 has servers able to refuse plain-text passwords without one), never paste a real password into a shared terminal, a screen share, a ticket or a chat, and remember that the printf line is now in your shell history. Test with a throwaway credential where you can, or let swaks prompt for the password.
Script it with swaks
Once you know what a session looks like, swaks (the Swiss Army Knife for SMTP) runs the whole thing in one line and prints every command and reply. Without --server it looks up the recipient domain's MX for you; the default port is 25.
# Does the MX accept mail for this address? Stops before DATA.
swaks --to someone@example.net --quit-after RCPT
# Send a real test message to your own address through a given server
swaks --to me@example.com --server mx.example.com
# Port 587, STARTTLS required, authenticate (prompts for the password)
swaks --to me@example.com --from me@example.com \
--server smtp.example.com --port 587 --tls --auth-user me@example.com
# Port 465, implicit TLS (the default port becomes 465)
swaks --to me@example.com --from me@example.com \
--server smtp.example.com --tls-on-connect --auth-user me@example.com--quit-after RCPT is the scripted version of stopping before DATA. --tls makes swaks exit if STARTTLS fails rather than fall back to plain text, which is what you want in a test. Leave out --auth-password and swaks asks for it, so the password stays out of your history and your CI logs.
Why port 25 times out from your laptop or cloud server
If telnet mx.example.net 25 hangs and then fails while the same host answers from elsewhere, your network is probably blocking outbound port 25. Many networks do, because malware on infected machines uses it to send spam:
- Comcast (Xfinity) does not support port 25 for sending email from residential connections and recommends 587 with TLS.
- Google Cloud blocks connections to port 25 on destinations outside your VPC network, and places no restriction on 587 or 465.
- Azure blocks outbound port 25 from virtual machines on most subscription types (Enterprise Agreement and MCA-E are the exceptions) and recommends an authenticated relay on 587.
So a timeout on 25 tells you about your own network, not the server. Test the MX from a machine that is allowed to reach it, or use an online test such as Microsoft's Remote Connectivity Analyzer. Your app should not be sending on 25 anyway: it submits to a provider on 587 or 465.
Test your app's email without emailing real people
The commands above test a server. Testing what your app sends, the password reset, the sign-up code, the receipt, needs a server that accepts everything and delivers nothing. Pointing staging at your real provider risks mailing customers; pointing it at nothing means you never see the message.
The Emailens sandbox is an authenticated SMTP relay for this: smtp.emailens.dev on port 2525 or 587, with STARTTLS enforced and credentials per developer or service. Every message is captured in your sandbox inbox and never reaches the recipient. From there a CI test can long-poll an endpoint until the email arrives and read the extracted one-time code, and you can open the captured email in the 21-client rendering check. The same swaks command works against it:
swaks --to anyone@example.com --from app@myapp.com \
--server smtp.emailens.dev --port 2525 --tls \
--auth-user esmtp_staging_clx9If you only need to catch mail on your own machine, a local capture server such as Mailpit does the SMTP part; see Emailens vs Mailpit for where they differ. Once the message itself is right and it goes to real inboxes, authentication decides whether it is accepted: check the domain with the SPF, DKIM and DMARC checkers, and read the email deliverability guide for how they fit together.
Questions
How do I check if an SMTP server is working?
Connect to it and read the first line. A working server answers a new connection with a 220 greeting; then send EHLO and expect a list of 250 lines. telnet host 25 does this for a plain connection, and openssl s_client -starttls smtp -connect host:587 does it for an encrypted one. If the connection times out instead, the server is down or a firewall between you and it is blocking the port.
Why does Windows say telnet is not recognized?
The Telnet Client ships with Windows but is not installed by default. Install it from an elevated prompt with dism /online /Enable-Feature /FeatureName:TelnetClient, or tick Telnet Client under Turn Windows features on or off in the Control Panel, then open a new command prompt.
Which port should I test, 25, 587 or 465?
Test the port your client will use. Port 25 is server-to-server relay, where MX hosts receive mail. Port 587 is submission with STARTTLS and, by default, requires authentication. Port 465 is submission with TLS from the first byte. An app sending through a provider uses 587 or 465; testing someone's MX means port 25.
How do I test SMTP authentication?
Open an encrypted session on 587 or 465 with openssl s_client, send EHLO, then AUTH PLAIN followed by the base64 of a null byte, the username, a null byte and the password. 235 means the credentials work; 535 means they were refused. swaks --auth-user does the same and prompts for the password, which keeps it out of your shell history.
Can I test an SMTP server online?
Yes. Microsoft's Remote Connectivity Analyzer at testconnectivity.microsoft.com has an Inbound SMTP Email test that connects to your server from the internet. An online test is useful when your own network blocks port 25, but it only proves the server is reachable from that service, not from where your app runs.
Your next question
Also useful: Email Header Analyzer · SPF Record Checker · Emailens vs Mailpit
Verify your SPF, DKIM, DMARC and BIMI records, with fix suggestions.
Check your domain, freeGet new email CSS fixes by email, or follow by RSS.