Skip to content

Instantly share code, notes, and snippets.

@shgysk8zer0
Last active May 16, 2018 04:54
Show Gist options
  • Save shgysk8zer0/a1704f1ad4ce45ad4959 to your computer and use it in GitHub Desktop.
Save shgysk8zer0/a1704f1ad4ce45ad4959 to your computer and use it in GitHub Desktop.
PHP Email Class
<?php
/**
* Simple PHP mail class using mail()
*
* Strips, converts, etc. Automatically sets required headers. Takes most
* of the work out of the coding side of writing emails.
*
* You should verify that you have an email service installed.
* On Ubuntu, I use ssmtp (see link for manpage)
*
* @author Chris Zuber <shgysk8zer0@gmail.com>
* @package core_shared
* @link http://php.net/manual/en/function.mail.php
* @link http://manpages.ubuntu.com/manpages/intrepid/man5/ssmtp.conf.5.html
*
* @example
* //Can be either a comma separated string or an array
* $to = ['user1@domain.com', 'user2@domain.com'];
* $subject = 'Sending email with PHP!';
* $message = file_get_contents('/path/to/someFile.html');
* $additional_headers = [
* 'content-type' => [
* 'text/html',
* 'charset' => $email::CHARSET
* ]
* ];
*
* $mail = new \core\email($to, $subject, $message, $additional_headers);
*
* $success = $mail->send(true);
*
* @copyright 2014, Chris Zuber
* @license http://opensource.org/licenses/GPL-3.0 GNU General Public License, version 3 (GPL-3.0)
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace core;
class email {
public $to = null, $from = null, $subject = null, $message = null;
protected $additional_headers = [], $additional_paramaters = [],
$default_headers = null;
const WRAP_AT = 70,
MAX_LENGTH = 1000,
HEADER_FILTER = '^A-z\-',
NL = "\r\n",
CHARSET = 'UTF-8',
CONTENT_TYPE = 'text/plain',
MIME_VERSION = '1.0';
/**
* Initialize the class and set its default variable from arguments
* $default_headers is built dynamically based on SERVER_ADMIN and
*
*
* @param mixed $to [String of array of recipients]
* @param string $subject [The subject of the email]
* @param string $message [Email body text]
* @param array $additional_headers [Things like 'From', 'To', etc]
* @param array $additional_paramaters [Additional command line arguments]
*/
public function __construct(
$to = null,
$subject = null,
$message = null,
array $additional_headers = null,
array $additional_paramaters = null
) {
$this->to = $to;
$this->subject = $subject;
$this->message = $message;
$this->default_headers = [
'MIME-Version' => $this::MIME_VERSION,
'Content-Type' => [
$this::CONTENT_TYPE,
'charset' => $this::CHARSET
],
'To' => $this->recepients(),
'From' => array_key_exists('SERVER_ADMIN', $_SERVER) ? $_SERVER['SERVER_ADMIN'] : null,
'X-Mailer' => 'PHP/' . PHP_VERSION
];
if(is_array($additional_headers)) {
$this->additional_headers = $additional_headers;
}
if(is_array($additional_paramaters)) {
$this->additional_paramaters = $additional_paramaters;
}
}
/**
* Set a value in $additional_headers using Magic Method
*
* @param string $key [Key in $additional_headers]
* @param mixed $value [Value to set it to]
* @return void
*
* @example $mail->From = 'user@domain.com';
*/
public function __set($key, $value) {
$this->additional_headers[str_replace('_', '-', $key)] = $value;
}
/**
* Retrieve a value from $additional_headers using Magic Method
*
* @param string $key [Key in $additional_headers]
* @return mixed [The value of $additional_headers[$key]]
*
* @example echo $mail->From;
*/
public function __get($key) {
return ($this->__isset($key)) ? $this->additional_headers[str_replace('_', '-', $key)] : null;
}
/**
* Check existance of $key in $additional_headers using Magic Method
*
* @param string $key [Key in $additional_headers]
* @return boolean
*
* @example isset($mail->From)
*/
public function __isset($key) {
return (array_key_exists(str_replace('_', '-', $key), $this->additional_headers));
}
/**
* Remove from $additional_headers using Magic Method
*
* @param string $key [Key in $additional_headers]
* @return void
*
* @example unset($mail->From)
*/
public function __unset($key) {
if($this->__isset($key)) unset($this->additional_headers[str_replace('_', '-', $key)]);
}
/**
* Headers are in two arrays -- default_headers & additional headers
* Headers in mail() are to be in the format: "Key: Value\r\n"
* Convert [$key => $value] on merging the two header array into the
* required format.
*
* @param void
* @return string
*/
protected function convert_headers() {
$headers = array_filter(array_merge($this->default_headers, $this->additional_headers));
return join($this::NL, array_map(function($key, $value) {
$key = preg_replace('/[' . $this::HEADER_FILTER . ']/', '-', strtoupper($key));
if(is_array($value)) {
return "{$key}:" . join('; ', array_map(function($sub_key, $sub_value) {
return (is_string($sub_key)) ? "{$sub_key}={$sub_value}" : "{$sub_value}";
}, array_keys($value), array_values($value)));
}
elseif(is_string($value)) {
return "{$key}: $value";
}
}, array_keys($headers), array_values($headers)));
}
/**
* Documentation lacks usage of $additional_paramaters, so this is just
* a basic array to string conversion by joining with newlines
*
* @return string
*/
protected function convert_paramaters() {
return join(PHP_EOL, $this->additional_paramaters);
}
/**
* $to is mixed, and may be a comma separated string or an array
* In either case, we want the output to be a string of valid email
* addresses separated by a ",".
*
* @param void
* @return string [user1@domain.com, user2@domain.com]
*/
protected function recepients() {
if(is_string($this->to)) {
return join(', ', array_filter(explode(', ', $this->to), [$this ,'is_email']));
}
elseif(is_array($this->to)) {
return join(', ', array_filter($this->to, [$this, 'is_email']));
}
elseif(is_object($this->to)) {
return join(', ', array_filter(get_object_vars($this->to), [$this, 'is_email']));
}
}
/**
* Verify that $address is a valid email address
*
* @param string $address [Text which should be an email address]
* @return boolean [Whether or not it matches the specification]
*/
public function is_email($address) {
return filter_var($address, FILTER_VALIDATE_EMAIL);
}
/**
* Most emails should be either plain text or HTML (no attachment support)
*
* The suggested length for plain text is 70 characters, and we will
* want to remove any HTML tags
*
* If this is an HTML message, we will want to wrap all lines to a max
* length of 1,000 (sometimes a requirement, better safe than sorry)
*
* In both cases, the only valid newline charter is "\r\n", so replace
* default newline with that.
*
* @param bool $html [Whether or not HTML output is desired]
* @return string
*/
protected function convert_message($html = false) {
return str_replace(
PHP_EOL,
$this::NL,
($html) ?
wordwrap(
$this->message,
$this::MAX_LENGTH,
$this::NL
) : wordwrap(
strip_tags($this->message),
$this::WRAP_AT,
$this::NL
)
);
}
/**
* Converts a subject into a wrapped special character safe string
*
* @param void
* @return string
*/
protected function trim_subject() {
return wordwrap(
strip_tags($this->subject),
$this::WRAP_AT,
$this::NL
);
}
/**
* Sends the email.
*
* All trimming, wrapping, converting, etc takes place here. Prior to
* this, the class variables are their original values. None are updated
* in this method, mail() only gets the output of the conversions.
*
* @param boolean $html [Is this an HTML email?]
* @return boolean [Success of mail()]
*/
public function send($html = false) {
if($html) {
$this->additional_headers['Content-Type'] = [
'text/html',
'charset' => $this::CHARSET
];
}
return mail(
$this->recepients(),
$this->trim_subject(),
$this->convert_message($html),
$this->convert_headers(),
$this->convert_paramaters()
);
}
}
?>
<?php
//Add classes/ directory to include_path()
set_include_path(__DIR__ . DIRECTORY_SEPARATOR . 'classes' . PATH_SEPARATOR . get_include_path());
//Set extension(s) for class autoloader
spl_autoload_extensions('.class.php');
//Enable auto loading of classes
spl_autoload_register();
//$to can be either an array of contacts, or a comma separated string.
//Email addresses will be verified, and invalid ones will be removed
$to = [
'user1@domain.com',
'user2@domain.com'
];
$subject = 'Sending email with PHP!';
$message = '
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Sending email with PHP!</title>
</head>
<body>
<h1>Lorem ipsum</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sit amet diam quis odio pretium porttitor eget in libero. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed accumsan leo in metus pharetra efficitur. Cras posuere augue non elit luctus, at malesuada arcu viverra. Sed rutrum nibh leo, vitae iaculis dui tempus vel. Cras eros enim, lobortis at tempor ut, vehicula convallis diam. Sed accumsan venenatis lacinia. Etiam consectetur eleifend est, id pulvinar odio volutpat ut. Suspendisse quis est id tellus vehicula condimentum. Aenean quis sapien et dui rhoncus vulputate ac ut ex. Ut eget fermentum mauris. Vestibulum nibh justo, luctus in accumsan quis, molestie non nibh. Ut placerat fermentum lacus, sed feugiat quam. Proin accumsan euismod arcu et rutrum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
</p>
<p>
Suspendisse potenti. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Suspendisse ac mi sit amet dolor gravida rutrum. Vestibulum dapibus eros quis tortor aliquam tincidunt. Vivamus ultrices vel mauris vitae pharetra. Mauris eu consequat tellus. Cras nec dictum mi. Fusce lobortis, ipsum vitae semper dictum, nisl nisl ullamcorper purus, vel gravida dui risus ac dolor. Etiam in velit quis ligula ornare rutrum. Aliquam sed lacus eget lorem molestie mattis eget ut velit. Sed tempus nibh nec risus eleifend, vitae pulvinar odio tristique. Aliquam rhoncus lobortis magna ut mattis.
</p>
<p>
Nullam pulvinar, libero ut posuere condimentum, sem massa aliquet diam, id aliquet purus risus at orci. Proin suscipit lectus id urna molestie consequat eget in nulla. Cras consequat viverra eleifend. Pellentesque bibendum, dui ac lacinia varius, turpis nisl rhoncus lacus, ac condimentum metus purus blandit diam. Praesent blandit eget lectus eu blandit. Phasellus ut lorem at urna ultricies hendrerit. Praesent sit amet metus sit amet eros efficitur euismod nec in libero. Interdum et malesuada fames ac ante ipsum primis in faucibus. Fusce dui lacus, pretium eget ultrices non, varius at massa. Sed at risus velit. Suspendisse congue nec odio eget tristique. Ut nec interdum purus. Donec efficitur volutpat felis quis cursus. Nullam quis nisi odio.
</p>
<p>
Aliquam ultricies posuere augue, rutrum rhoncus arcu condimentum quis. Cras vestibulum, nulla eget sodales ultricies, nunc ligula sollicitudin ipsum, sed gravida nulla justo ut libero. Nam efficitur imperdiet orci blandit condimentum. Nullam non lorem et dolor iaculis congue dictum sit amet mauris. Etiam convallis ultricies placerat. In tincidunt iaculis odio, ac congue est scelerisque non. Sed a tortor ac augue luctus convallis. Ut non neque in tortor porta tincidunt sit amet ac ligula. Ut hendrerit mauris et diam ornare, interdum pellentesque nisl porta. Aliquam luctus arcu id urna condimentum, vel pharetra quam pellentesque. Aliquam iaculis tortor sem, vitae interdum purus scelerisque id. Sed pellentesque leo augue, at rhoncus orci dapibus non. Nullam in tellus ipsum.
</p>
<p>
Sed auctor, massa sed viverra elementum, turpis ante tincidunt mi, eget consequat nulla libero ac sem. Morbi eget pretium velit. Donec vitae consequat quam. Mauris et justo condimentum, euismod lorem tempus, commodo orci. Ut placerat felis ante, a eleifend enim finibus id. Sed imperdiet lorem a purus aliquam, a auctor turpis vulputate. In nec consectetur magna. Etiam rhoncus tempus magna. Morbi facilisis consectetur suscipit. Ut scelerisque viverra auctor.
</p>
</body>
</html>';
//Load the class
$email = new \core\email($to, $subject, $message);
//\core\email::send() takes an optional boolean argument to switch from
//text/plain to text/html. If not set to true, all HTML tags will be
//stripped, content-type will be text/plain, and message will be word wrapped
//at 70 characters.
if($email->send(true)) {
exit('Email Sent');
}
else {
exit('Failed sending email');
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment