How to Send Mail in Laravel Using Mailtrap

There are many ways to send mail in Laravel. Mailtrap in Laravel provides a quick and easy way for developers to test mail in Laravel. In this topic, we will develop a Laravel 10 application to send mail in Laravel using Mailtrap. It will have a simple form to send mail and the controller will get details from the submitted form to send mail using the Laravel mail method. We will use Mailtrap for receiving mail in the Mailtrap inbox.

During development, you need to test your code for sending mail in Laravel, so, it will help you verify that "send mail" is working for your project.

Laravel mail using mailtrap

Create a Laravel project

Let us create a project in Laravel 10. We will give the project name as lara_mail.


composer create-project --prefer-dist laravel/laravel lara_mail

MySQL Database and Migration

Update .env file for database details. We are using a MySQL database named 'lara_mail', so we updated the file as below:


DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=lara_mail
DB_USERNAME=root
DB_PASSWORD=

We will create a custom table called 'mail_logs' to store details of emails sent. Let us create a migration for this table. Go to your project folder and run the below command for migration from the VS code terminal.


php artisan make:model MailLog -m

It will create the migration file name <yyyy_mm_dd_xxxxxx>_create_mail_logs_table.php under the database/migrations folder and a Model named "MailLog" under app/Models folder.

Migration scripts for mail_logs


<?php
  public function up(): void
    {
        Schema::create('mail_logs', function (Blueprint $table) {
            $table->id();
            $table->string('from_email');
            $table->string('to_email');
            $table->string('subject');
            $table->string('mail_body');
            $table->dateTime('date_sent')->default(DB::raw('now()'));
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('mail_logs');
    }

Let us now run the Laravel migration to create the new table and the default tables for Laravel. Run the below command from the project folder to create the tables.


php artisan migrate

After running the migration, the below tables will be created.

mailtrap laravel

Update the Model

The MailLog model is already created, let us update it to add $fillable columns.


<?php
class MailLog extends Model
{
    use HasFactory;

    protected $fillable = ['from_email', 'to_email', 'subject', 'mail_body', 'date_sent'];
}

Setup Mailtrap account

For sending mail, you can create a Mailtrap account and add the settings in your .env file. If you do not have an account in Mailtrap, go to https://mailtrap.io/ and sign up. Once you complete the signup, go to "My Inbox", and you will get your credentials. Get the Host, Port, Username and Password to update your .env file as shown below:


MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=tls

The Controller

We will create a controller named "MailController" with a method to get details from a submitted form and send mail using Mailtrap.

Let us run the below command from the terminal to create the controller:


php artisan make:controller MailController

We will have a form to enter the email ID to whom the message is to be sent, the subject, and a mail body. Once the user submits the form using the Send button, the controller method will process them and send the mail.

mailtrap laravel

There are two methods in the controller, one for the form, sendMail(), and the other for sending mail after the form is submitted, postSendMail().


public function sendMail(){
        $title = "Send Mail";
        return view('send_mail', compact('title'));
    }

public function postSendMail(Request $request){
        $request->validate(
            [
                'to_email'    => 'required|email|max:255',
                'subject'     => 'required|max:255',
                'mail_body'   => 'required',
            ]
        );

        DB::beginTransaction();
        try {
            $mail = new MailLog;
            $mail->from_email   = env('MAIL_FROM_ADDRESS', 'admin@test.com');
            $mail->to_email     = $request->to_email;
            $mail->subject      = $request->subject;
            $mail->mail_body    = $request->mail_body;
            
            $mail_body = $mail->mail_body;
            $mail->save();

            // send mail

            Mail::send('mail.mail_template', ['mail_body' => $mail_body], function ($message) use ($request) {
                $message->to($request->to_email);
                $message->subject($request->subject);
            });
            DB::commit();
            return redirect("/")->withSuccess('Email is sent to ' . $request->to_email);
        } catch (Exception $e) {
            DB::rollBack();
            return redirect("/")->withErrors('Some Error occurred, please try later');
        }
    }

In the postSendMail() method, I am taking the values from the form, validating them and saving the details in the "mail_logs" table. After that mail is sent using "mail_template" which is a view with the mail_body as the data to the view. Note that "to" and "subject" parameters are also used in the form.

Routes

There are two routes as given below:


Route::get('/', [MailController::class, 'sendMail'])->name('sendmail.form');
Route::post('/sendmail', [MailController::class, 'postSendMail'])->name('sendmail.post');

Laravel blade views

We have one view for the form to send mail. Also, I am using a loader when the form is submitted. So, when the form is submitted loader is called using jQuery. Below are the views along with the layout:

resources/views/layouts/header.blade.php


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>{{$title}}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
    <meta name="_token" content="{{ csrf_token() }}">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" type="text/css" media="screen" href="{{asset('css/style.css')}}" />
</head>

resources/views/layouts/footer.blade.php


<div class="copyright">
  <p>
      © Copyright 2023. All Rights
      Reserved.
  </p>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>

resources/views/layouts/master.blade.php


@include('layouts.header')
<body>
        <div class="container">
            
            @yield('main-content')
        </div>
    @include('layouts.footer')
    @stack('js')
</body>

</html>

Form to send mail.

resources/views/send_mail.blade.php


@extends('layouts.master')
@section('main-content')
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">
                    <h3>Send Mail in Laravel</h3>
                </div>
                <div class="card-body">
                    @if (session('success'))
                        <div class="alert alert-success">
                            {{ session('success') }}
                        </div>
                    @endif
                    @if (session('error'))
                        <div class="alert alert-danger">
                            {{ session('error') }}
                        </div>
                    @endif
                    <form id = "thisForm" action="{{ route('sendmail.post') }}" method="post">
                        @csrf
                        <div class="form-group mb-3">
                            <label for="to_email">To Email</label>
                            <input type="text" placeholder="Enter Email Id " name="to_email" class="form-control mt-2"
                                value="{{ old('to_email') }}" />
                            <div class="error">
                                @error('to_email')
                                    {{ $message }}
                                @enderror
                            </div>
                        </div>

                        <div class="form-group mb-3">
                            <label for="subject">Subject</label>
                            <input type="text" name="subject" placeholder="Enter Subject" class="form-control mt-2"
                                value="{{ old('subject') }}" />
                            <div class="error">
                                @error('subject')
                                    {{ $message }}
                                @enderror
                            </div>
                        </div>

                        <div class="form-group mb-3">
                            <label for="password">Email Body</label>
                            <textarea class="form-control mt-2" name="mail_body" placeholder="Type Text to send">{{ old('mail_body') }}</textarea>
                            <div class="error">
                                @error('mail_body')
                                    {{ $message }}
                                @enderror
                            </div>
                        </div>

                        <div class="form-group d-flex justify-content-end">
                            <button type="submit" class="submit-btn">Send</button>
                        </div>
                        <div id ="loader"></div>
                    </form>
                </div>
            </div>
        </div>
    </div>
@endsection
@push('js')
<script>
    $("#thisForm").submit(function() {
        $(".submit-btn").attr("disabled", true);
        $("#loader").show();
    });
</script>
@endpush

Mail Template.

resources/views/mail/mail_template.blade.php


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
        h1 {
            color: rgb(43, 21, 235);
        }
    </style>
</head>

<body>
    <h1>Laravel Email using Mailtrap</h1>

    <p>{{$mail_body}}</p>
</body>

</html>

I am using some styles and the stylesheet is given below:

public/css/style.css


* {box-sizing: border-box;
}
body {
  margin: 0;
  font-family: Helvetica, sans-serif;;
}
h1,h4, h3 {
  text-align: center;
  margin-bottom: 20px;
  margin-top: 10px;
}

footer{
    text-align: center;
}

.container{
    min-height:700px;
}
.custom-btn {
    background-color: #2c3691;
    color: #fff !important;
    padding: 11px 16px !important;
    border-radius: 7px;
}
.submit-btn {
    background-color: #2c3691;
    color: #fff !important;
    padding: 5px 16px !important;
    border-radius: 7px;
}

.error{
  color: red;
}

li {
    list-style: none;
    font-family: var(--body-font);
}

a {
    text-decoration: none;
}

ul {
    margin: 0;
}

.navbar_inner nav ul li a {
    color: var(--dark);
    font-weight: 500;
    font-size: 16px;
}

.navbar_inner nav ul li a.active {
    color: var(--orange);
}

.navbar_inner nav ul li {
    padding: 0px 10px;
}

.navbar_inner nav ul li:last-child {
    padding-right: 0;
}

.navbar_section {
    box-shadow: var(--shadow1);
    position: relative;
}

.copyright {
    position: relative;
    text-align: center;
    background-color: #11195a;
}

.copyright p {
    padding: 0;
    margin: 0;
    color: #fff;
    font-size: 14px;
    padding: 10px;
}

#loader {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    background: rgba(0,0,0,0.75) url("/img/loader.gif") no-repeat center center;
    z-index: 99999;
}

@media  only screen and (max-width: 768px) {
    .custom-btn {
        background-color: var(--orange);
        color: #fff !important;
        padding: 8px 7px !important;
        border-radius: 7px;
    }
}

Test the application

From the project root, start the php development server:


php artisan serve

From the browser start localhost:8000. Send an email using the form and check if you get the mail in your mailtrap inbox. Also, check that a row is inserted in the mail_logs table with the details of the email.

Below is a test mail I received when the form was submitted :

send email in laravel

download source code for Laravel mail using mailtrap Download code from Github.

Post a Comment

Save my Name and Email id for future comments