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('[email protected]','site mailer');
$data->addAddress('[email protected]', '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(['[email protected]'=>'site mailer'])
->setTo(['[email protected]'=>'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:
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':
With the phpMailer version you had $data->SMTPSecure take care of that part.