source: branches/beta/data/module/Mail/mimePart.php @ 14676

Revision 14676, 12.2 KB checked in by adati, 17 years ago (diff)

1.4.0a-betaのマージ

  • Property svn:eol-style set to native
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Copyright (c) 2002-2003  Richard Heyes                                |
4// | All rights reserved.                                                  |
5// |                                                                       |
6// | Redistribution and use in source and binary forms, with or without    |
7// | modification, are permitted provided that the following conditions    |
8// | are met:                                                              |
9// |                                                                       |
10// | o Redistributions of source code must retain the above copyright      |
11// |   notice, this list of conditions and the following disclaimer.       |
12// | o Redistributions in binary form must reproduce the above copyright   |
13// |   notice, this list of conditions and the following disclaimer in the |
14// |   documentation and/or other materials provided with the distribution.|
15// | o The names of the authors may not be used to endorse or promote      |
16// |   products derived from this software without specific prior written  |
17// |   permission.                                                         |
18// |                                                                       |
19// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
20// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
21// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
23// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
25// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
28// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
30// |                                                                       |
31// +-----------------------------------------------------------------------+
32// | Author: Richard Heyes <richard@phpguru.org>                           |
33// +-----------------------------------------------------------------------+
34
35/**
36*
37*  Raw mime encoding class
38*
39* What is it?
40*   This class enables you to manipulate and build
41*   a mime email from the ground up.
42*
43* Why use this instead of mime.php?
44*   mime.php is a userfriendly api to this class for
45*   people who aren't interested in the internals of
46*   mime mail. This class however allows full control
47*   over the email.
48*
49* Eg.
50*
51* // Since multipart/mixed has no real body, (the body is
52* // the subpart), we set the body argument to blank.
53*
54* $params['content_type'] = 'multipart/mixed';
55* $email = new Mail_mimePart('', $params);
56*
57* // Here we add a text part to the multipart we have
58* // already. Assume $body contains plain text.
59*
60* $params['content_type'] = 'text/plain';
61* $params['encoding']     = '7bit';
62* $text = $email->addSubPart($body, $params);
63*
64* // Now add an attachment. Assume $attach is
65* the contents of the attachment
66*
67* $params['content_type'] = 'application/zip';
68* $params['encoding']     = 'base64';
69* $params['disposition']  = 'attachment';
70* $params['dfilename']    = 'example.zip';
71* $attach =& $email->addSubPart($body, $params);
72*
73* // Now build the email. Note that the encode
74* // function returns an associative array containing two
75* // elements, body and headers. You will need to add extra
76* // headers, (eg. Mime-Version) before sending.
77*
78* $email = $message->encode();
79* $email['headers'][] = 'Mime-Version: 1.0';
80*
81*
82* Further examples are available at http://www.phpguru.org
83*
84* TODO:
85*  - Set encode() to return the $obj->encoded if encode()
86*    has already been run. Unless a flag is passed to specifically
87*    re-build the message.
88*
89* @author  Richard Heyes <richard@phpguru.org>
90* @version $Revision: 1.13 $
91* @package Mail
92*/
93
94class Mail_mimePart {
95
96   /**
97    * The encoding type of this part
98    * @var string
99    */
100    var $_encoding;
101
102   /**
103    * An array of subparts
104    * @var array
105    */
106    var $_subparts;
107
108   /**
109    * The output of this part after being built
110    * @var string
111    */
112    var $_encoded;
113
114   /**
115    * Headers for this part
116    * @var array
117    */
118    var $_headers;
119
120   /**
121    * The body of this part (not encoded)
122    * @var string
123    */
124    var $_body;
125
126    /**
127     * Constructor.
128     *
129     * Sets up the object.
130     *
131     * @param $body   - The body of the mime part if any.
132     * @param $params - An associative array of parameters:
133     *                  content_type - The content type for this part eg multipart/mixed
134     *                  encoding     - The encoding to use, 7bit, 8bit, base64, or quoted-printable
135     *                  cid          - Content ID to apply
136     *                  disposition  - Content disposition, inline or attachment
137     *                  dfilename    - Optional filename parameter for content disposition
138     *                  description  - Content description
139     *                  charset      - Character set to use
140     * @access public
141     */
142    function Mail_mimePart($body = '', $params = array())
143    {
144        if (!defined('MAIL_MIMEPART_CRLF')) {
145            define('MAIL_MIMEPART_CRLF', defined('MAIL_MIME_CRLF') ? MAIL_MIME_CRLF : "\r\n", TRUE);
146        }
147
148        foreach ($params as $key => $value) {
149            switch ($key) {
150                case 'content_type':
151                    $headers['Content-Type'] = $value . (isset($charset) ? '; charset="' . $charset . '"' : '');
152                    break;
153
154                case 'encoding':
155                    $this->_encoding = $value;
156                    $headers['Content-Transfer-Encoding'] = $value;
157                    break;
158
159                case 'cid':
160                    $headers['Content-ID'] = '<' . $value . '>';
161                    break;
162
163                case 'disposition':
164                    $headers['Content-Disposition'] = $value . (isset($dfilename) ? '; filename="' . $dfilename . '"' : '');
165                    break;
166
167                case 'dfilename':
168                    if (isset($headers['Content-Disposition'])) {
169                        $headers['Content-Disposition'] .= '; filename="' . $value . '"';
170                    } else {
171                        $dfilename = $value;
172                    }
173                    break;
174
175                case 'description':
176                    $headers['Content-Description'] = $value;
177                    break;
178
179                case 'charset':
180                    if (isset($headers['Content-Type'])) {
181                        $headers['Content-Type'] .= '; charset="' . $value . '"';
182                    } else {
183                        $charset = $value;
184                    }
185                    break;
186            }
187        }
188
189        // Default content-type
190        if (!isset($headers['Content-Type'])) {
191            $headers['Content-Type'] = 'text/plain';
192        }
193
194        //Default encoding
195        if (!isset($this->_encoding)) {
196            $this->_encoding = '7bit';
197        }
198
199        // Assign stuff to member variables
200        $this->_encoded  = array();
201        $this->_headers  = $headers;
202        $this->_body     = $body;
203    }
204
205    /**
206     * encode()
207     *
208     * Encodes and returns the email. Also stores
209     * it in the encoded member variable
210     *
211     * @return An associative array containing two elements,
212     *         body and headers. The headers element is itself
213     *         an indexed array.
214     * @access public
215     */
216    function encode()
217    {
218        $encoded =& $this->_encoded;
219
220        if (!empty($this->_subparts)) {
221            srand((double)microtime()*1000000);
222            $boundary = '=_' . md5(rand() . microtime());
223            $this->_headers['Content-Type'] .= ';' . MAIL_MIMEPART_CRLF . "\t" . 'boundary="' . $boundary . '"';
224
225            // Add body parts to $subparts
226            for ($i = 0; $i < count($this->_subparts); $i++) {
227                $headers = array();
228                $tmp = $this->_subparts[$i]->encode();
229                foreach ($tmp['headers'] as $key => $value) {
230                    $headers[] = $key . ': ' . $value;
231                }
232                $subparts[] = implode(MAIL_MIMEPART_CRLF, $headers) . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF . $tmp['body'];
233            }
234
235            $encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF .
236                               implode('--' . $boundary . MAIL_MIMEPART_CRLF, $subparts) .
237                               '--' . $boundary.'--' . MAIL_MIMEPART_CRLF;
238
239        } else {
240            $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding) . MAIL_MIMEPART_CRLF;
241        }
242
243        // Add headers to $encoded
244        $encoded['headers'] =& $this->_headers;
245
246        return $encoded;
247    }
248
249    /**
250     * &addSubPart()
251     *
252     * Adds a subpart to current mime part and returns
253     * a reference to it
254     *
255     * @param $body   The body of the subpart, if any.
256     * @param $params The parameters for the subpart, same
257     *                as the $params argument for constructor.
258     * @return A reference to the part you just added. It is
259     *         crucial if using multipart/* in your subparts that
260     *         you use =& in your script when calling this function,
261     *         otherwise you will not be able to add further subparts.
262     * @access public
263     */
264    function &addSubPart($body, $params)
265    {
266        $this->_subparts[] = new Mail_mimePart($body, $params);
267        return $this->_subparts[count($this->_subparts) - 1];
268    }
269
270    /**
271     * _getEncodedData()
272     *
273     * Returns encoded data based upon encoding passed to it
274     *
275     * @param $data     The data to encode.
276     * @param $encoding The encoding type to use, 7bit, base64,
277     *                  or quoted-printable.
278     * @access private
279     */
280    function _getEncodedData($data, $encoding)
281    {
282        switch ($encoding) {
283            case '8bit':
284            case '7bit':
285                return $data;
286                break;
287
288            case 'quoted-printable':
289                return $this->_quotedPrintableEncode($data);
290                break;
291
292            case 'base64':
293                return rtrim(chunk_split(base64_encode($data), 76, MAIL_MIMEPART_CRLF));
294                break;
295
296            default:
297                return $data;
298        }
299    }
300
301    /**
302     * quoteadPrintableEncode()
303     *
304     * Encodes data to quoted-printable standard.
305     *
306     * @param $input    The data to encode
307     * @param $line_max Optional max line length. Should
308     *                  not be more than 76 chars
309     *
310     * @access private
311     */
312    function _quotedPrintableEncode($input , $line_max = 76)
313    {
314        $lines  = preg_split("/\r?\n/", $input);
315        $eol    = MAIL_MIMEPART_CRLF;
316        $escape = '=';
317        $output = '';
318
319        while(list(, $line) = each($lines)){
320
321            $linlen     = strlen($line);
322            $newline = '';
323
324            for ($i = 0; $i < $linlen; $i++) {
325                $char = substr($line, $i, 1);
326                $dec  = ord($char);
327
328                if (($dec == 32) AND ($i == ($linlen - 1))){    // convert space at eol only
329                    $char = '=20';
330
331                } elseif(($dec == 9) AND ($i == ($linlen - 1))) {  // convert tab at eol only
332                    $char = '=09';
333                } elseif($dec == 9) {
334                    ; // Do nothing if a tab.
335                } elseif(($dec == 61) OR ($dec < 32 ) OR ($dec > 126)) {
336                    $char = $escape . strtoupper(sprintf('%02s', dechex($dec)));
337                }
338
339                if ((strlen($newline) + strlen($char)) >= $line_max) {        // MAIL_MIMEPART_CRLF is not counted
340                    $output  .= $newline . $escape . $eol;                    // soft line break; " =\r\n" is okay
341                    $newline  = '';
342                }
343                $newline .= $char;
344            } // end of for
345            $output .= $newline . $eol;
346        }
347        $output = substr($output, 0, -1 * strlen($eol)); // Don't want last crlf
348        return $output;
349    }
350} // End of class
351?>
Note: See TracBrowser for help on using the repository browser.