Spade

Mini Shell

Directory:~$ /home/lmsyaran/public_html/joomla4/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ /home/lmsyaran/public_html/joomla4/hdpreplyviaemail.tar

hdpreplyviaemail.php000064400000023413151163263020010616 0ustar00<?php
/**
 * @version        4.3.0
 * @package        Joomla
 * @subpackage     helpdeskpro Pro
 * @author         Tuan Pham Ngoc
 * @copyright      Copyright (C) 2013 - 2021 Ossolution Team
 * @license        GNU/GPL, see LICENSE.php
 */

use Ddeboer\Imap\Search\Date\Since;
use Ddeboer\Imap\Search\Flag\Unanswered;
use Ddeboer\Imap\SearchExpression;
use Ddeboer\Imap\Server;
use EmailReplyParser\Parser\EmailParser;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Plugin\CMSPlugin;
use OSSolution\HelpdeskPro\Site\Helper\Helper as HelpdeskproHelper;

defined('_JEXEC') or die;

class plgSystemHDPReplyViaEmail extends CMSPlugin
{
	/**
	 * Application object.
	 *
	 * @var    JApplicationCms
	 */
	protected $app;

	/**
	 * Database object.
	 *
	 * @var    JDatabaseDriver
	 */
	protected $db;

	/**
	 * Constructor
	 *
	 * @param   object  &$subject  The object to observe
	 * @param   array    $config
	 */
	public function __construct(&$subject, $config = array())
	{
		if (!file_exists(JPATH_ROOT .
'/components/com_helpdeskpro/helpdeskpro.php'))
		{
			return;
		}

		parent::__construct($subject, $config);
	}

	/**
	 * Protect access to articles
	 *
	 * @return void
	 * @throws Exception
	 */
	public function onAfterRoute()
	{
		if (version_compare(PHP_VERSION, '7.2.0', '<'))
		{
			$this->app->enqueueMessage('Reply Via Email Only Works With
PHP 7.2.0+');

			return;
		}

		if (!$this->canRun())
		{
			return;
		}


		//Store last run time
		$db = $this->db;
		$this->params->set('last_run', time());
		$params = $this->params->toString();

		$query = $db->getQuery(true)
			->update('#__extensions')
			->set('params = ' . $db->quote($params))
			->where($db->quoteName('element') . '=' .
$db->quote($this->_name))
			->where($db->quoteName('folder') . '=' .
$db->quote('system'));

		try
		{
			// Lock the tables to prevent multiple plugin executions causing a race
condition
			$db->lockTable('#__extensions');
		}
		catch (Exception $e)
		{
			// If we can't lock the tables it's too risk continuing
execution
			return;
		}

		try
		{
			// Update the plugin parameters
			$result = $db->setQuery($query)->execute();
			$this->clearCacheGroups(array('com_plugins'), array(0,
1));
		}
		catch (Exception $exc)
		{
			// If we failed to execute
			$db->unlockTables();
			$result = false;
		}

		try
		{
			// Unlock the tables after writing
			$db->unlockTables();
		}
		catch (Exception $e)
		{
			// If we can't lock the tables assume we have somehow failed
			$result = false;
		}

		// Abort on failure
		if (!$result)
		{
			return;
		}

		$this->fetNewEmails();
	}

	/**
	 * Fetch emails and create ticket
	 *
	 * @throws Exception
	 */
	private function fetNewEmails()
	{
		require_once JPATH_ROOT .
'/plugins/system/hdpreplyviaemail/lib/vendor/autoload.php';

		$host     = $this->params->get('host');
		$port     = $this->params->get('port', 993);
		$username = $this->params->get('username');
		$password = $this->params->get('password');

		$requiredParams = [$host, $username, $password];

		// Make sure all required parameters are provided before processing it
further
		foreach ($requiredParams as $param)
		{
			if (!strlen(trim($param)))
			{
				return;
			}
		}

		// Attempt to connect to the mailbox
		try
		{
			// $server = new Server('mail.joomdonation.com', 993,
'/imap/ssl/novalidate-cert');
			$server = new Server($host, $port, $this->buildFlags());
			// $connection is instance of \Ddeboer\Imap\Connection
			// $connection =
$server->authenticate('tickets@joomdonation.com',
'#$$A%u^tet*d*');
			$connection = $server->authenticate($username, $password);
		}
		catch (Exception $e)
		{
			$this->logData($e->getMessage());

			// Log the error here
			return;
		}

		$mailbox = $connection->getMailbox('INBOX');

		// Search for emails from yesterday only

		$today     = new DateTimeImmutable();
		$yesterday = $today->sub(new DateInterval('P10D'));

		$date = JFactory::getDate('Now',
JFactory::getConfig()->get('offset'));
		$date->modify('-1 day');

		$search = new SearchExpression();
		$search->addCondition(new Unanswered());
		$search->addCondition(new Since($yesterday));

		$messages = $mailbox->getMessages($search, \SORTDATE);

		// Bootstrap the component
		require_once JPATH_ADMINISTRATOR .
'/components/com_helpdeskpro/init.php';

		// Get component config data
		$config = require JPATH_ADMINISTRATOR .
'/components/com_helpdeskpro/config.php';

		// Creating component container
		$container =
\OSL\Container\Container::getInstance('com_helpdeskpro',
$config);
		$db        = $container->db;
		$query     = $db->getQuery(true);

		$config = HelpdeskproHelper::getConfig();

		$allowedFileTypes = explode('|',
$config->allowed_file_types);

		for ($i = 0, $n = count($allowedFileTypes); $i < $n; $i++)
		{
			$allowedFileTypes[$i] = trim(strtoupper($allowedFileTypes[$i]));
		}

		$ticketIdRegex = '/#(\d+)/';

		/** @var  \OSSolution\HelpdeskPro\Admin\Model\Ticket $model */

		$model = $container->factory->createModel('Ticket', [],
'admin');

		foreach ($messages as $message)
		{
			$subject   = $message->getSubject();
			$body      = $message->getBodyText();
			$fromName  = $message->getFrom()->getName();
			$fromEmail = $message->getFrom()->getAddress();

			$email = (new EmailParser())->parse($body);

			$body = $email->getVisibleText() ?: $body;

			if (preg_match($ticketIdRegex, $subject, $matches))
			{
				$ticketId = (int) $matches[1];
			}
			else
			{
				$ticketId = 0;
			}

			$attachmentsPath = JPATH_ROOT .
'/media/com_helpdeskpro/attachments';
			$attachments     = [];

			foreach ($message->getAttachments() as $attachment)
			{
				$filename                        = $attachment->getFilename();
				$attachments['original_names'][] = $filename;
				$filename                        = File::makeSafe($filename);
				$fileExt                         =
strtoupper(File::getExt($filename));

				if (in_array($fileExt, $allowedFileTypes))
				{
					if (File::exists($attachmentsPath . '/' . $filename))
					{
						$filename = File::stripExt($filename) . '_' . uniqid() .
'.' . $fileExt;
					}

					file_put_contents($attachmentsPath . '/' . $filename,
$attachment->getDecodedContent());

					$attachments['names'][] = $filename;
				}
			}

			$data = [];

			if ($ticketId)
			{
				// Add comment
				$data['ticket_id'] = $ticketId;
				$data['message']   = $body;

				// Try to get user id from email
				$query->clear()
					->select('id')
					->from('#__users')
					->where('email = ' . $db->quote($fromEmail));
				$db->setQuery($query);
				$data['user_id'] = (int) $db->loadResult();

				$model->addTicketComment($data, $attachments);
			}
			elseif ($this->params->get('new_ticket_category_id'))
			{
				// Add a new ticket
				$data['name']        = $fromName;
				$data['email']       = $fromEmail;
				$data['subject']     = $subject;
				$data['message']     = $body;
				$data['category_id'] =
$this->params->get('new_ticket_category_id');

				$model->addNewTicket($data, $attachments);
			}

			// Mark the message as ANSWERED so that it won't be processed next
time
			$message->setFlag('\\ANSWERED');
		}
	}

	/**
	 * Build the flags used for imap connection from plugin parameters
	 *
	 * @return string
	 */
	private function buildFlags()
	{
		$encryption          = $this->params->get('encryption',
'ssl');
		$validateCertificate =
$this->params->get('validate_certificate', 1);

		$flags = ['imap'];

		if ($encryption)
		{
			$flags[] = $encryption;
		}

		if ($validateCertificate)
		{
			$flags[] = 'validate-cert';
		}
		else
		{
			$flags[] = 'novalidate-cert';
		}

		return '/' . implode('/', $flags);
	}

	/**
	 * Clears cache groups. We use it to clear the plugins cache after we
update the last run timestamp.
	 *
	 * @param   array  $clearGroups   The cache groups to clean
	 * @param   array  $cacheClients  The cache clients (site, admin) to
clean
	 *
	 * @return  void
	 *
	 * @since   2.0.4
	 */
	private function clearCacheGroups(array $clearGroups, array $cacheClients
= array(0, 1))
	{
		$conf = JFactory::getConfig();

		foreach ($clearGroups as $group)
		{
			foreach ($cacheClients as $client_id)
			{
				try
				{
					$options = array(
						'defaultgroup' => $group,
						'cachebase'    => ($client_id) ? JPATH_ADMINISTRATOR .
'/cache' :
							$conf->get('cache_path', JPATH_SITE .
'/cache'),
					);
					$cache   = JCache::getInstance('callback', $options);
					$cache->clean();
				}
				catch (Exception $e)
				{
					// Ignore it
				}
			}
		}
	}

	/**
	 * Helper method to write data to a log file, for debuging purpose
	 *
	 * @param   string  $logFile
	 * @param   array   $data
	 * @param   string  $message
	 */
	private function logData($data = [], $message = null)
	{
		$text = '[' . gmdate('m/d/Y g:i A') . '] -
';

		foreach ($data as $key => $value)
		{
			$text .= "$key=$value, ";
		}

		$text .= $message;

		$fp = fopen(__DIR__ . '/logs.txt', 'a');
		fwrite($fp, $text . "\n\n");
		fclose($fp);
	}

	/**
	 * Method to check if the plugin could be run
	 *
	 * @return bool
	 */
	protected function canRun()
	{
		// If trigger secret_code is set, usually from cron-job request, we will
process email-queues immediately
		if (trim($this->params->get('secret_code')))
		{
			if ($this->params->get('secret_code') ==
$this->app->input->getString('secret_code'))
			{
				return true;
			}

			return false;
		}

		$lastRun   = (int) $this->params->get('last_run', 0);
		$now       = time();
		$cacheTime = 1200; // Every 20 minutes

		if (($now - $lastRun) < $cacheTime)
		{
			return false;
		}

		return true;
	}
}
hdpreplyviaemail.xml000064400000005125151163263020010627 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.9.0" type="plugin"
group="system" method="upgrade">
    <name>System - Helpdeskpro Reply Via Email</name>
    <author>Tuan Pham Ngoc</author>
    <authorEmail>tuanpn@joomdonation.com</authorEmail>
    <authorUrl>http://www.joomdonation.com</authorUrl>
    <copyright>Copyright (C) 2013 - 2021 Ossolution
Team</copyright>
    <license>GNU General Public License version 3, or
later</license>
    <creationDate>May 2021</creationDate>
    <version>4.3.0</version>
    <description>Enable and Configure this plugin to allow reply
ticket via email.</description>
    <files>
        <filename
plugin="hdpreplyviaemail">hdpreplyviaemail.php</filename>
        <folder>lib</folder>
    </files>
    <config>
        <fields name="params"
addfieldpath="/administrator/components/com_helpdeskpro/fields">
            <fieldset name="basic">
                <field name="last_run" label="Last Run
Time" type="hidden" readonly="true"
size="30"
                       description="Store Last Run Time of the
plugin"/>
                <field name="new_ticket_category_id"
type="hdpcategory" category_type="1" label="New
Ticket Category"
                       description="Select the category which new
ticket will be created" default="0"/>
                <field name="host" label="Host"
type="text" default="localhost"/>
                <field name="port" label="Port"
type="text" default="993"/>
                <field name="encryption" type="list"
label="Encryption" default="ssl">
                    <option value="ssl">ssl</option>
                    <option value="tls">tls</option>
                    <option
value="notls">notls</option>
                </field>
                <field
                        name="validate_certificate"
                        type="radio"
                        label="Validate Certificates"
                        class="btn-group btn-group-yesno"
                        default="1"
                >
                    <option value="1">JYES</option>
                    <option value="0">JNO</option>
                </field>
                <field name="username"
label="Username" type="text"/>
                <field name="password"
label="Password" type="password"/>
                <field name="secret_code"
type="text" value="" label="Secret Code"
description="Secret Code which is used to compare with the secret_code
variable from the request to determine of the process should be processed.
Usually uses with cron job"/>
            </fieldset>
        </fields>
    </config>
</extension>lib/composer.json000064400000000175151163263020010036
0ustar00{
  "require": {
    "php": ">=7.3.0",
    "ddeboer/imap": "1.11.0",
    "willdurand/email-reply-parser": "2.9.0"
  }
}lib/composer.lock000064400000011303151163263020010010 0ustar00{
    "_readme": [
        "This file locks the dependencies of your project to a known
state",
        "Read more about it at
https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
        "This file is @generated automatically"
    ],
    "content-hash":
"80b24dc22e1bb3829c47171aa96ddcf6",
    "packages": [
        {
            "name": "ddeboer/imap",
            "version": "1.11.0",
            "source": {
                "type": "git",
                "url":
"https://github.com/ddeboer/imap.git",
                "reference":
"a089dfcb9d177f921eb5dadc8d4144a44dff22ee"
            },
            "dist": {
                "type": "zip",
                "url":
"https://api.github.com/repos/ddeboer/imap/zipball/a089dfcb9d177f921eb5dadc8d4144a44dff22ee",
                "reference":
"a089dfcb9d177f921eb5dadc8d4144a44dff22ee",
                "shasum": ""
            },
            "require": {
                "ext-iconv": "*",
                "ext-imap": "*",
                "ext-mbstring": "*",
                "php": "^7.3 || ^8.0"
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer":
"^2.16.7",
                "laminas/laminas-mail": "^2.12.3",
                "phpstan/phpstan": "^0.12.57",
                "phpstan/phpstan-phpunit": "^0.12.16",
                "phpstan/phpstan-strict-rules":
"^0.12.5",
                "phpunit/phpunit": "^9.4.3"
            },
            "type": "library",
            "autoload": {
                "psr-4": {
                    "Ddeboer\\Imap\\": "src/"
                }
            },
            "notification-url":
"https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "David de Boer",
                    "email": "david@ddeboer.nl"
                },
                {
                    "name": "Filippo Tessarotto",
                    "email": "zoeslam@gmail.com"
                },
                {
                    "name": "Community contributors",
                    "homepage":
"https://github.com/ddeboer/imap/graphs/contributors"
                }
            ],
            "description": "Object-oriented IMAP for
PHP",
            "keywords": [
                "email",
                "imap",
                "mail"
            ],
            "funding": [
                {
                    "url":
"https://github.com/Slamdunk",
                    "type": "github"
                },
                {
                    "url":
"https://github.com/ddeboer",
                    "type": "github"
                }
            ],
            "time": "2020-11-30T14:52:49+00:00"
        },
        {
            "name": "willdurand/email-reply-parser",
            "version": "2.9.0",
            "source": {
                "type": "git",
                "url":
"https://github.com/willdurand/EmailReplyParser.git",
                "reference":
"642bec19af70c2bf2f2611301349107fe2e6dd08"
            },
            "dist": {
                "type": "zip",
                "url":
"https://api.github.com/repos/willdurand/EmailReplyParser/zipball/642bec19af70c2bf2f2611301349107fe2e6dd08",
                "reference":
"642bec19af70c2bf2f2611301349107fe2e6dd08",
                "shasum": ""
            },
            "require": {
                "php": ">=5.6.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^4.8.35|^5.7"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.8-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "EmailReplyParser\\":
"src/EmailReplyParser"
                }
            },
            "notification-url":
"https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "William Durand",
                    "email": "will+git@drnd.me"
                }
            ],
            "description": "Port of the cool GitHub's
EmailReplyParser library in PHP",
            "keywords": [
                "email",
                "reply-parser"
            ],
            "time": "2020-03-24T16:04:10+00:00"
        }
    ],
    "packages-dev": [],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": [],
    "prefer-stable": false,
    "prefer-lowest": false,
    "platform": {
        "php": ">=7.3.0"
    },
    "platform-dev": [],
    "plugin-api-version": "1.1.0"
}
lib/vendor/autoload.php000064400000000271151163263020011127
0ustar00<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer/autoload_real.php';

return
ComposerAutoloaderInit29cf158d4ae02e703ea9cc9d1ec80b34::getLoader();
lib/vendor/composer/autoload_classmap.php000064400000000234151163263020014640
0ustar00<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
);
lib/vendor/composer/autoload_namespaces.php000064400000000236151163263020015156
0ustar00<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
);
lib/vendor/composer/autoload_psr4.php000064400000000503151163263020013724
0ustar00<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'EmailReplyParser\\' => array($vendorDir .
'/willdurand/email-reply-parser/src/EmailReplyParser'),
    'Ddeboer\\Imap\\' => array($vendorDir .
'/ddeboer/imap/src'),
);
lib/vendor/composer/autoload_real.php000064400000003527151163263020013770
0ustar00<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInit29cf158d4ae02e703ea9cc9d1ec80b34
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    /**
     * @return \Composer\Autoload\ClassLoader
     */
    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

       
spl_autoload_register(array('ComposerAutoloaderInit29cf158d4ae02e703ea9cc9d1ec80b34',
'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
       
spl_autoload_unregister(array('ComposerAutoloaderInit29cf158d4ae02e703ea9cc9d1ec80b34',
'loadClassLoader'));

        $useStaticLoader = PHP_VERSION_ID >= 50600 &&
!defined('HHVM_VERSION') &&
(!function_exists('zend_loader_file_encoded') ||
!zend_loader_file_encoded());
        if ($useStaticLoader) {
            require_once __DIR__ . '/autoload_static.php';

           
call_user_func(\Composer\Autoload\ComposerStaticInit29cf158d4ae02e703ea9cc9d1ec80b34::getInitializer($loader));
        } else {
            $map = require __DIR__ . '/autoload_namespaces.php';
            foreach ($map as $namespace => $path) {
                $loader->set($namespace, $path);
            }

            $map = require __DIR__ . '/autoload_psr4.php';
            foreach ($map as $namespace => $path) {
                $loader->setPsr4($namespace, $path);
            }

            $classMap = require __DIR__ .
'/autoload_classmap.php';
            if ($classMap) {
                $loader->addClassMap($classMap);
            }
        }

        $loader->register(true);

        return $loader;
    }
}
lib/vendor/composer/autoload_static.php000064400000002125151163263020014325
0ustar00<?php

// autoload_static.php @generated by Composer

namespace Composer\Autoload;

class ComposerStaticInit29cf158d4ae02e703ea9cc9d1ec80b34
{
    public static $prefixLengthsPsr4 = array (
        'E' => 
        array (
            'EmailReplyParser\\' => 17,
        ),
        'D' => 
        array (
            'Ddeboer\\Imap\\' => 13,
        ),
    );

    public static $prefixDirsPsr4 = array (
        'EmailReplyParser\\' => 
        array (
            0 => __DIR__ . '/..' .
'/willdurand/email-reply-parser/src/EmailReplyParser',
        ),
        'Ddeboer\\Imap\\' => 
        array (
            0 => __DIR__ . '/..' .
'/ddeboer/imap/src',
        ),
    );

    public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 =
ComposerStaticInit29cf158d4ae02e703ea9cc9d1ec80b34::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 =
ComposerStaticInit29cf158d4ae02e703ea9cc9d1ec80b34::$prefixDirsPsr4;

        }, null, ClassLoader::class);
    }
}
lib/vendor/composer/ClassLoader.php000064400000033120151163263020013341
0ustar00<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component',
__DIR__.'/component');
 *     $loader->add('Symfony',          
__DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for
instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @see    http://www.php-fig.org/psr/psr-0/
 * @see    http://www.php-fig.org/psr/psr-4/
 */
class ClassLoader
{
    // PSR-4
    private $prefixLengthsPsr4 = array();
    private $prefixDirsPsr4 = array();
    private $fallbackDirsPsr4 = array();

    // PSR-0
    private $prefixesPsr0 = array();
    private $fallbackDirsPsr0 = array();

    private $useIncludePath = false;
    private $classMap = array();
    private $classMapAuthoritative = false;
    private $missingClasses = array();
    private $apcuPrefix;

    public function getPrefixes()
    {
        if (!empty($this->prefixesPsr0)) {
            return call_user_func_array('array_merge',
$this->prefixesPsr0);
        }

        return array();
    }

    public function getPrefixesPsr4()
    {
        return $this->prefixDirsPsr4;
    }

    public function getFallbackDirs()
    {
        return $this->fallbackDirsPsr0;
    }

    public function getFallbackDirsPsr4()
    {
        return $this->fallbackDirsPsr4;
    }

    public function getClassMap()
    {
        return $this->classMap;
    }

    /**
     * @param array $classMap Class to filename map
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap,
$classMap);
        } else {
            $this->classMap = $classMap;
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix, either
     * appending or prepending to the ones previously set for this prefix.
     *
     * @param string       $prefix  The prefix
     * @param array|string $paths   The PSR-0 root directories
     * @param bool         $prepend Whether to prepend the directories
     */
    public function add($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirsPsr0 = array_merge(
                    (array) $paths,
                    $this->fallbackDirsPsr0
                );
            } else {
                $this->fallbackDirsPsr0 = array_merge(
                    $this->fallbackDirsPsr0,
                    (array) $paths
                );
            }

            return;
        }

        $first = $prefix[0];
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
            $this->prefixesPsr0[$first][$prefix] = (array) $paths;

            return;
        }
        if ($prepend) {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                (array) $paths,
                $this->prefixesPsr0[$first][$prefix]
            );
        } else {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $this->prefixesPsr0[$first][$prefix],
                (array) $paths
            );
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace, either
     * appending or prepending to the ones previously set for this
namespace.
     *
     * @param string       $prefix  The prefix/namespace, with trailing
'\\'
     * @param array|string $paths   The PSR-4 base directories
     * @param bool         $prepend Whether to prepend the directories
     *
     * @throws \InvalidArgumentException
     */
    public function addPsr4($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                $this->fallbackDirsPsr4 = array_merge(
                    (array) $paths,
                    $this->fallbackDirsPsr4
                );
            } else {
                $this->fallbackDirsPsr4 = array_merge(
                    $this->fallbackDirsPsr4,
                    (array) $paths
                );
            }
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4
prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                (array) $paths,
                $this->prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $this->prefixDirsPsr4[$prefix],
                (array) $paths
            );
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix,
     * replacing any others previously set for this prefix.
     *
     * @param string       $prefix The prefix
     * @param array|string $paths  The PSR-0 base directories
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr0 = (array) $paths;
        } else {
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace,
     * replacing any others previously set for this namespace.
     *
     * @param string       $prefix The prefix/namespace, with trailing
'\\'
     * @param array|string $paths  The PSR-4 base directories
     *
     * @throws \InvalidArgumentException
     */
    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4
prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }

    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to
check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Turns off searching the prefix and fallback directories for classes
     * that have not been registered with the class map.
     *
     * @param bool $classMapAuthoritative
     */
    public function setClassMapAuthoritative($classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }

    /**
     * Should class lookup fail if not found in the current class map?
     *
     * @return bool
     */
    public function isClassMapAuthoritative()
    {
        return $this->classMapAuthoritative;
    }

    /**
     * APCu prefix to use to cache found/not-found classes, if the
extension is enabled.
     *
     * @param string|null $apcuPrefix
     */
    public function setApcuPrefix($apcuPrefix)
    {
        $this->apcuPrefix = function_exists('apcu_fetch')
&& filter_var(ini_get('apc.enabled'),
FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
    }

    /**
     * The APCu prefix in use, or null if APCu caching is not enabled.
     *
     * @return string|null
     */
    public function getApcuPrefix()
    {
        return $this->apcuPrefix;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true,
$prepend);
    }

    /**
     * Unregisters this instance as an autoloader.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return bool|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            includeFile($file);

            return true;
        }
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative ||
isset($this->missingClasses[$class])) {
            return false;
        }
        if (null !== $this->apcuPrefix) {
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
            if ($hit) {
                return $file;
            }
        }

        $file = $this->findFileWithExtension($class, '.php');

        // Search for Hack files if we are running on HHVM
        if (false === $file && defined('HHVM_VERSION'))
{
            $file = $this->findFileWithExtension($class,
'.hh');
        }

        if (null !== $this->apcuPrefix) {
            apcu_add($this->apcuPrefix.$class, $file);
        }

        if (false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = true;
        }

        return $file;
    }

    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\\',
DIRECTORY_SEPARATOR) . $ext;

        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            $subPath = $class;
            while (false !== $lastPos = strrpos($subPath, '\\'))
{
                $subPath = substr($subPath, 0, $lastPos);
                $search = $subPath . '\\';
                if (isset($this->prefixDirsPsr4[$search])) {
                    $pathEnd = DIRECTORY_SEPARATOR .
substr($logicalPathPsr4, $lastPos + 1);
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
                        if (file_exists($file = $dir . $pathEnd)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR .
$logicalPathPsr4)) {
                return $file;
            }
        }

        // PSR-0 lookup
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), '_',
DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_',
DIRECTORY_SEPARATOR) . $ext;
        }

        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs)
{
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR
. $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR .
$logicalPathPsr0)) {
                return $file;
            }
        }

        // PSR-0 include paths.
        if ($this->useIncludePath && $file =
stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }

        return false;
    }
}

/**
 * Scope isolated include.
 *
 * Prevents access to $this/self from included files.
 */
function includeFile($file)
{
    include $file;
}
lib/vendor/composer/installed.json000064400000007443151163263020013317
0ustar00[
    {
        "name": "ddeboer/imap",
        "version": "1.11.0",
        "version_normalized": "1.11.0.0",
        "source": {
            "type": "git",
            "url":
"https://github.com/ddeboer/imap.git",
            "reference":
"a089dfcb9d177f921eb5dadc8d4144a44dff22ee"
        },
        "dist": {
            "type": "zip",
            "url":
"https://api.github.com/repos/ddeboer/imap/zipball/a089dfcb9d177f921eb5dadc8d4144a44dff22ee",
            "reference":
"a089dfcb9d177f921eb5dadc8d4144a44dff22ee",
            "shasum": ""
        },
        "require": {
            "ext-iconv": "*",
            "ext-imap": "*",
            "ext-mbstring": "*",
            "php": "^7.3 || ^8.0"
        },
        "require-dev": {
            "friendsofphp/php-cs-fixer": "^2.16.7",
            "laminas/laminas-mail": "^2.12.3",
            "phpstan/phpstan": "^0.12.57",
            "phpstan/phpstan-phpunit": "^0.12.16",
            "phpstan/phpstan-strict-rules": "^0.12.5",
            "phpunit/phpunit": "^9.4.3"
        },
        "time": "2020-11-30T14:52:49+00:00",
        "type": "library",
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "Ddeboer\\Imap\\": "src/"
            }
        },
        "notification-url":
"https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "David de Boer",
                "email": "david@ddeboer.nl"
            },
            {
                "name": "Filippo Tessarotto",
                "email": "zoeslam@gmail.com"
            },
            {
                "name": "Community contributors",
                "homepage":
"https://github.com/ddeboer/imap/graphs/contributors"
            }
        ],
        "description": "Object-oriented IMAP for PHP",
        "keywords": [
            "email",
            "imap",
            "mail"
        ],
        "funding": [
            {
                "url": "https://github.com/Slamdunk",
                "type": "github"
            },
            {
                "url": "https://github.com/ddeboer",
                "type": "github"
            }
        ]
    },
    {
        "name": "willdurand/email-reply-parser",
        "version": "2.9.0",
        "version_normalized": "2.9.0.0",
        "source": {
            "type": "git",
            "url":
"https://github.com/willdurand/EmailReplyParser.git",
            "reference":
"642bec19af70c2bf2f2611301349107fe2e6dd08"
        },
        "dist": {
            "type": "zip",
            "url":
"https://api.github.com/repos/willdurand/EmailReplyParser/zipball/642bec19af70c2bf2f2611301349107fe2e6dd08",
            "reference":
"642bec19af70c2bf2f2611301349107fe2e6dd08",
            "shasum": ""
        },
        "require": {
            "php": ">=5.6.0"
        },
        "require-dev": {
            "phpunit/phpunit": "^4.8.35|^5.7"
        },
        "time": "2020-03-24T16:04:10+00:00",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.8-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-4": {
                "EmailReplyParser\\":
"src/EmailReplyParser"
            }
        },
        "notification-url":
"https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "William Durand",
                "email": "will+git@drnd.me"
            }
        ],
        "description": "Port of the cool GitHub's
EmailReplyParser library in PHP",
        "keywords": [
            "email",
            "reply-parser"
        ]
    }
]
lib/vendor/composer/LICENSE000064400000002103151163263020011436 0ustar00
Copyright (c) Nils Adermann, Jordi Boggiano

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.

lib/vendor/ddeboer/imap/CHANGELOG.md000064400000116454151163263020012764
0ustar00# Changelog

## [1.11.0](https://github.com/ddeboer/imap/tree/1.11.0) (2020-11-30)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.10.1...1.11.0)

**Implemented enhancements:**

- PHP 8 Compatibility [\#481](https://github.com/ddeboer/imap/issues/481)
- \[GA\] PHP 8 compatibility fix
[\#483](https://github.com/ddeboer/imap/pull/483)
([Slamdunk](https://github.com/Slamdunk))
- Support PHP 8.0, require PHP 7.3
[\#482](https://github.com/ddeboer/imap/pull/482)
([Slamdunk](https://github.com/Slamdunk))

**Fixed bugs:**

- Fix: Outlook date format
[\#480](https://github.com/ddeboer/imap/pull/480)
([gajosadrian](https://github.com/gajosadrian))

**Closed issues:**

- Closing Connection [\#479](https://github.com/ddeboer/imap/issues/479)
- Problem with charset of message part / DataPartInfo
[\#475](https://github.com/ddeboer/imap/issues/475)
- Unsupported charset "X-UNKNOWN"
[\#425](https://github.com/ddeboer/imap/issues/425)

## [1.10.1](https://github.com/ddeboer/imap/tree/1.10.1) (2020-08-26)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.10.0...1.10.1)

**Fixed bugs:**

- getThread and getMessageSequence not using with the same id
[\#469](https://github.com/ddeboer/imap/issues/469)
- imap\_thread: use absolude ids
[\#474](https://github.com/ddeboer/imap/pull/474)
([Slamdunk](https://github.com/Slamdunk))

**Closed issues:**

- How to get a message by Message-ID
[\#472](https://github.com/ddeboer/imap/issues/472)
- Mail with e-sign [\#467](https://github.com/ddeboer/imap/issues/467)
- Duplicate method definition in MessageInterface
[\#455](https://github.com/ddeboer/imap/issues/455)
- Missed errors in search method
[\#444](https://github.com/ddeboer/imap/issues/444)

**Merged pull requests:**

- Subtype not always present
[\#473](https://github.com/ddeboer/imap/pull/473)
([Piskvor](https://github.com/Piskvor))
- Improved error handling for message search method
[\#445](https://github.com/ddeboer/imap/pull/445)
([ikarol](https://github.com/ikarol))

## [1.10.0](https://github.com/ddeboer/imap/tree/1.10.0) (2020-01-24)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.9.0...1.10.0)

**Implemented enhancements:**

- Handle comments \(CFWS\) in Date header + not-valid formats
[\#439](https://github.com/ddeboer/imap/pull/439)
([pupaxxo](https://github.com/pupaxxo))
- Support PHP 7.4, require PHP 7.2
[\#433](https://github.com/ddeboer/imap/pull/433)
([Slamdunk](https://github.com/Slamdunk))

**Closed issues:**

- Invalid Date header when trying to fetching date on not RFC compliant
emails [\#438](https://github.com/ddeboer/imap/issues/438)

**Merged pull requests:**

- Clear the last used mailbox cache when closing a connection
[\#447](https://github.com/ddeboer/imap/pull/447)
([dhzavann](https://github.com/dhzavann))
- README: update PHP version to match composer.json
[\#441](https://github.com/ddeboer/imap/pull/441)
([Slamdunk](https://github.com/Slamdunk))
- Typo [\#440](https://github.com/ddeboer/imap/pull/440)
([OskarStark](https://github.com/OskarStark))

## [1.9.0](https://github.com/ddeboer/imap/tree/1.9.0) (2019-11-25)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.8.0...1.9.0)

**Implemented enhancements:**

- Quota: let's also test the numbers
[\#431](https://github.com/ddeboer/imap/pull/431)
([Slamdunk](https://github.com/Slamdunk))
- Add getQuota method using imap\_get\_quotaroot to Connection class
[\#430](https://github.com/ddeboer/imap/pull/430)
([arkadiusjonczek](https://github.com/arkadiusjonczek))

**Closed issues:**

- markAsSeen\(\)  not work
[\#415](https://github.com/ddeboer/imap/issues/415)

**Merged pull requests:**

- CS Fix: strip redundant php docs
[\#428](https://github.com/ddeboer/imap/pull/428)
([Slamdunk](https://github.com/Slamdunk))
- Fix: Variable name [\#412](https://github.com/ddeboer/imap/pull/412)
([localheinz](https://github.com/localheinz))

## [1.8.0](https://github.com/ddeboer/imap/tree/1.8.0) (2019-04-15)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.2...1.8.0)

**Implemented enhancements:**

- Add phpstan-strict-rules, expose PartiInterface::getDescription\(\)
[\#409](https://github.com/ddeboer/imap/pull/409)
([Slamdunk](https://github.com/Slamdunk))

## [1.7.2](https://github.com/ddeboer/imap/tree/1.7.2) (2019-04-12)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.1...1.7.2)

**Fixed bugs:**

- Handle message/rfc822 when content-disposition is missing
[\#410](https://github.com/ddeboer/imap/pull/410)
([Daredzik](https://github.com/Daredzik))

## [1.7.1](https://github.com/ddeboer/imap/tree/1.7.1) (2019-03-18)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.0...1.7.1)

**Fixed bugs:**

- Encoding problem with 1.7
[\#405](https://github.com/ddeboer/imap/issues/405)
- imap\_search/imap\_sort: default params must not be passed if unspecified
[\#406](https://github.com/ddeboer/imap/pull/406)
([Slamdunk](https://github.com/Slamdunk))

## [1.7.0](https://github.com/ddeboer/imap/tree/1.7.0) (2019-03-04)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.6.0...1.7.0)

**Implemented enhancements:**

- Docker and Travis differs in handling new message eols
[\#404](https://github.com/ddeboer/imap/pull/404)
([Slamdunk](https://github.com/Slamdunk))
- Update PHP-CS-Fixer rules
[\#403](https://github.com/ddeboer/imap/pull/403)
([Slamdunk](https://github.com/Slamdunk))
- Add charset for imap\_search or imap\_sort
[\#402](https://github.com/ddeboer/imap/pull/402)
([Slamdunk](https://github.com/Slamdunk))
- PHPStan clean ups [\#400](https://github.com/ddeboer/imap/pull/400)
([Slamdunk](https://github.com/Slamdunk))
- Adding an undelete\(\) message method
[\#386](https://github.com/ddeboer/imap/pull/386)
([C-Duv](https://github.com/C-Duv))

**Closed issues:**

- Convert from GBK \(X-GBK\) to UTF-8 Issue
[\#395](https://github.com/ddeboer/imap/issues/395)

**Merged pull requests:**

- Add new ResourceCheckFailureException to handle imap\_check\(\) false
[\#399](https://github.com/ddeboer/imap/pull/399)
([pyatnitsev](https://github.com/pyatnitsev))
- Remove GBK -\> X-GBK Alias and add X-GBK -\> GBK
[\#396](https://github.com/ddeboer/imap/pull/396)
([pyatnitsev](https://github.com/pyatnitsev))
- Add Feature Requests to README.md
[\#394](https://github.com/ddeboer/imap/pull/394)
([Slamdunk](https://github.com/Slamdunk))

## [1.6.0](https://github.com/ddeboer/imap/tree/1.6.0) (2018-12-04)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.5...1.6.0)

**Implemented enhancements:**

- Require PHP ^7.1 [\#257](https://github.com/ddeboer/imap/issues/257)
- Require PHP ^7.1 [\#383](https://github.com/ddeboer/imap/pull/383)
([Slamdunk](https://github.com/Slamdunk))
- Add ability to pass options and retries to imap\_open
[\#382](https://github.com/ddeboer/imap/pull/382)
([Slamdunk](https://github.com/Slamdunk))
- Docker setup for running tests
[\#374](https://github.com/ddeboer/imap/pull/374)
([LeadTechVisas](https://github.com/LeadTechVisas))
- Get messages by UID sequence
[\#373](https://github.com/ddeboer/imap/pull/373)
([LeadTechVisas](https://github.com/LeadTechVisas))

**Fixed bugs:**

- Undeliverable mail: attachment parsing error
[\#334](https://github.com/ddeboer/imap/issues/334)
- imap\_getmailboxes returns false;
[\#134](https://github.com/ddeboer/imap/issues/134)
- Fix mailbox name as only numbers
[\#381](https://github.com/ddeboer/imap/pull/381)
([Slamdunk](https://github.com/Slamdunk))
- Gracefully handle possible non-array return value of imap\_getmailboxes
[\#372](https://github.com/ddeboer/imap/pull/372)
([Slamdunk](https://github.com/Slamdunk))

**Closed issues:**

- \[AUTHENTICATIONFAILED\] Authentication failed - Too many login failures
[\#368](https://github.com/ddeboer/imap/issues/368)
- last folder in list [\#353](https://github.com/ddeboer/imap/issues/353)
- Caching IMAP server connections
[\#88](https://github.com/ddeboer/imap/issues/88)

## [1.5.5](https://github.com/ddeboer/imap/tree/1.5.5) (2018-08-21)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.4...1.5.5)

**Fixed bugs:**

- Plain text attachments are not identified as Attachment parts
[\#341](https://github.com/ddeboer/imap/issues/341)
- Handle plain/text attachments without Content-Type header
[\#367](https://github.com/ddeboer/imap/pull/367)
([Slamdunk](https://github.com/Slamdunk))

## [1.5.4](https://github.com/ddeboer/imap/tree/1.5.4) (2018-08-19)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.3...1.5.4)

**Fixed bugs:**

- Very long filename, result of getFilename\(\) = NULL?
[\#365](https://github.com/ddeboer/imap/issues/365)
- Support RFC2231 attachment filenames
[\#366](https://github.com/ddeboer/imap/pull/366)
([Slamdunk](https://github.com/Slamdunk))

## [1.5.3](https://github.com/ddeboer/imap/tree/1.5.3) (2018-07-20)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.2...1.5.3)

**Fixed bugs:**

- Dates: handle UT timezone
[\#361](https://github.com/ddeboer/imap/pull/361)
([Slamdunk](https://github.com/Slamdunk))

## [1.5.2](https://github.com/ddeboer/imap/tree/1.5.2) (2018-07-10)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.1...1.5.2)

**Fixed bugs:**

- Fails to load Message Headers
[\#358](https://github.com/ddeboer/imap/issues/358)
- Handle invalid headers [\#359](https://github.com/ddeboer/imap/pull/359)
([Slamdunk](https://github.com/Slamdunk))

## [1.5.1](https://github.com/ddeboer/imap/tree/1.5.1) (2018-05-04)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.0...1.5.1)

**Fixed bugs:**

- getContent\(\) method returns wrong content part
[\#342](https://github.com/ddeboer/imap/issues/342)
- Fix handle of attachment messages with attachments
[\#343](https://github.com/ddeboer/imap/pull/343)
([Slamdunk](https://github.com/Slamdunk))

## [1.5.0](https://github.com/ddeboer/imap/tree/1.5.0) (2018-03-26)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.4.1...1.5.0)

**Implemented enhancements:**

- ImapResource: cache last opened mailbox
[\#328](https://github.com/ddeboer/imap/pull/328)
([Slamdunk](https://github.com/Slamdunk))

**Fixed bugs:**

- AbstractPart::isAttachment\(\) handle unknown part type
[\#302](https://github.com/ddeboer/imap/pull/302)
([Slamdunk](https://github.com/Slamdunk))

## [1.4.1](https://github.com/ddeboer/imap/tree/1.4.1) (2018-03-22)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.4.0...1.4.1)

**Fixed bugs:**

- Return value of
Ddeboer\\Imap\\Message\\AbstractPart::getDecodedContent\(\) must be of the
type string, boolean returned
[\#284](https://github.com/ddeboer/imap/issues/284)
- base64\_decode may return false in PHP \< 7.1
[\#324](https://github.com/ddeboer/imap/pull/324)
([Slamdunk](https://github.com/Slamdunk))

**Merged pull requests:**

- Add entry in README about Mailbox::addMessage
[\#325](https://github.com/ddeboer/imap/pull/325)
([soywod](https://github.com/soywod))

## [1.4.0](https://github.com/ddeboer/imap/tree/1.4.0) (2018-03-19)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.3.1...1.4.0)

**Implemented enhancements:**

- Lazy load Message [\#320](https://github.com/ddeboer/imap/pull/320)
([Slamdunk](https://github.com/Slamdunk))

**Fixed bugs:**

- Invalid argument supplied for foreach\(\) in Parameters.php line 52
[\#317](https://github.com/ddeboer/imap/issues/317)
- Message "11964" does not exist: imap\_fetchstructure\(\): Bad
message number [\#310](https://github.com/ddeboer/imap/issues/310)
- imap\_mime\_header\_decode may return false
[\#322](https://github.com/ddeboer/imap/pull/322)
([Slamdunk](https://github.com/Slamdunk))

## [1.3.1](https://github.com/ddeboer/imap/tree/1.3.1) (2018-03-09)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.3.0...1.3.1)

**Implemented enhancements:**

- Allow empty port [\#312](https://github.com/ddeboer/imap/pull/312)
([Slamdunk](https://github.com/Slamdunk))

**Closed issues:**

- getServerString\(\) with no port
[\#311](https://github.com/ddeboer/imap/issues/311)

## [1.3.0](https://github.com/ddeboer/imap/tree/1.3.0) (2018-02-28)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.3...1.3.0)

**Implemented enhancements:**

- Implement bulk-move [\#306](https://github.com/ddeboer/imap/pull/306)
([particleflux](https://github.com/particleflux))

**Closed issues:**

- feature: Bulk move [\#305](https://github.com/ddeboer/imap/issues/305)

**Merged pull requests:**

- README.md: add `Unknown search criterion: OR` note
[\#304](https://github.com/ddeboer/imap/pull/304)
([Slamdunk](https://github.com/Slamdunk))

## [1.2.3](https://github.com/ddeboer/imap/tree/1.2.3) (2018-02-09)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.2...1.2.3)

**Fixed bugs:**

- $part-\>type can be 9
[\#301](https://github.com/ddeboer/imap/issues/301)

**Merged pull requests:**

- README.md: code-coverage has higher priority than Scrutinizer
[\#300](https://github.com/ddeboer/imap/pull/300)
([Slamdunk](https://github.com/Slamdunk))

## [1.2.2](https://github.com/ddeboer/imap/tree/1.2.2) (2018-02-05)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.1...1.2.2)

**Implemented enhancements:**

- Allow PHPUnit ^7.0 [\#296](https://github.com/ddeboer/imap/pull/296)
([Slamdunk](https://github.com/Slamdunk))

**Fixed bugs:**

- Attachment-\>getFilename return null
[\#297](https://github.com/ddeboer/imap/issues/297)
- Don't handle multiplart as an attachment
[\#298](https://github.com/ddeboer/imap/pull/298)
([Slamdunk](https://github.com/Slamdunk))

## [1.2.1](https://github.com/ddeboer/imap/tree/1.2.1) (2018-01-29)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.0...1.2.1)

**Implemented enhancements:**

- Introduce strict comparison
[\#289](https://github.com/ddeboer/imap/pull/289)
([Slamdunk](https://github.com/Slamdunk))

**Fixed bugs:**

- Invalid Date header found: "Thur, 04 Jan 2018 06:44:23 +0400"
[\#293](https://github.com/ddeboer/imap/issues/293)
- MessageIterator::current\(\) fails when there are no messages
[\#288](https://github.com/ddeboer/imap/issues/288)
- Remove weekday while parsing date header
[\#294](https://github.com/ddeboer/imap/pull/294)
([Slamdunk](https://github.com/Slamdunk))
- MessageIterator: forbid raw calls
[\#290](https://github.com/ddeboer/imap/pull/290)
([Slamdunk](https://github.com/Slamdunk))

## [1.2.0](https://github.com/ddeboer/imap/tree/1.2.0) (2018-01-15)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.2...1.2.0)

**Implemented enhancements:**

- Make imap\_append\(\) optional arguments reachable
[\#280](https://github.com/ddeboer/imap/pull/280)
([Slamdunk](https://github.com/Slamdunk))
- PHPStan: introduce static analysis
[\#276](https://github.com/ddeboer/imap/pull/276)
([Slamdunk](https://github.com/Slamdunk))

**Fixed bugs:**

- getAttachments\(\) problem when mixin inline and attachment
[\#281](https://github.com/ddeboer/imap/issues/281)
- UnexpectedEncodingException: Cannot decode "5"
[\#278](https://github.com/ddeboer/imap/issues/278)
- Handle correctly multiple nested attachments
[\#283](https://github.com/ddeboer/imap/pull/283)
([Slamdunk](https://github.com/Slamdunk))
- Manageable UnexpectedEncodingException
[\#282](https://github.com/ddeboer/imap/pull/282)
([Slamdunk](https://github.com/Slamdunk))

**Closed issues:**

- Appending mail with options
[\#279](https://github.com/ddeboer/imap/issues/279)

## [1.1.2](https://github.com/ddeboer/imap/tree/1.1.2) (2017-12-12)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.1...1.1.2)

**Fixed bugs:**

- Unsupported charset "134": mb\_convert\_encoding\(\): Illegal
character encoding specified
[\#270](https://github.com/ddeboer/imap/issues/270)
- Support Microsoft charset values
[\#271](https://github.com/ddeboer/imap/pull/271)
([Slamdunk](https://github.com/Slamdunk))

## [1.1.1](https://github.com/ddeboer/imap/tree/1.1.1) (2017-11-10)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.0...1.1.1)

**Implemented enhancements:**

- Transcoder: expand charset aliases list
[\#267](https://github.com/ddeboer/imap/pull/267)
([Slamdunk](https://github.com/Slamdunk))

**Fixed bugs:**

- Charset aliases: fix to lowercase search
[\#266](https://github.com/ddeboer/imap/pull/266)
([Slamdunk](https://github.com/Slamdunk))

**Merged pull requests:**

- README.md: add timeout note
[\#263](https://github.com/ddeboer/imap/pull/263)
([Slamdunk](https://github.com/Slamdunk))

## [1.1.0](https://github.com/ddeboer/imap/tree/1.1.0) (2017-11-06)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.8...1.1.0)

**Implemented enhancements:**

- Deprecate MessageInterface::maskAsSeen\(\) in favour of
MessageInterface::markAsSeen\(\)
[\#255](https://github.com/ddeboer/imap/pull/255)
([Slamdunk](https://github.com/Slamdunk))
- Lazy load structured Headers
[\#250](https://github.com/ddeboer/imap/pull/250)
([Slamdunk](https://github.com/Slamdunk))
- Implement imap\_thread [\#249](https://github.com/ddeboer/imap/pull/249)
([Slamdunk](https://github.com/Slamdunk))
- Require ext-iconv [\#248](https://github.com/ddeboer/imap/pull/248)
([Slamdunk](https://github.com/Slamdunk))
- Message Part: expose $partNumber
[\#244](https://github.com/ddeboer/imap/pull/244)
([wujku](https://github.com/wujku))
- Add Mockability helpers and documentation
[\#236](https://github.com/ddeboer/imap/pull/236)
([Slamdunk](https://github.com/Slamdunk))
- Add missing interface change for \#225
[\#233](https://github.com/ddeboer/imap/pull/233)
([Slamdunk](https://github.com/Slamdunk))
- Connection: check if the connection is still active with `imap\_ping`
[\#232](https://github.com/ddeboer/imap/pull/232)
([wujku](https://github.com/wujku))
- Message: add `References` and `In-Reply-To` headers shortcuts
[\#230](https://github.com/ddeboer/imap/pull/230)
([wujku](https://github.com/wujku))
- Added bulk set / clear flags functionality for mailbox messages
[\#225](https://github.com/ddeboer/imap/pull/225)
([wujku](https://github.com/wujku))

**Merged pull requests:**

- make docs more obvious [\#252](https://github.com/ddeboer/imap/pull/252)
([lgg](https://github.com/lgg))
- README.md: add Table of Contents with Travis checker
[\#234](https://github.com/ddeboer/imap/pull/234)
([Slamdunk](https://github.com/Slamdunk))

## [1.0.8](https://github.com/ddeboer/imap/tree/1.0.8) (2017-10-27)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.7...1.0.8)

**Implemented enhancements:**

- Headers: no catchable exception
[\#246](https://github.com/ddeboer/imap/issues/246)
- imap\_thread [\#113](https://github.com/ddeboer/imap/issues/113)

**Fixed bugs:**

- \[TypeError\] Return value of
Ddeboer\Imap\Message\AbstractMessage::getId\(\) must be of the type string,
null returned [\#253](https://github.com/ddeboer/imap/issues/253)
- BasicMessageInterface::getId\(\) can be null
[\#254](https://github.com/ddeboer/imap/pull/254)
([Slamdunk](https://github.com/Slamdunk))

## [1.0.7](https://github.com/ddeboer/imap/tree/1.0.7) (2017-10-16)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.6...1.0.7)

**Fixed bugs:**

- Problem with a IMAP resource stream
[\#245](https://github.com/ddeboer/imap/issues/245)
- IMAP resource must be checked at every call for mailbox context
[\#247](https://github.com/ddeboer/imap/pull/247)
([Slamdunk](https://github.com/Slamdunk))

## [1.0.6](https://github.com/ddeboer/imap/tree/1.0.6) (2017-10-12)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.5...1.0.6)

**Fixed bugs:**

- \[TypeError\] Return value of AbstractMessage::getFrom\(\) must be an
instance of EmailAddress, null returned
[\#241](https://github.com/ddeboer/imap/issues/241)
- Message: Date header can be absent
[\#243](https://github.com/ddeboer/imap/pull/243)
([Slamdunk](https://github.com/Slamdunk))
- Message: From header can be absent
[\#242](https://github.com/ddeboer/imap/pull/242)
([Slamdunk](https://github.com/Slamdunk))

## [1.0.5](https://github.com/ddeboer/imap/tree/1.0.5) (2017-10-12)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.4...1.0.5)

**Fixed bugs:**

- Use set\_error\_handler with late exception
[\#240](https://github.com/ddeboer/imap/pull/240)
([Slamdunk](https://github.com/Slamdunk))

## [1.0.4](https://github.com/ddeboer/imap/tree/1.0.4) (2017-10-11)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.3...1.0.4)

**Implemented enhancements:**

- Avoid \(set|restor\)\_error\_handler
[\#239](https://github.com/ddeboer/imap/pull/239)
([Slamdunk](https://github.com/Slamdunk))

**Fixed bugs:**

- Current Transcoder class does not support all charsets. 
[\#237](https://github.com/ddeboer/imap/issues/237)
- Relay also iconv during decoding
[\#238](https://github.com/ddeboer/imap/pull/238)
([Slamdunk](https://github.com/Slamdunk))

## [1.0.3](https://github.com/ddeboer/imap/tree/1.0.3) (2017-10-11)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.2...1.0.3)

**Fixed bugs:**

- Attachment::getFilename\(\) may be null on inline-att, widen return type
[\#235](https://github.com/ddeboer/imap/pull/235)
([wujku](https://github.com/wujku))

## [1.0.2](https://github.com/ddeboer/imap/tree/1.0.2) (2017-10-06)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.1...1.0.2)

**Fixed bugs:**

- Issue with saving XML attachments
[\#228](https://github.com/ddeboer/imap/issues/228)
- Do not charset-decode attachments
[\#231](https://github.com/ddeboer/imap/pull/231)
([Slamdunk](https://github.com/Slamdunk))

## [1.0.1](https://github.com/ddeboer/imap/tree/1.0.1) (2017-10-05)

[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.0...1.0.1)

**Fixed bugs:**

- Error with attachment charset
[\#226](https://github.com/ddeboer/imap/issues/226)
- If charset is not specified defaults to "us-ascii"
[\#227](https://github.com/ddeboer/imap/pull/227)
([Slamdunk](https://github.com/Slamdunk))

## [1.0.0](https://github.com/ddeboer/imap/tree/1.0.0) (2017-10-04)

[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.2...1.0.0)

**Implemented enhancements:**

- Need getAll for headers
[\#200](https://github.com/ddeboer/imap/issues/200)
- Tests: implement @covers to avoid false positive on code-coverage
[\#188](https://github.com/ddeboer/imap/issues/188)
- Remove commented code
[\#174](https://github.com/ddeboer/imap/issues/174)
- Regex in SearchExpressions
[\#157](https://github.com/ddeboer/imap/issues/157)
- How do I get unread messages count?
[\#98](https://github.com/ddeboer/imap/issues/98)
- Add mocking ability through Interfaces
[\#221](https://github.com/ddeboer/imap/pull/221)
([Slamdunk](https://github.com/Slamdunk))
- Wrap imap resource to periodically check its status
[\#220](https://github.com/ddeboer/imap/pull/220)
([Slamdunk](https://github.com/Slamdunk))
- Add more coding-standard rules
[\#218](https://github.com/ddeboer/imap/pull/218)
([Slamdunk](https://github.com/Slamdunk))
- Always keep unseen: remove keepUnseen, add markAsSeen
[\#217](https://github.com/ddeboer/imap/pull/217)
([Slamdunk](https://github.com/Slamdunk))
- Embedded messages: refactor \#106
[\#216](https://github.com/ddeboer/imap/pull/216)
([Slamdunk](https://github.com/Slamdunk))
- Headers now extends \ArrayIterator
[\#215](https://github.com/ddeboer/imap/pull/215)
([Slamdunk](https://github.com/Slamdunk))
- Implement imap\_mail\_copy
[\#214](https://github.com/ddeboer/imap/pull/214)
([Slamdunk](https://github.com/Slamdunk))
- Imap sort [\#213](https://github.com/ddeboer/imap/pull/213)
([Slamdunk](https://github.com/Slamdunk))
- Increased code-coverage [\#211](https://github.com/ddeboer/imap/pull/211)
([Slamdunk](https://github.com/Slamdunk))
- Update to PHPUnit ^6.2 [\#209](https://github.com/ddeboer/imap/pull/209)
([Slamdunk](https://github.com/Slamdunk))
- Use specific exceptions to ease user catches
[\#208](https://github.com/ddeboer/imap/pull/208)
([Slamdunk](https://github.com/Slamdunk))
- Wrap Exception on invalid Date header
[\#205](https://github.com/ddeboer/imap/pull/205)
([Slamdunk](https://github.com/Slamdunk))
- Add tests for \#144 set flags functionalities
[\#203](https://github.com/ddeboer/imap/pull/203)
([Slamdunk](https://github.com/Slamdunk))
- Add imap\_fetchheader\(\) functionality to get raw headers
[\#202](https://github.com/ddeboer/imap/pull/202)
([Slamdunk](https://github.com/Slamdunk))
- Parse all email type headers
[\#199](https://github.com/ddeboer/imap/pull/199)
([Slamdunk](https://github.com/Slamdunk))
- Test search conditions [\#198](https://github.com/ddeboer/imap/pull/198)
([Slamdunk](https://github.com/Slamdunk))
- Mailbox: get status [\#192](https://github.com/ddeboer/imap/pull/192)
([Slamdunk](https://github.com/Slamdunk))
- SearchExpression is a Search\ConditionInterface
[\#191](https://github.com/ddeboer/imap/pull/191)
([Slamdunk](https://github.com/Slamdunk))
- SearchCondition: \_\_toString\(\) -\> toString\(\)
[\#187](https://github.com/ddeboer/imap/pull/187)
([Slamdunk](https://github.com/Slamdunk))
- Retain imap\_getmailboxes\(\) results
[\#184](https://github.com/ddeboer/imap/pull/184)
([Slamdunk](https://github.com/Slamdunk))
- Add type hints and return types
[\#183](https://github.com/ddeboer/imap/pull/183)
([Slamdunk](https://github.com/Slamdunk))
- Exception: increase verbosity with imap\_alerts\(\) and imap\_errors\(\)
[\#182](https://github.com/ddeboer/imap/pull/182)
([Slamdunk](https://github.com/Slamdunk))
- Add coding-standards [\#181](https://github.com/ddeboer/imap/pull/181)
([Slamdunk](https://github.com/Slamdunk))
- Travis: re-enable code-coverage on scrutinizer
[\#177](https://github.com/ddeboer/imap/pull/177)
([Slamdunk](https://github.com/Slamdunk))
- Add .gitattributes to remove from releases unneded files
[\#173](https://github.com/ddeboer/imap/pull/173)
([Slamdunk](https://github.com/Slamdunk))
- Travis: use local Dovecot installation
[\#170](https://github.com/ddeboer/imap/pull/170)
([Slamdunk](https://github.com/Slamdunk))
- Need all Headers in string format
[\#149](https://github.com/ddeboer/imap/pull/149)
([FlashWS](https://github.com/FlashWS))
- Get raw mail [\#146](https://github.com/ddeboer/imap/pull/146)
([styxit](https://github.com/styxit))
- add getBcc\(\), Set, Clear Flag\(\Seen, \Answered, \Flagged, \Deleted,
and \Draft\), getHeadersRaw\(\)
[\#144](https://github.com/ddeboer/imap/pull/144)
([trungpv93](https://github.com/trungpv93))

**Fixed bugs:**

- Search\Condition needs charset escaping/indication
[\#190](https://github.com/ddeboer/imap/issues/190)
- imap\_utf7\_\(encode|decode\) -\> mb\_convert\_encoding
[\#185](https://github.com/ddeboer/imap/issues/185)
- España [\#176](https://github.com/ddeboer/imap/issues/176)
- getHeaders\(\) decode broke information
[\#171](https://github.com/ddeboer/imap/issues/171)
- Date format for date search condition
[\#168](https://github.com/ddeboer/imap/issues/168)
- Error when trying fetch messages from container
[\#167](https://github.com/ddeboer/imap/issues/167)
- Attachment encoding error
[\#158](https://github.com/ddeboer/imap/issues/158)
- getFilename\(\) is empty and no attachment, even when there is an
attachment. [\#142](https://github.com/ddeboer/imap/issues/142)
- Encoding issues [\#136](https://github.com/ddeboer/imap/issues/136)
- URGENT: The timezone could not be found in the database
[\#135](https://github.com/ddeboer/imap/issues/135)
- Incorrect transcoding of text attachments
[\#132](https://github.com/ddeboer/imap/issues/132)
- Undefined offset  [\#123](https://github.com/ddeboer/imap/issues/123)
- ICS file not supported as attachment
[\#120](https://github.com/ddeboer/imap/issues/120)
- Should iconv be a requirement?
[\#115](https://github.com/ddeboer/imap/issues/115)
- KeepUnseen doen't work
[\#92](https://github.com/ddeboer/imap/issues/92)
- PHP Fatal error Failed to parse time string in
ddeboer/imap/src/Message.php
[\#89](https://github.com/ddeboer/imap/issues/89)
- encoding issue [\#85](https://github.com/ddeboer/imap/issues/85)
- keepUnseen not working correctly with Hotmail
[\#84](https://github.com/ddeboer/imap/issues/84)
- Iconv Exception [\#78](https://github.com/ddeboer/imap/issues/78)
- $message-\>getAttachments\(\) doesn't recognize some attachments
[\#74](https://github.com/ddeboer/imap/issues/74)
- Message::move\(\) doesn't work.
[\#73](https://github.com/ddeboer/imap/issues/73)
- Message\Part: part number must distinguish original message
[\#223](https://github.com/ddeboer/imap/pull/223)
([Slamdunk](https://github.com/Slamdunk))
- Recursive Embedded email body bug
[\#222](https://github.com/ddeboer/imap/pull/222)
([Slamdunk](https://github.com/Slamdunk))
- Exclude HTML from allowed attachment subtype
[\#212](https://github.com/ddeboer/imap/pull/212)
([Slamdunk](https://github.com/Slamdunk))
- Fix imap\_mail\_move behaviour and test it
[\#207](https://github.com/ddeboer/imap/pull/207)
([Slamdunk](https://github.com/Slamdunk))
- Undefined encoding: throw exception
[\#197](https://github.com/ddeboer/imap/pull/197)
([Slamdunk](https://github.com/Slamdunk))
- Message charset: mb\_convert\_encoding + aliases
[\#196](https://github.com/ddeboer/imap/pull/196)
([Slamdunk](https://github.com/Slamdunk))
- Mailbox: only UTF-8 names
[\#193](https://github.com/ddeboer/imap/pull/193)
([Slamdunk](https://github.com/Slamdunk))
- Search\Date\AbstractDate: fix format to RFC-3501
[\#189](https://github.com/ddeboer/imap/pull/189)
([Slamdunk](https://github.com/Slamdunk))
- Travis: fix failing tests
[\#172](https://github.com/ddeboer/imap/pull/172)
([Slamdunk](https://github.com/Slamdunk))
- Return body of single-part HTML message as HTML, not text
[\#101](https://github.com/ddeboer/imap/pull/101)
([joker806](https://github.com/joker806))
- Implement "undisclosed recipients" addresses
[\#86](https://github.com/ddeboer/imap/pull/86)
([darit](https://github.com/darit))

**Closed issues:**

- Potential memory issue with attachments
[\#195](https://github.com/ddeboer/imap/issues/195)
- Explain Message::delete
[\#175](https://github.com/ddeboer/imap/issues/175)
- Get raw message [\#161](https://github.com/ddeboer/imap/issues/161)
- Composer install problem
[\#160](https://github.com/ddeboer/imap/issues/160)
- Transcoder not exist [\#154](https://github.com/ddeboer/imap/issues/154)
- The library doesn't support using sort by
[\#151](https://github.com/ddeboer/imap/issues/151)
- Office 365 - Array to string conversion error
[\#131](https://github.com/ddeboer/imap/issues/131)
- Is there a method to turn a seen message into an "unseen" one ?
[\#130](https://github.com/ddeboer/imap/issues/130)
- Create mailbox [\#126](https://github.com/ddeboer/imap/issues/126)
- Move and Delete Message not working
[\#112](https://github.com/ddeboer/imap/issues/112)
- Problem on production server
[\#111](https://github.com/ddeboer/imap/issues/111)
- Authentication failed for a Gmail account
[\#109](https://github.com/ddeboer/imap/issues/109)
- A method to run IMAP commands?
[\#83](https://github.com/ddeboer/imap/issues/83)

**Merged pull requests:**

- Update README.md to latest develop changes
[\#224](https://github.com/ddeboer/imap/pull/224)
([Slamdunk](https://github.com/Slamdunk))
- Add Filippo Tessarotto as an author of the package
[\#219](https://github.com/ddeboer/imap/pull/219)
([Slamdunk](https://github.com/Slamdunk))
- README.md: call Connection::expunge after move and delete
[\#210](https://github.com/ddeboer/imap/pull/210)
([Slamdunk](https://github.com/Slamdunk))
- Remove misleading Mailbox::expunge\(\)
[\#206](https://github.com/ddeboer/imap/pull/206)
([Slamdunk](https://github.com/Slamdunk))
- Add CHANGELOG.md [\#194](https://github.com/ddeboer/imap/pull/194)
([Slamdunk](https://github.com/Slamdunk))
- README.md updates [\#178](https://github.com/ddeboer/imap/pull/178)
([Slamdunk](https://github.com/Slamdunk))

## [0.5.2](https://github.com/ddeboer/imap/tree/0.5.2) (2015-12-03)

[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.1...0.5.2)

**Closed issues:**

- $message-\>getAttachments\(\) returns null if message has no
attachments [\#80](https://github.com/ddeboer/imap/issues/80)
- Email objects visibility
[\#76](https://github.com/ddeboer/imap/issues/76)

**Merged pull requests:**

- Fixed the keepUnseen method
[\#95](https://github.com/ddeboer/imap/pull/95)
([aeyoll](https://github.com/aeyoll))
- Mark Mailbox as countable, fix doc comments
[\#91](https://github.com/ddeboer/imap/pull/91)
([krzysiekpiasecki](https://github.com/krzysiekpiasecki))
- Message::getAttachments confirm to signature
[\#82](https://github.com/ddeboer/imap/pull/82)
([boekkooi](https://github.com/boekkooi))
- Added hasMailbox to Connection
[\#81](https://github.com/ddeboer/imap/pull/81)
([boekkooi](https://github.com/boekkooi))
- Make sure imap connection are reopened
[\#79](https://github.com/ddeboer/imap/pull/79)
([joserobleda](https://github.com/joserobleda))

## [0.5.1](https://github.com/ddeboer/imap/tree/0.5.1) (2015-02-01)

[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.0...0.5.1)

**Closed issues:**

- imap\_open error  [\#72](https://github.com/ddeboer/imap/issues/72)
- $message-\>getAttachments\(\) does not return anything, even though a
message has at least one attachment
[\#71](https://github.com/ddeboer/imap/issues/71)
- Prepare docs for 1.0 [\#69](https://github.com/ddeboer/imap/issues/69)
- "date" header is not reliable
[\#63](https://github.com/ddeboer/imap/issues/63)
- File Attachments don't show up
[\#55](https://github.com/ddeboer/imap/issues/55)

**Merged pull requests:**

- Add support for attachments without content disposition
[\#70](https://github.com/ddeboer/imap/pull/70)
([ddeboer](https://github.com/ddeboer))

## [0.5.0](https://github.com/ddeboer/imap/tree/0.5.0) (2015-01-24)

[Full Changelog](https://github.com/ddeboer/imap/compare/0.4.0...0.5.0)

**Closed issues:**

- Use utf8\_encode\(\) function to encode content
[\#66](https://github.com/ddeboer/imap/issues/66)
- Please add function order by date
[\#59](https://github.com/ddeboer/imap/issues/59)
- mb\_convert\_encoding breaks code
[\#57](https://github.com/ddeboer/imap/issues/57)
- How get I getMessages but newest first ...
[\#11](https://github.com/ddeboer/imap/issues/11)

## [0.4.0](https://github.com/ddeboer/imap/tree/0.4.0) (2015-01-04)

[Full Changelog](https://github.com/ddeboer/imap/compare/0.3.1...0.4.0)

**Closed issues:**

- Please add 6th parameter to imap\_open call
[\#62](https://github.com/ddeboer/imap/issues/62)
- Should Message::delete\(\) use the Message UID?
[\#46](https://github.com/ddeboer/imap/issues/46)
- mb\_convert\_encoding\(\): Illegal character encoding specified
[\#35](https://github.com/ddeboer/imap/issues/35)
- Deleting a message isn't working
[\#30](https://github.com/ddeboer/imap/issues/30)
- imap\_header doesn't work with message uid
[\#26](https://github.com/ddeboer/imap/issues/26)

**Merged pull requests:**

- Added basic requirement [\#61](https://github.com/ddeboer/imap/pull/61)
([nikoskip](https://github.com/nikoskip))
- FIX: PHP error: "Cannot declare class Ddeboer\Imap\Search\Text\Text
..." [\#58](https://github.com/ddeboer/imap/pull/58)
([racztiborzoltan](https://github.com/racztiborzoltan))
- Message::delete sets the FT\_UID flag.  Fixes \#30 Fixes \#46
[\#54](https://github.com/ddeboer/imap/pull/54)
([ctalbot](https://github.com/ctalbot))
- Allow binary-encoded part content
[\#48](https://github.com/ddeboer/imap/pull/48)
([joker806](https://github.com/joker806))
- Fix CS [\#47](https://github.com/ddeboer/imap/pull/47)
([xelan](https://github.com/xelan))
- fixed typo [\#45](https://github.com/ddeboer/imap/pull/45)
([xelan](https://github.com/xelan))

## [0.3.1](https://github.com/ddeboer/imap/tree/0.3.1) (2014-08-11)

[Full Changelog](https://github.com/ddeboer/imap/compare/0.3.0...0.3.1)

**Merged pull requests:**

- \imap\_header dosen't work with UID
[\#44](https://github.com/ddeboer/imap/pull/44)
([ysramirez](https://github.com/ysramirez))

## [0.3.0](https://github.com/ddeboer/imap/tree/0.3.0) (2014-08-10)

[Full Changelog](https://github.com/ddeboer/imap/compare/0.2...0.3.0)

**Closed issues:**

- please remove useless wiki
[\#42](https://github.com/ddeboer/imap/issues/42)
- Travis tests allways fail?
[\#40](https://github.com/ddeboer/imap/issues/40)
- Garbled e-mail body encoding
[\#27](https://github.com/ddeboer/imap/issues/27)
- Improve docs [\#25](https://github.com/ddeboer/imap/issues/25)
- "undisclosed-recipients" throws error
[\#23](https://github.com/ddeboer/imap/issues/23)

**Merged pull requests:**

- correct minor typo [\#43](https://github.com/ddeboer/imap/pull/43)
([cordoval](https://github.com/cordoval))
- Utf-8 encode body content.
[\#39](https://github.com/ddeboer/imap/pull/39)
([cmoralesweb](https://github.com/cmoralesweb))
- Fix regex parsing the date header \(allowing multiple brackets\)
[\#38](https://github.com/ddeboer/imap/pull/38)
([joker806](https://github.com/joker806))
- Allow empty connection flags
[\#34](https://github.com/ddeboer/imap/pull/34)
([joker806](https://github.com/joker806))
- Fixed typo [\#32](https://github.com/ddeboer/imap/pull/32)
([abhinavkumar940](https://github.com/abhinavkumar940))

## [0.2](https://github.com/ddeboer/imap/tree/0.2) (2013-11-24)

[Full Changelog](https://github.com/ddeboer/imap/compare/0.1...0.2)

## [0.1](https://github.com/ddeboer/imap/tree/0.1) (2013-11-22)

[Full
Changelog](https://github.com/ddeboer/imap/compare/c02d49cdb9246901bb00d211a0f2aba208f6fab6...0.1)

**Closed issues:**

- Prevent setting SEEN flag
[\#20](https://github.com/ddeboer/imap/issues/20)
- Add tests [\#18](https://github.com/ddeboer/imap/issues/18)
- delete messages [\#9](https://github.com/ddeboer/imap/issues/9)
- README is missing basic usage
[\#7](https://github.com/ddeboer/imap/issues/7)
- Subject and other texts are decoded incorrectly 
[\#3](https://github.com/ddeboer/imap/issues/3)

**Merged pull requests:**

- also fetch inline attachments
[\#24](https://github.com/ddeboer/imap/pull/24)
([kaiserlos](https://github.com/kaiserlos))
- since leading slash is always needed
[\#22](https://github.com/ddeboer/imap/pull/22)
([huglester](https://github.com/huglester))
- Added missed createMailbox\($name\) function
[\#19](https://github.com/ddeboer/imap/pull/19)
([burci](https://github.com/burci))
- Added move and delete function to message + expunge function
[\#17](https://github.com/ddeboer/imap/pull/17)
([burci](https://github.com/burci))
- Clean up some unused variable
[\#16](https://github.com/ddeboer/imap/pull/16)
([burci](https://github.com/burci))
- Fixed mailbox encoding [\#15](https://github.com/ddeboer/imap/pull/15)
([burci](https://github.com/burci))
- Create new mailbox [\#14](https://github.com/ddeboer/imap/pull/14)
([burci](https://github.com/burci))
- Fixed bug in getDecodedContent with 'format=flowed' email
[\#13](https://github.com/ddeboer/imap/pull/13)
([burci](https://github.com/burci))
- Fixed date parsing for some imap servers
[\#12](https://github.com/ddeboer/imap/pull/12)
([thelfensdrfer](https://github.com/thelfensdrfer))
- Add support for more complex search expressions.
[\#10](https://github.com/ddeboer/imap/pull/10)
([jamesiarmes](https://github.com/jamesiarmes))
- Allow user to change server connection flags
[\#6](https://github.com/ddeboer/imap/pull/6)
([mvar](https://github.com/mvar))
- Improvements in EmailAddress class
[\#4](https://github.com/ddeboer/imap/pull/4)
([mvar](https://github.com/mvar))



\* *This Changelog was automatically generated by
[github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
lib/vendor/ddeboer/imap/composer.json000064400000002427151163263020013667
0ustar00{
    "name": "ddeboer/imap",
    "description": "Object-oriented IMAP for PHP",
    "keywords": [
        "email",
        "mail",
        "imap"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "David de Boer",
            "email": "david@ddeboer.nl"
        },
        {
            "name": "Filippo Tessarotto",
            "email": "zoeslam@gmail.com"
        },
        {
            "name": "Community contributors",
            "homepage":
"https://github.com/ddeboer/imap/graphs/contributors"
        }
    ],
    "require": {
        "php": "^7.3 || ^8.0",
        "ext-iconv": "*",
        "ext-imap": "*",
        "ext-mbstring": "*"
    },
    "require-dev": {
        "friendsofphp/php-cs-fixer": "^2.16.7",
        "laminas/laminas-mail": "^2.12.3",
        "phpstan/phpstan": "^0.12.57",
        "phpstan/phpstan-phpunit": "^0.12.16",
        "phpstan/phpstan-strict-rules": "^0.12.5",
        "phpunit/phpunit": "^9.4.3"
    },
    "config": {
        "platform": {
            "php": "7.3"
        }
    },
    "autoload": {
        "psr-4": {
            "Ddeboer\\Imap\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Ddeboer\\Imap\\Tests\\": "tests/"
        }
    }
}
lib/vendor/ddeboer/imap/LICENSE000064400000002105151163263020012143
0ustar00Copyright (C) 2013 David de Boer <david@ddeboer.nl>

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.lib/vendor/ddeboer/imap/README.md000064400000025110151163263030012417
0ustar00# IMAP library

[![Latest Stable
Version](https://img.shields.io/packagist/v/ddeboer/imap.svg)](https://packagist.org/packages/ddeboer/imap)
[![Downloads](https://img.shields.io/packagist/dt/ddeboer/imap.svg)](https://packagist.org/packages/ddeboer/imap)
[![Integrate](https://github.com/ddeboer/imap/workflows/Integrate/badge.svg?branch=master)](https://github.com/ddeboer/imap/actions)
[![Code
Coverage](https://codecov.io/gh/ddeboer/imap/coverage.svg?branch=master)](https://codecov.io/gh/ddeboer/imap?branch=master)

A PHP 7.3+ library to read and process e-mails over IMAP.

This library requires
[IMAP](https://secure.php.net/manual/en/book.imap.php),
[iconv](https://secure.php.net/manual/en/book.iconv.php) and
[Multibyte String](https://secure.php.net/manual/en/book.mbstring.php)
extensions installed.

## Table of Contents

1. [Feature Requests](#feature-requests)
1. [Installation](#installation)
1. [Usage](#usage)
    1. [Connect and Authenticate](#connect-and-authenticate)
    1. [Mailboxes](#mailboxes)
    1. [Messages](#messages)
        1. [Searching for Messages](#searching-for-messages)
        1. [Unknown search criterion: OR](#unknown-search-criterion-or)
        1. [Message Properties and
Operations](#message-properties-and-operations)
    1. [Message Attachments](#message-attachments)
    1. [Embedded Messages](#embedded-messages)
    1. [Timeouts](#timeouts)
1. [Mock the library](#mock-the-library)
1. [Running the Tests](#running-the-tests)
    1. [Running Tests using Docker](#running-tests-using-docker)

## Feature Requests

[![Feature
Requests](https://feathub.com/ddeboer/imap?format=svg)](https://feathub.com/ddeboer/imap)

## Installation

The recommended way to install the IMAP library is through
[Composer](https://getcomposer.org):

```bash
$ composer require ddeboer/imap
```

This command requires you to have Composer installed globally, as
explained
in the [installation chapter](https://getcomposer.org/doc/00-intro.md)
of the Composer documentation.

## Usage

### Connect and Authenticate

```php
use Ddeboer\Imap\Server;

$server = new Server('imap.gmail.com');

// $connection is instance of \Ddeboer\Imap\Connection
$connection = $server->authenticate('my_username',
'my_password');
```

You can specify port, [flags and
parameters](https://secure.php.net/manual/en/function.imap-open.php)
to the server:

```php
$server = new Server(
    $hostname, // required
    $port,     // defaults to '993'
    $flags,    // defaults to '/imap/ssl/validate-cert'
    $parameters
);
```

### Mailboxes

Retrieve mailboxes (also known as mail folders) from the mail server and
iterate
over them:

```php
$mailboxes = $connection->getMailboxes();

foreach ($mailboxes as $mailbox) {
    // Skip container-only mailboxes
    // @see
https://secure.php.net/manual/en/function.imap-getmailboxes.php
    if ($mailbox->getAttributes() & \LATT_NOSELECT) {
        continue;
    }

    // $mailbox is instance of \Ddeboer\Imap\Mailbox
    printf('Mailbox "%s" has %s messages',
$mailbox->getName(), $mailbox->count());
}
```

Or retrieve a specific mailbox:

```php
$mailbox = $connection->getMailbox('INBOX');
```

Delete a mailbox:

```php
$connection->deleteMailbox($mailbox);
```

You can bulk set, or clear, any
[flag](https://secure.php.net/manual/en/function.imap-setflag-full.php) of
mailbox messages (by UIDs):

```php
$mailbox->setFlag('\\Seen \\Flagged', ['1:5',
'7', '9']);
$mailbox->setFlag('\\Seen', '1,3,5,6:8');

$mailbox->clearFlag('\\Flagged', '1,3');
```

**WARNING** You must retrieve new Message instances in case of bulk modify
flags to refresh the single Messages flags.

### Messages

Retrieve messages (e-mails) from a mailbox and iterate over them:

```php
$messages = $mailbox->getMessages();

foreach ($messages as $message) {
    // $message is instance of \Ddeboer\Imap\Message
}
```

To insert a new message (that just has been sent) into the Sent mailbox and
flag it as seen:

```php
$mailbox = $connection->getMailbox('Sent');
$mailbox->addMessage($messageMIME, '\\Seen');
```

Note that the message should be a string at MIME format (as described in
the [RFC2045](https://tools.ietf.org/html/rfc2045)).

#### Searching for Messages

```php
use Ddeboer\Imap\SearchExpression;
use Ddeboer\Imap\Search\Email\To;
use Ddeboer\Imap\Search\Text\Body;

$search = new SearchExpression();
$search->addCondition(new To('me@here.com'));
$search->addCondition(new Body('contents'));

$messages = $mailbox->getMessages($search);
```

**WARNING** We are currently unable to have both spaces _and_
double-quotes
escaped together. Only spaces are currently escaped correctly.
You can use `Ddeboer\Imap\Search\RawExpression` to write the complete
search
condition by yourself.

Messages can also be retrieved sorted as per
[imap_sort](https://secure.php.net/manual/en/function.imap-sort.php)
function:

```php
$today = new DateTimeImmutable();
$thirtyDaysAgo = $today->sub(new DateInterval('P30D'));

$messages = $mailbox->getMessages(
    new Ddeboer\Imap\Search\Date\Since($thirtyDaysAgo),
    \SORTDATE, // Sort criteria
    true // Descending order
);
```

#### Unknown search criterion: OR

Note that PHP imap library relies on the `c-client` library available at
https://www.washington.edu/imap/
which doesn't fully support some IMAP4 search criteria like `OR`. If
you want those unsupported criteria,
you need to manually patch the latest version (`imap-2007f` of 23-Jul-2011
at the time of this commit)
and recompile PHP onto your patched `c-client` library.

By the way most of the common search criteria are available and
functioning, browse them in `./src/Search`.

References:

1.
https://stackoverflow.com/questions/36356715/imap-search-unknown-search-criterion-or
1. imap-2007f.tar.gz: `./src/c-client/mail.c` and `./docs/internal.txt`

#### Message Properties and Operations

Get message number and unique [message
id](https://en.wikipedia.org/wiki/Message-ID)
in the form <...>:

```php
$message->getNumber();
$message->getId();
```

Get other message properties:

```php
$message->getSubject();
$message->getFrom();    // Message\EmailAddress
$message->getTo();      // array of Message\EmailAddress
$message->getDate();    // DateTimeImmutable
$message->isAnswered();
$message->isDeleted();
$message->isDraft();
$message->isSeen();
```

Get message headers as a
[\Ddeboer\Imap\Message\Headers](/src/Ddeboer/Imap/Message/Headers.php)
object:

```php
$message->getHeaders();
```

Get message body as HTML or plain text:

```php
$message->getBodyHtml();    // Content of text/html part, if present
$message->getBodyText();    // Content of text/plain part, if present
```

Reading the message body keeps the message as unseen.
If you want to mark the message as seen:

```php
$message->markAsSeen();
```

Or you can set, or clear, any
[flag](https://secure.php.net/manual/en/function.imap-setflag-full.php):

```php
$message->setFlag('\\Seen \\Flagged');
$message->clearFlag('\\Flagged');
```

Move a message to another mailbox:

```php
$mailbox = $connection->getMailbox('another-mailbox');
$message->move($mailbox);
$connection->expunge();
```

Deleting messages:

```php
$mailbox->getMessage(1)->delete();
$mailbox->getMessage(2)->delete();
$connection->expunge();
```

### Message Attachments

Get message attachments (both inline and attached) and iterate over them:

```php
$attachments = $message->getAttachments();

foreach ($attachments as $attachment) {
    // $attachment is instance of \Ddeboer\Imap\Message\Attachment
}
```

Download a message attachment to a local file:

```php
// getDecodedContent() decodes the attachment’s contents automatically:
file_put_contents(
    '/my/local/dir/' . $attachment->getFilename(),
    $attachment->getDecodedContent()
);
```

### Embedded Messages

Check if attachment is embedded message and get it:

```php
$attachments = $message->getAttachments();

foreach ($attachments as $attachment) {
    if ($attachment->isEmbeddedMessage()) {
        $embeddedMessage = $attachment->getEmbeddedMessage();
        // $embeddedMessage is instance of
\Ddeboer\Imap\Message\EmbeddedMessage
    }
}
```

An EmbeddedMessage has the same API as a normal Message, apart from flags
and operations like copy, move or delete.

### Timeouts

The IMAP extension provides the
[imap_timeout](https://secure.php.net/manual/en/function.imap-timeout.php)
function to adjust the timeout seconds for various operations.

However the extension's implementation doesn't link the
functionality to a
specific context or connection, instead they are global. So in order to
not
affect functionalities outside this library, we had to choose whether wrap
every `imap_*` call around an optional user-provided timeout or leave this
task to the user.

Because of the heterogeneous world of IMAP servers and the high complexity
burden cost for such a little gain of the former, we chose the latter.

## Mock the library

Mockability is granted by interfaces present for each API.
Dig into [MockabilityTest](tests/MockabilityTest.php) for an example of a
mocked workflow.

## Running the Tests

This library is functionally tested on [Travis
CI](https://travis-ci.org/ddeboer/imap)
against a local Dovecot server.

If you have your own IMAP (test) account, you can run the tests locally by
providing your IMAP credentials:

```bash
$ composer install
$ IMAP_SERVER_NAME="my.imap.server.com"
IMAP_SERVER_PORT="60993" IMAP_USERNAME="johndoe"
IMAP_PASSWORD="p4ssword" vendor/bin/phpunit
```

You can also copy `phpunit.xml.dist` file to a custom `phpunit.xml` and
put
these environment variables in it:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
    bootstrap="./vendor/autoload.php"
    colors="true"
    verbose="true"
>
    <testsuites>
        <testsuite name="ddeboer/imap">
            <directory>./tests/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory
suffix=".php">./src</directory>
        </whitelist>
    </filter>
    <php>
        <env name="IMAP_SERVER_NAME"
value="my.imap.server.com" />
        <env name="IMAP_SERVER_PORT" value="60993"
/>
        <env name="IMAP_USERNAME" value="johndoe"
/>
        <env name="IMAP_PASSWORD" value="p4ssword"
/>
    </php>
</phpunit>
```

**WARNING** Tests create new mailboxes without removing them.

### Running Tests using Docker

If you have Docker installed you can run the tests locally with the
following command:

```
$ docker-compose run tests
```
lib/vendor/ddeboer/imap/src/Connection.php000064400000014367151163263030014553
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

use Ddeboer\Imap\Exception\CreateMailboxException;
use Ddeboer\Imap\Exception\DeleteMailboxException;
use Ddeboer\Imap\Exception\ImapGetmailboxesException;
use Ddeboer\Imap\Exception\ImapNumMsgException;
use Ddeboer\Imap\Exception\ImapQuotaException;
use Ddeboer\Imap\Exception\InvalidResourceException;
use Ddeboer\Imap\Exception\MailboxDoesNotExistException;

/**
 * A connection to an IMAP server that is authenticated for a user.
 */
final class Connection implements ConnectionInterface
{
    /**
     * @var ImapResourceInterface
     */
    private $resource;

    /**
     * @var string
     */
    private $server;

    /**
     * @var null|array
     */
    private $mailboxes;

    /**
     * @var null|array
     */
    private $mailboxNames;

    /**
     * Constructor.
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(ImapResourceInterface $resource, string
$server)
    {
        $this->resource = $resource;
        $this->server   = $server;
    }

    /**
     * Get IMAP resource.
     */
    public function getResource(): ImapResourceInterface
    {
        return $this->resource;
    }

    /**
     * Delete all messages marked for deletion.
     */
    public function expunge(): bool
    {
        return \imap_expunge($this->resource->getStream());
    }

    /**
     * Close connection.
     */
    public function close(int $flag = 0): bool
    {
        $this->resource->clearLastMailboxUsedCache();

        return \imap_close($this->resource->getStream(), $flag);
    }

    /**
     * Get Mailbox quota.
     */
    public function getQuota(string $root = 'INBOX'): array
    {
        $errorMessage = null;
        $errorNumber  = 0;
        \set_error_handler(static function ($nr, $message) use
(&$errorMessage, &$errorNumber): bool {
            $errorMessage = $message;
            $errorNumber = $nr;

            return true;
        });

        $return = \imap_get_quotaroot($this->resource->getStream(),
$root);

        \restore_error_handler();

        if (false === $return || null !== $errorMessage) {
            throw new ImapQuotaException(
                \sprintf(
                    'IMAP Quota request failed for
"%s"%s',
                    $root,
                    null !== $errorMessage ? ': ' . $errorMessage
: ''
                ),
                $errorNumber
            );
        }

        return $return;
    }

    /**
     * Get a list of mailboxes (also known as folders).
     *
     * @return MailboxInterface[]
     */
    public function getMailboxes(): array
    {
        $this->initMailboxNames();

        if (null === $this->mailboxes) {
            $this->mailboxes = [];
            foreach ($this->mailboxNames as $mailboxName =>
$mailboxInfo) {
                $this->mailboxes[(string) $mailboxName] =
$this->getMailbox((string) $mailboxName);
            }
        }

        return $this->mailboxes;
    }

    /**
     * Check that a mailbox with the given name exists.
     *
     * @param string $name Mailbox name
     */
    public function hasMailbox(string $name): bool
    {
        $this->initMailboxNames();

        return isset($this->mailboxNames[$name]);
    }

    /**
     * Get a mailbox by its name.
     *
     * @param string $name Mailbox name
     *
     * @throws MailboxDoesNotExistException If mailbox does not exist
     */
    public function getMailbox(string $name): MailboxInterface
    {
        if (false === $this->hasMailbox($name)) {
            throw new MailboxDoesNotExistException(\sprintf('Mailbox
name "%s" does not exist', $name));
        }

        return new Mailbox($this->resource, $name,
$this->mailboxNames[$name]);
    }

    /**
     * Count number of messages not in any mailbox.
     *
     * @return int
     */
    public function count()
    {
        $return = \imap_num_msg($this->resource->getStream());

        if (false === $return) {
            throw new ImapNumMsgException('imap_num_msg
failed');
        }

        return $return;
    }

    /**
     * Check if the connection is still active.
     *
     * @throws InvalidResourceException If connection was closed
     */
    public function ping(): bool
    {
        return \imap_ping($this->resource->getStream());
    }

    /**
     * Create mailbox.
     *
     * @throws CreateMailboxException
     */
    public function createMailbox(string $name): MailboxInterface
    {
        if (false ===
\imap_createmailbox($this->resource->getStream(), $this->server .
\mb_convert_encoding($name, 'UTF7-IMAP', 'UTF-8'))) {
            throw new CreateMailboxException(\sprintf('Can not create
"%s" mailbox at "%s"', $name, $this->server));
        }

        $this->mailboxNames = $this->mailboxes = null;
        $this->resource->clearLastMailboxUsedCache();

        return $this->getMailbox($name);
    }

    /**
     * Create mailbox.
     *
     * @throws DeleteMailboxException
     */
    public function deleteMailbox(MailboxInterface $mailbox): void
    {
        if (false ===
\imap_deletemailbox($this->resource->getStream(),
$mailbox->getFullEncodedName())) {
            throw new DeleteMailboxException(\sprintf('Mailbox
"%s" could not be deleted', $mailbox->getName()));
        }

        $this->mailboxes = $this->mailboxNames = null;
        $this->resource->clearLastMailboxUsedCache();
    }

    /**
     * Get mailbox names.
     */
    private function initMailboxNames(): void
    {
        if (null !== $this->mailboxNames) {
            return;
        }

        $this->mailboxNames = [];
        $mailboxesInfo      =
\imap_getmailboxes($this->resource->getStream(), $this->server,
'*');
        if (!\is_array($mailboxesInfo)) {
            throw new ImapGetmailboxesException('imap_getmailboxes
failed');
        }

        foreach ($mailboxesInfo as $mailboxInfo) {
            $name                      =
\mb_convert_encoding(\str_replace($this->server, '',
$mailboxInfo->name), 'UTF-8', 'UTF7-IMAP');
            \assert(\is_string($name));
            $this->mailboxNames[$name] = $mailboxInfo;
        }
    }
}
lib/vendor/ddeboer/imap/src/ConnectionInterface.php000064400000002657151163263030016373
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

/**
 * A connection to an IMAP server that is authenticated for a user.
 */
interface ConnectionInterface extends \Countable
{
    /**
     * Get IMAP resource.
     */
    public function getResource(): ImapResourceInterface;

    /**
     * Delete all messages marked for deletion.
     */
    public function expunge(): bool;

    /**
     * Close connection.
     */
    public function close(int $flag = 0): bool;

    /**
     * Check if the connection is still active.
     */
    public function ping(): bool;

    /**
     * Get Mailbox quota.
     */
    public function getQuota(string $root = 'INBOX'): array;

    /**
     * Get a list of mailboxes (also known as folders).
     *
     * @return MailboxInterface[]
     */
    public function getMailboxes(): array;

    /**
     * Check that a mailbox with the given name exists.
     *
     * @param string $name Mailbox name
     */
    public function hasMailbox(string $name): bool;

    /**
     * Get a mailbox by its name.
     *
     * @param string $name Mailbox name
     */
    public function getMailbox(string $name): MailboxInterface;

    /**
     * Create mailbox.
     */
    public function createMailbox(string $name): MailboxInterface;

    /**
     * Delete mailbox.
     */
    public function deleteMailbox(MailboxInterface $mailbox): void;
}
lib/vendor/ddeboer/imap/src/Exception/AbstractException.php000064400000004064151163263030020025
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

abstract class AbstractException extends \RuntimeException
{
    /**
     * @var array
     */
    private static $errorLabels = [
        \E_ERROR                => 'E_ERROR',
        \E_WARNING              => 'E_WARNING',
        \E_PARSE                => 'E_PARSE',
        \E_NOTICE               => 'E_NOTICE',
        \E_CORE_ERROR           => 'E_CORE_ERROR',
        \E_CORE_WARNING         => 'E_CORE_WARNING',
        \E_COMPILE_ERROR        => 'E_COMPILE_ERROR',
        \E_COMPILE_WARNING      => 'E_COMPILE_WARNING',
        \E_USER_ERROR           => 'E_USER_ERROR',
        \E_USER_WARNING         => 'E_USER_WARNING',
        \E_USER_NOTICE          => 'E_USER_NOTICE',
        \E_STRICT               => 'E_STRICT',
        \E_RECOVERABLE_ERROR    => 'E_RECOVERABLE_ERROR',
        \E_DEPRECATED           => 'E_DEPRECATED',
        \E_USER_DEPRECATED      => 'E_USER_DEPRECATED',
    ];

    /**
     * @param string     $message  The exception message
     * @param int        $code     The exception code
     * @param \Throwable $previous The previous exception
     */
    final public function __construct(string $message, int $code = 0,
\Throwable $previous = null)
    {
        $errorType = '';
        if (isset(self::$errorLabels[$code])) {
            $errorType = \sprintf('[%s] ',
self::$errorLabels[$code]);
        }

        $joinString      = "\n- ";
        $alerts          = \imap_alerts();
        $errors          = \imap_errors();
        $completeMessage = \sprintf(
            "%s%s\nimap_alerts (%s):%s\nimap_errors (%s):%s",
            $errorType,
            $message,
            false !== $alerts ? \count($alerts) : 0,
            false !== $alerts ? $joinString . \implode($joinString,
$alerts) : '',
            false !== $errors ? \count($errors) : 0,
            false !== $errors ? $joinString . \implode($joinString,
$errors) : ''
        );

        parent::__construct($completeMessage, $code, $previous);
    }
}
lib/vendor/ddeboer/imap/src/Exception/AuthenticationFailedException.php000064400000000225151163263030022341
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class AuthenticationFailedException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/CreateMailboxException.php000064400000000216151163263030020774
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class CreateMailboxException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/DeleteMailboxException.php000064400000000216151163263030020773
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class DeleteMailboxException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/ImapFetchbodyException.php000064400000000216151163263030020773
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class ImapFetchbodyException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/ImapFetchheaderException.php000064400000000220151163263030021261
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class ImapFetchheaderException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/ImapGetmailboxesException.php000064400000000221151163263040021504
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class ImapGetmailboxesException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/ImapMsgnoException.php000064400000000212151163263040020144
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class ImapMsgnoException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/ImapNumMsgException.php000064400000000213151163263040020270
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class ImapNumMsgException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/ImapQuotaException.php000064400000000212151163263040020152
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class ImapQuotaException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/ImapStatusException.php000064400000000213151163263040020345
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class ImapStatusException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/InvalidDateHeaderException.php000064400000000222151163263040021550
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class InvalidDateHeaderException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/InvalidHeadersException.php000064400000000217151163263050021142
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class InvalidHeadersException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/InvalidResourceException.php000064400000000220151163263050021350
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class InvalidResourceException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/InvalidSearchCriteriaException.php000064400000000226151163263050022457
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class InvalidSearchCriteriaException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/MailboxDoesNotExistException.php000064400000000224151163263050022162
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class MailboxDoesNotExistException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/MessageCopyException.php000064400000000214151163263050020474
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class MessageCopyException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/MessageDeleteException.php000064400000000216151163263050020766
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class MessageDeleteException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/MessageDoesNotExistException.php000064400000000224151163263050022153
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class MessageDoesNotExistException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/MessageMoveException.php000064400000000214151163263050020470
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class MessageMoveException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/MessageStructureException.php000064400000000221151163263050021560
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class MessageStructureException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/MessageUndeleteException.php000064400000000220151163263050021324
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class MessageUndeleteException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/NotEmbeddedMessageException.php000064400000000223151163263050021734
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class NotEmbeddedMessageException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/OutOfBoundsException.php000064400000000214151163263060020465
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class OutOfBoundsException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/ReopenMailboxException.php000064400000000216151163263060021024
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class ReopenMailboxException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/ResourceCheckFailureException.php000064400000000225151163263060022315
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class ResourceCheckFailureException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/UnexpectedEncodingException.php000064400000000223151163263060022031
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class UnexpectedEncodingException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/Exception/UnsupportedCharsetException.php000064400000000223151163263060022120
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Exception;

final class UnsupportedCharsetException extends AbstractException
{
}
lib/vendor/ddeboer/imap/src/ImapResource.php000064400000005215151163263060015045
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

use Ddeboer\Imap\Exception\InvalidResourceException;
use Ddeboer\Imap\Exception\ReopenMailboxException;

/**
 * An imap resource stream.
 */
final class ImapResource implements ImapResourceInterface
{
    /**
     * @var mixed
     */
    private $resource;

    /**
     * @var null|MailboxInterface
     */
    private $mailbox;

    /**
     * @var null|string
     */
    private static $lastMailboxUsedCache;

    /**
     * Constructor.
     *
     * @param resource $resource
     */
    public function __construct($resource, MailboxInterface $mailbox =
null)
    {
        $this->resource = $resource;
        $this->mailbox  = $mailbox;
    }

    /**
     * Get IMAP resource stream.
     *
     * @throws InvalidResourceException
     *
     * @return resource
     */
    public function getStream()
    {
        if (false === \is_resource($this->resource) || 'imap'
!== \get_resource_type($this->resource)) {
            throw new InvalidResourceException('Supplied resource is
not a valid imap resource');
        }

        $this->initMailbox();

        return $this->resource;
    }

    /**
     * Clear last mailbox used cache.
     */
    public function clearLastMailboxUsedCache(): void
    {
        self::$lastMailboxUsedCache = null;
    }

    /**
     * If connection is not currently in this mailbox, switch it to this
mailbox.
     */
    private function initMailbox(): void
    {
        if (null === $this->mailbox ||
self::isMailboxOpen($this->mailbox, $this->resource)) {
            return;
        }

        \imap_reopen($this->resource,
$this->mailbox->getFullEncodedName());

        if (self::isMailboxOpen($this->mailbox, $this->resource)) {
            return;
        }

        throw new ReopenMailboxException(\sprintf('Cannot reopen
mailbox "%s"', $this->mailbox->getName()));
    }

    /**
     * Check whether the current mailbox is open.
     *
     * @param mixed $resource
     */
    private static function isMailboxOpen(MailboxInterface $mailbox,
$resource): bool
    {
        $currentMailboxName = $mailbox->getFullEncodedName();
        if ($currentMailboxName === self::$lastMailboxUsedCache) {
            return true;
        }

        self::$lastMailboxUsedCache = null;
        $check                      = \imap_check($resource);
        $return                     = false !== $check &&
$check->Mailbox === $currentMailboxName;

        if (true === $return) {
            self::$lastMailboxUsedCache = $currentMailboxName;
        }

        return $return;
    }
}
lib/vendor/ddeboer/imap/src/ImapResourceInterface.php000064400000000521151163263060016661
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

interface ImapResourceInterface
{
    /**
     * Get IMAP resource stream.
     *
     * @return resource
     */
    public function getStream();

    /**
     * Clear last mailbox used cache.
     */
    public function clearLastMailboxUsedCache(): void;
}
lib/vendor/ddeboer/imap/src/Mailbox.php000064400000022452151163263060014044
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

use DateTimeInterface;
use Ddeboer\Imap\Exception\ImapNumMsgException;
use Ddeboer\Imap\Exception\ImapStatusException;
use Ddeboer\Imap\Exception\InvalidSearchCriteriaException;
use Ddeboer\Imap\Exception\MessageCopyException;
use Ddeboer\Imap\Exception\MessageMoveException;
use Ddeboer\Imap\Search\ConditionInterface;
use Ddeboer\Imap\Search\LogicalOperator\All;

/**
 * An IMAP mailbox (commonly referred to as a 'folder').
 */
final class Mailbox implements MailboxInterface
{
    /**
     * @var ImapResourceInterface
     */
    private $resource;

    /**
     * @var string
     */
    private $name;

    /**
     * @var \stdClass
     */
    private $info;

    /**
     * Constructor.
     *
     * @param ImapResourceInterface $resource IMAP resource
     * @param string                $name     Mailbox decoded name
     * @param \stdClass             $info     Mailbox info
     */
    public function __construct(ImapResourceInterface $resource, string
$name, \stdClass $info)
    {
        $this->resource = new ImapResource($resource->getStream(),
$this);
        $this->name     = $name;
        $this->info     = $info;
    }

    /**
     * Get mailbox decoded name.
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * Get mailbox encoded path.
     */
    public function getEncodedName(): string
    {
        /** @var string $name */
        $name = $this->info->name;

        return (string) \preg_replace('/^{.+}/', '',
$name);
    }

    /**
     * Get mailbox encoded full name.
     */
    public function getFullEncodedName(): string
    {
        return $this->info->name;
    }

    /**
     * Get mailbox attributes.
     */
    public function getAttributes(): int
    {
        return $this->info->attributes;
    }

    /**
     * Get mailbox delimiter.
     */
    public function getDelimiter(): string
    {
        return $this->info->delimiter;
    }

    /**
     * Get number of messages in this mailbox.
     *
     * @return int
     */
    public function count()
    {
        $return = \imap_num_msg($this->resource->getStream());

        if (false === $return) {
            throw new ImapNumMsgException('imap_num_msg
failed');
        }

        return $return;
    }

    /**
     * Get Mailbox status.
     */
    public function getStatus(int $flags = null): \stdClass
    {
        $return = \imap_status($this->resource->getStream(),
$this->getFullEncodedName(), $flags ?? \SA_ALL);

        if (false === $return) {
            throw new ImapStatusException('imap_status failed');
        }

        return $return;
    }

    /**
     * Bulk Set Flag for Messages.
     *
     * @param string                       $flag    \Seen, \Answered,
\Flagged, \Deleted, and \Draft
     * @param array|MessageIterator|string $numbers Message numbers
     */
    public function setFlag(string $flag, $numbers): bool
    {
        return \imap_setflag_full($this->resource->getStream(),
$this->prepareMessageIds($numbers), $flag, \ST_UID);
    }

    /**
     * Bulk Clear Flag for Messages.
     *
     * @param string                       $flag    \Seen, \Answered,
\Flagged, \Deleted, and \Draft
     * @param array|MessageIterator|string $numbers Message numbers
     */
    public function clearFlag(string $flag, $numbers): bool
    {
        return \imap_clearflag_full($this->resource->getStream(),
$this->prepareMessageIds($numbers), $flag, \ST_UID);
    }

    /**
     * Get message ids.
     *
     * @param ConditionInterface $search Search expression (optional)
     */
    public function getMessages(ConditionInterface $search = null, int
$sortCriteria = null, bool $descending = false, string $charset = null):
MessageIteratorInterface
    {
        if (null === $search) {
            $search = new All();
        }
        $query = $search->toString();

        if (\PHP_VERSION_ID < 80000) {
            $descending = (int) $descending;
        }

        // We need to clear the stack to know whether imap_last_error()
        // is related to this imap_search
        \imap_errors();

        if (null !== $sortCriteria) {
            $params = [
                $this->resource->getStream(),
                $sortCriteria,
                $descending,
                \SE_UID,
                $query,
            ];
            if (null !== $charset) {
                $params[] = $charset;
            }
            $messageNumbers = \imap_sort(...$params);
        } else {
            $params = [
                $this->resource->getStream(),
                $query,
                \SE_UID,
            ];
            if (null !== $charset) {
                $params[] = $charset;
            }
            $messageNumbers = \imap_search(...$params);
        }
        if (false !== \imap_last_error()) {
            // this way all errors occurred during search will be reported
            throw new InvalidSearchCriteriaException(
                \sprintf('Invalid search criteria [%s]', $query)
            );
        }
        if (false === $messageNumbers) {
            // imap_search can also return false
            $messageNumbers = [];
        }

        return new MessageIterator($this->resource, $messageNumbers);
    }

    /**
     * Get message iterator for a sequence.
     *
     * @param string $sequence Message numbers
     */
    public function getMessageSequence(string $sequence):
MessageIteratorInterface
    {
        \imap_errors();

        $overview =
\imap_fetch_overview($this->resource->getStream(), $sequence,
\FT_UID);
        if (false !== \imap_last_error()) {
            throw new InvalidSearchCriteriaException(
                \sprintf('Invalid sequence [%s]', $sequence)
            );
        }
        if (\is_array($overview) && [] !== $overview) {
            $messageNumbers = \array_column($overview, 'uid');
        } else {
            $messageNumbers = [];
        }

        return new MessageIterator($this->resource, $messageNumbers);
    }

    /**
     * Get a message by message number.
     *
     * @param int $number Message number
     */
    public function getMessage(int $number): MessageInterface
    {
        return new Message($this->resource, $number);
    }

    /**
     * Get messages in this mailbox.
     */
    public function getIterator(): MessageIteratorInterface
    {
        return $this->getMessages();
    }

    /**
     * Add a message to the mailbox.
     */
    public function addMessage(string $message, string $options = null,
DateTimeInterface $internalDate = null): bool
    {
        $arguments = [
            $this->resource->getStream(),
            $this->getFullEncodedName(),
            $message,
        ];
        if (null !== $options) {
            $arguments[] = $options;
            if (null !== $internalDate) {
                $arguments[] = $internalDate->format('d-M-Y H:i:s
O');
            }
        }

        return \imap_append(...$arguments);
    }

    /**
     * Returns a tree of threaded message for the current Mailbox.
     */
    public function getThread(): array
    {
        \set_error_handler(static function (): bool {
            return true;
        });

        /** @var array|false $tree */
        $tree = \imap_thread($this->resource->getStream(), \SE_UID);

        \restore_error_handler();

        return false !== $tree ? $tree : [];
    }

    /**
     * Bulk move messages.
     *
     * @param array|MessageIterator|string $numbers Message numbers
     * @param MailboxInterface             $mailbox Destination Mailbox to
move the messages to
     *
     * @throws \Ddeboer\Imap\Exception\MessageMoveException
     */
    public function move($numbers, MailboxInterface $mailbox): void
    {
        if (!\imap_mail_move($this->resource->getStream(),
$this->prepareMessageIds($numbers), $mailbox->getEncodedName(),
\CP_UID)) {
            throw new MessageMoveException(\sprintf('Messages cannot
be moved to "%s"', $mailbox->getName()));
        }
    }

    /**
     * Bulk copy messages.
     *
     * @param array|MessageIterator|string $numbers Message numbers
     * @param MailboxInterface             $mailbox Destination Mailbox to
copy the messages to
     *
     * @throws \Ddeboer\Imap\Exception\MessageCopyException
     */
    public function copy($numbers, MailboxInterface $mailbox): void
    {
        if (!\imap_mail_copy($this->resource->getStream(),
$this->prepareMessageIds($numbers), $mailbox->getEncodedName(),
\CP_UID)) {
            throw new MessageCopyException(\sprintf('Messages cannot
be copied to "%s"', $mailbox->getName()));
        }
    }

    /**
     * Prepare message ids for the use with bulk functions.
     *
     * @param array|MessageIterator|string $messageIds Message numbers
     */
    private function prepareMessageIds($messageIds): string
    {
        if ($messageIds instanceof MessageIterator) {
            $messageIds = $messageIds->getArrayCopy();
        }

        if (\is_array($messageIds)) {
            $messageIds = \implode(',', $messageIds);
        }

        return $messageIds;
    }
}
lib/vendor/ddeboer/imap/src/MailboxInterface.php000064400000006313151163263060015663
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

use DateTimeInterface;
use Ddeboer\Imap\Search\ConditionInterface;

/**
 * An IMAP mailbox (commonly referred to as a 'folder').
 */
interface MailboxInterface extends \Countable, \IteratorAggregate
{
    /**
     * Get mailbox decoded name.
     */
    public function getName(): string;

    /**
     * Get mailbox encoded path.
     */
    public function getEncodedName(): string;

    /**
     * Get mailbox encoded full name.
     */
    public function getFullEncodedName(): string;

    /**
     * Get mailbox attributes.
     */
    public function getAttributes(): int;

    /**
     * Get mailbox delimiter.
     */
    public function getDelimiter(): string;

    /**
     * Get Mailbox status.
     */
    public function getStatus(int $flags = null): \stdClass;

    /**
     * Bulk Set Flag for Messages.
     *
     * @param string                       $flag    \Seen, \Answered,
\Flagged, \Deleted, and \Draft
     * @param array|MessageIterator|string $numbers Message numbers
     */
    public function setFlag(string $flag, $numbers): bool;

    /**
     * Bulk Clear Flag for Messages.
     *
     * @param string                       $flag    \Seen, \Answered,
\Flagged, \Deleted, and \Draft
     * @param array|MessageIterator|string $numbers Message numbers
     */
    public function clearFlag(string $flag, $numbers): bool;

    /**
     * Get message ids.
     *
     * @param ConditionInterface $search Search expression (optional)
     */
    public function getMessages(ConditionInterface $search = null, int
$sortCriteria = null, bool $descending = false, string $charset = null):
MessageIteratorInterface;

    /**
     * Get message iterator for a sequence.
     *
     * @param string $sequence Message numbers
     */
    public function getMessageSequence(string $sequence):
MessageIteratorInterface;

    /**
     * Get a message by message number.
     *
     * @param int $number Message number
     */
    public function getMessage(int $number): MessageInterface;

    /**
     * Get messages in this mailbox.
     */
    public function getIterator(): MessageIteratorInterface;

    /**
     * Add a message to the mailbox.
     */
    public function addMessage(string $message, string $options = null,
DateTimeInterface $internalDate = null): bool;

    /**
     * Returns a tree of threaded message for the current Mailbox.
     */
    public function getThread(): array;

    /**
     * Bulk move messages.
     *
     * @param array|MessageIterator|string $numbers Message numbers
     * @param MailboxInterface             $mailbox Destination Mailbox to
move the messages to
     *
     * @throws \Ddeboer\Imap\Exception\MessageMoveException
     */
    public function move($numbers, self $mailbox): void;

    /**
     * Bulk copy messages.
     *
     * @param array|MessageIterator|string $numbers Message numbers
     * @param MailboxInterface             $mailbox Destination Mailbox to
copy the messages to
     *
     * @throws \Ddeboer\Imap\Exception\MessageCopyException
     */
    public function copy($numbers, self $mailbox): void;
}
lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php000064400000016534151163263060017111
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

use Ddeboer\Imap\Exception\InvalidDateHeaderException;

abstract class AbstractMessage extends AbstractPart
{
    /**
     * @var null|array
     */
    private $attachments;

    /**
     * Get message headers.
     */
    abstract public function getHeaders(): Headers;

    /**
     * Get message id.
     *
     * A unique message id in the form <...>
     */
    final public function getId(): ?string
    {
        return $this->getHeaders()->get('message_id');
    }

    /**
     * Get message sender (from headers).
     */
    final public function getFrom(): ?EmailAddress
    {
        $from = $this->getHeaders()->get('from');

        return null !== $from ? $this->decodeEmailAddress($from[0]) :
null;
    }

    /**
     * Get To recipients.
     *
     * @return EmailAddress[] Empty array in case message has no To:
recipients
     */
    final public function getTo(): array
    {
        return
$this->decodeEmailAddresses($this->getHeaders()->get('to')
?: []);
    }

    /**
     * Get Cc recipients.
     *
     * @return EmailAddress[] Empty array in case message has no CC:
recipients
     */
    final public function getCc(): array
    {
        return
$this->decodeEmailAddresses($this->getHeaders()->get('cc')
?: []);
    }

    /**
     * Get Bcc recipients.
     *
     * @return EmailAddress[] Empty array in case message has no BCC:
recipients
     */
    final public function getBcc(): array
    {
        return
$this->decodeEmailAddresses($this->getHeaders()->get('bcc')
?: []);
    }

    /**
     * Get Reply-To recipients.
     *
     * @return EmailAddress[] Empty array in case message has no Reply-To:
recipients
     */
    final public function getReplyTo(): array
    {
        return
$this->decodeEmailAddresses($this->getHeaders()->get('reply_to')
?: []);
    }

    /**
     * Get Sender.
     *
     * @return EmailAddress[] Empty array in case message has no Sender:
recipients
     */
    final public function getSender(): array
    {
        return
$this->decodeEmailAddresses($this->getHeaders()->get('sender')
?: []);
    }

    /**
     * Get Return-Path.
     *
     * @return EmailAddress[] Empty array in case message has no
Return-Path: recipients
     */
    final public function getReturnPath(): array
    {
        return
$this->decodeEmailAddresses($this->getHeaders()->get('return_path')
?: []);
    }

    /**
     * Get date (from headers).
     */
    final public function getDate(): ?\DateTimeImmutable
    {
        /** @var null|string $dateHeader */
        $dateHeader = $this->getHeaders()->get('date');
        if (null === $dateHeader) {
            return null;
        }

        $alteredValue = $dateHeader;
        $alteredValue = \str_replace(',', '',
$alteredValue);
        $alteredValue = (string) \preg_replace('/^[a-zA-Z]+ ?/',
'', $alteredValue);
        $alteredValue = (string) \preg_replace('/\(.*\)/',
'', $alteredValue);
        $alteredValue = (string) \preg_replace('/\<.*\>/',
'', $alteredValue);
        $alteredValue = (string) \preg_replace('/\bUT\b/',
'UTC', $alteredValue);
        if (0 === \preg_match('/\d\d:\d\d:\d\d.*
[\+\-]\d\d:?\d\d/', $alteredValue)) {
            $alteredValue .= ' +0000';
        }
        // Handle numeric months
        $alteredValue = (string) \preg_replace('/^(\d\d) (\d\d)
(\d\d(?:\d\d)?) /', '$3-$2-$1 ', $alteredValue);

        try {
            $date = new \DateTimeImmutable($alteredValue);
        } catch (\Throwable $ex) {
            throw new InvalidDateHeaderException(\sprintf('Invalid
Date header found: "%s"', $dateHeader), 0, $ex);
        }

        return $date;
    }

    /**
     * Get message size (from headers).
     *
     * @return null|int|string
     */
    final public function getSize()
    {
        return $this->getHeaders()->get('size');
    }

    /**
     * Get message subject (from headers).
     */
    final public function getSubject(): ?string
    {
        return $this->getHeaders()->get('subject');
    }

    /**
     * Get message In-Reply-To (from headers).
     */
    final public function getInReplyTo(): array
    {
        $inReplyTo =
$this->getHeaders()->get('in_reply_to');

        return null !== $inReplyTo ? \explode(' ', $inReplyTo) :
[];
    }

    /**
     * Get message References (from headers).
     */
    final public function getReferences(): array
    {
        $references =
$this->getHeaders()->get('references');

        return null !== $references ? \explode(' ', $references)
: [];
    }

    /**
     * Get body HTML.
     */
    final public function getBodyHtml(): ?string
    {
        $iterator = new \RecursiveIteratorIterator($this,
\RecursiveIteratorIterator::SELF_FIRST);
        foreach ($iterator as $part) {
            if (self::SUBTYPE_HTML === $part->getSubtype()) {
                return $part->getDecodedContent();
            }
        }

        // If message has no parts and is HTML, return content of message
itself.
        if (self::SUBTYPE_HTML === $this->getSubtype()) {
            return $this->getDecodedContent();
        }

        return null;
    }

    /**
     * Get body text.
     */
    final public function getBodyText(): ?string
    {
        $iterator = new \RecursiveIteratorIterator($this,
\RecursiveIteratorIterator::SELF_FIRST);
        foreach ($iterator as $part) {
            if (self::SUBTYPE_PLAIN === $part->getSubtype()) {
                return $part->getDecodedContent();
            }
        }

        // If message has no parts, return content of message itself.
        if (self::SUBTYPE_PLAIN === $this->getSubtype()) {
            return $this->getDecodedContent();
        }

        return null;
    }

    /**
     * Get attachments (if any) linked to this e-mail.
     *
     * @return AttachmentInterface[]
     */
    final public function getAttachments(): array
    {
        if (null === $this->attachments) {
            $this->attachments = self::gatherAttachments($this);
        }

        return $this->attachments;
    }

    private static function gatherAttachments(PartInterface $part): array
    {
        $attachments = [];
        foreach ($part->getParts() as $childPart) {
            if ($childPart instanceof Attachment) {
                $attachments[] = $childPart;
            }
            if ($childPart->hasChildren()) {
                $attachments = \array_merge($attachments,
self::gatherAttachments($childPart));
            }
        }

        return $attachments;
    }

    /**
     * Does this message have attachments?
     */
    final public function hasAttachments(): bool
    {
        return \count($this->getAttachments()) > 0;
    }

    /**
     * @param \stdClass[] $addresses
     */
    private function decodeEmailAddresses(array $addresses): array
    {
        $return = [];
        foreach ($addresses as $address) {
            if (isset($address->mailbox)) {
                $return[] = $this->decodeEmailAddress($address);
            }
        }

        return $return;
    }

    private function decodeEmailAddress(\stdClass $value): EmailAddress
    {
        return new EmailAddress($value->mailbox, $value->host,
$value->personal);
    }
}
lib/vendor/ddeboer/imap/src/Message/AbstractPart.php000064400000032713151163263060016430
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

use Ddeboer\Imap\Exception\ImapFetchbodyException;
use Ddeboer\Imap\Exception\UnexpectedEncodingException;
use Ddeboer\Imap\ImapResourceInterface;
use Ddeboer\Imap\Message;

/**
 * A message part.
 */
abstract class AbstractPart implements PartInterface
{
    /**
     * @var ImapResourceInterface
     */
    protected $resource;

    /**
     * @var bool
     */
    private $structureParsed = false;

    /**
     * @var array
     */
    private $parts = [];

    /**
     * @var string
     */
    private $partNumber;

    /**
     * @var int
     */
    private $messageNumber;

    /**
     * @var \stdClass
     */
    private $structure;

    /**
     * @var Parameters
     */
    private $parameters;

    /**
     * @var null|string
     */
    private $type;

    /**
     * @var null|string
     */
    private $subtype;

    /**
     * @var null|string
     */
    private $encoding;

    /**
     * @var null|string
     */
    private $disposition;

    /**
     * @var null|string
     */
    private $description;

    /**
     * @var null|string
     */
    private $bytes;

    /**
     * @var null|string
     */
    private $lines;

    /**
     * @var null|string
     */
    private $content;

    /**
     * @var null|string
     */
    private $decodedContent;

    /**
     * @var int
     */
    private $key = 0;

    /**
     * @var array
     */
    private static $typesMap = [
        \TYPETEXT        => self::TYPE_TEXT,
        \TYPEMULTIPART   => self::TYPE_MULTIPART,
        \TYPEMESSAGE     => self::TYPE_MESSAGE,
        \TYPEAPPLICATION => self::TYPE_APPLICATION,
        \TYPEAUDIO       => self::TYPE_AUDIO,
        \TYPEIMAGE       => self::TYPE_IMAGE,
        \TYPEVIDEO       => self::TYPE_VIDEO,
        \TYPEMODEL       => self::TYPE_MODEL,
        \TYPEOTHER       => self::TYPE_OTHER,
    ];

    /**
     * @var array
     */
    private static $encodingsMap = [
        \ENC7BIT            => self::ENCODING_7BIT,
        \ENC8BIT            => self::ENCODING_8BIT,
        \ENCBINARY          => self::ENCODING_BINARY,
        \ENCBASE64          => self::ENCODING_BASE64,
        \ENCQUOTEDPRINTABLE => self::ENCODING_QUOTED_PRINTABLE,
    ];

    /**
     * @var array
     */
    private static $attachmentKeys = [
        'name'      => true,
        'filename'  => true,
        'name*'     => true,
        'filename*' => true,
    ];

    /**
     * Constructor.
     *
     * @param ImapResourceInterface $resource      IMAP resource
     * @param int                   $messageNumber Message number
     * @param string                $partNumber    Part number
     * @param \stdClass             $structure     Part structure
     */
    public function __construct(
        ImapResourceInterface $resource,
        int $messageNumber,
        string $partNumber,
        \stdClass $structure
    ) {
        $this->resource      = $resource;
        $this->messageNumber = $messageNumber;
        $this->partNumber    = $partNumber;
        $this->setStructure($structure);
    }

    /**
     * Get message number (from headers).
     */
    final public function getNumber(): int
    {
        $this->assertMessageExists($this->messageNumber);

        return $this->messageNumber;
    }

    /**
     * Ensure message exists.
     */
    protected function assertMessageExists(int $messageNumber): void
    {
    }

    /**
     * @param \stdClass $structure Part structure
     */
    final protected function setStructure(\stdClass $structure): void
    {
        $this->structure = $structure;
    }

    /**
     * Part structure.
     */
    final public function getStructure(): \stdClass
    {
        $this->lazyLoadStructure();

        return $this->structure;
    }

    /**
     * Lazy load structure.
     */
    protected function lazyLoadStructure(): void
    {
    }

    /**
     * Part parameters.
     */
    final public function getParameters(): Parameters
    {
        $this->lazyParseStructure();

        return $this->parameters;
    }

    /**
     * Part charset.
     */
    final public function getCharset(): ?string
    {
        $this->lazyParseStructure();

        return $this->parameters->get('charset') ?: null;
    }

    /**
     * Part type.
     */
    final public function getType(): ?string
    {
        $this->lazyParseStructure();

        return $this->type;
    }

    /**
     * Part subtype.
     */
    final public function getSubtype(): ?string
    {
        $this->lazyParseStructure();

        return $this->subtype;
    }

    /**
     * Part encoding.
     */
    final public function getEncoding(): ?string
    {
        $this->lazyParseStructure();

        return $this->encoding;
    }

    /**
     * Part disposition.
     */
    final public function getDisposition(): ?string
    {
        $this->lazyParseStructure();

        return $this->disposition;
    }

    /**
     * Part description.
     */
    final public function getDescription(): ?string
    {
        $this->lazyParseStructure();

        return $this->description;
    }

    /**
     * Part bytes.
     *
     * @return null|int|string
     */
    final public function getBytes()
    {
        $this->lazyParseStructure();

        return $this->bytes;
    }

    /**
     * Part lines.
     */
    final public function getLines(): ?string
    {
        $this->lazyParseStructure();

        return $this->lines;
    }

    /**
     * Get raw part content.
     */
    final public function getContent(): string
    {
        if (null === $this->content) {
            $this->content =
$this->doGetContent($this->getContentPartNumber());
        }

        return $this->content;
    }

    /**
     * Get content part number.
     */
    protected function getContentPartNumber(): string
    {
        return $this->partNumber;
    }

    /**
     * Get part number.
     */
    final public function getPartNumber(): string
    {
        return $this->partNumber;
    }

    /**
     * Get decoded part content.
     */
    final public function getDecodedContent(): string
    {
        if (null === $this->decodedContent) {
            if (self::ENCODING_UNKNOWN === $this->getEncoding()) {
                throw new UnexpectedEncodingException('Cannot decode a
content with an uknown encoding');
            }

            $content = $this->getContent();
            if (self::ENCODING_BASE64 === $this->getEncoding()) {
                $content = \base64_decode($content, false);
            } elseif (self::ENCODING_QUOTED_PRINTABLE ===
$this->getEncoding()) {
                $content = \quoted_printable_decode($content);
            }

            if (false === $content) {
                throw new UnexpectedEncodingException('Cannot decode
content');
            }

            // If this part is a text part, convert its charset to UTF-8.
            // We don't want to decode an attachment's charset.
            if (!$this instanceof Attachment && null !==
$this->getCharset() && self::TYPE_TEXT === $this->getType())
{
                $content = Transcoder::decode($content,
$this->getCharset());
            }

            $this->decodedContent = $content;
        }

        return $this->decodedContent;
    }

    /**
     * Get raw message content.
     */
    final protected function doGetContent(string $partNumber): string
    {
        $return = \imap_fetchbody(
            $this->resource->getStream(),
            $this->getNumber(),
            $partNumber,
            \FT_UID | \FT_PEEK
        );

        if (false === $return) {
            throw new ImapFetchbodyException('imap_fetchbody
failed');
        }

        return $return;
    }

    /**
     * Get an array of all parts for this message.
     *
     * @return PartInterface[]
     */
    final public function getParts(): array
    {
        $this->lazyParseStructure();

        return $this->parts;
    }

    /**
     * Get current child part.
     *
     * @return mixed
     */
    final public function current()
    {
        $this->lazyParseStructure();

        return $this->parts[$this->key];
    }

    /**
     * Get current child part.
     *
     * @return \RecursiveIterator
     */
    final public function getChildren()
    {
        return $this->current();
    }

    /**
     * Get current child part.
     *
     * @return bool
     */
    final public function hasChildren()
    {
        $this->lazyParseStructure();

        return \count($this->parts) > 0;
    }

    /**
     * Get current part key.
     *
     * @return int
     */
    final public function key()
    {
        return $this->key;
    }

    /**
     * Move to next part.
     *
     * @return void
     */
    final public function next()
    {
        ++$this->key;
    }

    /**
     * Reset part key.
     *
     * @return void
     */
    final public function rewind()
    {
        $this->key = 0;
    }

    /**
     * Check if current part is a valid one.
     *
     * @return bool
     */
    final public function valid()
    {
        $this->lazyParseStructure();

        return isset($this->parts[$this->key]);
    }

    /**
     * Parse part structure.
     */
    private function lazyParseStructure(): void
    {
        if (true === $this->structureParsed) {
            return;
        }
        $this->structureParsed = true;

        $this->lazyLoadStructure();

        $this->type = self::$typesMap[$this->structure->type] ??
self::TYPE_UNKNOWN;

        // In our context, \ENCOTHER is as useful as an unknown encoding
        $this->encoding =
self::$encodingsMap[$this->structure->encoding] ??
self::ENCODING_UNKNOWN;
        if (isset($this->structure->subtype)) {
            $this->subtype = $this->structure->subtype;
        }

        if (isset($this->structure->bytes)) {
            $this->bytes = $this->structure->bytes;
        }
        if ($this->structure->ifdisposition) {
            $this->disposition = $this->structure->disposition;
        }
        if ($this->structure->ifdescription) {
            $this->description = $this->structure->description;
        }

        $this->parameters = new Parameters();
        if ($this->structure->ifparameters) {
           
$this->parameters->add($this->structure->parameters);
        }

        if ($this->structure->ifdparameters) {
           
$this->parameters->add($this->structure->dparameters);
        }

        // When the message is not multipart and the body is the attachment
content
        // Prevents infinite recursion
        if (self::isAttachment($this->structure) && !$this
instanceof Attachment) {
            $this->parts[] = new Attachment($this->resource,
$this->getNumber(), '1', $this->structure);
        }

        if (isset($this->structure->parts)) {
            $parts = $this->structure->parts;
            //
https://secure.php.net/manual/en/function.imap-fetchbody.php#89002
            if ($this instanceof Attachment &&
$this->isEmbeddedMessage() && 1 === \count($parts) &&
\TYPEMULTIPART === $parts[0]->type) {
                $parts = $parts[0]->parts;
            }
            foreach ($parts as $key => $partStructure) {
                $partNumber = (!$this instanceof Message) ?
$this->partNumber . '.' : '';
                $partNumber .= (string) ($key + 1);

                $newPartClass = self::isAttachment($partStructure)
                    ? Attachment::class
                    : SimplePart::class
                ;

                $this->parts[] = new $newPartClass($this->resource,
$this->getNumber(), $partNumber, $partStructure);
            }
        }
    }

    /**
     * Check if the given part is an attachment.
     */
    private static function isAttachment(\stdClass $part): bool
    {
        if (isset(self::$typesMap[$part->type]) &&
self::TYPE_MULTIPART === self::$typesMap[$part->type]) {
            return false;
        }

        // Attachment with correct Content-Disposition header
        if ($part->ifdisposition) {
            if ('attachment' ===
\strtolower($part->disposition)) {
                return true;
            }

            if (
                    'inline' ===
\strtolower($part->disposition)
                && self::SUBTYPE_PLAIN !==
\strtoupper($part->subtype)
                && self::SUBTYPE_HTML !==
\strtoupper($part->subtype)
            ) {
                return true;
            }
        }

        // Attachment without Content-Disposition header
        if ($part->ifparameters) {
            foreach ($part->parameters as $parameter) {
                if
(isset(self::$attachmentKeys[\strtolower($parameter->attribute)])) {
                    return true;
                }
            }
        }

        /*
        if ($part->ifdparameters) {
            foreach ($part->dparameters as $parameter) {
                if
(isset(self::$attachmentKeys[\strtolower($parameter->attribute)])) {
                    return true;
                }
            }
        }
         */

        if (self::SUBTYPE_RFC822 === \strtoupper($part->subtype)) {
            return true;
        }

        return false;
    }
}
lib/vendor/ddeboer/imap/src/Message/Attachment.php000064400000003043151163263060016120
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

use Ddeboer\Imap\Exception\NotEmbeddedMessageException;

/**
 * An e-mail attachment.
 */
final class Attachment extends AbstractPart implements AttachmentInterface
{
    /**
     * Get attachment filename.
     */
    public function getFilename(): ?string
    {
        return $this->getParameters()->get('filename')
            ?: $this->getParameters()->get('name');
    }

    /**
     * Get attachment file size.
     *
     * @return null|int Number of bytes
     */
    public function getSize()
    {
        $size = $this->getParameters()->get('size');
        if (\is_numeric($size)) {
            $size = (int) $size;
        }

        return $size;
    }

    /**
     * Is this attachment also an Embedded Message?
     */
    public function isEmbeddedMessage(): bool
    {
        return self::TYPE_MESSAGE === $this->getType();
    }

    /**
     * Return embedded message.
     *
     * @throws NotEmbeddedMessageException
     */
    public function getEmbeddedMessage(): EmbeddedMessageInterface
    {
        if (!$this->isEmbeddedMessage()) {
            throw new NotEmbeddedMessageException(\sprintf(
                'Attachment "%s" in message "%s"
is not embedded message',
                $this->getPartNumber(),
                $this->getNumber()
            ));
        }

        return new EmbeddedMessage($this->resource,
$this->getNumber(), $this->getPartNumber(),
$this->getStructure()->parts[0]);
    }
}
lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php000064400000001201151163263060017733
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

/**
 * An e-mail attachment.
 */
interface AttachmentInterface extends PartInterface
{
    /**
     * Get attachment filename.
     */
    public function getFilename(): ?string;

    /**
     * Get attachment file size.
     *
     * @return null|int Number of bytes
     */
    public function getSize();

    /**
     * Is this attachment also an Embedded Message?
     */
    public function isEmbeddedMessage(): bool;

    /**
     * Return embedded message.
     */
    public function getEmbeddedMessage(): EmbeddedMessageInterface;
}
lib/vendor/ddeboer/imap/src/Message/BasicMessageInterface.php000064400000005602151163263060020202
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

interface BasicMessageInterface extends PartInterface
{
    /**
     * Get raw message headers.
     */
    public function getRawHeaders(): string;

    /**
     * Get the raw message, including all headers, parts, etc. unencoded
and unparsed.
     *
     * @return string the raw message
     */
    public function getRawMessage(): string;

    /**
     * Get message headers.
     */
    public function getHeaders(): Headers;

    /**
     * Get message id.
     *
     * A unique message id in the form <...>
     */
    public function getId(): ?string;

    /**
     * Get message sender (from headers).
     */
    public function getFrom(): ?EmailAddress;

    /**
     * Get To recipients.
     *
     * @return EmailAddress[] Empty array in case message has no To:
recipients
     */
    public function getTo(): array;

    /**
     * Get Cc recipients.
     *
     * @return EmailAddress[] Empty array in case message has no CC:
recipients
     */
    public function getCc(): array;

    /**
     * Get Bcc recipients.
     *
     * @return EmailAddress[] Empty array in case message has no BCC:
recipients
     */
    public function getBcc(): array;

    /**
     * Get Reply-To recipients.
     *
     * @return EmailAddress[] Empty array in case message has no Reply-To:
recipients
     */
    public function getReplyTo(): array;

    /**
     * Get Sender.
     *
     * @return EmailAddress[] Empty array in case message has no Sender:
recipients
     */
    public function getSender(): array;

    /**
     * Get Return-Path.
     *
     * @return EmailAddress[] Empty array in case message has no
Return-Path: recipients
     */
    public function getReturnPath(): array;

    /**
     * Get date (from headers).
     */
    public function getDate(): ?\DateTimeImmutable;

    /**
     * Get message size (from headers).
     *
     * @return null|int|string
     */
    public function getSize();

    /**
     * Get message subject (from headers).
     */
    public function getSubject(): ?string;

    /**
     * Get message In-Reply-To (from headers).
     */
    public function getInReplyTo(): array;

    /**
     * Get message References (from headers).
     */
    public function getReferences(): array;

    /**
     * Get body HTML.
     *
     * @return null|string Null if message has no HTML message part
     */
    public function getBodyHtml(): ?string;

    /**
     * Get body text.
     */
    public function getBodyText(): ?string;

    /**
     * Get attachments (if any) linked to this e-mail.
     *
     * @return AttachmentInterface[]
     */
    public function getAttachments(): array;

    /**
     * Does this message have attachments?
     */
    public function hasAttachments(): bool;
}
lib/vendor/ddeboer/imap/src/Message/EmailAddress.php000064400000003024151163263060016364
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

/**
 * An e-mail address.
 */
final class EmailAddress
{
    /**
     * @var string
     */
    private $mailbox;

    /**
     * @var null|string
     */
    private $hostname;

    /**
     * @var null|string
     */
    private $name;

    /**
     * @var null|string
     */
    private $address;

    public function __construct(string $mailbox, string $hostname = null,
string $name = null)
    {
        $this->mailbox  = $mailbox;
        $this->hostname = $hostname;
        $this->name     = $name;

        if (null !== $hostname) {
            $this->address = $mailbox . '@' . $hostname;
        }
    }

    /**
     * @return null|string
     */
    public function getAddress()
    {
        return $this->address;
    }

    /**
     * Returns address with person name.
     */
    public function getFullAddress(): string
    {
        $address = \sprintf('%s@%s', $this->mailbox,
$this->hostname);
        if (null !== $this->name) {
            $address = \sprintf('"%s" <%s>',
\addcslashes($this->name, '"'), $address);
        }

        return $address;
    }

    public function getMailbox(): string
    {
        return $this->mailbox;
    }

    /**
     * @return null|string
     */
    public function getHostname()
    {
        return $this->hostname;
    }

    /**
     * @return null|string
     */
    public function getName()
    {
        return $this->name;
    }
}
lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php000064400000003217151163263060017031
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

final class EmbeddedMessage extends AbstractMessage implements
EmbeddedMessageInterface
{
    /**
     * @var null|Headers
     */
    private $headers;

    /**
     * @var null|string
     */
    private $rawHeaders;

    /**
     * @var null|string
     */
    private $rawMessage;

    /**
     * Get message headers.
     */
    public function getHeaders(): Headers
    {
        if (null === $this->headers) {
            $this->headers = new
Headers(\imap_rfc822_parse_headers($this->getRawHeaders()));
        }

        return $this->headers;
    }

    /**
     * Get raw message headers.
     */
    public function getRawHeaders(): string
    {
        if (null === $this->rawHeaders) {
            $rawHeaders       = \explode("\r\n\r\n",
$this->getRawMessage(), 2);
            $this->rawHeaders = \current($rawHeaders);
        }

        return $this->rawHeaders;
    }

    /**
     * Get the raw message, including all headers, parts, etc. unencoded
and unparsed.
     *
     * @return string the raw message
     */
    public function getRawMessage(): string
    {
        if (null === $this->rawMessage) {
            $this->rawMessage =
$this->doGetContent($this->getPartNumber());
        }

        return $this->rawMessage;
    }

    /**
     * Get content part number.
     */
    protected function getContentPartNumber(): string
    {
        $partNumber = $this->getPartNumber();
        if (0 === \count($this->getParts())) {
            $partNumber .= '.1';
        }

        return $partNumber;
    }
}
lib/vendor/ddeboer/imap/src/Message/EmbeddedMessageInterface.php000064400000000220151163263070020642
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

interface EmbeddedMessageInterface extends BasicMessageInterface
{
}
lib/vendor/ddeboer/imap/src/Message/Headers.php000064400000003253151163263070015407
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

/**
 * Collection of message headers.
 */
final class Headers extends Parameters
{
    /**
     * Constructor.
     */
    public function __construct(\stdClass $headers)
    {
        parent::__construct();

        // Store all headers as lowercase
        $headers = \array_change_key_case((array) $headers);

        foreach ($headers as $key => $value) {
            $this[$key] = $this->parseHeader($key, $value);
        }
    }

    /**
     * Get header.
     *
     * @return mixed
     */
    public function get(string $key)
    {
        return parent::get(\strtolower($key));
    }

    /**
     * Parse header.
     *
     * @param mixed $value
     *
     * @return mixed
     */
    private function parseHeader(string $key, $value)
    {
        switch ($key) {
            case 'msgno':
                return (int) $value;
            case 'from':
            case 'to':
            case 'cc':
            case 'bcc':
            case 'reply_to':
            case 'sender':
            case 'return_path':
                /** @var \stdClass $address */
                foreach ($value as $address) {
                    if (isset($address->mailbox)) {
                        $address->host     = $address->host ?? null;
                        $address->personal =
isset($address->personal) ? $this->decode($address->personal) :
null;
                    }
                }

                return $value;
            case 'date':
            case 'subject':
                return $this->decode($value);
        }

        return $value;
    }
}
lib/vendor/ddeboer/imap/src/Message/Parameters.php000064400000003770151163263070016143
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

class Parameters extends \ArrayIterator
{
    /**
     * @var array
     */
    private static $attachmentCustomKeys = [
        'name*'     => 'name',
        'filename*' => 'filename',
    ];

    public function __construct(array $parameters = [])
    {
        parent::__construct();

        $this->add($parameters);
    }

    public function add(array $parameters = []): void
    {
        foreach ($parameters as $parameter) {
            $key = \strtolower($parameter->attribute);
            if (isset(self::$attachmentCustomKeys[$key])) {
                $key = self::$attachmentCustomKeys[$key];
            }
            $value      = $this->decode($parameter->value);
            $this[$key] = $value;
        }
    }

    /**
     * @return mixed
     */
    public function get(string $key)
    {
        return $this[$key] ?? null;
    }

    /**
     * Decode value.
     */
    final protected function decode(string $value): string
    {
        $parts = \imap_mime_header_decode($value);
        if (!\is_array($parts)) {
            return $value;
        }

        $decoded = '';
        foreach ($parts as $part) {
            $text = $part->text;
            if ('default' !== $part->charset) {
                $text = Transcoder::decode($text, $part->charset);
            }
            // RFC2231
            if (1 ===
\preg_match('/^(?<encoding>[^\']+)\'[^\']*?\'(?<urltext>.+)$/',
$text, $matches)) {
                $hasInvalidChars = 1 ===
\preg_match('#[^%a-zA-Z0-9\-_\.\+]#',
$matches['urltext']);
                $hasEscapedChars = 1 ===
\preg_match('#%[a-zA-Z0-9]{2}#', $matches['urltext']);
                if (!$hasInvalidChars && $hasEscapedChars) {
                    $text =
Transcoder::decode(\urldecode($matches['urltext']),
$matches['encoding']);
                }
            }

            $decoded .= $text;
        }

        return $decoded;
    }
}
lib/vendor/ddeboer/imap/src/Message/PartInterface.php000064400000005036151163263070016564
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

/**
 * A message part.
 */
interface PartInterface extends \RecursiveIterator
{
    public const TYPE_TEXT          = 'text';
    public const TYPE_MULTIPART     = 'multipart';
    public const TYPE_MESSAGE       = 'message';
    public const TYPE_APPLICATION   = 'application';
    public const TYPE_AUDIO         = 'audio';
    public const TYPE_IMAGE         = 'image';
    public const TYPE_VIDEO         = 'video';
    public const TYPE_MODEL         = 'model';
    public const TYPE_OTHER         = 'other';
    public const TYPE_UNKNOWN       = 'unknown';

    public const ENCODING_7BIT              = '7bit';
    public const ENCODING_8BIT              = '8bit';
    public const ENCODING_BINARY            = 'binary';
    public const ENCODING_BASE64            = 'base64';
    public const ENCODING_QUOTED_PRINTABLE  =
'quoted-printable';
    public const ENCODING_UNKNOWN           = 'unknown';

    public const SUBTYPE_PLAIN  = 'PLAIN';
    public const SUBTYPE_HTML   = 'HTML';
    public const SUBTYPE_RFC822 = 'RFC822';

    /**
     * Get message number (from headers).
     */
    public function getNumber(): int;

    /**
     * Part charset.
     */
    public function getCharset(): ?string;

    /**
     * Part type.
     */
    public function getType(): ?string;

    /**
     * Part subtype.
     */
    public function getSubtype(): ?string;

    /**
     * Part encoding.
     */
    public function getEncoding(): ?string;

    /**
     * Part disposition.
     */
    public function getDisposition(): ?string;

    /**
     * Part description.
     */
    public function getDescription(): ?string;

    /**
     * Part bytes.
     *
     * @return null|int|string
     */
    public function getBytes();

    /**
     * Part lines.
     */
    public function getLines(): ?string;

    /**
     * Part parameters.
     */
    public function getParameters(): Parameters;

    /**
     * Get raw part content.
     */
    public function getContent(): string;

    /**
     * Get decoded part content.
     */
    public function getDecodedContent(): string;

    /**
     * Part structure.
     */
    public function getStructure(): \stdClass;

    /**
     * Get part number.
     */
    public function getPartNumber(): string;

    /**
     * Get an array of all parts for this message.
     *
     * @return PartInterface[]
     */
    public function getParts(): array;
}
lib/vendor/ddeboer/imap/src/Message/SimplePart.php000064400000000231151163263070016105
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

/**
 * A message part.
 */
final class SimplePart extends AbstractPart
{
}
lib/vendor/ddeboer/imap/src/Message/Transcoder.php000064400000036326151163263070016147
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Message;

use Ddeboer\Imap\Exception\UnsupportedCharsetException;

final class Transcoder
{
    /**
     * @var array
     *
     * @see https://encoding.spec.whatwg.org/#encodings
     * @see
https://dxr.mozilla.org/mozilla-central/source/dom/encoding/labelsencodings.properties
     * @see
https://dxr.mozilla.org/mozilla1.9.1/source/intl/uconv/src/charsetalias.properties
     * @see https://msdn.microsoft.com/en-us/library/cc194829.aspx
     */
    private static $charsetAliases = [
        '128'                       => 'Shift_JIS',
        '129'                       => 'EUC-KR',
        '134'                       => 'GB2312',
        '136'                       => 'Big5',
        '161'                       =>
'windows-1253',
        '162'                       =>
'windows-1254',
        '177'                       =>
'windows-1255',
        '178'                       =>
'windows-1256',
        '186'                       =>
'windows-1257',
        '204'                       =>
'windows-1251',
        '222'                       =>
'windows-874',
        '238'                       =>
'windows-1250',
        '5601'                      => 'EUC-KR',
        '646'                       => 'us-ascii',
        '850'                       => 'IBM850',
        '852'                       => 'IBM852',
        '855'                       => 'IBM855',
        '857'                       => 'IBM857',
        '862'                       => 'IBM862',
        '864'                       => 'IBM864',
        '864i'                      => 'IBM864i',
        '866'                       => 'IBM866',
        'ansi-1251'                 =>
'windows-1251',
        'ansi_x3.4-1968'            => 'us-ascii',
        'arabic'                    =>
'ISO-8859-6',
        'ascii'                     => 'us-ascii',
        'asmo-708'                  =>
'ISO-8859-6',
        'big5-hkscs'                => 'Big5',
        'chinese'                   => 'GB2312',
        'cn-big5'                   => 'Big5',
        'cns11643'                  => 'x-euc-tw',
        'cp-866'                    => 'IBM866',
        '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',
        'cp819'                     =>
'ISO-8859-1',
        'cp850'                     => 'IBM850',
        'cp852'                     => 'IBM852',
        'cp855'                     => 'IBM855',
        'cp857'                     => 'IBM857',
        'cp862'                     => 'IBM862',
        'cp864'                     => 'IBM864',
        'cp864i'                    => 'IBM864i',
        'cp866'                     => 'IBM866',
        'cp932'                     => 'Shift_JIS',
        'csbig5'                    => 'Big5',
        'cseucjpkdfmtjapanese'      => 'EUC-JP',
        'cseuckr'                   => 'EUC-KR',
        'cseucpkdfmtjapanese'       => 'EUC-JP',
        'csgb2312'                  => 'GB2312',
        'csibm850'                  => 'IBM850',
        'csibm852'                  => 'IBM852',
        'csibm855'                  => 'IBM855',
        'csibm857'                  => 'IBM857',
        'csibm862'                  => 'IBM862',
        'csibm864'                  => 'IBM864',
        'csibm864i'                 => 'IBM864i',
        'csibm866'                  => 'IBM866',
        'csiso103t618bit'           => 'T.61-8bit',
        'csiso111ecmacyrillic'      =>
'ISO-IR-111',
        'csiso2022jp'               =>
'ISO-2022-JP',
        'csiso2022jp2'              =>
'ISO-2022-JP',
        'csiso2022kr'               =>
'ISO-2022-KR',
        'csiso58gb231280'           => 'GB2312',
        'csiso88596e'               =>
'ISO-8859-6-E',
        'csiso88596i'               =>
'ISO-8859-6-I',
        'csiso88598e'               =>
'ISO-8859-8-E',
        'csiso88598i'               =>
'ISO-8859-8-I',
        'csisolatin1'               =>
'ISO-8859-1',
        'csisolatin2'               =>
'ISO-8859-2',
        'csisolatin3'               =>
'ISO-8859-3',
        'csisolatin4'               =>
'ISO-8859-4',
        'csisolatin5'               =>
'ISO-8859-9',
        'csisolatin6'               =>
'ISO-8859-10',
        'csisolatin9'               =>
'ISO-8859-15',
        'csisolatinarabic'          =>
'ISO-8859-6',
        'csisolatincyrillic'        =>
'ISO-8859-5',
        'csisolatingreek'           =>
'ISO-8859-7',
        'csisolatinhebrew'          =>
'ISO-8859-8',
        'cskoi8r'                   => 'KOI8-R',
        'csksc56011987'             => 'EUC-KR',
        'csmacintosh'               =>
'x-mac-roman',
        'csshiftjis'                => 'Shift_JIS',
        'csueckr'                   => 'EUC-KR',
        'csunicode'                 => 'UTF-16BE',
        'csunicode11'               => 'UTF-16BE',
        'csunicode11utf7'           => 'UTF-7',
        'csunicodeascii'            => 'UTF-16BE',
        'csunicodelatin1'           => 'UTF-16BE',
        'csviqr'                    => 'VIQR',
        'csviscii'                  => 'VISCII',
        'cyrillic'                  =>
'ISO-8859-5',
        'dos-874'                   =>
'windows-874',
        'ecma-114'                  =>
'ISO-8859-6',
        'ecma-118'                  =>
'ISO-8859-7',
        'ecma-cyrillic'             =>
'ISO-IR-111',
        'elot_928'                  =>
'ISO-8859-7',
        'gb_2312'                   => 'GB2312',
        'gb_2312-80'                => 'GB2312',
        'greek'                     =>
'ISO-8859-7',
        'greek8'                    =>
'ISO-8859-7',
        'hebrew'                    =>
'ISO-8859-8',
        'ibm-864'                   => 'IBM864',
        'ibm-864i'                  => 'IBM864i',
        'ibm819'                    =>
'ISO-8859-1',
        'ibm874'                    =>
'windows-874',
        'iso-10646'                 => 'UTF-16BE',
        'iso-10646-j-1'             => 'UTF-16BE',
        'iso-10646-ucs-2'           => 'UTF-16BE',
        'iso-10646-ucs-4'           => 'UTF-32BE',
        'iso-10646-ucs-basic'       => 'UTF-16BE',
        'iso-10646-unicode-latin1'  => 'UTF-16BE',
        'iso-2022-cn-ext'           =>
'ISO-2022-CN',
        'iso-2022-jp-2'             =>
'ISO-2022-JP',
        'iso-8859-8i'               =>
'ISO-8859-8-I',
        'iso-ir-100'                =>
'ISO-8859-1',
        'iso-ir-101'                =>
'ISO-8859-2',
        'iso-ir-103'                => 'T.61-8bit',
        'iso-ir-109'                =>
'ISO-8859-3',
        'iso-ir-110'                =>
'ISO-8859-4',
        'iso-ir-126'                =>
'ISO-8859-7',
        'iso-ir-127'                =>
'ISO-8859-6',
        'iso-ir-138'                =>
'ISO-8859-8',
        'iso-ir-144'                =>
'ISO-8859-5',
        'iso-ir-148'                =>
'ISO-8859-9',
        'iso-ir-149'                => 'EUC-KR',
        'iso-ir-157'                =>
'ISO-8859-10',
        'iso-ir-58'                 => 'GB2312',
        'iso8859-1'                 =>
'ISO-8859-1',
        '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',
        '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',
        'iso88591'                  =>
'ISO-8859-1',
        'iso885910'                 =>
'ISO-8859-10',
        'iso885911'                 =>
'ISO-8859-11',
        'iso885912'                 =>
'ISO-8859-12',
        'iso885913'                 =>
'ISO-8859-13',
        'iso885914'                 =>
'ISO-8859-14',
        'iso885915'                 =>
'ISO-8859-15',
        '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',
        'iso_8859-1'                =>
'ISO-8859-1',
        'iso_8859-15'               =>
'ISO-8859-15',
        'iso_8859-1:1987'           =>
'ISO-8859-1',
        'iso_8859-2'                =>
'ISO-8859-2',
        'iso_8859-2:1987'           =>
'ISO-8859-2',
        'iso_8859-3'                =>
'ISO-8859-3',
        'iso_8859-3:1988'           =>
'ISO-8859-3',
        'iso_8859-4'                =>
'ISO-8859-4',
        'iso_8859-4:1988'           =>
'ISO-8859-4',
        'iso_8859-5'                =>
'ISO-8859-5',
        'iso_8859-5:1988'           =>
'ISO-8859-5',
        'iso_8859-6'                =>
'ISO-8859-6',
        'iso_8859-6:1987'           =>
'ISO-8859-6',
        'iso_8859-7'                =>
'ISO-8859-7',
        'iso_8859-7:1987'           =>
'ISO-8859-7',
        'iso_8859-8'                =>
'ISO-8859-8',
        'iso_8859-8:1988'           =>
'ISO-8859-8',
        'iso_8859-9'                =>
'ISO-8859-9',
        'iso_8859-9:1989'           =>
'ISO-8859-9',
        'koi'                       => 'KOI8-R',
        'koi8'                      => 'KOI8-R',
        'koi8-ru'                   => 'KOI8-U',
        'koi8_r'                    => 'KOI8-R',
        'korean'                    => 'EUC-KR',
        'ks_c_5601-1987'            => 'EUC-KR',
        'ks_c_5601-1989'            => 'EUC-KR',
        'ksc5601'                   => 'EUC-KR',
        'ksc_5601'                  => 'EUC-KR',
        'l1'                        =>
'ISO-8859-1',
        'l2'                        =>
'ISO-8859-2',
        'l3'                        =>
'ISO-8859-3',
        'l4'                        =>
'ISO-8859-4',
        'l5'                        =>
'ISO-8859-9',
        'l6'                        =>
'ISO-8859-10',
        'l9'                        =>
'ISO-8859-15',
        'latin1'                    =>
'ISO-8859-1',
        'latin2'                    =>
'ISO-8859-2',
        'latin3'                    =>
'ISO-8859-3',
        'latin4'                    =>
'ISO-8859-4',
        'latin5'                    =>
'ISO-8859-9',
        'latin6'                    =>
'ISO-8859-10',
        'logical'                   =>
'ISO-8859-8-I',
        'mac'                       =>
'x-mac-roman',
        'macintosh'                 =>
'x-mac-roman',
        'ms932'                     => 'Shift_JIS',
        'ms_kanji'                  => 'Shift_JIS',
        'shift-jis'                 => 'Shift_JIS',
        'sjis'                      => 'Shift_JIS',
        'sun_eu_greek'              =>
'ISO-8859-7',
        't.61'                      => 'T.61-8bit',
        'tis620'                    => 'TIS-620',
        'unicode-1-1-utf-7'         => 'UTF-7',
        'unicode-1-1-utf-8'         => 'UTF-8',
        'unicode-2-0-utf-7'         => 'UTF-7',
        'visual'                    =>
'ISO-8859-8',
        'windows-31j'               => 'Shift_JIS',
        'windows-949'               => 'EUC-KR',
        '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',
        'x-euc-jp'                  => 'EUC-JP',
        'x-gbk'                     => 'gbk',
        'x-iso-10646-ucs-2-be'      => 'UTF-16BE',
        'x-iso-10646-ucs-2-le'      => 'UTF-16LE',
        'x-iso-10646-ucs-4-be'      => 'UTF-32BE',
        'x-iso-10646-ucs-4-le'      => 'UTF-32LE',
        'x-sjis'                    => 'Shift_JIS',
        'x-unicode-2-0-utf-7'       => 'UTF-7',
        'x-x-big5'                  => 'Big5',
        'zh_cn.euc'                 => 'GB2312',
        'zh_tw-big5'                => 'Big5',
        'zh_tw-euc'                 => 'x-euc-tw',
    ];

    /**
     * Decode text to UTF-8.
     *
     * @param string $text        Text to decode
     * @param string $fromCharset Original charset
     */
    public static function decode(string $text, string $fromCharset):
string
    {
        static $utf8Aliases = [
            'unicode-1-1-utf-8' => true,
            'utf8'              => true,
            'utf-8'             => true,
            'UTF8'              => true,
            'UTF-8'             => true,
        ];

        if (isset($utf8Aliases[$fromCharset])) {
            return $text;
        }

        $originalFromCharset  = $fromCharset;
        $lowercaseFromCharset = \strtolower($fromCharset);
        if (isset(self::$charsetAliases[$lowercaseFromCharset])) {
            $fromCharset = self::$charsetAliases[$lowercaseFromCharset];
        }

        \set_error_handler(static function (): bool {
            return true;
        });

        $iconvDecodedText = \iconv($fromCharset, 'UTF-8',
$text);
        if (false === $iconvDecodedText) {
            $iconvDecodedText = \iconv($originalFromCharset,
'UTF-8', $text);
        }

        \restore_error_handler();

        if (false !== $iconvDecodedText) {
            return $iconvDecodedText;
        }

        $errorMessage = null;
        $errorNumber  = 0;
        \set_error_handler(static function ($nr, $message) use
(&$errorMessage, &$errorNumber): bool {
            $errorMessage = $message;
            $errorNumber = $nr;

            return true;
        });

        $decodedText = '';

        try {
            $decodedText = \mb_convert_encoding($text, 'UTF-8',
$fromCharset);
        } catch (\Error $error) {
            $errorMessage = $error->getMessage();
        }

        \restore_error_handler();

        if (null !== $errorMessage) {
            throw new UnsupportedCharsetException(\sprintf(
                'Unsupported charset "%s"%s: %s',
                $originalFromCharset,
                ($fromCharset !== $originalFromCharset) ? \sprintf('
(alias found: "%s")', $fromCharset) : '',
                $errorMessage
            ), $errorNumber);
        }

        return $decodedText;
    }
}
lib/vendor/ddeboer/imap/src/Message.php000064400000023505151163263070014036
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

use Ddeboer\Imap\Exception\ImapFetchheaderException;
use Ddeboer\Imap\Exception\InvalidHeadersException;
use Ddeboer\Imap\Exception\MessageCopyException;
use Ddeboer\Imap\Exception\MessageDeleteException;
use Ddeboer\Imap\Exception\MessageDoesNotExistException;
use Ddeboer\Imap\Exception\MessageMoveException;
use Ddeboer\Imap\Exception\MessageStructureException;
use Ddeboer\Imap\Exception\MessageUndeleteException;

/**
 * An IMAP message (e-mail).
 */
final class Message extends Message\AbstractMessage implements
MessageInterface
{
    /**
     * @var bool
     */
    private $messageNumberVerified = false;

    /**
     * @var int
     */
    private $imapMsgNo = 0;

    /**
     * @var bool
     */
    private $structureLoaded = false;

    /**
     * @var null|Message\Headers
     */
    private $headers;

    /**
     * @var null|string
     */
    private $rawHeaders;

    /**
     * @var null|string
     */
    private $rawMessage;

    /**
     * Constructor.
     *
     * @param ImapResourceInterface $resource      IMAP resource
     * @param int                   $messageNumber Message number
     */
    public function __construct(ImapResourceInterface $resource, int
$messageNumber)
    {
        parent::__construct($resource, $messageNumber, '1', new
\stdClass());
    }

    /**
     * Lazy load structure.
     */
    protected function lazyLoadStructure(): void
    {
        if (true === $this->structureLoaded) {
            return;
        }
        $this->structureLoaded = true;

        $messageNumber = $this->getNumber();

        $errorMessage = null;
        $errorNumber  = 0;
        \set_error_handler(static function ($nr, $message) use
(&$errorMessage, &$errorNumber): bool {
            $errorMessage = $message;
            $errorNumber = $nr;

            return true;
        });

        $structure = \imap_fetchstructure(
            $this->resource->getStream(),
            $messageNumber,
            \FT_UID
        );

        \restore_error_handler();

        if (!$structure instanceof \stdClass) {
            throw new MessageStructureException(\sprintf(
                'Message "%s" structure is empty: %s',
                $messageNumber,
                $errorMessage
            ), $errorNumber);
        }

        $this->setStructure($structure);
    }

    /**
     * Ensure message exists.
     */
    protected function assertMessageExists(int $messageNumber): void
    {
        if (true === $this->messageNumberVerified) {
            return;
        }
        $this->messageNumberVerified = true;

        $msgno = null;
        \set_error_handler(static function (): bool {
            return true;
        });

        $msgno = \imap_msgno($this->resource->getStream(),
$messageNumber);

        \restore_error_handler();

        if (\is_numeric($msgno) && $msgno > 0) {
            $this->imapMsgNo = $msgno;

            return;
        }

        throw new MessageDoesNotExistException(\sprintf(
            'Message "%s" does not exist',
            $messageNumber
        ));
    }

    private function getMsgNo(): int
    {
        // Triggers assertMessageExists()
        $this->getNumber();

        return $this->imapMsgNo;
    }

    /**
     * Get raw message headers.
     */
    public function getRawHeaders(): string
    {
        if (null === $this->rawHeaders) {
            $rawHeaders =
\imap_fetchheader($this->resource->getStream(),
$this->getNumber(), \FT_UID);

            if (false === $rawHeaders) {
                throw new ImapFetchheaderException('imap_fetchheader
failed');
            }

            $this->rawHeaders = $rawHeaders;
        }

        return $this->rawHeaders;
    }

    /**
     * Get the raw message, including all headers, parts, etc. unencoded
and unparsed.
     *
     * @return string the raw message
     */
    public function getRawMessage(): string
    {
        if (null === $this->rawMessage) {
            $this->rawMessage = $this->doGetContent('');
        }

        return $this->rawMessage;
    }

    /**
     * Get message headers.
     */
    public function getHeaders(): Message\Headers
    {
        if (null === $this->headers) {
            // imap_headerinfo is much faster than imap_fetchheader
            // imap_headerinfo returns only a subset of all mail headers,
            // but it does include the message flags.
            $headers = \imap_headerinfo($this->resource->getStream(),
$this->getMsgNo());
            if (false === $headers) {
                // @see https://github.com/ddeboer/imap/issues/358
                throw new InvalidHeadersException(\sprintf('Message
"%s" has invalid headers', $this->getNumber()));
            }
            $this->headers = new Message\Headers($headers);
        }

        return $this->headers;
    }

    /**
     * Clearmessage headers.
     */
    private function clearHeaders(): void
    {
        $this->headers = null;
    }

    /**
     * Get message recent flag value (from headers).
     */
    public function isRecent(): ?string
    {
        return $this->getHeaders()->get('recent');
    }

    /**
     * Get message unseen flag value (from headers).
     */
    public function isUnseen(): bool
    {
        return 'U' ===
$this->getHeaders()->get('unseen');
    }

    /**
     * Get message flagged flag value (from headers).
     */
    public function isFlagged(): bool
    {
        return 'F' ===
$this->getHeaders()->get('flagged');
    }

    /**
     * Get message answered flag value (from headers).
     */
    public function isAnswered(): bool
    {
        return 'A' ===
$this->getHeaders()->get('answered');
    }

    /**
     * Get message deleted flag value (from headers).
     */
    public function isDeleted(): bool
    {
        return 'D' ===
$this->getHeaders()->get('deleted');
    }

    /**
     * Get message draft flag value (from headers).
     */
    public function isDraft(): bool
    {
        return 'X' ===
$this->getHeaders()->get('draft');
    }

    /**
     * Has the message been marked as read?
     */
    public function isSeen(): bool
    {
        return 'N' !==
$this->getHeaders()->get('recent') && 'U'
!== $this->getHeaders()->get('unseen');
    }

    /**
     * Mark message as seen.
     *
     * @deprecated since version 1.1, to be removed in 2.0
     */
    public function maskAsSeen(): bool
    {
        \trigger_error(\sprintf('%s is deprecated and will be removed
in 2.0. Use %s::markAsSeen instead.', __METHOD__, __CLASS__),
\E_USER_DEPRECATED);

        return $this->markAsSeen();
    }

    /**
     * Mark message as seen.
     */
    public function markAsSeen(): bool
    {
        return $this->setFlag('\\Seen');
    }

    /**
     * Move message to another mailbox.
     *
     * @throws MessageCopyException
     */
    public function copy(MailboxInterface $mailbox): void
    {
        // 'deleted' header changed, force to reload headers,
would be better to set deleted flag to true on header
        $this->clearHeaders();

        if (!\imap_mail_copy($this->resource->getStream(), (string)
$this->getNumber(), $mailbox->getEncodedName(), \CP_UID)) {
            throw new MessageCopyException(\sprintf('Message
"%s" cannot be copied to "%s"',
$this->getNumber(), $mailbox->getName()));
        }
    }

    /**
     * Move message to another mailbox.
     *
     * @throws MessageMoveException
     */
    public function move(MailboxInterface $mailbox): void
    {
        // 'deleted' header changed, force to reload headers,
would be better to set deleted flag to true on header
        $this->clearHeaders();

        if (!\imap_mail_move($this->resource->getStream(), (string)
$this->getNumber(), $mailbox->getEncodedName(), \CP_UID)) {
            throw new MessageMoveException(\sprintf('Message
"%s" cannot be moved to "%s"',
$this->getNumber(), $mailbox->getName()));
        }
    }

    /**
     * Delete message.
     *
     * @throws MessageDeleteException
     */
    public function delete(): void
    {
        // 'deleted' header changed, force to reload headers,
would be better to set deleted flag to true on header
        $this->clearHeaders();

        if (!\imap_delete($this->resource->getStream(), (string)
$this->getNumber(), \FT_UID)) {
            throw new MessageDeleteException(\sprintf('Message
"%s" cannot be deleted', $this->getNumber()));
        }
    }

    /**
     * Undelete message.
     *
     * @throws MessageUndeleteException
     */
    public function undelete(): void
    {
        // 'deleted' header changed, force to reload headers,
would be better to set deleted flag to false on header
        $this->clearHeaders();
        if (!\imap_undelete($this->resource->getStream(), (string)
$this->getNumber(), \FT_UID)) {
            throw new MessageUndeleteException(\sprintf('Message
"%s" cannot be undeleted', $this->getNumber()));
        }
    }

    /**
     * Set Flag Message.
     *
     * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and
\Draft
     */
    public function setFlag(string $flag): bool
    {
        $result = \imap_setflag_full($this->resource->getStream(),
(string) $this->getNumber(), $flag, \ST_UID);

        $this->clearHeaders();

        return $result;
    }

    /**
     * Clear Flag Message.
     *
     * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and
\Draft
     */
    public function clearFlag(string $flag): bool
    {
        $result = \imap_clearflag_full($this->resource->getStream(),
(string) $this->getNumber(), $flag, \ST_UID);

        $this->clearHeaders();

        return $result;
    }
}
lib/vendor/ddeboer/imap/src/MessageInterface.php000064400000004040151163263070015650
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

/**
 * An IMAP message (e-mail).
 */
interface MessageInterface extends Message\BasicMessageInterface
{
    /**
     * Get raw part content.
     */
    public function getContent(): string;

    /**
     * Get message recent flag value (from headers).
     */
    public function isRecent(): ?string;

    /**
     * Get message unseen flag value (from headers).
     */
    public function isUnseen(): bool;

    /**
     * Get message flagged flag value (from headers).
     */
    public function isFlagged(): bool;

    /**
     * Get message answered flag value (from headers).
     */
    public function isAnswered(): bool;

    /**
     * Get message deleted flag value (from headers).
     */
    public function isDeleted(): bool;

    /**
     * Get message draft flag value (from headers).
     */
    public function isDraft(): bool;

    /**
     * Has the message been marked as read?
     */
    public function isSeen(): bool;

    /**
     * Mark message as seen.
     *
     * @deprecated since version 1.1, to be removed in 2.0
     */
    public function maskAsSeen(): bool;

    /**
     * Mark message as seen.
     */
    public function markAsSeen(): bool;

    /**
     * Move message to another mailbox.
     */
    public function copy(MailboxInterface $mailbox): void;

    /**
     * Move message to another mailbox.
     */
    public function move(MailboxInterface $mailbox): void;

    /**
     * Delete message.
     */
    public function delete(): void;

    /**
     * Undelete message.
     */
    public function undelete(): void;

    /**
     * Set Flag Message.
     *
     * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and
\Draft
     */
    public function setFlag(string $flag): bool;

    /**
     * Clear Flag Message.
     *
     * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and
\Draft
     */
    public function clearFlag(string $flag): bool;
}
lib/vendor/ddeboer/imap/src/MessageIterator.php000064400000002506151163263070015546
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

final class MessageIterator extends \ArrayIterator implements
MessageIteratorInterface
{
    /**
     * @var ImapResourceInterface
     */
    private $resource;

    /**
     * Constructor.
     *
     * @param ImapResourceInterface $resource       IMAP resource
     * @param array                 $messageNumbers Array of message
numbers
     */
    public function __construct(ImapResourceInterface $resource, array
$messageNumbers)
    {
        $this->resource = $resource;

        parent::__construct($messageNumbers);
    }

    /**
     * Get current message.
     */
    public function current(): MessageInterface
    {
        $current = parent::current();
        if (!\is_int($current)) {
            throw new Exception\OutOfBoundsException(\sprintf(
                'The current value "%s" isn\'t an
integer and doesn\'t represent a message;'
                . ' try to cycle this "%s" with a native php
function like foreach or with the method getArrayCopy(),'
                . ' or check it by calling the methods
valid().',
                \is_object($current) ? \get_class($current) :
\gettype($current),
                static::class
            ));
        }

        return new Message($this->resource, $current);
    }
}
lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php000064400000000335151163263070017365
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

interface MessageIteratorInterface extends \Iterator
{
    /**
     * Get current message.
     */
    public function current(): MessageInterface;
}
lib/vendor/ddeboer/imap/src/Search/AbstractDate.php000064400000002177151163263070016222
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search;

use DateTimeInterface;

/**
 * Represents a date condition.
 */
abstract class AbstractDate implements ConditionInterface
{
    /**
     * Format for dates to be sent to the IMAP server.
     *
     * @var string
     */
    private $dateFormat;

    /**
     * The date to be used for the condition.
     *
     * @var DateTimeInterface
     */
    private $date;

    /**
     * Constructor.
     *
     * @param DateTimeInterface $date optional date for the condition
     */
    public function __construct(DateTimeInterface $date, string $dateFormat
= 'j-M-Y')
    {
        $this->date       = $date;
        $this->dateFormat = $dateFormat;
    }

    /**
     * Converts the condition to a string that can be sent to the IMAP
server.
     */
    final public function toString(): string
    {
        return \sprintf('%s "%s"',
$this->getKeyword(), $this->date->format($this->dateFormat));
    }

    /**
     * Returns the keyword that the condition represents.
     */
    abstract protected function getKeyword(): string;
}
lib/vendor/ddeboer/imap/src/Search/AbstractText.php000064400000001621151163263070016262
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search;

/**
 * Represents a text based condition. Text based conditions use a contains
 * restriction.
 */
abstract class AbstractText implements ConditionInterface
{
    /**
     * Text to be used for the condition.
     *
     * @var string
     */
    private $text;

    /**
     * Constructor.
     *
     * @param string $text optional text for the condition
     */
    public function __construct(string $text)
    {
        $this->text = $text;
    }

    /**
     * Converts the condition to a string that can be sent to the IMAP
server.
     */
    final public function toString(): string
    {
        return \sprintf('%s "%s"',
$this->getKeyword(), $this->text);
    }

    /**
     * Returns the keyword that the condition represents.
     */
    abstract protected function getKeyword(): string;
}
lib/vendor/ddeboer/imap/src/Search/ConditionInterface.php000064400000000504151163263070017420
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search;

/**
 * Represents a condition that can be used in a search expression.
 */
interface ConditionInterface
{
    /**
     * Converts the condition to a string that can be sent to the IMAP
server.
     */
    public function toString(): string;
}
lib/vendor/ddeboer/imap/src/Search/Date/Before.php000064400000000721151163263070015731
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Date;

use Ddeboer\Imap\Search\AbstractDate;

/**
 * Represents a date before condition. Messages must have a date before
the
 * specified date in order to match the condition.
 */
final class Before extends AbstractDate
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'BEFORE';
    }
}
lib/vendor/ddeboer/imap/src/Search/Date/On.php000064400000000707151163263070015107
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Date;

use Ddeboer\Imap\Search\AbstractDate;

/**
 * Represents a date on condition. Messages must have a date matching the
 * specified date in order to match the condition.
 */
final class On extends AbstractDate
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'ON';
    }
}
lib/vendor/ddeboer/imap/src/Search/Date/Since.php000064400000000715151163263070015573
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Date;

use Ddeboer\Imap\Search\AbstractDate;

/**
 * Represents a date after condition. Messages must have a date after the
 * specified date in order to match the condition.
 */
final class Since extends AbstractDate
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'SINCE';
    }
}
lib/vendor/ddeboer/imap/src/Search/Email/Bcc.php000064400000000771151163263070015375
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Email;

use Ddeboer\Imap\Search\AbstractText;

/**
 * Represents a "Bcc" email address condition. Messages must have
been addressed
 * to the specified recipient (along with any others) in order to match
the
 * condition.
 */
final class Bcc extends AbstractText
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'BCC';
    }
}
lib/vendor/ddeboer/imap/src/Search/Email/Cc.php000064400000000766151163263070015237
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Email;

use Ddeboer\Imap\Search\AbstractText;

/**
 * Represents a "Cc" email address condition. Messages must have
been addressed
 * to the specified recipient (along with any others) in order to match
the
 * condition.
 */
final class Cc extends AbstractText
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'CC';
    }
}
lib/vendor/ddeboer/imap/src/Search/Email/From.php000064400000000741151163263070015606
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Email;

use Ddeboer\Imap\Search\AbstractText;

/**
 * Represents a "From" email address condition. Messages must
have been sent
 * from the specified email address in order to match the condition.
 */
final class From extends AbstractText
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'FROM';
    }
}
lib/vendor/ddeboer/imap/src/Search/Email/To.php000064400000000766151163263070015274
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Email;

use Ddeboer\Imap\Search\AbstractText;

/**
 * Represents a "To" email address condition. Messages must have
been addressed
 * to the specified recipient (along with any others) in order to match
the
 * condition.
 */
final class To extends AbstractText
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'TO';
    }
}
lib/vendor/ddeboer/imap/src/Search/Flag/Answered.php000064400000000731151163263070016274
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Flag;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents an ANSWERED flag condition. Messages must have the \\ANSWERED
flag
 * set in order to match the condition.
 */
final class Answered implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'ANSWERED';
    }
}
lib/vendor/ddeboer/imap/src/Search/Flag/Flagged.php000064400000000757151163263070016065
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Flag;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents a FLAGGED flag condition. Messages must have the \\FLAGGED
flag
 * (i.e. urgent or important) set in order to match the condition.
 */
final class Flagged implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'FLAGGED';
    }
}
lib/vendor/ddeboer/imap/src/Search/Flag/Recent.php000064400000000721151163263070015743
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Flag;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents an RECENT flag condition. Messages must have the \\RECENT
flag
 * set in order to match the condition.
 */
final class Recent implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'RECENT';
    }
}
lib/vendor/ddeboer/imap/src/Search/Flag/Seen.php000064400000000711151163263070015414
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Flag;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents an SEEN flag condition. Messages must have the \\SEEN flag
 * set in order to match the condition.
 */
final class Seen implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'SEEN';
    }
}
lib/vendor/ddeboer/imap/src/Search/Flag/Unanswered.php000064400000000743151163263070016642
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Flag;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents an UNANSWERED flag condition. Messages must not have the
 * \\ANSWERED flag set in order to match the condition.
 */
final class Unanswered implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'UNANSWERED';
    }
}
lib/vendor/ddeboer/imap/src/Search/Flag/Unflagged.php000064400000000770151163263070016423
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Flag;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents a UNFLAGGED flag condition. Messages must no have the
\\FLAGGED
 * flag (i.e. urgent or important) set in order to match the condition.
 */
final class Unflagged implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'UNFLAGGED';
    }
}
lib/vendor/ddeboer/imap/src/Search/Flag/Unseen.php000064400000000723151163263070015762
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Flag;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents an UNSEEN flag condition. Messages must not have the \\SEEN
flag
 * set in order to match the condition.
 */
final class Unseen implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'UNSEEN';
    }
}
lib/vendor/ddeboer/imap/src/Search/LogicalOperator/All.php000064400000000740151163263070017451
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\LogicalOperator;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents an ALL operator. Messages must match all conditions following
this
 * operator in order to match the expression.
 */
final class All implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'ALL';
    }
}
lib/vendor/ddeboer/imap/src/Search/LogicalOperator/OrConditions.php000064400000002407151163263070021355
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\LogicalOperator;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents an OR operator. Messages only need to match one of the
conditions
 * after this operator to match the expression.
 */
final class OrConditions implements ConditionInterface
{
    /**
     * The conditions that together represent the expression.
     *
     * @var array
     */
    private $conditions = [];

    public function __construct(array $conditions)
    {
        foreach ($conditions as $condition) {
            $this->addCondition($condition);
        }
    }

    /**
     * Adds a new condition to the expression.
     *
     * @param ConditionInterface $condition the condition to be added
     */
    private function addCondition(ConditionInterface $condition)
    {
        $this->conditions[] = $condition;
    }

    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        $conditions = \array_map(static function (ConditionInterface
$condition): string {
            return $condition->toString();
        }, $this->conditions);

        return \sprintf('( %s )', \implode(' OR ',
$conditions));
    }
}
lib/vendor/ddeboer/imap/src/Search/RawExpression.php000064400000001071151163263070016462
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search;

/**
 * Represents a raw expression.
 */
final class RawExpression implements ConditionInterface
{
    /**
     * Text to be used for the condition.
     *
     * @var string
     */
    private $expression;

    /**
     * @param string $expression text for the condition
     */
    public function __construct(string $expression)
    {
        $this->expression = $expression;
    }

    public function toString(): string
    {
        return $this->expression;
    }
}
lib/vendor/ddeboer/imap/src/Search/State/Deleted.php000064400000000747151163263070016310
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\State;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents a DELETED condition. Messages must have been marked for
deletion
 * but not yet expunged in order to match the condition.
 */
final class Deleted implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'DELETED';
    }
}
lib/vendor/ddeboer/imap/src/Search/State/NewMessage.php000064400000000651151163263070016772
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\State;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents a NEW condition. Only new messages will match this
condition.
 */
final class NewMessage implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'NEW';
    }
}
lib/vendor/ddeboer/imap/src/Search/State/Old.php000064400000000643151163263070015453
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\State;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents an OLD condition. Only old messages will match this
condition.
 */
final class Old implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'OLD';
    }
}
lib/vendor/ddeboer/imap/src/Search/State/Undeleted.php000064400000000734151163263070016647
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\State;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Represents a UNDELETED condition. Messages must not have been marked
for
 * deletion in order to match the condition.
 */
final class Undeleted implements ConditionInterface
{
    /**
     * Returns the keyword that the condition represents.
     */
    public function toString(): string
    {
        return 'UNDELETED';
    }
}
lib/vendor/ddeboer/imap/src/Search/Text/Body.php000064400000000730151163263070015473
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Text;

use Ddeboer\Imap\Search\AbstractText;

/**
 * Represents a body text contains condition. Messages must have a body
 * containing the specified text in order to match the condition.
 */
final class Body extends AbstractText
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'BODY';
    }
}
lib/vendor/ddeboer/imap/src/Search/Text/Keyword.php000064400000000742151163263070016225
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Text;

use Ddeboer\Imap\Search\AbstractText;

/**
 * Represents a keyword text contains condition. Messages must have a
keyword
 * matching the specified text in order to match the condition.
 */
final class Keyword extends AbstractText
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'KEYWORD';
    }
}
lib/vendor/ddeboer/imap/src/Search/Text/Subject.php000064400000000737151163263070016204
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Text;

use Ddeboer\Imap\Search\AbstractText;

/**
 * Represents a subject contains condition. Messages must have a subject
 * containing the specified text in order to match the condition.
 */
final class Subject extends AbstractText
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'SUBJECT';
    }
}
lib/vendor/ddeboer/imap/src/Search/Text/Text.php000064400000000714151163263070015524
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Text;

use Ddeboer\Imap\Search\AbstractText;

/**
 * Represents a message text contains condition. Messages must contain the
 * specified text in order to match the condition.
 */
final class Text extends AbstractText
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'TEXT';
    }
}
lib/vendor/ddeboer/imap/src/Search/Text/Unkeyword.php000064400000000762151163263070016572
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Search\Text;

use Ddeboer\Imap\Search\AbstractText;

/**
 * Represents a keyword text does not contain condition. Messages must not
have
 * a keyword matching the specified text in order to match the condition.
 */
final class Unkeyword extends AbstractText
{
    /**
     * Returns the keyword that the condition represents.
     */
    protected function getKeyword(): string
    {
        return 'UNKEYWORD';
    }
}
lib/vendor/ddeboer/imap/src/SearchExpression.php000064400000002057151163263070015736
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

use Ddeboer\Imap\Search\ConditionInterface;

/**
 * Defines a search expression that can be used to look up email messages.
 */
final class SearchExpression implements ConditionInterface
{
    /**
     * The conditions that together represent the expression.
     *
     * @var array
     */
    private $conditions = [];

    /**
     * Adds a new condition to the expression.
     *
     * @param ConditionInterface $condition the condition to be added
     */
    public function addCondition(ConditionInterface $condition): self
    {
        $this->conditions[] = $condition;

        return $this;
    }

    /**
     * Converts the expression to a string that can be sent to the IMAP
server.
     */
    public function toString(): string
    {
        $conditions = \array_map(static function (ConditionInterface
$condition): string {
            return $condition->toString();
        }, $this->conditions);

        return \implode(' ', $conditions);
    }
}
lib/vendor/ddeboer/imap/src/Server.php000064400000007543151163263070013724
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

use Ddeboer\Imap\Exception\AuthenticationFailedException;
use Ddeboer\Imap\Exception\ResourceCheckFailureException;

/**
 * An IMAP server.
 */
final class Server implements ServerInterface
{
    /**
     * @var string Internet domain name or bracketed IP address of server
     */
    private $hostname;

    /**
     * @var string TCP port number
     */
    private $port;

    /**
     * @var string Optional flags
     */
    private $flags;

    /**
     * @var array
     */
    private $parameters;

    /**
     * @var int Connection options
     */
    private $options;

    /**
     * @var int Retries number
     */
    private $retries;

    /**
     * Constructor.
     *
     * @param string $hostname   Internet domain name or bracketed IP
address
     *                           of server
     * @param string $port       TCP port number
     * @param string $flags      Optional flags
     * @param array  $parameters Connection parameters
     * @param int    $options    Connection options
     * @param int    $retries    Retries number
     */
    public function __construct(
        string $hostname,
        string $port = '993',
        string $flags = '/imap/ssl/validate-cert',
        array $parameters = [],
        int $options = 0,
        int $retries = 1
    ) {
        if (!\function_exists('imap_open')) {
            throw new \RuntimeException('IMAP extension must be
enabled');
        }

        $this->hostname   = $hostname;
        $this->port       = $port;
        $this->flags      = '' !== $flags ? '/' .
\ltrim($flags, '/') : '';
        $this->parameters = $parameters;
        $this->options    = $options;
        $this->retries    = $retries;
    }

    /**
     * Authenticate connection.
     *
     * @param string $username Username
     * @param string $password Password
     *
     * @throws AuthenticationFailedException
     */
    public function authenticate(string $username, string $password):
ConnectionInterface
    {
        $errorMessage = null;
        $errorNumber  = 0;
        \set_error_handler(static function ($nr, $message) use
(&$errorMessage, &$errorNumber): bool {
            $errorMessage = $message;
            $errorNumber = $nr;

            return true;
        });

        $resource = \imap_open(
            $this->getServerString(),
            $username,
            $password,
            $this->options,
            $this->retries,
            $this->parameters
        );

        \restore_error_handler();

        if (false === $resource || null !== $errorMessage) {
            throw new AuthenticationFailedException(\sprintf(
                'Authentication failed for user
"%s"%s',
                $username,
                null !== $errorMessage ? ': ' . $errorMessage :
''
            ), $errorNumber);
        }

        $check = \imap_check($resource);

        if (false === $check) {
            throw new ResourceCheckFailureException('Resource check
failure');
        }

        $mailbox       = $check->Mailbox;
        $connection    = $mailbox;
        $curlyPosition = \strpos($mailbox, '}');
        if (false !== $curlyPosition) {
            $connection = \substr($mailbox, 0, $curlyPosition + 1);
        }

        // These are necessary to get rid of PHP throwing IMAP errors
        \imap_errors();
        \imap_alerts();

        return new Connection(new ImapResource($resource), $connection);
    }

    /**
     * Glues hostname, port and flags and returns result.
     */
    private function getServerString(): string
    {
        return \sprintf(
            '{%s%s%s}',
            $this->hostname,
            '' !== $this->port ? ':' .
$this->port : '',
            $this->flags
        );
    }
}
lib/vendor/ddeboer/imap/src/ServerInterface.php000064400000000550151163263070015534
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap;

/**
 * An IMAP server.
 */
interface ServerInterface
{
    /**
     * Authenticate connection.
     *
     * @param string $username Username
     * @param string $password Password
     */
    public function authenticate(string $username, string $password):
ConnectionInterface;
}
lib/vendor/ddeboer/imap/src/Test/RawMessageIterator.php000064400000000636151163263070017141
0ustar00<?php

declare(strict_types=1);

namespace Ddeboer\Imap\Test;

use Ddeboer\Imap\MessageInterface;
use Ddeboer\Imap\MessageIteratorInterface;

/**
 * A MessageIterator to be used in a mocked environment.
 */
final class RawMessageIterator extends \ArrayIterator implements
MessageIteratorInterface
{
    public function current(): MessageInterface
    {
        return parent::current();
    }
}
lib/vendor/willdurand/email-reply-parser/.gitignore000064400000000026151163263070016460
0ustar00vendor/
composer.lock
lib/vendor/willdurand/email-reply-parser/.travis.yml000064400000000351151163263070016602
0ustar00language: php
sudo: required
dist: trusty
group: edge

php:
    - 5.6
    - 7.0
    - 7.1
    - 7.2
    - hhvm-3.9
    - hhvm-3.18

before_script:
    - composer install

script: ./vendor/bin/phpunit --coverage-text
lib/vendor/willdurand/email-reply-parser/composer.json000064400000001416151163263070017216
0ustar00{
    "name": "willdurand/email-reply-parser",
    "type": "library",
    "description": "Port of the cool GitHub's
EmailReplyParser library in PHP",
    "keywords": ["email", "reply-parser"],
    "license": "MIT",
    "authors": [
        {
            "name": "William Durand",
            "email": "will+git@drnd.me"
        }
    ],
    "require": {
        "php": ">=5.6.0"
    },
    "autoload": {
        "psr-4": { "EmailReplyParser\\":
"src/EmailReplyParser" }
    },
    "autoload-dev": {
        "psr-4": { "EmailReplyParser\\Tests\\":
"tests/EmailReplyParser/Tests" }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.8-dev"
        }
    },
    "require-dev": {
        "phpunit/phpunit": "^4.8.35|^5.7"
    }
}
lib/vendor/willdurand/email-reply-parser/CONTRIBUTING.md000064400000002343151163263070016725
0ustar00Contributing
============

First of all, **thank you** for contributing, **you are awesome**!

Here are a few rules to follow in order to ease code reviews, and
discussions before
maintainers accept and merge your work.

You MUST follow the [PSR-1](http://www.php-fig.org/psr/1/) and
[PSR-2](http://www.php-fig.org/psr/2/). If you don't know about any of
them, you
should really read the recommendations. Can't wait? Use the
[PHP-CS-Fixer
tool](http://cs.sensiolabs.org/).

You MUST run the test suite.

You MUST write (or update) unit tests.

You SHOULD write documentation.

Please, write [commit messages that make
sense](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
and [rebase your
branch](http://git-scm.com/book/en/Git-Branching-Rebasing)
before submitting your Pull Request.

One may ask you to [squash your
commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html)
too. This is used to "clean" your Pull Request before merging it
(we don't want
commits such as `fix tests`, `fix 2`, `fix 3`, etc.).

Also, while creating your Pull Request on GitHub, you MUST write a
description
which gives the context and/or explains why you are creating it.

Thank you!
lib/vendor/willdurand/email-reply-parser/LICENSE000064400000002151151163263070015476
0ustar00The MIT License

Copyright (c) GitHub, William Durand <william.durand1@gmail.com>

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.

lib/vendor/willdurand/email-reply-parser/phpunit.xml.dist000064400000001242151163263070017644
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
    backupStaticAttributes="false"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    processIsolation="false"
    stopOnFailure="false"
    syntaxCheck="false"
    bootstrap="vendor/autoload.php"
    >
    <testsuites>
        <testsuite name="EmailReplyParser Test Suite">
            <directory>./tests/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory>./src/EmailReplyParser/</directory>
        </whitelist>
    </filter>
</phpunit>
lib/vendor/willdurand/email-reply-parser/README.md000064400000007451151163263070015760
0ustar00EmailReplyParser
================

[![Build
Status](https://secure.travis-ci.org/willdurand/EmailReplyParser.png)](http://travis-ci.org/willdurand/EmailReplyParser)
[![Total
Downloads](https://poser.pugx.org/willdurand/email-reply-parser/downloads.png)](https://packagist.org/packages/willdurand/email-reply-parser)
[![Latest Stable
Version](https://poser.pugx.org/willdurand/email-reply-parser/v/stable.png)](https://packagist.org/packages/willdurand/email-reply-parser)
![PHP7 ready](https://img.shields.io/badge/PHP7-ready-green.svg)

**EmailReplyParser** is a PHP library for parsing plain text email
content,
based on GitHub's
[email_reply_parser](http://github.com/github/email_reply_parser)
library written in Ruby.


Installation
------------

The recommended way to install EmailReplyParser is through
[Composer](http://getcomposer.org/):

``` shell
composer require willdurand/email-reply-parser
```

Usage
-----

Instantiate an `EmailParser` object and parse your email:

``` php
<?php

use EmailReplyParser\Parser\EmailParser;

$email = (new EmailParser())->parse($emailContent);
```

You get an `Email` object that contains a set of `Fragment` objects. The
`Email`
class exposes two methods:

* `getFragments()`: returns all fragments;
* `getVisibleText()`: returns a string which represents the content
considered
  as "visible".

The `Fragment` represents a part of the full email content, and has the
following API:

``` php
<?php

$fragment = current($email->getFragments());

$fragment->getContent();

$fragment->isSignature();

$fragment->isQuoted();

$fragment->isHidden();

$fragment->isEmpty();
```

Alternatively, you can rely on the `EmailReplyParser` to either parse an
email
or get its visible content in a single line of code:

``` php
$email = \EmailReplyParser\EmailReplyParser::read($emailContent);

$visibleText =
\EmailReplyParser\EmailReplyParser::parseReply($emailContent);
```


Known Issues
------------

### Quoted Headers

Quoted headers aren't picked up if there's an extra line break:

    On <date>, <author> wrote:

    > blah

Also, they're not picked up if the email client breaks it up into
multiple lines.  GMail breaks up any lines over 80 characters for you.

    On <date>, <author>
    wrote:
    > blah

The above `On ....wrote:` can be cleaned up with the following regex:

``` php
$fragment_without_date_author = preg_replace(
    '/\nOn(.*?)wrote:(.*?)$/si',
    '',
    $fragment->getContent()
);
```

Note though that we're search for "on" and
"wrote".  Therefore, it won't work
with other languages.

Possible solution: Remove "reply@reply.github.com" lines...

### Weird Signatures

Lines starting with `-` or `_` sometimes mark the beginning of
signatures:

    Hello

    --
    Rick

Not everyone follows this convention:

    Hello

    Mr Rick Olson
    Galactic President Superstar Mc Awesomeville
    GitHub

    **********************DISCLAIMER***********************************
    * Note: blah blah blah                                            *
    **********************DISCLAIMER***********************************



### Strange Quoting

Apparently, prefixing lines with `>` isn't universal either:

    Hello

    --
    Rick

    ________________________________________
    From: Bob [reply@reply.github.com]
    Sent: Monday, March 14, 2011 6:16 PM
    To: Rick


Unit Tests
----------

Setup the test suite using Composer:

    $ composer install

Run it using PHPUnit:

    $ phpunit


Contributing
------------

See CONTRIBUTING file.


Credits
-------

* GitHub
* William Durand <william.durand1@gmail.com>


License
-------

EmailReplyParser is released under the MIT License. See the bundled
LICENSE
file for details.
lib/vendor/willdurand/email-reply-parser/src/autoload.php000064400000001610151163263070017600
0ustar00<?php

/**
 * Simple autoloader that follow the PHP Standards Recommendation #0
(PSR-0)
 * @see
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md for
more informations.
 *
 * Code inspired from the SplClassLoader RFC
 * @see https://wiki.php.net/rfc/splclassloader#example_implementation
 */
spl_autoload_register(function ($className) {
    $className = ltrim($className, '\\');
    $fileName = '';
    if ($lastNsPos = strripos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName = str_replace('\\', DIRECTORY_SEPARATOR,
$namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName = __DIR__ . DIRECTORY_SEPARATOR . $fileName . $className .
'.php';
    if (file_exists($fileName)) {
        require $fileName;

        return true;
    }

    return false;
});
lib/vendor/willdurand/email-reply-parser/src/EmailReplyParser/Email.php000064400000002007151163263070022240
0ustar00<?php

/**
 * This file is part of the EmailReplyParser package.
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @license    MIT License
 */

namespace EmailReplyParser;

/**
 * @author William Durand <william.durand1@gmail.com>
 */
final class Email
{
    /**
     * @var Fragment[]
     */
    private $fragments;

    /**
     * @param Fragment[] $fragments
     */
    public function __construct(array $fragments = array())
    {
        $this->fragments = $fragments;
    }

    /**
     * @return Fragment[]
     */
    public function getFragments()
    {
        return $this->fragments;
    }

    /**
     * @return string
     */
    public function getVisibleText()
    {
        $visibleFragments = array_filter($this->fragments, function
(Fragment $fragment) {
            return !$fragment->isHidden();
        });

        return rtrim(implode("\n", $visibleFragments));
    }
}
lib/vendor/willdurand/email-reply-parser/src/EmailReplyParser/EmailReplyParser.php000064400000001516151163263070024435
0ustar00<?php

/**
 * This file is part of the EmailReplyParser package.
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @license    MIT License
 */

namespace EmailReplyParser;

use EmailReplyParser\Parser\EmailParser;

/**
 * @author William Durand <william.durand1@gmail.com>
 */
class EmailReplyParser
{
    /**
     * @param string $text An email as text.
     *
     * @return Email
     */
    public static function read($text)
    {
        $parser = new EmailParser();

        return $parser->parse($text);
    }

    /**
     * @param string $text An email as text.
     *
     * @return string
     */
    public static function parseReply($text)
    {
        return static::read($text)->getVisibleText();
    }
}
lib/vendor/willdurand/email-reply-parser/src/EmailReplyParser/Fragment.php000064400000003356151163263070022764
0ustar00<?php

/**
 * This file is part of the EmailReplyParser package.
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @license    MIT License
 */

namespace EmailReplyParser;

/**
 * @author William Durand <william.durand1@gmail.com>
 */
final class Fragment
{
    /**
     * @var string
     */
    private $content;

    /**
     * @var boolean
     */
    private $isHidden;

    /**
     * @var boolean
     */
    private $isSignature;

    /**
     * @var boolean
     */
    private $isQuoted;

    /**
     * @param string  $content
     * @param boolean $isHidden
     * @param boolean $isSignature
     * @param boolean $isQuoted
     */
    public function __construct($content, $isHidden, $isSignature,
$isQuoted)
    {
        $this->content     = $content;
        $this->isHidden    = $isHidden;
        $this->isSignature = $isSignature;
        $this->isQuoted    = $isQuoted;
    }

    /**
     * @return string
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * @return boolean
     */
    public function isHidden()
    {
        return $this->isHidden;
    }

    /**
     * @return boolean
     */
    public function isSignature()
    {
        return $this->isSignature;
    }

    /**
     * @return boolean
     */
    public function isQuoted()
    {
        return $this->isQuoted;
    }

    /**
     * @return boolean
     */
    public function isEmpty()
    {
        return '' === str_replace("\n", '',
$this->getContent());
    }

    public function __toString()
    {
        return $this->getContent();
    }
}
lib/vendor/willdurand/email-reply-parser/src/EmailReplyParser/Parser/EmailParser.php000064400000017301151163263070024654
0ustar00<?php

/**
 * This file is part of the EmailReplyParser package.
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @license    MIT License
 */

namespace EmailReplyParser\Parser;

use EmailReplyParser\Email;
use EmailReplyParser\Fragment;

/**
 * @author William Durand <william.durand1@gmail.com>
 */
class EmailParser
{
    const QUOTE_REGEX = '/^>+/s';

    /**
     * Regex to match signatures
     *
     * @var string
     */
    private $signatureRegex = '/(?:^\s*--|^\s*__|^-\w|^-- $)|(?:^Sent
from my (?:\s*\w+){1,4}$)|(?:^={30,}$)$/s';

    /**
     * @var string[]
     */
    private $quoteHeadersRegex = array(
       
'/^\s*(On(?:(?!^>*\s*On\b|\bwrote:).){0,1000}wrote:)$/ms', //
On DATE, NAME <EMAIL> wrote:
       
'/^\s*(Le(?:(?!^>*\s*Le\b|\bécrit:).){0,1000}écrit(\s|\xc2\xa0):)$/ms',
// Le DATE, NAME <EMAIL> a écrit :
       
'/^\s*(El(?:(?!^>*\s*El\b|\bescribió:).){0,1000}escribió:)$/ms',
// El DATE, NAME <EMAIL> escribió:
       
'/^\s*(Il(?:(?!^>*\s*Il\b|\bscritto:).){0,1000}scritto:)$/ms',
// Il DATE, NAME <EMAIL> ha scritto:
        '/^[\S\s]+ (написа(л|ла|в)+)+:$/msu', //
Everything before написал: not ending on wrote:
        '/^\s*(Op\s.+?(schreef|geschreven).+:)$/ms', // Op DATE
schreef NAME <EMAIL>:, Op DATE heeft NAME <EMAIL> het volgende
geschreven:
       
'/^\s*((W\sdniu|Dnia)\s.+?(pisze|napisał(\(a\))?):)$/msu', // W
dniu DATE, NAME <EMAIL> pisze|napisał:
        '/^\s*(Den\s.+\sskrev\s.+:)$/m', // Den DATE skrev NAME
<EMAIL>:
        '/^\s*(Am\s.+\sum\s.+\sschrieb\s.+:)$/m', // Am DATE um
TIME schrieb NAME:
        '/^(在.+写道:)$/ms', // > 在 DATE, TIME, NAME
写道:
        '/^(20[0-9]{2}\..+\s작성:)$/m', // DATE TIME NAME
작성:
        '/^(20[0-9]{2}\/.+のメッセージ:)$/m', // DATE
TIME、NAME のメッセージ:
        '/^(.+\s<.+>\sschrieb:)$/m', // NAME <EMAIL>
schrieb:
        '/^\s*(From\s?:.+\s?(\[|<).+(\]|>))/mu', //
"From: NAME <EMAIL>" OR "From : NAME
<EMAIL>" OR "From : NAME<EMAIL>"(With support
whitespace before start and before <)
        '/^\s*(发件人\s?:.+\s?(\[|<).+(\]|>))/mu', //
"发件人: NAME <EMAIL>" OR "发件人 : NAME
<EMAIL>" OR "发件人 : NAME<EMAIL>"(With
support whitespace before start and before <)
        '/^\s*(De\s?:.+\s?(\[|<).+(\]|>))/mu', // "De:
NAME <EMAIL>" OR "De : NAME <EMAIL>" OR "De
: NAME<EMAIL>"  (With support whitespace before start and before
<)
        '/^\s*(Van\s?:.+\s?(\[|<).+(\]|>))/mu', //
"Van: NAME <EMAIL>" OR "Van : NAME <EMAIL>"
OR "Van : NAME<EMAIL>"  (With support whitespace before
start and before <)
        '/^\s*(Da\s?:.+\s?(\[|<).+(\]|>))/mu', // "Da:
NAME <EMAIL>" OR "Da : NAME <EMAIL>" OR "Da
: NAME<EMAIL>"  (With support whitespace before start and before
<)
       
'/^(20[0-9]{2}\-(?:0?[1-9]|1[012])\-(?:0?[0-9]|[1-2][0-9]|3[01]|[1-9])\s[0-2]?[0-9]:\d{2}\s.+?:)$/ms',
// 20YY-MM-DD HH:II GMT+01:00 NAME <EMAIL>:
        '/^\s*([a-z]{3,4}\.\s.+\sskrev\s.+:)$/ms', // DATE skrev
NAME <EMAIL>:
    );

    /**
     * @var FragmentDTO[]
     */
    private $fragments = array();

    /**
     * Parse a text which represents an email and splits it into
fragments.
     *
     * @param string $text A text.
     *
     * @return Email
     */
    public function parse($text)
    {
        $text = str_replace(array("\r\n", "\r"),
"\n", $text);

        foreach ($this->quoteHeadersRegex as $regex) {
            if (preg_match($regex, $text, $matches)) {
                $text = str_replace($matches[1],
str_replace("\n", ' ', $matches[1]), $text);
            }
        }

        $fragment = null;
        $text_array = explode("\n", $text);
        while (($line = array_pop($text_array)) !== NULL) {
            $line = ltrim($line, "\n");

            if (!$this->isSignature($line)) {
                $line = rtrim($line);
            }

            if ($fragment) {
                $first = reset($fragment->lines);

                if ($this->isSignature($first)) {
                    $fragment->isSignature = true;
                    $this->addFragment($fragment);

                    $fragment = null;
                } elseif (empty($line) &&
$this->isQuoteHeader($first)) {
                    $fragment->isQuoted = true;
                    $this->addFragment($fragment);

                    $fragment = null;
                }
            }

            $isQuoted = $this->isQuote($line);

            if (null === $fragment || !$this->isFragmentLine($fragment,
$line, $isQuoted)) {
                if ($fragment) {
                    $this->addFragment($fragment);
                }

                $fragment = new FragmentDTO();
                $fragment->isQuoted = $isQuoted;
            }

            array_unshift($fragment->lines, $line);
        }

        if ($fragment) {
            $this->addFragment($fragment);
        }

        $email = $this->createEmail($this->fragments);

        $this->fragments = array();

        return $email;
    }

    /**
     * @return string[]
     */
    public function getQuoteHeadersRegex()
    {
        return $this->quoteHeadersRegex;
    }

    /**
     * @param string[] $quoteHeadersRegex
     *
     * @return EmailParser
     */
    public function setQuoteHeadersRegex(array $quoteHeadersRegex)
    {
        $this->quoteHeadersRegex = $quoteHeadersRegex;

        return $this;
    }

    /**
     * @return string
     * @since 2.7.0
     */
    public function getSignatureRegex()
    {
        return $this->signatureRegex;
    }

    /**
     * @param string $signatureRegex
     *
     * @return EmailParser
     * @since 2.7.0
     */
    public function setSignatureRegex($signatureRegex)
    {
        $this->signatureRegex = $signatureRegex;

        return $this;
    }

    /**
     * @param FragmentDTO[] $fragmentDTOs
     *
     * @return Email
     */
    protected function createEmail(array $fragmentDTOs)
    {
        $fragments = array();
        foreach ($fragmentDTOs as $fragment) {
            $fragments[] = new Fragment(
                preg_replace("/^\n/", '',
implode("\n", $fragment->lines)),
                $fragment->isHidden,
                $fragment->isSignature,
                $fragment->isQuoted
            );
        }

        return new Email($fragments);
    }

    private function isQuoteHeader($line)
    {
        foreach ($this->quoteHeadersRegex as $regex) {
            if (preg_match($regex, $line)) {
                return true;
            }
        }

        return false;
    }

    private function isSignature($line)
    {
        return preg_match($this->signatureRegex, $line) ? true : false;
    }

    /**
     * @param string $line
     * @return bool
     */
    private function isQuote($line)
    {
        return preg_match(static::QUOTE_REGEX, $line) ? true : false;
    }

    private function isEmpty(FragmentDTO $fragment)
    {
        return '' === implode('',
$fragment->lines);
    }

    /**
     * @param FragmentDTO $fragment
     * @param string  $line
     * @param boolean $isQuoted
     * @return bool
     */
    private function isFragmentLine(FragmentDTO $fragment, $line,
$isQuoted)
    {
        return $fragment->isQuoted === $isQuoted ||
            ($fragment->isQuoted &&
($this->isQuoteHeader($line) || empty($line)));
    }

    private function addFragment(FragmentDTO $fragment)
    {
        if ($fragment->isQuoted || $fragment->isSignature ||
$this->isEmpty($fragment)) {
            $fragment->isHidden = true;
        }

        array_unshift($this->fragments, $fragment);
    }
}
lib/vendor/willdurand/email-reply-parser/src/EmailReplyParser/Parser/FragmentDTO.php000064400000001216151163263070024560
0ustar00<?php

/**
 * This file is part of the EmailReplyParser package.
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @license    MIT License
 */

namespace EmailReplyParser\Parser;

/**
 * @author William Durand <william.durand1@gmail.com>
 */
class FragmentDTO
{
    /**
     * @var string[]
     */
    public $lines = array();

    /**
     * @var boolean
     */
    public $isHidden = false;

    /**
     * @var boolean
     */
    public $isSignature = false;

    /**
     * @var boolean
     */
    public $isQuoted = false;
}