読者です 読者をやめる 読者になる 読者になる

とっしぃのTech Memo

PHPとかサーバとか他色々言語のメモ的な。あとはたまにガジェットとか。

Laravel5.2でパスワードリセットのメールをテキストで送りたい

なんでデフォルトがHTMLなんや。

でもテキストで送れないとなるとトークン自分で作ったりその認証したりめんどいので なんとかソースコード追って設定(+override)でどうにかしたい。

まずはRouting

Laravelは5.2からartisanコマンドにmake:authが出来て、ルーティングやらなんやらを一気にやってくれるようになったみたいですね。 5.1以前をやったことないので前は知らないけど(´・ω・`)

とりあえずphp artisan make:authを打ってみて、ルーティングを見てみる。

Route::post('password/email', 'Auth\PasswordController@sendResetLinkEmail');

PasswordControllerのsendResetLinkEmailメソッドでメールを発行しているらしい。

じゃあそのメソッド見れば解決やん。

・・・

ない(´・ω・`)

そんなメソッド書いてない(´・ω・`)

ということでPasswordControllerの上の方を見てみると

    use ResetsPasswords;

という記述が。

Laravelはこういったtrait機能をふんだんに使った書き方がされているみたい。

んでそのtraitは

use Illuminate\Foundation\Auth\ResetsPasswords;

とのことなのでそちらを見てみるとありましたねsendResetLinkEmail

    /**
     * Send a reset link to the given user.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function sendResetLinkEmail(Request $request)
    {
        $this->validate($request, ['email' => 'required|email']);

        $broker = $this->getBroker();

        $response = Password::broker($broker)->sendResetLink(
            $request->only('email'), $this->resetEmailBuilder()
        );

        switch ($response) {
            case Password::RESET_LINK_SENT:
                return $this->getSendResetLinkEmailSuccessResponse($response);

            case Password::INVALID_USER:
            default:
                return $this->getSendResetLinkEmailFailureResponse($response);
        }
    }

この中でメールを送っているらしき部分は

        $response = Password::broker($broker)->sendResetLink(
            $request->only('email'), $this->resetEmailBuilder()
        );

なので、今度はそこをvendor/laravelの中で探すと vendor/laravel/framework/src/Illuminate/Auth/Passwords/PasswordBroker.php にそれっぽいのを発見。

    /**
     * Send the password reset link via e-mail.
     *
     * @param  \Illuminate\Contracts\Auth\CanResetPassword  $user
     * @param  string  $token
     * @param  \Closure|null  $callback
     * @return int
     */
    public function emailResetLink(CanResetPasswordContract $user, $token, Closure $callback = null)
    {
        // We will use the reminder view that was given to the broker to display the
        // password reminder e-mail. We'll pass a "token" variable into the views
        // so that it may be displayed for an user to click for password reset.
        $view = $this->emailView;

        return $this->mailer->send($view, compact('token', 'user'), function ($m) use ($user, $token, $callback) {
            $m->to($user->getEmailForPasswordReset());

            if (! is_null($callback)) {
                call_user_func($callback, $m, $user, $token);
            }
        });
    }

見事にsendしてる。

んでここの$view、その前を見ると$this->emailViewを、テキストメールの送り方である['text' => 'view_name']にできればおっけー。

その$this->emailViewはどうやらコンストラクタで設定されているようなので、PasswordBrokerをnewしてるところを探せばいけるんじゃないかね。

するとnewしてるのはvendor/laravel/framework/src/Illuminate/Auth/Passwords/PasswordBrokerManager.phpと判明。

その中のresolveメソッドでnewしてた。

    /**
     * Resolve the given broker.
     *
     * @param  string  $name
     * @return \Illuminate\Contracts\Auth\PasswordBroker
     *
     * @throws \InvalidArgumentException
     */
    protected function resolve($name)
    {
        $config = $this->getConfig($name);

        if (is_null($config)) {
            throw new InvalidArgumentException("Password resetter [{$name}] is not defined.");
        }

        // The password broker uses a token repository to validate tokens and send user
        // password e-mails, as well as validating that password reset process as an
        // aggregate service of sorts providing a convenient interface for resets.
        return new PasswordBroker(
            $this->createTokenRepository($config),
            $this->app['auth']->createUserProvider($config['provider']),
            $this->app['mailer'],
            $config['email']
        );
    }

どうやら$config['email']がそれっぽい。

んで$this->getConfig($name);はというと

    /**
     * Get the password broker configuration.
     *
     * @param  string  $name
     * @return array
     */
    protected function getConfig($name)
    {
        return $this->app['config']["auth.passwords.{$name}"];
    }

これっすねー。

Laravelのconfigファイルは、configディレクトリ以下にファイルを置くだけで使えるので、 この記述からはconfig/auth.phpファイルのpasswords['email']を見ている、と。

ということで、上記を['text' => 'auth.emails.password']に変えてみたら見事にテキストメールで送られました。

ふぅ(´・ω・`)