Sending Confirmation Emails with Phalcon and Swift

Thien Tran Duy
Share

Today, sending emails is considered the basic functionality of any web application. Usually, an email is sent to notify the user of some kind of activity that has taken place on the website, such as when he registers the account, updates information, or when new friends have been found. In this short tutorial I’ll show you how to send emails via Gmail quickly from within a Phalcon sample application. You can download the full source code from GitHub. We'll be building functionality which lets us send a confirmation email, and reacts to the click of said confirmation email.

Step 1: Install Phalcon, Phalcon Tools

Installing Phalcon is easy if you just follow the instructions on their website. Don't forget to install the Phalcon tools as well!

If you're using Vagrant, you can also install the whole set into your box by following this tutorial.

Step 2: Initial setup of our application

We’ve successfully set up the development environment. Now we proceed to create the skeleton of our application. Open terminal (in Linux & Mac) or command prompt (cmd in Windows) and type following in the folder where you keep your web projects:

    phalcon project sendmail

This will produce the following file and folder structure:

sendmail project structure

Try it out. Open your web browser and type in http://127.0.0.1/sendmail/, or the address of the virtual host you gave to your project. Provided everything is running fine, as in the image below, continue to step 3.

enter image description here

Step 3: Initial configuration

There are a few things you need to configure at first:

  1. Database connection (app/config/config.php)
  2. Model, view, and controller directories
  3. Base application URL
  4. Mail server configuration

All configurations are stored in the config.php file as per the image below:

config.php

Enter configuration settings as in the image above, only replace credentials with your own.

Regarding "mail", here I've left the driver set to smtp. I set the host to use smtp.gmail.com which is Gmail’s SMTP server. I set the port to 465 via SSL, and from to my email address, basically the same email address we'll be using to actually send the emails.

Step 4: Database schema and configuration

The following schema shows 2 tables which we'll be using:

    CREATE TABLE IF NOT EXISTS `users` (
          `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
          `username` varchar(40) NOT NULL,
          `email` varchar(40) NOT NULL,
          `password` char(60) NOT NULL,
          `mustChangePassword` char(1) DEFAULT NULL,
          `fullName` varchar(50) NOT NULL,
          `active` char(1) DEFAULT NULL,
          PRIMARY KEY (`id`)
        ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

    CREATE TABLE IF NOT EXISTS `email_confirmations` (
          `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
          `usersId` int(10) unsigned NOT NULL,
          `code` char(32) NOT NULL,
          `createdAt` int(10) unsigned NOT NULL,
          `modifiedAt` int(10) unsigned DEFAULT NULL,
          `confirmed` char(1) DEFAULT 'N',
          PRIMARY KEY (`id`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

I leave out the details of how to create a database on purpose – it's assumed you know how to do this. Create a sample database with your favorite tool, and execute the above code against it.

A note about relationships here:

  • The model “users” has many “email_confirmations”.
  • The model "email_confirmations" belongs to "users"

Keep this in mind for later.

Step 5: Models and validation

A model is a class that extends Phalcon\Mvc\Model. It must be placed in the models directory. A model file must contain a single class; its class name should be in camel case notation and should correspond to the database table name. If, instead, you want to have a model User and a database table "users" you need to use the getSource method to configure this.

We will now let Phalcon Tools generate the code for us. Using the command line and moving to your project’s directory, execute the following command:

    phalcon model users
    phalcon model email_confirmations

Let’s check out sample generated class Users for table users, and upgrade it accordingly:

enter image description here

In the code above, we test if the login field validates against the rule Email. Additionally, we ensure that login is unique. Take note of the return statement which checks if validation has returned any validation messages.

Let’s check out the generated class EmailConfirmations:

email_confirmation

The following code represents a very simple skeleton and I will only explain how afterCreate() and initialize() should look like – the rest of the code is available in the repository linked at the beginning of this article.

  1. The initialize() method is only called once during the request. In this method, Phalcon is to automatically generate a hasMany relation.
        public function initialize(){
            $this->belongsTo('usersId', 'Users', 'id', array(
                'alias' => 'user'
            ));
        }

The first parameter indicates the field of the local model EmailConfirmations in the relationship; the second indicates the name of the referenced model (Users) and the third the field name in the referenced model. The alias is there to create an alternative name for the connection between these two models, so we can reference an email confirmation's user just by calling $emailConfirmationInstance->user.

  1. The afterCreate() method sends a confirmation email to a user after account creation. Notice we're using abstracted functionality to send the email – the email service resides in our dependency injector and does this separately from the model itself.
            public function afterCreate(){
                $this->getDI()->getMail()->send(
                    array($this->user->email => $this->user->username),
                    'Please confirm your email',
                    'confirmation',
                    array( 'confirmUrl' => '/confirm/' . $this->code.'/'. $this->user->email)
                );
            }

afterCreate() and beforeValidationOnUpdate() are Events – see the docs for more information on those.

Step 6: Controller and Library

The following code presents a very simple Controller skeleton and I’ll explain what view() and create() actions should look like, the rest of the code is available in the source.

    class SessionController extends ControllerBase{
            public function indexAction() {}
            public function signupAction(){}
            public function loginAction() {}
            public function confirmEmailAction(){}
    }

The signupAction() is receiving data from the form and storing it the table, while confirmEmailAction() confirms the account after signup. You can see the full file at SessionController.php.

This part of the application is implemented in the “Mail” component.

        require_once __DIR__ . '/../../vendor/Swift/swift_required.php';
        class Mail extends Phalcon\Mvc\User\Component
        {

            protected $_transport;

            public function getTemplate($name, $params){}
            public function send($to, $subject, $name, $params){}  
        }

Here, I'm using the Swift mail library. Install it via composer, or just include it in the vendor folder like on the linked GitHub repo (see here). This class extends the Phalcon\Mvc\User\Component, which, while not required, helps us fetch it via the DI container. Now, we register this class in the services container:

        <?php
        //app/config/service.php
        //Mail service uses Gmail;
        $di->set('mail', function(){
                return new Mail();
        });

The function getTemplate defines the template to be used with the email (see source for details).

    public function send($to, $subject, $name, $params)
    {
        //Settings
        $mailSettings = $this->config->mail;
        $template = $this->getTemplate($name, $params);
        // Create the message
        $message = Swift_Message::newInstance()
              ->setSubject($subject)
                              ->setTo($to)
              ->setFrom(array(
                  $mailSettings->fromEmail => $mailSettings->fromName
              ))
              ->setBody($template, 'text/html');
              if (!$this->_transport) {
                $this->_transport = Swift_SmtpTransport::newInstance(
                    $mailSettings->smtp->server,
                    $mailSettings->smtp->port,
                    $mailSettings->smtp->security
                )
                  ->setUsername($mailSettings->smtp->username)
                  ->setPassword($mailSettings->smtp->password);
              }
              // Create the Mailer using your created Transport
            $mailer = Swift_Mailer::newInstance($this->_transport);
            return $mailer->send($message);
        }

Step 7: view

I use scaffolding based on Twitter Bootstrap library. Even though scaffolding is a temporary solution it doesn’t mean it can’t look nice!

Keep in mind that when using scaffolding with bootstrap, Phalcon will only generate HTML tags with appropriate HTML classes – it is up to you to include the static resources like images and CSS, so navigate to your project root and edit the file app\views\index.volt by adding the stylesheet line:

        <head>
        <title>Phalcon PHP Framework</title>
        {{stylesheet_link ('http//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css',false)}} 
        {{stylesheet_link ('css/css.css')}} 
        </head>
        <body>
            {{ content() }}
        </body>

This particular example uses the Volt templating engine. Volt is an ultra-fast and designer friendly templating language written in C for PHP. It provides you with a set of helpers to write views in an easy way. More information is available in the official docs.

Next, create a signup form. A typical view would incorporate usage of the Phalcon\Tag component, a convienient helper class that aids creation of forms, links and other html elements:

form signup

Time to try it out. Open your web brower, visit the app, and go to [app url]/signup.

signup form

… and then check that user’s email account to verify that the email was sent successfully:

confirm account

Perfect! Our email was sent! Click confirm to activate the account, and that's it!

Conclusion

And that’s all there is to sending email messages with Phalcon and Gmail. You can of course customize your email messages as much as you’d like to make the mail more appealing.

For more information on Phalcon check out the online documentation. Thanks for reading – leave your feedback and comments below.