Email confirmation on FOSUserBundle Profile Edit Email confirmation on FOSUserBundle Profile Edit symfony symfony

Email confirmation on FOSUserBundle Profile Edit


Using new FOSUserBundle's events (FOS 2.0 feature), you can create a ChangeProfileListener that handle email changes.

The idea : use the same logic as a registration process : disable our user, send him a token (and logging-him out for our case).

There is two things to do :

  • create an event suscriber
  • overwrite the mail.txt.twig to replace the "registration" message by a neutral "email confirmation" message.

Here is my listener, don't forget to replace namespace.

EventListener/ChangeProfileListener.php:

<?php// src/Fuz/HomeBundle/EventListener/ChangeProfileListener.phpnamespace Fuz\HomeBundle\EventListener;use FOS\UserBundle\FOSUserEvents;use FOS\UserBundle\Event\GetResponseUserEvent;use FOS\UserBundle\Event\FormEvent;use FOS\UserBundle\Mailer\MailerInterface;use FOS\UserBundle\Util\TokenGeneratorInterface;use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpFoundation\Session\SessionInterface;use Symfony\Component\Routing\Generator\UrlGeneratorInterface;class ChangeProfileListener implements EventSubscriberInterface{    private $mailer;    private $tokenGenerator;    private $router;    private $session;    private $tokenStorage;    public function __construct(MailerInterface $mailer, TokenGeneratorInterface $tokenGenerator,       UrlGeneratorInterface $router, SessionInterface $session, TokenStorageInterface $tokenStorage)    {        $this->mailer = $mailer;        $this->tokenGenerator = $tokenGenerator;        $this->router = $router;        $this->session = $session;        $this->tokenStorage = $tokenStorage;    }    public static function getSubscribedEvents()    {        return array(                FOSUserEvents::PROFILE_EDIT_INITIALIZE => 'onProfileEditInitialize',                FOSUserEvents::PROFILE_EDIT_SUCCESS => 'onProfileEditSuccess',        );    }    public function onProfileEditInitialize(GetResponseUserEvent $event)    {        // required, because when Success's event is called, session already contains new email        $this->email = $event->getUser()->getEmail();    }    public function onProfileEditSuccess(FormEvent $event)    {        $user = $event->getForm()->getData();        if ($user->getEmail() !== $this->email)        {            // disable user            $user->setEnabled(false);            // send confirmation token to new email            $user->setConfirmationToken($this->tokenGenerator->generateToken());            $this->mailer->sendConfirmationEmailMessage($user);            // force user to log-out            $this->tokenStorage->setToken();            // redirect user to check email page            $this->session->set('fos_user_send_confirmation_email/email', $user->getEmail());            $url = $this->router->generate('fos_user_registration_check_email');            $event->setResponse(new RedirectResponse($url));        }    }}

services.yml :

parameters:    fuz_home.email_change.listener.class: Fuz\HomeBundle\EventListener\ChangeProfileListenerservices:      fuz_home.email_change.listener:          class: %fuz_home.email_change.listener.class%          arguments: ['@fos_user.mailer', '@fos_user.util.token_generator', '@router', '@session', '@security.token_storage']          tags:            - { name: kernel.event_subscriber }

About overwritting email template, that's just creating app/Resources/FOSUserBundle/views/Registration/email.txt.twig and put, for example :

{% block subject %}Email Confirmation{% endblock %}{% block body_text %}Welcome to example.com, {{ user.username }}!                                                To confirm your email, please follow this link:                                                                    {{ confirmationUrl }}You will be able to log-in using the username or email you given:                                        Username : {{ user.username }}                                                                                                         Email    : {{ user.email }}                                                                                                 If you received this e-mail in error just ignore this message. No further actions are required from you.                                                                       *****                                                                                                            See you soon!{% endblock %}


The functionality to send a confirmation email only exists in

RegistrationFormHandler->onSucces

where that configuration variable is passed and checked. Similar functionality doesn't exist in the profile/edit:

ProfileFormHandler->onSuccess.

You would therefore need to override the FOS ProfileFormHandler and add this functionality yourself. This is covered in the FOSUserBundle documentation: Overriding Forms.