Overview

Packages

  • Mail

Classes

  • Horde_Mail
  • Horde_Mail_Exception
  • Horde_Mail_Rfc822
  • Horde_Mail_Rfc822_Address
  • Horde_Mail_Rfc822_Group
  • Horde_Mail_Rfc822_Object
  • Horde_Mail_Transport
  • Horde_Mail_Transport_Mail
  • Horde_Mail_Transport_Mock
  • Horde_Mail_Transport_Null
  • Horde_Mail_Transport_Sendmail
  • Horde_Mail_Transport_Smtp
  • Horde_Mail_Transport_Smtpmx
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Mail transport base class.
  4:  *
  5:  * LICENSE:
  6:  *
  7:  * Copyright (c) 2002-2007, Richard Heyes
  8:  * All rights reserved.
  9:  *
 10:  * Redistribution and use in source and binary forms, with or without
 11:  * modification, are permitted provided that the following conditions
 12:  * are met:
 13:  *
 14:  * o Redistributions of source code must retain the above copyright
 15:  *   notice, this list of conditions and the following disclaimer.
 16:  * o Redistributions in binary form must reproduce the above copyright
 17:  *   notice, this list of conditions and the following disclaimer in the
 18:  *   documentation and/or other materials provided with the distribution.
 19:  * o The names of the authors may not be used to endorse or promote
 20:  *   products derived from this software without specific prior written
 21:  *   permission.
 22:  *
 23:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 24:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 25:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 26:  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 27:  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 28:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 29:  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 30:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 31:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 32:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 33:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 34:  *
 35:  * @category    Mail
 36:  * @package     Mail
 37:  * @author      Chuck Hagenbuch <chuck@horde.org>
 38:  * @author      Michael Slusarz <slusarz@horde.org>
 39:  * @copyright   1997-2010 Chuck Hagenbuch
 40:  * @copyright   2010 Michael Slusarz
 41:  * @license     http://www.horde.org/licenses/bsd New BSD License
 42:  */
 43: 
 44: /**
 45:  * Mail transport base class.
 46:  *
 47:  * @access public
 48:  * @version $Revision: 294747 $
 49:  * @package Mail
 50:  */
 51: abstract class Horde_Mail_Transport
 52: {
 53:     /**
 54:      * Line terminator used for separating header lines.
 55:      *
 56:      * @var string
 57:      */
 58:     public $sep = PHP_EOL;
 59: 
 60:     /**
 61:      * Configuration parameters.
 62:      *
 63:      * @var array
 64:      */
 65:     protected $_params = array();
 66: 
 67:     /**
 68:      * Send a message.
 69:      *
 70:      * @param mixed $recipients  Either a comma-seperated list of recipients
 71:      *                           (RFC822 compliant), or an array of
 72:      *                           recipients, each RFC822 valid. This may
 73:      *                           contain recipients not specified in the
 74:      *                           headers, for Bcc:, resending messages, etc.
 75:      * @param array $headers     The headers to send with the mail, in an
 76:      *                           associative array, where the array key is the
 77:      *                           header name (ie, 'Subject'), and the array
 78:      *                           value is the header value (ie, 'test'). The
 79:      *                           header produced from those values would be
 80:      *                           'Subject: test'.
 81:      *                           If the '_raw' key exists, the value of this
 82:      *                           key will be used as the exact text for
 83:      *                           sending the message.
 84:      * @param mixed $body        The full text of the message body, including
 85:      *                           any Mime parts, etc. Either a string or a
 86:      *                           stream resource.
 87:      *
 88:      * @throws Horde_Mail_Exception
 89:      */
 90:     abstract public function send($recipients, array $headers, $body);
 91: 
 92:     /**
 93:      * Take an array of mail headers and return a string containing text
 94:      * usable in sending a message.
 95:      *
 96:      * @param array $headers  The array of headers to prepare, in an
 97:      *                        associative array, where the array key is the
 98:      *                        header name (ie, 'Subject'), and the array value
 99:      *                        is the header value (ie, 'test'). The header
100:      *                        produced from those values would be 'Subject:
101:      *                        test'.
102:      *                        If the '_raw' key exists, the value of this key
103:      *                        will be used as the exact text for sending the
104:      *                        message.
105:      *
106:      * @return mixed  Returns false if it encounters a bad address; otherwise
107:      *                returns an array containing two elements: Any From:
108:      *                address found in the headers, and the plain text version
109:      *                of the headers.
110:      * @throws Horde_Mail_Exception
111:      */
112:     public function prepareHeaders(array $headers)
113:     {
114:         $from = null;
115:         $lines = array();
116:         $raw = isset($headers['_raw'])
117:             ? $headers['_raw']
118:             : null;
119: 
120:         $parser = new Horde_Mail_Rfc822();
121: 
122:         foreach ($headers as $key => $value) {
123:             if (strcasecmp($key, 'From') === 0) {
124:                 $addresses = $parser->parseAddressList($value, array(
125:                     'nest_groups' => false,
126:                 ));
127:                 $from = $addresses[0]->full_address;
128: 
129:                 // Reject envelope From: addresses with spaces.
130:                 if (strstr($from, ' ')) {
131:                     return false;
132:                 }
133: 
134:                 $lines[] = $key . ': ' . $this->_normalizeEOL($value);
135:             } elseif (!$raw && (strcasecmp($key, 'Received') === 0)) {
136:                 $received = array();
137:                 if (!is_array($value)) {
138:                     $value = array($value);
139:                 }
140: 
141:                 foreach ($value as $line) {
142:                     $received[] = $key . ': ' . $this->_normalizeEOL($line);
143:                 }
144: 
145:                 // Put Received: headers at the top.  Spam detectors often
146:                 // flag messages with Received: headers after the Subject:
147:                 // as spam.
148:                 $lines = array_merge($received, $lines);
149:             } elseif (!$raw) {
150:                 // If $value is an array (i.e., a list of addresses), convert
151:                 // it to a comma-delimited string of its elements (addresses).
152:                 if (is_array($value)) {
153:                     $value = implode(', ', $value);
154:                 }
155:                 $lines[] = $key . ': ' . $this->_normalizeEOL($value);
156:             }
157:         }
158: 
159:         return array($from, $raw ? $raw : implode($this->sep, $lines));
160:     }
161: 
162:     /**
163:      * Take a set of recipients and parse them, returning an array of bare
164:      * addresses (forward paths) that can be passed to sendmail or an SMTP
165:      * server with the 'RCPT TO:' command.
166:      *
167:      * @param mixed  Either a comma-separated list of recipients (RFC822
168:      *               compliant), or an array of recipients, each RFC822 valid.
169:      *
170:      * @return array  Forward paths (bare addresses).
171:      * @throws Horde_Mail_Exception
172:      */
173:     public function parseRecipients($recipients)
174:     {
175:         // if we're passed an array, assume addresses are valid and
176:         // implode them before parsing.
177:         if (is_array($recipients)) {
178:             $recipients = implode(', ', $recipients);
179:         }
180: 
181:         // Parse recipients, leaving out all personal info. This is
182:         // for smtp recipients, etc. All relevant personal information
183:         // should already be in the headers.
184:         $parser = new Horde_Mail_Rfc822();
185:         $addresses = $parser->parseAddressList($recipients, array(
186:             'nest_groups' => false
187:         ));
188: 
189:         $recipients = array();
190: 
191:         foreach ($addresses as $ob) {
192:             $recipients[] = $ob->full_address;
193:         }
194: 
195:         return $recipients;
196:     }
197: 
198:     /**
199:      * Sanitize an array of mail headers by removing any additional header
200:      * strings present in a legitimate header's value.  The goal of this
201:      * filter is to prevent mail injection attacks.
202:      *
203:      * Raw headers are sent as-is.
204:      *
205:      * @param array $headers  The associative array of headers to sanitize.
206:      *
207:      * @return array  The sanitized headers.
208:      */
209:     protected function _sanitizeHeaders($headers)
210:     {
211:         foreach (array_diff(array_keys($headers), array('_raw')) as $key) {
212:             $headers[$key] = preg_replace('=((<CR>|<LF>|0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i', null, $headers[$key]);
213:         }
214: 
215:         return $headers;
216:     }
217: 
218:     /**
219:      * Normalizes EOLs in string data.
220:      *
221:      * @param string $data  Data.
222:      *
223:      * @return string  Normalized data.
224:      */
225:     protected function _normalizeEOL($data)
226:     {
227:         return strtr($data, array(
228:             "\r\n" => $this->sep,
229:             "\r" => $this->sep,
230:             "\n" => $this->sep
231:         ));
232:     }
233: 
234: }
235: 
API documentation generated by ApiGen