Email sending
- Introduction
- Generate a mailable class
- Write a mailable class
- Markdown mail class
- Send email
- Render mailable class
- Localization Mailable Class
- Mail & Local Development
- Event
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.
composer require guzzlehttp/guzzleMailgun 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 classIn 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 OrderShippedWriting Mailable ClassesAll 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.
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 viewYou 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 aPlain text emailIf you want to define an email in plain text format, you can use theresources/views/emails
directory to store all email templates. Of course, you can also place the email templates in any other location under the
resources/viewsdirectory.
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 dataThrough public propertiesUsually, 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 formatTo 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.shippedThen, 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 MessageMarkdown 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 ComponentThe 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 @endcomponentPanel componentPanel 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. @endcomponentTable ComponentThe 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 thetheme
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 browserDesign 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', ], ];