type fixes
This commit is contained in:
@@ -68,7 +68,7 @@ class BeforeFetch implements BeforeFetchInterface
|
||||
{
|
||||
if (
|
||||
$message->hasHeader('from') &&
|
||||
preg_match('/MAILER-DAEMON|POSTMASTER/i', $message->getHeader('from'))
|
||||
preg_match('/MAILER-DAEMON|POSTMASTER/i', $message->getHeader('from') ?? '')
|
||||
) {
|
||||
try {
|
||||
$toSkip = $this->processBounced($message);
|
||||
@@ -113,7 +113,7 @@ class BeforeFetch implements BeforeFetchInterface
|
||||
else {
|
||||
$to = $message->getHeader('to');
|
||||
|
||||
if (preg_match('/\+bounce-qid-[a-z0-9\-]*/', $to, $m)) {
|
||||
if (preg_match('/\+bounce-qid-[a-z0-9\-]*/', $to ?? '', $m)) {
|
||||
/** @var array{string} */
|
||||
$arr = preg_split('/\+bounce-qid-/', $m[0], -1, \PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
|
||||
@@ -81,7 +81,8 @@ class Service
|
||||
|
||||
$params = $params
|
||||
->withPassword(
|
||||
$params->getPassword() ?? $this->crypt->decrypt($account->getPassword())
|
||||
$params->getPassword() ??
|
||||
$this->crypt->decrypt($account->getPassword() ?? '')
|
||||
)
|
||||
->withImapHandlerClassName($account->getImapHandlerClassName());
|
||||
}
|
||||
@@ -98,7 +99,8 @@ class Service
|
||||
|
||||
$params = $params
|
||||
->withPassword(
|
||||
$params->getPassword() ?? $this->crypt->decrypt($account->getPassword())
|
||||
$params->getPassword() ??
|
||||
$this->crypt->decrypt($account->getPassword() ?? '')
|
||||
)
|
||||
->withImapHandlerClassName($account->getImapHandlerClassName());
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ class StorageFactory implements StorageFactoryInterface
|
||||
->setSecurity($account->getSecurity())
|
||||
->setUsername($account->getUsername())
|
||||
->setPassword(
|
||||
$this->crypt->decrypt($account->getPassword())
|
||||
$this->crypt->decrypt($account->getPassword() ?? '')
|
||||
)
|
||||
->setId($account->getId())
|
||||
->setImapHandlerClassName($account->getImapHandlerClassName())
|
||||
@@ -104,7 +104,7 @@ class StorageFactory implements StorageFactoryInterface
|
||||
);
|
||||
}
|
||||
|
||||
if (method_exists($handler, 'prepareProtocol')) {
|
||||
if ($handler && method_exists($handler, 'prepareProtocol')) {
|
||||
// for backward compatibility
|
||||
$rawParams['ssl'] = $rawParams['security'] ?? null;
|
||||
|
||||
|
||||
@@ -68,11 +68,15 @@ class Account implements AccountInterface
|
||||
throw new Error("No assigned user.");
|
||||
}
|
||||
|
||||
$this->user = $this->entityManager->getEntity(User::ENTITY_TYPE, $this->entity->getAssignedUser()->getId());
|
||||
$userId = $this->entity->getAssignedUser()->getId();
|
||||
|
||||
if (!$this->user) {
|
||||
$user = $this->entityManager->getEntityById(User::ENTITY_TYPE, $userId);
|
||||
|
||||
if (!$user) {
|
||||
throw new Error("Assigned user not found.");
|
||||
}
|
||||
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function updateFetchData(FetchData $fetchData): void
|
||||
@@ -114,10 +118,12 @@ class Account implements AccountInterface
|
||||
{
|
||||
$linkMultiple = LinkMultiple::create();
|
||||
|
||||
$userLink = $this->getUser();
|
||||
|
||||
return $linkMultiple->withAdded(
|
||||
LinkMultipleItem
|
||||
::create($this->getUser()->getId())
|
||||
->withName($this->getUser()->getName())
|
||||
::create($userLink->getId())
|
||||
->withName($userLink->getName() ?? '')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -128,7 +134,13 @@ class Account implements AccountInterface
|
||||
|
||||
public function getUser(): Link
|
||||
{
|
||||
return $this->entity->getAssignedUser();
|
||||
$userLink = $this->entity->getAssignedUser();
|
||||
|
||||
if (!$userLink) {
|
||||
throw new Error("No assigned user.");
|
||||
}
|
||||
|
||||
return $userLink;
|
||||
}
|
||||
|
||||
public function getTeams(): LinkMultiple
|
||||
@@ -144,7 +156,7 @@ class Account implements AccountInterface
|
||||
return $linkMultiple->withAdded(
|
||||
LinkMultipleItem
|
||||
::create($team->getId())
|
||||
->withName($team->getName())
|
||||
->withName($team->getName() ?? '')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,8 @@ class Service
|
||||
|
||||
$params = $params
|
||||
->withPassword(
|
||||
$params->getPassword() ?? $this->crypt->decrypt($account->getPassword())
|
||||
$params->getPassword() ??
|
||||
$this->crypt->decrypt($account->getPassword() ?? '')
|
||||
)
|
||||
->withImapHandlerClassName($account->getImapHandlerClassName());
|
||||
}
|
||||
@@ -136,7 +137,8 @@ class Service
|
||||
|
||||
$params = $params
|
||||
->withPassword(
|
||||
$params->getPassword() ?? $this->crypt->decrypt($account->getPassword())
|
||||
$params->getPassword() ??
|
||||
$this->crypt->decrypt($account->getPassword() ?? '')
|
||||
)
|
||||
->withImapHandlerClassName($account->getImapHandlerClassName());
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ use Espo\Repositories\UserData as UserDataRepository;
|
||||
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use LogicException;
|
||||
use Throwable;
|
||||
|
||||
class StorageFactory implements StorageFactoryInterface
|
||||
@@ -71,16 +72,24 @@ class StorageFactory implements StorageFactoryInterface
|
||||
|
||||
public function create(Account $account): LaminasStorage
|
||||
{
|
||||
$userLink = $account->getUser();
|
||||
|
||||
if (!$userLink) {
|
||||
throw new LogicException("No user for mail account.");
|
||||
}
|
||||
|
||||
$userId = $userLink->getId();
|
||||
|
||||
$params = Params::createBuilder()
|
||||
->setHost($account->getHost())
|
||||
->setPort($account->getPort())
|
||||
->setSecurity($account->getSecurity())
|
||||
->setUsername($account->getUsername())
|
||||
->setPassword(
|
||||
$this->crypt->decrypt($account->getPassword())
|
||||
$this->crypt->decrypt($account->getPassword() ?? '')
|
||||
)
|
||||
->setEmailAddress($account->getEmailAddress())
|
||||
->setUserId($account->getUser()->getId())
|
||||
->setUserId($userId)
|
||||
->setId($account->getId())
|
||||
->setImapHandlerClassName($account->getImapHandlerClassName())
|
||||
->build();
|
||||
@@ -123,7 +132,7 @@ class StorageFactory implements StorageFactoryInterface
|
||||
);
|
||||
}
|
||||
|
||||
if (method_exists($handler, 'prepareProtocol')) {
|
||||
if ($handler && method_exists($handler, 'prepareProtocol')) {
|
||||
// for backward compatibility
|
||||
$rawParams['ssl'] = $rawParams['security'] ?? null;
|
||||
|
||||
@@ -140,7 +149,7 @@ class StorageFactory implements StorageFactoryInterface
|
||||
$imapHandlers = $userData->get('imapHandlers') ?? (object) [];
|
||||
|
||||
if (isset($imapHandlers->$emailAddress)) {
|
||||
/** @var ?class-string */
|
||||
/** @var class-string */
|
||||
$handlerClassName = $imapHandlers->$emailAddress;
|
||||
|
||||
try {
|
||||
@@ -153,7 +162,7 @@ class StorageFactory implements StorageFactoryInterface
|
||||
);
|
||||
}
|
||||
|
||||
if (method_exists($handler, 'prepareProtocol')) {
|
||||
if ($handler && method_exists($handler, 'prepareProtocol')) {
|
||||
$imapParams = $handler->prepareProtocol($userId, $emailAddress, $rawParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,13 +49,16 @@ class FiltersMatcher
|
||||
foreach ($filterList as $filter) {
|
||||
$filterCount = 0;
|
||||
|
||||
if ($filter->getFrom()) {
|
||||
$from = $filter->getFrom();
|
||||
$subject = $filter->getSubject();
|
||||
|
||||
if ($from) {
|
||||
$filterCount++;
|
||||
|
||||
if (
|
||||
!$this->matchString(
|
||||
strtolower($filter->getFrom()),
|
||||
strtolower($email->getFromAddress())
|
||||
strtolower($from),
|
||||
strtolower($email->getFromAddress() ?? '')
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
@@ -70,10 +73,12 @@ class FiltersMatcher
|
||||
}
|
||||
}
|
||||
|
||||
if ($filter->getSubject()) {
|
||||
if ($subject) {
|
||||
$filterCount++;
|
||||
|
||||
if (!$this->matchString($filter->getSubject(), $email->getSubject())) {
|
||||
if (
|
||||
!$this->matchString($subject, $email->getSubject() ?? '')
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -100,9 +105,20 @@ class FiltersMatcher
|
||||
|
||||
private function matchTo(Email $email, EmailFilter $filter): bool
|
||||
{
|
||||
$filterTo = $filter->getTo();
|
||||
|
||||
if ($filterTo === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count($email->getToAddressList())) {
|
||||
foreach ($email->getToAddressList() as $to) {
|
||||
if ($this->matchString(strtolower($filter->getTo()), strtolower($to))) {
|
||||
if (
|
||||
$this->matchString(
|
||||
strtolower($filterTo),
|
||||
strtolower($to)
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -122,11 +138,11 @@ class FiltersMatcher
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stripos($bodyPlain, $phrase) !== false) {
|
||||
if ($bodyPlain && stripos($bodyPlain, $phrase) !== false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (stripos($body, $phrase) !== false) {
|
||||
if ($body && stripos($body, $phrase) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ use Espo\Repositories\Email as EmailRepository;
|
||||
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use Espo\Core\Utils\DateTime as DateTimeUtil;
|
||||
|
||||
use Espo\Core\Notification\AssignmentNotificator;
|
||||
use Espo\Core\Notification\AssignmentNotificatorFactory;
|
||||
use Espo\Core\Notification\AssignmentNotificator\Params as AssignmentNotificatorParams;
|
||||
@@ -182,6 +184,7 @@ class Importer
|
||||
$parser->hasHeader($message, 'message-Id') &&
|
||||
$parser->getHeader($message, 'message-Id')
|
||||
) {
|
||||
/** @var string */
|
||||
$messageId = $parser->getMessageId($message);
|
||||
|
||||
$email->set('messageId', $messageId);
|
||||
@@ -217,25 +220,35 @@ class Importer
|
||||
|
||||
if ($parser->hasHeader($message, 'date')) {
|
||||
try {
|
||||
$dt = new DateTime($parser->getHeader($message, 'date'));
|
||||
/** @var string */
|
||||
$dateHeaderValue = $parser->getHeader($message, 'date');
|
||||
|
||||
$dateSent = $dt->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s');
|
||||
$dt = new DateTime($dateHeaderValue);
|
||||
|
||||
$dateSent = $dt
|
||||
->setTimezone(new DateTimeZone('UTC'))
|
||||
->format(DateTimeUtil::SYSTEM_DATE_TIME_FORMAT);
|
||||
|
||||
$email->set('dateSent', $dateSent);
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
}
|
||||
else {
|
||||
$email->set('dateSent', date('Y-m-d H:i:s'));
|
||||
$email->set('dateSent', date(DateTimeUtil::SYSTEM_DATE_TIME_FORMAT));
|
||||
}
|
||||
|
||||
if ($parser->hasHeader($message, 'delivery-Date')) {
|
||||
try {
|
||||
$dt = new DateTime($parser->getHeader($message, 'delivery-Date'));
|
||||
/** @var string */
|
||||
$deliveryDateHeaderValue = $parser->getHeader($message, 'delivery-Date');
|
||||
|
||||
$deliveryDate = $dt->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s');
|
||||
$dt = new DateTime($deliveryDateHeaderValue);
|
||||
|
||||
$email->set('delivery-Date', $deliveryDate);
|
||||
$deliveryDate = $dt
|
||||
->setTimezone(new DateTimeZone('UTC'))
|
||||
->format(DateTimeUtil::SYSTEM_DATE_TIME_FORMAT);
|
||||
|
||||
$email->set('deliveryDate', $deliveryDate);
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
}
|
||||
@@ -280,6 +293,7 @@ class Importer
|
||||
if ($replied) {
|
||||
$email->set('repliedId', $replied->getId());
|
||||
|
||||
/** @var string[] */
|
||||
$repliedTeamIdList = $replied->getLinkMultipleIdList('teams');
|
||||
|
||||
foreach ($repliedTeamIdList as $repliedTeamId) {
|
||||
@@ -449,6 +463,7 @@ class Importer
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var string[] */
|
||||
$parentTeamIdList = $parent->getLinkMultipleIdList('teams');
|
||||
|
||||
foreach ($parentTeamIdList as $parentTeamId) {
|
||||
@@ -653,6 +668,7 @@ class Importer
|
||||
|
||||
$duplicate->loadLinkMultipleField('users');
|
||||
|
||||
/** @var string[] */
|
||||
$fetchedUserIdList = $duplicate->getLinkMultipleIdList('users');
|
||||
|
||||
$duplicate->setLinkMultipleIdList('users', []);
|
||||
@@ -710,6 +726,7 @@ class Importer
|
||||
);
|
||||
}
|
||||
|
||||
/** @var string[] */
|
||||
$fetchedTeamIdList = $duplicate->getLinkMultipleIdList('teams');
|
||||
|
||||
foreach ($teamIdList as $teamId) {
|
||||
@@ -731,9 +748,9 @@ class Importer
|
||||
|
||||
$dt->modify('+5 seconds');
|
||||
|
||||
$executeAt = $dt->format('Y-m-d H:i:s');
|
||||
$executeAt = $dt->format(DateTimeUtil::SYSTEM_DATE_TIME_FORMAT);
|
||||
|
||||
$job = $this->entityManager->getEntity('Job');
|
||||
$job = $this->entityManager->getNewEntity('Job');
|
||||
|
||||
$job->set([
|
||||
'serviceName' => 'Stream',
|
||||
|
||||
@@ -44,7 +44,7 @@ class XQueueItemId implements Header\HeaderInterface
|
||||
private ?string $id = null;
|
||||
|
||||
/**
|
||||
* @param ?string $headerLine
|
||||
* @param string $headerLine
|
||||
* @return self
|
||||
*/
|
||||
public static function fromString($headerLine)
|
||||
|
||||
@@ -38,6 +38,8 @@ class Imap extends \Laminas\Mail\Storage\Imap
|
||||
{
|
||||
$nextUid = strval(intval($uid) + 1);
|
||||
|
||||
assert($this->protocol !== null);
|
||||
|
||||
return $this->protocol->search(['UID ' . $nextUid . ':*']);
|
||||
}
|
||||
|
||||
@@ -46,6 +48,8 @@ class Imap extends \Laminas\Mail\Storage\Imap
|
||||
*/
|
||||
public function getIdsSinceDate(string $date): array
|
||||
{
|
||||
assert($this->protocol !== null);
|
||||
|
||||
return $this->protocol->search(['SINCE "' . $date . '"']);
|
||||
}
|
||||
|
||||
@@ -55,6 +59,8 @@ class Imap extends \Laminas\Mail\Storage\Imap
|
||||
*/
|
||||
public function getHeaderAndFlags(int $id): array
|
||||
{
|
||||
assert($this->protocol !== null);
|
||||
|
||||
/** @var array{'RFC822.HEADER': string, FLAGS: string[]} */
|
||||
$data = $this->protocol->fetch(['FLAGS', 'RFC822.HEADER'], $id);
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ namespace Espo\Core\Mail;
|
||||
|
||||
use Espo\Core\Mail\Account\Storage;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class MessageWrapper implements Message
|
||||
{
|
||||
private int $id;
|
||||
@@ -81,17 +83,29 @@ class MessageWrapper implements Message
|
||||
|
||||
public function hasHeader(string $name): bool
|
||||
{
|
||||
return $this->getParser()->hasHeader($this, $name);
|
||||
if (!$this->parser) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
return $this->parser->hasHeader($this, $name);
|
||||
}
|
||||
|
||||
public function getHeader(string $attribute): ?string
|
||||
{
|
||||
return $this->getParser()->getHeader($this, $attribute);
|
||||
if (!$this->parser) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
return $this->parser->getHeader($this, $attribute);
|
||||
}
|
||||
|
||||
public function getRawContent(): string
|
||||
{
|
||||
if (is_null($this->rawContent)) {
|
||||
if (!$this->storage) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
$this->rawContent = $this->storage->getRawContent($this->id);
|
||||
}
|
||||
|
||||
|
||||
@@ -602,7 +602,9 @@ class Sender
|
||||
|
||||
$htmlPart = null;
|
||||
|
||||
if ($email->get('isHtml')) {
|
||||
$isHtml = $email->get('isHtml');
|
||||
|
||||
if ($isHtml) {
|
||||
$htmlPart = new MimePart($email->getBodyForSending());
|
||||
|
||||
$htmlPart->encoding = Mime::ENCODING_QUOTEDPRINTABLE;
|
||||
@@ -613,7 +615,7 @@ class Sender
|
||||
if (!empty($attachmentPartList)) {
|
||||
$messageType = 'multipart/related';
|
||||
|
||||
if ($email->get('isHtml')) {
|
||||
if ($isHtml) {
|
||||
$content = new MimeMessage();
|
||||
|
||||
$content->addPart($textPart);
|
||||
@@ -637,7 +639,7 @@ class Sender
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($email->get('isHtml')) {
|
||||
if ($isHtml) {
|
||||
$body->setParts([$textPart, $htmlPart]);
|
||||
|
||||
$messageType = 'multipart/alternative';
|
||||
@@ -698,6 +700,8 @@ class Sender
|
||||
|
||||
$message->getHeaders()->addHeader($messageIdHeader);
|
||||
|
||||
assert($this->transport !== null);
|
||||
|
||||
$this->transport->send($message);
|
||||
|
||||
$email->set('status', 'Sent');
|
||||
|
||||
Reference in New Issue
Block a user