Laravel - Sending Email
Laravel - Sending Email
Section titled “Laravel - Sending Email”Laravel provides a clean, simple API over the popular Symfony Mailer component (formerly SwiftMailer), allowing you to quickly get started sending mail through a local or cloud-based service of your choice.
Configuration
Section titled “Configuration”Laravel’s email services are configured via your application’s .env file and the config/mail.php configuration file. The .env file allows you to quickly change mail drivers and credentials without modifying code.
Common .env mail variables:
MAIL_MAILER=smtpMAIL_HOST=mailpitMAIL_PORT=1025MAIL_USERNAME=nullMAIL_PASSWORD=nullMAIL_ENCRYPTION=nullMAIL_FROM_ADDRESS="hello@example.com"MAIL_FROM_NAME="${APP_NAME}"Explanation of common options:
MAIL_MAILER: The driver to use (e.g.,smtp,ses,mailgun,postmark,sendmail,log). For local development,log(writes emails to log files) or a tool like Mailpit/MailHog (smtpconfigured to its host/port) is highly recommended.MAIL_HOST,MAIL_PORT,MAIL_USERNAME,MAIL_PASSWORD,MAIL_ENCRYPTION: Credentials for SMTP.MAIL_FROM_ADDRESS,MAIL_FROM_NAME: The default sender address and name for your emails.
For services like Gmail, you might need to generate an “App Password” if 2-Step Verification is enabled. Example for Gmail SMTP:
MAIL_MAILER=smtpMAIL_HOST=smtp.gmail.comMAIL_PORT=587MAIL_USERNAME=your-gmail-username@gmail.comMAIL_PASSWORD=your-gmail-app-passwordMAIL_ENCRYPTION=tlsMAIL_FROM_ADDRESS="your-gmail-username@gmail.com"MAIL_FROM_NAME="Your Application Name"After modifying your .env file, clear the config cache: php artisan config:clear.
Generating Mailables
Section titled “Generating Mailables”In Laravel, each type of email sent by your application is represented as a “mailable” class. These classes are stored in the app/Mail directory. You can generate a new mailable class using the Artisan command:
php artisan make:mail OrderShippedThis command will create app/Mail/OrderShipped.php. A mailable class contains methods for building the email, such as defining its sender, recipients, subject, and the view to use.
Configuring the Mailable:
Section titled “Configuring the Mailable:”Within a mailable class, you typically configure its properties (data to pass to the view) in the constructor and build the email message within the build method (older versions) or envelope and content methods (newer versions).
Example Mailable (OrderShipped.php - modern syntax with Envelope and Content):
<?php
namespace App\Mail;
use App\Models\Order; // Assuming you have an Order modeluse Illuminate\Bus\Queueable;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Mail\Mailable;use Illuminate\Mail\Mailables\Content;use Illuminate\Mail\Mailables\Envelope;use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable implements ShouldQueue // Optional: for queueing{ use Queueable, SerializesModels;
public Order $order;
/** * Create a new message instance. */ public function __construct(Order $order) { $this->order = $order; }
/** * Get the message envelope. */ public function envelope(): Envelope { return new Envelope( from: new \Illuminate\Mail\Mailables\Address('noreply@example.com', 'Example App'), subject: 'Your Order Has Shipped!', ); }
/** * Get the message content definition. */ public function content(): Content { return new Content( view: 'emails.orders.shipped', // Blade view for the email // with: ['orderName' => $this->order->name], // Alternative to public properties ); }
/** * Get the attachments for the message. * * @return array<int, \Illuminate\Mail\Mailables\Attachment> */ public function attachments(): array { return [ // Attachment::fromPath(public_path('/path/to/file.pdf')), ]; }}Creating the Email View (resources/views/emails/orders/shipped.blade.php):
Section titled “Creating the Email View (resources/views/emails/orders/shipped.blade.php):”<!DOCTYPE html><html><head> <title>Order Shipped</title></head><body> <h1>Hi, {{ $order->customer_name }}!</h1> {{-- Accessing public property from Mailable --}} <p>Your order #{{ $order->id }} has been shipped.</p> <p>Thank you for your purchase!</p></body></html>Sending Mail
Section titled “Sending Mail”To send a mailable, use the to method on the Mail facade. The to method accepts an email address, a user instance, or a collection of users. Then, call the send method with an instance of your mailable class.
Example in a Controller:
<?php
namespace App\Http\Controllers;
use App\Mail\OrderShipped;use App\Models\Order; // Assuming Order model existsuse Illuminate\Http\Request;use Illuminate\Support\Facades\Mail;
class OrderController extends Controller{ public function ship(Request $request, string $orderId) { $order = Order::findOrFail($orderId); // Fetch the order
// Send the email Mail::to($order->customer_email) // Or $request->user() if sending to the logged-in user // ->cc($moreUsers) // ->bcc($evenMoreUsers) ->send(new OrderShipped($order));
return redirect()->route('orders.show', $orderId)->with('status', 'Order shipped email sent!'); }}You would typically call this ship method from a route definition.
Sending Plain Text Emails (using Mail::raw or text view in Mailable)
Section titled “Sending Plain Text Emails (using Mail::raw or text view in Mailable)”If you need to send a simple plain text email without a Blade template, you can use Mail::raw():
Mail::raw('This is a plain text email body.', function ($message) { $message->to('recipient@example.com') ->subject('Simple Text Email');});For Mailables, you can specify a text view in the Content object:
public function content(): Content{ return new Content( view: 'emails.orders.shipped', // HTML view text: 'emails.orders.shipped_plain' // Plain text view );}Attachments in Mailables
Section titled “Attachments in Mailables”To add attachments, use the attach method within the Mailable’s attachments method or directly on the Envelope (or build method in older versions).
// In Mailable's attachments() method (newer Laravel):use Illuminate\Mail\Mailables\Attachment;
public function attachments(): array{ return [ Attachment::fromPath(public_path('documents/invoice.pdf')) ->as('customer-invoice.pdf') ->withMime('application/pdf'), Attachment::fromStorageDisk('s3', 'avatars/profile.jpg'), // Attach from a storage disk ];}Queuing Mail
Section titled “Queuing Mail”Sending emails can significantly slow down your application’s response time. Laravel allows you to easily queue emails for background sending. Implement the ShouldQueue interface on your mailable class.
class OrderShipped extends Mailable implements ShouldQueue{ ... }Then, when you call Mail::send(), Laravel will automatically push the job to your queue. You’ll need to have a queue worker running: php artisan queue:work.
Local Development with Mailpit/MailHog
Section titled “Local Development with Mailpit/MailHog”During local development, you often don’t want to send real emails. Tools like Mailpit or MailHog act as local SMTP servers that catch all outgoing emails and display them in a web interface. This is invaluable for testing.
Configure your .env to point to Mailpit (usually running on localhost:1025):
MAIL_MAILER=smtpMAIL_HOST=localhost # or 127.0.0.1MAIL_PORT=1025MAIL_USERNAME=nullMAIL_PASSWORD=nullMAIL_ENCRYPTION=null # or 'tls' if Mailpit is configured for itCommon Learning Obstacle: Email Configuration Issues
Many beginners struggle with email sending due to incorrect .env configuration or issues with their mail server (e.g., Gmail blocking less secure apps, ISP blocking SMTP ports). Using MAIL_MAILER=log or Mailpit during development can help isolate whether the issue is with Laravel’s code or the mail server setup.
Additional Resources:
Section titled “Additional Resources:”For comprehensive details, refer to the official Laravel documentation on Mail: https://laravel.com/docs/mail