Sending Emails in CakePHP3 Using Mail Class

Abhigyan Singh 01st Oct 2020

In this article, you will learn how to configure mail transport options, make mail headers, create email templates, and create reusable emails in cakephp3. Here we use SMTP (Simple Mail Transfer Protocol) to send emails using CakePHP. These days it is very important to send emails from our web application like emails for registration, email for forgetting URL link, welcome message, etc. Here we will show how to send emails using our CakePHP web application.

You can easily send an email by loading the Email class then write these few lines.

use Cake\Mailer\Email;

// instantiate Email class
$email = new Email();
$email->from([[email protected]' => Your website'])
->to(youremail @example.com')
->subject('about email')
->send(' Your message');

You can make configurations using SMTP servers in config/app.php. need a server host, port, username, and password. we also can add TLS SMTP using the tls field. I am using the Gmail SMTP server and you can also use it by your email account authentication.

In config.php

'EmailTransport' => [
'default' => [
'className' => 'SMTP',
// The following keys are used in SMTP transports
'host' => 'ssl://smtp.gmail.com',
'port' => 465,
'timeout' => 30,
'username' => '[email protected]',
'password' => your email password',
'client' => null,
'tls' => null,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],

Or you can put configuration code in controller or models like that

use Cake\Mailer\Email;
Email::configTransport('gmail', [
'host' => 'smtp.gmail.com',
'port' => 587,
'username' => '[email protected]',
'password' => 'secret',
'className' => 'Smtp',
'tls' => true
]);

Note: If you are using localhost for this code, you might need to open the php.ini  file in the PHP directory and allow  php_openssl.dll. Eliminate semicolon before this line if exist.

extension=php_openssl.dll

Save changes and restart your apache server.

After making configurations, you can make an instantiation from the Email class and begin to configure your email profiles.
For instance, In UsersController.php  you might want to send an email for newly registered users. So, the add() function can be like that :

UsersController.php  

<?php
namespace App\Controller;

use App\Controller\AppController;
use Cake\Mailer\MailerAwareTrait;
use Cake\Mailer\Email;

class UsersController extends AppController{
use MailerAwareTrait;
public function initialize()
{
parent::initialize();
$this->loadComponent('Flash'); // Include the FlashComponent
// Auth component allow visitors to access add action to register and access logout action
$this->Auth->allow(['logout', 'add']);

}

public function login()
{
if ($this->request->is('post')) {
// Auth component identify if sent user data belongs to a user
$user = $this->Auth->identify();
if ($user) {
//
$this->Auth->setUser($user);

return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Invalid username or password, try again.'));
}
}

public function logout(){
$this->Flash->success('You successfully have loged out');
return $this->redirect($this->Auth->logout());
}
public function index()
{
$this->set('users',$this->Users->find('all'));
}
public function view($id)
{
$user = $this->Users->get($id);
$this->set('user',$user);

}
public function add()
{
$user = $this->Users->newEntity();
if($this->request->is('post')) {
$this->Users->patchEntity($user,$this->request->data);
if($this->Users->save($user)){
/* simple way sending emails */
//
// $email = new Email('default');
// $email->from(['[email protected]' => 'My Site']) // sender email
// ->to('[email protected]') // receiver email
// ->cc('[email protected]') // cabron copy email
// ->bcc('[email protected]') // blind carbon copy email
// ->subject('About') // message subjetc
// ->replyTo('[email protected]') // emial to reply toll ll
// ->send('This is a simple message content '); // send function take the message content parameter

/* Sending emails using reusable emails */
$this->getMailer('User')->send('registered', [$user]); // call send function with template name and sent data to the template

$this->Flash->success(__('Your account has been registered .'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Unable to register your account.'));
}
$this->set('user',$user);
}

public function edit($id)
{
$user = $this->Users->get($id);
if ($this->request->is(['post', 'put'])) {
$this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('Your profile data has been updated.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Unable to update your profile.'));
}

$this->set('user', $user);

}
public function delete($id)
{
$this->request->allowMethod(['post', 'delete']);

$user = $this->Users->get($id);
if ($this->Users->delete($user)) {
$this->Flash->success(__('The user with id: {0} has been deleted.', h($id)));
return $this->redirect(['action' => 'index']);
}

}
}

?>

We used some keys in the previous code to make email headers and content :

from: the sender’s email.

to: the receiver’s email.

cc:  carbon copy email.

Bcc:  blind carbon copy email

Subject: Message subject

replyTo:  email to reply to

send() function:  it sends emails using specified content, template, and layout.

How to make reusable emails?

To have a clean and organized and flexible, Mailers in pagination CakePHP allow you to make reusable emails.
We want to create reusable emails for UsersController. So, Create file src/Mailer/UserMailer.php.Inside it, we will create a function for every template or email. We want to make two messages; registered for newly registered users and forget the password for resetting passwords.

UserMailer.php

<?php
namespace App\Mailer;
use Cake\Mailer\Mailer;
class UserMailer extends Mailer
{
public function registered($user)
{
// attach a text file
$this->attachments([
'text for user.txt'=> [
'file'=> 'files/example.txt',
'mimetype'=>'plain/text',
'contentId'=>'3734hf38'
],
// attach an image file
'edit.png'=>[
'file'=>'files/welcome.png',
'mimetype'=>'image/png',
'contentId'=>'734h3r38'
]
])
->to($user->email)
->emailFormat('html')
->subject(sprintf('Welcome %s', $user->name))
->viewVars([
'username'=> $user->name,
'useremail'=>$user->email
])
// the template file you will use in this emial
->template('registered') // By default template with same name as method name is used.
// the layout .ctp file you will use in this email
->layout('customLayout');
}
public function resetPassword($user)
{
$this->to($user->email)
->subject('Reset password')
->set(['token' => $user->token]);
}
}

In the previous code, we used attachments() to attach files to the email. It needs a file name that will appear to the receiver and array of the file path, file type, and content-id.Content id is used if you want to use this file in the Html template body like <img
src="cid:my-content-id">
.

template()  is used to specify the templates used in this email.

layout()  is used to specify the layout template used in this email.

viewers() Passes data in the template file

Create the template file src/Template/Email/HTML/registered.ctp.

<p>Hello <?php echo $username?><<?php echo $useremail?>></p>
<p>
Welcome to Our web site .We hope you enjoy our services :<br>
<br>
</p>

<p>
You were rgistered successfully
<img src='cid:734h3r38' />
</p>

Note: As we use an HTML email format, we created an HTML template and put it in the Html templates directory  src/Template/Email/html/.We can use a text email format by this key and ‘text’ value

->emailFormat('text')

In-text email format we put the template file in the text templates directory src/Template/Email/text/

We can make multipart templated email message by this code

->emailFormat('both').

Create the layout template src/Template/Layout/Email/html/customLayout.ctp.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title><?php echo $this->fetch('title'); ?></title>
</head>
<body>
<?php echo $this->fetch('content'); ?>
</body>
</html>

Now we can use UserMailer to send user-related emails from any place in the application. Here is how to use it in UsersController.php

<?php
namespace App\Controller;

use App\Controller\AppController;
use Cake\Mailer\MailerAwareTrait;
use Cake\Mailer\Email;

class UsersController extends AppController{
use MailerAwareTrait;
public function initialize()
{
parent::initialize();
$this->loadComponent('Flash'); // Include the FlashComponent
// Auth component allow visitors to access add action to register and access logout action
$this->Auth->allow(['logout', 'add']);

}

public function add()
{
$user = $this->Users->newEntity();
if($this->request->is('post')) {
$this->Users->patchEntity($user,$this->request->data);
if($this->Users->save($user)){
/* Sending emails using reusable emails */
$this->getMailer('User')->send('registered', [$user]); // call send function with template name and sent data to the template

$this->Flash->success(__('Your account has been registered .'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Unable to register your account.'));
}
$this->set('user',$user);
}
// … Other functions

}
?>

You can find the code of re-usable emails in the downloads demo. Read, write code, try with valid data, and ask in comments if you have any problems.

Authored By Abhigyan Singh

He is a continuous blogger and has blogged on different topic. He loves to surf Internet and always trying to get new Idea about new Technology and Innovations and sharing these great information to all the technology lovers.

Also on DiscussDesk