Search code examples
phpemaillaravel-5sendmailswiftmailer

Laravel Mail / Swift / How to globally configure "sender" address


Laravel offers the config mail.from to allow specifying a global/default From address. This calls setFrom on the Swift-Message internally and sets the "Header From" that shows in the recipients email client. However, the message is then also sent with Return-Path/Envelope-From of this value, because of getReversePath, that derives this From value as no other option (Sender/Return-Path) has been set.

The site is running on a multi-project host with Exim4 running locally, so there are no restrictions to set these addresses like if I was using something like Gmail SMTP. Laravel is configured to use sendmail.

Let's assume the machines hostname is webX.hosts.our-company-intern.com and the project that runs on it belongs to a subdomain of customer-brand.com. E-Mails should be sent from the "main-domain" (without the subdomain part), though, like [email protected]. customer-brand.com. does not resolve to the machine the subdomain project is hosted.

I would like to send the mail with an Envelope address of my actual hostname (better: preserve the default Envelope-From/Return-Path Exim/Sendmail would use), like [email protected] and only have From: [email protected].

Reason for that is, I'd like to have a valid Return-Path indicating from which host it actually came from. SPF is also a reason, but not the main one; we control the customer-brand.com domain and could just add our hosts address, I'd still like to avoid it if possible and use our domain that already have all our hosts in their SPF record.

When I put the following line in the Laravel vendor class-method Mailer::send:

$message->sender('[email protected]');

This yields my desired result, but of course I cannot just edit it in vendor code. Where can I configure this properly (maybe via a callback that executes for every message)? Or isn't there any such option and I should write an issue in the Laravel/Mail package?

I also tried putting -f in the sendmail command: /usr/sbin/sendmail -bs -f"[email protected]" - however this already fails at the _establishProcessConnection(). Called in CLI the error is:

exim: incompatible command-line options or arguments


Versions:

  • Laravel 5.4.36
  • Swiftmailer 5.4.9
  • Exim 4.89-2+deb9u2

Config mail.php:

'from' => [
    'address' => '[email protected]',
    'name' => 'Customer Brand',
],

Tinker-Shell test code:

Mail::raw('Text to e-mail', function($message) {
  $message->to('[email protected]');
})

Current mail headers:

Received: from webX.hosts.our-company-intern.com (xxx.xxx.xxx.xxx) by ...
Received: from appname (helo=[127.0.0.1])
    by webX.hosts.our-company-intern.com with local-smtp (Exim 4.89)
    (envelope-from <[email protected]>)  // this should change
    ...
From: Customer Brand <[email protected]>
Return-Path: [email protected]  // this should change

Solution

  • On the top of my head: you could hook in the Illuminate\Mail\Events\MessageSending event and add the sender there.

    Given the corporate environment I'll assume you know how to listen to events (if not, let me know). In that case, here's the listener you'll need:

    class MessageSendingListener
    {
        /**
         * Handle the event.
         *
         * @param  \Illuminate\Mail\Events\MessageSending  $event
         * @return void
         */
        public function handle(MessageSending $event)
        {
            // $event->message is of type \Swift_Message
            // So you'll need the setSender() method here.
    
            $event->message->setSender('[email protected]');
        }
    }