0

When the user registers, an email will be sent to confirmation

But how do I send a notification when a user updates their email?

Like when he registers

Use the link below to use Laravel's own verification system

ANSWER 2024/4/8

important: This method does not use MustVerifyEmail In the future, I will write the method of using MustVerifyEmail as an update here

Use the link below to use Laravel's own verification system https://laravel.com/docs/11.x/verification

SUMMARY SAMPLE:

This link explains about it https://laravel.com/docs/11.x/mail

For testing, you can set the value of MAIL_MAILER to log in .env to see when the email is sent in /storage/log/laravel.log.

A simple example, without the need for a package, for the user to receive a link for confirmation after changing the email, we can proceed like this:

In routes/web.php

<?php

use App\Mail\EmailConfirmation;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Route;

Route::middleware('auth')->group(function(){
    Route::get('change-email', function(){
        $email = Auth::user()->email;
        return view('change-email', compact('email'));
    })->name('change-email');
    
    Route::post('change-email-post', function(Request $request)
    {
        $validatedData = $request->validate([
            'email' => 'required|email',
        ]);
    
        $updated = User::where(['id' => Auth::id()])->update($validatedData);
    
        if($updated) {
            $key = setVerifyToken($validatedData['email']);
            $link = route('verify', ['key' => $key]);
            Mail::to(Auth::user())->send(new EmailConfirmation(Auth::user(), $link));
            session()->flash('message', 'Your email is update, please check your inbox to confirm the new email');
        } else {
            session()->flash('message', 'Cannot update your email, try again after 60 seconds');
        }
    
        return redirect()->route('change-email', ['email' => $validatedData['email']]);
    })->name('change-email-post');
});

Route::get('verify/{key}', function($key){
    $email = getVerifyValue($key, $state);

    if(! $state) {
        $message = $email;
    } else {
        $user = User::where(['email' => $email, 'email_verified_at' => null])->update([
            'email_verified_at' => Carbon::now(),
        ]);

        if($user) {
            $message = "Email is verified";
        } else {
            $message = "Unverified user not found";
        }
    }

    return view('verify', compact('message'));
})->name('verify');

The change-email path is used to display the form

The change-email-post route is used to send confirmation emails and email updates

The verify path is used to verify the email.

Then it is better to create a helper for ease of work Of course, you can define functions wherever you want.هد In composer.json

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        },
        "files": [
            "app\\helpers.php"
        ]
    },

Then create the ‍app/helpers.php file

Then type the following command: composer dump-autoload Then create the app/helpers.php file

In app/helpers.php

<?php

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

if(! function_exists('setVerifyToken')) {
    function setVerifyToken($account){
        // '<str>' skeleton key
        // '<email>:<expire link>'
        $key = base64_encode(Hash::make(Str::random(30).$account));
        $expire = time() + 600; // 10 minute
        Cache::put($key, $account.':'.$expire);

        return $key;
    }
}

if(! function_exists('getVerifyValue')) {
    function getVerifyValue(string $key, &$state) {
        if(! Cache::has($key)) {
            $state = false;
            return "key not found";
        }

        [$email, $expire] = explode(':', Cache::get($key));

        if($expire < time()) {
            $state = false;
            return "key is expired"; //expired
        }

        $state = true;
        return $email;
    }
}

The setVerifyToken() function creates a hash for us using Hash::make and creates a string, the first part of which is 30 random characters and the second part of the requested account string, so that the probability of two similar links for two different emails interfering is close to zero. reach it

After caching it, it returns the value of $key, which can be used to reset and confirm the correctness of $key using the getVerifyValue() function.

We can use mail to send email php artisan make:mail EmailConfirmation

In app/Mail/EmailConfirmation.php

<?php

namespace App\Mail;

use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class EmailConfirmation extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     */
    public function __construct(public User $user, public $link)
    {
        //
    }

    /**
     * Get the message envelope.
     */
    public function envelope(): Envelope
    {
        return new Envelope(
            from: config('mail.from.address'),
            subject: 'Email Confirmation',
        );
    }

    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        return new Content(
            view: 'email-confirmation',
        );
    }

    /**
     * Get the attachments for the message.
     *
     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
     */
    public function attachments(): array
    {
        return [];
    }
}

And then making blade templates;

In resources/views/change-email.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form method="POST" action="{{ route('change-email-post') }}">
        @csrf
        <input name="email" value="{{ $email }}" type="email">
        <button type="submit">update</button>
        @if(session()->has('message'))
            <li>{{session()->get('message')}}</li>
        @endif
        @if ($errors->any())
            <div class="alert alert-danger">
                <ul>
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif
    </form>
</body>
</html>

In resources/views/email-confirmation.blade.php

Hello {{ $user->name }}
Your {{ $user->email }} email needs confirmation
Please confirm your link by clicking on the link below
{{ $link }}

In resources/views/verify.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    {{ $message }};
</body>
</html>

Now we run the php artisan optimize:clear and php artisan optimize commands

2
  • where do you want to notif the user, to the old email or new email? Commented Feb 11, 2022 at 16:31
  • Here are lots of ways to do it, please google it you will find out, you can set observer or you can send it on the update time. Commented Feb 11, 2022 at 16:31

1 Answer 1

0

if you want to reverify your user's email , you should set his email_verified_at to null then call sendEmailVerificationNotification method .

in your user model (located in app\user) add this method :

 public function sendNewVerification() {
    $this->email_verified_at =null; 
   $this->sendEmailVerificationNotification();
 }

and call it in your controller .

hope that would work.

2
  • Thanks for the reply ... but how do I call it in my controller? Commented Feb 12, 2022 at 9:35
  • it depends on where you put this action . for example if your controller's method it's called update use this there . also i can help you more if you attach a screen shot of your controller and method that you are working on .
    – saeed mzr
    Commented Feb 12, 2022 at 11:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.