Various...

This commit is contained in:
andre.peters
2017-12-09 13:17:15 +01:00
parent 5f5b6652a1
commit adc23d86f9
70 changed files with 6008 additions and 1381 deletions

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Vincent Dauce
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,167 @@
# php-mime-mail-parser
A fully tested mailparse extension wrapper for PHP 5.4+
[![Latest Version](https://img.shields.io/packagist/v/php-mime-mail-parser/php-mime-mail-parser.svg?style=flat-square)](https://github.com/php-mime-mail-parser/php-mime-mail-parser/releases)
[![Total Downloads](https://img.shields.io/packagist/dt/php-mime-mail-parser/php-mime-mail-parser.svg?style=flat-square)](https://packagist.org/packages/php-mime-mail-parser/php-mime-mail-parser)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
## Why?
This extension can be used to...
* Parse and read email from Postfix
* Create webmail
* Store email information such a subject, HTML body, attachments, and etc. into a database
## Is it reliable?
Yes. All known issues have been reproduced, fixed and tested.
We use Travis CI to help ensure code quality. You can see real-time statistics below:
[![Build Status](https://img.shields.io/travis/php-mime-mail-parser/php-mime-mail-parser/master.svg?style=flat-square)](https://travis-ci.org/php-mime-mail-parser/php-mime-mail-parser)
[![Coverage](https://img.shields.io/coveralls/php-mime-mail-parser/php-mime-mail-parser.svg?style=flat-square)](https://coveralls.io/r/php-mime-mail-parser/php-mime-mail-parser)
[![Quality Score](https://img.shields.io/scrutinizer/g/php-mime-mail-parser/php-mime-mail-parser.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-mime-mail-parser/php-mime-mail-parser)
## How do I install it?
The easiest way is via [Composer](https://getcomposer.org/).
To install the latest version of PHP MIME Mail Parser, run the command below:
composer require php-mime-mail-parser/php-mime-mail-parser
## Requirements
The following versions of PHP are supported:
* PHP 5.4
* PHP 5.5
* PHP 5.6
* PHP 7
* HHVM
```
sudo apt install php-cli php-pear php-dev php-mbstring
```
Make sure you have the mailparse extension (http://php.net/manual/en/book.mailparse.php) properly installed. The command line `php -m | grep mailparse` need to return "mailparse" else install it:
* PHP version > 7.0: mailparse
* PHP version < 7.0: mailparse 2.1.6
Follow this steps to install mailparse:
* Compile in the temp folder the extension mailparse or mailparse-2.1.6 (workaround because pecl install doesn't work yet)
```
cd
pecl download mailparse
tar -xvf mailparse-3.0.2.tgz
cd mailparse-3.0.2/
phpize
./configure
sed -i 's/#if\s!HAVE_MBSTRING/#ifndef MBFL_MBFILTER_H/' ./mailparse.c
make
sudo mv modules/mailparse.so /usr/lib/php/20160303/
```
* Add the extension mailparse and activate it
```
echo "extension=mailparse.so" | sudo tee /etc/php/7.1/mods-available/mailparse.ini
sudo phpenmod mailparse
```
On Windows, you need to download mailparse DLL from http://pecl.php.net/package/mailparse and add the line "extension=php_mailparse.dll" to php.ini accordingly.
## How do I use it?
```php
<?php
// Include the library first
require_once __DIR__.'/vendor/autoload.php';
$path = 'path/to/mail.txt';
$Parser = new PhpMimeMailParser\Parser();
// There are four methods available to indicate which mime mail to parse.
// You only need to use one of the following four:
// 1. Specify a file path to the mime mail.
$Parser->setPath($path);
// 2. Specify a php file resource (stream) to the mime mail.
$Parser->setStream(fopen($path, "r"));
// 3. Specify the raw mime mail text.
$Parser->setText(file_get_contents($path));
// 4. Specify a stream to work with mail server
$Parser->setStream(fopen("php://stdin", "r"));
// Once we've indicated where to find the mail, we can parse out the data
$to = $Parser->getHeader('to'); // "test" <test@example.com>, "test2" <test2@example.com>
$addressesTo = $Parser->getAddresses('to'); //Return an array : [[test, test@example.com, false],[test2, test2@example.com, false]]
$from = $Parser->getHeader('from'); // "test" <test@example.com>
$addressesFrom = $Parser->getAddresses('from'); //Return an array : test, test@example.com, false
$subject = $Parser->getHeader('subject');
$text = $Parser->getMessageBody('text');
$html = $Parser->getMessageBody('html');
$htmlEmbedded = $Parser->getMessageBody('htmlEmbedded'); //HTML Body included data
$stringHeaders = $Parser->getHeadersRaw(); // Get all headers as a string, no charset conversion
$arrayHeaders = $Parser->getHeaders(); // Get all headers as an array, with charset conversion
// Pass in a writeable path to save attachments
$attach_dir = '/path/to/save/attachments/'; // Be sure to include the trailing slash
$include_inline = true; // Optional argument to include inline attachments (default: true)
$Parser->saveAttachments($attach_dir [,$include_inline]);
// Get an array of Attachment items from $Parser
$attachments = $Parser->getAttachments([$include_inline]);
// Loop through all the Attachments
if (count($attachments) > 0) {
foreach ($attachments as $attachment) {
echo 'Filename : '.$attachment->getFilename().'<br />'; // logo.jpg
echo 'Filesize : '.filesize($attach_dir.$attachment->getFilename()).'<br />'; // 1000
echo 'Filetype : '.$attachment->getContentType().'<br />'; // image/jpeg
echo 'MIME part string : '.$attachment->getMimePartStr().'<br />'; // (the whole MIME part of the attachment)
}
}
?>
```
Next you need to forward emails to this script above. For that I'm using [Postfix](http://www.postfix.org/) like a mail server, you need to configure /etc/postfix/master.cf
Add this line at the end of the file (specify myhook to send all emails to the script test.php)
```
myhook unix - n n - - pipe
flags=F user=www-data argv=php -c /etc/php5/apache2/php.ini -f /var/www/test.php ${sender} ${size} ${recipient}
```
Edit this line (register myhook)
```
smtp inet n - - - - smtpd
-o content_filter=myhook:dummy
```
The php script must use the fourth method to work with this configuration.
## Can I contribute?
Feel free to contribute!
git clone https://github.com/php-mime-mail-parser/php-mime-mail-parser
cd php-mime-mail-parser
composer install
./vendor/bin/phpunit
If you report an issue, please provide the raw email that triggered it. This helps us reproduce the issue and fix it more quickly.
### License
The php-mime-mail-parser/php-mime-mail-parser is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)

View File

@@ -0,0 +1,61 @@
{
"name": "php-mime-mail-parser/php-mime-mail-parser",
"type": "library",
"description": "Fully Tested Mailparse Extension Wrapper for PHP 5.4+",
"keywords": ["mime", "mail", "mailparse", "MimeMailParser"],
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
"license": "MIT",
"authors": [
{
"name":"eXorus",
"email":"exorus.spam@gmail.com",
"homepage":"https://github.com/eXorus/",
"role":"Developer"
},
{
"name":"M.Valinskis",
"email":"M.Valins@gmail.com",
"homepage":"https://code.google.com/p/php-mime-mail-parser",
"role":"Developer"
},
{
"name":"eugene.emmett.wood",
"email":"gene_w@cementhorizon.com",
"homepage":"https://code.google.com/p/php-mime-mail-parser",
"role":"Developer"
},
{
"name":"alknetso",
"email":"alkne@gmail.com",
"homepage":"https://code.google.com/p/php-mime-mail-parser",
"role":"Developer"
},
{
"name":"bucabay",
"email":"gabe@fijiwebdesign.com",
"homepage":"http://www.fijiwebdesign.com",
"role":"Developer"
}
],
"repository":{
"type":"git",
"url":"https://github.com/php-mime-mail-parser/php-mime-mail-parser.git"
},
"require": {
"php": "^5.4.0 || ^7.0",
"ext-mailparse": "*"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0",
"phpunit/php-token-stream": "^1.3.0",
"satooshi/php-coveralls": "0.*",
"squizlabs/PHP_CodeSniffer": "2.*"
},
"replace": {
"exorus/php-mime-mail-parser": "*",
"messaged/php-mime-mail-parser": "*"
},
"autoload": {
"psr-4": { "PhpMimeMailParser\\": "src/" }
}
}

View File

@@ -0,0 +1,303 @@
<?php
/**
* @link http://php.net/manual/en/mailparse.constants.php
*/
define('MAILPARSE_EXTRACT_OUTPUT', 0);
/**
* @link http://php.net/manual/en/mailparse.constants.php
*/
define('MAILPARSE_EXTRACT_STREAM', 1);
/**
* @link http://php.net/manual/en/mailparse.constants.php
*/
define('MAILPARSE_EXTRACT_RETURN', 2);
/**
* Parses a file. This is the optimal way of parsing a mail file that you have on
* disk.
*
* @link http://php.net/manual/en/functions.mailparse-msg-parse-file.php
*
* @param string $filename Path to the file holding the message. The file is opened
* and streamed through the parser
*
* @return resource Returns a MIME resource representing the structure, or false on error
*/
function mailparse_msg_parse_file($filename)
{
}
/**
* .
*
* @link http://php.net/manual/en/functions.mailparse-msg-get-part.php
*
* @param resource $mimemail A valid MIME resource
* @param string $mimesection
*
* @return resource
*/
function mailparse_msg_get_part($mimemail, $mimesection)
{
}
/**
* .
*
* @link http://php.net/manual/en/functions.mailparse-msg-get-structure.php
*
* @param resource $mimemail A valid MIME resource
*
* @return array
*/
function mailparse_msg_get_structure($mimemail)
{
}
/**
* .
*
* @link http://php.net/manual/en/functions.mailparse-msg-get-part-data.php
*
* @param resource $mimemail A valid MIME resource
*
* @return array
*/
function mailparse_msg_get_part_data($mimemail)
{
}
/**
* .
*
* @link http://php.net/manual/en/functions.mailparse-msg-extract-part.php
*
* @param resource $mimemail A valid MIME resource
* @param string $msgbody
* @param callable $callbackfunc
*
* @return void
*/
function mailparse_msg_extract_part($mimemail, $msgbody, $callbackfunc)
{
}
/**
* Extracts/decodes a message section from the supplied filename.
*
* @link http://php.net/manual/en/functions.mailparse-msg-extract-part-file.php
*
* @param resource $mimemail A valid MIME resource, created with
* mailparse_msg_create
* @param mixed $filename Can be a file name or a valid stream resource
* @param callable $callbackfunc If set, this must be either a valid callback that
* will be passed the extracted section, or null to make this function return the
* extracted section
*
* @return string If $callbackfunc is not null returns true on success
*/
function mailparse_msg_extract_part_file($mimemail, $filename, $callbackfunc = false)
{
}
/**
* .
*
* @link http://php.net/manual/en/functions.mailparse-msg-extract-whole-part-file.php
*
* @param resource $mimemail A valid MIME resource
* @param string $filename
* @param callable $callbackfunc
*
* @return string
*/
function mailparse_msg_extract_whole_part_file($mimemail, $filename, $callbackfunc)
{
}
/**
* Create a MIME mail resource.
*
* @link http://php.net/manual/en/functions.mailparse-msg-create.php
* @return resource Returns a handle that can be used to parse a message
*/
function mailparse_msg_create()
{
}
/**
* Frees a MIME resource.
*
* @link http://php.net/manual/en/functions.mailparse-msg-free.php
*
* @param resource $mimemail A valid MIME resource allocated by
* mailparse_msg_create or mailparse_msg_parse_file
*
* @return bool
*/
function mailparse_msg_free($mimemail)
{
}
/**
* Incrementally parse data into the supplied mime mail resource.
*
* @link http://php.net/manual/en/functions.mailparse-msg-parse.php
*
* @param resource $mimemail A valid MIME resource
* @param string $data
*
* @return bool
*/
function mailparse_msg_parse($mimemail, $data)
{
}
/**
* Parses a RFC 822 compliant recipient list, such as that found in the To: header.
*
* @link http://php.net/manual/en/functions.mailparse-rfc822-parse-addresses.php
*
* @param string $addresses A string containing addresses, like in: Wez Furlong
* wez@example.com, doe@example.com
*
* @return array Returns an array of associative arrays with the following keys for each
* recipient: display The recipient name, for display purpose. If this part is not
* set for a recipient, this key will hold the same value as address. address The
* email address is_group true if the recipient is a newsgroup, false otherwise
*/
function mailparse_rfc822_parse_addresses($addresses)
{
}
/**
* Figures out the best way of encoding the content read from the given file
* pointer.
*
* @link http://php.net/manual/en/functions.mailparse-determine-best-xfer-encoding.php
*
* @param resource $fp A valid file pointer, which must be seek-able
*
* @return string Returns one of the character encodings supported by the mbstring module
*/
function mailparse_determine_best_xfer_encoding($fp)
{
}
/**
* Streams data from the source file pointer, apply $encoding and write to the
* destination file pointer.
*
* @link http://php.net/manual/en/functions.mailparse-stream-encode.php
*
* @param resource $sourcefp A valid file handle. The file is streamed through the
* parser
* @param resource $destfp The destination file handle in which the encoded data
* will be written
* @param string $encoding One of the character encodings supported by the mbstring
* module
*
* @return bool
*/
function mailparse_stream_encode($sourcefp, $destfp, $encoding)
{
}
/**
* Scans the data from the given file pointer and extract each embedded uuencoded
* file into a temporary file.
*
* @link http://php.net/manual/en/functions.mailparse-uudecode-all.php
*
* @param resource $fp A valid file pointer
*
* @return array Returns an array of associative arrays listing filename information.
* filename Path to the temporary file name created origfilename The original
* filename, for uuencoded parts only The first filename entry is the message body.
* The next entries are the decoded uuencoded files
*/
function mailparse_uudecode_all($fp)
{
}
/**
* @return
*/
function mailparse_test()
{
}
class mimemessage
{
/**
* @return
*/
public function mimemessage()
{
}
/**
* @return
*/
public function get_child()
{
}
/**
* @return
*/
public function get_child_count()
{
}
/**
* @return
*/
public function get_parent()
{
}
/**
* @return
*/
public function extract_headers()
{
}
/**
* @return
*/
public function extract_body()
{
}
/**
* @return
*/
public function enum_uue()
{
}
/**
* @return
*/
public function extract_uue()
{
}
/**
* @return
*/
public function remove()
{
}
/**
* @return
*/
public function add_child()
{
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="vendor/autoload.php">
<testsuite name="eXorus PhpMimeMailParser Test Suite">
<directory suffix="Test.php">tests</directory>
</testsuite>
</phpunit>

View File

@@ -0,0 +1,183 @@
<?php
namespace PhpMimeMailParser;
/**
* Attachment of php-mime-mail-parser
*
* Fully Tested Mailparse Extension Wrapper for PHP 5.4+
*
*/
class Attachment
{
/**
* @var string $filename Filename
*/
protected $filename;
/**
* @var string $contentType Mime Type
*/
protected $contentType;
/**
* @var string $content File Content
*/
protected $content;
/**
* @var string $contentDisposition Content-Disposition (attachment or inline)
*/
protected $contentDisposition;
/**
* @var string $contentId Content-ID
*/
protected $contentId;
/**
* @var array $headers An Array of the attachment headers
*/
protected $headers;
/**
* @var resource $stream
*/
protected $stream;
/**
* @var string $mimePartStr
*/
protected $mimePartStr;
/**
* Attachment constructor.
*
* @param string $filename
* @param string $contentType
* @param resource $stream
* @param string $contentDisposition
* @param string $contentId
* @param array $headers
* @param string $mimePartStr
*/
public function __construct(
$filename,
$contentType,
$stream,
$contentDisposition = 'attachment',
$contentId = '',
$headers = [],
$mimePartStr = ''
) {
$this->filename = $filename;
$this->contentType = $contentType;
$this->stream = $stream;
$this->content = null;
$this->contentDisposition = $contentDisposition;
$this->contentId = $contentId;
$this->headers = $headers;
$this->mimePartStr = $mimePartStr;
}
/**
* retrieve the attachment filename
*
* @return string
*/
public function getFilename()
{
return $this->filename;
}
/**
* Retrieve the Attachment Content-Type
*
* @return string
*/
public function getContentType()
{
return $this->contentType;
}
/**
* Retrieve the Attachment Content-Disposition
*
* @return string
*/
public function getContentDisposition()
{
return $this->contentDisposition;
}
/**
* Retrieve the Attachment Content-ID
*
* @return string
*/
public function getContentID()
{
return $this->contentId;
}
/**
* Retrieve the Attachment Headers
*
* @return array
*/
public function getHeaders()
{
return $this->headers;
}
/**
* Get a handle to the stream
*
* @return stream
*/
public function getStream()
{
return $this->stream;
}
/**
* Read the contents a few bytes at a time until completed
* Once read to completion, it always returns false
*
* @param int $bytes (default: 2082)
*
* @return string|bool
*/
public function read($bytes = 2082)
{
return feof($this->stream) ? false : fread($this->stream, $bytes);
}
/**
* Retrieve the file content in one go
* Once you retrieve the content you cannot use MimeMailParser_attachment::read()
*
* @return string
*/
public function getContent()
{
if ($this->content === null) {
fseek($this->stream, 0);
while (($buf = $this->read()) !== false) {
$this->content .= $buf;
}
}
return $this->content;
}
/**
* Get mime part string for this attachment
*
* @return string
*/
public function getMimePartStr()
{
return $this->mimePartStr;
}
}

View File

@@ -0,0 +1,338 @@
<?php namespace PhpMimeMailParser;
use PhpMimeMailParser\Contracts\CharsetManager;
class Charset implements CharsetManager
{
/**
* Charset Aliases
*/
private $charsetAlias = [
'ascii' => 'us-ascii',
'us-ascii' => 'us-ascii',
'ansi_x3.4-1968' => 'us-ascii',
'646' => 'us-ascii',
'iso-8859-1' => 'ISO-8859-1',
'iso-8859-2' => 'ISO-8859-2',
'iso-8859-3' => 'ISO-8859-3',
'iso-8859-4' => 'ISO-8859-4',
'iso-8859-5' => 'ISO-8859-5',
'iso-8859-6' => 'ISO-8859-6',
'iso-8859-6-i' => 'ISO-8859-6-I',
'iso-8859-6-e' => 'ISO-8859-6-E',
'iso-8859-7' => 'ISO-8859-7',
'iso-8859-8' => 'ISO-8859-8',
'iso-8859-8-i' => 'ISO-8859-8',
'iso-8859-8-e' => 'ISO-8859-8-E',
'iso-8859-9' => 'ISO-8859-9',
'iso-8859-10' => 'ISO-8859-10',
'iso-8859-11' => 'ISO-8859-11',
'iso-8859-13' => 'ISO-8859-13',
'iso-8859-14' => 'ISO-8859-14',
'iso-8859-15' => 'ISO-8859-15',
'iso-8859-16' => 'ISO-8859-16',
'iso-ir-111' => 'ISO-IR-111',
'iso-2022-cn' => 'ISO-2022-CN',
'iso-2022-cn-ext' => 'ISO-2022-CN',
'iso-2022-kr' => 'ISO-2022-KR',
'iso-2022-jp' => 'ISO-2022-JP',
'utf-16be' => 'UTF-16BE',
'utf-16le' => 'UTF-16LE',
'utf-16' => 'UTF-16',
'windows-1250' => 'windows-1250',
'windows-1251' => 'windows-1251',
'windows-1252' => 'windows-1252',
'windows-1253' => 'windows-1253',
'windows-1254' => 'windows-1254',
'windows-1255' => 'windows-1255',
'windows-1256' => 'windows-1256',
'windows-1257' => 'windows-1257',
'windows-1258' => 'windows-1258',
'ibm866' => 'IBM866',
'ibm850' => 'IBM850',
'ibm852' => 'IBM852',
'ibm855' => 'IBM855',
'ibm857' => 'IBM857',
'ibm862' => 'IBM862',
'ibm864' => 'IBM864',
'utf-8' => 'UTF-8',
'utf-7' => 'UTF-7',
'shift_jis' => 'Shift_JIS',
'big5' => 'Big5',
'euc-jp' => 'EUC-JP',
'euc-kr' => 'EUC-KR',
'gb2312' => 'GB2312',
'gb18030' => 'gb18030',
'viscii' => 'VISCII',
'koi8-r' => 'KOI8-R',
'koi8_r' => 'KOI8-R',
'cskoi8r' => 'KOI8-R',
'koi' => 'KOI8-R',
'koi8' => 'KOI8-R',
'koi8-u' => 'KOI8-U',
'tis-620' => 'TIS-620',
't.61-8bit' => 'T.61-8bit',
'hz-gb-2312' => 'HZ-GB-2312',
'big5-hkscs' => 'Big5-HKSCS',
'gbk' => 'gbk',
'cns11643' => 'x-euc-tw',
'x-imap4-modified-utf7' => 'x-imap4-modified-utf7',
'x-euc-tw' => 'x-euc-tw',
'x-mac-ce' => 'x-mac-ce',
'x-mac-turkish' => 'x-mac-turkish',
'x-mac-greek' => 'x-mac-greek',
'x-mac-icelandic' => 'x-mac-icelandic',
'x-mac-croatian' => 'x-mac-croatian',
'x-mac-romanian' => 'x-mac-romanian',
'x-mac-cyrillic' => 'x-mac-cyrillic',
'x-mac-ukrainian' => 'x-mac-cyrillic',
'x-mac-hebrew' => 'x-mac-hebrew',
'x-mac-arabic' => 'x-mac-arabic',
'x-mac-farsi' => 'x-mac-farsi',
'x-mac-devanagari' => 'x-mac-devanagari',
'x-mac-gujarati' => 'x-mac-gujarati',
'x-mac-gurmukhi' => 'x-mac-gurmukhi',
'armscii-8' => 'armscii-8',
'x-viet-tcvn5712' => 'x-viet-tcvn5712',
'x-viet-vps' => 'x-viet-vps',
'iso-10646-ucs-2' => 'UTF-16BE',
'x-iso-10646-ucs-2-be' => 'UTF-16BE',
'x-iso-10646-ucs-2-le' => 'UTF-16LE',
'x-user-defined' => 'x-user-defined',
'x-johab' => 'x-johab',
'latin1' => 'ISO-8859-1',
'iso_8859-1' => 'ISO-8859-1',
'iso8859-1' => 'ISO-8859-1',
'iso8859-2' => 'ISO-8859-2',
'iso8859-3' => 'ISO-8859-3',
'iso8859-4' => 'ISO-8859-4',
'iso8859-5' => 'ISO-8859-5',
'iso8859-6' => 'ISO-8859-6',
'iso8859-7' => 'ISO-8859-7',
'iso8859-8' => 'ISO-8859-8',
'iso8859-9' => 'ISO-8859-9',
'iso8859-10' => 'ISO-8859-10',
'iso8859-11' => 'ISO-8859-11',
'iso8859-13' => 'ISO-8859-13',
'iso8859-14' => 'ISO-8859-14',
'iso8859-15' => 'ISO-8859-15',
'iso_8859-1:1987' => 'ISO-8859-1',
'iso-ir-100' => 'ISO-8859-1',
'l1' => 'ISO-8859-1',
'ibm819' => 'ISO-8859-1',
'cp819' => 'ISO-8859-1',
'csisolatin1' => 'ISO-8859-1',
'latin2' => 'ISO-8859-2',
'iso_8859-2' => 'ISO-8859-2',
'iso_8859-2:1987' => 'ISO-8859-2',
'iso-ir-101' => 'ISO-8859-2',
'l2' => 'ISO-8859-2',
'csisolatin2' => 'ISO-8859-2',
'latin3' => 'ISO-8859-3',
'iso_8859-3' => 'ISO-8859-3',
'iso_8859-3:1988' => 'ISO-8859-3',
'iso-ir-109' => 'ISO-8859-3',
'l3' => 'ISO-8859-3',
'csisolatin3' => 'ISO-8859-3',
'latin4' => 'ISO-8859-4',
'iso_8859-4' => 'ISO-8859-4',
'iso_8859-4:1988' => 'ISO-8859-4',
'iso-ir-110' => 'ISO-8859-4',
'l4' => 'ISO-8859-4',
'csisolatin4' => 'ISO-8859-4',
'cyrillic' => 'ISO-8859-5',
'iso_8859-5' => 'ISO-8859-5',
'iso_8859-5:1988' => 'ISO-8859-5',
'iso-ir-144' => 'ISO-8859-5',
'csisolatincyrillic' => 'ISO-8859-5',
'arabic' => 'ISO-8859-6',
'iso_8859-6' => 'ISO-8859-6',
'iso_8859-6:1987' => 'ISO-8859-6',
'iso-ir-127' => 'ISO-8859-6',
'ecma-114' => 'ISO-8859-6',
'asmo-708' => 'ISO-8859-6',
'csisolatinarabic' => 'ISO-8859-6',
'csiso88596i' => 'ISO-8859-6-I',
'csiso88596e' => 'ISO-8859-6-E',
'greek' => 'ISO-8859-7',
'greek8' => 'ISO-8859-7',
'sun_eu_greek' => 'ISO-8859-7',
'iso_8859-7' => 'ISO-8859-7',
'iso_8859-7:1987' => 'ISO-8859-7',
'iso-ir-126' => 'ISO-8859-7',
'elot_928' => 'ISO-8859-7',
'ecma-118' => 'ISO-8859-7',
'csisolatingreek' => 'ISO-8859-7',
'hebrew' => 'ISO-8859-8',
'iso_8859-8' => 'ISO-8859-8',
'visual' => 'ISO-8859-8',
'iso_8859-8:1988' => 'ISO-8859-8',
'iso-ir-138' => 'ISO-8859-8',
'csisolatinhebrew' => 'ISO-8859-8',
'csiso88598i' => 'ISO-8859-8',
'iso-8859-8i' => 'ISO-8859-8',
'logical' => 'ISO-8859-8',
'csiso88598e' => 'ISO-8859-8-E',
'latin5' => 'ISO-8859-9',
'iso_8859-9' => 'ISO-8859-9',
'iso_8859-9:1989' => 'ISO-8859-9',
'iso-ir-148' => 'ISO-8859-9',
'l5' => 'ISO-8859-9',
'csisolatin5' => 'ISO-8859-9',
'unicode-1-1-utf-8' => 'UTF-8',
'utf8' => 'UTF-8',
'x-sjis' => 'Shift_JIS',
'shift-jis' => 'Shift_JIS',
'ms_kanji' => 'Shift_JIS',
'csshiftjis' => 'Shift_JIS',
'windows-31j' => 'Shift_JIS',
'cp932' => 'Shift_JIS',
'sjis' => 'Shift_JIS',
'cseucpkdfmtjapanese' => 'EUC-JP',
'x-euc-jp' => 'EUC-JP',
'csiso2022jp' => 'ISO-2022-JP',
'iso-2022-jp-2' => 'ISO-2022-JP',
'csiso2022jp2' => 'ISO-2022-JP',
'csbig5' => 'Big5',
'cn-big5' => 'Big5',
'x-x-big5' => 'Big5',
'zh_tw-big5' => 'Big5',
'cseuckr' => 'EUC-KR',
'ks_c_5601-1987' => 'EUC-KR',
'iso-ir-149' => 'EUC-KR',
'ks_c_5601-1989' => 'EUC-KR',
'ksc_5601' => 'EUC-KR',
'ksc5601' => 'EUC-KR',
'korean' => 'EUC-KR',
'csksc56011987' => 'EUC-KR',
'5601' => 'EUC-KR',
'windows-949' => 'EUC-KR',
'gb_2312-80' => 'GB2312',
'iso-ir-58' => 'GB2312',
'chinese' => 'GB2312',
'csiso58gb231280' => 'GB2312',
'csgb2312' => 'GB2312',
'zh_cn.euc' => 'GB2312',
'gb_2312' => 'GB2312',
'x-cp1250' => 'windows-1250',
'x-cp1251' => 'windows-1251',
'x-cp1252' => 'windows-1252',
'x-cp1253' => 'windows-1253',
'x-cp1254' => 'windows-1254',
'x-cp1255' => 'windows-1255',
'x-cp1256' => 'windows-1256',
'x-cp1257' => 'windows-1257',
'x-cp1258' => 'windows-1258',
'windows-874' => 'windows-874',
'ibm874' => 'windows-874',
'dos-874' => 'windows-874',
'macintosh' => 'macintosh',
'x-mac-roman' => 'macintosh',
'mac' => 'macintosh',
'csmacintosh' => 'macintosh',
'cp866' => 'IBM866',
'cp-866' => 'IBM866',
'866' => 'IBM866',
'csibm866' => 'IBM866',
'cp850' => 'IBM850',
'850' => 'IBM850',
'csibm850' => 'IBM850',
'cp852' => 'IBM852',
'852' => 'IBM852',
'csibm852' => 'IBM852',
'cp855' => 'IBM855',
'855' => 'IBM855',
'csibm855' => 'IBM855',
'cp857' => 'IBM857',
'857' => 'IBM857',
'csibm857' => 'IBM857',
'cp862' => 'IBM862',
'862' => 'IBM862',
'csibm862' => 'IBM862',
'cp864' => 'IBM864',
'864' => 'IBM864',
'csibm864' => 'IBM864',
'ibm-864' => 'IBM864',
't.61' => 'T.61-8bit',
'iso-ir-103' => 'T.61-8bit',
'csiso103t618bit' => 'T.61-8bit',
'x-unicode-2-0-utf-7' => 'UTF-7',
'unicode-2-0-utf-7' => 'UTF-7',
'unicode-1-1-utf-7' => 'UTF-7',
'csunicode11utf7' => 'UTF-7',
'csunicode' => 'UTF-16BE',
'csunicode11' => 'UTF-16BE',
'iso-10646-ucs-basic' => 'UTF-16BE',
'csunicodeascii' => 'UTF-16BE',
'iso-10646-unicode-latin1' => 'UTF-16BE',
'csunicodelatin1' => 'UTF-16BE',
'iso-10646' => 'UTF-16BE',
'iso-10646-j-1' => 'UTF-16BE',
'latin6' => 'ISO-8859-10',
'iso-ir-157' => 'ISO-8859-10',
'l6' => 'ISO-8859-10',
'csisolatin6' => 'ISO-8859-10',
'iso_8859-15' => 'ISO-8859-15',
'csisolatin9' => 'ISO-8859-15',
'l9' => 'ISO-8859-15',
'ecma-cyrillic' => 'ISO-IR-111',
'csiso111ecmacyrillic' => 'ISO-IR-111',
'csiso2022kr' => 'ISO-2022-KR',
'csviscii' => 'VISCII',
'zh_tw-euc' => 'x-euc-tw',
'iso88591' => 'ISO-8859-1',
'iso88592' => 'ISO-8859-2',
'iso88593' => 'ISO-8859-3',
'iso88594' => 'ISO-8859-4',
'iso88595' => 'ISO-8859-5',
'iso88596' => 'ISO-8859-6',
'iso88597' => 'ISO-8859-7',
'iso88598' => 'ISO-8859-8',
'iso88599' => 'ISO-8859-9',
'iso885910' => 'ISO-8859-10',
'iso885911' => 'ISO-8859-11',
'iso885912' => 'ISO-8859-12',
'iso885913' => 'ISO-8859-13',
'iso885914' => 'ISO-8859-14',
'iso885915' => 'ISO-8859-15',
'tis620' => 'TIS-620',
'cp1250' => 'windows-1250',
'cp1251' => 'windows-1251',
'cp1252' => 'windows-1252',
'cp1253' => 'windows-1253',
'cp1254' => 'windows-1254',
'cp1255' => 'windows-1255',
'cp1256' => 'windows-1256',
'cp1257' => 'windows-1257',
'cp1258' => 'windows-1258',
'x-gbk' => 'gbk',
'windows-936' => 'gbk',
'ansi-1251' => 'windows-1251',
];
/**
* {@inheritdoc}
*/
public function decodeCharset($encodedString, $charset)
{
if (strtolower($charset) == 'utf-8' || strtolower($charset) == 'us-ascii') {
return $encodedString;
} else {
return iconv($this->getCharsetAlias($charset), 'UTF-8//TRANSLIT//IGNORE', $encodedString);
}
}
/**
* {@inheritdoc}
*/
public function getCharsetAlias($charset)
{
$charset = strtolower($charset);
if (array_key_exists($charset, $this->charsetAlias)) {
return $this->charsetAlias[$charset];
} else {
return null;
}
}
}

View File

@@ -0,0 +1,24 @@
<?php namespace PhpMimeMailParser\Contracts;
interface CharsetManager
{
/**
* Decode the string from Charset
*
* @param string $encodedString The string in its original encoded state
* @param string $charset The Charset header of the part.
*
* @return string The decoded string
*/
public function decodeCharset($encodedString, $charset);
/**
* Get charset alias
*
* @param string $charset .
*
* @return string The charset alias
*/
public function getCharsetAlias($charset);
}

View File

@@ -0,0 +1,8 @@
<?php
namespace PhpMimeMailParser;
class Exception extends \RuntimeException
{
}

View File

@@ -0,0 +1,893 @@
<?php
namespace PhpMimeMailParser;
use PhpMimeMailParser\Contracts\CharsetManager;
/**
* Parser of php-mime-mail-parser
*
* Fully Tested Mailparse Extension Wrapper for PHP 5.4+
*
*/
class Parser
{
/**
* Attachment filename argument option for ->saveAttachments().
*/
const ATTACHMENT_DUPLICATE_THROW = 'DuplicateThrow';
const ATTACHMENT_DUPLICATE_SUFFIX = 'DuplicateSuffix';
const ATTACHMENT_RANDOM_FILENAME = 'RandomFilename';
/**
* PHP MimeParser Resource ID
*
* @var resource $resource
*/
protected $resource;
/**
* A file pointer to email
*
* @var resource $stream
*/
protected $stream;
/**
* A text of an email
*
* @var string $data
*/
protected $data;
/**
* Parts of an email
*
* @var array $parts
*/
protected $parts;
/**
* @var CharsetManager object
*/
protected $charset;
/**
* Parser constructor.
*
* @param CharsetManager|null $charset
*/
public function __construct(CharsetManager $charset = null)
{
if ($charset == null) {
$charset = new Charset();
}
$this->charset = $charset;
}
/**
* Free the held resources
*
* @return void
*/
public function __destruct()
{
// clear the email file resource
if (is_resource($this->stream)) {
fclose($this->stream);
}
// clear the MailParse resource
if (is_resource($this->resource)) {
mailparse_msg_free($this->resource);
}
}
/**
* Set the file path we use to get the email text
*
* @param string $path File path to the MIME mail
*
* @return Parser MimeMailParser Instance
*/
public function setPath($path)
{
// should parse message incrementally from file
$this->resource = mailparse_msg_parse_file($path);
$this->stream = fopen($path, 'r');
$this->parse();
return $this;
}
/**
* Set the Stream resource we use to get the email text
*
* @param resource $stream
*
* @return Parser MimeMailParser Instance
* @throws Exception
*/
public function setStream($stream)
{
// streams have to be cached to file first
$meta = @stream_get_meta_data($stream);
if (!$meta || !$meta['mode'] || $meta['mode'][0] != 'r' || $meta['eof']) {
throw new Exception(
'setStream() expects parameter stream to be readable stream resource.'
);
}
/** @var resource $tmp_fp */
$tmp_fp = tmpfile();
if ($tmp_fp) {
while (!feof($stream)) {
fwrite($tmp_fp, fread($stream, 2028));
}
fseek($tmp_fp, 0);
$this->stream = &$tmp_fp;
} else {
throw new Exception(
'Could not create temporary files for attachments. Your tmp directory may be unwritable by PHP.'
);
}
fclose($stream);
$this->resource = mailparse_msg_create();
// parses the message incrementally (low memory usage but slower)
while (!feof($this->stream)) {
mailparse_msg_parse($this->resource, fread($this->stream, 2082));
}
$this->parse();
return $this;
}
/**
* Set the email text
*
* @param string $data
*
* @return Parser MimeMailParser Instance
*/
public function setText($data)
{
if (!$data) {
throw new Exception('You must not call MimeMailParser::setText with an empty string parameter');
}
$this->resource = mailparse_msg_create();
// does not parse incrementally, fast memory hog might explode
mailparse_msg_parse($this->resource, $data);
$this->data = $data;
$this->parse();
return $this;
}
/**
* Parse the Message into parts
*
* @return void
*/
protected function parse()
{
$structure = mailparse_msg_get_structure($this->resource);
$this->parts = [];
foreach ($structure as $part_id) {
$part = mailparse_msg_get_part($this->resource, $part_id);
$this->parts[$part_id] = mailparse_msg_get_part_data($part);
}
}
/**
* Retrieve a specific Email Header, without charset conversion.
*
* @param string $name Header name (case-insensitive)
*
* @return string
* @throws Exception
*/
public function getRawHeader($name)
{
$name = strtolower($name);
if (isset($this->parts[1])) {
$headers = $this->getPart('headers', $this->parts[1]);
return (isset($headers[$name])) ? $headers[$name] : false;
} else {
throw new Exception(
'setPath() or setText() or setStream() must be called before retrieving email headers.'
);
}
}
/**
* Retrieve a specific Email Header
*
* @param string $name Header name (case-insensitive)
*
* @return string
*/
public function getHeader($name)
{
$rawHeader = $this->getRawHeader($name);
if ($rawHeader === false) {
return false;
}
return $this->decodeHeader($rawHeader);
}
/**
* Retrieve all mail headers
*
* @return array
* @throws Exception
*/
public function getHeaders()
{
if (isset($this->parts[1])) {
$headers = $this->getPart('headers', $this->parts[1]);
foreach ($headers as $name => &$value) {
if (is_array($value)) {
foreach ($value as &$v) {
$v = $this->decodeSingleHeader($v);
}
} else {
$value = $this->decodeSingleHeader($value);
}
}
return $headers;
} else {
throw new Exception(
'setPath() or setText() or setStream() must be called before retrieving email headers.'
);
}
}
/**
* Retrieve the raw mail headers as a string
*
* @return string
* @throws Exception
*/
public function getHeadersRaw()
{
if (isset($this->parts[1])) {
return $this->getPartHeader($this->parts[1]);
} else {
throw new Exception(
'setPath() or setText() or setStream() must be called before retrieving email headers.'
);
}
}
/**
* Retrieve the raw Header of a MIME part
*
* @return String
* @param $part Object
* @throws Exception
*/
protected function getPartHeader(&$part)
{
$header = '';
if ($this->stream) {
$header = $this->getPartHeaderFromFile($part);
} elseif ($this->data) {
$header = $this->getPartHeaderFromText($part);
}
return $header;
}
/**
* Retrieve the Header from a MIME part from file
*
* @return String Mime Header Part
* @param $part Array
*/
protected function getPartHeaderFromFile(&$part)
{
$start = $part['starting-pos'];
$end = $part['starting-pos-body'];
fseek($this->stream, $start, SEEK_SET);
$header = fread($this->stream, $end-$start);
return $header;
}
/**
* Retrieve the Header from a MIME part from text
*
* @return String Mime Header Part
* @param $part Array
*/
protected function getPartHeaderFromText(&$part)
{
$start = $part['starting-pos'];
$end = $part['starting-pos-body'];
$header = substr($this->data, $start, $end-$start);
return $header;
}
/**
* Checks whether a given part ID is a child of another part
* eg. an RFC822 attachment may have one or more text parts
*
* @param string $partId
* @param string $parentPartId
* @return bool
*/
protected function partIdIsChildOfPart($partId, $parentPartId)
{
return substr($partId, 0, strlen($parentPartId)) == $parentPartId;
}
/**
* Whether the given part ID is a child of any attachment part in the message.
*
* @param string $checkPartId
* @return bool
*/
protected function partIdIsChildOfAnAttachment($checkPartId)
{
foreach ($this->parts as $partId => $part) {
if ($this->getPart('content-disposition', $part) == 'attachment') {
if ($this->partIdIsChildOfPart($checkPartId, $partId)) {
return true;
}
}
}
return false;
}
/**
* Returns the email message body in the specified format
*
* @param string $type text, html or htmlEmbedded
*
* @return false|string Body or False if not found
* @throws Exception
*/
public function getMessageBody($type = 'text')
{
$body = false;
$mime_types = [
'text' => 'text/plain',
'html' => 'text/html',
'htmlEmbedded' => 'text/html',
];
if (in_array($type, array_keys($mime_types))) {
$part_type = $type === 'htmlEmbedded' ? 'html' : $type;
$inline_parts = $this->getInlineParts($part_type);
$body = empty($inline_parts) ? '' : $inline_parts[0];
} else {
throw new Exception(
'Invalid type specified for getMessageBody(). Expected: text, html or htmlEmbeded.'
);
}
if ($type == 'htmlEmbedded') {
$attachments = $this->getAttachments();
foreach ($attachments as $attachment) {
if ($attachment->getContentID() != '') {
$body = str_replace(
'"cid:'.$attachment->getContentID().'"',
'"'.$this->getEmbeddedData($attachment->getContentID()).'"',
$body
);
}
}
}
return $body;
}
/**
* Returns the embedded data structure
*
* @param string $contentId Content-Id
*
* @return string
*/
protected function getEmbeddedData($contentId)
{
foreach ($this->parts as $part) {
if ($this->getPart('content-id', $part) == $contentId) {
$embeddedData = 'data:';
$embeddedData .= $this->getPart('content-type', $part);
$embeddedData .= ';'.$this->getPart('transfer-encoding', $part);
$embeddedData .= ','.$this->getPartBody($part);
return $embeddedData;
}
}
return '';
}
/**
* Return an array with the following keys display, address, is_group
*
* @param string $name Header name (case-insensitive)
*
* @return array
*/
public function getAddresses($name)
{
$value = $this->getHeader($name);
return mailparse_rfc822_parse_addresses($value);
}
/**
* Returns the attachments contents in order of appearance
*
* @return Attachment[]
*/
public function getInlineParts($type = 'text')
{
$inline_parts = [];
$dispositions = ['inline'];
$mime_types = [
'text' => 'text/plain',
'html' => 'text/html',
];
if (!in_array($type, array_keys($mime_types))) {
throw new Exception('Invalid type specified for getInlineParts(). "type" can either be text or html.');
}
foreach ($this->parts as $partId => $part) {
if ($this->getPart('content-type', $part) == $mime_types[$type]
&& $this->getPart('content-disposition', $part) != 'attachment'
&& !$this->partIdIsChildOfAnAttachment($partId)
) {
$headers = $this->getPart('headers', $part);
$encodingType = array_key_exists('content-transfer-encoding', $headers) ?
$headers['content-transfer-encoding'] : '';
if (is_array($encodingType)) {
$encodingType = $encodingType[0];
}
$undecoded_body = $this->decodeContentTransfer($this->getPartBody($part), $encodingType);
$inline_parts[] = $this->charset->decodeCharset($undecoded_body, $this->getPartCharset($part));
}
}
return $inline_parts;
}
/**
* Returns the attachments contents in order of appearance
*
* @return Attachment[]
*/
public function getAttachments($include_inline = true)
{
$attachments = [];
$dispositions = $include_inline ?
['attachment', 'inline'] :
['attachment'];
$non_attachment_types = ['text/plain', 'text/html'];
$nonameIter = 0;
foreach ($this->parts as $part) {
$disposition = $this->getPart('content-disposition', $part);
$filename = 'noname';
if (isset($part['disposition-filename'])) {
$filename = $this->decodeHeader($part['disposition-filename']);
// Escape all potentially unsafe characters from the filename
$filename = preg_replace('((^\.)|\/|(\.$))', '_', $filename);
} elseif (isset($part['content-name'])) {
// if we have no disposition but we have a content-name, it's a valid attachment.
// we simulate the presence of an attachment disposition with a disposition filename
$filename = $this->decodeHeader($part['content-name']);
// Escape all potentially unsafe characters from the filename
$filename = preg_replace('((^\.)|\/|(\.$))', '_', $filename);
$disposition = 'attachment';
} elseif (in_array($part['content-type'], $non_attachment_types, true)
&& $disposition !== 'attachment') {
// it is a message body, no attachment
continue;
} elseif (substr($part['content-type'], 0, 10) !== 'multipart/') {
// if we cannot get it by getMessageBody(), we assume it is an attachment
$disposition = 'attachment';
}
if (in_array($disposition, $dispositions) === true) {
if ($filename == 'noname') {
$nonameIter++;
$filename = 'noname'.$nonameIter;
}
$headersAttachments = $this->getPart('headers', $part);
$contentidAttachments = $this->getPart('content-id', $part);
$mimePartStr = $this->getPartComplete($part);
$attachments[] = new Attachment(
$filename,
$this->getPart('content-type', $part),
$this->getAttachmentStream($part),
$disposition,
$contentidAttachments,
$headersAttachments,
$mimePartStr
);
}
}
return $attachments;
}
/**
* Save attachments in a folder
*
* @param string $attach_dir directory
* @param bool $include_inline
* @param string $filenameStrategy How to generate attachment filenames
*
* @return array Saved attachments paths
* @throws Exception
*/
public function saveAttachments(
$attach_dir,
$include_inline = true,
$filenameStrategy = self::ATTACHMENT_DUPLICATE_SUFFIX
) {
$attachments = $this->getAttachments($include_inline);
if (empty($attachments)) {
return false;
}
if (!is_dir($attach_dir)) {
mkdir($attach_dir);
}
$attachments_paths = [];
foreach ($attachments as $attachment) {
// Determine filename
switch ($filenameStrategy) {
case self::ATTACHMENT_RANDOM_FILENAME:
$attachment_path = tempnam($attach_dir, '');
break;
case self::ATTACHMENT_DUPLICATE_THROW:
case self::ATTACHMENT_DUPLICATE_SUFFIX:
$attachment_path = $attach_dir . $attachment->getFilename();
break;
default:
throw new Exception('Invalid filename strategy argument provided.');
}
// Handle duplicate filename
if (file_exists($attachment_path)) {
switch ($filenameStrategy) {
case self::ATTACHMENT_DUPLICATE_THROW:
throw new Exception('Could not create file for attachment: duplicate filename.');
case self::ATTACHMENT_DUPLICATE_SUFFIX:
$attachment_path = tempnam($attach_dir, $attachment->getFilename());
break;
}
}
/** @var resource $fp */
if ($fp = fopen($attachment_path, 'w')) {
while ($bytes = $attachment->read()) {
fwrite($fp, $bytes);
}
fclose($fp);
$attachments_paths[] = realpath($attachment_path);
} else {
throw new Exception('Could not write attachments. Your directory may be unwritable by PHP.');
}
}
return $attachments_paths;
}
/**
* Read the attachment Body and save temporary file resource
*
* @param array $part
*
* @return resource Mime Body Part
* @throws Exception
*/
protected function getAttachmentStream(&$part)
{
/** @var resource $temp_fp */
$temp_fp = tmpfile();
$headers = $this->getPart('headers', $part);
$encodingType = array_key_exists('content-transfer-encoding', $headers) ?
$headers['content-transfer-encoding'] : '';
if ($temp_fp) {
if ($this->stream) {
$start = $part['starting-pos-body'];
$end = $part['ending-pos-body'];
fseek($this->stream, $start, SEEK_SET);
$len = $end - $start;
$written = 0;
while ($written < $len) {
$write = $len;
$part = fread($this->stream, $write);
fwrite($temp_fp, $this->decodeContentTransfer($part, $encodingType));
$written += $write;
}
} elseif ($this->data) {
$attachment = $this->decodeContentTransfer($this->getPartBodyFromText($part), $encodingType);
fwrite($temp_fp, $attachment, strlen($attachment));
}
fseek($temp_fp, 0, SEEK_SET);
} else {
throw new Exception(
'Could not create temporary files for attachments. Your tmp directory may be unwritable by PHP.'
);
}
return $temp_fp;
}
/**
* Decode the string from Content-Transfer-Encoding
*
* @param string $encodedString The string in its original encoded state
* @param string $encodingType The encoding type from the Content-Transfer-Encoding header of the part.
*
* @return string The decoded string
*/
protected function decodeContentTransfer($encodedString, $encodingType)
{
$encodingType = strtolower($encodingType);
if ($encodingType == 'base64') {
return base64_decode($encodedString);
} elseif ($encodingType == 'quoted-printable') {
return quoted_printable_decode($encodedString);
} else {
return $encodedString; //8bit, 7bit, binary
}
}
/**
* $input can be a string or array
*
* @param string|array $input
*
* @return string
*/
protected function decodeHeader($input)
{
//Sometimes we have 2 label From so we take only the first
if (is_array($input)) {
return $this->decodeSingleHeader($input[0]);
}
return $this->decodeSingleHeader($input);
}
/**
* Decodes a single header (= string)
*
* @param string $input
*
* @return string
*/
protected function decodeSingleHeader($input)
{
// For each encoded-word...
while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)((\s+)=\?)?/i', $input, $matches)) {
$encoded = $matches[1];
$charset = $matches[2];
$encoding = $matches[3];
$text = $matches[4];
$space = isset($matches[6]) ? $matches[6] : '';
switch (strtolower($encoding)) {
case 'b':
$text = $this->decodeContentTransfer($text, 'base64');
break;
case 'q':
$text = str_replace('_', ' ', $text);
preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
foreach ($matches[1] as $value) {
$text = str_replace('='.$value, chr(hexdec($value)), $text);
}
break;
}
$text = $this->charset->decodeCharset($text, $this->charset->getCharsetAlias($charset));
$input = str_replace($encoded . $space, $text, $input);
}
return $input;
}
/**
* Return the charset of the MIME part
*
* @param array $part
*
* @return string|false
*/
protected function getPartCharset($part)
{
if (isset($part['charset'])) {
return $this->charset->getCharsetAlias($part['charset']);
} else {
return false;
}
}
/**
* Retrieve a specified MIME part
*
* @param string $type
* @param array $parts
*
* @return string|array
*/
protected function getPart($type, $parts)
{
return (isset($parts[$type])) ? $parts[$type] : false;
}
/**
* Retrieve the Body of a MIME part
*
* @param array $part
*
* @return string
*/
protected function getPartBody(&$part)
{
$body = '';
if ($this->stream) {
$body = $this->getPartBodyFromFile($part);
} elseif ($this->data) {
$body = $this->getPartBodyFromText($part);
}
return $body;
}
/**
* Retrieve the Body from a MIME part from file
*
* @param array $part
*
* @return string Mime Body Part
*/
protected function getPartBodyFromFile(&$part)
{
$start = $part['starting-pos-body'];
$end = $part['ending-pos-body'];
$body = '';
if ($end - $start > 0) {
fseek($this->stream, $start, SEEK_SET);
$body = fread($this->stream, $end - $start);
}
return $body;
}
/**
* Retrieve the Body from a MIME part from text
*
* @param array $part
*
* @return string Mime Body Part
*/
protected function getPartBodyFromText(&$part)
{
$start = $part['starting-pos-body'];
$end = $part['ending-pos-body'];
return substr($this->data, $start, $end - $start);
}
/**
* Retrieve the content of a MIME part
*
* @param array $part
*
* @return string
*/
protected function getPartComplete(&$part)
{
$body = '';
if ($this->stream) {
$body = $this->getPartFromFile($part);
} elseif ($this->data) {
$body = $this->getPartFromText($part);
}
return $body;
}
/**
* Retrieve the content from a MIME part from file
*
* @param array $part
*
* @return string Mime Content
*/
protected function getPartFromFile(&$part)
{
$start = $part['starting-pos'];
$end = $part['ending-pos'];
$body = '';
if ($end - $start > 0) {
fseek($this->stream, $start, SEEK_SET);
$body = fread($this->stream, $end - $start);
}
return $body;
}
/**
* Retrieve the content from a MIME part from text
*
* @param array $part
*
* @return string Mime Content
*/
protected function getPartFromText(&$part)
{
$start = $part['starting-pos'];
$end = $part['ending-pos'];
return substr($this->data, $start, $end - $start);
}
/**
* Retrieve the resource
*
* @return resource resource
*/
public function getResource()
{
return $this->resource;
}
/**
* Retrieve the file pointer to email
*
* @return resource stream
*/
public function getStream()
{
return $this->stream;
}
/**
* Retrieve the text of an email
*
* @return string data
*/
public function getData()
{
return $this->data;
}
/**
* Retrieve the parts of an email
*
* @return array parts
*/
public function getParts()
{
return $this->parts;
}
/**
* Retrieve the charset manager object
*
* @return CharsetManager charset
*/
public function getCharset()
{
return $this->charset;
}
}