PHPackages                             adesin-fr/laravel-mail-2fa - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Mail &amp; Notifications](/categories/mail)
4. /
5. adesin-fr/laravel-mail-2fa

ActiveLibrary[Mail &amp; Notifications](/categories/mail)

adesin-fr/laravel-mail-2fa
==========================

Laravel 2FA package using email OTP codes with InertiaJS support

2026.2.1(4mo ago)014MITPHPPHP ^8.2

Since Jan 6Pushed 4mo agoCompare

[ Source](https://github.com/Adesin-fr/laravel-mail-2fa)[ Packagist](https://packagist.org/packages/adesin-fr/laravel-mail-2fa)[ RSS](/packages/adesin-fr-laravel-mail-2fa/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (7)Versions (2)Used By (0)

Laravel Mail 2FA
================

[](#laravel-mail-2fa)

A simple Laravel package for two-factor authentication via email OTP codes with InertiaJS support.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11.0+
- InertiaJS with Vue 3

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require adesin-fr/laravel-mail-2fa
```

Publishing Assets
-----------------

[](#publishing-assets)

### Publish all assets at once:

[](#publish-all-assets-at-once)

```
php artisan vendor:publish --tag=mail2fa
```

### Or publish individually:

[](#or-publish-individually)

**Configuration file:**

```
php artisan vendor:publish --tag=mail2fa-config
```

**Database migrations:**

```
php artisan vendor:publish --tag=mail2fa-migrations
```

**Email views (Blade templates):**

```
php artisan vendor:publish --tag=mail2fa-views
```

**Inertia Vue components:**

```
php artisan vendor:publish --tag=mail2fa-inertia
```

Run Migrations
--------------

[](#run-migrations)

The package adds `mfa_code` and `mfa_expires_at` columns to your `users` table:

```
php artisan migrate
```

Configuration
-------------

[](#configuration)

After publishing, edit `config/mail2fa.php`:

```
return [
    // Enable/disable 2FA globally
    'enabled' => env('MAIL2FA_ENABLED', true),

    // Length of the verification code (default: 6)
    'code_length' => env('MAIL2FA_CODE_LENGTH', 6),

    // Code expiration in minutes (default: 10)
    'code_expiration' => env('MAIL2FA_CODE_EXPIRATION', 10),

    // Cooldown between resend requests in seconds (default: 60)
    'resend_cooldown' => env('MAIL2FA_RESEND_COOLDOWN', 60),

    // Verification session lifetime in minutes (null = entire session)
    'verification_lifetime' => env('MAIL2FA_VERIFICATION_LIFETIME', null),

    // Route configuration
    'routes' => [
        'prefix' => '2fa',
        'middleware' => ['web', 'auth'],
        'names' => [
            'verify' => 'mail2fa.verify',
            'verify.post' => 'mail2fa.verify.post',
            'resend' => 'mail2fa.resend',
        ],
    ],

    // Inertia component path
    'inertia' => [
        'verify_component' => 'Mail2FA/Verify',
    ],
];
```

User Model Setup
----------------

[](#user-model-setup)

Make sure your User model has the `mfa_code` and `mfa_expires_at` fields in the `$fillable` array:

```
// app/Models/User.php

protected $fillable = [
    'name',
    'email',
    'password',
    'mfa_code',      // Add this
    'mfa_expires_at', // Add this
];

protected $casts = [
    // ... other casts
    'mfa_expires_at' => 'datetime',
];
```

Usage
-----

[](#usage)

### Protecting Routes

[](#protecting-routes)

Add the `mail2fa` middleware to any routes you want to protect:

```
// Single route
Route::get('/dashboard', DashboardController::class)
    ->middleware(['auth', 'mail2fa']);

// Route group
Route::middleware(['auth', 'mail2fa'])->group(function () {
    Route::get('/dashboard', DashboardController::class);
    Route::get('/settings', SettingsController::class);
});
```

### How It Works

[](#how-it-works)

1. User attempts to access a protected route
2. Middleware checks if user has verified 2FA in current session
3. If not verified, user is redirected to `/2fa/verify`
4. A 6-digit code is sent to the user's email
5. User enters the code
6. If correct, user is redirected to their intended destination
7. Session is marked as verified for the configured lifetime

### Environment Variables

[](#environment-variables)

```
MAIL2FA_ENABLED=true
MAIL2FA_CODE_LENGTH=6
MAIL2FA_CODE_EXPIRATION=10
MAIL2FA_RESEND_COOLDOWN=60
MAIL2FA_VERIFICATION_LIFETIME=
```

Customization
-------------

[](#customization)

### Custom Email Template

[](#custom-email-template)

After publishing views, edit `resources/views/vendor/mail2fa/emails/verification-code.blade.php`.

### Custom Inertia Components

[](#custom-inertia-components)

After publishing Inertia components, edit the Vue files in `resources/js/Pages/Mail2FA/`:

- `Verify.vue` - Main verification page

### Custom Inertia Component Path

[](#custom-inertia-component-path)

If you want to use different component paths:

```
// config/mail2fa.php
'inertia' => [
    'verify_component' => 'Auth/TwoFactorVerify',
],
```

API
---

[](#api)

### Routes

[](#routes)

MethodURINameDescriptionGET/2fa/verifymail2fa.verifyShow verification formPOST/2fa/verifymail2fa.verify.postSubmit verification codePOST/2fa/resendmail2fa.resendResend verification code### Clear Verification

[](#clear-verification)

To programmatically clear a user's verification status (e.g., on logout):

```
use AdesinFr\Mail2FA\Traits\Mail2FATrait;

class AuthController
{
    use Mail2FATrait;

    public function logout(Request $request)
    {
        $this->clearVerification($request);
        // ... rest of logout logic
    }
}
```

Testing
-------

[](#testing)

Run tests with Pest:

```
composer test
```

Or run Pest directly:

```
./vendor/bin/pest
```

Security Considerations
-----------------------

[](#security-considerations)

- Codes are stored hashed (bcrypt) in the database
- Configurable code expiration
- Rate limiting on code resend via cooldown
- Codes are cleared after successful verification
- Session-based verification status

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance77

Regular maintenance activity

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

126d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f7caa80ffede6a2b3888071d496741ce6a215a6cefe798465e7ba7e7ad1841c3?d=identicon)[Adesin-fr](/maintainers/Adesin-fr)

---

Top Contributors

[![LemarinelNet](https://avatars.githubusercontent.com/u/10656218?v=4)](https://github.com/LemarinelNet "LemarinelNet (2 commits)")

---

Tags

laravelotpsecurityemail2faTwo Factor Authenticationinertia

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/adesin-fr-laravel-mail-2fa/health.svg)

```
[![Health](https://phpackages.com/badges/adesin-fr-laravel-mail-2fa/health.svg)](https://phpackages.com/packages/adesin-fr-laravel-mail-2fa)
```

###  Alternatives

[tzsk/otp

A secure, database-free One-Time Password (OTP) generator and verifier for PHP and Laravel.

241641.4k1](/packages/tzsk-otp)[s-ichikawa/laravel-sendgrid-driver

This library adds a 'sendgrid' mail driver to Laravel.

4139.3M1](/packages/s-ichikawa-laravel-sendgrid-driver)[laravel-notification-channels/discord

Laravel notification driver for Discord.

2371.3M11](/packages/laravel-notification-channels-discord)[erag/laravel-disposable-email

A Laravel package to detect and block disposable email addresses.

226102.4k](/packages/erag-laravel-disposable-email)[meness/verifi

A Laravel package to handle email verification.

5516.9k](/packages/meness-verifi)[martian/spammailchecker

A laravel package that protect users from entering non-existing/spam email addresses.

422.0k](/packages/martian-spammailchecker)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
