From c9ea492b68d4200d51f0a316c9ae3bbf9aecf280 Mon Sep 17 00:00:00 2001 From: Rosario Carvello Date: Fri, 10 May 2024 16:29:52 +0200 Subject: [PATCH] Add PHPMailer wrapper --- config/phpmailerservice.config.inc | 8 + framework/classes/Common.php | 6 - framework/classes/MailService.php | 697 +++++++++++++++++++++++++ framework/classes/PHPMailerService.php | 70 +++ index.php | 4 +- 5 files changed, 777 insertions(+), 8 deletions(-) create mode 100644 config/phpmailerservice.config.inc create mode 100644 framework/classes/MailService.php create mode 100644 framework/classes/PHPMailerService.php diff --git a/config/phpmailerservice.config.inc b/config/phpmailerservice.config.inc new file mode 100644 index 0000000..d52cebf --- /dev/null +++ b/config/phpmailerservice.config.inc @@ -0,0 +1,8 @@ + + * @version GIT:v1.1.0 + * @copyright (c) 2016 Rosario Carvello - All rights reserved. See License.txt file + * @license BSD Clause 3 License + * @license https://opensource.org/licenses/BSD-3-Clause This software is distributed under BSD-3-Clause Public License + */ + +namespace framework\classes; +class MailService +{ + /** + * @var int $_wrap + */ + protected $_wrap = 78; + + /** + * @var array $_to + */ + protected $_to = array(); + + /** + * @var string $_subject + */ + protected $_subject; + + /** + * @var string $_message + */ + protected $_message; + + /** + * @var array $_headers + */ + protected $_headers = array(); + + /** + * @var string $_parameters + */ + protected $_params; + + /** + * @var array $_attachments + */ + protected $_attachments = array(); + + /** + * @var string $_uid + */ + protected $_uid; + + /** + * Named constructor. + * + * @return static + */ + public static function make() + { + return new SimpleMail(); + } + + /** + * __construct + * + * Resets the class properties. + */ + public function __construct() + { + $this->reset(); + } + + /** + * reset + * + * Resets all properties to initial state. + * + * @return self + */ + public function reset() + { + $this->_to = array(); + $this->_headers = array(); + $this->_subject = null; + $this->_message = null; + $this->_wrap = 78; + $this->_params = null; + $this->_attachments = array(); + $this->_uid = $this->getUniqueId(); + return $this; + } + + /** + * setTo + * + * @param string $email The email address to send to. + * @param string $name The name of the person to send to. + * + * @return self + */ + public function setTo($email, $name) + { + $this->_to[] = $this->formatHeader((string)$email, (string)$name); + return $this; + } + + /** + * getTo + * + * Return an array of formatted To addresses. + * + * @return array + */ + public function getTo() + { + return $this->_to; + } + + /** + * setFrom + * + * @param string $email The email to send as from. + * @param string $name The name to send as from. + * + * @return self + */ + public function setFrom($email, $name) + { + $this->addMailHeader('From', (string)$email, (string)$name); + return $this; + } + + /** + * setCc + * + * @param array $pairs An array of name => email pairs. + * + * @return self + */ + public function setCc(array $pairs) + { + return $this->addMailHeaders('Cc', $pairs); + } + + /** + * setBcc + * + * @param array $pairs An array of name => email pairs. + * + * @return self + */ + public function setBcc(array $pairs) + { + return $this->addMailHeaders('Bcc', $pairs); + } + + /** + * setReplyTo + * + * @param string $email + * @param string $name + * + * @return self + */ + public function setReplyTo($email, $name = null) + { + return $this->addMailHeader('Reply-To', $email, $name); + } + + /** + * setHtml + * + * @return self + */ + public function setHtml() + { + return $this->addGenericHeader( + 'Content-Type', 'text/html; charset="utf-8"' + ); + } + + /** + * setSubject + * + * @param string $subject The email subject + * + * @return self + */ + public function setSubject($subject) + { + $this->_subject = $this->encodeUtf8( + $this->filterOther((string)$subject) + ); + return $this; + } + + /** + * getSubject function. + * + * @return string + */ + public function getSubject() + { + return $this->_subject; + } + + /** + * setMessage + * + * @param string $message The message to send. + * + * @return self + */ + public function setMessage($message) + { + $this->_message = str_replace("\n.", "\n..", (string)$message); + return $this; + } + + /** + * getMessage + * + * @return string + */ + public function getMessage() + { + return $this->_message; + } + + /** + * addAttachment + * + * @param string $path The file path to the attachment. + * @param string $filename The filename of the attachment when emailed. + * @param null $data + * + * @return self + */ + public function addAttachment($path, $filename = null, $data = null) + { + $filename = empty($filename) ? basename($path) : $filename; + $filename = $this->encodeUtf8($this->filterOther((string)$filename)); + $data = empty($data) ? $this->getAttachmentData($path) : $data; + $this->_attachments[] = array( + 'path' => $path, + 'file' => $filename, + 'data' => chunk_split(base64_encode($data)) + ); + return $this; + } + + /** + * getAttachmentData + * + * @param string $path The path to the attachment file. + * + * @return string + */ + public function getAttachmentData($path) + { + $filesize = filesize($path); + $handle = fopen($path, "r"); + $attachment = fread($handle, $filesize); + fclose($handle); + return $attachment; + } + + /** + * addMailHeader + * + * @param string $header The header to add. + * @param string $email The email to add. + * @param string $name The name to add. + * + * @return self + */ + public function addMailHeader($header, $email, $name = null) + { + $address = $this->formatHeader((string)$email, (string)$name); + $this->_headers[] = sprintf('%s: %s', (string)$header, $address); + return $this; + } + + /** + * addMailHeaders + * + * @param string $header The header to add. + * @param array $pairs An array of name => email pairs. + * + * @return self + */ + public function addMailHeaders($header, array $pairs) + { + if (count($pairs) === 0) { + throw new InvalidArgumentException( + 'You must pass at least one name => email pair.' + ); + } + $addresses = array(); + foreach ($pairs as $name => $email) { + $name = is_numeric($name) ? null : $name; + $addresses[] = $this->formatHeader($email, $name); + } + $this->addGenericHeader($header, implode(',', $addresses)); + return $this; + } + + /** + * addGenericHeader + * + * @param string $header The generic header to add. + * @param mixed $value The value of the header. + * + * @return self + */ + public function addGenericHeader($header, $value) + { + $this->_headers[] = sprintf( + '%s: %s', + (string)$header, + (string)$value + ); + return $this; + } + + /** + * getHeaders + * + * Return the headers registered so far as an array. + * + * @return array + */ + public function getHeaders() + { + return $this->_headers; + } + + /** + * setAdditionalParameters + * + * Such as "-fyouremail@yourserver.com + * + * @param string $additionalParameters The addition mail parameter. + * + * @return self + */ + public function setParameters($additionalParameters) + { + $this->_params = (string)$additionalParameters; + return $this; + } + + /** + * getAdditionalParameters + * + * @return string + */ + public function getParameters() + { + return $this->_params; + } + + /** + * setWrap + * + * @param int $wrap The number of characters at which the message will wrap. + * + * @return self + */ + public function setWrap($wrap = 78) + { + $wrap = (int)$wrap; + if ($wrap < 1) { + $wrap = 78; + } + $this->_wrap = $wrap; + return $this; + } + + /** + * getWrap + * + * @return int + */ + public function getWrap() + { + return $this->_wrap; + } + + /** + * hasAttachments + * + * Checks if the email has any registered attachments. + * + * @return bool + */ + public function hasAttachments() + { + return !empty($this->_attachments); + } + + /** + * assembleAttachment + * + * @return string + */ + public function assembleAttachmentHeaders() + { + $head = array(); + $head[] = "MIME-Version: 1.0"; + $head[] = "Content-Type: multipart/mixed; boundary=\"{$this->_uid}\""; + + return join(PHP_EOL, $head); + } + + /** + * assembleAttachmentBody + * + * @return string + */ + public function assembleAttachmentBody() + { + $body = array(); + $body[] = "This is a multi-part message in MIME format."; + $body[] = "--{$this->_uid}"; + $body[] = "Content-Type: text/html; charset=\"utf-8\""; + $body[] = "Content-Transfer-Encoding: quoted-printable"; + $body[] = ""; + $body[] = quoted_printable_encode($this->_message); + $body[] = ""; + $body[] = "--{$this->_uid}"; + + foreach ($this->_attachments as $attachment) { + $body[] = $this->getAttachmentMimeTemplate($attachment); + } + + return implode(PHP_EOL, $body) . '--'; + } + + /** + * getAttachmentMimeTemplate + * + * @param array $attachment An array containing 'file' and 'data' keys. + * + * @return string + */ + public function getAttachmentMimeTemplate($attachment) + { + $file = $attachment['file']; + $data = $attachment['data']; + + $head = array(); + $head[] = "Content-Type: application/octet-stream; name=\"{$file}\""; + $head[] = "Content-Transfer-Encoding: base64"; + $head[] = "Content-Disposition: attachment; filename=\"{$file}\""; + $head[] = ""; + $head[] = $data; + $head[] = ""; + $head[] = "--{$this->_uid}"; + + return implode(PHP_EOL, $head); + } + + /** + * send + * + * @return boolean + * @throws \RuntimeException on no 'To: ' address to send to. + */ + public function send() + { + $to = $this->getToForSend(); + $headers = $this->getHeadersForSend(); + + if (empty($to)) { + throw new \RuntimeException( + 'Unable to send, no To address has been set.' + ); + } + + if ($this->hasAttachments()) { + $message = $this->assembleAttachmentBody(); + $headers .= PHP_EOL . $this->assembleAttachmentHeaders(); + } else { + $message = $this->getWrapMessage(); + } + + return mail($to, $this->_subject, $message, $headers, $this->_params); + } + + /** + * debug + * + * @return string + */ + public function debug() + { + return '
' . print_r($this, true) . '
'; + } + + /** + * magic __toString function + * + * @return string + */ + public function __toString() + { + return print_r($this, true); + } + + /** + * formatHeader + * + * Formats a display address for emails according to RFC2822 e.g. + * Name + * + * @param string $email The email address. + * @param string $name The display name. + * + * @return string + */ + public function formatHeader($email, $name = null) + { + $email = $this->filterEmail((string)$email); + if (empty($name)) { + return $email; + } + $name = $this->encodeUtf8($this->filterName((string)$name)); + return sprintf('"%s" <%s>', $name, $email); + } + + /** + * encodeUtf8 + * + * @param string $value The value to encode. + * + * @return string + */ + public function encodeUtf8($value) + { + $value = trim($value); + if (preg_match('/(\s)/', $value)) { + return $this->encodeUtf8Words($value); + } + return $this->encodeUtf8Word($value); + } + + /** + * encodeUtf8Word + * + * @param string $value The word to encode. + * + * @return string + */ + public function encodeUtf8Word($value) + { + return sprintf('=?UTF-8?B?%s?=', base64_encode($value)); + } + + /** + * encodeUtf8Words + * + * @param string $value The words to encode. + * + * @return string + */ + public function encodeUtf8Words($value) + { + $words = explode(' ', $value); + $encoded = array(); + foreach ($words as $word) { + $encoded[] = $this->encodeUtf8Word($word); + } + return join($this->encodeUtf8Word(' '), $encoded); + } + + /** + * filterEmail + * + * Removes any carriage return, line feed, tab, double quote, comma + * and angle bracket characters before sanitizing the email address. + * + * @param string $email The email to filter. + * + * @return string + */ + public function filterEmail($email) + { + $rule = array( + "\r" => '', + "\n" => '', + "\t" => '', + '"' => '', + ',' => '', + '<' => '', + '>' => '' + ); + $email = strtr($email, $rule); + $email = filter_var($email, FILTER_SANITIZE_EMAIL); + return $email; + } + + /** + * filterName + * + * Removes any carriage return, line feed or tab characters. Replaces + * double quotes with single quotes and angle brackets with square + * brackets, before sanitizing the string and stripping out html tags. + * + * @param string $name The name to filter. + * + * @return string + */ + public function filterName($name) + { + $rule = array( + "\r" => '', + "\n" => '', + "\t" => '', + '"' => "'", + '<' => '[', + '>' => ']', + ); + $filtered = filter_var( + $name, + FILTER_SANITIZE_STRING, + FILTER_FLAG_NO_ENCODE_QUOTES + ); + return trim(strtr($filtered, $rule)); + } + + /** + * filterOther + * + * Removes ASCII control characters including any carriage return, line + * feed or tab characters. + * + * @param string $data The data to filter. + * + * @return string + */ + public function filterOther($data) + { + return filter_var($data, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); + } + + /** + * getHeadersForSend + * + * @return string + */ + public function getHeadersForSend() + { + if (empty($this->_headers)) { + return ''; + } + return join(PHP_EOL, $this->_headers); + } + + /** + * getToForSend + * + * @return string + */ + public function getToForSend() + { + if (empty($this->_to)) { + return ''; + } + return join(', ', $this->_to); + } + + /** + * getUniqueId + * + * @return string + */ + public function getUniqueId() + { + return md5(uniqid(time())); + } + + /** + * getWrapMessage + * + * @return string + */ + public function getWrapMessage() + { + return wordwrap($this->_message, $this->_wrap); + } +} diff --git a/framework/classes/PHPMailerService.php b/framework/classes/PHPMailerService.php new file mode 100644 index 0000000..fdb29bd --- /dev/null +++ b/framework/classes/PHPMailerService.php @@ -0,0 +1,70 @@ + + * @version GIT:v1.1.0 + * @copyright (c) 2016 Rosario Carvello - All rights reserved. See License.txt file + * @license BSD Clause 3 License + * @license https://opensource.org/licenses/BSD-3-Clause This software is distributed under BSD-3-Clause Public License + */ + +namespace framework\classes; +class PHPMailerService +{ + protected $smtp_username = SMTP_USERNAME; + protected $smtp_password = SMTP_PASSWORD; + protected $smtp_host = SMTP_HOST; + protected $smtp_port = SMTP_PORT; + protected $smtp_secure = 'ssl'; // can be ssl or tls + + protected $sender_email = DEFAULT_EMAIL; + protected $sender_name = DEFAULT_EMAIL_ACCOUNT_NAME; + + public function __construct() + { + if (empty($this->smtp_port)) { + $this->smtp_port = 465; + } + } + + public function send_mail($receipient_emails, $subject, $msg) + { + require_once LIBS_DIR . 'PHPMailer/PHPMailerAutoload.php'; + $mail = new PHPMailer; + if (USE_SMTP == true) { + //$mail->SMTPDebug = 3; // Enable verbose debug output + $mail->isSMTP(); // Set mailer to use SMTP + $mail->Host = $this->smtp_host; // Specify main and backup SMTP servers + $mail->SMTPAuth = true; // Enable SMTP authentication + $mail->Username = $this->smtp_username; // SMTP username + $mail->Password = $this->smtp_password; // SMTP password + $mail->SMTPSecure = $this->smtp_secure; // Enable TLS encryption, `ssl` also accepted + $mail->Port = $this->smtp_port; // TCP port to connect to + } + + $mail->From = $this->sender_email; + $mail->FromName = $this->sender_name; + + if (is_array($receipient_emails)) { + foreach ($receipient_emails as $email) { + $mail->addAddress($email); // Add a recipient + } + } else { + $mail->addAddress($receipient_emails); // Add a recipient + } + + $mail->isHTML(true); // Set email format to HTML + $mail->Subject = $subject; + $mail->Body = $msg; + $mail->AltBody = strip_tags($msg); + if ($mail->send()) { + return true; + } else { + return $mail->ErrorInfo; + } + } +} diff --git a/index.php b/index.php index 72d31f4..7cb9d43 100644 --- a/index.php +++ b/index.php @@ -23,9 +23,9 @@ /* Path of this script */ define ("RELATIVE_PATH", ""); - +ini_set('display_errors', 1); /* Enable error reporting and disable notices */ -error_reporting(E_ALL & ~E_NOTICE); +// error_reporting(E_ALL & ~E_NOTICE); // error_reporting(E_ALL); // ini_set('display_errors', '1');