v7‰PNG
IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ±üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0AºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT
Template.php 0000644 00000022601 15210162050 0007021 0 ustar 00 setFlags(self::ARRAY_AS_PROPS);
$this->setArray(array(
'site_title' => Am_Di::getInstance()->config->get('site_title'),
'root_url' => ROOT_URL,
'admin_email' => Am_Di::getInstance()->config->get('admin_email'),
));
}
public function __call($name, $arguments)
{
if (strpos($name, 'set')===0) {
$var = lcfirst(substr($name, 3));
$this[$var] = $arguments[0];
return $this;
}
trigger_error("Method [$name] does not exists in " . __CLASS__, E_USER_ERROR);
}
public function setArray(array $vars)
{
foreach ($vars as $k => $v)
$this->$k = $v;
return $this;
}
function setBcc($bcc)
{
$this->bcc = $bcc;
}
function setTemplate($format, $subject, $bodyText, $bodyHtml, $attachments, $id, $name, $layout = null)
{
// switch bodyText/bodyHtml based on format
if (($format == 'text') && empty($bodyText)) {
$bodyText = $bodyHtml;
$bodyHtml = null;
} elseif (($format == 'html') && empty($bodyHtml)) {
$bodyHtml = $bodyText;
$bodyText = null;
}
$this->template = array(
'format' => $format,
'subject' => $subject,
'bodyText' => $bodyText,
'bodyHtml' => $bodyHtml,
'attachments' => $attachments,
'id' => $id,
'name' => $name,
'layout' => $layout
);
}
/** @return Am_Mail */
function getMail()
{
if (!$this->mail)
$this->mail = Am_Di::getInstance()->mail;;
return $this->mail;
}
public function addTo($email, $name)
{
$this->getMail()->addTo($email, $name);
}
function parse()
{
Am_Di::getInstance()->hook->call(Am_Event::MAIL_TEMPLATE_BEFORE_PARSE, array(
'template' => $this,
'body' => !empty($this->template['bodyText']) ? $this->template['bodyText'] : $this->template['bodyHtml'],
'subject' => $this->template['subject'],
'mail' => $this->getMail()
));
if($this->getMailPeriodic() == Am_Mail::REGULAR) $this->getMail()->addUnsubscribeLink(Am_Mail::LINK_USER);
$this->subject = $this->_parse($this->template['subject']);
$layout = $this->template['layout'];
if ($_text = $this->template['bodyText']) {
$this->text = $this->_parse($_text, $layout);
}
if ($_html = $this->template['bodyHtml']) {
$html = $this->_parse($_html, $layout);
$this->text = strip_tags($this->_parse($_html));
$this->html = strpos($html, '
{$this->subject}$html" :
$html;
}
$this->parseAttachments();
}
protected function parseAttachments()
{
if(in_array($this->template['name'],array(EmailTemplate::AUTORESPONDER,
EmailTemplate::EXPIRE, EmailTemplate::PRODUCTWELCOME, EmailTemplate::PAYMENT)))
$upload = new Am_Upload(Am_Di::getInstance(), EmailTemplate::ATTACHMENT_AUTORESPONDER_EXPIRE_FILE_PREFIX);
elseif(in_array($this->template['name'],array(EmailTemplate::PENDING_TO_ADMIN, EmailTemplate::PENDING_TO_USER)))
$upload = new Am_Upload(Am_Di::getInstance(), EmailTemplate::ATTACHMENT_PENDING_FILE_PREFIX);
else
$upload = new Am_Upload(Am_Di::getInstance(), EmailTemplate::ATTACHMENT_FILE_PREFIX);
$upload->unserialize($this->template['attachments']);
foreach ($upload->getUploads() as $file)
{
$f = @fopen($file->getFullPath(), 'r');
if (!$f) {
trigger_error("Could not open attachment [" . $file->getName() . "] for EmailTemplate#{$this->email_template_id}",
E_USER_WARNING);
continue;
}
$this->getMail()->createAttachment($f, $file->getType(),
Zend_Mime::DISPOSITION_ATTACHMENT, Zend_Mime::ENCODING_BASE64, $file->getName());
}
}
protected function _parse($text, $layout = null)
{
$tpl = new Am_SimpleTemplate();
$tpl->assignStdVars();
$tpl->assign($this->getArrayCopy());
$tpl->assign(get_object_vars($this));
$text = $tpl->render($text);
if ($layout) {
$tpl->assign('content', $text);
$text = $tpl->render($layout);
}
return $text;
}
function send($recepient, $transport = null)
{
try {
$this->_send($recepient, $transport);
} catch (Exception $e) {
// Catch all exceptions here. If there is an issue with template,
// other parts of the script should not be affected.
Am_Di::getInstance()->errorLogTable->log($e);
trigger_error("Could not send message - error happened: " . $e->getMessage(), E_USER_WARNING);
}
}
protected function _send($recepient, $transport = null)
{
if (!$this->template)
throw new Am_Exception_InternalError("Template was not set in " . __METHOD__);
$this->getMail()->clearRecipients();
if ($this->bcc) {
$this->getMail()->addBcc($this->bcc);
}
if ($recepient instanceof User) {
$this->getMail()->addTo($email = $recepient->email, $recepient->getName());
} elseif ($recepient instanceof Admin) {
$this->getMail()->addTo($email = $recepient->email, $recepient->getName());
} elseif ($recepient===self::TO_ADMIN) {
$name = Am_Di::getInstance()->config->get('site_title') . ' Admin';
if($this->admins)
{
if(in_array(-1, $this->admins))
$this->addTo(Am_Di::getInstance()->config->get('admin_email'), Am_Di::getInstance()->config->get('site_title') . ' Admin');
foreach (Am_Di::getInstance()->adminTable->loadIds($this->admins) as $admin)
$this->getMail()->addTo($admin->email, $admin->getName());
if ($copyAdmin = Am_Di::getInstance()->config->get('copy_admin_email'))
foreach (preg_split("/[,;]/", $copyAdmin) as $copy)
if ($copy) $this->getMail()->addBcc($copy);
} else {
$this->getMail()->toAdmin();
}
} else {
$this->getMail()->addTo($email = $recepient);
}
if (!$this->is_parsed) {
$this->is_parsed = true;
$this->parse();
$this->getMail()->setSubject($this->subject);
}
$this->getMail()->setBodyText($this->text);
if ($this->html) {
$this->getMail()->setBodyHtml($this->html);
}
$this->getMail()->setPeriodic($this->getMailPeriodic());
$this->getMail()->send($transport);
}
/**
* Shortcut to email subscribed admins
*/
function sendAdmin()
{
$this->send(self::TO_ADMIN);
}
function getMailPeriodic()
{
return $this->_mailPeriodic;
}
function setMailPeriodic($periodic)
{
$this->_mailPeriodic = $periodic;
}
/**
* @return Am_Mail_Template|null null if no template found
*/
static function load($id, $lang = null, $throwException = false)
{
$di = Am_Di::getInstance();
if(is_null($lang)) $lang = $di->locale->getLanguage();
list($lang,) = explode('_', $lang);
$et = $di->emailTemplateTable->findFirstExact($id, $lang);
if ($et)
{
return self::createFromEmailTemplate($et);
} elseif ($throwException)
throw new Am_Exception_Configuration("No e-mail template found for [$id,$lang]");
}
/** @return Am_Mail_Template */
static function createFromEmailTemplate(EmailTemplate $et)
{
$t = new self;
$t->setTemplate(
$et->format,
$et->subject,
$et->plain_txt,
$et->txt,
$et->attachments,
$et->email_template_id . '-' . $et->name . '-' . $et->lang,
$et->name,
$et->getLayout()
);
$t->admins = array_filter(explode(',', $et->recipient_admins));
$rec = Am_Mail_TemplateTypes::getInstance()->find($et->name);
if ($rec)
$t->setMailPeriodic($rec['mailPeriodic']);
$bcc = $et->bcc ? array_map('trim', explode (',', $et->bcc)) : array();
$t->setBcc($bcc);
if ($et->reply_to && ($admin = $et->getDi()->adminTable->load($et->reply_to, false))) {
$t->getMail()->setReplyTo($admin->email, $admin->getName());
}
return $t;
}
function getConfig()
{
return $this->template;
}
}
TemplateTypes.php 0000644 00000033414 15210162050 0010052 0 ustar 00 offsetExists($id) ? $this->offsetGet($id) : null;
}
/** @return Am_Mail_TemplateTypes */
static function createInstance()
{
$o = new self;
$o->tagSets = array(
'admin' => array(
'%admin.name_f%' => ___('Admin First Name'),
'%admin.name_l%' => ___('Admin Last Name'),
'%admin.login%' => ___('Admin Username'),
'%admin.email%' => ___('Admin E-Mail')
),
'user' => array(
'%user.name_f%' => ___('User First Name'),
'%user.name_l%' => ___('User Last Name'),
'%user.login%' => ___('Username'),
'%user.email%' => ___('E-Mail'),
'%user.user_id%' => ___('User Internal ID#'),
'%user.street%' => ___('User Street'),
'%user.street2%' => ___('User Street (Second Line)'),
'%user.city%' => ___('User City'),
'%user.state%' => ___('User State'),
'%user.zip%' => ___('User ZIP'),
'%user.country%' => ___('User Country'),
'%user.phone%' => ___('User Phone'),
'%user.status%' => ___('User Status (0-pending, 1-active, 2-expired)')
),
'invoice' => array(
'%invoice.invoice_id%' => ___('Invoice Internal ID#'),
'%invoice.public_id%' => ___('Invoice Public ID#'),
'%invoice.first_total%' => ___('Invoice First Total'),
'%invoice.second_total%' => ___('Invoice Second Total'),
),
'payment' => array(
'%payment.amount%' => ___('Payment Amount'),
'%payment.currency%' => ___('Payment Currency'),
'%payment.receipt_id%' => ___('Payment Receipt Id'),
)
);
$table = Am_Di::getInstance()->userTable;
$fields = $table->customFields()->getAll();
uksort($fields, array($table, 'sortCustomFields'));
foreach ($fields as $field) {
if (@$field->sql && @$field->from_config) {
$o->tagSets['user']['%user.' . $field->name . '%'] = ___('User %s', $field->title);
}
}
$o->tagSets['user']['%user.unsubscribe_link%'] = ___('User Unsubscribe Link');
$event = new Am_Event(Am_Event::EMAIL_TEMPLATE_TAG_SETS);
$event->setReturn($o->tagSets);
Am_Di::getInstance()->hook->call($event);
$o->tagSets = $event->getReturn();
$event = new Am_Event(Am_Event::SETUP_EMAIL_TEMPLATE_TYPES);
Am_Di::getInstance()->hook->call($event);
$res = $event->getReturn();
$o->exchangeArray(array_merge(array(
'bruteforce_notify' => array(
'id' => 'bruteforce_notify',
'title' => ___('Bruteforce Notification'),
'mailPeriodic' => Am_Mail::ADMIN_REQUESTED,
'isAdmin' => true,
'vars' => array('ip' => ___('IP Address'), 'login' => ___('Last Used Login'))
),
'profile_changed' => array(
'id' => 'profile_changed',
'title' => ___('Profile Changed'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'isAdmin' => true,
'vars' => array('user', 'changes' => ___('Changes in User Profile'))
),
'registration_mail' => array(
'id' => 'registration_mail',
'title' => 'Registration E-Mail',
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user', 'password' => ___('Plain-Text Password')),
),
'registration_mail_admin' => array(
'id' => 'registration_mail_admin',
'title' => 'Registration E-Mail to Admin',
'mailPeriodic' => Am_Mail::ADMIN_REQUESTED,
'isAdmin' => true,
'vars' => array('user', 'password' => ___('Plain-Text Password')),
),
'changepass_mail' => array(
'id' => 'changepass_mail',
'title' => ___('Password Change E-Mail'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user', 'password' => 'Plain-Text Password'),
),
'send_signup_mail' => array(
'id' => 'send_signup_mail',
'title' => ___('Send Signup Mail'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user'),
),
'mail_payment_admin' => array(
'id' => 'mail_payment_admin',
'title' => ___('Mail Payment Admin'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user'),
),
'send_payment_mail' => array(
'id' => 'send_payment_mail',
'title' => ___('Send Payment Mail'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user','invoice','product_title'=> ___('Product(s) Title')),
),
'send_payment_admin' => array(
'id' => 'send_payment_admin',
'title' => ___('Send Payment Admin'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'isAdmin' => true,
'vars' => array('user','invoice','product_title'=> ___('Product(s) Title')),
),
'manually_approve' => array(
'id' => 'manually_approve',
'title' => ___('Manually Approve'),
'mailPeriodic' => Am_Mail::ADMIN_REQUESTED,
'vars' => array('user'),
),
'manually_approve_admin' => array(
'id' => 'manually_approve_admin',
'title' => ___('Manually Approve Admin'),
'mailPeriodic' => Am_Mail::ADMIN_REQUESTED,
'isAdmin' => true,
'vars' => array('user'),
),
'invoice_approval_wait_user' => array(
'id' => 'invoice_approval_wait_user',
'title' => ___('Manually Approve Invoice'),
'mailPeriodic' => Am_Mail::ADMIN_REQUESTED,
'vars' => array('user','invoice'),
),
'invoice_pay_link' => array(
'id' => 'invoice_pay_link',
'title' => 'Payment Link for Invoice',
'mailPeriodic' => Am_Mail::ADMIN_REQUESTED,
'vars' => array(
'invoice_text' => ___('Invoice Text'),
'product_title' => ___('Product Title'),
'url' => ___('Payment Link'),
'message' => ___('Your Message'),
'user', 'invoice'),
),
'invoice_approval_wait_admin' => array(
'id' => 'invoice_approval_wait_admin',
'title' => ___('Manually Approve Invoice Admin'),
'mailPeriodic' => Am_Mail::ADMIN_REQUESTED,
'isAdmin' => true,
'vars' => array('user', 'invoice'),
),
'invoice_approved_user' => array(
'id' => 'invoice_approved_user',
'title' => ___('Invoice Approved'),
'mailPeriodic' => Am_Mail::ADMIN_REQUESTED,
'vars' => array('user', 'invoice'),
),
'card_expires' =>
array(
'id' => 'card_expires',
'title' => ___('Card Expires'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user'),
),
'send_security_code' =>
array(
'id' => 'send_security_code',
'title' => ___('Send Security Code'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user', 'code' => ___('Security Code'), 'url' => ___('Click Url')),
),
'verify_email_signup' =>
array(
'id' => 'verify_email_signup',
'title' => ___('Verify Email Signup'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user', 'url' => ___('Email Confirmation URL')),
),
'verify_email_profile' =>
array(
'id' => 'verify_email_profile',
'title' => ___('Verify Email Profile'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user', 'url' => ___('Email Confirmation URL')),
),
'autoresponder' =>
array(
'id' => 'autoresponder',
'title' => ___('Auto-Responder'),
'mailPeriodic' => Am_Mail::REGULAR,
'vars' => array('user', 'last_product_title' => ___('Product Title of the Latest Purchased Product')),
),
'productwelcome' =>
array(
'id' => 'productwelcome',
'title' => ___('Product Welcome E-mail'),
'mailPeriodic' => Am_Mail::REGULAR,
'vars' => array('user', 'invoice', 'payment', 'last_product_title' => ___('Product Title of the Latest Purchased Product')),
),
'payment' =>
array(
'id' => 'payment',
'title' => ___('Payment E-mail'),
'mailPeriodic' => Am_Mail::REGULAR,
'vars' => array('user', 'invoice', 'payment'),
),
'expire' =>
array(
'id' => 'expire',
'title' => ___('Expiration E-Mail'),
'mailPeriodic' => Am_Mail::REGULAR,
'vars' => array('user', 'expires' => ___('Expiration Date'), 'product_title' => ___('Expire Product Title')),
),
'pending_to_user' => array(
'id' => 'pending_to_user',
'title' => ___('Pending Invoice Notifications to User'),
'mailPeriodic' => Am_Mail::REGULAR,
'vars' => array('user', 'invoice', 'invoice_text' => ___('Invoice Text'), 'day'=> ___('Day of Notification Sending'), 'product_title'=> ___('Product(s) Title'), 'paylink' => ___('Payment Link to Complete Pending Invoice') ),
),
'pending_to_admin' => array(
'id' => 'pending_to_admin',
'title' => ___('Pending Invoice Notifications to Admin'),
'mailPeriodic' => Am_Mail::REGULAR,
'isAdmin' => true,
'vars' => array('user', 'invoice', 'invoice_text' => ___('Invoice Text'), 'day'=>___('Day of Notification Sending'), 'product_title'=>___('Product(s) Title')),
),
'max_ip_actions_admin' =>
array(
'id' => 'max_ip_actions_admin',
'title' => ___('Email admin regarding account sharing'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'isAdmin' => true,
'vars' => array('user'),
),
'max_ip_actions_user' =>
array(
'id' => 'max_ip_actions_user',
'title' => ___('Email user regarding account sharing'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user'),
),
'mail_cancel_member' => array(
'id' => 'mail_cancel_member',
'title' => ___('Send Cancel Notifications to User'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user', 'invoice'),
),
'mail_cancel_admin' => array(
'id' => 'mail_cancel_admin',
'title' => ___('Send Cancel Notifications to Admin'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'isAdmin' => true,
'vars' => array('user', 'invoice'),
),
'send_free_payment_admin' => array(
'id' => 'send_free_payment_admin',
'title' => ___('Send Free Payment Admin'),
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'isAdmin' => true,
'vars' => array('user','invoice'),
),
), $res));
return $o;
}
/**
* Return array - key => value of available options for template with given $id
* @param type $id
* @return array
*/
public function getTagsOptions($id)
{
$record = @$this[$id];
$ret = array(
'%site_title%' => ___('Site Title'),
'%root_url%' => ___('aMember Root URL'),
'%admin_email%' => ___('Admin E-Mail Address'),
);
if (!$record || empty($record['vars']))
return $ret;
foreach ($record['vars'] as $k => $v)
{
if (is_int($k)) // tag set
$ret = array_merge($ret, $this->tagSets[$v]);
else // single variable
$ret['%'.$k.'%'] = $v;
}
$event = new Am_Event(Am_Event::EMAIL_TEMPLATE_TAG_OPTIONS, array('templateName' => $id));
$event->setReturn($ret);
Am_Di::getInstance()->hook->call($event);
$ret = $event->getReturn();
return $ret;
}
public function add($id, $title, $mailPeriodic, array $vars)
{
$this[$id] = array('id' => $id, 'title' => $title, 'mailPeriodic' => $mailPeriodic, 'vars' => $vars);
}
}
Part.php 0000644 00000036571 15210162410 0006167 0 ustar 00 value) or string, if a content part is found it's used as toplines
* - noToplines ignore content found after headers in param 'headers'
* - content content as string
*
* @param array $params full message with or without headers
* @throws Zend_Mail_Exception
*/
public function __construct(array $params)
{
if (isset($params['handler'])) {
if (!$params['handler'] instanceof Zend_Mail_Storage_Abstract) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('handler is not a valid mail handler');
}
if (!isset($params['id'])) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('need a message id with a handler');
}
$this->_mail = $params['handler'];
$this->_messageNum = $params['id'];
}
if (isset($params['partclass'])) {
$this->setPartClass($params['partclass']);
}
if (isset($params['raw'])) {
Zend_Mime_Decode::splitMessage($params['raw'], $this->_headers, $this->_content);
} else if (isset($params['headers'])) {
if (is_array($params['headers'])) {
$this->_headers = $params['headers'];
} else {
if (!empty($params['noToplines'])) {
Zend_Mime_Decode::splitMessage($params['headers'], $this->_headers, $null);
} else {
Zend_Mime_Decode::splitMessage($params['headers'], $this->_headers, $this->_topLines);
}
}
if (isset($params['content'])) {
$this->_content = $params['content'];
}
}
}
/**
* Set name pf class used to encapsulate message parts
* @param string $class
* @return Zend_Mail_Part
*/
public function setPartClass($class)
{
if ( !class_exists($class) ) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception("Class '{$class}' does not exist");
}
if ( !is_subclass_of($class, 'Zend_Mail_Part_Interface') ) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception("Class '{$class}' must implement Zend_Mail_Part_Interface");
}
$this->_partClass = $class;
return $this;
}
/**
* Retrieve the class name used to encapsulate message parts
* @return string
*/
public function getPartClass()
{
if ( !$this->_partClass ) {
$this->_partClass = __CLASS__;
}
return $this->_partClass;
}
/**
* Check if part is a multipart message
*
* @return bool if part is multipart
*/
public function isMultipart()
{
try {
return stripos($this->contentType, 'multipart/') === 0;
} catch(Zend_Mail_Exception $e) {
return false;
}
}
/**
* Body of part
*
* If part is multipart the raw content of this part with all sub parts is returned
*
* @return string body
* @throws Zend_Mail_Exception
*/
public function getContent()
{
if ($this->_content !== null) {
return $this->_content;
}
if ($this->_mail) {
return $this->_mail->getRawContent($this->_messageNum);
} else {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('no content');
}
}
/**
* Return size of part
*
* Quite simple implemented currently (not decoding). Handle with care.
*
* @return int size
*/
public function getSize() {
return strlen($this->getContent());
}
/**
* Cache content and split in parts if multipart
*
* @return null
* @throws Zend_Mail_Exception
*/
protected function _cacheContent()
{
// caching content if we can't fetch parts
if ($this->_content === null && $this->_mail) {
$this->_content = $this->_mail->getRawContent($this->_messageNum);
}
if (!$this->isMultipart()) {
return;
}
// split content in parts
$boundary = $this->getHeaderField('content-type', 'boundary');
if (!$boundary) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('no boundary found in content type to split message');
}
$parts = Zend_Mime_Decode::splitMessageStruct($this->_content, $boundary);
if ($parts === null) {
return;
}
$partClass = $this->getPartClass();
$counter = 1;
foreach ($parts as $part) {
$this->_parts[$counter++] = new $partClass(array('headers' => $part['header'], 'content' => $part['body']));
}
}
/**
* Get part of multipart message
*
* @param int $num number of part starting with 1 for first part
* @return Zend_Mail_Part wanted part
* @throws Zend_Mail_Exception
*/
public function getPart($num)
{
if (isset($this->_parts[$num])) {
return $this->_parts[$num];
}
if (!$this->_mail && $this->_content === null) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('part not found');
}
if ($this->_mail && $this->_mail->hasFetchPart) {
// TODO: fetch part
// return
}
$this->_cacheContent();
if (!isset($this->_parts[$num])) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('part not found');
}
return $this->_parts[$num];
}
/**
* Count parts of a multipart part
*
* @return int number of sub-parts
*/
public function countParts()
{
if ($this->_countParts) {
return $this->_countParts;
}
$this->_countParts = count($this->_parts);
if ($this->_countParts) {
return $this->_countParts;
}
if ($this->_mail && $this->_mail->hasFetchPart) {
// TODO: fetch part
// return
}
$this->_cacheContent();
$this->_countParts = count($this->_parts);
return $this->_countParts;
}
/**
* Get all headers
*
* The returned headers are as saved internally. All names are lowercased. The value is a string or an array
* if a header with the same name occurs more than once.
*
* @return array headers as array(name => value)
*/
public function getHeaders()
{
if ($this->_headers === null) {
if (!$this->_mail) {
$this->_headers = array();
} else {
$part = $this->_mail->getRawHeader($this->_messageNum);
Zend_Mime_Decode::splitMessage($part, $this->_headers, $null);
}
}
return $this->_headers;
}
/**
* Get a header in specificed format
*
* Internally headers that occur more than once are saved as array, all other as string. If $format
* is set to string implode is used to concat the values (with Zend_Mime::LINEEND as delim).
*
* @param string $name name of header, matches case-insensitive, but camel-case is replaced with dashes
* @param string $format change type of return value to 'string' or 'array'
* @return string|array value of header in wanted or internal format
* @throws Zend_Mail_Exception
*/
public function getHeader($name, $format = null)
{
if ($this->_headers === null) {
$this->getHeaders();
}
$lowerName = strtolower($name);
if ($this->headerExists($name) == false) {
$lowerName = strtolower(preg_replace('%([a-z])([A-Z])%', '\1-\2', $name));
if($this->headerExists($lowerName) == false) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception("no Header with Name $name or $lowerName found");
}
}
$name = $lowerName;
$header = $this->_headers[$name];
switch ($format) {
case 'string':
if (is_array($header)) {
$header = implode(Zend_Mime::LINEEND, $header);
}
break;
case 'array':
$header = (array)$header;
default:
// do nothing
}
return $header;
}
/**
* Check wheater the Mail part has a specific header.
*
* @param string $name
* @return boolean
*/
public function headerExists($name)
{
$name = strtolower($name);
if(isset($this->_headers[$name])) {
return true;
} else {
return false;
}
}
/**
* Get a specific field from a header like content type or all fields as array
*
* If the header occurs more than once, only the value from the first header
* is returned.
*
* Throws a Zend_Mail_Exception if the requested header does not exist. If
* the specific header field does not exist, returns null.
*
* @param string $name name of header, like in getHeader()
* @param string $wantedPart the wanted part, default is first, if null an array with all parts is returned
* @param string $firstName key name for the first part
* @return string|array wanted part or all parts as array($firstName => firstPart, partname => value)
* @throws Zend_Exception, Zend_Mail_Exception
*/
public function getHeaderField($name, $wantedPart = 0, $firstName = 0) {
return Zend_Mime_Decode::splitHeaderField(current($this->getHeader($name, 'array')), $wantedPart, $firstName);
}
/**
* Getter for mail headers - name is matched in lowercase
*
* This getter is short for Zend_Mail_Part::getHeader($name, 'string')
*
* @see Zend_Mail_Part::getHeader()
*
* @param string $name header name
* @return string value of header
* @throws Zend_Mail_Exception
*/
public function __get($name)
{
return $this->getHeader($name, 'string');
}
/**
* Isset magic method proxy to hasHeader
*
* This method is short syntax for Zend_Mail_Part::hasHeader($name);
*
* @see Zend_Mail_Part::hasHeader
*
* @param string
* @return boolean
*/
public function __isset($name)
{
return $this->headerExists($name);
}
/**
* magic method to get content of part
*
* @return string content
*/
public function __toString()
{
return $this->getContent();
}
/**
* implements RecursiveIterator::hasChildren()
*
* @return bool current element has children/is multipart
*/
public function hasChildren()
{
$current = $this->current();
return $current && $current instanceof Zend_Mail_Part && $current->isMultipart();
}
/**
* implements RecursiveIterator::getChildren()
*
* @return Zend_Mail_Part same as self::current()
*/
public function getChildren()
{
return $this->current();
}
/**
* implements Iterator::valid()
*
* @return bool check if there's a current element
*/
public function valid()
{
if ($this->_countParts === null) {
$this->countParts();
}
return $this->_iterationPos && $this->_iterationPos <= $this->_countParts;
}
/**
* implements Iterator::next()
*
* @return null
*/
public function next()
{
++$this->_iterationPos;
}
/**
* implements Iterator::key()
*
* @return string key/number of current part
*/
public function key()
{
return $this->_iterationPos;
}
/**
* implements Iterator::current()
*
* @return Zend_Mail_Part current part
*/
public function current()
{
return $this->getPart($this->_iterationPos);
}
/**
* implements Iterator::rewind()
*
* @return null
*/
public function rewind()
{
$this->countParts();
$this->_iterationPos = 1;
}
}
Part/Interface.php 0000644 00000010114 15210162410 0010050 0 ustar 00 value)
*/
public function getHeaders();
/**
* Get a header in specificed format
*
* Internally headers that occur more than once are saved as array, all other as string. If $format
* is set to string implode is used to concat the values (with Zend_Mime::LINEEND as delim).
*
* @param string $name name of header, matches case-insensitive, but camel-case is replaced with dashes
* @param string $format change type of return value to 'string' or 'array'
* @return string|array value of header in wanted or internal format
* @throws Zend_Mail_Exception
*/
public function getHeader($name, $format = null);
/**
* Get a specific field from a header like content type or all fields as array
*
* If the header occurs more than once, only the value from the first header
* is returned.
*
* Throws a Zend_Mail_Exception if the requested header does not exist. If
* the specific header field does not exist, returns null.
*
* @param string $name name of header, like in getHeader()
* @param string $wantedPart the wanted part, default is first, if null an array with all parts is returned
* @param string $firstName key name for the first part
* @return string|array wanted part or all parts as array($firstName => firstPart, partname => value)
* @throws Zend_Exception, Zend_Mail_Exception
*/
public function getHeaderField($name, $wantedPart = 0, $firstName = 0);
/**
* Getter for mail headers - name is matched in lowercase
*
* This getter is short for Zend_Mail_Part::getHeader($name, 'string')
*
* @see Zend_Mail_Part::getHeader()
*
* @param string $name header name
* @return string value of header
* @throws Zend_Mail_Exception
*/
public function __get($name);
/**
* magic method to get content of part
*
* @return string content
*/
public function __toString();
}
Part/File.php 0000644 00000013774 15210162410 0007046 0 ustar 00 _fh = fopen($params['file'], 'r');
} else {
$this->_fh = $params['file'];
}
if (!$this->_fh) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('could not open file');
}
if (isset($params['startPos'])) {
fseek($this->_fh, $params['startPos']);
}
$header = '';
$endPos = isset($params['endPos']) ? $params['endPos'] : null;
while (($endPos === null || ftell($this->_fh) < $endPos) && trim($line = fgets($this->_fh))) {
$header .= $line;
}
Zend_Mime_Decode::splitMessage($header, $this->_headers, $null);
$this->_contentPos[0] = ftell($this->_fh);
if ($endPos !== null) {
$this->_contentPos[1] = $endPos;
} else {
fseek($this->_fh, 0, SEEK_END);
$this->_contentPos[1] = ftell($this->_fh);
}
if (!$this->isMultipart()) {
return;
}
$boundary = $this->getHeaderField('content-type', 'boundary');
if (!$boundary) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('no boundary found in content type to split message');
}
$part = array();
$pos = $this->_contentPos[0];
fseek($this->_fh, $pos);
while (!feof($this->_fh) && ($endPos === null || $pos < $endPos)) {
$line = fgets($this->_fh);
if ($line === false) {
if (feof($this->_fh)) {
break;
}
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('error reading file');
}
$lastPos = $pos;
$pos = ftell($this->_fh);
$line = trim($line);
if ($line == '--' . $boundary) {
if ($part) {
// not first part
$part[1] = $lastPos;
$this->_partPos[] = $part;
}
$part = array($pos);
} else if ($line == '--' . $boundary . '--') {
$part[1] = $lastPos;
$this->_partPos[] = $part;
break;
}
}
$this->_countParts = count($this->_partPos);
}
/**
* Body of part
*
* If part is multipart the raw content of this part with all sub parts is returned
*
* @return string body
* @throws Zend_Mail_Exception
*/
public function getContent($stream = null)
{
fseek($this->_fh, $this->_contentPos[0]);
if ($stream !== null) {
return stream_copy_to_stream($this->_fh, $stream, $this->_contentPos[1] - $this->_contentPos[0]);
}
$length = $this->_contentPos[1] - $this->_contentPos[0];
return $length < 1 ? '' : fread($this->_fh, $length);
}
/**
* Return size of part
*
* Quite simple implemented currently (not decoding). Handle with care.
*
* @return int size
*/
public function getSize() {
return $this->_contentPos[1] - $this->_contentPos[0];
}
/**
* Get part of multipart message
*
* @param int $num number of part starting with 1 for first part
* @return Zend_Mail_Part wanted part
* @throws Zend_Mail_Exception
*/
public function getPart($num)
{
--$num;
if (!isset($this->_partPos[$num])) {
/**
* @see Zend_Mail_Exception
*/
//--//require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('part not found');
}
return new self(array('file' => $this->_fh, 'startPos' => $this->_partPos[$num][0],
'endPos' => $this->_partPos[$num][1]));
}
}
Message/Interface.php 0000644 00000002763 15210162410 0010541 0 ustar 00 _flags = array_combine($params['flags'], $params['flags']);
}
parent::__construct($params);
}
/**
* return toplines as found after headers
*
* @return string toplines
*/
public function getTopLines()
{
return $this->_topLines;
}
/**
* check if flag is set
*
* @param mixed $flag a flag name, use constants defined in Zend_Mail_Storage
* @return bool true if set, otherwise false
*/
public function hasFlag($flag)
{
return isset($this->_flags[$flag]);
}
/**
* get all set flags
*
* @return array array with flags, key and value are the same for easy lookup
*/
public function getFlags()
{
return $this->_flags;
}
}
Protocol/Abstract.php 0000644 00000025765 15210162410 0010630 0 ustar 00 _validHost = new Am_Util_Dummy_Zend_Validate();
//$this->_validHost->addValidator(new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_ALL));
if (!$this->_validHost->isValid($host)) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages()));
}
$this->_host = $host;
$this->_port = $port;
}
/**
* Class destructor to cleanup open resources
*
* @return void
*/
public function __destruct()
{
$this->_disconnect();
}
/**
* Set the maximum log size
*
* @param integer $maximumLog Maximum log size
* @return void
*/
public function setMaximumLog($maximumLog)
{
$this->_maximumLog = (int) $maximumLog;
}
/**
* Get the maximum log size
*
* @return int the maximum log size
*/
public function getMaximumLog()
{
return $this->_maximumLog;
}
/**
* Create a connection to the remote host
*
* Concrete adapters for this class will implement their own unique connect scripts, using the _connect() method to create the socket resource.
*/
abstract public function connect();
/**
* Retrieve the last client request
*
* @return string
*/
public function getRequest()
{
return $this->_request;
}
/**
* Retrieve the last server response
*
* @return array
*/
public function getResponse()
{
return $this->_response;
}
/**
* Retrieve the transaction log
*
* @return string
*/
public function getLog()
{
return implode('', $this->_log);
}
/**
* Reset the transaction log
*
* @return void
*/
public function resetLog()
{
$this->_log = array();
}
/**
* Add the transaction log
*
* @param string new transaction
* @return void
*/
protected function _addLog($value)
{
if ($this->_maximumLog >= 0 && count($this->_log) >= $this->_maximumLog) {
array_shift($this->_log);
}
$this->_log[] = $value;
}
/**
* Connect to the server using the supplied transport and target
*
* An example $remote string may be 'tcp://mail.example.com:25' or 'ssh://hostname.com:2222'
*
* @param string $remote Remote
* @throws Zend_Mail_Protocol_Exception
* @return boolean
*/
protected function _connect($remote)
{
$errorNum = 0;
$errorStr = '';
// open connection
$this->_socket = @stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION);
if ($this->_socket === false) {
if ($errorNum == 0) {
$errorStr = 'Could not open socket';
}
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception($errorStr);
}
if (($result = $this->_setStreamTimeout(self::TIMEOUT_CONNECTION)) === false) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Could not set stream timeout');
}
return $result;
}
/**
* Disconnect from remote host and free resource
*
* @return void
*/
protected function _disconnect()
{
if (is_resource($this->_socket)) {
fclose($this->_socket);
}
}
/**
* Send the given request followed by a LINEEND to the server.
*
* @param string $request
* @throws Zend_Mail_Protocol_Exception
* @return integer|boolean Number of bytes written to remote host
*/
protected function _send($request)
{
if (!is_resource($this->_socket)) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
}
$this->_request = $request;
$result = fwrite($this->_socket, $request . self::EOL);
// Save request to internal log
$this->_addLog($request . self::EOL);
if ($result === false) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Could not send request to ' . $this->_host);
}
return $result;
}
/**
* Get a line from the stream.
*
* @var integer $timeout Per-request timeout value if applicable
* @throws Zend_Mail_Protocol_Exception
* @return string
*/
protected function _receive($timeout = null)
{
if (!is_resource($this->_socket)) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
}
// Adapters may wish to supply per-commend timeouts according to appropriate RFC
if ($timeout !== null) {
$this->_setStreamTimeout($timeout);
}
// Retrieve response
$reponse = fgets($this->_socket, 1024);
// Save request to internal log
$this->_addLog($reponse);
// Check meta data to ensure connection is still valid
$info = stream_get_meta_data($this->_socket);
if (!empty($info['timed_out'])) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception($this->_host . ' has timed out');
}
if ($reponse === false) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Could not read from ' . $this->_host);
}
return $reponse;
}
/**
* Parse server response for successful codes
*
* Read the response from the stream and check for expected return code.
* Throws a Zend_Mail_Protocol_Exception if an unexpected code is returned.
*
* @param string|array $code One or more codes that indicate a successful response
* @throws Zend_Mail_Protocol_Exception
* @return string Last line of response string
*/
protected function _expect($code, $timeout = null)
{
$this->_response = array();
$cmd = '';
$more = '';
$msg = '';
$errMsg = '';
if (!is_array($code)) {
$code = array($code);
}
do {
$this->_response[] = $result = $this->_receive($timeout);
list($cmd, $more, $msg) = preg_split('/([\s-]+)/', $result, 2, PREG_SPLIT_DELIM_CAPTURE);
if ($errMsg !== '') {
$errMsg .= ' ' . $msg;
} elseif ($cmd === null || !in_array($cmd, $code)) {
$errMsg = $msg;
}
} while (strpos($more, '-') === 0); // The '-' message prefix indicates an information string instead of a response string.
if ($errMsg !== '') {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception($errMsg, $cmd);
}
return $msg;
}
/**
* Set stream timeout
*
* @param integer $timeout
* @return boolean
*/
protected function _setStreamTimeout($timeout)
{
return stream_set_timeout($this->_socket, $timeout);
}
}
Protocol/Smtp/Auth/Plain.php 0000644 00000004575 15210162410 0011750 0 ustar 00 _username = $config['username'];
}
if (isset($config['password'])) {
$this->_password = $config['password'];
}
}
parent::__construct($host, $port, $config);
}
/**
* Perform PLAIN authentication with supplied credentials
*
* @return void
*/
public function auth()
{
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH PLAIN');
$this->_expect(334);
$this->_send(base64_encode("\0" . $this->_username . "\0" . $this->_password));
$this->_expect(235);
$this->_auth = true;
}
}
Protocol/Smtp/Auth/Login.php 0000644 00000004660 15210162410 0011750 0 ustar 00 _username = $config['username'];
}
if (isset($config['password'])) {
$this->_password = $config['password'];
}
}
parent::__construct($host, $port, $config);
}
/**
* Perform LOGIN authentication with supplied credentials
*
* @return void
*/
public function auth()
{
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH LOGIN');
$this->_expect(334);
$this->_send(base64_encode($this->_username));
$this->_expect(334);
$this->_send(base64_encode($this->_password));
$this->_expect(235);
$this->_auth = true;
}
}
Protocol/Smtp/Auth/Crammd5.php 0000644 00000006057 15210162410 0012172 0 ustar 00 _username = $config['username'];
}
if (isset($config['password'])) {
$this->_password = $config['password'];
}
}
parent::__construct($host, $port, $config);
}
/**
* @todo Perform CRAM-MD5 authentication with supplied credentials
*
* @return void
*/
public function auth()
{
// Ensure AUTH has not already been initiated.
parent::auth();
$this->_send('AUTH CRAM-MD5');
$challenge = $this->_expect(334);
$challenge = base64_decode($challenge);
$digest = $this->_hmacMd5($this->_password, $challenge);
$this->_send(base64_encode($this->_username . ' ' . $digest));
$this->_expect(235);
$this->_auth = true;
}
/**
* Prepare CRAM-MD5 response to server's ticket
*
* @param string $key Challenge key (usually password)
* @param string $data Challenge data
* @param string $block Length of blocks
* @return string
*/
protected function _hmacMd5($key, $data, $block = 64)
{
if (strlen($key) > 64) {
$key = pack('H32', md5($key));
} elseif (strlen($key) < 64) {
$key = str_pad($key, $block, "\0");
}
$k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64);
$k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64);
$inner = pack('H32', md5($k_ipad . $data));
$digest = md5($k_opad . $inner);
return $digest;
}
}
Protocol/Smtp.php 0000644 00000027150 15210162410 0007776 0 ustar 00 _secure = 'tls';
break;
case 'ssl':
$this->_transport = 'ssl';
$this->_secure = 'ssl';
if ($port == null) {
$port = 465;
}
break;
default:
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception($config['ssl'] . ' is unsupported SSL type');
break;
}
}
// If no port has been specified then check the master PHP ini file. Defaults to 25 if the ini setting is null.
if ($port == null) {
if (($port = ini_get('smtp_port')) == '') {
$port = 25;
}
}
parent::__construct($host, $port);
}
/**
* Connect to the server with the parameters given in the constructor.
*
* @return boolean
*/
public function connect()
{
return $this->_connect($this->_transport . '://' . $this->_host . ':'. $this->_port);
}
/**
* Initiate HELO/EHLO sequence and set flag to indicate valid smtp session
*
* @param string $host The client hostname or IP address (default: 127.0.0.1)
* @throws Zend_Mail_Protocol_Exception
* @return void
*/
public function helo($host = '127.0.0.1')
{
// Respect RFC 2821 and disallow HELO attempts if session is already initiated.
if ($this->_sess === true) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Cannot issue HELO to existing session');
}
// Validate client hostname
if (!$this->_validHost->isValid($host)) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages()));
}
// Initiate helo sequence
$this->_expect(220, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
$this->_ehlo($host);
// If a TLS session is required, commence negotiation
if ($this->_secure == 'tls') {
$this->_send('STARTTLS');
$this->_expect(220, 180);
if (!stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Unable to connect via TLS');
}
$this->_ehlo($host);
}
$this->_startSession();
$this->auth();
}
/**
* Send EHLO or HELO depending on capabilities of smtp host
*
* @param string $host The client hostname or IP address (default: 127.0.0.1)
* @throws Zend_Mail_Protocol_Exception
* @return void
*/
protected function _ehlo($host)
{
// Support for older, less-compliant remote servers. Tries multiple attempts of EHLO or HELO.
try {
$this->_send('EHLO ' . $host);
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
} catch (Zend_Mail_Protocol_Exception $e) {
$this->_send('HELO ' . $host);
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
} catch (Zend_Mail_Protocol_Exception $e) {
throw $e;
}
}
/**
* Issues MAIL command
*
* @param string $from Sender mailbox
* @throws Zend_Mail_Protocol_Exception
* @return void
*/
public function mail($from)
{
if ($this->_sess !== true) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('A valid session has not been started');
}
$this->_send('MAIL FROM:<' . $from . '>');
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
// Set mail to true, clear recipients and any existing data flags as per 4.1.1.2 of RFC 2821
$this->_mail = true;
$this->_rcpt = false;
$this->_data = false;
}
/**
* Issues RCPT command
*
* @param string $to Receiver(s) mailbox
* @throws Zend_Mail_Protocol_Exception
* @return void
*/
public function rcpt($to)
{
if ($this->_mail !== true) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('No sender reverse path has been supplied');
}
// Set rcpt to true, as per 4.1.1.3 of RFC 2821
$this->_send('RCPT TO:<' . $to . '>');
$this->_expect(array(250, 251), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
$this->_rcpt = true;
}
/**
* Issues DATA command
*
* @param string $data
* @throws Zend_Mail_Protocol_Exception
* @return void
*/
public function data($data)
{
// Ensure recipients have been set
if ($this->_rcpt !== true) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('No recipient forward path has been supplied');
}
$this->_send('DATA');
$this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2
foreach (explode(Zend_Mime::LINEEND, $data) as $line) {
if (strpos($line, '.') === 0) {
// Escape lines prefixed with a '.'
$line = '.' . $line;
}
$this->_send($line);
}
$this->_send('.');
$this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2
$this->_data = true;
}
/**
* Issues the RSET command and validates answer
*
* Can be used to restore a clean smtp communication state when a transaction has been cancelled or commencing a new transaction.
*
* @return void
*/
public function rset()
{
$this->_send('RSET');
// MS ESMTP doesn't follow RFC, see [ZF-1377]
$this->_expect(array(250, 220));
$this->_mail = false;
$this->_rcpt = false;
$this->_data = false;
}
/**
* Issues the NOOP command and validates answer
*
* Not used by Zend_Mail, could be used to keep a connection alive or check if it is still open.
*
* @return void
*/
public function noop()
{
$this->_send('NOOP');
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
/**
* Issues the VRFY command and validates answer
*
* Not used by Zend_Mail.
*
* @param string $user User Name or eMail to verify
* @return void
*/
public function vrfy($user)
{
$this->_send('VRFY ' . $user);
$this->_expect(array(250, 251, 252), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
}
/**
* Issues the QUIT command and clears the current session
*
* @return void
*/
public function quit()
{
if ($this->_sess) {
$this->_send('QUIT');
$this->_expect(221, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
$this->_stopSession();
}
}
/**
* Default authentication method
*
* This default method is implemented by AUTH adapters to properly authenticate to a remote host.
*
* @throws Zend_Mail_Protocol_Exception
* @return void
*/
public function auth()
{
if ($this->_auth === true) {
/**
* @see Zend_Mail_Protocol_Exception
*/
//--//require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Already authenticated for this session');
}
}
/**
* Closes connection
*
* @return void
*/
public function disconnect()
{
$this->_disconnect();
}
/**
* Start mail session
*
* @return void
*/
protected function _startSession()
{
$this->_sess = true;
}
/**
* Stop mail session
*
* @return void
*/
protected function _stopSession()
{
$this->_sess = false;
}
}
Protocol/Exception.php 0000644 00000002127 15210162410 0011006 0 ustar 00 toArray();
}
if (is_array($parameters)) {
$parameters = implode(' ', $parameters);
}
$this->parameters = $parameters;
}
/**
* Send mail using PHP native mail()
*
* @access public
* @return void
* @throws Zend_Mail_Transport_Exception if parameters is set
* but not a string
* @throws Zend_Mail_Transport_Exception on mail() failure
*/
public function _sendMail()
{
if ($this->parameters === null) {
set_error_handler(array($this, '_handleMailErrors'));
$result = mail(
$this->recipients,
$this->_mail->getSubject(),
$this->body,
$this->header);
restore_error_handler();
} else {
if(!is_string($this->parameters)) {
/**
* @see Zend_Mail_Transport_Exception
*
* Exception is thrown here because
* $parameters is a public property
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception(
'Parameters were set but are not a string'
);
}
set_error_handler(array($this, '_handleMailErrors'));
$result = mail(
$this->recipients,
$this->_mail->getSubject(),
$this->body,
$this->header,
$this->parameters);
restore_error_handler();
}
if ($this->_errstr !== null || !$result) {
/**
* @see Zend_Mail_Transport_Exception
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('Unable to send mail. ' . $this->_errstr);
}
}
/**
* Format and fix headers
*
* mail() uses its $to and $subject arguments to set the To: and Subject:
* headers, respectively. This method strips those out as a sanity check to
* prevent duplicate header entries.
*
* @access protected
* @param array $headers
* @return void
* @throws Zend_Mail_Transport_Exception
*/
protected function _prepareHeaders($headers)
{
if (!$this->_mail) {
/**
* @see Zend_Mail_Transport_Exception
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Zend_Mail object');
}
// mail() uses its $to parameter to set the To: header, and the $subject
// parameter to set the Subject: header. We need to strip them out.
if (0 === strpos(PHP_OS, 'WIN')) {
// If the current recipients list is empty, throw an error
if (empty($this->recipients)) {
/**
* @see Zend_Mail_Transport_Exception
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('Missing To addresses');
}
} else {
// All others, simply grab the recipients and unset the To: header
if (!isset($headers['To'])) {
/**
* @see Zend_Mail_Transport_Exception
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('Missing To header');
}
unset($headers['To']['append']);
$this->recipients = implode(',', $headers['To']);
}
// Remove recipient header
unset($headers['To']);
// Remove subject header, if present
if (isset($headers['Subject'])) {
unset($headers['Subject']);
}
// Prepare headers
parent::_prepareHeaders($headers);
// Fix issue with empty blank line ontop when using Sendmail Trnasport
$this->header = rtrim($this->header);
}
/**
* Temporary error handler for PHP native mail().
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param string $errline
* @param array $errcontext
* @return true
*/
public function _handleMailErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null)
{
$this->_errstr = $errstr;
return true;
}
}
Transport/Abstract.php 0000644 00000024211 15210162410 0011004 0 ustar 00 _mail->getType();
if (!$type) {
if ($this->_mail->hasAttachments) {
$type = Zend_Mime::MULTIPART_MIXED;
} elseif ($this->_mail->getBodyText() && $this->_mail->getBodyHtml()) {
$type = Zend_Mime::MULTIPART_ALTERNATIVE;
} else {
$type = Zend_Mime::MULTIPART_MIXED;
}
}
$this->_headers['Content-Type'] = array(
$type . ';'
. $this->EOL
. " " . 'boundary="' . $boundary . '"'
);
$this->boundary = $boundary;
}
$this->_headers['MIME-Version'] = array('1.0');
return $this->_headers;
}
/**
* Prepend header name to header value
*
* @param string $item
* @param string $key
* @param string $prefix
* @static
* @access protected
* @return void
*/
protected static function _formatHeader(&$item, $key, $prefix)
{
$item = $prefix . ': ' . $item;
}
/**
* Prepare header string for use in transport
*
* Prepares and generates {@link $header} based on the headers provided.
*
* @param mixed $headers
* @access protected
* @return void
* @throws Zend_Mail_Transport_Exception if any header lines exceed 998
* characters
*/
protected function _prepareHeaders($headers)
{
if (!$this->_mail) {
/**
* @see Zend_Mail_Transport_Exception
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('Missing Zend_Mail object in _mail property');
}
$this->header = '';
foreach ($headers as $header => $content) {
if (isset($content['append'])) {
unset($content['append']);
$value = implode(',' . $this->EOL . ' ', $content);
$this->header .= $header . ': ' . $value . $this->EOL;
} else {
array_walk($content, array(get_class($this), '_formatHeader'), $header);
$this->header .= implode($this->EOL, $content) . $this->EOL;
}
}
// Sanity check on headers -- should not be > 998 characters
$sane = true;
foreach (explode($this->EOL, $this->header) as $line) {
if (strlen(trim($line)) > 998) {
$sane = false;
break;
}
}
if (!$sane) {
/**
* @see Zend_Mail_Transport_Exception
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Exception('At least one mail header line is too long');
}
}
/**
* Generate MIME compliant message from the current configuration
*
* If both a text and HTML body are present, generates a
* multipart/alternative Zend_Mime_Part containing the headers and contents
* of each. Otherwise, uses whichever of the text or HTML parts present.
*
* The content part is then prepended to the list of Zend_Mime_Parts for
* this message.
*
* @return void
*/
protected function _buildBody()
{
if (($text = $this->_mail->getBodyText())
&& ($html = $this->_mail->getBodyHtml()))
{
// Generate unique boundary for multipart/alternative
$mime = new Zend_Mime(null);
$boundaryLine = $mime->boundaryLine($this->EOL);
$boundaryEnd = $mime->mimeEnd($this->EOL);
$text->disposition = false;
$html->disposition = false;
$body = $boundaryLine
. $text->getHeaders($this->EOL)
. $this->EOL
. $text->getContent($this->EOL)
. $this->EOL
. $boundaryLine
. $html->getHeaders($this->EOL)
. $this->EOL
. $html->getContent($this->EOL)
. $this->EOL
. $boundaryEnd;
$mp = new Zend_Mime_Part($body);
$mp->type = Zend_Mime::MULTIPART_ALTERNATIVE;
$mp->boundary = $mime->boundary();
$this->_isMultipart = true;
// Ensure first part contains text alternatives
array_unshift($this->_parts, $mp);
// Get headers
$this->_headers = $this->_mail->getHeaders();
return;
}
// If not multipart, then get the body
if (false !== ($body = $this->_mail->getBodyHtml())) {
array_unshift($this->_parts, $body);
} elseif (false !== ($body = $this->_mail->getBodyText())) {
array_unshift($this->_parts, $body);
}
if (!$body) {
/**
* @see Zend_Mail_Transport_Exception
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('No body specified');
}
// Get headers
$this->_headers = $this->_mail->getHeaders();
$headers = $body->getHeadersArray($this->EOL);
foreach ($headers as $header) {
// Headers in Zend_Mime_Part are kept as arrays with two elements, a
// key and a value
$this->_headers[$header[0]] = array($header[1]);
}
}
/**
* Send a mail using this transport
*
* @param Zend_Mail $mail
* @access public
* @return void
* @throws Zend_Mail_Transport_Exception if mail is empty
*/
public function send(Zend_Mail $mail)
{
$this->_isMultipart = false;
$this->_mail = $mail;
$this->_parts = $mail->getParts();
$mime = $mail->getMime();
// Build body content
$this->_buildBody();
// Determine number of parts and boundary
$count = count($this->_parts);
$boundary = null;
if ($count < 1) {
/**
* @see Zend_Mail_Transport_Exception
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('Empty mail cannot be sent');
}
if ($count > 1) {
// Multipart message; create new MIME object and boundary
$mime = new Zend_Mime($this->_mail->getMimeBoundary());
$boundary = $mime->boundary();
} elseif ($this->_isMultipart) {
// multipart/alternative -- grab boundary
$boundary = $this->_parts[0]->boundary;
}
// Determine recipients, and prepare headers
$this->recipients = implode(',', $mail->getRecipients());
$this->_prepareHeaders($this->_getHeaders($boundary));
// Create message body
// This is done so that the same Zend_Mail object can be used in
// multiple transports
$message = new Zend_Mime_Message();
$message->setParts($this->_parts);
$message->setMime($mime);
$this->body = $message->generateMessage($this->EOL);
// Send to transport!
$this->_sendMail();
}
}
Transport/Smtp.php 0000644 00000014506 15210162410 0010172 0 ustar 00 _name = $config['name'];
}
if (isset($config['port'])) {
$this->_port = $config['port'];
}
if (isset($config['auth'])) {
$this->_auth = $config['auth'];
}
$this->_host = $host;
$this->_config = $config;
}
/**
* Class destructor to ensure all open connections are closed
*
* @return void
*/
public function __destruct()
{
if ($this->_connection instanceof Zend_Mail_Protocol_Smtp) {
try {
$this->_connection->quit();
} catch (Zend_Mail_Protocol_Exception $e) {
// ignore
}
$this->_connection->disconnect();
}
}
/**
* Sets the connection protocol instance
*
* @param Zend_Mail_Protocol_Abstract $client
*
* @return void
*/
public function setConnection(Zend_Mail_Protocol_Abstract $connection)
{
$this->_connection = $connection;
}
/**
* Gets the connection protocol instance
*
* @return Zend_Mail_Protocol|null
*/
public function getConnection()
{
return $this->_connection;
}
/**
* Send an email via the SMTP connection protocol
*
* The connection via the protocol adapter is made just-in-time to allow a
* developer to add a custom adapter if required before mail is sent.
*
* @return void
* @todo Rename this to sendMail, it's a public method...
*/
public function _sendMail()
{
if($this->_connection instanceof Zend_Mail_Protocol_Smtp)
{
try{
$this->_connection->rset();
}catch(Zend_Mail_Protocol_Exception $e){
// We got an exception. This is impossible to reset connection.
// Let's use new one;
$this->_connection = null;
}
}
// If sending multiple messages per session use existing adapter
if (!($this->_connection instanceof Zend_Mail_Protocol_Smtp)) {
// Check if authentication is required and determine required class
$connectionClass = 'Zend_Mail_Protocol_Smtp';
if ($this->_auth) {
$connectionClass .= '_Auth_' . ucwords($this->_auth);
}
if (!class_exists($connectionClass)) {
//--//require_once 'Zend/Loader.php';
Zend_Loader::loadClass($connectionClass);
}
$this->setConnection(new $connectionClass($this->_host, $this->_port, $this->_config));
$this->_connection->connect();
$this->_connection->helo($this->_name);
}
// Set sender email address
$this->_connection->mail($this->_mail->getReturnPath());
// Set recipient forward paths
foreach ($this->_mail->getRecipients() as $recipient) {
$this->_connection->rcpt($recipient);
}
// Issue DATA command to client
$this->_connection->data($this->header . Zend_Mime::LINEEND . $this->body);
}
/**
* Format and fix headers
*
* Some SMTP servers do not strip BCC headers. Most clients do it themselves as do we.
*
* @access protected
* @param array $headers
* @return void
* @throws Zend_Transport_Exception
*/
protected function _prepareHeaders($headers)
{
if (!$this->_mail) {
/**
* @see Zend_Mail_Transport_Exception
*/
//--//require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Zend_Mail object');
}
unset($headers['Bcc']);
// Prepare headers
parent::_prepareHeaders($headers);
}
}
Transport/Exception.php 0000644 00000002137 15210162410 0011202 0 ustar 00 _flags = array_merge($this->_flags, array_combine($params['flags'],$params['flags']));
}
parent::__construct($params);
}
/**
* return toplines as found after headers
*
* @return string toplines
*/
public function getTopLines()
{
return $this->_topLines;
}
/**
* check if flag is set
*
* @param mixed $flag a flag name, use constants defined in Zend_Mail_Storage
* @return bool true if set, otherwise false
*/
public function hasFlag($flag)
{
return isset($this->_flags[$flag]);
}
/**
* get all set flags
*
* @return array array with flags, key and value are the same for easy lookup
*/
public function getFlags()
{
return $this->_flags;
}
}