• Модуль: mail
  • Путь к файлу: ~/bitrix/modules/mail/lib/helper/mailbox/imap.php
  • Класс: BitrixMailHelperMailboxImap
  • Вызов: Imap::syncDirInternal
protected function syncDirInternal($dir)
{
	$messagesSynced = 0;

	$meta = $this->client->select($dir->getPath(), $error);

	if (false === $meta)
	{
		$this->warnings->add($this->client->getErrors()->toArray());

		if ($this->client->isExistsDir($dir->getPath(), $error) === false)
		{
			$this->getDirsHelper()->removeDirsLikePath([$dir]);
		}

		return false;
	}

	$this->getDirsHelper()->updateMessageCount($dir->getId(), $meta['exists']);

	$intervalSynchronizationAttempts = 0;

	while ($range = $this->getSyncRange($dir->getPath(), $uidtoken, $intervalSynchronizationAttempts))
	{
		$reverse = $range[0] > $range[1];

		sort($range);

		$messages = $this->client->fetch(
			true,
			$dir->getPath(),
			join(':', $range),
			'(UID FLAGS INTERNALDATE RFC822.SIZE BODYSTRUCTURE BODY.PEEK[HEADER])',
			$error
		);

		$fetchErrors=$this->client->getErrors();
		$errorReceivingMessages = $fetchErrors->getErrorByCode(210) !== null;
		$failureDueToDataVolume = $fetchErrors->getErrorByCode(104) !== null;

		if (empty($messages))
		{
			if (false === $messages)
			{
				if($errorReceivingMessages && !$failureDueToDataVolume)
				{
					/*
					 	 Skip the intervals where all the messages were broken
					*/
					return $messagesSynced;
				}
				elseif($failureDueToDataVolume && $intervalSynchronizationAttempts < count(self::MAXIMUM_SYNCHRONIZATION_LENGTHS_OF_INTERVALS) - 1 )
				{
					$intervalSynchronizationAttempts++;
					continue;
					/*
						Trying to resynchronize by reducing the interval
					*/
				}
				else
				{
					/*
						Fatal errors in which we cannot perform synchronization
					*/
					$this->warnings->add($fetchErrors->toArray());
					return false;
				}
			}
			break;
		}
		else
		{
			$intervalSynchronizationAttempts = 0;
		}

		$reverse ? krsort($messages) : ksort($messages);

		$this->parseHeaders($messages);

		$this->blacklistMessages($dir->getPath(), $messages);

		$this->removeExistingMessagesFromSynchronizationList($dir->getPath(), $uidtoken, $messages);

		foreach ($messages as &$message)
		{
			$this->fillMessageFields($message, $dir->getPath(), $uidtoken);
		}

		$this->linkWithExistingMessages($messages);

		$hashesMap = [];

		//To display new messages(grid reload) until synchronization is complete
		$numberOfMessagesInABatch = 1;
		$numberLeftToFillTheBatch = $numberOfMessagesInABatch;

		foreach ($messages as $item)
		{
			$isOutgoing = false;

			if(empty($item['__replaces']))
			{
				$outgoingMessageId = $this->selectOutgoingMessageIdFromHeader($item);

				if($outgoingMessageId)
				{
					$item['__replaces'] = $outgoingMessageId;
					$isOutgoing = true;
				}
			}

			if ($this->syncMessage($dir->getPath(), $item, $hashesMap, false, $isOutgoing))
			{
				$this->lastSyncResult['newMessageId'] = end($hashesMap);
				$messagesSynced++;

				$numberLeftToFillTheBatch--;
				if($numberLeftToFillTheBatch === 0 and MainLoader::includeModule('pull'))
				{
					$numberOfMessagesInABatch *= 2;
					$numberLeftToFillTheBatch = $numberOfMessagesInABatch;
					CPullWatch::addToStack(
						'mail_mailbox_' . $this->mailbox['ID'],
						[
							'params' => [
								'dir' => $dir->getPath(),
								'mailboxId' => $this->mailbox['ID'],
							],
							'module_id' => 'mail',
							'command' => 'new_message_is_synchronized',
						]
					);
					BitrixPullEvent::send();
				}
			}

			if ($this->isTimeQuotaExceeded())
			{
				break 2;
			}
		}
	}

	if (false === $range)
	{
		$this->warnings->add($this->client->getErrors()->toArray());

		return false;
	}

	return $messagesSynced;
}