Swift Wrapper Class
Posted: Thu Jun 04, 2009 1:39 pm
Below is my new Swift wrapper class for Version 4. I would love any critique. This class can be extended for specific uses, but in its simplest form lets you send messages quite easily. We use it to send single messages, and batch messages as well.
Here are some notes:
Here are some notes:
- There are two main functions: SendMessage, and SendMail. SendMail is quite similar to the PHP mail function. SendMessage is used if you manually set all the parameters
- Email format is checked. I allow entry of emails in array format, and comma delimited lists (email1,email2... or name:email..., or name<email>...).
- I compress HTML messages, removing extra space.
- This only uses SMTP or Sendmail options. If you use SMTP, you have to set the parameters after you instantiate the class with the SetSmtp() function
- This will take html only content and then try to create text content by stripping the tags. This needs more work.
- There are two function to for attachments: SetAttachedFiles, and SetAttachedDynamicFiles
- It tries to get a return path from a list or array, if you do not set it as a single email
- GetMessageDetails() is for debugging purposes.
Code: Select all
class MailSwift
{
protected $Subject = '';
protected $Body_Text = '';
protected $Body_Html = '';
protected $Body_Html_Raw = '';
protected $From = '';
protected $To = '';
protected $Cc = '';
protected $Bcc = '';
protected $Attachment = '';
protected $Return_Path = '';
protected $Transport = '';
protected $Mailer = '';
protected $Smtp = array();
protected $Attached_Files = array();
protected $Attached_Dynamic_Files= array();
protected $Text_Headers = array();
protected $Message;
public $Error = '';
public $Error_Extended = '';
// add translations as necessary for this text
public $Text_Messages = array (
'ATTACHMENT_NOT_FOUND' => 'Attachment not found',
'BAD_EMAIL_RETURN_PATH' => 'Bad Email Return Path',
'BAD_EMAIL' => 'Bad Email',
'MESSAGE_FAILED' => 'Message Failed',
'TRANSPORT_FAILED' => 'Transport Failed to Initialize'
);
// function to check if email has valid form
public function CheckEmail($email)
{
$last_dot = strrpos($email, '.');
$at_sign = strrpos($email, '@');
$at_groups = explode('@', $email);
$length = strlen($email);
$bad_email = (
(count($at_groups) != 2) || ($last_dot===false) || ($at_sign===false) || ($length===false)||
($last_dot - $at_sign < 2) || ($length - $last_dot < 3) || ($at_sign == 0)
);
return !$bad_email;
}
// function to add to error string
protected function AddError($error)
{
$this->Error .= "$error<br />\n";
}
// function to set SMTP parameters, could be called in construct of child classes
public function SetSmtp($smtp, $username, $password, $port=25)
{
$this->Smtp = array(
'smtp' => $smtp,
'username' => $username,
'password' => $password,
'port' => $port
);
}
// function to set subject
public function SetSubject($subject)
{
// remove HTML special characters from subject
$subject = htmlspecialchars_decode($subject);
$this->Subject = $subject;
}
// function to remove extra spaces in HTML code
public function CompressHtml($html)
{
$E = chr(27);
//trim and replace line breaks with escape character
$RESULT = mb_ereg_replace("[\r\n|\n]+", $E, trim($html));
//compress spaces
$RESULT = mb_ereg_replace("[[:space:]]+", ' ', $RESULT);
//remove space around line breaks
$RESULT = mb_ereg_replace("{$E}[[:space:]]+", $E, $RESULT);
$RESULT = mb_ereg_replace("[[:space:]]+$E", $E, $RESULT);
//restore line breaks, removing multiples
$RESULT = mb_ereg_replace("$E+", "\n", $RESULT);
return $RESULT;
}
// function to set html body
public function SetBodyHtml($text)
{
// raw is uncompressed
$this->Body_Html_Raw = $text;
$this->Body_Html = $this->CompressHtml($text);
}
// function to set text body
public function SetBodyText($text)
{
$this->Body_Text = $text;
}
// function to set text body from HTML
public function SetBodyTextFromHtml()
{
// strip tags is only a start, other transforms are needed, such as links
$text = strip_tags($this->Body_Html_Raw);
$this->Body_Text = $text;
}
// function to check to see if a file attachment exists
protected function CheckAttachmentExists($attachment)
{
if (file_exists($attachment)) {
return true;
} else {
$this->AddError($this->Text_Messages['ATTACHMENT_NOT_FOUND'] . " ($attachment)");
return false;
}
}
// function to set attachment files
public function SetAttachedFiles($attachments)
{
// assumes an array of file links or a single attachment
if ($attachments) {
if (is_array($attachments)) {
foreach ($attachments as $attachment) {
if ($this->CheckAttachmentExists($attachment)) {
$this->Attached_Files[] = $attachment;
}
}
} else {
if ($this->CheckAttachmentExists($attachments)) {
$this->Attached_Files[] = $attachments;
}
}
} else {
$this->Attached_Files = array();
}
}
// function to attach dynamic content
public function SetAttachedDynamicFiles($attachments)
{
// requires an array of rows: ('data', 'filename', 'type')
if ($attachments) {
if (is_array($attachments[0])) {
$this->Attached_Dynamic_Files = $attachments;
} else {
// must be a single item
$this->Attached_Dynamic_Files[] = $attachments;
}
} else {
$this->Attached_Dynamic_Files = array();
}
}
// function to set custom headers
public function SetTextHeaders($headers)
{
// assumes an associative array of header-name => value
if ($headers and is_array($headers)) {
foreach ($headers as $name => $value) {
$this->Text_Headers[$name] = $value;
}
} else {
$this->Text_Headers = array();
}
}
// function to get emails to set, can take arrays or comma delimited lists
protected function GetEmails($list)
{
if ($list) {
if (is_array($list)) {
return $list;
} else {
//comma delimited list in: name:email,... || email1,email2..., || name <email>,. . .
$emails = explode(',', $list);
$RESULT = array();
foreach ($emails as $email) {
$email = trim($email);
if (strpos($email, '<') !== false) {
// --- get name <email> format ---
$email_part = trim(preg_replace('/.+<|>/', '', $email));
$name = trim(preg_replace('/<.+/', '', $email));
$email = $email_part;
} else {
$parts = explode(':', $email);
// --- get name:email format ---
if (count($parts) > 1) {
$name = trim($parts[0]);
$email = trim($parts[1]);
} else {
$name = '';
}
}
if ( $this->CheckEmail($email) ) {
if ($name) {
$RESULT[$email] = $name;
} else {
$RESULT[] = $email;
}
} else {
$this->AddError($this->Text_Messages['BAD_EMAIL'] . ": $email");
}
}
return $RESULT;
}
} else {
return '';
}
}
// function to set TO
public function SetTo($to)
{
$this->To = $this->GetEmails($to);
}
// function to set FROM
public function SetFrom($from)
{
$this->From = $this->GetEmails($from);
}
// function to set CC
public function SetCc($cc)
{
$this->Cc = $this->GetEmails($cc);
}
// function to set BCC
public function SetBcc($bcc)
{
$this->Bcc = $this->GetEmails($bcc);
}
// function to set the return path
public function SetReturnPath($return_path)
{
if (is_array($return_path)) {
foreach ($return_path as $key => $value) {
if ($this->CheckEmail($key)) {
$this->Return_Path = $key;
} elseif ($this->CheckEmail($value)) {
$this->Return_Path = $value;
} else {
$this->Return_Path = '';
$this->AddError($this->Text_Messages['BAD_EMAIL_RETURN_PATH']);
}
return;
}
} elseif ($this->CheckEmail($return_path)) {
$this->Return_Path = $return_path;
} else {
$this->Return_Path = '';
if (!empty($return_path)) {
$this->AddError($this->Text_Messages['BAD_EMAIL_RETURN_PATH']);
}
}
}
// function to instantiate the transport and mailer, if not already set, check for SMTP, otherwise uses sendmail
public function SetTransportAndMailer()
{
if (!$this->Transport) {
try {
if (!empty($this->Smtp)) {
$this->Transport = Swift_SmtpTransport::newInstance($this->Smtp['smtp'], $this->Smtp['port'])
->setUsername($this->Smtp['username'])
->setPassword($this->Smtp['password']);
} else {
$this->Transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');
}
return $this->Mailer = Swift_Mailer::newInstance($this->Transport);
} catch(Exception $e) {
$this->AddError($this->Text_Messages['TRANSPORT_FAILED']); // message to public
$this->Error_Extended = $e->getMessage(); // message for admin
return false;
}
}
}
// function to output email details for diagnosis, used in function below
protected function GetEmailDetails($email, $title='')
{
$RESULT = '';
if (is_array($email)) {
foreach ($email as $key => $value) {
$RESULT .= "<dt>$title:</dt><dd>$key => $value</dd>\n";
}
} else {
$RESULT .= "<dt>$title:</dt><dd>$email</dd>\n";
}
return $RESULT;
}
// function to output message details for diagnosis, using a definition list
public function GetMessageDetails()
{
$RESULT = '<dl>';
$RESULT .= $this->GetEmailDetails($this->From, 'From');
$RESULT .= $this->GetEmailDetails($this->To, 'To');
if ($this->Cc) {
$RESULT .= $this->GetEmailDetails($this->Cc, 'Cc');
}
if ($this->Bcc) {
$RESULT .= $this->GetEmailDetails($this->Bcc, 'Bcc');
}
if ($this->Return_Path) {
$RESULT .= $this->GetEmailDetails($this->Return_Path, 'Return Path');
}
if ($this->Text_Headers) {
$RESULT .= "<dt>Custom Headers:</dt><dd>\n<ul>\n";
foreach ($this->Text_Headers as $name => $value) {
$RESULT .= "<li>$name: $value</li>\n";
}
$RESULT .= "</ul>\n</dd>";
}
$RESULT .= "<dt>Subject:</dt><dd>{$this->Subject}</dd>\n";
$RESULT .= "<dt>HTML:</dt><dd>{$this->Body_Html}</dd>\n";
$RESULT .= "<dt>Text:</dt><dd><pre>{$this->Body_Text}</pre></dd>\n";
if ($this->Attached_Files) {
$RESULT .= "<dt>Attachments:</dt><dd>\n<ul>\n";
foreach ($this->Attached_Files as $attachment) {
$RESULT .= "<li>$attachment</li>\n";
}
$RESULT .= "</ul>\n</dd>";
}
if ($this->Attached_Dynamic_Files) {
$RESULT .= "<dt>Dynamic Attachments:</dt><dd>\n<ul>\n";
foreach ($this->Attached_Dynamic_Files as $attachment) {
//$data = $attachment[0];
$filename = $attachment[1];
$type = $attachment[2];
$RESULT .= "<li>$filename, $type</li>\n";
}
$RESULT .= "</ul>\n</dd>";
}
return $RESULT;
}
// function to send a message pulling from the class variables
public function SendMessage()
{
try {
$message = Swift_Message::newInstance()
->setSubject($this->Subject)
->setFrom($this->From)
->setTo($this->To);
if(!$this->Return_Path) {
$this->SetReturnPath($this->From);
}
$message->setReturnPath($this->Return_Path);
if ($this->Cc) {
$message->setCc($this->Cc);
}
if ($this->Bcc) {
$message->setBcc($this->Bcc);
}
if ($this->Text_Headers) {
foreach ($this->Text_Headers as $name => $value) {
$message->getHeaders()->addTextHeader($name, $value);
}
}
if ($this->Attached_Files) {
foreach ($this->Attached_Files as $attachment) {
$message->attach(Swift_Attachment::fromPath($attachment));
}
}
if($this->Attached_Dynamic_Files) {
foreach ($this->Attached_Dynamic_Files as $attachment) {
$data = $attachment[0];
$filename = $attachment[1];
$type = $attachment[2];
$message->attach(Swift_Attachment::newInstance($data, $filename, $type));
}
}
if ($this->Body_Html) {
$body_html = Swift_MimePart::newInstance( $this->Body_Html, 'text/html' );
$message->attach($body_html, 'text/html');
}
if (empty($this->Body_Text) and $this->Body_Html) {
$this->SetBodyTextFromHtml();
}
$body_text = Swift_MimePart::newInstance( $this->Body_Text, 'text/plain' );
$message->addPart($this->Body_Text, 'text/plain');
$this->SetTransportAndMailer();
return $this->Mailer->send($message);
} catch (Exception $e) {
$this->AddError($this->Text_Messages['MESSAGE_FAILED']); // message to public
$this->Error_Extended = $e->getMessage(); // message for admin
return false;
}
}
// general function to send a messages, sets the basics, will need to set attachments, special headers, and SMTP before this function is called
public function SendMail($from, $to, $subject, $message_html='', $message_text='', $bounce='', $cc='', $bcc='')
{
$error_point = 0;
try {
$this->Error = '';
$this->Error_Extended = '';
$this->SetFrom($from);
$this->SetTo($to);
$this->SetCc($cc);
$this->SetBcc($bcc);
$this->SetSubject($subject);
$this->SetBodyHtml($message_html);
$this->SetBodyText($message_text);
$this->SetReturnPath($bounce);
$error_point = 1;
return $this->SendMessage();
} catch (Exception $e) {
if ($error_point == 0) {
// this means error occurred before SendMessage(), so need to add errors, otherwise errors already added
$this->AddError($this->Text_Messages['MESSAGE_FAILED']); // message to public
$this->Error_Extended = $e->getMessage(); // message for admin
}
return false;
}
}
}