// how to fix
PHPMailer "SMTP Error: Could not authenticate": how to fix it
PHPMailer fails with SMTP Error: Could not authenticate? Turn on debug output, then fix the login, port, encryption or provider settings.
What it means
PHPMailer connected to the SMTP server, but the server refused the username and password. PHPMailer shows a short message:
SMTP Error: Could not authenticate.
This short text hides the real reason. The server's answer (often a 535 code) is only visible with debug output on. Do not confuse it with SMTP connect() failed, which means PHPMailer could not even reach the server (wrong host, port blocked, TLS problem).
Why it happens
- Wrong username or password. Most providers want the full email address as username. Passwords with special characters can be cut or changed when stored in a
.envfile or a config with quotes. - The provider no longer accepts the normal password. Gmail requires an app password (see Gmail 535 5.7.8 username and password not accepted). Microsoft 365 often has SMTP AUTH turned off (see Microsoft 365 535 5.7.139).
- Special SMTP credentials. Services such as Amazon SES, SendGrid or Mailgun use dedicated SMTP credentials, not your account login (for SES, see Amazon SES 535 credentials invalid).
- Wrong port and encryption pair. Port 465 needs implicit TLS (
ENCRYPTION_SMTPS); port 587 needs STARTTLS (ENCRYPTION_STARTTLS). Some servers do not offer login at all before encryption is on. - The host redirects SMTP. Some shared hosts send all outgoing SMTP to their own server. Your login then reaches the wrong server and fails.
- Account locked or blocked after too many failed attempts, or a security check by the provider.
How to check
Turn on debug output for one test (never leave it on in production, it prints the login exchange):
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->Host = 'smtp.example.com';
$mail->Port = 587;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->SMTPAuth = true;
$mail->Username = 'you@yourdomain.com';
$mail->Password = getenv('SMTP_PASSWORD');Read the lines starting with SERVER -> CLIENT:
- A
535line afterAUTHgives the provider's reason (bad credentials, app password required, SMTP AUTH disabled…). - If the
220greeting or the certificate shows a hostname that is not your provider's, your host is redirecting SMTP. - If no
AUTHappears in the250list afterEHLO, the server does not offer login on this port or before TLS.
Test the same login outside PHP with swaks, from the same server:
swaks --server smtp.example.com:587 --tls --auth LOGIN \ --auth-user you@yourdomain.com --to you@yourdomain.com
If swaks works, the problem is in your PHP config (password quoting, wrong variable). If swaks fails too, it is the account or the provider.
How to fix it
- Use the exact settings of your provider: host, port, encryption and username format from their documentation.
- Store the password safely and check it is read correctly (print its length during a test, not the password).
- Use the right credential type: an app password for Gmail, SMTP credentials for SES or other services, and SMTP AUTH enabled on the mailbox for Microsoft 365. PHPMailer also supports OAuth2 (XOAUTH2) for Gmail and Microsoft 365 if you prefer not to use passwords.
- Match port and encryption: 587 with
ENCRYPTION_STARTTLS, or 465 withENCRYPTION_SMTPS. - On shared hosting, ask the host whether outgoing SMTP is redirected, and use their SMTP server or allow external SMTP in the panel if they offer it.
- Unlock the account if the provider blocked it, then retry once rather than in a loop.
Once mail goes out, make sure it is authenticated for your domain; contact forms and WordPress sites have extra pitfalls covered in website emails going to spam.
Check that it is fixed
Run the script again with debug on: you should see 235 Authentication successful (wording varies) and then 250 after the message data. Set the recipient to the unique address on the Delivmail home page and read the report to check SPF, DKIM and DMARC. Then turn debug off and send to the real recipient.
Check that it is fixed
DNS changes can take from a few minutes to a few hours. Then send a new test email or scan your domain again.
Related guides
- Emails from your website or WordPress go to spamContact forms, order confirmations and password resets sent by your website often land in spam. Send them through authenticated SMTP or a transactional email service.
- Amazon SES SMTP "535 Authentication Credentials Invalid": fix itAmazon SES rejects your SMTP login with 535 Authentication Credentials Invalid. Use real SMTP credentials, the right Region and endpoint, and test them.
- Amazon SES "Throttling: Maximum sending rate exceeded" (454): fix itAmazon SES returns "Maximum sending rate exceeded" or "Daily message quota exceeded". Check your quotas, slow down sending and request an increase.
- Mailgun "401 Forbidden": wrong API key or EU/US region mismatchMailgun returns 401 Forbidden or Unauthorized. Check the API key type, the "api" username and whether your domain uses the US or EU endpoint.
- Gmail SMTP "535-5.7.8 Username and Password not accepted" (and 534-5.7.9)Gmail SMTP login fails with 535-5.7.8 or 534-5.7.9 "Application-specific password required"? Use an app password or OAuth instead of your password.