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

View file

@ -16,7 +16,9 @@ use MailSo\Imap\FetchResponse;
use MailSo\Imap\Enumerations\FetchType; use MailSo\Imap\Enumerations\FetchType;
use MailSo\Imap\ResponseCollection; use MailSo\Imap\ResponseCollection;
use MailSo\Imap\SequenceSet; use MailSo\Imap\SequenceSet;
use MailSo\Imap\Enumerations\MessageFlag;
use MailSo\Imap\Enumerations\ResponseType; use MailSo\Imap\Enumerations\ResponseType;
use MailSo\Imap\Enumerations\StoreAction;
/** /**
* @category MailSo * @category MailSo
@ -32,8 +34,7 @@ trait Messages
*/ */
public function Fetch(array $aInputFetchItems, string $sIndexRange, bool $bIndexIsUid) : array public function Fetch(array $aInputFetchItems, string $sIndexRange, bool $bIndexIsUid) : array
{ {
if (!\strlen(\trim($sIndexRange))) if (!\strlen(\trim($sIndexRange))) {
{
$this->writeLogException(new \InvalidArgumentException, \LOG_ERR); $this->writeLogException(new \InvalidArgumentException, \LOG_ERR);
} }
@ -44,8 +45,7 @@ trait Messages
FetchType::UID, FetchType::UID,
FetchType::RFC822_SIZE FetchType::RFC822_SIZE
); );
foreach ($aInputFetchItems as $mFetchKey) foreach ($aInputFetchItems as $mFetchKey) {
{
switch ($mFetchKey) switch ($mFetchKey)
{ {
case FetchType::UID: case FetchType::UID:
@ -196,12 +196,14 @@ trait Messages
* @throws \MailSo\Net\Exceptions\* * @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\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->writeLogException(new \InvalidArgumentException, \LOG_ERR);
} }
$this->FolderSelect($sFromFolder);
return $this->SendRequestGetResponse( return $this->SendRequestGetResponse(
$oRange->UID ? 'UID COPY' : 'COPY', $oRange->UID ? 'UID COPY' : 'COPY',
array((string) $oRange, $this->EscapeFolderName($sToFolder)) array((string) $oRange, $this->EscapeFolderName($sToFolder))
@ -214,20 +216,48 @@ trait Messages
* @throws \MailSo\Net\Exceptions\* * @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\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); $this->writeLogException(new \InvalidArgumentException, \LOG_ERR);
} }
if (!$this->hasCapability('MOVE')) { if ($this->hasCapability('MOVE')) {
$this->writeLogException(new \MailSo\RuntimeException('Move is not supported'), \LOG_ERR); $this->FolderSelect($sFromFolder);
return $this->SendRequestGetResponse(
$oRange->UID ? 'UID MOVE' : 'MOVE',
array((string) $oRange, $this->EscapeFolderName($sToFolder))
);
} }
return $this->SendRequestGetResponse( $this->MessageCopy($sFromFolder, $sToFolder, $oRange);
$oRange->UID ? 'UID MOVE' : 'MOVE', $this->MessageDelete($sFromFolder, $oRange, true);
array((string) $oRange, $this->EscapeFolderName($sToFolder)) }
/**
* @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) { if ($iUid) {
$oRange = new SequenceSet([$iUid]); $oRange = new SequenceSet([$iUid]);
$this->MessageStoreFlag($oRange, $this->MessageStoreFlag($oRange,
array(\MailSo\Imap\Enumerations\MessageFlag::DELETED), array(MessageFlag::DELETED),
\MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT StoreAction::ADD_FLAGS_SILENT
); );
$this->FolderExpunge($oRange); $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, 'totalEmails' => (int) $this->MESSAGES,
'unreadEmails' => (int) $this->UNSEEN, 'unreadEmails' => (int) $this->UNSEEN,
'UidNext' => (int) $this->UIDNEXT, '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; private bool $UTF8 = false;
public function Hash() : string
{
return \md5('ImapClientHash/'.
$this->GetLogginedUser() . '@' .
$this->GetConnectedHost() . ':' .
$this->GetConnectedPort()
);
}
public function GetLogginedUser() : string public function GetLogginedUser() : string
{ {
return $this->sLogginedUser; 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 * RFC 7889
* APPENDLIMIT=<number> indicates that the IMAP server has the same upload limit for all mailboxes. * APPENDLIMIT=<number> indicates that the IMAP server has the same upload limit for all mailboxes.

View file

@ -11,30 +11,25 @@
namespace MailSo\Mail; namespace MailSo\Mail;
use MailSo\Imap\BodyStructure;
/** /**
* @category MailSo * @category MailSo
* @package Mail * @package Mail
*/ */
class Attachment implements \JsonSerializable class Attachment implements \JsonSerializable
{ {
/** private string $sFolder;
* @var string
*/
private $sFolder;
/** private int $iUid;
* @var int
*/
private $iUid;
/** private ?BodyStructure $oBodyStructure;
* @var \MailSo\Imap\BodyStructure
*/
private $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 public function Clear() : self
@ -56,11 +51,6 @@ class Attachment implements \JsonSerializable
return $this->iUid; return $this->iUid;
} }
public function MimeIndex() : string
{
return $this->oBodyStructure ? $this->oBodyStructure->PartID() : '';
}
public function FileName(bool $bCalculateOnEmpty = false) : string public function FileName(bool $bCalculateOnEmpty = false) : string
{ {
if (!$this->oBodyStructure) { if (!$this->oBodyStructure) {
@ -72,9 +62,9 @@ class Attachment implements \JsonSerializable
return $sFileName; return $sFileName;
} }
$sIdx = '-' . $this->MimeIndex(); $sIdx = '-' . $this->oBodyStructure->PartID();
$sMimeType = \strtolower(\trim($this->MimeType())); $sMimeType = \strtolower(\trim($this->oBodyStructure->ContentType()));
if ('message/rfc822' === $sMimeType) { if ('message/rfc822' === $sMimeType) {
return "message{$sIdx}.eml"; return "message{$sIdx}.eml";
} }
@ -95,72 +85,9 @@ class Attachment implements \JsonSerializable
return ($this->oBodyStructure->IsInline() ? 'inline' : 'part' ) . $sIdx; 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() : ''; return $this->oBodyStructure->{$name}(...$arguments);
}
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;
} }
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
@ -168,15 +95,15 @@ class Attachment implements \JsonSerializable
{ {
return array( return array(
'@Object' => 'Object/Attachment', '@Object' => 'Object/Attachment',
'Folder' => $this->Folder(), 'Folder' => $this->sFolder,
'Uid' => (string) $this->Uid(), 'Uid' => (string) $this->iUid,
'MimeIndex' => (string) $this->MimeIndex(), 'MimeIndex' => (string) $this->oBodyStructure->PartID(),
'MimeType' => $this->MimeType(), 'MimeType' => $this->oBodyStructure->ContentType(),
'FileName' => \MailSo\Base\Utils::SecureFileName($this->FileName(true)), 'FileName' => \MailSo\Base\Utils::SecureFileName($this->oBodyStructure->FileName(true)),
'EstimatedSize' => $this->EstimatedSize(), 'EstimatedSize' => $this->oBodyStructure->EstimatedSize(),
'Cid' => $this->Cid(), 'Cid' => $this->oBodyStructure->ContentID(),
'ContentLocation' => $this->ContentLocation(), 'ContentLocation' => $this->oBodyStructure->ContentLocation(),
'IsInline' => $this->IsInline() '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 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; throw new \InvalidArgumentException;
} }
@ -143,13 +142,10 @@ class MailClient
$iBodyTextLimit = $this->oImapClient->Settings->body_text_limit; $iBodyTextLimit = $this->oImapClient->Settings->body_text_limit;
$aFetchResponse = $this->oImapClient->Fetch(array(FetchType::BODYSTRUCTURE), $iIndex, $bIndexIsUid); $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(); $oBodyStructure = $aFetchResponse[0]->GetFetchBodyStructure();
if ($oBodyStructure) if ($oBodyStructure) {
{ foreach ($oBodyStructure->GetHtmlAndPlainParts() as $oPart) {
foreach ($oBodyStructure->GetHtmlAndPlainParts() as $oPart)
{
$sLine = FetchType::BODY_PEEK.'['.$oPart->PartID().']'; $sLine = FetchType::BODY_PEEK.'['.$oPart->PartID().']';
if (0 < $iBodyTextLimit && $iBodyTextLimit < $oPart->Size()) { if (0 < $iBodyTextLimit && $iBodyTextLimit < $oPart->Size()) {
$sLine .= "<0.{$iBodyTextLimit}>"; $sLine .= "<0.{$iBodyTextLimit}>";
@ -171,15 +167,13 @@ class MailClient
} }
} }
if (!$oBodyStructure) if (!$oBodyStructure) {
{
$aFetchItems[] = FetchType::BODYSTRUCTURE; $aFetchItems[] = FetchType::BODYSTRUCTURE;
} }
$aFetchResponse = $this->oImapClient->Fetch($aFetchItems, $iIndex, $bIndexIsUid); $aFetchResponse = $this->oImapClient->Fetch($aFetchItems, $iIndex, $bIndexIsUid);
if (\count($aFetchResponse)) if (\count($aFetchResponse)) {
{ $oMessage = Message::fromFetchResponse($sFolderName, $aFetchResponse[0], $oBodyStructure);
$oMessage = Message::NewFetchResponseInstance($sFolderName, $aFetchResponse[0], $oBodyStructure);
} }
return $oMessage; return $oMessage;
@ -197,8 +191,7 @@ class MailClient
*/ */
public function MessageMimeStream($mCallback, string $sFolderName, int $iIndex, string $sMimeIndex) : bool public function MessageMimeStream($mCallback, string $sFolderName, int $iIndex, string $sMimeIndex) : bool
{ {
if (!\is_callable($mCallback)) if (!\is_callable($mCallback)) {
{
throw new \InvalidArgumentException; throw new \InvalidArgumentException;
} }
@ -216,20 +209,17 @@ class MailClient
: FetchType::BODY_HEADER_PEEK), : FetchType::BODY_HEADER_PEEK),
$iIndex, true); $iIndex, true);
if (\count($aFetchResponse)) if (\count($aFetchResponse)) {
{
$sMime = $aFetchResponse[0]->GetFetchValue( $sMime = $aFetchResponse[0]->GetFetchValue(
\strlen($sMimeIndex) \strlen($sMimeIndex)
? FetchType::BODY.'['.$sMimeIndex.'.MIME]' ? FetchType::BODY.'['.$sMimeIndex.'.MIME]'
: FetchType::BODY_HEADER : FetchType::BODY_HEADER
); );
if (\strlen($sMime)) if (\strlen($sMime)) {
{
$oHeaders = new \MailSo\Mime\HeaderCollection($sMime); $oHeaders = new \MailSo\Mime\HeaderCollection($sMime);
if (\strlen($sMimeIndex)) if (\strlen($sMimeIndex)) {
{
$sFileName = $oHeaders->ParameterValue(MimeHeader::CONTENT_DISPOSITION, MimeParameter::FILENAME); $sFileName = $oHeaders->ParameterValue(MimeHeader::CONTENT_DISPOSITION, MimeParameter::FILENAME);
if (!\strlen($sFileName)) { if (!\strlen($sFileName)) {
$sFileName = $oHeaders->ParameterValue(MimeHeader::CONTENT_TYPE, MimeParameter::NAME); $sFileName = $oHeaders->ParameterValue(MimeHeader::CONTENT_TYPE, MimeParameter::NAME);
@ -247,9 +237,7 @@ class MailClient
} }
$sContentType = $oHeaders->ValueByName(MimeHeader::CONTENT_TYPE); $sContentType = $oHeaders->ValueByName(MimeHeader::CONTENT_TYPE);
} } else {
else
{
$sFileName = ($oHeaders->ValueByName(MimeHeader::SUBJECT) ?: $iIndex) . '.eml'; $sFileName = ($oHeaders->ValueByName(MimeHeader::SUBJECT) ?: $iIndex) . '.eml';
$sContentType = 'message/rfc822'; $sContentType = 'message/rfc822';
@ -264,8 +252,7 @@ class MailClient
$sPeek.'['.$sMimeIndex.']', $sPeek.'['.$sMimeIndex.']',
function ($sParent, $sLiteralAtomUpperCase, $rImapLiteralStream) use ($mCallback, $sMimeIndex, $sMailEncoding, $sContentType, $sFileName) 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 $mCallback($sMailEncoding
? \MailSo\Base\StreamWrappers\Binary::CreateStream($rImapLiteralStream, $sMailEncoding) ? \MailSo\Base\StreamWrappers\Binary::CreateStream($rImapLiteralStream, $sMailEncoding)
: $rImapLiteralStream, : $rImapLiteralStream,
@ -277,93 +264,6 @@ class MailClient
return ($aFetchResponse && 1 === \count($aFetchResponse)); 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 * @param resource $rMessageStream
*/ */
@ -382,8 +282,7 @@ class MailClient
public function MessageAppendFile(string $sMessageFileName, string $sFolderToSave, array $aAppendFlags = null, int &$iUid = null) : self 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; throw new \InvalidArgumentException;
} }
@ -392,23 +291,13 @@ class MailClient
$this->MessageAppendStream($rMessageStream, $iMessageStreamSize, $sFolderToSave, $aAppendFlags, $iUid); $this->MessageAppendStream($rMessageStream, $iMessageStreamSize, $sFolderToSave, $aAppendFlags, $iUid);
if (\is_resource($rMessageStream)) if (\is_resource($rMessageStream)) {
{ \fclose($rMessageStream);
fclose($rMessageStream);
} }
return $this; 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 * Returns list of new messages since $iPrevUidNext
* Currently only for INBOX * Currently only for INBOX
@ -496,7 +385,7 @@ class MailClient
'MailboxId' => $oInfo->MAILBOXID ?: '', 'MailboxId' => $oInfo->MAILBOXID ?: '',
// 'Flags' => $oInfo->Flags, // 'Flags' => $oInfo->Flags,
// 'PermanentFlags' => $oInfo->PermanentFlags, // 'PermanentFlags' => $oInfo->PermanentFlags,
'Hash' => $oInfo->getHash($this->GenerateImapClientHash()), 'Hash' => $oInfo->getHash($this->oImapClient->Hash()),
'MessagesFlags' => $aFlags, 'MessagesFlags' => $aFlags,
'NewMessages' => $this->getFolderNextMessageInformation( 'NewMessages' => $this->getFolderNextMessageInformation(
$sFolderName, $sFolderName,
@ -514,7 +403,7 @@ class MailClient
*/ */
public function FolderHash(string $sFolderName) : string 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); unset($oException);
} }
if ($oCacher && $oCacher->IsInited() && !empty($sSerializedHashKey)) if ($oCacher && $oCacher->IsInited() && !empty($sSerializedHashKey)) {
{
$oCacher->Set($sSerializedHashKey, \json_encode(array( $oCacher->Set($sSerializedHashKey, \json_encode(array(
'ThreadsUids' => $aResult 'ThreadsUids' => $aResult
))); )));
if ($this->oLogger) if ($this->oLogger) {
{
$this->oLogger->Write('Save Serialized Thread UIDS to cache ("'.$sFolderName.'" / '.$sSearchHash.') [count:'.\count($aResult).']'); $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 protected function MessageListByRequestIndexOrUids(MessageCollection $oMessageCollection, SequenceSet $oRange) : void
{ {
if (\count($oRange)) if (\count($oRange)) {
{
$aFetchResponse = $this->oImapClient->Fetch(array( $aFetchResponse = $this->oImapClient->Fetch(array(
FetchType::UID, FetchType::UID,
FetchType::RFC822_SIZE, FetchType::RFC822_SIZE,
@ -605,14 +491,13 @@ class MailClient
$this->getEnvelopeOrHeadersRequestString() $this->getEnvelopeOrHeadersRequestString()
), (string) $oRange, $oRange->UID); ), (string) $oRange, $oRange->UID);
if (\count($aFetchResponse)) if (\count($aFetchResponse)) {
{
$aCollection = \array_fill_keys($oRange->getArrayCopy(), null); $aCollection = \array_fill_keys($oRange->getArrayCopy(), null);
foreach ($aFetchResponse as /* @var $oFetchResponseItem \MailSo\Imap\FetchResponse */ $oFetchResponseItem) { foreach ($aFetchResponse as /* @var $oFetchResponseItem \MailSo\Imap\FetchResponse */ $oFetchResponseItem) {
$id = $oRange->UID $id = $oRange->UID
? $oFetchResponseItem->GetFetchValue(FetchType::UID) ? $oFetchResponseItem->GetFetchValue(FetchType::UID)
: $oFetchResponseItem->oImapResponse->ResponseList[1]; : $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))); $oMessageCollection->exchangeArray(\array_values(\array_filter($aCollection)));
} }
@ -686,7 +571,7 @@ class MailClient
if ($bUseCacheAfterSearch) { if ($bUseCacheAfterSearch) {
$sSerializedHash = 'GetUids/'. $sSerializedHash = 'GetUids/'.
($bUseSortIfSupported ? 'S' . $sSort : 'N').'/'. ($bUseSortIfSupported ? 'S' . $sSort : 'N').'/'.
$this->GenerateImapClientHash().'/'. $this->oImapClient->Hash().'/'.
$sFolderName.'/'.$sSearchCriterias; $sFolderName.'/'.$sSearchCriterias;
$sSerializedLog = '"'.$sFolderName.'" / '.$sSearchCriterias.''; $sSerializedLog = '"'.$sFolderName.'" / '.$sSearchCriterias.'';
@ -742,9 +627,7 @@ class MailClient
*/ */
public function MessageList(MessageListParams $oParams) : MessageCollection public function MessageList(MessageListParams $oParams) : MessageCollection
{ {
if (!\MailSo\Base\Validator::RangeInt($oParams->iOffset, 0) || if (0 > $oParams->iOffset || 0 > $oParams->iLimit || 999 < $oParams->iLimit) {
!\MailSo\Base\Validator::RangeInt($oParams->iLimit, 0, 999))
{
throw new \InvalidArgumentException; throw new \InvalidArgumentException;
} }
@ -773,7 +656,7 @@ class MailClient
$oParams->oCacher = null; $oParams->oCacher = null;
} }
$oMessageCollection->FolderHash = $oInfo->getHash($this->GenerateImapClientHash()); $oMessageCollection->FolderHash = $oInfo->getHash($this->oImapClient->Hash());
if (!$oParams->iThreadUid) { if (!$oParams->iThreadUid) {
$oMessageCollection->NewMessages = $this->getFolderNextMessageInformation( $oMessageCollection->NewMessages = $this->getFolderNextMessageInformation(
@ -893,8 +776,7 @@ class MailClient
public function FindMessageUidByMessageId(string $sFolderName, string $sMessageId) : ?int public function FindMessageUidByMessageId(string $sFolderName, string $sMessageId) : ?int
{ {
if (!\strlen($sMessageId)) if (!\strlen($sMessageId)) {
{
throw new \InvalidArgumentException; 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); $aFolders = $this->oImapClient->FolderStatusList($sParent, $sListPattern);
if (!$aFolders) { if (!$aFolders) {
return null; return null;
@ -976,12 +858,12 @@ class MailClient
} }
} }
/* // Allow non existent parent folders
if (\strlen($sDelimiter) && false !== \strpos($sFolderNameInUtf8, $sDelimiter)) { if (\strlen($sDelimiter) && false !== \strpos($sFolderNameInUtf8, $sDelimiter)) {
// TODO: Translate // TODO: Translate
throw new \MailSo\RuntimeException( throw new \MailSo\RuntimeException('New folder name contains delimiter.');
'New folder name contains delimiter.');
} }
*/
$sFullNameToCreate = $sFolderParentFullName.$sFolderNameInUtf8; $sFullNameToCreate = $sFolderParentFullName.$sFolderNameInUtf8;
$this->oImapClient->FolderCreate($sFullNameToCreate, $bSubscribeOnCreation); $this->oImapClient->FolderCreate($sFullNameToCreate, $bSubscribeOnCreation);
@ -1039,92 +921,33 @@ class MailClient
*/ */
protected function folderModify(string $sPrevFolderFullName, string $sNewFolderFullName, bool $bSubscribe) : self protected function folderModify(string $sPrevFolderFullName, string $sNewFolderFullName, bool $bSubscribe) : self
{ {
if (!\strlen($sPrevFolderFullName) || !\strlen($sNewFolderFullName)) if (!\strlen($sPrevFolderFullName) || !\strlen($sNewFolderFullName)) {
{
throw new \InvalidArgumentException; throw new \InvalidArgumentException;
} }
$aSubscribeFolders = array(); $aSubscribeFolders = array();
if ($bSubscribe) if ($bSubscribe) {
{
$aSubscribeFolders = $this->oImapClient->FolderSubscribeList($sPrevFolderFullName, '*'); $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->FolderUnsubscribe($oFolder->FullName());
} }
} }
$this->oImapClient->FolderRename($sPrevFolderFullName, $sNewFolderFullName); $this->oImapClient->FolderRename($sPrevFolderFullName, $sNewFolderFullName);
foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder) {
{ $sFolderFullNameForResubscribe = $oFolder->FullName();
$sFolderFullNameForResubscrine = $oFolder->FullName(); if (\str_starts_with($sFolderFullNameForResubscribe, $sPrevFolderFullName)) {
if (0 === \strpos($sFolderFullNameForResubscrine, $sPrevFolderFullName)) $sNewFolderFullNameForResubscribe = $sNewFolderFullName.
{ \substr($sFolderFullNameForResubscribe, \strlen($sPrevFolderFullName));
$sNewFolderFullNameForResubscrine = $sNewFolderFullName.
\substr($sFolderFullNameForResubscrine, \strlen($sPrevFolderFullName));
$this->oImapClient->FolderSubscribe($sNewFolderFullNameForResubscrine); $this->oImapClient->FolderSubscribe($sNewFolderFullNameForResubscribe);
} }
} }
return $this; 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 * @throws \InvalidArgumentException
*/ */
@ -1134,23 +957,8 @@ class MailClient
$this->oImapClient->SetLogger($oLogger); $this->oImapClient->SetLogger($oLogger);
} }
public function GetPersonalNamespace() : string
{
$oNamespace = $this->oImapClient->GetNamespace();
return $oNamespace ? $oNamespace->GetPersonalNamespace() : '';
}
public function __call(string $name, array $arguments) /*: mixed*/ public function __call(string $name, array $arguments) /*: mixed*/
{ {
return $this->oImapClient->{$name}(...$arguments); 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; $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; $oMessage = new self;
@ -625,7 +625,7 @@ class Message implements \JsonSerializable
{ {
// if ('application/pgp-keys' === $oAttachmentItem->ContentType()) import ??? // if ('application/pgp-keys' === $oAttachmentItem->ContentType()) import ???
$oMessage->oAttachments->append( $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]) { if ('i' === $k[0]) {
$this->$k = \max(0, (int) $v); $this->$k = \max(0, (int) $v);
} }
// \MailSo\Base\Validator::RangeInt($oParams->iOffset, 0) // 0 > $oParams->iOffset
// \MailSo\Base\Validator::RangeInt($oParams->iLimit, 0, 999) // 0 > $oParams->iLimit
// 999 < $oParams->iLimit
} }
} }

View file

@ -87,7 +87,7 @@ abstract class NetClient
public function Connect(ConnectSettings $oSettings) : void public function Connect(ConnectSettings $oSettings) : void
{ {
$oSettings->host = \trim($oSettings->host); $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); $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 private function parseResponse() : array
{ {
$aResult = array(); $aResult = array();
do while (true) {
{
$sResponseBuffer = $this->getNextBuffer(); $sResponseBuffer = $this->getNextBuffer();
if (null === $sResponseBuffer) { if (null === $sResponseBuffer) {
break; break;
@ -418,7 +417,6 @@ class SieveClient extends \MailSo\Net\NetClient
break; break;
} }
} }
while (true);
if (!$aResult || 'OK' !== \substr($aResult[\array_key_last($aResult)], 0, 2)) { if (!$aResult || 'OK' !== \substr($aResult[\array_key_last($aResult)], 0, 2)) {
$this->writeLogException(new \MailSo\Sieve\Exceptions\NegativeResponseException($aResult), \LOG_WARNING); $this->writeLogException(new \MailSo\Sieve\Exceptions\NegativeResponseException($aResult), \LOG_WARNING);

View file

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

View file

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