Skip to main content

Cakephp 3x- Add Email verification on registration



How to add email verification on registration Cakephp 3.x


In this tutorial we will add email verification on user register so whenever a new user registered in our site then he will receive an email with confirmation link and after confirmation link click , his account will activate. this tutorial is also for that users that want to learn how to setup email configration in cakephp 3.x. for basic knowledge you can check this post

Send mail using mail class in cakephp 3

SO FOLLOW THESE SIMPLE STEPS TO VERIFY USER EMAIL ON REGISTRATION

First we need to add one table with three columns id email and status . you can run below query to create a table
CREATE TABLE `cake`.`users` ( `id` INT NOT NULL AUTO_INCREMENT , `email` VARCHAR(50) NOT NULL , `otp` VARCHAR(50) NOT NULL , `status` INT NOT NULL DEFAULT '0' , PRIMARY KEY (`id`)) ENGINE = InnoDB;


Your database table should look like


In this tutorial we will use gmail for smtp so first we need to configure EmailTransport for gmail. so open rootDirectory/config/app and search for EmailTransport then add new settings like below we add gmail.

  'EmailTransport' => [
        'default' => [
            'className' => 'Mail',
            // The following keys are used in SMTP transports
            'host' => 'localhost',
            'port' => 25,
            'timeout' => 30,
            'username' => 'user',
            'password' => 'secret',
            'client' => null,
            'tls' => null,
            'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
        ],
        'gmail'=> [
          'host' => 'ssl://smtp.gmail.com',
          'port' => 465,
          'username' => 'yourEmail@gmail.com',
          'password' => 'YOURPASSWORD',
          'className' => 'Smtp',
          'log' => true,
          'context' => [
            'ssl' => [
                'verify_peer' => false,
                'verify_peer_name' => false,
                'allow_self_signed' => true
            ]
          ]
        ],
    ],



Now we setup gmail for send email and its also working for localhost

You can send email with cakephp simply by using this code in your controller

Note:- make sure use Cake\Mailer\Email; class loaded in your controller
$email = new Email('default');
$email->from(['me@example.com' => 'My Site'])
    ->to('you@example.com')
    ->subject('About')
    ->send('My message');

the above example is for send email with cakephp 3.x But for this tutorial we will
create a component for email

Create a file MainComponent.ctp in ProjectRootDirectory/src/Controller/Component and paste this code

<?php
namespace App\Controller\Component;

use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use Cake\Mailer\Email;
use Cake\Core\Configure;
use Cake\Routing\Router;

/**
 * Main component
 */
class MainComponent extends Component
{
  /**
     * Default configuration.
     *
     * @var array
     */
    protected $_defaultConfig = [];

    /*
    * Email Configuration
    * @params : array $config [Cake Email Params]
    *        - $config[to]   - Email of receiver
    *        - $config[from] - Email of sender
    *        - $cofig[message] - Message of email
    *          - $config[subject] - subject of email
    * @return : boolean
    */

     public function sendEmail($config= array()){ //pr($config); exit;
      $defaults = array_merge(array('sendAs'=>'html','transport'=>'gmail','from'=>'test'),$config);
      try{
        $Email = new Email();
        $Email->from(Configure::read('Site.email_from'))
            ->template('themetemplate', 'themelayout')
            ->to($defaults['to'])
            ->subject($defaults['subject'])
            ->emailFormat($defaults['sendAs'])
            ->transport($defaults['transport'])
            ->viewVars(['title' => $config['title'],'content'=>$config['body']]);
         if(isset($defaults['fileurl']) && isset($defaults['filename'])){
            $Email->attachments([
                  $defaults['filename'] => [
                 'file' => $defaults['fileurl']
                ]
              ]);
          }
      
        if(!$Email->send())
        return false;
      
      
      } catch (\Exception $e) { 
        return false;
        //$this->Flash->error($e->getMessage());
      }
      return true;
    }

}


Explaination -
->template => using for set html tempalte for email
->to       => pass to user email
->emailFormat => type of email like text or html
->transport  => set transport for email , we already added gmail for transport in app.php so we passing gmail in transport


Now we will create layout and template for email that we mentioned in our mail configuration

Create Layout src/Template/Layout/Email/html/themelayout.ctp and paste this code
<?php
/**
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://cakephp.org CakePHP(tm) Project
 * @since         0.10.0
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
    <title><?= $this->fetch('title') ?></title>
</head>
<body>
    <?= $this->fetch('content') ?>
</body>
</html>




Create template src/Template/Email/html/themetemplate.ctp and paste this code
  <table>
  <tbody style="background-color:#F5F5F5;">
   <tr>
  <td colspan="2" valign="top" style="padding-top:35px;color:rgb(79,129,189);font-size:23px;text-align:center">
  <?= $title ?>
  </td>
  </tr>
   <tr>
    <td colspan="2" style="padding:40px 25px 40px; color:#666;font-size:14px;line-height:22px;font-family:Verdana,sans;margin-top:0;margin-bottom:20px;font-weight:normal">
      <?= $content ?> 
      </td>
   </tr>
   </tbody>
   </table>

Here we passing $title and $content, that values we already send from our email configuration

Now everything setup for email


Now we need to create a src/Template/register.ctp  you can bake tempalte using cake bake template users or if want to do manually then follow below steps

Now create a form in this file or Paste this code into your register.ctp
<div class="row">
 <div class="col-sm-12">
 <?= $this->Form->create($user);?>
  <div class="form-group ">
        <?= $this->Form->input('email',['class'=>'form-control','required'=>'required','type'=>'email']);?>
      </div>
  <div class="row">
    <div class="col-sm-12">
      <?= $this->Form->button('Login',['class'=>'btn btn-primary','type'=>'submit']); ?>
    </div>
  </div>
    <?= $this->Form->end() ?>    

 </div>
</div>




Now we will create a src/Controller/UserController.php  and to use our email component we need to call component in our controller. you can call it in AppController so you can use from any controller for example we using in our controller .Here we call it in initialize function of controller by

Call Custom Component in cakephp.


   public function initialize() {
     parent::initialize();

     $this->loadComponent('Main');      
    }



 you can bake controller using cake bake all users or if want to do manually then follow below steps

Now Paste this code into your usersController.php
<?php
namespace App\Controller;

use App\Controller\AppController;
use Cake\Core\Configure;
use Cake\Network\Exception\NotFoundException;
use Cake\View\Exception\MissingTemplateException;
use Cake\Error\Debugger;
use Cake\Event\Event;
use Cake\Routing\Router;
/**
 * Users Controller
 *
 * @
 perty \App\Model\Table\UsersTable $Users
 */
class UsersController extends AppController
{
   /**
     * Register method
     *
     * @return \Cake\Network\Response|null
   * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
     */

   public function initialize() {
     parent::initialize(); 
     $this->loadComponent('Main');      
    }

  public function register(){
    $user = $this->Users->newEntity();
    try {
      if($this->request->is('post')) {
        $uniquecode = substr(md5(microtime()),0,10); //generate random string
        $randomKey = substr(md5(microtime()),0,10);
            $this->request->data['otp'] = $uniquecode;
            $getUserEmail = $this->Request->data['email'];
            
            $user = $this->Users->patchEntity($user,$this->request->data);
            if($this->Users->save($user)){
              $bodyEmail = "You have successfully registered.";
              $bodyEmail .= "To active account please click on below link";
              $aLink = Router::url(array("controller"=>"users","action"=>"activate", $uniquecode, $randomKey),true);
              $bodyEmail .= '<p><br><br><a style="width:50%;color:#fff;text-decoration:none;background:#333;display:block;padding:10px;text-align:center;-webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px;margin:10px auto " href="'.$aLink.'"> Please verify your email address </a></p>';
               if($this->Main->sendEmail(['to'=>$getUserEmail,'subject'=>'Registration Complete','title'=>'Registration Complete','body'=>$bodyEmail)){
                  $this->Flash->success(__('Your account has been registered. please check your email address to activate your account'));
              return $this->redirect(['action' => 'register']);
                }else{
                  $this->Flash->error(__('Registration not completed. Please try again.'));
                  return $this->redirect(['action' => 'index']);
                }             
            }else{
              $this->Flash->error(__('Unable to register your account.'));
            }
       }
    }catch (\Exception $e) {
       $this->Flash->error($e->getMessage());
       return $this->redirect(['action' => 'register']);
    }
    $this->set('user',$user);
    $this->set('page_title',__('Registeration'));
  }

    /**
     * Activate method
     *
     * @return \Cake\Network\Response|null
   * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
     */

    public function activate($getUniCode='', $randomKey='') 
    {
       if(trim($getUniCode)!="" && $randomKey!="") {
         $getUniCode = filter_var($getUniCode, FILTER_SANITIZE_STRING);
         $getUser = $this->Users->find('all',['conditions'=> ['otp'=> $getUniCode,'status'=> 0]])->first(); 
         if($getUser) {
           $getUserId = $getUser->id;
           $updateActivate  = $this->Users->updateAll(['status'=> 1, 'otp'=> ''], ['id'=> $getUserId]);
           $this->Flash->success(__('Your account has been Activated successfully. please login'));
           return $this->redirect(['action' => 'register']);
         }
       }

    }      

}

NOTE:-
Please check your both action allowed for all users . otherwise it will show "You are not authorized to access that location" . to allow action paste this code into initialize() or beforeFilter() function.

$this->Auth->allow(['register','activate']);

this will allow user to access that actions without login.

Explanation
Here we create 2 actions first is register to save register user email and generate u unique otp code and save it into db and send an email . second function is activate when a user click on activate link then it will redirect to activate action where we checking user otp is correct or not if its correct then activate his account and delete otp so he cant use same link to activate again.


Now run your register action of users controller and submit your email and you will receive an activation link email, using this link you can activate your account.

So we have successfully completed user email verification in cakephp 3.x. and also learn how to create component and use with cakephp 3.x .

Thank You.

Other Links

How to send OTP Email in cakephp 3x
How to send email with verification code in cakephp 3.x

Comments

Popular posts from this blog

Run and compile sass scss file to css using node

  Today we learn how to use scss and generate css using node  or Run and compile sass scss file to css using node   So please follow simple  steps :-   Today we will create a project that can read scss file and generates css with it  Note: Make sure you have installed node in your system. If you want to help to install node js based on your system then check our other tutorial or check node js official website. Now create a blank folder and open  terminal(linux) or cmd(windows) and navigate to your current project folder by using cd command Now run below command npm init after enter it will ask you some package info that you can fill according to you or just keep enter until it finished. The above command will generate package.json file Now  we will install npm module that will convert our scss to css Run below command: npm install node-sass So we have installed node-sass package . Now open package.json file in your...

How to retrieve Facebook Likes, share , comment Counts

function facebook_count($url){     // Query in FQL     $fql  = "SELECT share_count, like_count, comment_count ";     $fql .= " FROM link_stat WHERE url = '$url'";     $fqlURL = "https://api.facebook.com/method/fql.query?format=json&query=" . urlencode($fql);     // Facebook Response is in JSON     $response = file_get_contents($fqlURL);     return json_decode($response); } $fb = facebook_count('https://www.facebook.com/BahutHoGyiPadhai'); // facebook share count echo $fb[0]->share_count;  echo "like"; // facebook like count echo $fb[0]->like_count ; echo "comment"; // facebook comment count echo $fb[0]->comment_count;  ?>

Solution-windows 'expo' is not recognized as an internal or external command

Solution for expo is not recognized as an internal or external command,operable program or batch file in Windows 10 Sometimes expo will not work globally mostly in windows 10, If you are facing same issue then follow the below Steps 1) Click on windows button and search for  " Environment variables"  and click on "Edit the system environment variables" 2) Now you will see a popup like below screen. Then you need to click on Environment Variables. (Please see highlight part in below image)     3)Then click on new button that i have highlighted in below image 4. Then a popup will open and you need to fill details like below mentioned Variable Name :Path Variable Value: %USERPROFILE%\AppData\Roaming\npm Here we are creating a new path variable and passing location of npm.   Now Click on OK and close all the terminal windows and open new CMD or terminal and type Expo . Great now you can access expo from any...