Part of the guide: Laravel on cPanel & Shared Hosting: The Complete Guide
Laravel SMTP on cPanel: Fix 530, 535 & TLS Errors
Your Laravel application works on XAMPP, but after deploying it to cPanel, the first password reset email fails with Connection could not be established with host. Sometimes you get 535 Incorrect authentication data, Expected response code "250" but got code "530", or an SSL certificate verification error.
If Laravel SMTP on cPanel is failing, the quickest fix is to check the outgoing mail server shown in cPanel, match the SMTP port with the correct encryption scheme, confirm the mailbox credentials and clear Laravel's cached configuration.
Most SMTP failures fall into one of five areas: connectivity, encryption, authentication, configuration or message delivery. The actual error tells you which one to investigate.
Quick answer: Open cPanel → Email Accounts → Connect Devices, locate the outgoing SMTP hostname, and use the secure settings provided for your mailbox. For a typical modern Laravel installation, use port 465 with MAIL_SCHEME=smtps, or port 587 with MAIL_SCHEME=smtp and STARTTLS. Use the complete mailbox address as the username, clear the configuration cache, and send a test email through Laravel Tinker.
Do not disable SSL certificate verification to make SMTP work. A certificate error usually means the connection needs a different hostname or the mail server's certificate needs repair.
1. Laravel SMTP on cPanel: identify the error
Laravel uses Symfony Mailer to communicate with SMTP servers. That means the exception can come from several different stages of the connection.
Before changing your .env, read the full error message.
| Error message | Likely cause | What to check |
|---|---|---|
Connection could not be established with host | Network, hostname, port or TLS problem | SMTP host, port and hosting firewall |
Connection timed out | The server cannot complete a connection | DNS resolution, outbound SMTP restrictions or unreachable server |
Connection refused | The destination rejected the TCP connection | Wrong port, SMTP service stopped or connection restrictions |
SSL routines: wrong version number | TLS protocol mismatch | Whether the port expects implicit TLS or STARTTLS |
certificate verify failed | Certificate trust, expiry or hostname issue | Certificate chain and SMTP hostname |
Peer certificate CN did not match | Certificate name does not match MAIL_HOST | Use a hostname covered by the certificate |
Expected response code "250" but got code "530" | Server requires authentication or another prerequisite | Read the complete SMTP response, including whether STARTTLS is required |
535 Incorrect authentication data | Authentication rejected | Mailbox username, password or account restrictions |
The "" scheme is not supported | Older Laravel/Symfony compatibility problem | Installed versions and SMTP scheme configuration |
What does each error actually mean?
Connection timed out
Laravel attempted to contact the SMTP server but did not complete the connection within the configured timeout.
Possible reasons include an incorrect hostname, blocked outbound ports, DNS failures or an unreachable server.
Changing the mailbox password will not fix a network timeout.
Connection refused
The destination actively rejected the connection. For example, the application might still be using a development SMTP address such as 127.0.0.1:2525 even though no SMTP listener exists there.
Check the resolved mail configuration rather than assuming Laravel loaded your latest .env.
SSL wrong version number
This commonly happens when an application starts an encrypted TLS connection on a port expecting an ordinary SMTP greeting, or the reverse.
A typical example is combining MAIL_SCHEME=smtps with port 587.
530 authentication or STARTTLS required
A 530 response is not always a missing username.
Depending on the SMTP server, it may indicate that authentication is required or that STARTTLS must be completed first.
Read the entire SMTP reply before deciding which setting to change.
535 authentication failed
The server received an authentication attempt but rejected it.
The username, password, authentication policy or mailbox status needs investigation.
No exception, but no email
Check the active mailer.
Modern Laravel application templates use log as the fallback mailer in config/mail.php. If MAIL_MAILER is absent and no other configuration overrides that default, messages may be written to the application's configured log channel rather than sent.
Also check whether the email was queued instead of dispatched immediately.
2. Find the SMTP hostname and configure Laravel .env
Do not guess the outgoing mail server.
A common mistake is assuming mail.example.com must be correct because the application's domain is example.com.
The website, DNS and mailbox may be hosted on different servers.
Step 1: Get the actual SMTP settings from cPanel
- Log in to cPanel.
- Open Email → Email Accounts.
- Find the mailbox Laravel will use, such as
noreply@example.com. - Click Connect Devices.
- Locate Mail Client Manual Settings.
- Review Secure SSL/TLS Settings (Recommended).
- Copy the outgoing SMTP server, port and username.
For a standard cPanel-managed mailbox, the documented secure SMTP port is 465.
cPanel also documents port 587 under its non-SSL client settings. On servers supporting STARTTLS, port 587 can still establish an encrypted connection after the initial SMTP greeting. You should confirm that your server advertises STARTTLS and supports the required authentication method.
The correct hostname may be your mail subdomain or the hosting server's own hostname.
If your email is hosted externally, such as with Google Workspace, Microsoft 365 or Zoho, use that provider's SMTP settings instead of assuming the cPanel server handles your mailbox.
Step 2: Configure port 465 using implicit TLS
Open your application's .env file.
For Laravel installations whose SMTP configuration reads MAIL_SCHEME, use:
MAIL_MAILER=smtp
MAIL_SCHEME=smtps
MAIL_HOST=mail.example.com
MAIL_PORT=465
MAIL_USERNAME=noreply@example.com
MAIL_PASSWORD="your-mailbox-password"
MAIL_FROM_ADDRESS="noreply@example.com"
MAIL_FROM_NAME="${APP_NAME}"
Replace the example hostname, address and password with your actual mailbox details.
How it works: smtps establishes a TLS-encrypted connection immediately, before normal SMTP commands are exchanged.
That matches the standard behavior of port 465.
Avoid adding ssl:// to MAIL_HOST. Put the plain hostname in that setting and let the mail transport handle encryption.
Step 3: Configure port 587 using STARTTLS
If your provider specifically supports SMTP submission on port 587, use:
MAIL_MAILER=smtp
MAIL_SCHEME=smtp
MAIL_HOST=mail.example.com
MAIL_PORT=587
MAIL_USERNAME=noreply@example.com
MAIL_PASSWORD="your-mailbox-password"
MAIL_FROM_ADDRESS="noreply@example.com"
MAIL_FROM_NAME="${APP_NAME}"
With the smtp scheme, Symfony Mailer normally upgrades the connection using STARTTLS when the server advertises that capability and the required PHP OpenSSL support is available.
There is one security detail that often gets overlooked.
Automatic STARTTLS is not the same as requiring TLS.
If the server does not advertise STARTTLS, a normal SMTP transport may continue without encryption unless configured to require TLS.
Do not send production mailbox credentials over an unencrypted Internet connection. If STARTTLS is missing or broken, investigate the server configuration rather than disabling encryption.
For most standard cPanel setups, port 465 with a valid certificate is a straightforward choice.
Step 4: Understand MAIL_SCHEME versus MAIL_ENCRYPTION
Older Laravel projects commonly contain:
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
Modern Laravel application templates instead use:
'scheme' => env('MAIL_SCHEME'),
Laravel 12 and 13 application templates use MAIL_SCHEME, and current Laravel 11 templates also include it.
Modern Laravel framework code uses the explicit scheme when provided. Otherwise, it normally selects smtps for port 465 and smtp for other ports.
Symfony Mailer does not interpret the old encryption configuration value as the effective SMTP transport scheme.
Therefore, changing:
MAIL_ENCRYPTION=ssl
to:
MAIL_ENCRYPTION=tls
is not a reliable solution for modern Laravel applications.
Important: Updating the Laravel framework does not necessarily replace the config/mail.php file in an existing application.
Check the actual configuration file before assuming that MAIL_SCHEME is supported.
For older projects, follow the installed framework's requirements rather than copying settings from a newer skeleton without checking compatibility.
A related Laravel 11 compatibility issue occurred when Symfony Mailer 7.2 rejected an empty SMTP scheme. If you encounter The "" scheme is not supported, inspect the installed dependency versions and apply a compatible framework update.
Do not force a Composer dependency change directly on production without testing it first.
Step 5: Check passwords and MAIL_URL
Mailbox passwords sometimes contain symbols that need careful handling in environment files.
For passwords containing spaces or characters such as #, wrapping the value in double quotes helps prevent incorrect parsing:
MAIL_PASSWORD="Example#Password 2026"
If your actual password contains characters requiring special handling by the dotenv parser, follow that parser's escaping rules.
Do not put real passwords into screenshots, support tickets or published error logs.
Also look for:
MAIL_URL=
The standard Laravel SMTP configuration supports a mail transport URL, which can override individual connection details.
If you are configuring the mailer using separate host, port and credential fields, remove an obsolete MAIL_URL value rather than leaving a conflicting connection string.
When using a URL-style configuration, reserved characters in usernames and passwords must be percent-encoded.
For example, @ becomes %40.
Step 6: Clear Laravel's cached configuration
After editing .env, run the following commands from the Laravel project root:
php artisan config:clear
This removes Laravel's cached configuration so the application can read the updated settings.
If your normal deployment process uses cached configuration, rebuild it:
php artisan config:cache
Do not run config:cache until you have confirmed the environment values are correct.
For persistent queue workers, run:
php artisan queue:restart
This asks existing workers to exit gracefully after their current job. A process manager must restart them, or mail jobs will stop being processed.
The Laravel queue restart signal also depends on the application's cache configuration.
For more deployment checks, see Deploy Laravel on cPanel: Step-by-Step Checklist.
3. Fix MAIL_HOST and SSL certificate errors
A correct mailbox password cannot solve a certificate hostname mismatch.
When Symfony Mailer establishes a secure SMTP connection, PHP normally verifies the server's certificate.
That includes checking whether the hostname matches an identity listed in the certificate.
Consider these common SMTP hostname choices:
| MAIL_HOST value | When it may work | Potential problem |
|---|---|---|
localhost | Local mail service configured on the same machine | Certificate identity may not match |
127.0.0.1 | Local server with specifically configured transport | IP certificate mismatch or no SMTP service |
mail.example.com | DNS points to the correct server and certificate covers that name | Missing, expired or incorrect certificate |
server123.host.com | Hosting server presents a trusted certificate covering this name | The server may still present a different certificate |
| Server IP address | Special configurations with valid IP certificate coverage | Most ordinary shared-hosting certificates do not cover the IP |
A hosting server's own hostname is often the easiest solution when cPanel recommends it.
However, the hostname must still resolve correctly and match a valid certificate presented by the SMTP service.
It is not safe to assume that every server hostname always passes certificate verification.
Verify the SMTP certificate using OpenSSL
If OpenSSL is installed on your computer or hosting server, test port 465 using:
openssl s_client -connect mail.example.com:465 -servername mail.example.com -verify_hostname mail.example.com -verify_return_error -brief
Replace mail.example.com with the outgoing server you intend to use.
The command attempts a TLS connection and checks the certificate against that hostname.
A successful test should report successful certificate verification.
If the certificate has expired, the chain cannot be trusted or the hostname is wrong, the output should help identify the problem.
For port 587, test STARTTLS instead:
openssl s_client -starttls smtp -connect mail.example.com:587 -servername mail.example.com -verify_hostname mail.example.com -verify_return_error -brief
This tells OpenSSL to perform the SMTP STARTTLS negotiation before validating the certificate.
Run these tests against the same SMTP hostname your Laravel application uses.
A passing certificate test from your laptop does not prove that outbound SMTP is available from the hosting server. Network restrictions can differ.
Also, checking only the certificate's Common Name is insufficient because valid certificate identities may be listed in the Subject Alternative Name extension.
Fix the certificate rather than disabling verification
If the certificate does not match mail.example.com, check the outgoing server displayed in cPanel's Connect Devices interface.
If it recommends the server hostname and that hostname has a valid certificate, use it.
If you control the mail service, repair or renew the certificate and ensure the SMTP server presents the correct one.
If your hosting provider controls it, ask support to verify the SMTP TLS certificate and hostname.
Some online fixes suggest:
'verify_peer' => false,
Avoid this as a production workaround.
Disabling peer verification weakens the protection that confirms you are communicating with the intended mail server.
Symfony's documentation treats disabled peer verification as an exceptional development or testing option, not the recommended production configuration.
4. Fix SMTP 530 and 535 authentication failures
Once the network and TLS connection work, the next possible failure is SMTP authentication.
Fix 530: authentication required
For a 530 response, begin by reading the full server message.
If it explicitly requires authentication, confirm that your mailbox credentials are populated.
Open Laravel Tinker:
php artisan tinker
Then inspect the mail configuration without printing the password:
config('mail.default');
config('mail.mailers.smtp.host');
config('mail.mailers.smtp.port');
config('mail.mailers.smtp.scheme');
config('mail.mailers.smtp.username');
These commands show the values Laravel is actually using.
Expected values for the port 465 example include:
smtp
mail.example.com
465
smtps
noreply@example.com
If the active username is null, investigate the .env key, cached configuration and contents of config/mail.php.
A null scheme can be normal when the framework infers the scheme from the port. Check the actual framework behavior before treating that alone as an error.
If the server's complete 530 response says STARTTLS is required, inspect TLS negotiation first. Adding a username will not resolve a missing STARTTLS handshake.
Fix 535: incorrect authentication data
A 535 response means the mail server rejected authentication.
Check the following:
1. Use the complete mailbox address
For a typical cPanel mailbox:
MAIL_USERNAME=noreply@example.com
Do not use the cPanel account login or only the part before @.
2. Use the mailbox password
The cPanel login password and individual mailbox password are not necessarily the same.
Open Email Accounts → Manage and reset the mailbox password if needed.
Update .env and clear the configuration cache afterward.
3. Check account restrictions
Hosting providers may temporarily block authentication attempts after repeated failures.
Some external email providers also require app passwords, OAuth-based authentication or other provider-specific authorization.
A valid password alone may not be sufficient when ordinary SMTP authentication is disabled.
4. Check the sender address
For the simplest test, use the authenticated mailbox as the sender:
MAIL_FROM_ADDRESS="noreply@example.com"
Some SMTP servers enforce sender permissions or reject messages using unapproved addresses.
Other servers permit aliases or domain-specific sender identities.
If your provider supports aliases, the sender does not necessarily need to be a separate mailbox, but it must comply with the provider's policy.
5. Check whether the email service is hosted locally
A domain may use cPanel for its website while its email is handled by another provider.
Check the mailbox provider and relevant DNS records.
If the mailbox belongs to Microsoft 365, Google Workspace or another external platform, follow that provider's authentication and SMTP requirements.
The cPanel Email vs Google Workspace vs Zoho Mail comparison explains the differences between common hosting arrangements.
5. When SMTP is blocked: restrictions and sendmail
A perfectly configured Laravel mailer can still fail if the hosting environment prevents the required network connection.
This is especially relevant when attempting to contact an external SMTP service from shared hosting.
Check outbound SMTP restrictions
cPanel & WHM includes an SMTP Restrictions feature.
When enabled, the server can restrict which users or processes connect directly to remote SMTP servers.
This helps prevent compromised hosting accounts from sending spam through unauthorized mail services.
For example, an application attempting to connect to an external SMTP provider may time out even when its credentials and hostname are correct.
Other firewall rules can produce similar symptoms.
Ask your hosting provider:
- Does my hosting account permit outbound connections to the required SMTP host and port?
- Is SMTP Restrictions enabled?
- Can my application use the local mail service?
- Is the SMTP hostname reachable from the hosting server itself?
Do not assume a timeout proves the remote email provider is down.
Use the local sendmail transport when appropriate
Laravel also supports handing outgoing messages to the hosting server's local mail program.
For a Laravel installation using the standard sendmail transport configuration, an example is:
MAIL_MAILER=sendmail
MAIL_SENDMAIL_PATH="/usr/sbin/sendmail -bs -i"
MAIL_FROM_ADDRESS="noreply@example.com"
MAIL_FROM_NAME="${APP_NAME}"
The sendmail executable path shown here is the default used in standard Laravel 12 and 13 configuration files.
It may differ on other platforms or hosting environments.
This transport does not require an SMTP mailbox password because it communicates with the local mail program instead of authenticating to an external SMTP submission server.
However, that does not guarantee successful delivery.
Possible problems include:
- The hosting account cannot execute the sendmail binary.
- The local mail service is unavailable or misconfigured.
- The server enforces sender restrictions or message limits.
- SPF, DKIM, DMARC or server reputation affects delivery.
Use sendmail only if your provider supports it and your application is authorized to send through the local mail server.
It is not a universal workaround for every SMTP problem.
When an email API is a better choice
For applications sending important transactional notifications at scale, an HTTPS-based email API can be more suitable than SMTP.
Laravel supports several API-based transports.
These services may require separate credentials, provider packages and paid or limited plans.
Before switching, compare the service's authentication requirements, costs, limits and hosting compatibility.
For small Laravel applications already using a properly configured cPanel mailbox, SMTP may be sufficient.
For newsletters or high-volume delivery, check provider policies rather than relying on a shared-hosting mailbox.
6. Test SMTP delivery, Laravel queues and mail limits
Changing .env is not the final verification.
You need to confirm that Laravel can create a message, pass it to the configured transport and receive a successful response.
Step 1: Send an email using Laravel Tinker
From your Laravel project root, run:
php artisan tinker
Then execute:
\Illuminate\Support\Facades\Mail::raw(
'SMTP test from Laravel on cPanel',
function ($message) {
$message
->to('your-address@gmail.com')
->subject('Laravel SMTP Test');
}
);
Replace your-address@gmail.com with an email inbox you control.
This test sends a basic message directly through Laravel's configured mailer without depending on a password reset controller, Blade template or queued mailable.
If the command completes without an exception, the configured transport has accepted the send operation.
For SMTP, successful acceptance does not guarantee that the message reached the recipient's inbox.
Check the recipient inbox and spam folder.
If necessary, review your hosting provider's outgoing mail delivery logs.
Step 2: Test the log mailer separately
If you want to determine whether your Laravel application can generate messages without contacting SMTP, temporarily use:
MAIL_MAILER=log
Clear the configuration cache and send the test again.
The message should appear in the configured application logging channel, often in:
storage/logs/laravel.log
Your actual logging destination may differ depending on Laravel's logging configuration.
This test is useful for isolating application-level mail generation problems.
However, it cannot verify SMTP credentials, network access, TLS negotiation or remote delivery.
Restore:
MAIL_MAILER=smtp
and clear or rebuild the configuration cache before testing real SMTP again.
Step 3: Check queued emails
If your application sends mail through queued jobs, a working SMTP configuration alone is insufficient.
For example, a mailable implementing ShouldQueue or a call using ->queue() normally requires an operational queue backend and a worker.
The standard Laravel 12 queue configuration defaults to the database connection unless it has been changed.
Check the active queue connection:
php artisan tinker
Then:
config('queue.default');
If the result is database, verify that the required database tables exist and that the relevant migrations have been applied.
To process queued jobs manually, run:
php artisan queue:work --stop-when-empty --tries=3
This starts a worker, processes available jobs and exits once the queue becomes empty.
It is useful for testing or for short-lived execution environments.
For continuous production processing, Laravel generally expects a worker managed by a process supervisor.
On shared cPanel hosting, some sites instead use a cron job to launch a short-lived worker periodically.
If using cPanel Cron Jobs, configure the actual absolute paths to the PHP executable and Laravel artisan file. Use a suitable locking mechanism or an equivalent safeguard to prevent overlapping worker runs.
The Laravel scheduler can coordinate jobs, but merely creating a cron entry for schedule:run does not automatically run a queue worker unless a suitable scheduled worker command has been defined.
See Laravel schedule:run Not Working on cPanel? Fix It for the related cron troubleshooting steps.
Step 4: Inspect failed jobs
Run:
php artisan queue:failed
This lists recorded failed jobs when failed-job storage is configured.
The detailed exception may be available in the failed_jobs storage record and associated application logs.
Do not publish logs containing credentials or personal information.
Once the underlying SMTP problem is fixed, retry a specific failed job using its actual ID:
php artisan queue:retry YOUR_FAILED_JOB_ID
Replace YOUR_FAILED_JOB_ID with the identifier shown by Laravel.
Laravel also supports:
php artisan queue:retry all
But do not run this blindly on a production system.
Review failed jobs before retrying them, especially when they contain customer notifications, invoices, password reset messages or other time-sensitive content.
A message may have been accepted by the SMTP server before the application recorded a later failure.
Retrying such a job can potentially send a duplicate message.
For important workflows, use suitable idempotency or duplicate-prevention controls.
Step 5: Check cPanel hourly email limits
Even after SMTP authentication succeeds, delivery can be delayed or restricted by hosting limits.
WHM allows hosting administrators to set maximum outgoing email limits for domains.
The limit and behavior after reaching it depend on the hosting provider's configuration.
cPanel documentation explains that messages exceeding a configured limit may be accepted initially and then handled according to the server's queue-and-retry settings.
It is not correct to assume every excess message is always delivered later.
Some may be deferred or handled differently based on server policy.
If mail arrives late, ask your provider about the domain's hourly limit and mail queue.
Step 6: Verify SPF, DKIM and DMARC
If your test email reaches Gmail or Outlook but lands in spam, you are dealing with a different layer of the problem.
SMTP successfully transferring a message to a mail server does not guarantee inbox placement.
Check:
- SPF: Does DNS authorize the service sending email for your domain?
- DKIM: Is outgoing email signed with a valid signature?
- DMARC: Do your policies and message authentication align with the visible sender domain?
Also review the sending server's IP reputation and whether the configured From domain matches the service authorized to send.
The cPanel Emails Going to Spam: SPF, DKIM & DMARC Fix covers those checks in detail.
Final verification checklist
Before treating the SMTP issue as resolved, confirm:
| Test | Expected result |
|---|---|
| SMTP hostname | Matches the actual provider settings |
| Port and scheme | 465/smtps or supported 587/smtp with STARTTLS |
| Certificate verification | Valid, trusted certificate matching the hostname |
| SMTP credentials | Authentication succeeds |
| Laravel configuration | Updated values are loaded |
| Direct Tinker email | No transport exception |
| Queue processing | Pending mail jobs are processed |
| Recipient delivery | Test message arrives |
| SPF/DKIM/DMARC | Authentication records are correctly configured |
If direct Tinker mail works but password resets do not, investigate the password reset workflow, notification configuration and queues rather than changing SMTP settings again.
If Tinker fails with a transport exception, focus on that exception before debugging the application interface.
7. Frequently asked questions
Should I use port 465 or 587 for Laravel SMTP on cPanel?
For standard cPanel-managed email, port 465 with MAIL_SCHEME=smtps is a good starting point because cPanel documents it under its recommended secure settings.
Port 587 with MAIL_SCHEME=smtp can also work when the mail server supports STARTTLS.
Use the values provided by your actual mail provider and confirm that encryption is functioning.
Do not combine implicit TLS with a port expecting a normal SMTP greeting.
Why does MAIL_HOST=localhost cause certificate errors?
A mail server normally presents a certificate for a domain or server hostname rather than localhost.
When Symfony Mailer verifies the connection, a hostname mismatch can cause TLS negotiation to fail.
Use the authenticated SMTP service's documented hostname, covered by a valid certificate.
Local SMTP transport configurations are an exception and should be handled according to the local mail server's setup.
How do I fix 535 Incorrect authentication data in Laravel?
First verify the complete mailbox address and its password.
For a cPanel-managed mailbox, use the full email address rather than the cPanel account username.
Reset the mailbox password if necessary, update .env, clear the cached configuration and test again.
If the error persists, check account restrictions, blocked authentication attempts and provider-specific requirements.
Does Laravel 12 still use MAIL_ENCRYPTION?
The standard Laravel 12 mail configuration reads MAIL_SCHEME rather than MAIL_ENCRYPTION for its SMTP mailer.
With no explicit scheme, the framework normally selects smtps for port 465 and smtp for other ports.
Symfony Mailer handles encryption according to the transport configuration.
Older applications may retain custom or legacy configuration files, so inspect config/mail.php before assuming that changing a particular environment variable will have an effect.
References
The technical details above were checked against the following primary documentation and implementation sources:
- Laravel 12 Mail Documentation
- Laravel 12 Configuration
- Laravel 12 Queues
- Laravel 12 Default Mail Configuration
- Laravel 12 MailManager Implementation
- Laravel SMTP Scheme Compatibility Issue
- Laravel MAIL_ENCRYPTION Change Discussion
- Symfony Mailer Documentation
- cPanel Set Up Mail Client
- cPanel SMTP Restrictions
- cPanel Email Sending Limits
- PHP SSL Context Options


