Laravel mail: pass string instead of view
Stefan Bogdanescu
Founder & Senior Architect
Laravel Mail: Passing Plain Content Instead of Blade Views
When building robust email systems in Laravel, developers often encounter a common point of confusion: how to inject dynamic content directly into an email when that content is stored in your database rather than being rendered via a separate Blade file. The standard Mail::send() function often seems geared toward file paths, which can be misleading when dealing with application-level data.
This post will dive deep into the correct, idiomatic Laravel approach to sending emails containing plain, dynamic string content directly from your Eloquent models or controller logic.
Understanding the Mail System in Laravel
Laravel’s mail system is designed around Mailable classes. A Mailable class acts as a blueprint for an email, encapsulating both the data (the variables) and the presentation logic (how that data is formatted). This separation of concerns is crucial for maintainability and reusability.
When you use Mail::send(), it typically expects an instance of a Mailable object. If you want to send simple, raw text or HTML, you still need an object to define what the email looks like. The goal isn't just passing a string; it's passing that string within a structure that Laravel knows how to serialize into an email format.
The Developer Solution: Using Mailable for Dynamic Content
Instead of trying to force raw strings directly into Mail::send(), the best practice is to leverage your Mailable class to handle the injection of database content. This keeps your application logic clean and ensures that the data context is correctly managed.
Here is a step-by-step guide on how to achieve this:
Step 1: Define the Mailable Class
Create a Mailable class where you define the structure and use the data passed to it to construct the email body. This is where you pull your dynamic content from the database.
// app/Mail/ConfirmationMail.php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ConfirmationMail extends Mailable
{
use Queueable, SerializesModels;
public $userName;
public $confirmationMessage;
/**
* Create a new Mailable instance.
*/
public function __construct($userName, $confirmationMessage)
{
$this->userName = $userName;
$this->confirmationMessage = $confirmationMessage;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
// Constructing the plain content directly from instance properties
$content = "Hello, " . $this->userName . "!\n\n" . $this->confirmationMessage;
return $this->view('emails.confirmation', [
'content' => $content
]);
}
}
Step 2: Sending the Mail
Now, when you send the mail, you pass the necessary data (which might come from an Eloquent query) to the Mailable constructor.
use App\Mail\ConfirmationMail;
use Illuminate\Support\Facades\Mail;
// Assume $user is retrieved from the database
$user = \App\Models\User::find(1);
$messageBody = "Welcome aboard! Your account is now active.";
// Send the mail by instantiating the Mailable with your dynamic content
Mail::send(new ConfirmationMail($user->name, $messageBody));
Why This Approach Is Superior
Passing raw strings directly to Mail::send() bypasses Laravel's powerful templating and queueing mechanisms. By using a Mailable:
- Data Integrity: You ensure that the data being sent is tied directly to your application's models, preventing errors from static string manipulation.
- Separation of Concerns (SoC): The Mailable handles how the email is built, while the controller or service layer handles what data is needed (from the database). This aligns perfectly with good architectural principles often discussed in Laravel documentation and best practices related to application structure on laravelcompany.com.
- Maintainability: If you later decide to switch from plain text emails to HTML emails, you only need to modify the
build()method within the Mailable, leaving your sending logic untouched.
Conclusion
While it might seem tempting to use $content = "..." and pass it directly to a mail function, the robust solution in Laravel is to encapsulate that content within a dedicated Mailable class. This pattern ensures that your email delivery system remains scalable, testable, and easy to maintain as your application grows. By embracing Mailable objects, you are writing code that leverages the full potential of the Laravel framework for complex tasks like sending emails.
Note: Blog content is currently available in English.