Expected response code 220 but got code "", with message "" in Laravel
Stefan Bogdanescu
Founder & Senior Architect
Resolving Swift_TransportException: Expected response code 220 but got code "", with message "" in Laravel Mail
Sending emails reliably is a cornerstone of almost any application. When using Laravel's powerful Mail system, developers often encounter frustrating transport exceptions, especially when dealing with external SMTP services like Gmail. The error you are seeing—Swift_TransportException: Expected response code 220 but got code "", with message ""—is a generic signal that the underlying mail transport mechanism failed to establish a proper connection or receive the expected server handshake response from the mail server.
As a senior developer, I can tell you that this error is rarely about your view file content; it almost always points to an issue in the configuration, authentication, or network connectivity between your Laravel application and the SMTP server. Let's dive into why this happens and how we fix it.
Understanding the Transport Error
The response code 220 is a standard response from an SMTP (Simple Mail Transfer Protocol) server, indicating that the server is ready to accept commands. When your application expects 220 but receives an empty response (""), it means the connection was established, but the initial handshake or authentication failed immediately upon sending the command. This usually signifies one of the following problems:
- Authentication Failure: The username or password provided is incorrect, or two-factor authentication (2FA) is blocking the login attempt.
- Incorrect Port/Encryption: The port or encryption method (
tls) configured does not match what the server expects for that connection. - Server Rejection: The mail server (like Gmail) explicitly rejected the connection due to security policies, resulting in a silent failure from the transport layer.
Troubleshooting Your Laravel Mail Setup
Based on your provided configuration snippet, there are two main areas we need to scrutinize: the driver choice and the credentials.
1. Re-evaluating the Mail Driver
Your configuration specifies 'driver' => 'sendmail'. While this is a valid transport method on a Linux server, when connecting to external services like smtp.gmail.com, the standard and most robust approach in Laravel is to use the built-in SMTP driver. Using a custom or generic sendmail setup often bypasses Laravel’s specific error handling for SMTP connection issues.
Recommendation: Switch your configuration to use the standard smtp driver, as this allows Laravel to utilize its integrated error handling and logging features, which are crucial when debugging transport layer problems.
2. Fixing Authentication Issues (The Gmail Specific Fix)
If you are using a service like Gmail, the most common culprit is authentication related. Standard account passwords often fail when used directly with external applications due to Google's security protocols.
Best Practice for Gmail/Google Workspace: Instead of using your regular account password, you must generate an App Password. You need to enable 2-Factor Authentication (2FA) on your Google account, and then go into your Google Security settings to generate a unique 16-character password specifically for applications. This App Password should be used in place of your regular account password in the Laravel configuration.
Corrected Configuration Example
Here is how you should structure your config/mail.php file to resolve this error:
'driver' => 'smtp', // Change driver to use standard SMTP
'host' => 'smtp.gmail.com',
'port' => 587,
'encryption' => 'tls',
'username' => 'your_gmail_address@gmail.com', // Use your full email as the username
'password' => env('MAIL_PASSWORD'), // Always use environment variables!
'from' => array('address' => 'your_gmail_address@gmail.com', 'name' => 'MyName'),
'sendmail' => null, // Remove or set to null if using SMTP driver
'pretend' => false,
Crucial Note: Ensure your .env file securely holds these values:
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_ENCRYPTION=tls
MAIL_USERNAME=your_app_password@gmail.com
MAIL_PASSWORD=YOUR_GENERATED_APP_PASSWORD # Use the App Password here
Conclusion: Building Robust Email Infrastructure
The Swift_TransportException is a signal that the communication channel failed at the protocol level, not necessarily in your application logic. By diagnosing the issue as an authentication or configuration mismatch and switching to Laravel's standard SMTP setup while ensuring you are using properly generated App Passwords for services like Gmail, you move from guessing fixes to implementing robust, maintainable code.
Always remember that when building scalable applications, leveraging established frameworks like those found on laravelcompany.com ensures you utilize the best practices for handling complex external integrations. Debugging transport layers requires checking both your application settings and the external service's security requirements.