Send email after login with one-time-login plugin

Hello everyone, I tried to reply in my original post, but I cant.
I try to implement a way to send a email after somebody use the one time login plugin, I modified the plugin to keep the token, so I can use more than 1 time, and also remove the option to remove it after 15 minutes, and works fine, but now I try to use the email plugin to send a email when its used, Same like my previous topic I using the email plugin and in login plugin is working fine, its was a grammatical mistake, but now when I try to use in the same way in the one time login plugin, Send me this error:

This is the code I used in the one-time-login.php:

private function authenticateOtl()
$username = $this->grav['uri']->param('user');
$firstName = $this->grav['uri']->param('firstname');
$lastName = $this->grav['uri']->param('lastname');
$otl_nonce = $this->grav['uri']->param('otl_nonce');
$rolUsername = $this->grav['uri']->param('username');
$sitename = $this->grav['uri']->param('sitename');

$this->redirect = "/";

// Load user object.
$user = !empty($username) ? User::load($username) : null;
if (empty($user) || !$user->otl_nonce) {
    $this->grav['log']->info("Invalid OTL URL.");
    $this->grav['messages']->add('Invalid OTL URL.', 'error');
if ($user) {
    $otl_nonce_expire = $user->otl_nonce_expire;

    if (($user->otl_nonce == $otl_nonce) /* && (time() < $otl_nonce_expire) */) {
        // Remove OTL user entries.
        /* unset($user->otl_nonce);
        unset($user->otl_admin_logon); */
        $user->authenticated = true;
        $user->authorized = $user->authorize('admin.login');
        // Authenticate user to website.
        $this->grav['session']->user = $user;
        $this->grav['user'] = $user; 
        $time = date("l / d-m-Y(H:i:s)");
                $to = '';
                $from = '';
                $subject = $time . " | Inicio de sesión";
                $content = '
                table {
                table, th, td {
                border: 1px solid black;
                border-collapse: collapse;
                th, td {
                padding: 15px;
                text-align: left;
                table#t01 tr:nth-child(even) {
                background-color: #eee;
                table#t01 tr:nth-child(odd) {
                background-color: #fff;
                table#t01 th {
                background-color: black;
                color: white;
                <title>Inicio de sesión </title>
                <h1> Inicio de sesión  </h1>
                <th> Fecha de inicio de sesión </th>
                <th> Correo o nombre de usuario </th>

/*                         $message = $this->grav['Email']->message($subject, $content, 'text/html')

                    $sent = $this->grav['Email']->send($message);  */

        $this->redirect = "/10/=".$firstName ."&lastname=". $lastName;
    } else {
        $this->grav['messages']->add('Invalid OTL URL.', 'error');
        $this->grav['log']->info("Invalid OTL URL.");
// Redirect.

Also say that in my code I receive more parameters than just the username and the token, everything else is working, is just the part with the comments where send email.

Did you check the /logs folder as error suggests? What’s the exact error?

Its a really long one. But is actually the same as the picture.
[2021-03-05 15:41:12] grav.CRITICAL: Identifier "Email" is not defined. - Trace: #0 /var/www/vhosts/ Pimple\Container->offsetGet('Email') #1 /var/www/vhosts/ Grav\Plugin\LoginPlugin->userLoginAuthenticate(Object(Grav\Plugin\Login\Events\UserLoginEvent), 'onUserLoginAuth...', Object(Symfony\Component\EventDispatcher\EventDispatcher)) #2 /var/www/vhosts/ Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(Array, 'onUserLoginAuth...', Object(Grav\Plugin\Login\Events\UserLoginEvent)) #3 /var/www/vhosts/ Symfony\Component\EventDispatcher\EventDispatcher->callListeners(Array, 'onUserLoginAuth...', Object(Grav\Plugin\Login\Events\UserLoginEvent)) #4 /var/www/vhosts/ Symfony\Component\EventDispatcher\EventDispatcher->dispatch(Object(Grav\Plugin\Login\Events\UserLoginEvent), 'onUserLoginAuth...') #5 /var/www/vhosts/ Grav\Common\Grav->fireEvent('onUserLoginAuth...', Object(Grav\Plugin\Login\Events\UserLoginEvent)) #6 /var/www/vhosts/ Grav\Plugin\Login\Login->login(Array, Array) #7 /var/www/vhosts/ Grav\Plugin\LoginPlugin->Grav\Plugin\{closure}(Object(Grav\Common\Grav)) #8 /var/www/vhosts/ Pimple\Container->offsetGet('user') #9 /var/www/vhosts/ Grav\Plugin\Admin\Admin->__construct(Object(Grav\Common\Grav), '/admin', 'dashboard', NULL) #10 /var/www/vhosts/ Grav\Plugin\AdminPlugin->initializeAdmin() #11 /var/www/vhosts/ Grav\Plugin\AdminPlugin->onPluginsInitialized(Object(RocketTheme\Toolbox\Event\Event), 'onPluginsInitia...', Object(Symfony\Component\EventDispatcher\EventDispatcher)) #12 /var/www/vhosts/ Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(Array, 'onPluginsInitia...', Object(RocketTheme\Toolbox\Event\Event)) #13 /var/www/vhosts/ Symfony\Component\EventDispatcher\EventDispatcher->callListeners(Array, 'onPluginsInitia...', Object(RocketTheme\Toolbox\Event\Event)) #14 /var/www/vhosts/ Symfony\Component\EventDispatcher\EventDispatcher->dispatch(Object(RocketTheme\Toolbox\Event\Event), 'onPluginsInitia...') #15 /var/www/vhosts/ Grav\Common\Grav->fireEvent('onPluginsInitia...') #16 /var/www/vhosts/ Grav\Common\Processors\PluginsProcessor->process(Object(Nyholm\Psr7\ServerRequest), Object(Grav\Framework\RequestHandler\RequestHandler)) #17 /var/www/vhosts/ Grav\Framework\RequestHandler\RequestHandler->handle(Object(Nyholm\Psr7\ServerRequest)) #18 /var/www/vhosts/ Grav\Framework\RequestHandler\RequestHandler->handle(Object(Nyholm\Psr7\ServerRequest)) #19 /var/www/vhosts/ Grav\Common\Processors\InitializeProcessor::Grav\Common\Processors\{closure}() #20 /var/www/vhosts/ Grav\Common\Debugger->profile(Object(Closure)) #21 /var/www/vhosts/ Grav\Common\Processors\InitializeProcessor->process(Object(Nyholm\Psr7\ServerRequest), Object(Grav\Framework\RequestHandler\RequestHandler)) #22 /var/www/vhosts/ Grav\Framework\RequestHandler\RequestHandler->handle(Object(Nyholm\Psr7\ServerRequest)) #23 /var/www/vhosts/ Grav\Framework\RequestHandler\RequestHandler->handle(Object(Nyholm\Psr7\ServerRequest)) #24 /var/www/vhosts/ Grav\Common\Grav->process() #25 {main} [] []

Not familiar with OTL and plugin, but it seems like plugin is providing wrong data to onUserLoginAuth event, which actually again might be some misconfiguration :thinking: Sorry I can’t help you much further

1 Like

@mcambronero, When plugin ‘email’ is not installed, command $this->grav['Email'] will throw the following error:

[2021-03-11 19:09:44] grav.CRITICAL: Identifier "Email" is not defined. -
#0 path/to/method-call: Pimple\Container->offsetGet()

Which matches your error. Are you sure that plugin ‘email’ is installed (correctly)?

You might want to check out the One Time Login Mailer Plugin. It works with an unmodified One Time Login Plugin and of course requires a properly configured Email Plugin plus working mail server.

Yes I am sure its works when I use in console and also in login plugin

I will Check, thanks!

@mcambronero, The same error happens when the initialization of the email plugin happens later then when the one-time-login plugin calls $this->grav['Email'].

Looking at the code of one-time-login plugin, that seems indeed to be what’s happening here: Priority of one-time-login is higher then the priority of email plugin.

// email plugin

'onPluginsInitialized'      => ['onPluginsInitialized', 0],
// one-time-login

'onPluginsInitialized' => ['onPluginsInitialized', 1],

Plugin Email initializes $this->grav['Email'] during onPluginsInitialized while plugin one-time-login calls $this->grav['Email'] during onPluginsInitialized.


  1. Increase priority of email plugin.
    Not my first choice.
  2. Or lower priority of one-time-login plugin.
    Don’t know the side effect(s) of other plugins running while not yet logged in.
  3. Or instantiate the Email class manually.
use Grav\Plugin\Email\Email;
$email = new Email();
$isSent = $email->send($message);

Thanks you so much for all your help, this is the solution.

In my case I use the second solution and works, but I also found this article and I think is a better way to do it:
Plugin Prioritization | Grav Documentation (

1 Like

@mcambronero, Thanks! I Wasn’t aware of the ability to alter an event’s priority with a config setting without touching the plugin’s code.

What keeps you from using option 3?

1 Like