forked from science-ation/science-ation
1112 lines
31 KiB
PHP
1112 lines
31 KiB
PHP
<?php
|
|
/**
|
|
* o------------------------------------------------------------------------------o
|
|
* | This package is licensed under the Phpguru license. A quick summary is |
|
|
* | that for commercial use, there is a small one-time licensing fee to pay. For |
|
|
* | registered charities and educational institutes there is a reduced license |
|
|
* | fee available. You can read more at: |
|
|
* | |
|
|
* | http://www.phpguru.org/static/license.html |
|
|
* o------------------------------------------------------------------------------o
|
|
*
|
|
* © Copyright 2008,2009 Richard Heyes
|
|
*/
|
|
|
|
require_once(dirname(__FILE__) . '/mimePart.php');
|
|
|
|
class Rmail
|
|
{
|
|
/**
|
|
* The html part of the message
|
|
* @var string
|
|
*/
|
|
private $html;
|
|
|
|
/**
|
|
* The text part of the message(only used in TEXT only messages)
|
|
* @private string
|
|
*/
|
|
private $text;
|
|
|
|
/**
|
|
* The main body of the message after building
|
|
* @private string
|
|
*/
|
|
private $output;
|
|
|
|
/**
|
|
* An array of embedded images /objects
|
|
* @private array
|
|
*/
|
|
private $html_images;
|
|
|
|
/**
|
|
* An array of recognised image types for the findHtmlImages() method
|
|
* @private array
|
|
*/
|
|
private $image_types;
|
|
|
|
/**
|
|
* Parameters that affect the build process
|
|
* @private array
|
|
*/
|
|
private $build_params;
|
|
|
|
/**
|
|
* Array of attachments
|
|
* @private array
|
|
*/
|
|
private $attachments;
|
|
|
|
/**
|
|
* The main message headers
|
|
* @private array
|
|
*/
|
|
private $headers;
|
|
|
|
/**
|
|
* The return path address. If not set the From:
|
|
* address is used instead
|
|
* @private string
|
|
*/
|
|
private $return_path;
|
|
|
|
/**
|
|
* Array of information needed for smtp sending
|
|
* @private array
|
|
*/
|
|
private $smtp_params;
|
|
|
|
/**
|
|
* Sendmail path. Do not include -f
|
|
* @private $sendmail_path
|
|
*/
|
|
private $sendmail_path;
|
|
|
|
/**
|
|
* Constructor function.
|
|
*/
|
|
public function __construct()
|
|
{
|
|
/**
|
|
* Initialise some variables.
|
|
*/
|
|
$this->attachments = array();
|
|
$this->html_images = array();
|
|
$this->headers = array();
|
|
$this->text = '';
|
|
$this->sendmail_path = '/usr/lib/sendmail -ti';
|
|
|
|
/**
|
|
* If you want the auto load functionality
|
|
* to find other image/file types, add the
|
|
* extension and content type here.
|
|
*/
|
|
$this->image_types = array('gif' => 'image/gif',
|
|
'jpg' => 'image/jpeg',
|
|
'jpeg' => 'image/jpeg',
|
|
'jpe' => 'image/jpeg',
|
|
'bmp' => 'image/bmp',
|
|
'png' => 'image/png',
|
|
'tif' => 'image/tiff',
|
|
'tiff' => 'image/tiff',
|
|
'swf' => 'application/x-shockwave-flash');
|
|
|
|
/**
|
|
* Set these up
|
|
*/
|
|
$this->build_params['html_encoding'] = new QPrintEncoding();
|
|
$this->build_params['text_encoding'] = new SevenBitEncoding();
|
|
$this->build_params['html_charset'] = 'ISO-8859-1';
|
|
$this->build_params['text_charset'] = 'ISO-8859-1';
|
|
$this->build_params['head_charset'] = 'ISO-8859-1';
|
|
$this->build_params['text_wrap'] = 998;
|
|
|
|
/**
|
|
* Defaults for smtp sending
|
|
*/
|
|
if (!empty($_SERVER['HTTP_HOST'])) {
|
|
$helo = $_SERVER['HTTP_HOST'];
|
|
|
|
} elseif (!empty($_SERVER['SERVER_NAME'])) {
|
|
$helo = $_SERVER['SERVER_NAME'];
|
|
|
|
} else {
|
|
$helo = 'localhost';
|
|
}
|
|
|
|
$this->smtp_params['host'] = 'localhost';
|
|
$this->smtp_params['port'] = 25;
|
|
$this->smtp_params['helo'] = $helo;
|
|
$this->smtp_params['auth'] = false;
|
|
$this->smtp_params['user'] = '';
|
|
$this->smtp_params['pass'] = '';
|
|
|
|
/**
|
|
* Make sure the MIME version header is first.
|
|
*/
|
|
$this->headers['MIME-Version'] = '1.0';
|
|
$this->headers['X-Mailer'] = 'Rmail <http://www.phpguru.org/>';
|
|
}
|
|
|
|
/**
|
|
* Accessor to set the CRLF style
|
|
*
|
|
* @param string $crlf CRLF style to use.
|
|
* Use \r\n for SMTP, and \n
|
|
* for normal.
|
|
*/
|
|
public function setCRLF($crlf = "\n")
|
|
{
|
|
if (!defined('RMAIL_CRLF')) {
|
|
define('RMAIL_CRLF', $crlf, true);
|
|
}
|
|
|
|
if (!defined('MAIL_MIMEPART_CRLF')) {
|
|
define('MAIL_MIMEPART_CRLF', $crlf, true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Accessor to set the SMTP parameters
|
|
*
|
|
* @param string $host Hostname
|
|
* @param string $port Port
|
|
* @param string $helo HELO string to use
|
|
* @param bool $auth User authentication or not
|
|
* @param string $user Username
|
|
* @param string $pass Password
|
|
*/
|
|
public function setSMTPParams($host = null, $port = null, $helo = null, $auth = null, $user = null, $pass = null)
|
|
{
|
|
if (!is_null($host)) $this->smtp_params['host'] = $host;
|
|
if (!is_null($port)) $this->smtp_params['port'] = $port;
|
|
if (!is_null($helo)) $this->smtp_params['helo'] = $helo;
|
|
if (!is_null($auth)) $this->smtp_params['auth'] = $auth;
|
|
if (!is_null($user)) $this->smtp_params['user'] = $user;
|
|
if (!is_null($pass)) $this->smtp_params['pass'] = $pass;
|
|
}
|
|
|
|
/**
|
|
* Sets sendmail path and options (optionally) (when directly piping to sendmail)
|
|
*
|
|
* @param string $path Path and options for sendmail command
|
|
*/
|
|
public function setSendmailPath($path)
|
|
{
|
|
$this->sendmail_path = $path;
|
|
}
|
|
|
|
/**
|
|
* Accessor function to set the text encoding
|
|
*
|
|
* @param object $encoding Text encoding to use
|
|
*/
|
|
public function setTextEncoding(iEncoding $encoding)
|
|
{
|
|
$this->build_params['text_encoding'] = $encoding;
|
|
}
|
|
|
|
/**
|
|
* Accessor function to set the HTML encoding
|
|
*
|
|
* @param object $encoding HTML encoding to use
|
|
*/
|
|
public function setHTMLEncoding(iEncoding $encoding)
|
|
{
|
|
$this->build_params['html_encoding'] = $encoding;
|
|
}
|
|
|
|
/**
|
|
* Accessor function to set the text charset
|
|
*
|
|
* @param string $charset Character set to use
|
|
*/
|
|
public function setTextCharset($charset = 'ISO-8859-1')
|
|
{
|
|
$this->build_params['text_charset'] = $charset;
|
|
}
|
|
|
|
/**
|
|
* Accessor function to set the HTML charset
|
|
*
|
|
* @param string $charset Character set to use
|
|
*/
|
|
public function setHTMLCharset($charset = 'ISO-8859-1')
|
|
{
|
|
$this->build_params['html_charset'] = $charset;
|
|
}
|
|
|
|
/**
|
|
* Accessor function to set the header encoding charset
|
|
*
|
|
* @param string $charset Character set to use
|
|
*/
|
|
public function setHeadCharset($charset = 'ISO-8859-1')
|
|
{
|
|
$this->build_params['head_charset'] = $charset;
|
|
}
|
|
|
|
/**
|
|
* Accessor function to set the text wrap count
|
|
*
|
|
* @param integer $count Point at which to wrap text
|
|
*/
|
|
public function setTextWrap($count = 998)
|
|
{
|
|
$this->build_params['text_wrap'] = $count;
|
|
}
|
|
|
|
/**
|
|
* Accessor to set a header
|
|
*
|
|
* @param string $name Name of header
|
|
* @param string $value Value of header
|
|
*/
|
|
public function setHeader($name, $value)
|
|
{
|
|
$this->headers[$name] = $value;
|
|
}
|
|
|
|
/**
|
|
* Sets the delivery reciept address
|
|
*
|
|
* @param string $email The address you want the delivery reciept
|
|
* sent to. Note that this is sent at the
|
|
* discretion of the recipient
|
|
*/
|
|
public function setReceipt($email)
|
|
{
|
|
$this->headers['Disposition-Notification-To'] = $email;
|
|
}
|
|
|
|
/**
|
|
* Accessor to add a Subject: header
|
|
*
|
|
* @param string $subject Subject to set
|
|
*/
|
|
public function setSubject($subject)
|
|
{
|
|
$this->headers['Subject'] = $subject;
|
|
}
|
|
|
|
/**
|
|
* Accessor to add a From: header
|
|
*
|
|
* @param string $from From address
|
|
*/
|
|
public function setFrom($from)
|
|
{
|
|
$this->headers['From'] = $from;
|
|
}
|
|
|
|
/**
|
|
* Accessor to set priority. Priority given should be either
|
|
* high, normal or low. Can also be specified numerically,
|
|
* being 1, 3 or 5 (respectively).
|
|
*
|
|
* @param mixed $priority The priority to use.
|
|
*/
|
|
public function setPriority($priority = 'normal')
|
|
{
|
|
switch (strtolower($priority)) {
|
|
case 'high':
|
|
case '1':
|
|
$this->headers['X-Priority'] = '1';
|
|
$this->headers['X-MSMail-Priority'] = 'High';
|
|
break;
|
|
|
|
case 'normal':
|
|
case '3':
|
|
$this->headers['X-Priority'] = '3';
|
|
$this->headers['X-MSMail-Priority'] = 'Normal';
|
|
break;
|
|
|
|
case 'low':
|
|
case '5':
|
|
$this->headers['X-Priority'] = '5';
|
|
$this->headers['X-MSMail-Priority'] = 'Low';
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Accessor to set the return path
|
|
*
|
|
* @param string $return_path Return path to use
|
|
*/
|
|
public function setReturnPath($return_path)
|
|
{
|
|
$this->return_path = $return_path;
|
|
}
|
|
|
|
/**
|
|
* Accessor to add a Cc: header
|
|
*
|
|
* @param string $cc Carbon Copy address
|
|
*/
|
|
public function setCc($cc)
|
|
{
|
|
$this->headers['Cc'] = $cc;
|
|
}
|
|
|
|
/**
|
|
* Accessor to add a Bcc: header
|
|
*
|
|
* @param string $bcc Blind Carbon Copy address
|
|
*/
|
|
public function setBcc($bcc)
|
|
{
|
|
$this->headers['Bcc'] = $bcc;
|
|
}
|
|
|
|
/**
|
|
* Adds plain text. Use this function
|
|
* when NOT sending html email
|
|
*
|
|
* @param string $text Plain text of email
|
|
*/
|
|
public function setText($text)
|
|
{
|
|
$this->text = $text;
|
|
}
|
|
|
|
/**
|
|
* Adds HTML to the emails, with an associated text part.
|
|
* If third part is given, images in the email will be loaded
|
|
* from this directory.
|
|
*
|
|
* @param string $html HTML part of email
|
|
* @param string $images_dir Images directory
|
|
*/
|
|
function setHTML($html, $images_dir = null)
|
|
{
|
|
$this->html = $html;
|
|
|
|
if (!empty($images_dir)) {
|
|
$this->findHtmlImages($images_dir);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function for extracting images from
|
|
* html source. This function will look
|
|
* through the html code supplied by setHTML()
|
|
* and find any file that ends in one of the
|
|
* extensions defined in $obj->image_types.
|
|
* If the file exists it will read it in and
|
|
* embed it, (not an attachment).
|
|
*
|
|
* @param string $images_dir Images directory to look in
|
|
*/
|
|
private function findHtmlImages($images_dir)
|
|
{
|
|
// Build the list of image extensions
|
|
$extensions = array_keys($this->image_types);
|
|
|
|
preg_match_all('/(?:"|\')([^"\']+\.('.implode('|', $extensions).'))(?:"|\')/Ui', $this->html, $matches);
|
|
|
|
foreach ($matches[1] as $m) {
|
|
if (file_exists($images_dir . $m)) {
|
|
$html_images[] = $m;
|
|
$this->html = str_replace($m, basename($m), $this->html);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Go thru found images
|
|
*/
|
|
if (!empty($html_images)) {
|
|
|
|
// If duplicate images are embedded, they may show up as attachments, so remove them.
|
|
$html_images = array_unique($html_images);
|
|
sort($html_images);
|
|
|
|
foreach ($html_images as $img) {
|
|
if ($image = file_get_contents($images_dir . $img)) {
|
|
$ext = preg_replace('#^.*\.(\w{3,4})$#e', 'strtolower("$1")', $img);
|
|
$content_type = $this->image_types[$ext];
|
|
$this->addEmbeddedImage(new stringEmbeddedImage($image, basename($img), $content_type));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds an image to the list of embedded
|
|
* images.
|
|
*
|
|
* @param string $object Embedded image object
|
|
*/
|
|
public function addEmbeddedImage($embeddedImage)
|
|
{
|
|
$embeddedImage->cid = md5(uniqid(time()));
|
|
|
|
$this->html_images[] = $embeddedImage;
|
|
}
|
|
|
|
|
|
/**
|
|
* Adds a file to the list of attachments.
|
|
*
|
|
* @param string $attachment Attachment object
|
|
*/
|
|
public function addAttachment($attachment)
|
|
{
|
|
$this->attachments[] = $attachment;
|
|
}
|
|
|
|
/**
|
|
* Adds a text subpart to a mime_part object
|
|
*
|
|
* @param object $obj
|
|
* @return object Mime part object
|
|
*/
|
|
private function addTextPart(&$message)
|
|
{
|
|
$params['content_type'] = 'text/plain';
|
|
$params['encoding'] = $this->build_params['text_encoding']->getType();
|
|
$params['charset'] = $this->build_params['text_charset'];
|
|
|
|
if (!empty($message)) {
|
|
$message->addSubpart($this->text, $params);
|
|
} else {
|
|
$message = new Mail_mimePart($this->text, $params);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a html subpart to a mime_part object
|
|
*
|
|
* @param object $obj
|
|
* @return object Mime part object
|
|
*/
|
|
private function addHtmlPart(&$message)
|
|
{
|
|
$params['content_type'] = 'text/html';
|
|
$params['encoding'] = $this->build_params['html_encoding']->getType();
|
|
$params['charset'] = $this->build_params['html_charset'];
|
|
|
|
if (!empty($message)) {
|
|
$message->addSubpart($this->html, $params);
|
|
} else {
|
|
$message = new Mail_mimePart($this->html, $params);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Starts a message with a mixed part
|
|
*
|
|
* @return object Mime part object
|
|
*/
|
|
private function addMixedPart(&$message)
|
|
{
|
|
$params['content_type'] = 'multipart/mixed';
|
|
|
|
$message = new Mail_mimePart('', $params);
|
|
}
|
|
|
|
/**
|
|
* Adds an alternative part to a mime_part object
|
|
*
|
|
* @param object $obj
|
|
* @return object Mime part object
|
|
*/
|
|
private function addAlternativePart(&$message)
|
|
{
|
|
$params['content_type'] = 'multipart/alternative';
|
|
|
|
if (!empty($message)) {
|
|
return $message->addSubpart('', $params);
|
|
} else {
|
|
$message = new Mail_mimePart('', $params);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a html subpart to a mime_part object
|
|
*
|
|
* @param object $obj
|
|
* @return object Mime part object
|
|
*/
|
|
private function addRelatedPart(&$message)
|
|
{
|
|
$params['content_type'] = 'multipart/related';
|
|
|
|
if (!empty($message)) {
|
|
return $message->addSubpart('', $params);
|
|
} else {
|
|
$message = new Mail_mimePart('', $params);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds all html images to a mime_part object
|
|
*
|
|
* @param object $obj Message object
|
|
*/
|
|
private function addHtmlImageParts(&$message)
|
|
{
|
|
foreach ($this->html_images as $value) {
|
|
$params['content_type'] = $value->contentType;
|
|
$params['encoding'] = $value->encoding->getType();
|
|
$params['disposition'] = 'inline';
|
|
$params['dfilename'] = $value->name;
|
|
$params['cid'] = $value->cid;
|
|
|
|
$message->addSubpart($value->data, $params);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds all attachments to a mime_part object
|
|
*
|
|
* @param object $obj Message object
|
|
*/
|
|
private function addAttachmentParts(&$message)
|
|
{
|
|
foreach ($this->attachments as $value) {
|
|
$params['content_type'] = $value->contentType;
|
|
$params['encoding'] = $value->encoding->getType();
|
|
$params['disposition'] = 'attachment';
|
|
$params['dfilename'] = $value->name;
|
|
|
|
$message->addSubpart($value->data, $params);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Builds the multipart message.
|
|
*/
|
|
private function build()
|
|
{
|
|
if (!empty($this->html_images)) {
|
|
foreach ($this->html_images as $value) {
|
|
$quoted = preg_quote($value->name);
|
|
$cid = preg_quote($value->cid);
|
|
|
|
$this->html = preg_replace("#src=\"$quoted\"|src='$quoted'#", "src=\"cid:$cid\"", $this->html);
|
|
$this->html = preg_replace("#background=\"$quoted\"|background='$quoted'#", "background=\"cid:$cid\"", $this->html);
|
|
}
|
|
}
|
|
|
|
$message = null;
|
|
$attachments = !empty($this->attachments);
|
|
$html_images = !empty($this->html_images);
|
|
$html = !empty($this->html);
|
|
$text = !$html;
|
|
|
|
switch (true) {
|
|
case $text:
|
|
$message = null;
|
|
if ($attachments) {
|
|
$this->addMixedPart($message);
|
|
}
|
|
|
|
$this->addTextPart($message);
|
|
|
|
// Attachments
|
|
$this->addAttachmentParts($message);
|
|
break;
|
|
|
|
case $html AND !$attachments AND !$html_images:
|
|
$this->addAlternativePart($message);
|
|
|
|
$this->addTextPart($message);
|
|
$this->addHtmlPart($message);
|
|
break;
|
|
|
|
case $html AND !$attachments AND $html_images:
|
|
$this->addRelatedPart($message);
|
|
$alt = $this->addAlternativePart($message);
|
|
|
|
$this->addTextPart($alt);
|
|
$this->addHtmlPart($alt);
|
|
|
|
// HTML images
|
|
$this->addHtmlImageParts($message);
|
|
break;
|
|
|
|
case $html AND $attachments AND !$html_images:
|
|
$this->addMixedPart($message);
|
|
$alt = $this->addAlternativePart($message);
|
|
|
|
$this->addTextPart($alt);
|
|
$this->addHtmlPart($alt);
|
|
|
|
// Attachments
|
|
$this->addAttachmentParts($message);
|
|
break;
|
|
|
|
case $html AND $attachments AND $html_images:
|
|
$this->addMixedPart($message);
|
|
$rel = $this->addRelatedPart($message);
|
|
$alt = $this->addAlternativePart($rel);
|
|
|
|
$this->addTextPart($alt);
|
|
$this->addHtmlPart($alt);
|
|
|
|
// HTML images
|
|
$this->addHtmlImageParts($rel);
|
|
|
|
// Attachments
|
|
$this->addAttachmentParts($message);
|
|
break;
|
|
|
|
}
|
|
|
|
if (isset($message)) {
|
|
$output = $message->encode();
|
|
$this->output = $output['body'];
|
|
$this->headers = array_merge($this->headers, $output['headers']);
|
|
|
|
// Figure out hostname
|
|
if (!empty($_SERVER['HTTP_HOST'])) {
|
|
$hostname = $_SERVER['HTTP_HOST'];
|
|
|
|
} else if (!empty($_SERVER['SERVER_NAME'])) {
|
|
$hostname = $_SERVER['SERVER_NAME'];
|
|
|
|
} else if (!empty($_ENV['HOSTNAME'])) {
|
|
$hostname = $_ENV['HOSTNAME'];
|
|
|
|
} else {
|
|
$hostname = 'localhost';
|
|
}
|
|
|
|
$message_id = sprintf('<%s.%s@%s>', base_convert(time(), 10, 36), base_convert(rand(), 10, 36), $hostname);
|
|
$this->headers['Message-ID'] = $message_id;
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to encode a header if necessary
|
|
* according to RFC2047
|
|
*
|
|
* @param string $input Value to encode
|
|
* @param string $charset Character set to use
|
|
* @return string Encoded value
|
|
*/
|
|
private function encodeHeader($input, $charset = 'ISO-8859-1')
|
|
{
|
|
preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $input, $matches);
|
|
foreach ($matches[1] as $value) {
|
|
$replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
|
|
$input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
|
|
}
|
|
|
|
return $input;
|
|
}
|
|
|
|
/**
|
|
* Sends the mail.
|
|
*
|
|
* @param array $recipients Array of receipients to send the mail to
|
|
* @param string $type How to send the mail ('mail' or 'sendmail' or 'smtp')
|
|
* @return mixed
|
|
*/
|
|
public function send($recipients, $type = 'mail')
|
|
{
|
|
if (!defined('RMAIL_CRLF')) {
|
|
$this->setCRLF( ($type == 'mail' OR $type == 'sendmail') ? "\n" : "\r\n");
|
|
}
|
|
|
|
$this->build();
|
|
|
|
switch ($type) {
|
|
case 'mail':
|
|
$subject = '';
|
|
if (!empty($this->headers['Subject'])) {
|
|
$subject = $this->encodeHeader($this->headers['Subject'], $this->build_params['head_charset']);
|
|
unset($this->headers['Subject']);
|
|
}
|
|
|
|
// Get flat representation of headers
|
|
foreach ($this->headers as $name => $value) {
|
|
$headers[] = $name . ': ' . $this->encodeHeader($value, $this->build_params['head_charset']);
|
|
}
|
|
|
|
$to = $this->encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
|
|
|
|
if (!empty($this->return_path)) {
|
|
$result = mail($to, $subject, $this->output, implode(RMAIL_CRLF, $headers), '-f' . $this->return_path);
|
|
} else {
|
|
$result = mail($to, $subject, $this->output, implode(RMAIL_CRLF, $headers));
|
|
}
|
|
|
|
// Reset the subject in case mail is resent
|
|
if ($subject !== '') {
|
|
$this->headers['Subject'] = $subject;
|
|
}
|
|
|
|
|
|
// Return
|
|
return $result;
|
|
break;
|
|
|
|
case 'sendmail':
|
|
// Get flat representation of headers
|
|
foreach ($this->headers as $name => $value) {
|
|
$headers[] = $name . ': ' . $this->encodeHeader($value, $this->build_params['head_charset']);
|
|
}
|
|
|
|
// Encode To:
|
|
$headers[] = 'To: ' . $this->encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
|
|
|
|
// Get return path arg for sendmail command if necessary
|
|
$returnPath = '';
|
|
if (!empty($this->return_path)) {
|
|
$returnPath = '-f' . $this->return_path;
|
|
}
|
|
|
|
$pipe = popen($this->sendmail_path . " " . $returnPath, 'w');
|
|
$bytes = fputs($pipe, implode(RMAIL_CRLF, $headers) . RMAIL_CRLF . RMAIL_CRLF . $this->output);
|
|
$r = pclose($pipe);
|
|
|
|
return $r;
|
|
break;
|
|
|
|
case 'smtp':
|
|
require_once(dirname(__FILE__) . '/smtp.php');
|
|
require_once(dirname(__FILE__) . '/RFC822.php');
|
|
$smtp = &smtp::connect($this->smtp_params);
|
|
|
|
// Parse recipients argument for internet addresses
|
|
foreach ($recipients as $recipient) {
|
|
$addresses = Mail_RFC822::parseAddressList($recipient, $this->smtp_params['helo'], null, false);
|
|
foreach ($addresses as $address) {
|
|
$smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
|
|
}
|
|
}
|
|
unset($addresses); // These are reused
|
|
unset($address); // These are reused
|
|
|
|
// Get flat representation of headers, parsing
|
|
// Cc and Bcc as we go
|
|
foreach ($this->headers as $name => $value) {
|
|
if ($name == 'Cc' OR $name == 'Bcc') {
|
|
$addresses = Mail_RFC822::parseAddressList($value, $this->smtp_params['helo'], null, false);
|
|
foreach ($addresses as $address) {
|
|
$smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
|
|
}
|
|
}
|
|
if ($name == 'Bcc') {
|
|
continue;
|
|
}
|
|
$headers[] = $name . ': ' . $this->encodeHeader($value, $this->build_params['head_charset']);
|
|
}
|
|
// Add To header based on $recipients argument
|
|
$headers[] = 'To: ' . $this->encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
|
|
|
|
// Add headers to send_params
|
|
$send_params['headers'] = $headers;
|
|
$send_params['recipients'] = array_values(array_unique($smtp_recipients));
|
|
$send_params['body'] = $this->output;
|
|
|
|
// Setup return path
|
|
if (isset($this->return_path)) {
|
|
$send_params['from'] = $this->return_path;
|
|
} elseif (!empty($this->headers['From'])) {
|
|
$from = Mail_RFC822::parseAddressList($this->headers['From']);
|
|
$send_params['from'] = sprintf('%s@%s', $from[0]->mailbox, $from[0]->host);
|
|
} else {
|
|
$send_params['from'] = 'postmaster@' . $this->smtp_params['helo'];
|
|
}
|
|
|
|
// Send it
|
|
if (!$smtp->send($send_params)) {
|
|
$this->errors = $smtp->getErrors();
|
|
return false;
|
|
}
|
|
return true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Use this method to return the email
|
|
* in message/rfc822 format. Useful for
|
|
* adding an email to another email as
|
|
* an attachment.
|
|
*
|
|
* @param array $recipients Array of recipients
|
|
* @param string $type Method to be used to send the mail.
|
|
* Used to determine the line ending type.
|
|
*/
|
|
public function getRFC822($recipients, $type = 'mail')
|
|
{
|
|
// Make up the date header as according to RFC822
|
|
$this->setHeader('Date', date('D, d M y H:i:s O'));
|
|
|
|
if (!defined('RMAIL_CRLF')) {
|
|
$this->setCRLF($type == 'mail' ? "\n" : "\r\n");
|
|
}
|
|
|
|
$this->build();
|
|
|
|
// Return path ?
|
|
if (isset($this->return_path)) {
|
|
$headers[] = 'Return-Path: ' . $this->return_path;
|
|
}
|
|
|
|
// Get flat representation of headers
|
|
foreach ($this->headers as $name => $value) {
|
|
$headers[] = $name . ': ' . $value;
|
|
}
|
|
$headers[] = 'To: ' . implode(', ', $recipients);
|
|
|
|
return implode(RMAIL_CRLF, $headers) . RMAIL_CRLF . RMAIL_CRLF . $this->output;
|
|
}
|
|
} // End of class.
|
|
|
|
|
|
/**
|
|
* Attachment classes
|
|
*/
|
|
class attachment
|
|
{
|
|
/**
|
|
* Data of attachment
|
|
* @var string
|
|
*/
|
|
public $data;
|
|
|
|
/**
|
|
* Name of attachment (filename)
|
|
* @var string
|
|
*/
|
|
public $name;
|
|
|
|
/**
|
|
* Content type of attachment
|
|
* @var string
|
|
*/
|
|
public $contentType;
|
|
|
|
/**
|
|
* Encoding type of attachment
|
|
* @var object
|
|
*/
|
|
public $encoding;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param string $data File data
|
|
* @param string $name Name of attachment (filename)
|
|
* @param string $contentType Content type of attachment
|
|
* @param object $encoding Encoding type to use
|
|
*/
|
|
public function __construct($data, $name, $contentType, iEncoding $encoding)
|
|
{
|
|
$this->data = $data;
|
|
$this->name = $name;
|
|
$this->contentType = $contentType;
|
|
$this->encoding = $encoding;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* File based attachment class
|
|
*/
|
|
class fileAttachment extends attachment
|
|
{
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param string $filename Name of file
|
|
* @param string $contentType Content type of file
|
|
* @param string $encoding What encoding to use
|
|
*/
|
|
public function __construct($filename, $contentType = 'application/octet-stream', $encoding = null)
|
|
{
|
|
$encoding = is_null($encoding) ? new Base64Encoding() : $encoding;
|
|
|
|
parent::__construct(file_get_contents($filename), basename($filename), $contentType, $encoding);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Attachment class to handle attachments which are contained
|
|
* in a variable.
|
|
*/
|
|
class stringAttachment extends attachment
|
|
{
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param string $data File data
|
|
* @param string $name Name of attachment (filename)
|
|
* @param string $contentType Content type of file
|
|
* @param string $encoding What encoding to use
|
|
*/
|
|
public function __construct($data, $name = '', $contentType = 'application/octet-stream', $encoding = null)
|
|
{
|
|
$encoding = is_null($encoding) ? new Base64Encoding() : $encoding;
|
|
|
|
parent::__construct($data, $name, $contentType, $encoding);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* File based embedded image class
|
|
*/
|
|
class fileEmbeddedImage extends fileAttachment
|
|
{
|
|
}
|
|
|
|
|
|
/**
|
|
* String based embedded image class
|
|
*/
|
|
class stringEmbeddedImage extends stringAttachment
|
|
{
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
/**
|
|
* Encoding interface
|
|
*/
|
|
interface iEncoding
|
|
{
|
|
public function encode($input);
|
|
public function getType();
|
|
}
|
|
|
|
|
|
/**
|
|
* Base64 Encoding class
|
|
*/
|
|
class Base64Encoding implements iEncoding
|
|
{
|
|
/*
|
|
* Function to encode data using
|
|
* base64 encoding.
|
|
*
|
|
* @param string $input Data to encode
|
|
*/
|
|
public function encode($input)
|
|
{
|
|
return rtrim(chunk_split(base64_encode($input), 76, defined('MAIL_MIME_PART_CRLF') ? MAIL_MIME_PART_CRLF : "\r\n"));
|
|
}
|
|
|
|
/**
|
|
* Returns type
|
|
*/
|
|
public function getType()
|
|
{
|
|
return 'base64';
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Quoted Printable Encoding class
|
|
*/
|
|
class QPrintEncoding implements iEncoding
|
|
{
|
|
/*
|
|
* Function to encode data using
|
|
* quoted-printable encoding.
|
|
*
|
|
* @param string $input Data to encode
|
|
*/
|
|
public function encode($input)
|
|
{
|
|
// Replace non printables
|
|
$input = preg_replace('/([^\x20\x21-\x3C\x3E-\x7E\x0A\x0D])/e', 'sprintf("=%02X", ord("\1"))', $input);
|
|
$inputLen = strlen($input);
|
|
$outLines = array();
|
|
$output = '';
|
|
|
|
$lines = preg_split('/\r?\n/', $input);
|
|
|
|
// Walk through each line
|
|
for ($i=0; $i<count($lines); $i++) {
|
|
// Is line too long ?
|
|
if (strlen($lines[$i]) > $lineMax) {
|
|
$outLines[] = substr($lines[$i], 0, $lineMax - 1) . "="; // \r\n Gets added when lines are imploded
|
|
$lines[$i] = substr($lines[$i], $lineMax - 1);
|
|
$i--; // Ensure this line gets redone as we just changed it
|
|
} else {
|
|
$outLines[] = $lines[$i];
|
|
}
|
|
}
|
|
|
|
// Convert trailing whitespace
|
|
$output = preg_replace('/(\x20+)$/me', 'str_replace(" ", "=20", "\1")', $outLines);
|
|
|
|
return implode("\r\n", $output);
|
|
}
|
|
|
|
/**
|
|
* Returns type
|
|
*/
|
|
public function getType()
|
|
{
|
|
return 'quoted-printable';
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* 7Bit Encoding class
|
|
*/
|
|
class SevenBitEncoding implements iEncoding
|
|
{
|
|
/*
|
|
* Function to "encode" data using
|
|
* 7bit encoding.
|
|
*
|
|
* @param string $input Data to encode
|
|
*/
|
|
public function encode($input)
|
|
{
|
|
return $input;
|
|
}
|
|
|
|
/**
|
|
* Returns type
|
|
*/
|
|
public function getType()
|
|
{
|
|
return '7bit';
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* 8Bit Encoding class
|
|
*/
|
|
class EightBitEncoding implements iEncoding
|
|
{
|
|
/*
|
|
* Function to "encode" data using
|
|
* 8bit encoding.
|
|
*
|
|
* @param string $input Data to encode
|
|
*/
|
|
public function encode($input)
|
|
{
|
|
return $input;
|
|
}
|
|
|
|
/**
|
|
* Returns type
|
|
*/
|
|
public function getType()
|
|
{
|
|
return '8bit';
|
|
}
|
|
}
|
|
?>
|