Skip to main content
Glama
brianirish

Laravel MCP Companion

by brianirish
mail.md37.6 kB
# Mail - [Introduction](#introduction) - [Configuration](#configuration) - [Driver Prerequisites](#driver-prerequisites) - [Failover Configuration](#failover-configuration) - [Generating Mailables](#generating-mailables) - [Writing Mailables](#writing-mailables) - [Configuring The Sender](#configuring-the-sender) - [Configuring The View](#configuring-the-view) - [View Data](#view-data) - [Attachments](#attachments) - [Inline Attachments](#inline-attachments) - [Customizing The SwiftMailer Message](#customizing-the-swiftmailer-message) - [Markdown Mailables](#markdown-mailables) - [Generating Markdown Mailables](#generating-markdown-mailables) - [Writing Markdown Messages](#writing-markdown-messages) - [Customizing The Components](#customizing-the-components) - [Sending Mail](#sending-mail) - [Queueing Mail](#queueing-mail) - [Rendering Mailables](#rendering-mailables) - [Previewing Mailables In The Browser](#previewing-mailables-in-the-browser) - [Localizing Mailables](#localizing-mailables) - [Testing Mailables](#testing-mailables) - [Mail & Local Development](#mail-and-local-development) - [Events](#events) <a name="introduction"></a> ## Introduction Sending email doesn't have to be complicated. Laravel provides a clean, simple email API powered by the popular [SwiftMailer](https://swiftmailer.symfony.com/) library. Laravel and SwiftMailer provide drivers for sending email via SMTP, Mailgun, Postmark, Amazon SES, and `sendmail`, allowing you to quickly get started sending mail through a local or cloud based service of your choice. <a name="configuration"></a> ### Configuration Laravel's email services may be configured via your application's `config/mail.php` configuration file. Each mailer configured within this file may have its own unique configuration and even its own unique "transport", allowing your application to use different email services to send certain email messages. For example, your application might use Postmark to send transactional emails while using Amazon SES to send bulk emails. Within your `mail` configuration file, you will find a `mailers` configuration array. This array contains a sample configuration entry for each of the major mail drivers / transports supported by Laravel, while the `default` configuration value determines which mailer will be used by default when your application needs to send an email message. <a name="driver-prerequisites"></a> ### Driver / Transport Prerequisites The API based drivers such as Mailgun and Postmark are often simpler and faster than sending mail via SMTP servers. Whenever possible, we recommend that you use one of these drivers. All of the API based drivers require the Guzzle HTTP library, which may be installed via the Composer package manager: composer require guzzlehttp/guzzle <a name="mailgun-driver"></a> #### Mailgun Driver To use the Mailgun driver, first install the Guzzle HTTP library. Then, set the `default` option in your `config/mail.php` configuration file to `mailgun`. Next, verify that your `config/services.php` configuration file contains the following options: 'mailgun' => [ 'domain' => env('MAILGUN_DOMAIN'), 'secret' => env('MAILGUN_SECRET'), ], If you are not using the United States [Mailgun region](https://documentation.mailgun.com/en/latest/api-intro.html#mailgun-regions), you may define your region's endpoint in the `services` configuration file: 'mailgun' => [ 'domain' => env('MAILGUN_DOMAIN'), 'secret' => env('MAILGUN_SECRET'), 'endpoint' => env('MAILGUN_ENDPOINT', 'api.eu.mailgun.net'), ], <a name="postmark-driver"></a> #### Postmark Driver To use the Postmark driver, install Postmark's SwiftMailer transport via Composer: composer require wildbit/swiftmailer-postmark Next, install the Guzzle HTTP library and set the `default` option in your `config/mail.php` configuration file to `postmark`. Finally, verify that your `config/services.php` configuration file contains the following options: 'postmark' => [ 'token' => env('POSTMARK_TOKEN'), ], If you would like to specify the Postmark message stream that should be used by a given mailer, you may add the `message_stream_id` configuration option to the mailer's configuration array. This configuration array can be found in your application's `config/mail.php` configuration file: 'postmark' => [ 'transport' => 'postmark', 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'), ], This way you are also able to set up multiple Postmark mailers with different message streams. <a name="ses-driver"></a> #### SES Driver To use the Amazon SES driver you must first install the Amazon AWS SDK for PHP. You may install this library via the Composer package manager: ```bash composer require aws/aws-sdk-php ``` Next, set the `default` option in your `config/mail.php` configuration file to `ses` and verify that your `config/services.php` configuration file contains the following options: 'ses' => [ 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), ], To utilize AWS [temporary credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html) via a session token, you may add a `token` key to your application's SES configuration: 'ses' => [ 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 'token' => env('AWS_SESSION_TOKEN'), ], If you would like to define [additional options](https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-email-2010-12-01.html#sendrawemail) that Laravel should pass to the AWS SDK's `SendRawEmail` method when sending an email, you may define an `options` array within your `ses` configuration: 'ses' => [ 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 'options' => [ 'ConfigurationSetName' => 'MyConfigurationSet', 'Tags' => [ ['Name' => 'foo', 'Value' => 'bar'], ], ], ], <a name="failover-configuration"></a> ### Failover Configuration Sometimes, an external service you have configured to send your application's mail may be down. In these cases, it can be useful to define one or more backup mail delivery configurations that will be used in case your primary delivery driver is down. To accomplish this, you should define a mailer within your application's `mail` configuration file that uses the `failover` transport. The configuration array for your application's `failover` mailer should contain an array of `mailers` that reference the order in which mail drivers should be chosen for delivery: 'mailers' => [ 'failover' => [ 'transport' => 'failover', 'mailers' => [ 'postmark', 'mailgun', 'sendmail', ], ], // ... ], Once your failover mailer has been defined, you should set this mailer as the default mailer used by your application by specifying its name as the value of the `default` configuration key within your application's `mail` configuration file: 'default' => env('MAIL_MAILER', 'failover'), <a name="generating-mailables"></a> ## Generating Mailables When building Laravel applications, each type of email sent by your application is represented as a "mailable" class. These classes are stored in the `app/Mail` directory. Don't worry if you don't see this directory in your application, since it will be generated for you when you create your first mailable class using the `make:mail` Artisan command: php artisan make:mail OrderShipped <a name="writing-mailables"></a> ## Writing Mailables Once you have generated a mailable class, open it up so we can explore its contents. First, note that all of a mailable class' configuration is done in the `build` method. Within this method, you may call various methods such as `from`, `subject`, `view`, and `attach` to configure the email's presentation and delivery. > {tip} You may type-hint dependencies on the mailable's `build` method. The Laravel [service container](/docs/{{version}}/container) automatically injects these dependencies. <a name="configuring-the-sender"></a> ### Configuring The Sender <a name="using-the-from-method"></a> #### Using The `from` Method First, let's explore configuring the sender of the email. Or, in other words, who the email is going to be "from". There are two ways to configure the sender. First, you may use the `from` method within your mailable class' `build` method: /** * Build the message. * * @return $this */ public function build() { return $this->from('example@example.com', 'Example') ->view('emails.orders.shipped'); } <a name="using-a-global-from-address"></a> #### Using A Global `from` Address However, if your application uses the same "from" address for all of its emails, it can become cumbersome to call the `from` method in each mailable class you generate. Instead, you may specify a global "from" address in your `config/mail.php` configuration file. This address will be used if no other "from" address is specified within the mailable class: 'from' => ['address' => 'example@example.com', 'name' => 'App Name'], In addition, you may define a global "reply_to" address within your `config/mail.php` configuration file: 'reply_to' => ['address' => 'example@example.com', 'name' => 'App Name'], <a name="configuring-the-view"></a> ### Configuring The View Within a mailable class' `build` method, you may use the `view` method to specify which template should be used when rendering the email's contents. Since each email typically uses a [Blade template](/docs/{{version}}/blade) to render its contents, you have the full power and convenience of the Blade templating engine when building your email's HTML: /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped'); } > {tip} You may wish to create a `resources/views/emails` directory to house all of your email templates; however, you are free to place them wherever you wish within your `resources/views` directory. <a name="plain-text-emails"></a> #### Plain Text Emails If you would like to define a plain-text version of your email, you may use the `text` method. Like the `view` method, the `text` method accepts a template name which will be used to render the contents of the email. You are free to define both an HTML and plain-text version of your message: /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->text('emails.orders.shipped_plain'); } <a name="view-data"></a> ### View Data <a name="via-public-properties"></a> #### Via Public Properties Typically, you will want to pass some data to your view that you can utilize when rendering the email's HTML. There are two ways you may make data available to your view. First, any public property defined on your mailable class will automatically be made available to the view. So, for example, you may pass data into your mailable class' constructor and set that data to public properties defined on the class: <?php namespace App\Mail; use App\Models\Order; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class OrderShipped extends Mailable { use Queueable, SerializesModels; /** * The order instance. * * @var \App\Models\Order */ public $order; /** * Create a new message instance. * * @param \App\Models\Order $order * @return void */ public function __construct(Order $order) { $this->order = $order; } /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped'); } } Once the data has been set to a public property, it will automatically be available in your view, so you may access it like you would access any other data in your Blade templates: <div> Price: {{ $order->price }} </div> <a name="via-the-with-method"></a> #### Via The `with` Method: If you would like to customize the format of your email's data before it is sent to the template, you may manually pass your data to the view via the `with` method. Typically, you will still pass data via the mailable class' constructor; however, you should set this data to `protected` or `private` properties so the data is not automatically made available to the template. Then, when calling the `with` method, pass an array of data that you wish to make available to the template: <?php namespace App\Mail; use App\Models\Order; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class OrderShipped extends Mailable { use Queueable, SerializesModels; /** * The order instance. * * @var \App\Models\Order */ protected $order; /** * Create a new message instance. * * @param \App\Models\Order $order * @return void */ public function __construct(Order $order) { $this->order = $order; } /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->with([ 'orderName' => $this->order->name, 'orderPrice' => $this->order->price, ]); } } Once the data has been passed to the `with` method, it will automatically be available in your view, so you may access it like you would access any other data in your Blade templates: <div> Price: {{ $orderPrice }} </div> <a name="attachments"></a> ### Attachments To add attachments to an email, use the `attach` method within the mailable class' `build` method. The `attach` method accepts the full 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 files to a message, you may also specify the display name and / or MIME type by passing an `array` as the second argument to the `attach` method: /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->attach('/path/to/file', [ 'as' => 'name.pdf', 'mime' => 'application/pdf', ]); } <a name="attaching-files-from-disk"></a> #### Attaching Files From Disk If you have stored a file on one of your [filesystem disks](/docs/{{version}}/filesystem), you may attach it to the email using the `attachFromStorage` method: /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->attachFromStorage('/path/to/file'); } If necessary, you may specify the file's attachment name and additional options using the second and third arguments to the `attachFromStorage` method: /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->attachFromStorage('/path/to/file', 'name.pdf', [ 'mime' => 'application/pdf' ]); } The `attachFromStorageDisk` method may be used if you need to specify a storage disk other than your default disk: /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->attachFromStorageDisk('s3', '/path/to/file'); } <a name="raw-data-attachments"></a> #### Raw Data Attachments The `attachData` method may be used to attach a raw string of bytes as an attachment. For example, you might use this method if you have generated a PDF in memory and want to attach it to the email without writing it to disk. The `attachData` method accepts the raw data bytes as its first argument, the name of the file as its second argument, and an array of options as its third argument: /** * Build the message. * * @return $this */ public function build() { return $this->view('emails.orders.shipped') ->attachData($this->pdf, 'name.pdf', [ 'mime' => 'application/pdf', ]); } <a name="inline-attachments"></a> ### Inline Attachments Embedding inline images into your emails is typically cumbersome; however, Laravel provides a convenient way to attach images to your emails. To embed an inline image, use the `embed` method on the `$message` variable within your email template. Laravel automatically makes the `$message` variable available to all of your email templates, so you don't need to worry about passing it in manually: <body> Here is an image: <img src="{{ $message->embed($pathToImage) }}"> </body> > {note} The `$message` variable is not available in plain-text message templates since plain-text messages do not utilize inline attachments. <a name="embedding-raw-data-attachments"></a> #### Embedding Raw Data Attachments If you already have a raw image data string you wish to embed into an email template, you may call the `embedData` method on the `$message` variable. When calling the `embedData` method, you will need to provide a filename that should be assigned to the embedded image: <body> Here is an image from raw data: <img src="{{ $message->embedData($data, 'example-image.jpg') }}"> </body> <a name="customizing-the-swiftmailer-message"></a> ### Customizing The SwiftMailer Message The `withSwiftMessage` method of the `Mailable` base class allows you to register a closure which will be invoked with the SwiftMailer message instance before sending the message. This gives you an opportunity to deeply customize the message before it is delivered: /** * Build the message. * * @return $this */ public function build() { $this->view('emails.orders.shipped'); $this->withSwiftMessage(function ($message) { $message->getHeaders()->addTextHeader( 'Custom-Header', 'Header Value' ); }); return $this; } <a name="markdown-mailables"></a> ## Markdown Mailables Markdown mailable messages allow you to take advantage of the pre-built templates and components of [mail notifications](/docs/{{version}}/notifications#mail-notifications) in your mailables. Since the messages are written in Markdown, Laravel is able to render beautiful, responsive HTML templates for the messages while also automatically generating a plain-text counterpart. <a name="generating-markdown-mailables"></a> ### Generating Markdown Mailables To generate a mailable with a corresponding Markdown template, you may use the `--markdown` option of the `make:mail` Artisan command: php artisan make:mail OrderShipped --markdown=emails.orders.shipped Then, when configuring the mailable within its `build` method, call the `markdown` method instead of the `view` method. The `markdown` method accepts the name of the Markdown template and an optional array of data to make available to the template: /** * Build the message. * * @return $this */ public function build() { return $this->from('example@example.com') ->markdown('emails.orders.shipped', [ 'url' => $this->orderUrl, ]); } <a name="writing-markdown-messages"></a> ### Writing Markdown Messages Markdown mailables use a combination of Blade components and Markdown syntax which allow you to easily construct mail messages while leveraging Laravel's pre-built email UI components: @component('mail::message') # Order Shipped Your order has been shipped! @component('mail::button', ['url' => $url]) View Order @endcomponent Thanks,<br> {{ config('app.name') }} @endcomponent > {tip} Do not use excess indentation when writing Markdown emails. Per Markdown standards, Markdown parsers will render indented content as code blocks. <a name="button-component"></a> #### Button Component The button component renders a centered button link. The component accepts two arguments, a `url` and an optional `color`. Supported colors are `primary`, `success`, and `error`. You may add as many button components to a message as you wish: @component('mail::button', ['url' => $url, 'color' => 'success']) View Order @endcomponent <a name="panel-component"></a> #### Panel Component The panel component renders the given block of text in a panel that has a slightly different background color than the rest of the message. This allows you to draw attention to a given block of text: @component('mail::panel') This is the panel content. @endcomponent <a name="table-component"></a> #### Table Component The table component allows you to transform a Markdown table into an HTML table. The component accepts the Markdown table as its content. Table column alignment is supported using the default Markdown table alignment syntax: @component('mail::table') | Laravel | Table | Example | | ------------- |:-------------:| --------:| | Col 2 is | Centered | $10 | | Col 3 is | Right-Aligned | $20 | @endcomponent <a name="customizing-the-components"></a> ### Customizing The Components You may export all of the Markdown mail components to your own application for customization. To export the components, use the `vendor:publish` Artisan command to publish the `laravel-mail` asset tag: php artisan vendor:publish --tag=laravel-mail This command will publish the Markdown mail components to the `resources/views/vendor/mail` directory. The `mail` directory will contain an `html` and a `text` directory, each containing their respective representations of every available component. You are free to customize these components however you like. <a name="customizing-the-css"></a> #### Customizing The CSS After exporting the components, the `resources/views/vendor/mail/html/themes` directory will contain a `default.css` file. You may customize the CSS in this file and your styles will automatically be converted to inline CSS styles within the HTML representations of your Markdown mail messages. If you would like to build an entirely new theme for Laravel's Markdown components, you may place a CSS file within the `html/themes` directory. After naming and saving your CSS file, update the `theme` option of your application's `config/mail.php` configuration file to match the name of your new theme. To customize the theme for an individual mailable, you may set the `$theme` property of the mailable class to the name of the theme that should be used when sending that mailable. <a name="sending-mail"></a> ## Sending Mail To send a message, use the `to` method on the `Mail` [facade](/docs/{{version}}/facades). The `to` method accepts an email address, a user instance, or a collection of users. If you pass an object or collection of objects, the mailer will automatically use their `email` and `name` properties when determining the email's recipients, so make sure these attributes are available on your objects. Once you have specified your recipients, you may pass an instance of your mailable class to the `send` method: <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Mail\OrderShipped; use App\Models\Order; use Illuminate\Http\Request; use Illuminate\Support\Facades\Mail; class OrderShipmentController extends Controller { /** * Ship the given order. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $order = Order::findOrFail($request->order_id); // Ship the order... Mail::to($request->user())->send(new OrderShipped($order)); } } You are not limited to just specifying the "to" recipients when sending a message. You are free to set "to", "cc", and "bcc" recipients by chaining their respective methods together: Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->send(new OrderShipped($order)); <a name="looping-over-recipients"></a> #### Looping Over Recipients Occasionally, you may need to send a mailable to a list of recipients by iterating over an array of recipients / email addresses. However, since the `to` method appends email addresses to the mailable's list of recipients, each iteration through the loop will send another email to every previous recipient. Therefore, you should always re-create the mailable instance for each recipient: foreach (['taylor@example.com', 'dries@example.com'] as $recipient) { Mail::to($recipient)->send(new OrderShipped($order)); } <a name="sending-mail-via-a-specific-mailer"></a> #### Sending Mail Via A Specific Mailer By default, Laravel will send email using the mailer configured as the `default` mailer in your application's `mail` configuration file. However, you may use the `mailer` method to send a message using a specific mailer configuration: Mail::mailer('postmark') ->to($request->user()) ->send(new OrderShipped($order)); <a name="queueing-mail"></a> ### Queueing Mail <a name="queueing-a-mail-message"></a> #### Queueing A Mail Message Since sending email messages can negatively impact the response time of your application, many developers choose to queue email messages for background sending. Laravel makes this easy using its built-in [unified queue API](/docs/{{version}}/queues). To queue a mail message, use the `queue` method on the `Mail` facade after specifying the message's recipients: Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->queue(new OrderShipped($order)); This method will automatically take care of pushing a job onto the queue so the message is sent in the background. You will need to [configure your queues](/docs/{{version}}/queues) before using this feature. <a name="delayed-message-queueing"></a> #### Delayed Message Queueing If you wish to delay the delivery of a queued email message, you may use the `later` method. As its first argument, the `later` method accepts a `DateTime` instance indicating when the message should be sent: Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->later(now()->addMinutes(10), new OrderShipped($order)); <a name="pushing-to-specific-queues"></a> #### Pushing To Specific Queues Since all mailable classes generated using the `make:mail` command make use of the `Illuminate\Bus\Queueable` trait, you may call the `onQueue` and `onConnection` methods on any mailable class instance, allowing you 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); <a name="queueing-by-default"></a> #### Queueing By Default If you have mailable classes that you want to always be queued, you may implement the `ShouldQueue` contract on the class. Now, even if you call the `send` method when mailing, the mailable will still be queued since it implements the contract: use Illuminate\Contracts\Queue\ShouldQueue; class OrderShipped extends Mailable implements ShouldQueue { // } <a name="queued-mailables-and-database-transactions"></a> #### Queued Mailables & Database Transactions When queued mailables are dispatched within database transactions, they may be processed by the queue before the database transaction has committed. When this happens, any updates you have made to models or database records during the database transaction may not yet be reflected in the database. In addition, any models or database records created within the transaction may not exist in the database. If your mailable depends on these models, unexpected errors can occur when the job that sends the queued mailable is processed. If your queue connection's `after_commit` configuration option is set to `false`, you may still indicate that a particular queued mailable should be dispatched after all open database transactions have been committed by calling the `afterCommit` method when sending the mail message: Mail::to($request->user())->send( (new OrderShipped($order))->afterCommit() ); Alternatively, you may call the `afterCommit` method from your mailable's constructor: <?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class OrderShipped extends Mailable implements ShouldQueue { use Queueable, SerializesModels; /** * Create a new message instance. * * @return void */ public function __construct() { $this->afterCommit(); } } > {tip} To learn more about working around these issues, please review the documentation regarding [queued jobs and database transactions](/docs/{{version}}/queues#jobs-and-database-transactions). <a name="rendering-mailables"></a> ## Rendering Mailables Sometimes you may wish to capture the HTML content of a mailable without sending it. To accomplish this, you may call the `render` method of the mailable. This method will return the evaluated HTML content of the mailable as a string: use App\Mail\InvoicePaid; use App\Models\Invoice; $invoice = Invoice::find(1); return (new InvoicePaid($invoice))->render(); <a name="previewing-mailables-in-the-browser"></a> ### Previewing Mailables In The Browser When designing a mailable's template, it is convenient to quickly preview the rendered mailable in your browser like a typical Blade template. For this reason, Laravel allows you to return any mailable directly from a route closure or controller. When a mailable is returned, it will be rendered and displayed in the browser, allowing you to quickly preview its design without needing to send it to an actual email address: Route::get('/mailable', function () { $invoice = App\Models\Invoice::find(1); return new App\Mail\InvoicePaid($invoice); }); > {note} [Inline attachments](#inline-attachments) will not be rendered when a mailable is previewed in your browser. To preview these mailables, you should send them to an email testing application such as [MailHog](https://github.com/mailhog/MailHog) or [HELO](https://usehelo.com). <a name="localizing-mailables"></a> ## Localizing Mailables Laravel allows you to send mailables in a locale other than the request's current locale, and will even remember this locale if the mail is queued. To accomplish this, the `Mail` facade offers a `locale` method to set the desired language. The application will change into this locale when the mailable's template is being evaluated and then revert back to the previous locale when evaluation is complete: Mail::to($request->user())->locale('es')->send( new OrderShipped($order) ); <a name="user-preferred-locales"></a> ### User Preferred Locales Sometimes, applications store each user's preferred locale. By implementing the `HasLocalePreference` contract on one or more of your models, you may instruct Laravel to use this stored locale when sending mail: use Illuminate\Contracts\Translation\HasLocalePreference; class User extends Model implements HasLocalePreference { /** * Get the user's preferred locale. * * @return string */ public function preferredLocale() { return $this->locale; } } Once you have implemented the interface, Laravel will automatically use the preferred locale when sending mailables and notifications to the model. Therefore, there is no need to call the `locale` method when using this interface: Mail::to($request->user())->send(new OrderShipped($order)); <a name="testing-mailables"></a> ## Testing Mailables Laravel provides several convenient methods for testing that your mailables contain the content that you expect. These methods are: `assertSeeInHtml`, `assertDontSeeInHtml`, `assertSeeInText`, and `assertDontSeeInText`. As you might expect, the "HTML" assertions assert that the HTML version of your mailable contains a given string, while the "text" assertions assert that the plain-text version of your mailable contains a given string: use App\Mail\InvoicePaid; use App\Models\User; public function test_mailable_content() { $user = User::factory()->create(); $mailable = new InvoicePaid($user); $mailable->assertSeeInHtml($user->email); $mailable->assertSeeInHtml('Invoice Paid'); $mailable->assertSeeInText($user->email); $mailable->assertSeeInText('Invoice Paid'); } <a name="testing-mailable-sending"></a> #### Testing Mailable Sending We suggest testing the content of your mailables separately from your tests that assert that a given mailable was "sent" to a specific user. To learn how to test that mailables were sent, check out our documentation on the [Mail fake](/docs/{{version}}/mocking#mail-fake). <a name="mail-and-local-development"></a> ## Mail & Local Development When developing an application that sends email, you probably don't want to actually send emails to live email addresses. Laravel provides several ways to "disable" the actual sending of emails during local development. <a name="log-driver"></a> #### Log Driver Instead of sending your emails, the `log` mail driver will write all email messages to your log files for inspection. Typically, this driver would only be used during local development. For more information on configuring your application per environment, check out the [configuration documentation](/docs/{{version}}/configuration#environment-configuration). <a name="mailtrap"></a> #### HELO / Mailtrap / MailHog Alternatively, you may use a service like [HELO](https://usehelo.com) or [Mailtrap](https://mailtrap.io) and the `smtp` driver to send your email messages to a "dummy" mailbox where you may view them in a true email client. This approach has the benefit of allowing you to actually inspect the final emails in Mailtrap's message viewer. If you are using [Laravel Sail](/docs/{{version}}/sail), you may preview your messages using [MailHog](https://github.com/mailhog/MailHog). When Sail is running, you may access the MailHog interface at: `http://localhost:8025`. <a name="using-a-global-to-address"></a> #### Using A Global `to` Address Finally, you may specify a global "to" address by invoking the `alwaysTo` method offered by the `Mail` facade. Typically, this method should be called from the `boot` method of one of your application's service providers: use Illuminate\Support\Facades\Mail; /** * Bootstrap any application services. * * @return void */ public function boot() { if ($this->app->environment('local')) { Mail::alwaysTo('taylor@example.com'); } } <a name="events"></a> ## Events Laravel fires two events during the process of sending mail messages. The `MessageSending` event is fired prior to a message being sent, while the `MessageSent` event is fired after a message has been sent. Remember, these events are fired when the mail is being *sent*, not when it is queued. You may register event listeners for this event in your `App\Providers\EventServiceProvider` service provider: /** * 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', ], ];

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/brianirish/laravel-mcp-companion'

If you have feedback or need assistance with the MCP directory API, please join our Discord server