Updated PEAR::Mail_mime package

release-0.6
thomascube 18 years ago
parent ab71a531aa
commit ab6f8077e9

@ -1,112 +1,176 @@
<?php <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /**
// +-----------------------------------------------------------------------+ * The Mail_Mime class is used to create MIME E-mail messages
// | Copyright (c) 2002-2003 Richard Heyes | *
// | Copyright (c) 2003-2005 The PHP Group | * The Mail_Mime class provides an OO interface to create MIME
// | All rights reserved. | * enabled email messages. This way you can create emails that
// | | * contain plain-text bodies, HTML bodies, attachments, inline
// | Redistribution and use in source and binary forms, with or without | * images and specific headers.
// | modification, are permitted provided that the following conditions | *
// | are met: | * Compatible with PHP versions 4 and 5
// | | *
// | o Redistributions of source code must retain the above copyright | * LICENSE: This LICENSE is in the BSD license style.
// | notice, this list of conditions and the following disclaimer. | * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
// | o Redistributions in binary form must reproduce the above copyright | * Copyright (c) 2003-2006, PEAR <pear-group@php.net>
// | notice, this list of conditions and the following disclaimer in the | * All rights reserved.
// | documentation and/or other materials provided with the distribution.| *
// | o The names of the authors may not be used to endorse or promote | * Redistribution and use in source and binary forms, with or
// | products derived from this software without specific prior written | * without modification, are permitted provided that the following
// | permission. | * conditions are met:
// | | *
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | * - Redistributions of source code must retain the above copyright
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | * notice, this list of conditions and the following disclaimer.
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | * - Redistributions in binary form must reproduce the above copyright
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | * notice, this list of conditions and the following disclaimer in the
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | * documentation and/or other materials provided with the distribution.
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | * - Neither the name of the authors, nor the names of its contributors
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | * may be used to endorse or promote products derived from this
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | * software without specific prior written permission.
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | *
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// +-----------------------------------------------------------------------+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// | Author: Richard Heyes <richard@phpguru.org> | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// | Tomas V.V.Cox <cox@idecnet.com> (port to PEAR) | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// +-----------------------------------------------------------------------+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// $Id$ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail_Mime
* @author Richard Heyes <richard@phpguru.org>
* @author Tomas V.V. Cox <cox@idecnet.com>
* @author Cipriano Groenendal <cipri@php.net>
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail_mime
* @notes This class is based on HTML Mime Mail class from
* Richard Heyes <richard@phpguru.org> which was based also
* in the mime_mail.class by Tobias Ratschiller <tobias@dnet.it>
* and Sascha Schumann <sascha@schumann.cx>
*/
/**
* require PEAR
*
* This package depends on PEAR to raise errors.
*/
require_once('PEAR.php'); require_once('PEAR.php');
require_once('Mail/mimePart.php');
/** /**
* Mime mail composer class. Can handle: text and html bodies, embedded html * require Mail_mimePart
* images and attachments.
* Documentation and examples of this class are avaible here:
* http://pear.php.net/manual/
* *
* @notes This class is based on HTML Mime Mail class from * Mail_mimePart contains the code required to
* Richard Heyes <richard@phpguru.org> which was based also * create all the different parts a mail can
* in the mime_mail.class by Tobias Ratschiller <tobias@dnet.it> and * consist of.
* Sascha Schumann <sascha@schumann.cx> */
require_once('Mail/mimePart.php');
/**
* The Mail_Mime class provides an OO interface to create MIME
* enabled email messages. This way you can create emails that
* contain plain-text bodies, HTML bodies, attachments, inline
* images and specific headers.
* *
* @author Richard Heyes <richard.heyes@heyes-computing.net> * @category Mail
* @author Tomas V.V.Cox <cox@idecnet.com> * @package Mail_Mime
* @package Mail * @author Richard Heyes <richard@phpguru.org>
* @access public * @author Tomas V.V. Cox <cox@idecnet.com>
* @author Cipriano Groenendal <cipri@php.net>
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/Mail_mime
*/ */
class Mail_mime class Mail_mime
{ {
/** /**
* Contains the plain text part of the email * Contains the plain text part of the email
*
* @var string * @var string
* @access private
*/ */
var $_txtbody; var $_txtbody;
/** /**
* Contains the html part of the email * Contains the html part of the email
*
* @var string * @var string
* @access private
*/ */
var $_htmlbody; var $_htmlbody;
/** /**
* contains the mime encoded text * contains the mime encoded text
*
* @var string * @var string
* @access private
*/ */
var $_mime; var $_mime;
/** /**
* contains the multipart content * contains the multipart content
*
* @var string * @var string
* @access private
*/ */
var $_multipart; var $_multipart;
/** /**
* list of the attached images * list of the attached images
*
* @var array * @var array
* @access private
*/ */
var $_html_images = array(); var $_html_images = array();
/** /**
* list of the attachements * list of the attachements
*
* @var array * @var array
* @access private
*/ */
var $_parts = array(); var $_parts = array();
/** /**
* Build parameters * Build parameters
*
* @var array * @var array
* @access private
*/ */
var $_build_params = array(); var $_build_params = array();
/** /**
* Headers for the mail * Headers for the mail
*
* @var array * @var array
* @access private
*/ */
var $_headers = array(); var $_headers = array();
/** /**
* End Of Line sequence (for serialize) * End Of Line sequence (for serialize)
*
* @var string * @var string
* @access private
*/ */
var $_eol; var $_eol;
/** /**
* Constructor function * Constructor function.
*
* @param string $crlf what type of linebreak to use.
* Defaults to "\r\n"
* @return void
* *
* @access public * @access public
*/ */
@ -125,7 +189,7 @@ class Mail_mime
} }
/** /**
* Wakeup (unserialize) - re-sets EOL constant * wakeup function called by unserialize. It re-sets the EOL constant
* *
* @access private * @access private
*/ */
@ -134,6 +198,7 @@ class Mail_mime
$this->_setEOL($this->_eol); $this->_setEOL($this->_eol);
} }
/** /**
* Accessor function to set the body text. Body text is used if * Accessor function to set the body text. Body text is used if
* it's not an html mail being sent or else is used to fill the * it's not an html mail being sent or else is used to fill the
@ -141,12 +206,12 @@ class Mail_mime
* html should show. * html should show.
* *
* @param string $data Either a string or * @param string $data Either a string or
* the file name with the contents * the file name with the contents
* @param bool $isfile If true the first param should be treated * @param bool $isfile If true the first param should be treated
* as a file name, else as a string (default) * as a file name, else as a string (default)
* @param bool $append If true the text or file is appended to * @param bool $append If true the text or file is appended to
* the existing body, else the old body is * the existing body, else the old body is
* overwritten * overwritten
* @return mixed true on success or PEAR_Error object * @return mixed true on success or PEAR_Error object
* @access public * @access public
*/ */
@ -173,13 +238,13 @@ class Mail_mime
} }
/** /**
* Adds a html part to the mail * Adds a html part to the mail.
* *
* @param string $data Either a string or the file name with the * @param string $data either a string or the file name with the
* contents * contents
* @param bool $isfile If true the first param should be treated * @param bool $isfile a flag that determines whether $data is a
* as a file name, else as a string (default) * filename, or a string(false, default)
* @return mixed true on success or PEAR_Error object * @return bool true on success
* @access public * @access public
*/ */
function setHTMLBody($data, $isfile = false) function setHTMLBody($data, $isfile = false)
@ -197,36 +262,24 @@ class Mail_mime
return true; return true;
} }
/**
* returns the HTML body portion of the message
* @return string HTML body of the message
* @access public
*/
function getHTMLBody()
{
return $this->_htmlbody;
}
/** /**
* Adds an image to the list of embedded images. * Adds an image to the list of embedded images.
* *
* @param string $file The image file name OR image data itself * @param string $file the image file name OR image data itself
* @param string $c_type The content type * @param string $c_type the content type
* @param string $name The filename of the image. * @param string $name the filename of the image.
* Only use if $file is the image data * Only use if $file is the image data.
* @param bool $isfilename Whether $file is a filename or not * @param bool $isfile whether $file is a filename or not.
* Defaults to true * Defaults to true
* @param string $contentid Desired Content-ID of MIME part * @return bool true on success
* Defaults to generated unique ID
* @return mixed true on success or PEAR_Error object
* @access public * @access public
*/ */
function addHTMLImage($file, $c_type='application/octet-stream', function addHTMLImage($file, $c_type='application/octet-stream',
$name = '', $isfilename = true, $contentid = '') $name = '', $isfile = true)
{ {
$filedata = ($isfilename === true) ? $this->_file2str($file) $filedata = ($isfile === true) ? $this->_file2str($file)
: $file; : $file;
if ($isfilename === true) { if ($isfile === true) {
$filename = ($name == '' ? $file : $name); $filename = ($name == '' ? $file : $name);
} else { } else {
$filename = $name; $filename = $name;
@ -234,14 +287,11 @@ class Mail_mime
if (PEAR::isError($filedata)) { if (PEAR::isError($filedata)) {
return $filedata; return $filedata;
} }
if ($contentid == '') {
$contentid = md5(uniqid(time()));
}
$this->_html_images[] = array( $this->_html_images[] = array(
'body' => $filedata, 'body' => $filedata,
'name' => $filename, 'name' => $filename,
'c_type' => $c_type, 'c_type' => $c_type,
'cid' => $contentid 'cid' => md5(uniqid(time()))
); );
return true; return true;
} }
@ -254,7 +304,7 @@ class Mail_mime
* @param string $c_type The content type * @param string $c_type The content type
* @param string $name The filename of the attachment * @param string $name The filename of the attachment
* Only use if $file is the contents * Only use if $file is the contents
* @param bool $isFilename Whether $file is a filename or not * @param bool $isfile Whether $file is a filename or not
* Defaults to true * Defaults to true
* @param string $encoding The type of encoding to use. * @param string $encoding The type of encoding to use.
* Defaults to base64. * Defaults to base64.
@ -269,13 +319,13 @@ class Mail_mime
* @access public * @access public
*/ */
function addAttachment($file, $c_type = 'application/octet-stream', function addAttachment($file, $c_type = 'application/octet-stream',
$name = '', $isfilename = true, $name = '', $isfile = true,
$encoding = 'base64', $encoding = 'base64',
$disposition = 'attachment', $charset = '') $disposition = 'attachment', $charset = '')
{ {
$filedata = ($isfilename === true) ? $this->_file2str($file) $filedata = ($isfile === true) ? $this->_file2str($file)
: $file; : $file;
if ($isfilename === true) { if ($isfile === true) {
// Force the name the user supplied, otherwise use $file // Force the name the user supplied, otherwise use $file
$filename = (!empty($name)) ? $name : $file; $filename = (!empty($name)) ? $name : $file;
} else { } else {
@ -477,7 +527,7 @@ class Mail_mime
$params['encoding'] = $value['encoding']; $params['encoding'] = $value['encoding'];
if ($value['disposition'] != "inline") { if ($value['disposition'] != "inline") {
$fname = array("fname" => $value['name']); $fname = array("fname" => $value['name']);
$fname_enc = $this->_encodeHeaders($fname); $fname_enc = $this->_encodeHeaders($fname, array('head_charset' => $value['charset'] ? $value['charset'] : 'iso-8859-1'));
$params['dfilename'] = $fname_enc['fname']; $params['dfilename'] = $fname_enc['fname'];
} }
if ($value['charset']) { if ($value['charset']) {
@ -796,90 +846,146 @@ class Mail_mime
/** /**
* Encodes a header as per RFC2047 * Encodes a header as per RFC2047
* *
* @param array $input The header data to encode * @param array $input The header data to encode
* @param array $params Extra build parameters
* @return array Encoded data * @return array Encoded data
* @access private * @access private
*/ */
function _encodeHeaders($input) function _encodeHeaders($input, $params = array())
{ {
$maxlen = 73;
$build_params = $this->_build_params;
while (list($key, $value) = each($params)) {
$build_params[$key] = $value;
}
foreach ($input as $hdr_name => $hdr_value) { foreach ($input as $hdr_name => $hdr_value) {
// if header contains e-mail addresses $hdr_vals = preg_split("|(\s)|", $hdr_value, -1, PREG_SPLIT_DELIM_CAPTURE);
if (preg_match('/\s<.+@[a-z0-9\-\.]+\.[a-z]+>/U', $hdr_value)) $hdr_value_out="";
$chunks = $this->_explode_quoted_string(',', $hdr_value); $previous = "";
else foreach ($hdr_vals as $hdr_val){
$chunks = array($hdr_value); if (!trim($hdr_val)){
//whitespace needs to be handled with another string, or it
$hdr_value = ''; //won't show between encoded strings. Prepend this to the next item.
$line_len = 0; $previous .= $hdr_val;
continue;
foreach ($chunks as $i => $value) { }else{
$value = trim($value); $hdr_val = $previous . $hdr_val;
$previous = "";
//This header contains non ASCII chars and should be encoded. }
if (preg_match('#[\x80-\xFF]{1}#', $value)) { if (function_exists('iconv_mime_encode') && preg_match('#[\x80-\xFF]{1}#', $hdr_val)){
$suffix = ''; $imePref = array();
// Don't encode e-mail address if ($build_params['head_encoding'] == 'base64'){
if (preg_match('/(.+)\s(<.+@[a-z0-9\-\.]+>)$/Ui', $value, $matches)) { $imePrefs['scheme'] = 'B';
$value = $matches[1]; }else{
$suffix = ' '.$matches[2]; $imePrefs['scheme'] = 'Q';
} }
$imePrefs['input-charset'] = $build_params['head_charset'];
switch ($this->_build_params['head_encoding']) { $imePrefs['output-charset'] = $build_params['head_charset'];
$hdr_val = iconv_mime_encode($hdr_name, $hdr_val, $imePrefs);
$hdr_val = preg_replace("#^{$hdr_name}\:\ #", "", $hdr_val);
}elseif (preg_match('#[\x80-\xFF]{1}#', $hdr_val)){
//This header contains non ASCII chars and should be encoded.
switch ($build_params['head_encoding']) {
case 'base64': case 'base64':
// Base64 encoding has been selected. //Base64 encoding has been selected.
$mode = 'B';
$encoded = base64_encode($value); //Generate the header using the specified params and dynamicly
//determine the maximum length of such strings.
//75 is the value specified in the RFC. The first -2 is there so
//the later regexp doesn't break any of the translated chars.
//The -2 on the first line-regexp is to compensate for the ": "
//between the header-name and the header value
$prefix = '=?' . $build_params['head_charset'] . '?B?';
$suffix = '?=';
$maxLength = 75 - strlen($prefix . $suffix) - 2;
$maxLength1stLine = $maxLength - strlen($hdr_name) - 2;
//Base64 encode the entire string
$hdr_val = base64_encode($hdr_val);
//This regexp will break base64-encoded text at every
//$maxLength but will not break any encoded letters.
$reg1st = "|.{0,$maxLength1stLine}[^\=][^\=]|";
$reg2nd = "|.{0,$maxLength}[^\=][^\=]|";
break; break;
case 'quoted-printable': case 'quoted-printable':
default: default:
// quoted-printable encoding has been selected //quoted-printable encoding has been selected
$mode = 'Q';
$encoded = preg_replace('/([\x2C\x3F\x80-\xFF])/e', "'='.sprintf('%02X', ord('\\1'))", $value); //Generate the header using the specified params and dynamicly
// replace spaces with _ //determine the maximum length of such strings.
$encoded = str_replace(' ', '_', $encoded); //75 is the value specified in the RFC. The -2 is there so
//the later regexp doesn't break any of the translated chars.
//The -2 on the first line-regexp is to compensate for the ": "
//between the header-name and the header value
$prefix = '=?' . $build_params['head_charset'] . '?Q?';
$suffix = '?=';
$maxLength = 75 - strlen($prefix . $suffix) - 2;
$maxLength1stLine = $maxLength - strlen($hdr_name) - 2;
//Replace all special characters used by the encoder.
$search = array("=", "_", "?", " ");
$replace = array("=3D", "=5F", "=3F", "_");
$hdr_val = str_replace($search, $replace, $hdr_val);
//Replace all extended characters (\x80-xFF) with their
//ASCII values.
$hdr_val = preg_replace(
'#([\x80-\xFF])#e',
'"=" . strtoupper(dechex(ord("\1")))',
$hdr_val
);
//This regexp will break QP-encoded text at every $maxLength
//but will not break any encoded letters.
$reg1st = "|(.{0,$maxLength1stLine})[^\=]|";
$reg2nd = "|(.{0,$maxLength})[^\=]|";
break;
} }
//Begin with the regexp for the first line.
$value = '=?' . $this->_build_params['head_charset'] . '?' . $mode . '?' . $encoded . '?=' . $suffix; $reg = $reg1st;
} //Prevent lins that are just way to short;
if ($maxLength1stLine >1){
// add chunk to output string by regarding the header maxlen $reg = $reg2nd;
$len = strlen($value); }
if ($line_len + $len < $maxlen) { $output = "";
$hdr_value .= ($i>0?', ':'') . $value; while ($hdr_val) {
$line_len += $len + ($i>0?2:0); //Split translated string at every $maxLength
} //But make sure not to break any translated chars.
else { $found = preg_match($reg, $hdr_val, $matches);
$hdr_value .= ($i>0?', ':'') . "\n " . $value;
$line_len = $len; //After this first line, we need to use a different
//regexp for the first line.
$reg = $reg2nd;
//Save the found part and encapsulate it in the
//prefix & suffix. Then remove the part from the
//$hdr_val variable.
if ($found){
$part = $matches[0];
$hdr_val = substr($hdr_val, strlen($matches[0]));
}else{
$part = $hdr_val;
$hdr_val = "";
}
//RFC 2047 specifies that any split header should be seperated
//by a CRLF SPACE.
if ($output){
$output .= "\r\n ";
}
$output .= $prefix . $part . $suffix;
}
$hdr_val = $output;
} }
$hdr_value_out .= $hdr_val;
} }
$input[$hdr_name] = $hdr_value_out;
$input[$hdr_name] = $hdr_value;
} }
return $input; return $input;
} }
function _explode_quoted_string($delimiter, $string)
{
$quotes = explode("\"", $string);
foreach ($quotes as $key => $val)
if (($key % 2) == 1)
$quotes[$key] = str_replace($delimiter, "_!@!_", $quotes[$key]);
$string = implode("\"", $quotes);
$result = explode($delimiter, $string);
foreach ($result as $key => $val)
$result[$key] = str_replace("_!@!_", $delimiter, $result[$key]);
return $result;
}
/** /**
* Set the object's end-of-line and define the constant if applicable * Set the object's end-of-line and define the constant if applicable
* *
@ -897,5 +1003,3 @@ class Mail_mime
} // End of class } // End of class
?>

@ -1,136 +1,149 @@
<?php <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /**
// +-----------------------------------------------------------------------+ * The Mail_mimeDecode class is used to decode mail/mime messages
// | Copyright (c) 2002-2003 Richard Heyes | *
// | Copyright (c) 2003-2005 The PHP Group | * This class will parse a raw mime email and return
// | All rights reserved. | * the structure. Returned structure is similar to
// | | * that returned by imap_fetchstructure().
// | Redistribution and use in source and binary forms, with or without | *
// | modification, are permitted provided that the following conditions | * +----------------------------- IMPORTANT ------------------------------+
// | are met: | * | Usage of this class compared to native php extensions such as |
// | | * | mailparse or imap, is slow and may be feature deficient. If available|
// | o Redistributions of source code must retain the above copyright | * | you are STRONGLY recommended to use the php extensions. |
// | notice, this list of conditions and the following disclaimer. | * +----------------------------------------------------------------------+
// | o Redistributions in binary form must reproduce the above copyright | *
// | notice, this list of conditions and the following disclaimer in the | * Compatible with PHP versions 4 and 5
// | documentation and/or other materials provided with the distribution.| *
// | o The names of the authors may not be used to endorse or promote | * LICENSE: This LICENSE is in the BSD license style.
// | products derived from this software without specific prior written | * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
// | permission. | * Copyright (c) 2003-2006, PEAR <pear-group@php.net>
// | | * All rights reserved.
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | *
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | * Redistribution and use in source and binary forms, with or
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | * without modification, are permitted provided that the following
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | * conditions are met:
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | *
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | * - Redistributions of source code must retain the above copyright
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | * notice, this list of conditions and the following disclaimer.
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | * - Redistributions in binary form must reproduce the above copyright
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * notice, this list of conditions and the following disclaimer in the
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | * documentation and/or other materials provided with the distribution.
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * - Neither the name of the authors, nor the names of its contributors
// | | * may be used to endorse or promote products derived from this
// +-----------------------------------------------------------------------+ * software without specific prior written permission.
// | Author: Richard Heyes <richard@phpguru.org> | *
// +-----------------------------------------------------------------------+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail_Mime
* @author Richard Heyes <richard@phpguru.org>
* @author George Schlossnagle <george@omniti.com>
* @author Cipriano Groenendal <cipri@php.net>
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail_mime
*/
/**
* require PEAR
*
* This package depends on PEAR to raise errors.
*/
require_once 'PEAR.php'; require_once 'PEAR.php';
/** /**
* +----------------------------- IMPORTANT ------------------------------+ * The Mail_mimeDecode class is used to decode mail/mime messages
* | Usage of this class compared to native php extensions such as | *
* | mailparse or imap, is slow and may be feature deficient. If available| * This class will parse a raw mime email and return the structure.
* | you are STRONGLY recommended to use the php extensions. | * Returned structure is similar to that returned by imap_fetchstructure().
* +----------------------------------------------------------------------+ *
* * +----------------------------- IMPORTANT ------------------------------+
* Mime Decoding class * | Usage of this class compared to native php extensions such as |
* * | mailparse or imap, is slow and may be feature deficient. If available|
* This class will parse a raw mime email and return * | you are STRONGLY recommended to use the php extensions. |
* the structure. Returned structure is similar to * +----------------------------------------------------------------------+
* that returned by imap_fetchstructure(). *
* * @category Mail
* USAGE: (assume $input is your raw email) * @package Mail_Mime
* * @author Richard Heyes <richard@phpguru.org>
* $decode = new Mail_mimeDecode($input, "\r\n"); * @author George Schlossnagle <george@omniti.com>
* $structure = $decode->decode(); * @author Cipriano Groenendal <cipri@php.net>
* print_r($structure); * @author Sean Coates <sean@php.net>
* * @copyright 2003-2006 PEAR <pear-group@php.net>
* Or statically: * @license http://www.opensource.org/licenses/bsd-license.php BSD License
* * @version Release: @package_version@
* $params['input'] = $input; * @link http://pear.php.net/package/Mail_mime
* $structure = Mail_mimeDecode::decode($params); */
* print_r($structure);
*
* TODO:
* o UTF8: ???
> 4. We have also found a solution for decoding the UTF-8
> headers. Therefore I made the following function:
>
> function decode_utf8($txt) {
> $trans=array("Å&#8216;"=>"õ","ű"=>"û","Å<>"=>"Ã&#8226;","Å°"
=>"Ã&#8250;");
> $txt=strtr($txt,$trans);
> return(utf8_decode($txt));
> }
>
> And I have inserted the following line to the class:
>
> if (strtolower($charset)=="utf-8") $text=decode_utf8($text);
>
> ... before the following one in the "_decodeHeader" function:
>
> $input = str_replace($encoded, $text, $input);
>
> This way from now on it can easily decode the UTF-8 headers too.
*
* @author Richard Heyes <richard@phpguru.org>
* @version $Revision$
* @package Mail
*/
class Mail_mimeDecode extends PEAR class Mail_mimeDecode extends PEAR
{ {
/** /**
* The raw email to decode * The raw email to decode
*
* @var string * @var string
* @access private
*/ */
var $_input; var $_input;
/** /**
* The header part of the input * The header part of the input
*
* @var string * @var string
* @access private
*/ */
var $_header; var $_header;
/** /**
* The body part of the input * The body part of the input
*
* @var string * @var string
* @access private
*/ */
var $_body; var $_body;
/** /**
* If an error occurs, this is used to store the message * If an error occurs, this is used to store the message
*
* @var string * @var string
* @access private
*/ */
var $_error; var $_error;
/** /**
* Flag to determine whether to include bodies in the * Flag to determine whether to include bodies in the
* returned object. * returned object.
*
* @var boolean * @var boolean
* @access private
*/ */
var $_include_bodies; var $_include_bodies;
/** /**
* Flag to determine whether to decode bodies * Flag to determine whether to decode bodies
*
* @var boolean * @var boolean
* @access private
*/ */
var $_decode_bodies; var $_decode_bodies;
/** /**
* Flag to determine whether to decode headers * Flag to determine whether to decode headers
*
* @var boolean * @var boolean
* @access private
*/ */
var $_decode_headers; var $_decode_headers;
@ -834,4 +847,3 @@ class Mail_mimeDecode extends PEAR
} }
} // End of class } // End of class
?>

@ -1,125 +1,115 @@
<?php <?php
// +-----------------------------------------------------------------------+
// | Copyright (c) 2002-2003 Richard Heyes |
// | All rights reserved. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | o Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | o Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution.|
// | o The names of the authors may not be used to endorse or promote |
// | products derived from this software without specific prior written |
// | permission. |
// | |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
// | |
// +-----------------------------------------------------------------------+
// | Author: Richard Heyes <richard@phpguru.org> |
// +-----------------------------------------------------------------------+
/** /**
* * The Mail_mimePart class is used to create MIME E-mail messages
* Raw mime encoding class *
* * This class enables you to manipulate and build a mime email
* What is it? * from the ground up. The Mail_Mime class is a userfriendly api
* This class enables you to manipulate and build * to this class for people who aren't interested in the internals
* a mime email from the ground up. * of mime mail.
* * This class however allows full control over the email.
* Why use this instead of mime.php? *
* mime.php is a userfriendly api to this class for * Compatible with PHP versions 4 and 5
* people who aren't interested in the internals of *
* mime mail. This class however allows full control * LICENSE: This LICENSE is in the BSD license style.
* over the email. * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
* * Copyright (c) 2003-2006, PEAR <pear-group@php.net>
* Eg. * All rights reserved.
* *
* // Since multipart/mixed has no real body, (the body is * Redistribution and use in source and binary forms, with or
* // the subpart), we set the body argument to blank. * without modification, are permitted provided that the following
* * conditions are met:
* $params['content_type'] = 'multipart/mixed'; *
* $email = new Mail_mimePart('', $params); * - Redistributions of source code must retain the above copyright
* * notice, this list of conditions and the following disclaimer.
* // Here we add a text part to the multipart we have * - Redistributions in binary form must reproduce the above copyright
* // already. Assume $body contains plain text. * notice, this list of conditions and the following disclaimer in the
* * documentation and/or other materials provided with the distribution.
* $params['content_type'] = 'text/plain'; * - Neither the name of the authors, nor the names of its contributors
* $params['encoding'] = '7bit'; * may be used to endorse or promote products derived from this
* $text = $email->addSubPart($body, $params); * software without specific prior written permission.
* *
* // Now add an attachment. Assume $attach is * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* the contents of the attachment * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* $params['content_type'] = 'application/zip'; * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* $params['encoding'] = 'base64'; * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* $params['disposition'] = 'attachment'; * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* $params['dfilename'] = 'example.zip'; * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* $attach =& $email->addSubPart($body, $params); * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* // Now build the email. Note that the encode * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* // function returns an associative array containing two * THE POSSIBILITY OF SUCH DAMAGE.
* // elements, body and headers. You will need to add extra *
* // headers, (eg. Mime-Version) before sending. * @category Mail
* * @package Mail_Mime
* $email = $message->encode(); * @author Richard Heyes <richard@phpguru.org>
* $email['headers'][] = 'Mime-Version: 1.0'; * @author Cipriano Groenendal <cipri@php.net>
* * @author Sean Coates <sean@php.net>
* * @copyright 2003-2006 PEAR <pear-group@php.net>
* Further examples are available at http://www.phpguru.org * @license http://www.opensource.org/licenses/bsd-license.php BSD License
* * @version CVS: $Id$
* TODO: * @link http://pear.php.net/package/Mail_mime
* - Set encode() to return the $obj->encoded if encode() */
* has already been run. Unless a flag is passed to specifically
* re-build the message.
*
* @author Richard Heyes <richard@phpguru.org>
* @version $Revision$
* @package Mail
*/
/**
* The Mail_mimePart class is used to create MIME E-mail messages
*
* This class enables you to manipulate and build a mime email
* from the ground up. The Mail_Mime class is a userfriendly api
* to this class for people who aren't interested in the internals
* of mime mail.
* This class however allows full control over the email.
*
* @category Mail
* @package Mail_Mime
* @author Richard Heyes <richard@phpguru.org>
* @author Cipriano Groenendal <cipri@php.net>
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/Mail_mime
*/
class Mail_mimePart { class Mail_mimePart {
/** /**
* The encoding type of this part * The encoding type of this part
*
* @var string * @var string
* @access private
*/ */
var $_encoding; var $_encoding;
/** /**
* An array of subparts * An array of subparts
*
* @var array * @var array
* @access private
*/ */
var $_subparts; var $_subparts;
/** /**
* The output of this part after being built * The output of this part after being built
*
* @var string * @var string
* @access private
*/ */
var $_encoded; var $_encoded;
/** /**
* Headers for this part * Headers for this part
*
* @var array * @var array
* @access private
*/ */
var $_headers; var $_headers;
/** /**
* The body of this part (not encoded) * The body of this part (not encoded)
*
* @var string * @var string
* @access private
*/ */
var $_body; var $_body;
@ -234,7 +224,7 @@ class Mail_mimePart {
$encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF . $encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF .
implode('--' . $boundary . MAIL_MIMEPART_CRLF, $subparts) . implode('--' . $boundary . MAIL_MIMEPART_CRLF, $subparts) .
'--' . $boundary.'--' . MAIL_MIMEPART_CRLF; '--' . $boundary.'--' . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF;
} else { } else {
$encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding) . MAIL_MIMEPART_CRLF; $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding) . MAIL_MIMEPART_CRLF;
@ -299,7 +289,7 @@ class Mail_mimePart {
} }
/** /**
* quoteadPrintableEncode() * quotedPrintableEncode()
* *
* Encodes data to quoted-printable standard. * Encodes data to quoted-printable standard.
* *
@ -318,11 +308,12 @@ class Mail_mimePart {
while(list(, $line) = each($lines)){ while(list(, $line) = each($lines)){
$linlen = strlen($line); $line = preg_split('||', $line, -1, PREG_SPLIT_NO_EMPTY);
$linlen = count($line);
$newline = ''; $newline = '';
for ($i = 0; $i < $linlen; $i++) { for ($i = 0; $i < $linlen; $i++) {
$char = substr($line, $i, 1); $char = $line[$i];
$dec = ord($char); $dec = ord($char);
if (($dec == 32) AND ($i == ($linlen - 1))){ // convert space at eol only if (($dec == 32) AND ($i == ($linlen - 1))){ // convert space at eol only
@ -348,4 +339,3 @@ class Mail_mimePart {
return $output; return $output;
} }
} // End of class } // End of class
?>

@ -112,7 +112,7 @@ class html2text
"/[\n\t]+/", // Newlines and tabs "/[\n\t]+/", // Newlines and tabs
'/<script[^>]*>.*?<\/script>/i', // <script>s -- which strip_tags supposedly has problems with '/<script[^>]*>.*?<\/script>/i', // <script>s -- which strip_tags supposedly has problems with
//'/<!-- .* -->/', // Comments -- which strip_tags might have problem a with //'/<!-- .* -->/', // Comments -- which strip_tags might have problem a with
'/<a [^>]*href="([^"]+)"[^>]*>(.+?)<\/a>/ie', // <a href=""> '/<a [^>]*href=("|\')([^"\']+)\1[^>]*>(.+?)<\/a>/ie', // <a href="">
'/<h[123][^>]*>(.+?)<\/h[123]>/ie', // H1 - H3 '/<h[123][^>]*>(.+?)<\/h[123]>/ie', // H1 - H3
'/<h[456][^>]*>(.+?)<\/h[456]>/ie', // H4 - H6 '/<h[456][^>]*>(.+?)<\/h[456]>/ie', // H4 - H6
'/<p[^>]*>/i', // <P> '/<p[^>]*>/i', // <P>
@ -161,7 +161,7 @@ class html2text
' ', // Newlines and tabs ' ', // Newlines and tabs
'', // <script>s -- which strip_tags supposedly has problems with '', // <script>s -- which strip_tags supposedly has problems with
//'', // Comments -- which strip_tags might have problem a with //'', // Comments -- which strip_tags might have problem a with
'$this->_build_link_list("\\1", "\\2")', // <a href=""> '$this->_build_link_list("\\2", "\\3")', // <a href="">
"strtoupper(\"\n\n\\1\n\n\")", // H1 - H3 "strtoupper(\"\n\n\\1\n\n\")", // H1 - H3
"ucwords(\"\n\n\\1\n\")", // H4 - H6 "ucwords(\"\n\n\\1\n\")", // H4 - H6
"\n\n", // <P> "\n\n", // <P>

@ -0,0 +1,181 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/lib/rc_mime.inc |
| |
| This file is part of the RoundCube Webmail client |
| Copyright (C) 2007, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
| Extend PEAR:Mail_mime class and override encodeHeaders method |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
$Id: sendmail.inc 506 2007-03-14 00:39:51Z thomasb $
*/
// require Mail_mime class 1.4.0
require_once('Mail/mime.php');
class rc_mail_mime extends Mail_mime
{
/**
* Adds an image to the list of embedded images.
*
* @param string $file The image file name OR image data itself
* @param string $c_type The content type
* @param string $name The filename of the image.
* Only use if $file is the image data
* @param bool $isfilename Whether $file is a filename or not
* Defaults to true
* @param string $contentid Desired Content-ID of MIME part
* Defaults to generated unique ID
* @return mixed true on success or PEAR_Error object
* @access public
*/
function addHTMLImage($file, $c_type='application/octet-stream', $name = '', $isfilename = true, $contentid = '')
{
$filedata = ($isfilename === true) ? $this->_file2str($file) : $file;
if ($isfilename === true)
$filename = ($name == '' ? $file : $name);
else
$filename = $name;
if (PEAR::isError($filedata))
return $filedata;
if ($contentid == '')
$contentid = md5(uniqid(time()));
$this->_html_images[] = array(
'body' => $filedata,
'name' => $filename,
'c_type' => $c_type,
'cid' => $contentid
);
return true;
}
/**
* returns the HTML body portion of the message
* @return string HTML body of the message
* @access public
*/
function getHTMLBody()
{
return $this->_htmlbody;
}
/**
* Encodes a header as per RFC2047
*
* @param array $input The header data to encode
* @param array $params Extra build parameters
* @return array Encoded data
* @access private
* @override
*/
function _encodeHeaders($input, $params = array())
{
$maxlen = 73;
$params += $this->_build_params;
foreach ($input as $hdr_name => $hdr_value)
{
// if header contains e-mail addresses
if (preg_match('/\s<.+@[a-z0-9\-\.]+\.[a-z]+>/U', $hdr_value))
$chunks = $this->_explode_quoted_string(',', $hdr_value);
else
$chunks = array($hdr_value);
$hdr_value = '';
$line_len = 0;
foreach ($chunks as $i => $value)
{
$value = trim($value);
//This header contains non ASCII chars and should be encoded.
if (preg_match('#[\x80-\xFF]{1}#', $value))
{
$suffix = '';
// Don't encode e-mail address
if (preg_match('/(.+)\s(<.+@[a-z0-9\-\.]+>)$/Ui', $value, $matches))
{
$value = $matches[1];
$suffix = ' '.$matches[2];
}
switch ($params['head_encoding'])
{
case 'base64':
// Base64 encoding has been selected.
$mode = 'B';
$encoded = base64_encode($value);
break;
case 'quoted-printable':
default:
// quoted-printable encoding has been selected
$mode = 'Q';
$encoded = preg_replace('/([\x2C\x3F\x80-\xFF])/e', "'='.sprintf('%02X', ord('\\1'))", $value);
// replace spaces with _
$encoded = str_replace(' ', '_', $encoded);
}
$value = '=?' . $params['head_charset'] . '?' . $mode . '?' . $encoded . '?=' . $suffix;
}
// add chunk to output string by regarding the header maxlen
$len = strlen($value);
if ($line_len + $len < $maxlen)
{
$hdr_value .= ($i>0?', ':'') . $value;
$line_len += $len + ($i>0?2:0);
}
else
{
$hdr_value .= ($i>0?', ':'') . "\n " . $value;
$line_len = $len;
}
}
$input[$hdr_name] = $hdr_value;
}
return $input;
}
function _explode_quoted_string($delimiter, $string)
{
$result = array();
$strlen = strlen($string);
for ($q=$p=$i=0; $i < $strlen; $i++)
{
if ($string{$i} == "\"" && $string{$i-1} != "\\")
$q = $q ? false : true;
else if (!$q && $string{$i} == $delimiter)
{
$result[] = substr($string, $p, $i - $p);
$p = $i + 1;
}
}
$result[] = substr($string, $p);
return $result;
}
}
?>

@ -24,7 +24,7 @@
//require_once('lib/smtp.inc'); //require_once('lib/smtp.inc');
require_once('include/rcube_smtp.inc'); require_once('include/rcube_smtp.inc');
require_once('lib/html2text.inc'); require_once('lib/html2text.inc');
require_once('Mail/mime.php'); require_once('lib/rc_mail_mime.inc');
if (!isset($_SESSION['compose']['id'])) if (!isset($_SESSION['compose']['id']))
@ -244,12 +244,12 @@ else if (strtolower(substr(PHP_OS, 0, 3)=='mac'))
else else
$header_delm = "\n"; $header_delm = "\n";
// create PEAR::Mail_mime instance
$isHtmlVal = strtolower(get_input_value('_is_html', RCUBE_INPUT_POST)); $isHtmlVal = strtolower(get_input_value('_is_html', RCUBE_INPUT_POST));
$isHtml = ($isHtmlVal == "1"); $isHtml = ($isHtmlVal == "1");
$MAIL_MIME = new Mail_mime($header_delm); // create extended PEAR::Mail_mime instance
$MAIL_MIME = new rc_mail_mime($header_delm);
// For HTML-formatted messages, construct the MIME message with both // For HTML-formatted messages, construct the MIME message with both
// the HTML part and the plain-text part // the HTML part and the plain-text part
@ -275,13 +275,12 @@ else
// add stored attachments, if any // add stored attachments, if any
if (is_array($_SESSION['compose']['attachments'])) if (is_array($_SESSION['compose']['attachments']))
foreach ($_SESSION['compose']['attachments'] as $attachment) foreach ($_SESSION['compose']['attachments'] as $attachment)
$MAIL_MIME->addAttachment($attachment['path'], $attachment['mimetype'], $attachment['name'], TRUE); $MAIL_MIME->addAttachment($attachment['path'], $attachment['mimetype'], $attachment['name'], true, 'base64', 'attachment', $message_charset);
// add submitted attachments // add submitted attachments
if (is_array($_FILES['_attachments']['tmp_name'])) if (is_array($_FILES['_attachments']['tmp_name']))
foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath)
$MAIL_MIME->addAttachment($filepath, $files['type'][$i], $files['name'][$i], TRUE); $MAIL_MIME->addAttachment($filepath, $files['type'][$i], $files['name'][$i], true, 'base64', 'attachment', $message_charset);
// chose transfer encoding // chose transfer encoding

Loading…
Cancel
Save