ellite/Wallos · error · Exception
$this->lang('authenticate')
Error message
$this->lang('authenticate') What it means
Thrown in smtpConnect() when $this->smtp->authenticate() fails after a successful connection: the server rejected the AUTH attempt with the configured Username, Password, AuthType, and OAuth token. The message is the localized 'authenticate' string ('SMTP Error: Could not authenticate.'). This is an application-level credential rejection, not a connection problem.
Solutions
- Verify Username (often the full email address) and Password by logging into webmail or testing with swaks/openssl s_client.
- For Gmail, enable 2FA and use an App Password, or implement XOAUTH2 with the PHPMailer OAuth provider.
- Check $mailer->AuthType against the mechanisms the server advertises in EHLO (try 'LOGIN' or 'PLAIN' explicitly, or null for auto).
- Refresh the OAuth access token if using XOAUTH2 (expired token yields AUTH failure).
- Enable SMTPDebug = DEBUG_SERVER to see the server's exact AUTH reply (535 authentication failed, etc.).
Example fix
// before $mailer->Username = 'myuser@gmail.com'; $mailer->Password = 'normal-google-password'; // rejected // after $mailer->Username = 'myuser@gmail.com'; $mailer->Password = 'xxxx xxxx xxxx xxxx'; // Gmail App Password (2FA enabled) $mailer->AuthType = 'LOGIN';
Defensive patterns
Strategy: validation
Validate before calling
if ($mailer->SMTPAuth && (empty($mailer->Username) || empty($mailer->Password))) {
throw new RuntimeException('SMTP credentials missing: set Username/Password before send()');
}
if (str_contains($mailer->Host, 'gmail') && !preg_match('/^([a-z]+ ){3}[a-z]+$|^[a-z]{16}$/i', $mailer->Password ?? '')) {
error_log('Warning: Gmail usually requires an App Password, not the account password');
} Try / catch
try {
$mailer->send();
} catch (PHPMailer\PHPMailer\Exception $e) {
if (str_contains($mailer->ErrorInfo, 'Could not authenticate')) {
error_log('SMTP AUTH rejected: check credentials/AuthType; ' . $mailer->smtp->getError()['detail'] ?? '');
// refresh OAuth token or correct app password, then retry once
}
} Prevention
- Store credentials in env/secret manager and verify at startup.
- Use app passwords (Gmail) or OAuth2 (XOAUTH2) where providers require them.
- Match AuthType to a mechanism the server advertises in EHLO.
- Rotate/refresh OAuth tokens before expiry; catch AUTH failure to trigger refresh.
- Use the full email address as username on cPanel-style hosts.
When it happens
Trigger: Calling send() with isSMTP() and SMTPAuth = true when the SMTP server rejects the credentials: wrong password, AUTH mechanism mismatch (CRAM-MD5/LOGIN/PLAIN/XOAUTH2 unsupported), OAuth token expired, or account locked/2FA without app password.
Common situations: Gmail/Office365 requiring app passwords or OAuth2 instead of plain passwords, password rotations not updated in config, cPanel hosts requiring the full email address as username, servers advertising mechanisms PHPMailer's AuthType doesn't select, expired XOAUTH2 access tokens.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of ellite/Wallos@52820e87ca (2026-09-13).
Data as JSON: /api/errors/391f413da522e8b6.
Report an issue: GitHub.
Appendix: source
Thrown at libs/PHPMailer/PHPMailer.php:2223
$tls = true;
}
if ($tls) {
if (!$this->smtp->startTLS()) {
$message = $this->getSmtpErrorMessage('connect_host');
throw new Exception($message);
}
//We must resend EHLO after TLS negotiation
$this->smtp->hello($hello);
}
if (
$this->SMTPAuth && !$this->smtp->authenticate(
$this->Username,
$this->Password,
$this->AuthType,
$this->oauth
)
) {
throw new Exception($this->lang('authenticate'));
}
return true;
} catch (Exception $exc) {
$lastexception = $exc;
$this->edebug($exc->getMessage());
//We must have connected, but then failed TLS or Auth, so close connection nicely
$this->smtp->quit();
}
}
}
//If we get here, all connection attempts have failed, so close connection hard
$this->smtp->close();
//As we've caught all exceptions, just report whatever the last one was
if ($this->exceptions && null !== $lastexception) {
throw $lastexception;
}
if ($this->exceptions) {View on GitHub (pinned to 52820e87ca)