Search code examples
laravellaravel-5laravel-5.3laravel-mail

Customise Reset Password Email and pass User Data in Laravel 5.3


I am using Laravel 5.3 and customizing the Password Reset Email Template. I have done the following changes to create my own html email for the notification using a custom Mailable class. This is my progress so far:

ForgotPasswordController:

public function postEmail(Request $request)
    {
        $this->validate($request, ['email' => 'required|email']);

        $response = Password::sendResetLink($request->only('email'), function (Message $message) {
            $message->subject($this->getEmailSubject());
        });

        switch ($response) {
            case Password::RESET_LINK_SENT:
                return Response::json(['status' => trans($response)], 200);

            case Password::INVALID_USER:
                return Response::json(['email' => trans($response)], 400);
        }
    }

User Model:

public function sendPasswordResetNotification($token)
{
    Mail::queue(new ResetPassword($token));
}

ResetPassword Mailable Class:

protected $token;

public function __construct($token)
{
    $this->token = $token;
}

public function build()
{
    $userEmail = 'something'; // How to add User Email??
    $userName = 'Donald Trump'; // How to find out User's Name??
    $subject = 'Password Reset';

    return $this->view('emails.password')
                ->to($userEmail)
                ->subject($subject)
                ->with([
                        'token'   => $this->token
                        'userEmail' => $userEmail,
                        'userName'  => $userName
                      ]);
    }   

If you noticed above, I am not sure how do I pass the user's name and find out the user's email address. Do I need to send this data from the User Model or do I query it from the Mailable class? Can someone show me how I can do that please?


Solution

  • Usually you ask for the user email in order to send a reset password email, that email should come as a request parameter to your route controller.

    By default, L5.3 uses post('password/email) route to handle a reset password request. This route execute sendResetLinkEmail method which is defined in the 'SendsPasswordResetEmails' trait used by the App\Http\Controllers\Auth\ForgotPasswordController.

    From here you can take one of 2 options:

    1st: You could overwrite the route to call another function in the same controller (or any other controller, in this case could be your postEmail function) which search for the user model by the email you received, then you can pass the user model as function parameter to the method which execute the queue mail action (this may or may not require to overwrite the SendsPasswordResetEmails, depends on how you handle your reset password method).

    This solution would looks something like this:

    In routes/web.php

    post('password/email', 'Auth\ForgotPasswordController@postEmail')
    

    in app/Mail/passwordNotification.php (for instance)

    protected $token;
    protected $userModel;
    
    public function __construct($token, User $userModel)
    {
        $this->token = $token;
        $this->userModel = $userModel;
    }
    
    public function build()
    {
        $userEmail = $this->userModel->email;
        $userName = $this->userModel->email
        $subject = 'Password Reset';
    
        return $this->view('emails.password')
                    ->to($userEmail)
                    ->subject($subject)
                    ->with([
                            'token'   => $this->token
                            'userEmail' => $userEmail,
                            'userName'  => $userName
                          ]);
        }  
    

    in app/Http/Controllers/Auth/ForgotPasswordController

    public function postEmail(Request $request)
        {
            $this->validate($request, ['email' => 'required|email']);
            $userModel = User::where('email', $request->only('email'))->first();
            Mail::queue(new ResetPassword($token));
            //Manage here your response
        }
    

    2nd: You could just overwirte the trait SendsPasswordResetEmails to search for the user model by the email and use your customized function in sendResetLinkEmail function. There you could use your function but notice that you still have to handle somehow an status to create a response as you already have it on ForgotPasswordController.

    I hope it helps!