Cleanup MailSo

This commit is contained in:
the-djmaze 2022-12-19 17:26:59 +01:00
parent a78fcb6308
commit 22450e7430
14 changed files with 243 additions and 470 deletions

View file

@ -1,24 +0,0 @@
<?php
/*
* This file is part of MailSo.
*
* (c) 2014 Usenko Timur
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MailSo\Base;
/**
* @category MailSo
* @package Base
*/
class Validator
{
public static function RangeInt(int $iNumber, int $iMin = null, int $iMax = null) : bool
{
return (null === $iMin || $iNumber >= $iMin) && (null === $iMax || $iNumber <= $iMax);
}
}

View file

@ -16,6 +16,8 @@ use MailSo\Imap\Folder;
use MailSo\Imap\FolderInformation;
use MailSo\Imap\SequenceSet;
use MailSo\Imap\Enumerations\FolderStatus;
use MailSo\Imap\Enumerations\MessageFlag;
use MailSo\Imap\Enumerations\StoreAction;
/**
* @category MailSo
@ -23,20 +25,33 @@ use MailSo\Imap\Enumerations\FolderStatus;
*/
trait Folders
{
/**
* @throws \InvalidArgumentException
*/
public function FolderClear(string $sFolderFullName) : void
{
if (0 < $this->FolderSelect($sFolderFullName)->MESSAGES) {
$this->MessageStoreFlag(new SequenceSet('1:*', false),
array(MessageFlag::DELETED),
StoreAction::ADD_FLAGS_SILENT
);
$this->FolderExpunge();
}
}
/**
* @throws \InvalidArgumentException
* @throws \MailSo\RuntimeException
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderCreate(string $sFolderName, bool $bSubscribe = false) : self
public function FolderCreate(string $sFolderName, bool $bSubscribe = false) : void
{
$this->SendRequestGetResponse('CREATE', array(
$this->EscapeFolderName($sFolderName)
// , ['(USE (\Drafts \Sent))'] RFC 6154
));
$bSubscribe && $this->FolderSubscribe($sFolderName);
return $this;
}
/**
@ -45,23 +60,34 @@ trait Folders
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderDelete(string $sFolderName) : self
public function FolderDelete(string $sFolderName) : void
{
if (!$sFolderName || 'INBOX' === $sFolderName) {
throw new \InvalidArgumentException;
}
$oInfo = $this->hasCapability('IMAP4rev2')
? $this->FolderExamine($sFolderName)
: $this->FolderStatus($sFolderName);
if ($oInfo->MESSAGES) {
throw new \MailSo\Mail\Exceptions\NonEmptyFolder;
}
$this->FolderUnsubscribe($sFolderName);
$this->FolderUnselect();
// Uncomment will work issue #124 ?
// $this->selectOrExamineFolder($sFolderName, true);
$this->SendRequestGetResponse('DELETE',
array($this->EscapeFolderName($sFolderName)));
$this->SendRequestGetResponse('DELETE', [$this->EscapeFolderName($sFolderName)]);
// $this->FolderCheck();
// $this->FolderUnselect();
// Will this workaround solve Dovecot issue #124 ?
try {
$this->FolderRename($sFolderName, "{$sFolderName}-dummy");
$this->FolderRename("{$sFolderName}-dummy", $sFolderName);
} catch (\Throwable $e) {
} catch (\Throwable $oException) {
$this->writeLogException($oException, \LOG_WARNING, false);
}
return $this;
}
/**
@ -70,11 +96,9 @@ trait Folders
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderSubscribe(string $sFolderName) : self
public function FolderSubscribe(string $sFolderName) : void
{
$this->SendRequestGetResponse('SUBSCRIBE',
array($this->EscapeFolderName($sFolderName)));
return $this;
$this->SendRequestGetResponse('SUBSCRIBE', [$this->EscapeFolderName($sFolderName)]);
}
/**
@ -83,11 +107,9 @@ trait Folders
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderUnsubscribe(string $sFolderName) : self
public function FolderUnsubscribe(string $sFolderName) : void
{
$this->SendRequestGetResponse('UNSUBSCRIBE',
array($this->EscapeFolderName($sFolderName)));
return $this;
$this->SendRequestGetResponse('UNSUBSCRIBE', [$this->EscapeFolderName($sFolderName)]);
}
/**
@ -96,12 +118,12 @@ trait Folders
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderRename(string $sOldFolderName, string $sNewFolderName) : self
public function FolderRename(string $sOldFolderName, string $sNewFolderName) : void
{
$this->SendRequestGetResponse('RENAME', array(
$this->SendRequestGetResponse('RENAME', [
$this->EscapeFolderName($sOldFolderName),
$this->EscapeFolderName($sNewFolderName)));
return $this;
$this->EscapeFolderName($sNewFolderName)
]);
}
private function FolderStatusItems() : array
@ -202,12 +224,11 @@ trait Folders
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderCheck() : self
public function FolderCheck() : void
{
if ($this->IsSelected()) {
$this->SendRequestGetResponse('CHECK');
}
return $this;
}
/**
@ -232,7 +253,7 @@ trait Folders
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderUnselect() : self
public function FolderUnselect() : void
{
if ($this->IsSelected()) {
if ($this->hasCapability('UNSELECT')) {
@ -243,14 +264,13 @@ trait Folders
$this->SendRequestGetResponse('SELECT', ['""']);
// * OK [CLOSED] Previous mailbox closed.
// 3 NO [CANNOT] Invalid mailbox name: Name is empty
} catch (\MailSo\Imap\Exceptions\NegativeResponseException $e) {
if ('NO' === $e->GetResponseStatus()) {
} catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException) {
if ('NO' === $oException->GetResponseStatus()) {
$this->oCurrentFolderInfo = null;
}
}
}
}
return $this;
}
/**
@ -453,8 +473,7 @@ trait Folders
// $aParameters[] = $this->EscapeString(\strlen(\trim($sListPattern)) ? $sListPattern : '*');
// RFC 5819
if ($bUseListStatus && !$bIsSubscribeList && $this->hasCapability('LIST-STATUS'))
{
if ($bUseListStatus && !$bIsSubscribeList && $this->hasCapability('LIST-STATUS')) {
$aReturnParams[] = 'STATUS';
$aReturnParams[] = $this->FolderStatusItems();
}
@ -469,80 +488,71 @@ trait Folders
$aParameters[] = $aReturnParams;
}
/*
$bPassthru = false;
$aReturn = array();
if ($bPassthru) {
$this->SendRequest($sCmd, $aParameters);
$this->streamResponse();
return [];
}
*/
// RFC 5464
$bMetadata = !$bIsSubscribeList && $this->hasCapability('METADATA');
$aMetadata = null;
if ($bMetadata) {
// Dovecot supports fetching all METADATA at once
$aMetadata = $this->getAllMetadata();
}
// Dovecot supports fetching all METADATA at once
$aMetadata = $bMetadata ? $this->getAllMetadata() : null;
$this->SendRequest($sCmd, $aParameters);
if ($bPassthru) {
$this->streamResponse();
} else {
$sDelimiter = '';
$bInbox = false;
foreach ($this->yieldUntaggedResponses() as $oResponse) {
if ('STATUS' === $oResponse->StatusOrIndex && isset($oResponse->ResponseList[2])) {
$sFullName = $this->toUTF8($oResponse->ResponseList[2]);
if (!isset($aReturn[$sFullName])) {
$aReturn[$sFullName] = new Folder($sFullName);
}
$aReturn[$sFullName]->setStatusFromResponse($oResponse);
$aReturn = array();
$sDelimiter = '';
$bInbox = false;
foreach ($this->yieldUntaggedResponses() as $oResponse) {
if ('STATUS' === $oResponse->StatusOrIndex && isset($oResponse->ResponseList[2])) {
$sFullName = $this->toUTF8($oResponse->ResponseList[2]);
if (!isset($aReturn[$sFullName])) {
$aReturn[$sFullName] = new Folder($sFullName);
}
else if ($sCmd === $oResponse->StatusOrIndex && 5 === \count($oResponse->ResponseList)) {
try
{
$sFullName = $this->toUTF8($oResponse->ResponseList[4]);
/**
* $oResponse->ResponseList[0] = *
* $oResponse->ResponseList[1] = LIST (all) | LSUB (subscribed)
* $oResponse->ResponseList[2] = Flags
* $oResponse->ResponseList[3] = Delimiter
* $oResponse->ResponseList[4] = FullName
*/
if (!isset($aReturn[$sFullName])) {
$oFolder = new Folder($sFullName,
$oResponse->ResponseList[3], $oResponse->ResponseList[2]);
$aReturn[$sFullName] = $oFolder;
} else {
$oFolder = $aReturn[$sFullName];
$oFolder->setDelimiter($oResponse->ResponseList[3]);
$oFolder->setFlags($oResponse->ResponseList[2]);
}
if ($oFolder->IsInbox()) {
$bInbox = true;
}
if (!$sDelimiter) {
$sDelimiter = $oFolder->Delimiter();
}
if (isset($aMetadata[$oResponse->ResponseList[4]])) {
$oFolder->SetAllMetadata($aMetadata[$oResponse->ResponseList[4]]);
}
$aReturn[$sFullName]->setStatusFromResponse($oResponse);
}
else if ($sCmd === $oResponse->StatusOrIndex && 5 === \count($oResponse->ResponseList)) {
try
{
$sFullName = $this->toUTF8($oResponse->ResponseList[4]);
/**
* $oResponse->ResponseList[0] = *
* $oResponse->ResponseList[1] = LIST (all) | LSUB (subscribed)
* $oResponse->ResponseList[2] = Flags
* $oResponse->ResponseList[3] = Delimiter
* $oResponse->ResponseList[4] = FullName
*/
if (isset($aReturn[$sFullName])) {
$oFolder = $aReturn[$sFullName];
$oFolder->setDelimiter($oResponse->ResponseList[3]);
$oFolder->setFlags($oResponse->ResponseList[2]);
} else {
$oFolder = new Folder($sFullName, $oResponse->ResponseList[3], $oResponse->ResponseList[2]);
$aReturn[$sFullName] = $oFolder;
}
catch (\InvalidArgumentException $oException)
{
$this->writeLogException($oException, \LOG_WARNING, false);
}
catch (\Throwable $oException)
{
$this->writeLogException($oException, \LOG_WARNING, false);
}
}
}
if (!$bInbox && !$sParentFolderName && !isset($aReturn['INBOX'])) {
$aReturn['INBOX'] = new Folder('INBOX', $sDelimiter);
if ($oFolder->IsInbox()) {
$bInbox = true;
}
if (!$sDelimiter) {
$sDelimiter = $oFolder->Delimiter();
}
if (isset($aMetadata[$oResponse->ResponseList[4]])) {
$oFolder->SetAllMetadata($aMetadata[$oResponse->ResponseList[4]]);
}
$aReturn[$sFullName] = $oFolder;
}
catch (\Throwable $oException)
{
$this->writeLogException($oException, \LOG_WARNING, false);
}
}
}
@ -554,12 +564,16 @@ trait Folders
$oFolder->SetAllMetadata(
$this->getMetadata($oFolder->FullName(), ['/shared', '/private'], ['DEPTH'=>'infinity'])
);
} catch (\Throwable $e) {
} catch (\Throwable $oException) {
// Ignore error
}
}
}
if (!$bInbox && !$sParentFolderName && !isset($aReturn['INBOX'])) {
$aReturn['INBOX'] = new Folder('INBOX', $sDelimiter);
}
return $aReturn;
}

View file

@ -16,7 +16,9 @@ use MailSo\Imap\FetchResponse;
use MailSo\Imap\Enumerations\FetchType;
use MailSo\Imap\ResponseCollection;
use MailSo\Imap\SequenceSet;
use MailSo\Imap\Enumerations\MessageFlag;
use MailSo\Imap\Enumerations\ResponseType;
use MailSo\Imap\Enumerations\StoreAction;
/**
* @category MailSo
@ -32,8 +34,7 @@ trait Messages
*/
public function Fetch(array $aInputFetchItems, string $sIndexRange, bool $bIndexIsUid) : array
{
if (!\strlen(\trim($sIndexRange)))
{
if (!\strlen(\trim($sIndexRange))) {
$this->writeLogException(new \InvalidArgumentException, \LOG_ERR);
}
@ -44,8 +45,7 @@ trait Messages
FetchType::UID,
FetchType::RFC822_SIZE
);
foreach ($aInputFetchItems as $mFetchKey)
{
foreach ($aInputFetchItems as $mFetchKey) {
switch ($mFetchKey)
{
case FetchType::UID:
@ -196,12 +196,14 @@ trait Messages
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function MessageCopy(string $sToFolder, SequenceSet $oRange) : ResponseCollection
public function MessageCopy(string $sFromFolder, string $sToFolder, SequenceSet $oRange) : ResponseCollection
{
if (!\count($oRange)) {
if (!$sFromFolder || !$sToFolder || !\count($oRange)) {
$this->writeLogException(new \InvalidArgumentException, \LOG_ERR);
}
$this->FolderSelect($sFromFolder);
return $this->SendRequestGetResponse(
$oRange->UID ? 'UID COPY' : 'COPY',
array((string) $oRange, $this->EscapeFolderName($sToFolder))
@ -214,20 +216,48 @@ trait Messages
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function MessageMove(string $sToFolder, SequenceSet $oRange) : ResponseCollection
public function MessageMove(string $sFromFolder, string $sToFolder, SequenceSet $oRange) : ResponseCollection
{
if (!\count($oRange)) {
if (!$sFromFolder || !$sToFolder || !\count($oRange)) {
$this->writeLogException(new \InvalidArgumentException, \LOG_ERR);
}
if (!$this->hasCapability('MOVE')) {
$this->writeLogException(new \MailSo\RuntimeException('Move is not supported'), \LOG_ERR);
if ($this->hasCapability('MOVE')) {
$this->FolderSelect($sFromFolder);
return $this->SendRequestGetResponse(
$oRange->UID ? 'UID MOVE' : 'MOVE',
array((string) $oRange, $this->EscapeFolderName($sToFolder))
);
}
return $this->SendRequestGetResponse(
$oRange->UID ? 'UID MOVE' : 'MOVE',
array((string) $oRange, $this->EscapeFolderName($sToFolder))
$this->MessageCopy($sFromFolder, $sToFolder, $oRange);
$this->MessageDelete($sFromFolder, $oRange, true);
}
/**
* @throws \InvalidArgumentException
* @throws \MailSo\RuntimeException
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function MessageDelete(string $sFolder, SequenceSet $oRange, bool $bExpungeAll = false) : void
{
if (!$sFolder || !\count($oRange)) {
$this->writeLogException(new \InvalidArgumentException, \LOG_ERR);
}
$this->FolderSelect($sFolder);
$this->MessageStoreFlag($oRange,
array(MessageFlag::DELETED),
StoreAction::ADD_FLAGS_SILENT
);
if ($bExpungeAll && $this->Settings->expunge_all_on_delete) {
$this->FolderExpunge();
} else {
$this->FolderExpunge($oRange);
}
}
/**
@ -250,8 +280,8 @@ trait Messages
if ($iUid) {
$oRange = new SequenceSet([$iUid]);
$this->MessageStoreFlag($oRange,
array(\MailSo\Imap\Enumerations\MessageFlag::DELETED),
\MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT
array(MessageFlag::DELETED),
StoreAction::ADD_FLAGS_SILENT
);
$this->FolderExpunge($oRange);
}

View file

@ -126,4 +126,8 @@ trait Metadata
}
}
public function FolderRemoveMetadata($sFolderName, array $aEntries) : void
{
$this->FolderSetMetadata($sFolderName, \array_fill_keys(\array_keys($aEntries), null));
}
}

View file

@ -172,7 +172,7 @@ class Folder implements \JsonSerializable
'totalEmails' => (int) $this->MESSAGES,
'unreadEmails' => (int) $this->UNSEEN,
'UidNext' => (int) $this->UIDNEXT,
// 'Hash' => $this->Hash($this->MailClient()->GenerateImapClientHash())
// 'Hash' => $this->Hash($this->ImapClient()->Hash())
);
}
*/

View file

@ -53,6 +53,15 @@ class ImapClient extends \MailSo\Net\NetClient
private bool $UTF8 = false;
public function Hash() : string
{
return \md5('ImapClientHash/'.
$this->GetLogginedUser() . '@' .
$this->GetConnectedHost() . ':' .
$this->GetConnectedPort()
);
}
public function GetLogginedUser() : string
{
return $this->sLogginedUser;
@ -379,6 +388,12 @@ class ImapClient extends \MailSo\Net\NetClient
}
}
public function GetPersonalNamespace() : string
{
$oNamespace = $this->GetNamespace();
return $oNamespace ? $oNamespace->GetPersonalNamespace() : '';
}
/**
* RFC 7889
* APPENDLIMIT=<number> indicates that the IMAP server has the same upload limit for all mailboxes.

View file

@ -11,30 +11,25 @@
namespace MailSo\Mail;
use MailSo\Imap\BodyStructure;
/**
* @category MailSo
* @package Mail
*/
class Attachment implements \JsonSerializable
{
/**
* @var string
*/
private $sFolder;
private string $sFolder;
/**
* @var int
*/
private $iUid;
private int $iUid;
/**
* @var \MailSo\Imap\BodyStructure
*/
private $oBodyStructure;
private ?BodyStructure $oBodyStructure;
function __construct()
function __construct(string $sFolder, int $iUid, BodyStructure $oBodyStructure)
{
$this->Clear();
$this->sFolder = $sFolder;
$this->iUid = $iUid;
$this->oBodyStructure = $oBodyStructure;
}
public function Clear() : self
@ -56,11 +51,6 @@ class Attachment implements \JsonSerializable
return $this->iUid;
}
public function MimeIndex() : string
{
return $this->oBodyStructure ? $this->oBodyStructure->PartID() : '';
}
public function FileName(bool $bCalculateOnEmpty = false) : string
{
if (!$this->oBodyStructure) {
@ -72,9 +62,9 @@ class Attachment implements \JsonSerializable
return $sFileName;
}
$sIdx = '-' . $this->MimeIndex();
$sIdx = '-' . $this->oBodyStructure->PartID();
$sMimeType = \strtolower(\trim($this->MimeType()));
$sMimeType = \strtolower(\trim($this->oBodyStructure->ContentType()));
if ('message/rfc822' === $sMimeType) {
return "message{$sIdx}.eml";
}
@ -95,72 +85,9 @@ class Attachment implements \JsonSerializable
return ($this->oBodyStructure->IsInline() ? 'inline' : 'part' ) . $sIdx;
}
public function MimeType() : string
public function __call(string $name, array $arguments) //: mixed
{
return $this->oBodyStructure ? $this->oBodyStructure->ContentType() : '';
}
public function EncodedSize() : int
{
return $this->oBodyStructure ? $this->oBodyStructure->Size() : 0;
}
public function EstimatedSize() : int
{
return $this->oBodyStructure ? $this->oBodyStructure->EstimatedSize() : 0;
}
public function Cid() : string
{
return $this->oBodyStructure ? $this->oBodyStructure->ContentID() : '';
}
public function ContentLocation() : string
{
return $this->oBodyStructure ? $this->oBodyStructure->ContentLocation() : '';
}
public function IsInline() : bool
{
return $this->oBodyStructure ? $this->oBodyStructure->IsInline() : false;
}
public function IsImage() : bool
{
return $this->oBodyStructure ? $this->oBodyStructure->IsImage() : false;
}
public function IsArchive() : bool
{
return $this->oBodyStructure ? $this->oBodyStructure->IsArchive() : false;
}
public function IsPdf() : bool
{
return $this->oBodyStructure ? $this->oBodyStructure->IsPdf() : false;
}
public function IsDoc() : bool
{
return $this->oBodyStructure ? $this->oBodyStructure->IsDoc() : false;
}
public function IsPgpSignature() : bool
{
return $this->oBodyStructure ? $this->oBodyStructure->IsPgpSignature() : false;
}
public static function NewBodyStructureInstance(string $sFolder, int $iUid, \MailSo\Imap\BodyStructure $oBodyStructure) : self
{
return (new self)->InitByBodyStructure($sFolder, $iUid, $oBodyStructure);
}
public function InitByBodyStructure(string $sFolder, int $iUid, \MailSo\Imap\BodyStructure $oBodyStructure) : self
{
$this->sFolder = $sFolder;
$this->iUid = $iUid;
$this->oBodyStructure = $oBodyStructure;
return $this;
return $this->oBodyStructure->{$name}(...$arguments);
}
#[\ReturnTypeWillChange]
@ -168,15 +95,15 @@ class Attachment implements \JsonSerializable
{
return array(
'@Object' => 'Object/Attachment',
'Folder' => $this->Folder(),
'Uid' => (string) $this->Uid(),
'MimeIndex' => (string) $this->MimeIndex(),
'MimeType' => $this->MimeType(),
'FileName' => \MailSo\Base\Utils::SecureFileName($this->FileName(true)),
'EstimatedSize' => $this->EstimatedSize(),
'Cid' => $this->Cid(),
'ContentLocation' => $this->ContentLocation(),
'IsInline' => $this->IsInline()
'Folder' => $this->sFolder,
'Uid' => (string) $this->iUid,
'MimeIndex' => (string) $this->oBodyStructure->PartID(),
'MimeType' => $this->oBodyStructure->ContentType(),
'FileName' => \MailSo\Base\Utils::SecureFileName($this->oBodyStructure->FileName(true)),
'EstimatedSize' => $this->oBodyStructure->EstimatedSize(),
'Cid' => $this->oBodyStructure->ContentID(),
'ContentLocation' => $this->oBodyStructure->ContentLocation(),
'IsInline' => $this->oBodyStructure->IsInline()
);
}
}

View file

@ -121,8 +121,7 @@ class MailClient
*/
public function Message(string $sFolderName, int $iIndex, bool $bIndexIsUid = true, ?\MailSo\Cache\CacheClient $oCacher = null) : ?Message
{
if (!\MailSo\Base\Validator::RangeInt($iIndex, 1))
{
if (1 > $iIndex) {
throw new \InvalidArgumentException;
}
@ -143,13 +142,10 @@ class MailClient
$iBodyTextLimit = $this->oImapClient->Settings->body_text_limit;
$aFetchResponse = $this->oImapClient->Fetch(array(FetchType::BODYSTRUCTURE), $iIndex, $bIndexIsUid);
if (\count($aFetchResponse) && isset($aFetchResponse[0]))
{
if (\count($aFetchResponse) && isset($aFetchResponse[0])) {
$oBodyStructure = $aFetchResponse[0]->GetFetchBodyStructure();
if ($oBodyStructure)
{
foreach ($oBodyStructure->GetHtmlAndPlainParts() as $oPart)
{
if ($oBodyStructure) {
foreach ($oBodyStructure->GetHtmlAndPlainParts() as $oPart) {
$sLine = FetchType::BODY_PEEK.'['.$oPart->PartID().']';
if (0 < $iBodyTextLimit && $iBodyTextLimit < $oPart->Size()) {
$sLine .= "<0.{$iBodyTextLimit}>";
@ -171,15 +167,13 @@ class MailClient
}
}
if (!$oBodyStructure)
{
if (!$oBodyStructure) {
$aFetchItems[] = FetchType::BODYSTRUCTURE;
}
$aFetchResponse = $this->oImapClient->Fetch($aFetchItems, $iIndex, $bIndexIsUid);
if (\count($aFetchResponse))
{
$oMessage = Message::NewFetchResponseInstance($sFolderName, $aFetchResponse[0], $oBodyStructure);
if (\count($aFetchResponse)) {
$oMessage = Message::fromFetchResponse($sFolderName, $aFetchResponse[0], $oBodyStructure);
}
return $oMessage;
@ -197,8 +191,7 @@ class MailClient
*/
public function MessageMimeStream($mCallback, string $sFolderName, int $iIndex, string $sMimeIndex) : bool
{
if (!\is_callable($mCallback))
{
if (!\is_callable($mCallback)) {
throw new \InvalidArgumentException;
}
@ -216,20 +209,17 @@ class MailClient
: FetchType::BODY_HEADER_PEEK),
$iIndex, true);
if (\count($aFetchResponse))
{
if (\count($aFetchResponse)) {
$sMime = $aFetchResponse[0]->GetFetchValue(
\strlen($sMimeIndex)
? FetchType::BODY.'['.$sMimeIndex.'.MIME]'
: FetchType::BODY_HEADER
);
if (\strlen($sMime))
{
if (\strlen($sMime)) {
$oHeaders = new \MailSo\Mime\HeaderCollection($sMime);
if (\strlen($sMimeIndex))
{
if (\strlen($sMimeIndex)) {
$sFileName = $oHeaders->ParameterValue(MimeHeader::CONTENT_DISPOSITION, MimeParameter::FILENAME);
if (!\strlen($sFileName)) {
$sFileName = $oHeaders->ParameterValue(MimeHeader::CONTENT_TYPE, MimeParameter::NAME);
@ -247,9 +237,7 @@ class MailClient
}
$sContentType = $oHeaders->ValueByName(MimeHeader::CONTENT_TYPE);
}
else
{
} else {
$sFileName = ($oHeaders->ValueByName(MimeHeader::SUBJECT) ?: $iIndex) . '.eml';
$sContentType = 'message/rfc822';
@ -264,8 +252,7 @@ class MailClient
$sPeek.'['.$sMimeIndex.']',
function ($sParent, $sLiteralAtomUpperCase, $rImapLiteralStream) use ($mCallback, $sMimeIndex, $sMailEncoding, $sContentType, $sFileName)
{
if (\strlen($sLiteralAtomUpperCase) && \is_resource($rImapLiteralStream) && 'FETCH' === $sParent)
{
if (\strlen($sLiteralAtomUpperCase) && \is_resource($rImapLiteralStream) && 'FETCH' === $sParent) {
$mCallback($sMailEncoding
? \MailSo\Base\StreamWrappers\Binary::CreateStream($rImapLiteralStream, $sMailEncoding)
: $rImapLiteralStream,
@ -277,93 +264,6 @@ class MailClient
return ($aFetchResponse && 1 === \count($aFetchResponse));
}
/**
* @throws \InvalidArgumentException
* @throws \MailSo\RuntimeException
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function MessageDelete(string $sFolder, SequenceSet $oRange, bool $bExpungeAll = false) : self
{
if (!\strlen($sFolder) || !\count($oRange))
{
throw new \InvalidArgumentException;
}
$this->oImapClient->FolderSelect($sFolder);
$this->oImapClient->MessageStoreFlag($oRange,
array(MessageFlag::DELETED),
StoreAction::ADD_FLAGS_SILENT
);
if ($bExpungeAll && $this->oImapClient->Settings->expunge_all_on_delete) {
$this->oImapClient->FolderExpunge();
} else {
$this->oImapClient->FolderExpunge($oRange);
}
return $this;
}
/**
* @throws \InvalidArgumentException
* @throws \MailSo\RuntimeException
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function MessageMove(string $sFromFolder, string $sToFolder, SequenceSet $oRange) : self
{
if (!$sFromFolder || !$sToFolder || !\count($oRange)) {
throw new \InvalidArgumentException;
}
$this->oImapClient->FolderSelect($sFromFolder);
if ($this->oImapClient->hasCapability('MOVE')) {
$this->oImapClient->MessageMove($sToFolder, $oRange);
} else {
$this->oImapClient->MessageCopy($sToFolder, $oRange);
$this->MessageDelete($sFromFolder, $oRange, true);
}
return $this;
}
/**
* @throws \InvalidArgumentException
* @throws \MailSo\RuntimeException
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function MessageCopy(string $sFromFolder, string $sToFolder, SequenceSet $oRange) : self
{
if (!$sFromFolder || !$sToFolder || !\count($oRange))
{
throw new \InvalidArgumentException;
}
$this->oImapClient->FolderSelect($sFromFolder);
$this->oImapClient->MessageCopy($sToFolder, $oRange);
return $this;
}
/**
* @throws \MailSo\RuntimeException
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function FolderUnselect() : self
{
if ($this->oImapClient->IsSelected())
{
$this->oImapClient->FolderUnselect();
}
return $this;
}
/**
* @param resource $rMessageStream
*/
@ -382,8 +282,7 @@ class MailClient
public function MessageAppendFile(string $sMessageFileName, string $sFolderToSave, array $aAppendFlags = null, int &$iUid = null) : self
{
if (!\is_file($sMessageFileName) || !\is_readable($sMessageFileName))
{
if (!\is_file($sMessageFileName) || !\is_readable($sMessageFileName)) {
throw new \InvalidArgumentException;
}
@ -392,23 +291,13 @@ class MailClient
$this->MessageAppendStream($rMessageStream, $iMessageStreamSize, $sFolderToSave, $aAppendFlags, $iUid);
if (\is_resource($rMessageStream))
{
fclose($rMessageStream);
if (\is_resource($rMessageStream)) {
\fclose($rMessageStream);
}
return $this;
}
public function GenerateImapClientHash() : string
{
return \md5('ImapClientHash/'.
$this->oImapClient->GetLogginedUser() . '@' .
$this->oImapClient->GetConnectedHost() . ':' .
$this->oImapClient->GetConnectedPort()
);
}
/**
* Returns list of new messages since $iPrevUidNext
* Currently only for INBOX
@ -496,7 +385,7 @@ class MailClient
'MailboxId' => $oInfo->MAILBOXID ?: '',
// 'Flags' => $oInfo->Flags,
// 'PermanentFlags' => $oInfo->PermanentFlags,
'Hash' => $oInfo->getHash($this->GenerateImapClientHash()),
'Hash' => $oInfo->getHash($this->oImapClient->Hash()),
'MessagesFlags' => $aFlags,
'NewMessages' => $this->getFolderNextMessageInformation(
$sFolderName,
@ -514,7 +403,7 @@ class MailClient
*/
public function FolderHash(string $sFolderName) : string
{
return $this->oImapClient->FolderStatus($sFolderName)->getHash($this->GenerateImapClientHash());
return $this->oImapClient->FolderStatus($sFolderName)->getHash($this->oImapClient->Hash());
}
/**
@ -572,14 +461,12 @@ class MailClient
unset($oException);
}
if ($oCacher && $oCacher->IsInited() && !empty($sSerializedHashKey))
{
if ($oCacher && $oCacher->IsInited() && !empty($sSerializedHashKey)) {
$oCacher->Set($sSerializedHashKey, \json_encode(array(
'ThreadsUids' => $aResult
)));
if ($this->oLogger)
{
if ($this->oLogger) {
$this->oLogger->Write('Save Serialized Thread UIDS to cache ("'.$sFolderName.'" / '.$sSearchHash.') [count:'.\count($aResult).']');
}
}
@ -594,8 +481,7 @@ class MailClient
*/
protected function MessageListByRequestIndexOrUids(MessageCollection $oMessageCollection, SequenceSet $oRange) : void
{
if (\count($oRange))
{
if (\count($oRange)) {
$aFetchResponse = $this->oImapClient->Fetch(array(
FetchType::UID,
FetchType::RFC822_SIZE,
@ -605,14 +491,13 @@ class MailClient
$this->getEnvelopeOrHeadersRequestString()
), (string) $oRange, $oRange->UID);
if (\count($aFetchResponse))
{
if (\count($aFetchResponse)) {
$aCollection = \array_fill_keys($oRange->getArrayCopy(), null);
foreach ($aFetchResponse as /* @var $oFetchResponseItem \MailSo\Imap\FetchResponse */ $oFetchResponseItem) {
$id = $oRange->UID
? $oFetchResponseItem->GetFetchValue(FetchType::UID)
: $oFetchResponseItem->oImapResponse->ResponseList[1];
$aCollection[$id] = Message::NewFetchResponseInstance($oMessageCollection->FolderName, $oFetchResponseItem);
$aCollection[$id] = Message::fromFetchResponse($oMessageCollection->FolderName, $oFetchResponseItem);
}
$oMessageCollection->exchangeArray(\array_values(\array_filter($aCollection)));
}
@ -686,7 +571,7 @@ class MailClient
if ($bUseCacheAfterSearch) {
$sSerializedHash = 'GetUids/'.
($bUseSortIfSupported ? 'S' . $sSort : 'N').'/'.
$this->GenerateImapClientHash().'/'.
$this->oImapClient->Hash().'/'.
$sFolderName.'/'.$sSearchCriterias;
$sSerializedLog = '"'.$sFolderName.'" / '.$sSearchCriterias.'';
@ -742,9 +627,7 @@ class MailClient
*/
public function MessageList(MessageListParams $oParams) : MessageCollection
{
if (!\MailSo\Base\Validator::RangeInt($oParams->iOffset, 0) ||
!\MailSo\Base\Validator::RangeInt($oParams->iLimit, 0, 999))
{
if (0 > $oParams->iOffset || 0 > $oParams->iLimit || 999 < $oParams->iLimit) {
throw new \InvalidArgumentException;
}
@ -773,7 +656,7 @@ class MailClient
$oParams->oCacher = null;
}
$oMessageCollection->FolderHash = $oInfo->getHash($this->GenerateImapClientHash());
$oMessageCollection->FolderHash = $oInfo->getHash($this->oImapClient->Hash());
if (!$oParams->iThreadUid) {
$oMessageCollection->NewMessages = $this->getFolderNextMessageInformation(
@ -893,8 +776,7 @@ class MailClient
public function FindMessageUidByMessageId(string $sFolderName, string $sMessageId) : ?int
{
if (!\strlen($sMessageId))
{
if (!\strlen($sMessageId)) {
throw new \InvalidArgumentException;
}
@ -927,7 +809,7 @@ class MailClient
}
}
// $this->oImapClient->Settings->disable_list_status
// $this->oImapClient->Settings->disable_list_status
$aFolders = $this->oImapClient->FolderStatusList($sParent, $sListPattern);
if (!$aFolders) {
return null;
@ -976,12 +858,12 @@ class MailClient
}
}
/* // Allow non existent parent folders
if (\strlen($sDelimiter) && false !== \strpos($sFolderNameInUtf8, $sDelimiter)) {
// TODO: Translate
throw new \MailSo\RuntimeException(
'New folder name contains delimiter.');
throw new \MailSo\RuntimeException('New folder name contains delimiter.');
}
*/
$sFullNameToCreate = $sFolderParentFullName.$sFolderNameInUtf8;
$this->oImapClient->FolderCreate($sFullNameToCreate, $bSubscribeOnCreation);
@ -1039,92 +921,33 @@ class MailClient
*/
protected function folderModify(string $sPrevFolderFullName, string $sNewFolderFullName, bool $bSubscribe) : self
{
if (!\strlen($sPrevFolderFullName) || !\strlen($sNewFolderFullName))
{
if (!\strlen($sPrevFolderFullName) || !\strlen($sNewFolderFullName)) {
throw new \InvalidArgumentException;
}
$aSubscribeFolders = array();
if ($bSubscribe)
{
if ($bSubscribe) {
$aSubscribeFolders = $this->oImapClient->FolderSubscribeList($sPrevFolderFullName, '*');
foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder)
{
foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) {
$this->oImapClient->FolderUnsubscribe($oFolder->FullName());
}
}
$this->oImapClient->FolderRename($sPrevFolderFullName, $sNewFolderFullName);
foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder)
{
$sFolderFullNameForResubscrine = $oFolder->FullName();
if (0 === \strpos($sFolderFullNameForResubscrine, $sPrevFolderFullName))
{
$sNewFolderFullNameForResubscrine = $sNewFolderFullName.
\substr($sFolderFullNameForResubscrine, \strlen($sPrevFolderFullName));
foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) {
$sFolderFullNameForResubscribe = $oFolder->FullName();
if (\str_starts_with($sFolderFullNameForResubscribe, $sPrevFolderFullName)) {
$sNewFolderFullNameForResubscribe = $sNewFolderFullName.
\substr($sFolderFullNameForResubscribe, \strlen($sPrevFolderFullName));
$this->oImapClient->FolderSubscribe($sNewFolderFullNameForResubscrine);
$this->oImapClient->FolderSubscribe($sNewFolderFullNameForResubscribe);
}
}
return $this;
}
/**
* @throws \InvalidArgumentException
* @throws \MailSo\RuntimeException
*/
public function FolderDelete(string $sFolderFullName) : self
{
if (!\strlen($sFolderFullName) || 'INBOX' === $sFolderFullName) {
throw new \InvalidArgumentException;
}
if ($this->oImapClient->hasCapability('IMAP4rev2')) {
$oInfo = $this->oImapClient->FolderExamine($sFolderFullName);
} else {
$oInfo = $this->oImapClient->FolderStatus($sFolderFullName);
}
if ($oInfo->MESSAGES) {
throw new Exceptions\NonEmptyFolder;
}
$this->oImapClient->FolderUnsubscribe($sFolderFullName);
$this->oImapClient->FolderUnselect();
$this->oImapClient->FolderDelete($sFolderFullName);
return $this;
}
/**
* @throws \InvalidArgumentException
*/
public function FolderClear(string $sFolderFullName) : self
{
if (0 < $this->oImapClient->FolderSelect($sFolderFullName)->MESSAGES) {
$this->oImapClient->MessageStoreFlag(new SequenceSet('1:*', false),
array(MessageFlag::DELETED),
StoreAction::ADD_FLAGS_SILENT
);
$this->oImapClient->FolderExpunge();
}
return $this;
}
/**
* @throws \InvalidArgumentException
*/
public function FolderSubscribe(string $sFolderFullName, bool $bSubscribe) : self
{
if (!\strlen($sFolderFullName)) {
throw new \InvalidArgumentException;
}
$this->oImapClient->{$bSubscribe ? 'FolderSubscribe' : 'FolderUnsubscribe'}($sFolderFullName);
return $this;
}
/**
* @throws \InvalidArgumentException
*/
@ -1134,23 +957,8 @@ class MailClient
$this->oImapClient->SetLogger($oLogger);
}
public function GetPersonalNamespace() : string
{
$oNamespace = $this->oImapClient->GetNamespace();
return $oNamespace ? $oNamespace->GetPersonalNamespace() : '';
}
public function __call(string $name, array $arguments) /*: mixed*/
{
return $this->oImapClient->{$name}(...$arguments);
}
/**
* RFC 5464
*/
public function FolderDeleteMetadata($sFolderName, array $aEntries) : void
{
$this->oImapClient->FolderSetMetadata($sFolderName, \array_fill_keys(\array_keys($aEntries), null));
}
}

View file

@ -281,7 +281,7 @@ class Message implements \JsonSerializable
$this->aThreads = $aThreads;
}
public static function NewFetchResponseInstance(string $sFolder, \MailSo\Imap\FetchResponse $oFetchResponse, ?\MailSo\Imap\BodyStructure $oBodyStructure = null) : self
public static function fromFetchResponse(string $sFolder, \MailSo\Imap\FetchResponse $oFetchResponse, ?\MailSo\Imap\BodyStructure $oBodyStructure = null) : self
{
$oMessage = new self;
@ -625,7 +625,7 @@ class Message implements \JsonSerializable
{
// if ('application/pgp-keys' === $oAttachmentItem->ContentType()) import ???
$oMessage->oAttachments->append(
Attachment::NewBodyStructureInstance($oMessage->sFolder, $oMessage->iUid, $oAttachmentItem)
new Attachment($oMessage->sFolder, $oMessage->iUid, $oAttachmentItem)
);
}
}

View file

@ -38,7 +38,8 @@ class MessageListParams
if ('i' === $k[0]) {
$this->$k = \max(0, (int) $v);
}
// \MailSo\Base\Validator::RangeInt($oParams->iOffset, 0)
// \MailSo\Base\Validator::RangeInt($oParams->iLimit, 0, 999)
// 0 > $oParams->iOffset
// 0 > $oParams->iLimit
// 999 < $oParams->iLimit
}
}

View file

@ -87,7 +87,7 @@ abstract class NetClient
public function Connect(ConnectSettings $oSettings) : void
{
$oSettings->host = \trim($oSettings->host);
if (!\strlen($oSettings->host) || !\MailSo\Base\Validator::RangeInt($oSettings->port, 0, 65535)) {
if (!\strlen($oSettings->host) || 0 > $oSettings->port || 65535 < $oSettings->port) {
$this->writeLogException(new \MailSo\Base\Exceptions\InvalidArgumentException, \LOG_ERR);
}

View file

@ -392,8 +392,7 @@ class SieveClient extends \MailSo\Net\NetClient
private function parseResponse() : array
{
$aResult = array();
do
{
while (true) {
$sResponseBuffer = $this->getNextBuffer();
if (null === $sResponseBuffer) {
break;
@ -418,7 +417,6 @@ class SieveClient extends \MailSo\Net\NetClient
break;
}
}
while (true);
if (!$aResult || 'OK' !== \substr($aResult[\array_key_last($aResult)], 0, 2)) {
$this->writeLogException(new \MailSo\Sieve\Exceptions\NegativeResponseException($aResult), \LOG_WARNING);

View file

@ -125,7 +125,7 @@ trait Folders
try
{
$this->MailClient()->FolderSubscribe($sFolderFullName, $bSubscribe);
$this->MailClient()->{$bSubscribe ? 'FolderSubscribe' : 'FolderUnsubscribe'}($sFolderFullName);
}
catch (\Throwable $oException)
{

View file

@ -250,7 +250,7 @@ trait Response
{
$aResult = $mResponse->jsonSerialize();
$sHash = $mResponse->Hash($this->MailClient()->GenerateImapClientHash());
$sHash = $mResponse->Hash($this->MailClient()->ImapClient()->Hash());
if ($sHash) {
$aResult['Hash'] = $sHash;
}