Custom email: Net::SMTP doesn't select the correct authentication method automatically
From the feedback issue:
Problem
I set up a Microsoft account myself and configured everything accordingly. It didn't work.
What's really interesting is, that it used to work, when I tried it before release. Maybe something in the configuration or the system itself changed
A short recap of how I configured it and what I tried
- Enable Authenticated SMTP for the user in question (via the user flyout, Email and Apps section)
- Enable 2FA for that account in Active Directory (now Entra).
- Set
Set-TransportConfig -SmtpClientAuthenticationDisabled $falsevia Azure Cloud Shell. - Also tried
Set-TransportConfig -AllowLegacyTLSClients $true(reference) - Allow app password (via Entra admin center --> Named locations --> Configure MFA trusted IPs. (reference)
- Sign in to the "custom email" account and configure 2FA (for example TOTP using an authenticator app) via Security Info.
- Add an app password for that account on the same page. (reference)
- I also configured a transport rule, but I didn't get so far, so that's optional for now.
- Check credentials using
swakslike mentioned in the comment above. It works!I usedswaks --to user@example.com --from marc.saleiko@XYZ.onmicrosoft.com --auth-user marc.saleiko@XYZ.onmicrosoft.com --server smtp.office365.com:587 -tls-optional --auth-password superapppassword-tls-optionalbecause that's closest to the setup we use internally. - Used the same credentials for the custom email configuration in my local environment.
500error after a few seconds, because we don't catch the read timeout error yet. - I increased the read timeout locally and repeated the last step.
- Now we get a different error
504 5.7.4 Unrecognized authentication type. Looks like Microsoft wants explicit TLS. Tried that, but it also didn't work.
Replication and testing
Feel free to use this sample script to run tests on your own:
smtp_options = {
user_name: '',
password: '',
address: 'smtp.office365.com',
port: 587,
read_timeout: 7
}
recipient = 'name@gitlab.com'
mail = Mail.new do
from smtp_options[:user_name]
to recipient
subject 'M365 test email'
body 'test content'
end
mail.delivery_method(::Mail::SMTP, smtp_options)
mail.deliver
Basic Authenticated SMTP setup:
- Server:
smtp.office365.com - Port:
587(recommended) or port25 - TLS/StartTLS:
Enabled - Username/email address and password: Enter the sign-in credentials of the hosted mailbox being used
Solution path
- We require the SMTP server to return a list of AUTH types in the handshake phase. E.g.
250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH - ActionMailer will then pick one method and send the request.
- If will fail with
Net::SMTPAuthenticationError: 504 5.7.4 Unrecognized authentication typeif no list is provided. - Microsoft 365 doesn't provide such a list.
- Setting
authentication: :loginon the SMTP settings works, but needs to be set explicitly. - So we probably need an additional setting where maintainers+ can set an authentication method explicitly or let the server decide which to choose.
- This will also be a great addition for customers of other service providers where the server also doesn't return a list or they want to use some challenge based AUTh method like
cram_md5.
Edited by Marc Saleiko