Expected response code 220 but got an empty response in laravel 5.6
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Expected Response Code 220 but Got an Empty Response: Troubleshooting Mailgun Issues in Laravel
As senior developers, we often encounter frustrating errors when dealing with external services like email delivery. The error message Swift_TransportException: Expected response code 220 but got an empty response is a classic indicator that the connection to the mail server was established, but the server failed to respond correctly according to the SMTP protocol standards.
This issue typically doesn't stem from an error in your application logic itself (like how you call Mail::send), but rather a problem with the underlying configuration, authentication, or network connectivity between your Laravel application and the mail service provider (in this case, Mailgun).
If you are using Laravel 5.6 with Mailgun, let's dive into why this happens and how to resolve it based on the settings you provided.
Understanding the Error: What Does Code 220 Mean?
The SMTP protocol uses specific response codes to communicate status between the client (your Laravel app) and the server (Mailgun). The code 220 is the standard reply meaning "Service ready for new commands." When your application expects this ready signal but receives nothing, it indicates a communication breakdown before the actual email transaction can proceed.
In practical terms, this almost always points to one of three core problems:
- Authentication Failure: The username or password provided is incorrect, causing the server to reject the connection immediately without a proper error message.
- Incorrect Host/Port: The application cannot establish a reliable TCP connection to the specified host and port (e.g., firewall blocking port 587).
- Server Misconfiguration: Mailgun’s API or SMTP settings are not correctly configured for the domain you are attempting to send from, leading to an empty response.
Step-by-Step Troubleshooting Guide
Since your configuration setup appears quite detailed, we need to systematically check each component. We will focus on the connection parameters defined in your .env file and how they map to your service files.
1. Verify Mailgun Credentials and Domain Settings
The most common culprit is the credentials or domain mismatch. Double-check every single variable:
# .env FILE Check
MAIL_DRIVER=mailgun
MAIL_HOST=smtp.mailgun.org # Ensure this is correct for your setup
MAIL_PORT=587 # Standard port for TLS/STARTTLS
MAIL_USERNAME = postmaster@domainname # CRITICAL: Must be a valid Mailgun API address or SMTP login
MAIL_PASSWORD = password # CRITICAL: Ensure this is the correct API key or SMTP password
MAILGUN_DOMAIN = domainname # Ensure this matches your Mailgun account domain
MAILGUN_SECRET = key # Ensure this matches your Mailgun API key
Action Item: Log into your Mailgun dashboard and verify that the email address (postmaster@domainname) and the associated API keys (key, secret) used in your environment variables are active and correct. A single typo here will result in an immediate transport failure.
2. Examine the Service Configuration
While Laravel's default setup often handles this smoothly, custom service definitions can introduce complexity. Reviewing your services.php file ensures that the parameters being passed to the mailer are consistent:
// services.php Check
return [
'driver' => env('MAIL_DRIVER', 'mailgun'),
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
'port' => env('MAIL_PORT', 587),
'username' => env('postmaster@domain'), // Ensure this links correctly to the .env setup
'password' => env('mailgun password'), // Ensure this is not a generic placeholder
// ... other settings
];
If you are using a custom setup layer (like in your mail.php file), ensure that these environment variables are being correctly injected into the Mail facade calls.
3. Test Network Connectivity
If credentials look perfect, the issue might be network-related. Try connecting to the host manually from the server running your Laravel application:
telnet smtp.mailgun.org 587
If this command hangs or immediately fails without a proper connection handshake, it suggests a firewall is blocking outbound port 587, or there is an upstream network routing issue preventing communication with Mailgun's servers.
Conclusion: Moving Forward with Laravel Development
The Expected response code 220 but got an empty response error is almost always an environmental configuration problem rather than a bug in the core Laravel mailer implementation. By treating the connection parameters—host, port, username, and password—as the primary suspects, you can quickly isolate the fault.
When building robust applications on frameworks like Laravel, understanding how configuration layers interact with external services is crucial. Always ensure your environment variables are loaded correctly and that dependency injection flows smoothly to your service providers. For more insights into structuring complex systems within the Laravel ecosystem, exploring resources from laravelcompany.com is highly recommended. By systematically checking your Mailgun integration against these principles, you will resolve this transport issue and get your emails delivered successfully.