Issue
As you send email, you may encounter scenarios where it seems to take more time than it should to get to its final destination. Mail delays can manifest in a number of ways.
If you are experiencing severe latency, please first check our Status Page to verify the current state of all Twilio SendGrid services. If all systems are operational, mail delays are typically caused by application throughput limitations, downstream receiver filters, or local network bottlenecks. This guide covers the step-by-step workflows for diagnosing and resolving these issues.
Product
Twilio SendGrid (Email Delivery)
Resolution
Please start at the top and walk through each of the troubleshooting steps as you work your way down the page.
1. Optimize Application Throughput
Before checking for network problems, verify that your application is configured to transmit mail as efficiently as possible.
-
Verify you're using an official Twilio SendGrid library: If you are integrated with Twilio SendGrid using custom code, we highly recommend migrating to our official SDKs. You can find links for all of our official SDKs and getting started tutorials at API Libraries (SendGrid Docs).
-
Use the Twilio SendGrid SMTPAPI: You can use our SMTPAPI to greatly increase your message throughput. While standard SMTP connections allow you to send 100 messages per connection, utilizing the
x-smtpapiheader allows you to include up to 1,000 "TO:" recipients for each individual message payload. This option is available via standard SMTP infrastructure as well as the Web API v3.
- Try opening additional connections: Lastly, you can try to open additional concurrent connections from your environment. Generally, we recommend a maximum of 10 concurrent connections. However, please note that Twilio SendGrid can handle as much mail as you can throw at us. Make certain that the maximum amount of mail payload is passed before terminating each active connection.
2. Network Connectivity Verification (macOS)
Traditional network diagnostics like standard ping or traceroute are no longer supported on our edge relays and will time out. Use the following port-specific and DNS-specific tools instead to check for network congestion or traffic shaping.
Supported Ports
-
TLS via STARTTLS (Recommended):
587 -
TLS via STARTTLS / Unencrypted (Network-dependent):
25,2525 -
SSL/TLS (Implicit TLS):
465
Note: Many ISPs and corporate networks block port 25. If port 587 is blocked, 2525 is a common fallback. If STARTTLS is being interfered with on the network, port 465 (Implicit TLS) often works.
0) Set your SMTP Host
Define your target SMTP hostname in your terminal window:
Bash
SMTP_HOST="smtp.sendgrid.net"
1) DNS Checks (Detect Split DNS / DNS Rewriting)
1.1 What macOS resolves via the system resolver:
Bash
dscacheutil -q host -a name "$SMTP_HOST"1.2 Compare with public DNS (Bypasses VPN/Corporate DNS rewriting):
Bash
dig @1.1.1.1 +short "$SMTP_HOST"
dig @8.8.8.8 +short "$SMTP_HOST"What to look for: If
dscacheutilreturns an IP address in private subnets (e.g.,10.x,192.168.x,172.16–31.x, or100.64.x), but public DNS returns public IPs, your network or VPN is likely intercepting or rewriting DNS.
2) Port Reachability Test
Verify which ports are explicitly open from your current network:
Bash
for p in 587 25 2525 465; do
echo "== Testing port $p =="; nc -vz -w 3 "$SMTP_HOST" "$p"
done-
succeeded!= TCP connection is possible. -
timed out= Blocked by firewall or network routing. -
refused= Host is reachable, but the port is actively closed or filtered to reject.
3) Confirm SMTP Banner + STARTTLS Advertisement (587 / 25 / 2525)
3.1 Banner test (Should return a line starting with 220):
Bash
nc -v -w 5 "$SMTP_HOST" 587
3.2 EHLO capability check (Look for 250-STARTTLS in the response):
Bash
# Port 587
printf 'EHLO test.local\r\nQUIT\r\n' | nc -v -w 5 "$SMTP_HOST" 587
# Port 25
printf 'EHLO test.local\r\nQUIT\r\n' | nc -v -w 5 "$SMTP_HOST" 25
# Port 2525
printf 'EHLO test.local\r\nQUIT\r\n' | nc -v -w 5 "$SMTP_HOST" 2525Interpretation: If the EHLO response includes
STARTTLS, that port supports upgrading to secure TLS. IfSTARTTLSis missing, a proxy or network interceptor is stripping capabilities.
4) Verify TLS Negotiation (Cert/Handshake)
4.1 STARTTLS on 587 (Recommended):
Bash
openssl s_client -starttls smtp \
-connect "$SMTP_HOST:587" \
-servername "$SMTP_HOST" \
-crlf -showcerts4.2 STARTTLS on 25 and 2525:
Bash
openssl s_client -starttls smtp \
-connect "$SMTP_HOST:25" \
-servername "$SMTP_HOST" \
-crlf -showcerts
openssl s_client -starttls smtp \
-connect "$SMTP_HOST:2525" \
-servername "$SMTP_HOST" \
-crlf -showcerts4.3 Implicit TLS (SSL) on 465:
Bash
openssl s_client \
-connect "$SMTP_HOST:465" \
-servername "$SMTP_HOST" \
-crlf -showcertsInterpretation: Successful TLS handshakes usually conclude with
Verify return code: 0 (ok). Error messages likehandshake failure,wrong version number, or sudden disconnects point to local TLS inspection devices or network proxy interception.
macOS: “Send this to Support” diagnostic bundle
If any network step fails, paste this block into your terminal to output a diagnostic file to attach to your support ticket:
Bash
SMTP_HOST="smtp.sendgrid.net"
OUT="smtp_diagnostics_$(date +%Y%m%d_%H%M%S).txt"
{
echo "### Timestamp"
date
echo
echo "### Host"
echo "$SMTP_HOST"
echo
echo "### macOS version"
sw_vers
echo
echo "### DNS (system resolver: dscacheutil)"
dscacheutil -q host -a name "$SMTP_HOST" || true
echo
echo "### DNS (default dig)"
dig +short "$SMTP_HOST" || true
echo
echo "### DNS (public resolvers)"
echo "-- 1.1.1.1 --"
dig @1.1.1.1 +short "$SMTP_HOST" || true
echo "-- 8.8.8.8 --"
dig @8.8.8.8 +short "$SMTP_HOST" || true
echo
echo "### Port reachability (nc)"
for p in 587 25 2525 465; do
echo "-- port $p --"
nc -vz -w 3 "$SMTP_HOST" "$p" 2>&1 || true
done
echo
echo "### EHLO capability checks (look for STARTTLS)"
for p in 587 25 2525; do
echo "-- EHLO on port $p --"
printf 'EHLO test.local\r\nQUIT\r\n' | nc -v -w 5 "$SMTP_HOST" "$p" 2>&1 || true
echo
done
echo "### TLS handshake tests (openssl)"
echo "-- STARTTLS 587 --"
openssl s_client -starttls smtp -connect "$SMTP_HOST:587" -servername "$SMTP_HOST" -crlf 2>&1 </dev/null || true
echo
echo "-- STARTTLS 2525 --"
openssl s_client -starttls smtp -connect "$SMTP_HOST:2525" -servername "$SMTP_HOST" -crlf 2>&1 </dev/null || true
echo
echo "-- TLS 465 --"
openssl s_client -connect "$SMTP_HOST:465" -servername "$SMTP_HOST" -crlf 2>&1 </dev/null || true
echo
} | tee "$OUT"
echo
echo "Saved diagnostics to: $OUT"3. Network Connectivity Verification (Windows 10/11)
Open PowerShell (do not use CMD) and set the host globally before proceeding:
PowerShell
$SMTP_HOST = "smtp.sendgrid.net"1) DNS Resolution (System vs. Public)
Check what Windows is resolving locally:
PowerShell
Resolve-DnsName $SMTP_HOSTCompare with public DNS (Bypasses VPN/Corporate DNS rewriting):
PowerShell
nslookup $SMTP_HOST 1.1.1.1
nslookup $SMTP_HOST 8.8.8.8Show what DNS servers your current adapters are utilizing:
PowerShell
Get-DnsClientServerAddress -AddressFamily IPv4Red Flags: If system resolution returns private/CGNAT ranges (e.g.,
10.x,192.168.x,172.16-31.x,100.64.x) but public DNS returns public routing IPs, your network environment or active VPN is manipulating DNS traffic.
2) Port Reachability
Verify open outbound TCP paths directly to the endpoint:
PowerShell
587,25,2525,465 | ForEach-Object { Test-NetConnection -ComputerName $SMTP_HOST -Port $_ | Select-Object ComputerName,RemoteAddress,RemotePort,TcpTestSucceeded }-
TcpTestSucceeded : True= Reachable port. -
TcpTestSucceeded : False= Firewalled or blocked on this network.
3) Read the SMTP Banner + Confirm STARTTLS Advertisement
Paste this custom verification function into your PowerShell window to parse the capabilities structure:
PowerShell
function Test-SmtpEhlo {
param(
[Parameter(Mandatory=$true)][string]$Host,
[Parameter(Mandatory=$true)][int]$Port
)
$client = New-Object System.Net.Sockets.TcpClient
$client.ReceiveTimeout = 8000
$client.SendTimeout = 8000
$client.Connect($Host, $Port)
$stream = $client.GetStream()
$reader = New-Object System.IO.StreamReader($stream, [System.Text.Encoding]::ASCII)
$writer = New-Object System.IO.StreamWriter($stream, [System.Text.Encoding]::ASCII)
$writer.NewLine = "`r`n"
$writer.AutoFlush = $true
$banner = $reader.ReadLine()
"BANNER: $banner"
$writer.WriteLine("EHLO test.local")
$lines = @()
$line = $reader.ReadLine()
$lines += $line
while ($line -match '^250-') {
$line = $reader.ReadLine()
$lines += $line
}
"EHLO RESPONSE:"
$lines | ForEach-Object { " $_" }
if ($lines -match 'STARTTLS') {
"STARTTLS: ADVERTISED"
} else {
"STARTTLS: NOT ADVERTISED"
}
$writer.WriteLine("QUIT")
$client.Close()
}Run the functional check across valid STARTTLS ports:
PowerShell
Test-SmtpEhlo -Host $SMTP_HOST -Port 587
Test-SmtpEhlo -Host $SMTP_HOST -Port 25
Test-SmtpEhlo -Host $SMTP_HOST -Port 2525Look for STARTTLS: ADVERTISED. If missing, security capability stripping is occurring locally.
4) TLS Handshake Verification
Option A: OpenSSL (If available via Git for Windows or system binaries)
PowerShell
# STARTTLS (587 / 25 / 2525)
openssl s_client -starttls smtp -connect "$SMTP_HOST:587" -servername $SMTP_HOST -crlf -showcerts
openssl s_client -starttls smtp -connect "$SMTP_HOST:2525" -servername $SMTP_HOST -crlf -showcerts
openssl s_client -starttls smtp -connect "$SMTP_HOST:25" -servername $SMTP_HOST -crlf -showcerts
# Implicit TLS (465)
openssl s_client -connect "$SMTP_HOST:465" -servername $SMTP_HOST -crlf -showcertsOption B: Built-in cURL (Available on modern Windows builds)
Execute verbose validation using native curl pipes to monitor handshakes:
PowerShell
# STARTTLS on 587
"Subject: tls-test`r`n`r`nTest" | curl -v --url "smtp://$SMTP_HOST:587" --ssl-reqd --mail-from "<test@example.com>" --mail-rcpt "<test@example.com>" --upload-file -
# Implicit TLS on 465
"Subject: tls-test`r`n`r`nTest" | curl -v --url "smtps://$SMTP_HOST:465" --mail-from "<test@example.com>" --mail-rcpt "<test@example.com>" --upload-file -Windows: “Send this to Support” diagnostic bundle
Copy and paste this unified command block into PowerShell to instantly compile a smtp_diagnostics.txt log onto your Desktop:
PowerShell
$SMTP_HOST = "smtp.sendgrid.net"
$TS = Get-Date -Format "yyyyMMdd_HHmmss"
$OUT = "$env:USERPROFILE\Desktop\smtp_diagnostics_$TS.txt"
Start-Transcript -Path $OUT | Out-Null
"### Timestamp"
Get-Date
""
"### Host"
$SMTP_HOST
""
"### Windows version"
cmd /c ver
""
"### Adapter DNS servers"
Get-DnsClientServerAddress -AddressFamily IPv4 | Format-List
""
"### DNS resolution (system)"
try { Resolve-DnsName $SMTP_HOST | Format-List } catch { $_.Exception.Message }
""
"### DNS resolution (public resolvers)"
"--- 1.1.1.1 ---"
nslookup $SMTP_HOST 1.1.1.1
"--- 8.8.8.8 ---"
nslookup $SMTP_HOST 8.8.8.8
""
"### Port reachability (Test-NetConnection)"
foreach ($p in 587,25,2525,465) {
"== Port $p =="
Test-NetConnection -ComputerName $SMTP_HOST -Port $p | Select-Object ComputerName,RemoteAddress,RemotePort,TcpTestSucceeded | Format-List
}
""
"### EHLO capability checks (look for STARTTLS)"
function Test-SmtpEhlo {
param([string]$Host,[int]$Port)
$client = New-Object System.Net.Sockets.TcpClient
$client.ReceiveTimeout = 8000
$client.SendTimeout = 8000
$client.Connect($Host, $Port)
$stream = $client.GetStream()
$reader = New-Object System.IO.StreamReader($stream, [System.Text.Encoding]::ASCII)
$writer = New-Object System.IO.StreamWriter($stream, [System.Text.Encoding]::ASCII)
$writer.NewLine = "`r`n"
$writer.AutoFlush = $true
$banner = $reader.ReadLine()
"BANNER: $banner"
$writer.WriteLine("EHLO test.local")
$lines = @()
$line = $reader.ReadLine()
$lines += $line
while ($line -match '^250-') {
$line = $reader.ReadLine()
$lines += $line
}
"EHLO RESPONSE:"
$lines | ForEach-Object { " $_" }
if ($lines -match 'STARTTLS') { "STARTTLS: ADVERTISED" } else { "STARTTLS: NOT ADVERTISED" }
$writer.WriteLine("QUIT")
$client.Close()
}
foreach ($p in 587,25,2525) {
""
"== EHLO on port $p =="
try { Test-SmtpEhlo -Host $SMTP_HOST -Port $p } catch { $_.Exception.Message }
}
""
"### Optional: OpenSSL tests (if OpenSSL is installed)"
$openssl = Get-Command openssl -ErrorAction SilentlyContinue
if ($openssl) {
"OpenSSL found at: $($openssl.Path)"
""
"== openssl STARTTLS 587 =="
cmd /c "openssl s_client -starttls smtp -connect $SMTP_HOST:587 -servername $SMTP_HOST -crlf < NUL"
""
"== openssl STARTTLS 2525 =="
cmd /c "openssl s_client -starttls smtp -connect $SMTP_HOST:2525 -servername $SMTP_HOST -crlf < NUL"
""
"== openssl TLS 465 =="
cmd /c "openssl s_client -connect $SMTP_HOST:465 -servername $SMTP_HOST -crlf < NUL"
} else {
"OpenSSL not found in PATH. (If needed, install OpenSSL or run from Git Bash/WSL.)"
}
Stop-Transcript | Out-Null
"Saved diagnostics to: $OUT"4. Review Email Headers
If network connectivity checks return clean results, the latency is likely introduced after the email has departed SendGrid's servers, or while it sits in the recipient's intake queue. You can use email headers to locate exactly who to blame for the mail lag.
- Grab the raw header source configuration of the delayed message. Make sure you select everything above the primary content boundary block.
- Paste the source text into a free utility like Google's Admin Toolbox Message header analyzer.
- Review the parsed path calculation. The table will identify the exact entry/exit timestamps across all involved Mail Transfer Agents (MTAs), determining if the message sat at a specific relay or provider.
5. Packet Capture & Analysis
In cases where basic network paths succeed but protocol exchanges stall mysteriously, a packet-level trace reveals deeper infrastructure issues. The Twilio SendGrid support team may ask you for a Packet Capture (PCAP) to give us better visibility.
- Run a packet capture using tools like Wireshark or command-line interfaces like
tcpdump. - Make sure that the PCAP covers an exclusive attempt to send a single message payload targeting
smtp.sendgrid.net. - Analyze the capture output to observe structural protocol fragmentation, unexpected resets (RST packets), or missing TLS acknowledgement payloads.How to Interpret Your Results (macOS + Windows)
How to Interpret Your Results (macOS + Windows)
| What You See | What it Means | What to Try Next |
|---|---|---|
Your computer resolves the SMTP hostname to a private/internal IP (10.x, 192.168.x, 172.16-31.x, 100.64.x) but public DNS resolves to public IPs.
|
Your network (often VPN/corporate Wi-Fi) is rewriting DNS or routing SMTP through an internal relay/proxy. | Disconnect the VPN and retry, or try a different network (mobile hotspot). If you must stay on the corporate network, ask your network team to allow direct SMTP access to the host. |
| Port 587 fails (timeout / not reachable) but 2525 works. | Your network blocks port 587. | Use port 2525 with STARTTLS configuration. |
| Port 25 fails but 587/2525 work. | Port 25 is actively blocked by your ISP or network infrastructure policies. | Use port 587 (recommended) or port 2525. |
| All ports fail (25, 465, 587, 2525 all time out / not reachable). | Outbound SMTP is entirely blocked from your current network environment. | Try another network. If it works elsewhere, ask your network admin or ISP to allow outbound TCP traffic to the supported ports. |
Connection succeeds, but you do not receive an SMTP banner (no line starting with 220) or it disconnects instantly.
|
You may not be reaching an authentic SMTP server (DNS issue), or a firewall/proxy is interrupting the connection payload. | Re-check DNS results, test off your VPN, and switch to alternative ports like 2525 or 465. |
EHLO output does not include STARTTLS on 587, 25, or 2525.
|
STARTTLS is unavailable on that connection path, or a middlebox device is stripping security advertisements. | Try port 465 (Implicit SSL/TLS), or change networks/disable VPN and retest. Ask your network administrator if outbound SMTP traffic is being proxied or inspected. |
OpenSSL outputs Didn’t find STARTTLS in server response.
|
The server did not offer STARTTLS, so the secure TLS upgrade handshake cannot proceed. | Confirm capability via the EHLO script test, then try ports 2525 or 465. |
TLS handshake errors occur (e.g., handshake failure, wrong version number).
|
Incorrect TLS method mapping for the selected port, or active network inspection interference. | Ensure you are using: STARTTLS on ports 587/25/2525, and implicit TLS on port 465. If correct and it still fails, try another network/disable VPN. |
| Port 465 works, but STARTTLS on 587/2525 fails. | The network allows raw TLS pipes to 465 but inspects/interferes with step-up STARTTLS commands. | Configure your application to use port 465 from that network, or work with your network admin to allow clean STARTTLS pass-through on port 587/2525. |
TLS completes successfully, but returns errors like 530 Authentication required or 535 Authentication failed.
|
Network connectivity is perfect. This is an authentication, credential format, or account configuration issue. | Verify your username, password, or API key format, authentication method, and account permissions. |
What to Send Support
Please attach the generated output log file (smtp_diagnostics_*.txt from the Windows or macOS step) directly to your support ticket, and explicitly include:
- Whether you were on a VPN or corporate network when executing the diagnostic tasks.
- Your approximate geographic location and Internet Service Provider (ISP) to help isolate regional routing blocks.
- Which specific ports successfully connected versus those that timed out or were refused.
CRITICAL SECURITY NOTE: Do not include SMTP passwords, account API keys, or raw message body contents within your ticket description or attachments. Ensure all credentials are omitted before submission.