Implement mail configuration, preview and sending in Larravel


brief introduction

Larave is based on SwiftMailer The library provides a set of clean and refreshing mail APIs. Larravel is a service provider for SMTP, Mailgun, SparkPost, Amazon SES and PHP mail Functions, and sendmail Provides a driver that allows you to quickly send mail through local or cloud services.

Pre knowledge of mail drive

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

 composer require guzzlehttp/guzzle

Mailgun driver

To use the Mailgun driver (the first 10000 mails of Mailgun are free of charge, and the subsequent charges are charged), first install Guzzle, and then install the configuration file config/mail.php Set in driver Options are mailgun Next, verify the configuration file config/services.php The following options are included:

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

SparkPost Drive

To use the SparkPost driver, first install Guzzle, and then click the configuration file config/mail.php Set in driver The option value is sparkpost Next, verify the configuration file config/services.php The following options are included:

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

SES drive

To use the Amazon SES driver (charging), first install the Amazon AWS PHP SDK. You can add the following composer.json Filed require Part then run composer update Command to install the library:

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

Next, set the configuration file config/mail.php In driver Options are ses Then, verify the configuration file config/services.php The following options are included:

 'ses' => [ 'key' => 'your-ses-key', 'secret' => 'your-ses-secret', 'region' => 'ses-region',  // e.g. us-east-1 ],
Note: The bad news is that none of the above drivers is applicable to applications developed by domestic developers for domestic users, so they can be ignored.

Generate Mailable Class

In Larravel, every email sent by the application can be expressed as a "mailable" class, which is stored in the app/Mail catalog. If you don't see this directory, don't worry, it will be used by you make:mail Generated when the command creates the first mailable class:

 php artisan make:mail OrderShipped

The template code generated by default is as follows:

Write Mailable Class

All mailable configurations are 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 messages.

Configure sender

use from method

Let's take a look at the configuration of the mail sender, or, in other words, who the mail comes from. There are two ways to configure the sender. The first way is in the mailable class build Called in method from method:

 /** *Build message * * @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 in all mails, call it in each generated mailable class from The method is cumbersome. Instead, you can use the config/mail.php Specify a global sending address in the. This address can be used when no other sending address is specified in all mailable classes (that is, as the default sender):

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

Configure View

You can mail build Method view Method to specify which view template to use when rendering message content. Because each message usually uses Blade template To render the content, you can use all the functions provided by the Blade template engine when building the email HTML:

 /** *Build message * * @return $this * @translator laravelacademy.org */ public function build() { return $this->view('emails.orders.shipped'); }
Note: You can create a resources/views/emails Directory to store all mail templates. Of course, you can also place mail templates in resources/views Any other location under the directory.
Plain text message

If you want to define a plain text message, you can use text method. and view In the same way, text Method receives a template name used to render mail content. You can define both plain text messages and HTML messages:

 /** *Build 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 the HTML view of the rendered mail for use. There are two ways to transfer data to the view. The first is that the public attribute of the mailable class automatically takes effect in the view. For example, we pass the data to the constructor of the mailable class and set the data to the public attribute 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; /** *Order instance * * @var Order */ public $order; /** *Create a new message instance * * @return void */ public function __construct(Order $order) { $this->order = $order; } /** *Build message * * @return $this */ public function build() { return $this->view('emails.orders.shipped'); } }

After the data is set to the public attribute, it will automatically take effect in the view, so you can access them as you access other data in the Blade template:

Price: {{ $order->price }}

adopt with method

If you want to customize the format of mail data before sending the data to the template, you can use with Method to manually transfer data to the view. Generally, you still need to pass data through the mailable constructor, but this time you need to set the data to protected or private Property, so that these data will not automatically take effect in the view. Then, when the with Method, the array data is passed 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; /** *Order instance * * @var Order */ protected $order; /** *Create a new instance * * @return void */ public function __construct(Order $order) { $this->order = $order; } /** *Build message * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->with([ 'orderName' => $this->order->name, 'orderPrice' => $this->order->price, ]); } }

Data via with After the method is transferred to the view, it will automatically take effect in the view, so you can also access the transferred data as you access other data in the Blade template:

 Price: {{ $orderPrice }}

enclosure

To add an attachment to an email, you can click the build Method attach method. attach Method receives the complete file path as the first parameter:

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

When attaching files to messages, you can also pass an array as attach Method to specify the file display name or MIME type:

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

Native Data Attachment

attachData Method can be used to add a native byte string as an attachment. If you want to generate a PDF in memory and add it to an email as an attachment without saving it to disk, you can use this method. attachData The method receives data bytes as the first parameter, the file name as the second parameter, and the optional array as the third parameter:

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

Inline attachment

Nesting an inline image into an email is usually cumbersome. For this reason, Laravel provides a convenient way to attach an image to an email and obtain the corresponding CID. To embed an inline image, use it in the email view $message On variable embed Method. Larave injects in all mail views $message Variable and make it effective automatically, so you don't need to care about how to manually transfer this variable to the view:
 Here is an image: <img src="{{ $message->embed($pathToFile) }}">
Note: $message Variables are not applicable to markdown messages.
Embed native data attachments

If you already have a native data string that you want to embed in the mail template, you can use $message On variable embedData method:

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

Customize SwiftMailer messages

Mailable On the base class withSwiftMessage Method allows you to register a callback that can be called by the native SwiftMailer message instance before sending a message. This gives us the opportunity to customize messages before sending them:

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

Markdown mail class

Markdown mail messages allow you to use preset templates and mail notification components in mailable classes. Because these messages are written in Markdown format, Laravel can also render high color, responsive HTML templates for them, and automatically generate plain text copies.

Generate Markdown mail class

To generate a mailable class with a corresponding Markdown template, you can use the Artisan command make:mail Time band --markdown Options:

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

Then, configure the mailable build Method, use markdown Method substitution view method. markdown Method receives the name of the Markdown template and an optional array data in effect in the template:

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

Write Markdown message

The Markdown mail class uses the Blade component and Markdown syntax in combination, so that you can easily build mail messages without breaking away from the Laravel preset components:

 @component('mail::message') # Order Shipped Your order has been shipped! @component('mail::button', ['url' => $url]) View Order @endcomponent Thanks,
{{ config('app.name') }} @endcomponent
Note: Don't use extra indentation when writing Markdown emails. Markdown parsers will render the indentation into code blocks.
Button components

The button component renders a centered button link. This component receives two parameters, url And optional color , supported colors are blude green and red You can add any number of button components to the message:

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

PANEL AS

The panel component renders the given text block into a panel with a faint background color to distinguish it from the surrounding messages. For text blocks requiring attention:

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

Table Components

The table component allows you to convert a Markdown table into an HTML table. This component receives the Markdown table as its content. Table column alignment supports the use of the default Markdown table column alignment syntax:

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

Custom Components

You can export all Markdown mail components to your own application for customization, using Artisan commands vendor:publish To publish laravel-mail Resource tag:

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

This command will issue the Markdown mail component to resources/views/vendor/mail catalog. mail Directory contains html and markdown Directory, and each subdirectory contains all its own valid components. You can edit these components according to your own needs.

Custom CSS

After exporting components, resources/views/vendor/mail/html/themes The directory will contain a default default.css File, you can customize CSS in this file, so that the HTML style of Markdown mail messages will be automatically adjusted.

If you want to build a new theme for Markdown components, just click html/themes Write a new CSS file in the directory and modify it mail Profile's theme Option.

Preview the message in the browser

When designing the template of an email, it is convenient to quickly preview the rendered email like a normal Blade template. Therefore, Laravel allows you to return mailable classes directly from routing closures or controllers. When the mailable class returns, it will be rendered and displayed in the browser, so that you can quickly preview it without actually sending an email to view:

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

Send Mail

To send a message, use the Mail Facade On to method. to Method receives the mailbox address, user instance, or user collection as parameters. If objects or object collections are delivered, mail will automatically use them when setting mail recipients email and name Property, so make sure these properties are valid on the corresponding class in advance. After specifying the recipient, deliver an instance of the mailable class to 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 { /** *Process incoming orders * * @param  Request  $request * @param  int  $orderId * @return Response * @translator laravelacademy.org */ public function ship(Request $request, $orderId) { $order = Order::findOrFail($orderId); //Process Order Mail::to($request->user())->send(new OrderShipped($order)); } }

Of course, sending email messages is not limited to specifying a single recipient. You can set "to", "cc" and "bcc" through a single method chain call:

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

Mail Queue

Mail Message Queue

Because sending mail messages may significantly extend the response time of applications, many developers choose to send the mail to the queue and send it in the background. Larvel can use the built-in Unified Queue API To realize this function. To push mail messages to the queue, you can use the Mail On the facade queue method:

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

This method automatically pushes the mail task to the queue for sending in the background. Of course, you need to use this feature before Configure Queue

Delay Message Queuing

If you want to delay the sending of mail messages in the queue, you can use later method. later The first parameter of the method receives a DateTime Instance to indicate the mail sending time:

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

Push to the specified queue

By passing make:mail All mailable classes generated by the command use Illuminate\Bus\Queueable Trait, so you can call the onQueue and onConnection Method to specify the connection and queue name for the message:

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

Default Queue

If your mailable class always wants to be pushed to the queue, you can implement it on this class ShouldQueue Covenants. This way, even if you call send Method, the mailable class will still be pushed to the queue because it implements the contract:

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

Mail&Local Development

When developing email sending applications in the local environment, you may not really want to send email to a valid email address, but just want to do a test. To this end, Laravel provides several ways to "cancel" the actual sending of mail.

Log driven

One solution is to use log Mail driven. The driver writes all mail information to the log file for viewing. If you want to know more about the application configuration of each environment, check Configuration Document

General configuration

Another solution provided by Laravel is to set a universal recipient for all mails sent by the framework. In this way, all emails generated by the application will be sent to the specified address instead of the address specified by the actual sending email. This can be done by config/mail.php Set in to Options to implement:

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

Mailtrap

Finally, you can use Mailtrap Services and smtp Drive to send mail information to a "virtual" mailbox. This method allows you to view the final mail in the Mailtrap message viewer.

event

Larave will trigger two events before sending the mail message, MessageSending The event is triggered before the message is sent, MessageSent The event is triggered after the message is sent. It should be noted that these two events are triggered before and after the mail is sent, rather than pushed to the queue EventServiceProvider Register the corresponding event listener in:

 /** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'Illuminate\Mail\Events\MessageSending' => [ 'App\Listeners\LogSendingMessage', ], 'Illuminate\Mail\Events\MessageSent' => [ 'App\Listeners\LogSentMessage', ], ];

give the thumbs-up Cancel Like Collection Cancel Collection

<<Previous: Integrated Flysystem to realize advanced operation on file system

>>Next: Using multiple channels to send notifications in Laravel