Email sending


Mail

##Introduction

Laravel is provided based on the

SwiftMailer library Developed a clean and refreshing email API. Laravel provides drivers for SMTP, Mailgun, SparkPost, Amazon SES, PHP's mail function, and sendmail, allowing you to quickly send email via local or cloud services.

Mail Driver Preliminary Knowledge

API-based drivers such as Mailgun and SparkPost are usually simpler and more efficient than SMTP servers. Fast, so use these services if you can. All API drivers require that the application has the Guzzle HTTP library installed. You can install it through the Composer package manager:

composer require guzzlehttp/guzzle

Mailgun driver

To use the Mailgun driver (Mailgun The first 10,000 emails are free, subsequent charges are charged), first install Guzzle, and then set the

driver option to mailgun in the configuration file config/mail.php. Next, verify that the configuration file config/services.php contains the following options:

'mailgun' => [
    'domain' => 'your-mailgun-domain',    
    'secret' => 'your-mailgun-key',
  ],

If you are not using the "US"

Mailgun region , you can Define the terminal profile for your region in services:

'mailgun' => [
    'domain' => 'your-mailgun-domain',    
    'secret' => 'your-mailgun-key',    
    'endpoint' => 'api.eu.mailgun.net',
  ],

Postmark Driver

To use the Postmark driver, install Postmark's SwiftMailer through Composer:

composer require wildbit/swiftmailer-postmark

Next, install Guzzle and config/mail.php The driver option in the configuration file is set to postmark. Finally, verify that your config/services.php configuration file contains the following options:

'postmark' => [ 
   'token' => 'your-postmark-token',
  ],

SparkPost driver

To use the SparkPost driver, first install Guzzle, and then set the driver option value to sparkpost in the configuration file config/mail.php. Next, verify that the configuration file config/services.php contains the following options:

'sparkpost' => [
    'secret' => 'your-sparkpost-key',
   ],

If necessary, you can also set the API endpoint using:

'sparkpost' => [
    'secret' => 'your-sparkpost-key',    
    'options' => [     
       'endpoint' => 'https://api.eu.sparkpost.com/api/v1/transmissions',   
     ],
  ],

SES driver

To use the Amazon SES driver (charged), first install the Amazon AWS PHP SDK. You can do this by adding the following lines to composer.json The require section of the file and then run the composer update command to install the library:

"aws/aws-sdk-php": "~3.0"

Next, set up the configuration file config/mail.php## The driver option in # is ses. Then, verify that the configuration file config/services.php contains the following options:

'ses' => [
    'key' => 'your-ses-key',    
    'secret' => 'your-ses-secret',    
    'region' => 'ses-region', 
     // e.g. us-east-1
  ],

If you need to include

additional options when executing SES SendRawEmail Request, you can define the options array in the ses configuration:

'ses' => [
    'key' => 'your-ses-key',    
    'secret' => 'your-ses-secret',    
    'region' => 'ses-region',  
    // e.g. us-east-1    
    'options' => [    
        'ConfigurationSetName' => 'MyConfigurationSet',        
        'Tags' => [    
                [      
                     'Name' => 'foo',                
                     'Value' => 'bar',         
                  ],    
                ],   
             ],
        ],

Generate Mailable class

In Laravel, every email sent by the application can be represented as a "mailable" class, and these classes are stored in the

app/Mail directory. If you don’t see this directory, don’t worry, it will be generated when you create your first mailable class using the make:mail command:

php artisan make:mail OrderShipped

Writing Mailable Classes

All mailable class configurations are completed in the

build method. In this method, you can call multiple Methods such as from, subject, view, and attach to configure the content and sending of the email.

Configure sender

Use

from method

Let’s take a look at the configuration of the email sender, or, in other words, who the email is coming from. There are two ways to configure the sender. The first way is to call the

from method in the build method of the mailable class:

/**
 * 构建消息.
 *
 * @return $this
 */
 public function build(){
     return $this->from('example@example.com')              
       ->view('emails.orders.shipped');
    }

Use global from address

However, if your application uses the same sending address for all emails, call ## in each generated mailable class The #from method seems cumbersome. Instead, you can specify a global sending address in the configuration file config/mail.php, which will be used if no other from address is specified in the mailable class:

'from' => ['address' => 'example@example.com', 'name' => 'App Name'],

Additionally, you can define a global

reply_to address in the config/mail.php configuration file:

'reply_to' => ['address' => 'example@example.com', 'name' => 'App Name'],

Configuration view

You can use the

view method in the build method of the mailable class to specify the content of the rendered email. Which view template to use, since each email usually uses a Blade template to render the content, you can use all the features provided by the Blade template engine when building the email HTML:

/**
 * 构建消息.
 *
 * @return $this
 */
 public function build(){
     return $this->view('emails.orders.shipped');
   }

{Note:} You You can create a

resources/views/emails directory to store all email templates. Of course, you can also place the email templates in any other location under the resources/views directory.

Plain text email

If you want to define an email in plain text format, you can use the

text method. Like the view method, the text method receives a template name used to render the email content. You can define either a plain text message or an HTML message:

/**
 * 构建消息.
 *
 * @return $this
 */
 public function build(){
     return $this->view('emails.orders.shipped')             
        ->text('emails.orders.shipped_plain');
    }

View data

Through public properties

Usually, we need to pass some data to render An HTML view of the message is available for use. There are two ways to pass data to the view, first, any public properties defined in your mailable class will be automatically passed to the view. Therefore, you can pass data to the constructor of the mailable class and set the data as a public property of the class:

<?php
    namespace App\Mail;
    use App\Order;use Illuminate\Bus\Queueable;
    use Illuminate\Mail\Mailable;
    use Illuminate\Queue\SerializesModels;
    class OrderShipped extends Mailable{ 
       use Queueable, SerializesModels;   
     /**
     * 订单实例.
     *
     * @var Order
     */  
   public $order; 
    /**
     * 创建一个新的消息实例.
     *
     * @return void
     */   
   public function __construct(Order $order)   
   {     
      $this->order = $order;   
   }   
   /**
     * 构建消息.
     *
     * @return $this
     */   
    public function build()  
      {      
        return $this->view('emails.orders.shipped');  
         }
    }

After the data is set to the public property, it will automatically take effect in the view, so you They can be accessed just like other data in Blade templates:

<div>
    Price: {{ $order->price }}
</div>

Through the with method

If you want to customize the format of the email data before the data is sent to the template, you can manually pass the data to the view via the with method . Normally, you still need to pass data through the constructor of the mailable class, but this time you need to set the data to the protected or private attribute, so that the data will not Automatically takes effect in the view. Then, when the with method is called, pass the array data to the method so that the data takes effect in the view template:

<?php
    namespace App\Mail;
    use App\Order;
    use Illuminate\Bus\Queueable;
    use Illuminate\Mail\Mailable;
    use Illuminate\Queue\SerializesModels;
    class OrderShipped extends Mailable{ 
       use Queueable, SerializesModels;   
     /**
     * 订单实例.
     *
     * @var Order
     */ 
   protected $order;  
    /**
     * 创建一个新的实例.
     *
     * @return void
     */  
   public function __construct(Order $order)  
     {     
        $this->order = $order;  
      }   
    /**
     * 构建消息.
     *
     * @return $this
     */  
    public function build()  
      {     
         return $this->view('emails.orders.shipped')                
             ->with([                 
                    'orderName' => $this->order->name,                        
                    'orderPrice' => $this->order->price,                 
                    ]);  
           }
      }

After the data is passed to the view through the with method, will automatically take effect in the view, so you can also access the passed data just like accessing other data in the Blade template:

<div>
    Price: {{ $orderPrice }}
</div>

Attachment

To add an attachment to an email, use the attach method in the build method. The attach method accepts the absolute path to the file as its first argument:

    /**
     * Build the message.
     *
     * @return $this
     */    
     public function build()   
      {      
        return $this->view('emails.orders.shipped')                 
           ->attach('/path/to/file');  
      }

When attaching a file to a message, you can also pass an array to attach method as the second parameter to specify the display name and/or MIME type:

    /**
     * Build the message.
     *
     * @return $this
     */  
   public function build()  
    {      
      return $this->view('emails.orders.shipped')                
          ->attach('/path/to/file', [                        
                                          'as' => 'name.pdf',                       
                                           'mime' => 'application/pdf',       
                                     ]);  
     }

Add attachment from disk

If you have If a file is stored on storage, you can attach it to an email using the attachFromStorage method:

/**
 * 构建消息。
 *
 * @return $this
 */
 public function build(){
    return $this->view('email.orders.shipped')             
      ->attachFromStorage('/path/to/file');
 }

If necessary, you can use the attachFromStorage method The second and third parameters specify the file attachment name and other options:

/**
 * 构建消息。
 *
 * @return $this
 */
 public function build(){ 
   return $this->view('email.orders.shipped')            
      ->attachFromStorage('/path/to/file', 'name.pdf', [               
          'mime' => 'application/pdf'             
       ]);
    }

If you need to specify a storage disk other than the default disk, you can use the attachFromStorageDisk method:

/**
 * 构建消息。
 *
 * @return $this
 */
 public function build(){
    return $this->view('email.orders.shipped')            
       ->attachFromStorageDisk('s3', '/path/to/file');
   }

Raw data attachment

attachData You can use byte data as an attachment. For example, you can use this method to attach a PDF to an email that is generated in memory but not saved to disk. attachData The first parameter of the method receives raw byte data, the second parameter is the file name, and the third parameter accepts an array to specify other parameters:

    /**
     * Build the message.
     *
     * @return $this
     */
   public function build()  
     {     
        return $this->view('emails.orders.shipped')                
            ->attachData($this->pdf, 'name.pdf', [                   
                 'mime' => 'application/pdf',                
                ]);  
         }

Inline Attachments

Embedding inline images in emails is often cumbersome; however, Laravel provides a way to attach images to emails and obtain the appropriate CID Easy way. Inline images can be embedded using the embed method of the $message variable in the email template. Laravel automatically makes the $message variable available in all email templates, no need to worry about passing it manually:

<body>
    Here is an image:
    <img src="{{ $message->embed($pathToImage) }}">
</body>

{note} $message in the text Not available in Messages because text messages cannot use inline attachments.

Embed original data attachment

If you already have the original data string that you want to embed in the email template, you can use the embedData method of the $message variable:

<body>
    Here is an image from raw data:
        <img src="{{ $message->embedData($data, $name) }}">
</body>

##Custom SwiftMailer message

MailablewithSwiftMessage method of base class Allows you to register a callback that will be called before sending the message, with the original SwiftMailer message as the argument to the callback:

/**
 * 构建消息。
 *
 * @return $this
 */
 public function build(){
     $this->view('emails.orders.shipped');    
     $this->withSwiftMessage(function ($message) {    
         $message->getHeaders()             
            ->addTextHeader('Custom-Header', 'HeaderValue');   
     });
}

Markdown formatted Mailables class

Markdown formatted mailable messages allow you to benefit from pre-built templates and email notification components in the mailable class. Because messages are written in Markdown, Laravel can render beautiful, responsive HTML template messages and automatically generate text copies.

Generate Mailables class in Markdown format

To generate a mailable that applies Markdown template, you can use the code with

--markdown option make:mail Artisan command:

php artisan make:mail OrderShipped --markdown=emails.orders.shipped

Then, configure mailable in its

build method, calling markdown method instead of view method. markdown The method accepts the Markdown template name and an optional array of available names in the template:

/**
 * Build the message.
 *
 * @return $this
 */
 public function build(){ 
    return $this->from('example@example.com')            
        ->markdown('emails.orders.shipped');
   }

Writing Markdown Message

Markdown mailable uses a combination of Blade components and Markdown syntax, allowing you to more conveniently use Laravel prefabricated components to build email messages:

@component('mail::message')
# 订单已发货
Your order has been shipped!
@component('mail::button', ['url' => $url])
View Order
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent

{tip} Do not use when writing Markdown emails Extra indentation. The Markdown parser will render the indented content into code blocks.

Button Component

The Button component renders a centered button link. This component accepts two parameters,

url and optionally color. Color options support primary, success, and error. You can add as many button components to the message as you like:

@component('mail::button', ['url' => $url, 'color' => 'success'])
View Order
@endcomponent

Panel component

Panel component renders a given block of text within a panel, panel with other messages The background color is slightly different. Allows you to draw a warning text block:

@component('mail::panel')
This is the panel content.
@endcomponent

Table Component

The Table component allows you to convert Markdown tables into HTML tables. This component accepts a Markdown table as its content. Column alignment supports the default Markdown table alignment syntax:

@component('mail::table')
| Laravel       | Table         | Example  |
| ------------- |:-------------:| --------:|
| Col 2 is      | Centered      |       |
| Col 3 is      | Right-Aligned |       |
@endcomponent

Custom components

You can export all Markdown email components to your own application and use them as templates for custom components. To export these components, use the vendor:publish Artisan command with the laravel-mail asset tag:

php artisan vendor:publish --tag=laravel-mail

This command exports the Markdown mail component to resources/views/vendor/mail Directory. The mail directory contains html and text subdirectories, which contain corresponding descriptions of available components. These components can be customized however you wish.

Customized CSS

After the configuration is exported, the resources/views/vendor/mail/html/themes directory has a default. css file. CSS can be customized from this file and these styles will be automatically inlined into the HTML representation of the Markdown email message.

{tip} If you want to create a complete new theme for the Markdown component, you can create a new CSS file in the html/themes directory and modify the mail configuration The theme option of the file.

Send Mail

To send mail, use the Mail facade to method. to Method accepts an email address, user instance, or user collection. If you pass an object or collection of objects, the mailer will automatically use their email and name properties when setting the recipients, so make sure these properties are available for the object. Once the recipients are specified, a mailable class instance can be passed to the send method:

<?php
    namespace App\Http\Controllers;
    use App\Order;use App\Mail\OrderShipped;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Mail;
    use App\Http\Controllers\Controller;
    class OrderController extends Controller{   
     /**
     * 发送给定的订单。
     *
     * @param  Request  $request
     * @param  int  $orderId
     * @return Response
     */  
       public function ship(Request $request, $orderId)  
         {      
           $order = Order::findOrFail($orderId);        
           // 发送订单...        
           Mail::to($request->user())->send(new OrderShipped($order));  
           }
     }

More than just recipients can be specified when sending a message. You can also specify Cc and Bcc recipients at once through chain calls to "to", "cc", and "bcc":

Mail::to($request->user()) 
   ->cc($moreUsers)    
   ->bcc($evenMoreUsers)    
   ->send(new OrderShipped($order));

Rendering Mailable

Sometimes you may want to capture the HTML content of a mailable without sending it. This can be accomplished by calling the render method of mailable. This method returns the calculated string after mailable rendering:

$invoice = App\Invoice::find(1);
return (new App\Mail\InvoicePaid($invoice))->render();

##Preview Mailable in the browser

Design mailable When templating, it is convenient to preview and render mailables in the browser just like Blade templates. In this case, Laravel allows you to return any mailable directly in a route closure or control. The returned mailable will be rendered and displayed in the browser, allowing you to quickly preview the design without having to send it to a real email address:

Route::get('mailable', function () {
    $invoice = App\Invoice::find(1);    
    return new App\Mail\InvoicePaid($invoice);
  });

Mail Queue

Add email messages to the queue

Since sending email messages may significantly prolong the response time of the application, many developers choose to add email messages to the queue and send them in the background. Laravel makes this easy with its built-in unified queue API. To add a mail message to the queue, you can use the queue method of the Mail facade after specifying the recipient of the message:

Mail::to($request->user())  
  ->cc($moreUsers)    
  ->bcc($evenMoreUsers)    
  ->queue(new OrderShipped($order));

This method automatically pushes the job to Queued so that messages can be sent in the background. Before using this feature, you need to configure the queue:

Delay message queue

If you want to delay sending queued email messages, you can use the later method . later The first parameter of the method is to indicate when the message is sent DateTime Example:

$when = now()->addMinutes(10);Mail::to($request->user())  
              ->cc($moreUsers)    
              ->bcc($evenMoreUsers)    
              ->later($when, new OrderShipped($order));

Push to the specified Queue

Since all mailable classes generated using the make:mail command use the Illuminate\Bus\Queueable trait, you can use it on any mailable class instance Call the onQueue and onConnection methods to specify the message connection and queue name:

$message = (new OrderShipped($order))        
        ->onConnection('sqs')                
        ->onQueue('emails');Mail::to($request->user())    
        ->cc($moreUsers)    
        ->bcc($evenMoreUsers)    
        ->queue($message);

Default queue

If a mailable The class must eventually be queued, and the ShouldQueue contract can be implemented on this class. This way, the mailable will be serialized even if you call the send method when sending:

use Illuminate\Contracts\Queue\ShouldQueue;
class OrderShipped extends Mailable implements ShouldQueue{ 
   //
 }

Localized Mailable

Laravel allows you to send a mailable using a locale different from the current language, retaining that locale even if it is added to the queue.

To achieve this purpose, Mail facade provides the locale method to set the target language. The application that formats the mailable will switch to this locale and return to the original locale after formatting is complete:

Mail::to($request->user())->locale('es')->send( 
   new OrderShipped($order)
  );

User preferred locale

Yes time, the application stores each user's preferred locale. By implementing the HasLocalePreference contract on one or more models, you can tell Laravel to use the stored locale when sending emails:

use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference{    
     /**
     * 获取用户首选区域设置。
     *
     * @return string
     */   
  public function preferredLocale() 
     {     
        return $this->locale;  
       }
    }

Once this interface is implemented, Laravel will send emails to this model. mailable and notifications, the preferred locale will be used automatically. Therefore there is no need to call the locale method when using this interface:

Mail::to($request->user())->send(new OrderShipped($order));

##Mail & Local Development

When developing an application that sends email, you may not want to actually send email to a live email address. Laravel provides several ways to "disable" real sending during local development.

Log driver

log The email driver writes email messages to the log instead of sending emails, ready for viewing. For more information on application environment configuration, please consult the configuration documentation.

Common Configuration

Laravel provides additional solutions for specifying common recipients for emails sent via frames. With this method, emails generated by the application will be sent to the specified address, replacing the real address specified when sending the message. This can be achieved with the help of the to option of the config/mail.php configuration file:

'to' => [ 
   'address' => 'example@example.com',    
   'name' => 'Example'
  ],

Mailtrap

Finally, You can use the Mailtrap service and the smtp driver to send email messages to a "virtual" mailbox, so that the email messages can be viewed in a real email client. The benefit of this method is that it allows you to actually view the final email in Mailtrap's message viewer.

Events

Laravel triggers two events when handling the sending of email messages. The MessageSending event is triggered before the message is sent, and the MessageSent event is triggered after the message is sent. Remember, these events are triggered when the message is sent, not when it is queued. A listener for this event can be registered in EventServiceProvider:

/**
 * 为应用映射事件侦听器。
 *
 * @var array
 */
 protected $listen = [  
   'Illuminate\Mail\Events\MessageSending' => [     
      'App\Listeners\LogSendingMessage',   
   ],    
   'Illuminate\Mail\Events\MessageSent' => [     
      'App\Listeners\LogSentMessage', 
        ],
   ];
This article was first published on the LearnKu.com website.