Skip to content

Instantly share code, notes, and snippets.

@samuel-fonseca
Last active June 7, 2021 09:37
Show Gist options
  • Save samuel-fonseca/ad0e9fd6ed66b33fe4d1aafcf190f60c to your computer and use it in GitHub Desktop.
Save samuel-fonseca/ad0e9fd6ed66b33fe4d1aafcf190f60c to your computer and use it in GitHub Desktop.
A dynamic method to create HTML Emails and send them using PHPMailer XOAUTH2 with Gmail. This project is in no shape or form part of the PHPMailer project; I am simply using PHPMailer to send the emails because of their great project.
<?php
/**
* Generate dynamic HTML emails
*
* @package Dynamic HTML PHPMailer builder
* @author Samuel Fonseca <samuel@brazucaz.com>
* @description Setup dynamic HTML emails using PHPMailer
*/
/**
* NOTE: This class needs PHPMailer to work properly
* this is not an official extention, simply a test
* and a project which would hopefully help developers
* create dynamic HTML email bodies.
* I came up with the idea because I had a really hard
* time finding, and implementing a good solution.
* -----------
* This software is made available as-is. I am not responsible as to
* how you use it.
*/
/**
* I have no connection to PHPMailer
* All of PHPMailer's code is from their example
* find out more here: https://github.com/PHPMailer/PHPMailer
**/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\OAuth;
// Alias the League Google OAuth2 provider class
use League\OAuth2\Client\Provider\Google;
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
//Load dependencies from composer
//If this causes an error, run 'composer install'
require 'vendor/autoload.php';
class email
{
/**
* @var $firstname will hold the recipient's first name
*/
public $firstname = '';
/**
* @var $lastname will hold the recipient's last name
*/
public $lastname = '';
/**
* @var $email will hold the recipient's email
*/
public $email = '';
/**
* @var $subject will hold the emails's subject
*/
public $subject = '';
/**
* @var $body will hold the HTML body content
*/
public $body = '';
/**
* @var $sender_name will hold the sender's email
*/
public $sender_name = '';
/**
* @var $sender_email will hold the sender's email
*/
public $sender_email = '';
/**
* @var $message will hold the message with responses
*/
public $message = array();
/**
* Construct function
*
* @param $firstname for recipient
* @param $lastname for recipient
* @param $email for recipient
* @param $subject for email
*
**/
public function __construct( $firstname, $lastname, $email, $subject = '' )
{
$this->firstname = $firstname;
$this->lastname = $lastname;
$this->subject = $subject;
$this->email = $email;
}
/**
* set_sender function
*
* @param $name is the name of the sender (YOUR NAME)
* @param $email is the email of the sender (YOUR EMAIL)
*/
public function set_sender($name, $email)
{
$this->sender_name = $name;
$this->sender_email = $email;
}
/**
*
* Generate email
*
* @param $template_values will be an array with all the data
* @param $is_recurring boolean for us to know whether to add disclaimer (Donation only)
* @return boolean
**/
public function generate( $template_values )
{
// setup email body with HTML features
// I included the `styling` here since it
// would be easier, but go wild with it
$this->body = "<html lang='en'>
<head>
<meta name='viewport' content='width=device-width,initial-scale=1.0'>" . /** set viewport for phone displays **/ . "
<title>" . $this->subject . "</title>
<style>
body{font-family:'Roboto',sans-serif;background-color:#f2f2f2}.header{background-color:#333;display:flex;position:relative;flex-direction:column;justify-content:space-between;width:40%;margin:auto;margin-left:auto;box-sizing:border-box;color:white;color:var(--mdc-theme-text-primary-on-primary, white)}.header img{margin-right:auto;margin-left:auto;width:35%}.text-centered{text-align:center}.content{z-index:10;width:40%;margin-left:auto;margin-right:auto; background-color:white; padding:15px;}.table{width:100%;margin-left:auto;margin-right:auto;padding:15px;background-color:#fff}@media only screen and (max-width: 850px){.header{width:100%}.content{width:100%}}p.copyright{text-align:center;background-color:#333;display:block;margin-top:0;color:#fff;padding:20px}
</style>
</head>";
// if the content comes in an array the script
// will create a table which will hold the keys
// as well as the values beside each other
if ( is_array( $template_values ) )
{
$this->body .= "<body>
<div class='header mdc-elevation--z4'>
<h2 class='text-centered'>" . $this->subject . "</h2>
</div>
<div class='content'>
<table width='680' border='0' cellspacing='3' cellpadding='5' class='table mdc-elevation--z3'>
<tbody>";
// create loop to get contents of array
foreach ( $template_values as $key => $value )
{
// make sure $value is not an array as well
if ( !is_array($value) )
{ // <-- Need to break the content into sections
if ( empty($value) )
{
// we do not want any values that are empty
continue;
}
$this->body .= "<tr>";
$this->body .= "<td>" . $key . "</td>";
$this->body .= "<td>" . $value . "</td>";
$this->body .= "</tr>";
}
// if $value is an array then prepare to create new loop
else
{
$this->body .= "<tr>";
$this->body .= "<td colspan='2'><h3>" . $key . "</h3></td>";
$this->body .= "</tr>";
// loop through $value to get array content
foreach($value as $k => $val)
{
if ( empty($val) )
{
// we do not want any values that are empty
continue;
}
$this->body .= "<tr>";
$this->body .= "<td>" . $k . "</td>";
$this->body .= "<td>" . $val . "</td>";
$this->body .= "</tr>";
}
}
}
$this->body .= "</table>";
$this->body .= "</div>";
$this->body .= "</body>";
}
// if it's not an array, get the content
// and send it as HTML formatted text
else
{
$this->body .= "<body>
<div class='header mdc-elevation--z4'>
<h2 class='text-centered'>" . $this->subject . "</h2>
</div>
<div class='content'>"
. $template_values .
"</div>";
$this->body .= "</body>"; // <-- close `body` element
}
$this->body .= "</html>"; // <-- close `html` element
return true; // <-- email generated successfully
}
/**
*
* Send email
*
* @return $this->message
**/
public function send()
{
$mail = new PHPMailer;
$mail->isSMTP();
//Enable SMTP debugging
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2;
$mail->Host = 'smtp.gmail.com';
$mail->Port = 587;
$mail->SMTPSecure = 'tls';
// OR
// $mail->Host = 'tls://smtp.gmail.com:587';
/** AUTHENTICATION
* for security reasons I went with
* XOAUTH2 from Google, if you need
* setting it up look under their
* documentation:
* https://github.com/PHPMailer/PHPMailer/wiki/Using-Gmail-with-XOAUTH2
**/
$mail->SMTPAuth = true;
//Set AuthType to use XOAUTH2
$mail->AuthType = 'XOAUTH2';
//Fill in authentication details here
//Either the gmail account owner, or the user that gave consent
$email = 'someone@gmail.com'; // <-- your Google email
$clientId = 'YOUR_CLIENT_ID.apps.googleusercontent.com';
$clientSecret = 'YOUR_CLIENT_SECRET';
//Obtained by configuring and running get_oauth_token.php
//after setting up an app in Google Developer Console.
$refreshToken = 'YOUR_REFRESH_TOKEN';
//Create a new OAuth2 provider instance
$provider = new Google(
[
'clientId' => $clientId,
'clientSecret' => $clientSecret,
]
);
//Pass the OAuth provider instance to PHPMailer
$mail->setOAuth(
new OAuth(
[
'provider' => $provider,
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'refreshToken' => $refreshToken,
'userName' => $email,
]
)
);
// check for sender's name and email
if ( $this->sender_email == '' || $this->sender_name == '' )
{
$this->message = array("is_error" => 'danger',
"message" => "Sender name and email are required.");
return $this->message;
exit;
}
else
{
//Set who the message is to be sent from
//For gmail, this generally needs to be the same as the user you logged in as
$mail->setFrom($this->sender_email, $this->sender_name);
}
//Set who the message is to be sent to
$mail->addAddress($this->email, $this->firstname . ' ' . $this->lastname);
//Set the subject line
$mail->Subject = $this->subject;
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->CharSet = 'utf-8';
// body is set with generate
$mail->msgHTML( $this->body );
//send the message, check for errors
if (!$mail->send()) {
$this->message = array("is_error" => 'danger',
"message" => "Mailer Error: " . $mail->ErrorInfo);
} else {
$this->message = array("is_error" => 'success',
"message" => "An email confirmation has been sent to " . $this->email . ". If there are any problems do not hesitate to contact us.");
}
return $this->message;
}
}
@samuel-fonseca
Copy link
Author

samuel-fonseca commented Sep 28, 2017

To call the function just set it up as:

// first param firstname
// second param lastname
// third param email
$m = new email('samuel', 'lastname', 'email@somewhere.com');
// setup sender info
$m->set_sender('First Last', 'someone@gmail.com'); /** note: Gmail is required here for the XOAUTH2 **/
// if list of items send as 2d array
$m->generate('key' => 'value',
             'key2' => 'value2');
/** OR **/
$m->generate('A simple text email.');
// send
$m->send();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment