chore: Update copyright year from 2025 to 2026 across core files
- Updated copyright headers in 3,055 core application files - Changed 'Copyright (C) 2014-2025' to 'Copyright (C) 2014-2026' - Added 123 new files from EspoCRM core updates - Removed 4 deprecated files - Total changes: 61,637 insertions, 54,283 deletions This is a routine maintenance update for the new year 2026.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 EspoCRM, Inc.
|
||||
* Copyright (C) 2014-2026 EspoCRM, Inc.
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@@ -30,7 +30,6 @@
|
||||
namespace Espo\Core\Mail\Account;
|
||||
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
use Espo\Core\Mail\Account\Storage\Flag;
|
||||
use Espo\Core\Mail\Exceptions\ImapError;
|
||||
use Espo\Core\Mail\Exceptions\NoImap;
|
||||
@@ -41,7 +40,6 @@ use Espo\Core\Mail\MessageWrapper;
|
||||
use Espo\Core\Mail\Account\Hook\BeforeFetch as BeforeFetchHook;
|
||||
use Espo\Core\Mail\Account\Hook\AfterFetch as AfterFetchHook;
|
||||
use Espo\Core\Mail\Account\Hook\BeforeFetchResult as BeforeFetchHookResult;
|
||||
|
||||
use Espo\Core\Utils\Config;
|
||||
use Espo\Core\Utils\Log;
|
||||
use Espo\Core\Field\DateTime as DateTimeField;
|
||||
@@ -52,7 +50,6 @@ use Espo\ORM\Collection;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Query\Part\Expression;
|
||||
use Espo\ORM\Query\Part\Order;
|
||||
|
||||
use Throwable;
|
||||
use DateTime;
|
||||
|
||||
@@ -100,12 +97,13 @@ class Fetcher
|
||||
/**
|
||||
* @param Collection<EmailFilter> $filterList
|
||||
* @throws Error
|
||||
* @throws ImapError
|
||||
*/
|
||||
private function fetchFolder(
|
||||
Account $account,
|
||||
string $folderOriginal,
|
||||
Storage $storage,
|
||||
Collection $filterList
|
||||
Collection $filterList,
|
||||
): void {
|
||||
|
||||
$fetchData = $account->getFetchData();
|
||||
@@ -115,60 +113,59 @@ class Fetcher
|
||||
try {
|
||||
$storage->selectFolder($folderOriginal);
|
||||
} catch (Throwable $e) {
|
||||
$this->log->error(
|
||||
"{$account->getEntityType()} {$account->getId()}, " .
|
||||
"could not select folder '$folder'; [{$e->getCode()}] {$e->getMessage()}"
|
||||
);
|
||||
$message = "{$account->getEntityType()} {$account->getId()}, " .
|
||||
"could not select folder '$folder'; {$e->getMessage()}";
|
||||
|
||||
$this->log->error($message, ['exception' => $e]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$lastUniqueId = $fetchData->getLastUniqueId($folder);
|
||||
$lastId = $fetchData->getLastUid($folder);
|
||||
$lastDate = $fetchData->getLastDate($folder);
|
||||
$forceByDate = $fetchData->getForceByDate($folder);
|
||||
|
||||
$portionLimit = $forceByDate ? 0 : $account->getPortionLimit();
|
||||
|
||||
$previousLastUniqueId = $lastUniqueId;
|
||||
$previousLastId = $lastId;
|
||||
|
||||
$idList = $this->getIdList(
|
||||
$account,
|
||||
$storage,
|
||||
$lastUniqueId,
|
||||
$lastDate,
|
||||
$forceByDate
|
||||
$ids = $this->fetchIds(
|
||||
account: $account,
|
||||
storage: $storage,
|
||||
lastUid: $lastId,
|
||||
lastDate: $lastDate,
|
||||
forceByDate: $forceByDate,
|
||||
);
|
||||
|
||||
if (count($idList) === 1 && $lastUniqueId) {
|
||||
if ($storage->getUniqueId($idList[0]) === $lastUniqueId) {
|
||||
return;
|
||||
}
|
||||
if (count($ids) === 1 && $ids[0] === $lastId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$counter = 0;
|
||||
|
||||
foreach ($idList as $id) {
|
||||
if ($counter == count($idList) - 1) {
|
||||
$lastUniqueId = $storage->getUniqueId($id);
|
||||
foreach ($ids as $id) {
|
||||
if ($counter === count($ids) - 1) {
|
||||
$lastId = $id;
|
||||
}
|
||||
|
||||
if ($forceByDate && $previousLastUniqueId) {
|
||||
$uid = $storage->getUniqueId($id);
|
||||
if ($forceByDate && $previousLastId && $id <= $previousLastId) {
|
||||
$counter++;
|
||||
|
||||
if ((int) $uid <= (int) $previousLastUniqueId) {
|
||||
$counter++;
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$email = $this->fetchEmail($account, $storage, $id, $filterList);
|
||||
$email = $this->fetchEmail(
|
||||
account: $account,
|
||||
storage: $storage,
|
||||
id: $id,
|
||||
filterList: $filterList,
|
||||
mappedEmailFolderId: $account->getMappedEmailFolder($folderOriginal)?->getId(),
|
||||
);
|
||||
|
||||
$isLast = $counter === count($idList) - 1;
|
||||
$isLast = $counter === count($ids) - 1;
|
||||
$isLastInPortion = $counter === $portionLimit - 1;
|
||||
|
||||
if ($isLast || $isLastInPortion) {
|
||||
$lastUniqueId = $storage->getUniqueId($id);
|
||||
$lastId = $id;
|
||||
|
||||
if ($email && $email->getDateSent()) {
|
||||
$lastDate = $email->getDateSent();
|
||||
@@ -181,7 +178,7 @@ class Fetcher
|
||||
break;
|
||||
}
|
||||
|
||||
$counter++;
|
||||
$counter ++;
|
||||
}
|
||||
|
||||
if ($forceByDate) {
|
||||
@@ -189,25 +186,21 @@ class Fetcher
|
||||
}
|
||||
|
||||
$fetchData->setLastDate($folder, $lastDate);
|
||||
$fetchData->setLastUniqueId($folder, $lastUniqueId);
|
||||
$fetchData->setLastUid($folder, $lastId);
|
||||
|
||||
if ($forceByDate && $previousLastUniqueId) {
|
||||
$idList = $storage->getIdsFromUniqueId($previousLastUniqueId);
|
||||
if ($forceByDate && $previousLastId) {
|
||||
$ids = $storage->getUidsFromUid($previousLastId);
|
||||
|
||||
if (count($idList)) {
|
||||
$uid1 = $storage->getUniqueId($idList[0]);
|
||||
|
||||
if ((int) $uid1 > (int) $previousLastUniqueId) {
|
||||
$fetchData->setForceByDate($folder, false);
|
||||
}
|
||||
if (count($ids) && $ids[0] > $previousLastId) {
|
||||
$fetchData->setForceByDate($folder, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!$forceByDate &&
|
||||
$previousLastUniqueId &&
|
||||
count($idList) &&
|
||||
(int) $previousLastUniqueId >= (int) $lastUniqueId
|
||||
count($ids) &&
|
||||
$previousLastId &&
|
||||
$previousLastId >= $lastId
|
||||
) {
|
||||
// Handling broken numbering. Next time fetch since the last date rather than the last UID.
|
||||
$fetchData->setForceByDate($folder, true);
|
||||
@@ -219,21 +212,22 @@ class Fetcher
|
||||
/**
|
||||
* @return int[]
|
||||
* @throws Error
|
||||
* @throws ImapError
|
||||
*/
|
||||
private function getIdList(
|
||||
private function fetchIds(
|
||||
Account $account,
|
||||
Storage $storage,
|
||||
?string $lastUID,
|
||||
?int $lastUid,
|
||||
?DateTimeField $lastDate,
|
||||
bool $forceByDate
|
||||
bool $forceByDate,
|
||||
): array {
|
||||
|
||||
if (!empty($lastUID) && !$forceByDate) {
|
||||
return $storage->getIdsFromUniqueId($lastUID);
|
||||
if ($lastUid !== null && !$forceByDate) {
|
||||
return $storage->getUidsFromUid($lastUid);
|
||||
}
|
||||
|
||||
if ($lastDate) {
|
||||
return $storage->getIdsSinceDate($lastDate);
|
||||
return $storage->getUidsSinceDate($lastDate);
|
||||
}
|
||||
|
||||
if (!$account->getFetchSince()) {
|
||||
@@ -242,7 +236,7 @@ class Fetcher
|
||||
|
||||
$fetchSince = $account->getFetchSince()->toDateTime();
|
||||
|
||||
return $storage->getIdsSinceDate(
|
||||
return $storage->getUidsSinceDate(
|
||||
DateTimeField::fromDateTime($fetchSince)
|
||||
);
|
||||
}
|
||||
@@ -254,7 +248,8 @@ class Fetcher
|
||||
Account $account,
|
||||
Storage $storage,
|
||||
int $id,
|
||||
Collection $filterList
|
||||
Collection $filterList,
|
||||
?string $mappedEmailFolderId,
|
||||
): ?Email {
|
||||
|
||||
$teamIdList = $account->getTeams()->getIdList();
|
||||
@@ -265,11 +260,7 @@ class Fetcher
|
||||
|
||||
$fetchOnlyHeader = $this->checkFetchOnlyHeader($storage, $id);
|
||||
|
||||
$folderData = [];
|
||||
|
||||
if ($userId && $account->getEmailFolder()) {
|
||||
$folderData[$userId] = $account->getEmailFolder()->getId();
|
||||
}
|
||||
$folderData = $this->prepareFolderData($userId, $mappedEmailFolderId, $account);
|
||||
|
||||
$flags = null;
|
||||
|
||||
@@ -286,7 +277,12 @@ class Fetcher
|
||||
->withGroupEmailFolderId($groupEmailFolderId);
|
||||
|
||||
try {
|
||||
$message = new MessageWrapper($id, $storage, $parser);
|
||||
$message = new MessageWrapper(
|
||||
id: $id,
|
||||
storage: $storage,
|
||||
parser: $parser,
|
||||
peek: $account->keepFetchedEmailsUnread(),
|
||||
);
|
||||
|
||||
$hookResult = null;
|
||||
|
||||
@@ -313,7 +309,7 @@ class Fetcher
|
||||
$flags !== null &&
|
||||
!in_array(Flag::SEEN, $flags)
|
||||
) {
|
||||
$storage->setFlags($id, self::flagsWithoutRecent($flags));
|
||||
$storage->unmarkSeen($id);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->log->error(
|
||||
@@ -433,10 +429,10 @@ class Fetcher
|
||||
try {
|
||||
return $this->importer->import($message, $data);
|
||||
} catch (Throwable $e) {
|
||||
$this->log->error(
|
||||
"{$account->getEntityType()} {$account->getId()}, import message; " .
|
||||
"{$e->getCode()} {$e->getMessage()}"
|
||||
);
|
||||
$message = "{$account->getEntityType()} {$account->getId()}, import message; " .
|
||||
"{$e->getCode()} {$e->getMessage()}";
|
||||
|
||||
$this->log->error($message, ['exception' => $e]);
|
||||
|
||||
if ($this->entityManager->getLocker()->isLocked()) {
|
||||
$this->entityManager->getLocker()->rollback();
|
||||
@@ -447,13 +443,22 @@ class Fetcher
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $flags
|
||||
* @return string[]
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private static function flagsWithoutRecent(array $flags): array
|
||||
private function prepareFolderData(?string $userId, ?string $mappedEmailFolderId, Account $account): array
|
||||
{
|
||||
return array_values(
|
||||
array_diff($flags, [Flag::RECENT])
|
||||
);
|
||||
if (!$userId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$folderData = [];
|
||||
|
||||
if ($mappedEmailFolderId) {
|
||||
$folderData[$userId] = $mappedEmailFolderId;
|
||||
} else if ($account->getEmailFolder()) {
|
||||
$folderData[$userId] = $account->getEmailFolder()->getId();
|
||||
}
|
||||
|
||||
return $folderData;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user