I am struggling with sending mail from web using Exchange online account. Recently, while moving to Laravel, I found that the existing settings, that worked well with PHPMailer does not work with Laravels underlying SwiftMailer.
PHPMailer works:
$data = new PHPMailer(true);
$data->CharSet = 'UTF-8';
$data->isSMTP();
$data->Host = config('mail.host');
$data->SMTPAuth = true; // apparently this line does the trick
$data->Username = config('mail.username');
$data->Password = config('mail.password');
$data->SMTPSecure = config('mail.encryption');
$data->Port = config('mail.port');
$data->setFrom('site@mydomain.com','site mailer');
$data->addAddress('me@mydomain.com', 'Me');
$data->Subject = 'Wonderful Subject PHPMailer';
$data->Body = 'Here is the message itself PHPMailer';
$data->send();
Same logic with SwiftMailer:
$transport = (new Swift_SmtpTransport(config('mail.host'), config("mail.port"), config('mail.encryption')))
->setUsername(config('mail.username'))
->setPassword(config('mail.password'));
$mailer = new Swift_Mailer($transport);
$message = (new Swift_Message('Wonderful Subject'))
->setFrom(['site@mydomain.com'=>'site mailer'])
->setTo(['me@mydomain.com'=>'Me'])
->setBody('Here is the message itself');
$numSent = $mailer->send($message);
SwiftMailer, gives error:
530 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM [xxxxxxxxxxxxx.xxxxxxxx.prod.outlook.com]
The SMTP server is same in both cases smtp-mail.outlook.com
and port 587
NB Yes, I am well aware of suggestions elsewhere to use mydomain-com.mail.protection.outlook.com
and port 25. But by doing so, messages are received in Junk with cause "We could not verify the identity of the sender", which is a behavior I cannot accept.
And we are talking about small amount, so not interested in other/3rd party mass mailing services.
My findings so far are, that $phpMailer->SMTPAuth = true;
is game changer. Without this line, it yields same error as SwiftMailer.
The Question is how to force same behavior on SwiftMailer
?
As stated earlier, I actually use the Laravel Mail, but for the purpose of this example I extracted SwiftMailer calls directly.
EDIT: SwiftMailer has $transport->setAuthMode()
, which should be the same as $phpMailer->AuthType
. Tried available CRAM-MD5, LOGIN, PLAIN, XOAUTH2 values for both.
PHPMailer worked with all of those, except XOAUTH2. For SwiftMailer none of those changed anything, still gives the error.
EDIT2:
I do have SPF record (DNS TXT) v=spf1 include:spf.protection.outlook.com -all
SOLVED: Added tls
to Swift transport construction.
Apparently PHPMailer defaulted to tls, because config('mail.encryption')
was null
.
https://stackoverflow.com/a/48933513/10283047 deals with sending mail in Java, but the basic problem seemed to be the same here:
If you connect via port 587 you initially start a plain connection where you have to start TLS by explicitly sending the STARTTLS-command. You have to tell JavaMail to do that, otherwise it will try to proceed unsecured. The SMTP-server doesn't send any authentication-mechanism-informations unless the TLS-connection is established, so JavaMail is assuming that no authentication is needed and tries to send the mail without.
So it appears you need to explicitly specify that you want this to be an encrypted connection here as well.
The third parameter for the Swift_SmtpTransport constructor does that, supply either 'ssl' or 'tls':
new Swift_SmtpTransport('smtp.example.org', 587, 'ssl'); // or
new Swift_SmtpTransport('smtp.example.org', 587, 'tls');
With the phpMailer version you had $data->SMTPSecure take care of that part.