From c53d8d026021f97075fb2f4940ba22793c38fb6e Mon Sep 17 00:00:00 2001 From: davehauenstein Date: Wed, 15 Apr 2009 22:06:42 +0000 Subject: added toolbar; functionality includes refresh button to get back to original page, print article, email a link to the article with a personal note git-svn-id: http://arc90labs-readability.googlecode.com/svn/trunk@31 d4e419ec-0920-11de-bbfd-a7c1bc4c261e --- lib/Zend/Mail/Transport/Abstract.php | 350 ++++++++++++++++++++++++++++++++++ lib/Zend/Mail/Transport/Exception.php | 39 ++++ lib/Zend/Mail/Transport/Sendmail.php | 170 +++++++++++++++++ lib/Zend/Mail/Transport/Smtp.php | 241 +++++++++++++++++++++++ 4 files changed, 800 insertions(+) create mode 100644 lib/Zend/Mail/Transport/Abstract.php create mode 100644 lib/Zend/Mail/Transport/Exception.php create mode 100644 lib/Zend/Mail/Transport/Sendmail.php create mode 100644 lib/Zend/Mail/Transport/Smtp.php (limited to 'lib/Zend/Mail/Transport') diff --git a/lib/Zend/Mail/Transport/Abstract.php b/lib/Zend/Mail/Transport/Abstract.php new file mode 100644 index 0000000..603411a --- /dev/null +++ b/lib/Zend/Mail/Transport/Abstract.php @@ -0,0 +1,350 @@ +_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 . '; charset="' . $this->_mail->getCharset() . '";' + . $this->EOL + . " " . 'boundary="' . $boundary . '"' + ); + $this->_headers['MIME-Version'] = array('1.0'); + + $this->boundary = $boundary; + } + + 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(); + } +} diff --git a/lib/Zend/Mail/Transport/Exception.php b/lib/Zend/Mail/Transport/Exception.php new file mode 100644 index 0000000..16ef240 --- /dev/null +++ b/lib/Zend/Mail/Transport/Exception.php @@ -0,0 +1,39 @@ +parameters = $parameters; + } + + + /** + * Send mail using PHP native mail() + * + * @access public + * @return void + * @throws Zend_Mail_Transport_Exception on mail() failure + */ + public function _sendMail() + { + if ($this->parameters === null) { + $result = mail( + $this->recipients, + $this->_mail->getSubject(), + $this->body, + $this->header); + } else { + $result = mail( + $this->recipients, + $this->_mail->getSubject(), + $this->body, + $this->header, + $this->parameters); + } + if (!$result) { + /** + * @see Zend_Mail_Transport_Exception + */ + require_once 'Zend/Mail/Transport/Exception.php'; + throw new Zend_Mail_Transport_Exception('Unable to send mail'); + } + } + + + /** + * 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); + } + +} + diff --git a/lib/Zend/Mail/Transport/Smtp.php b/lib/Zend/Mail/Transport/Smtp.php new file mode 100644 index 0000000..714266e --- /dev/null +++ b/lib/Zend/Mail/Transport/Smtp.php @@ -0,0 +1,241 @@ +_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 + */ + public function _sendMail() + { + // 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); + } + Zend_Loader::loadClass($connectionClass); + $this->setConnection(new $connectionClass($this->_host, $this->_port, $this->_config)); + $this->_connection->connect(); + $this->_connection->helo($this->_name); + } else { + // Reset connection to ensure reliable transaction + $this->_connection->rset(); + } + + // Set mail return path from 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); + } +} -- cgit v1.2.3