• Модуль: mail
  • Путь к файлу: ~/bitrix/modules/mail/lib/imap.php
  • Класс: BitrixMailImap
  • Вызов: Imap::fetch
public function fetch($uid, $mailbox, $range, $select, &$error, $outputFormat = 'smart')
{
	$error = null;

	if (!preg_match('/(([1-9]d*|*)(:(?2))?)(,(?1))*/', $range))
	{
		return false;
	}

	if (empty($select))
	{
		$select = '(FLAGS)';
	}
	else if (is_array($select))
	{
		$select = sprintf('(%s)', join(' ', $select));
	}

	if (!$this->select($mailbox, $error))
	{
		return false;
	}

	$list = array();

	if ($this->sessMailbox['exists'] > 0)
	{
		$fetchUntaggedRegex = '/^ * x20 ( d+ ) x20 FETCH x20 ( ( .+ ) ) rn $/isx';
		$this->getUntagged($fetchUntaggedRegex, true);

		$response = $this->executeCommand(
			sprintf('%sFETCH %s %s', $uid ? 'UID ' : '', $range, $select),
			$error
		);

		if ($error)
		{
			$error = $error == Imap::ERR_COMMAND_REJECTED ? null : $error;
			$error = $this->errorMessage(array(Imap::ERR_FETCH, $error), $response);

			return false;
		}

		$shiftName = function (&$item)
		{
			$result = false;

			// #120949
			$regex = sprintf(
				'/^
					(
						[a-z0-9]+ (?: . [a-z0-9]+ )*
						(?: [ (?: [a-z0-9]+ (?: . [a-z0-9]* )* (?: x20 %s )* )? ] )?
						(?: < d+ > )?
					)
					x20
				/ix',
				self::$astringRegex
			);

			if (preg_match($regex, $item, $matches))
			{
				$result = $matches[1];

				$item = BinaryString::getSubstring($item, BinaryString::getLength($matches[0]));
			}

			return $result;
		};

		$shiftValue = function (&$item) use (&$shiftValue)
		{
			$result = false;

			$tail = ' (?= [x20)] | $ ) x20? ';

			if (BinaryString::getSubstring($item, 0, 1) === '(')
			{
				$item = BinaryString::getSubstring($item, 1);

				$result = array();

				while (BinaryString::getLength($item) > 0 && BinaryString::getSubstring($item, 0, 1) !== ')')
				{
					$subresult = $shiftValue($item);

					if (false !== $subresult)
					{
						$result[] = $subresult;
					}
					else
					{
						return false;
					}
				}

				if (preg_match('/^ ) (?= [x20()] | $ ) x20? /ix', $item, $matches))
				{
					$item = BinaryString::getSubstring($item, BinaryString::getLength($matches[0]));
				}
				else
				{
					return false;
				}
			}
			else if (preg_match('/^ { ( d+ ) } rn /ix', $item, $matches))
			{
				$item = BinaryString::getSubstring($item, BinaryString::getLength($matches[0]));

				if (BinaryString::getLength($item) >= $matches[1])
				{
					$result = BinaryString::getSubstring($item, 0, $matches[1]);

					$item = BinaryString::getSubstring($item, $matches[1]);

					if (preg_match(sprintf('/^ %s /ix', $tail), $item, $matches))
					{
						$item = BinaryString::getSubstring($item, BinaryString::getLength($matches[0]));
					}
					else
					{
						return false;
					}
				}
			}
			else if (preg_match(sprintf('/^ NIL %s /ix', $tail), $item, $matches))
			{
				$result = null;

				$item = BinaryString::getSubstring($item, BinaryString::getLength($matches[0]));
			}
			else if (preg_match(sprintf('/^ " ( (?: %s )* ) " %s /ix', self::$qcharExtRegex, $tail), $item, $matches))
			{
				$result = self::unescapeQuoted($matches[1]);

				$item = BinaryString::getSubstring($item, BinaryString::getLength($matches[0]));
			}
			else if (preg_match(sprintf('/^ ( x5c? %s ) %s /ix', self::$astringRegex, $tail), $item, $matches))
			{
				$result = $matches[1];

				$item = BinaryString::getSubstring($item, BinaryString::getLength($matches[0]));
			}
			else if (preg_match(sprintf('/^ %s /ix', $tail), $item, $matches))
			{
				$result = '';

				$item = BinaryString::getSubstring($item, BinaryString::getLength($matches[0]));
			}

			return $result;
		};

		$bodystructure = function (&$value) use (&$bodystructure)
		{
			if (!is_array($value) || !is_array($value[0]))
			{
				return $value;
			}

			$value[0] = $bodystructure($value[0]);
			$value[0] = array($value[0]);

			while (array_key_exists(1, $value) && is_array($value[1]))
			{
				$value[0][] = $bodystructure($value[1]);

				array_splice($value, 1, 1);
			}

			while (count($value[0]) == 1 && count($value[0][0]) == 1)
			{
				$value[0] = $value[0][0];
			}

			return $value;
		};

		foreach ($this->getUntagged($fetchUntaggedRegex, true) as $item)
		{
			$data = array(
				'id' => $item[1][1],
			);

			while (BinaryString::getLength($item[1][2]) > 0)
			{
				if (($name = $shiftName($item[1][2])) !== false)
				{
					if (($value = $shiftValue($item[1][2])) !== false)
					{
						if (in_array(mb_strtoupper($name), array('BODY', 'BODYSTRUCTURE')))
						{
							$value = $bodystructure($value);
						}

						$data[$name] = $value;

						continue;
					}
				}

				break;
			}

			$list[$data['id']] = $data;
		}
	}

	ksort($list);

	// todo remove the different format of the data output
	if ($outputFormat === 'smart' && !preg_match('/[:,]/', $range))
	{
		$list = reset($list);
	}

	return $list;
}