mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-11 00:14:50 +03:00
Move IMAP mailbox commands to trait
This commit is contained in:
parent
5953b515f1
commit
971cdafb0f
4 changed files with 510 additions and 505 deletions
|
|
@ -0,0 +1,496 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of MailSo.
|
||||
*
|
||||
* (c) 2014 Usenko Timur
|
||||
* (c) 2021 DJMaze
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace MailSo\Imap\Commands;
|
||||
|
||||
use MailSo\Imap\Folder;
|
||||
use MailSo\Imap\FolderInformation;
|
||||
use MailSo\Imap\Enumerations\FolderStatus;
|
||||
|
||||
/**
|
||||
* @category MailSo
|
||||
* @package Imap
|
||||
*/
|
||||
trait Folders
|
||||
{
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderCreate(string $sFolderName) : self
|
||||
{
|
||||
$this->SendRequestGetResponse('CREATE',
|
||||
array($this->EscapeFolderName($sFolderName)));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderDelete(string $sFolderName) : self
|
||||
{
|
||||
// Uncomment will work issue #124 ?
|
||||
// $this->selectOrExamineFolder($sFolderName, true);
|
||||
$this->SendRequestGetResponse('DELETE',
|
||||
array($this->EscapeFolderName($sFolderName)));
|
||||
// $this->FolderCheck();
|
||||
// $this->FolderUnselect();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderSubscribe(string $sFolderName) : self
|
||||
{
|
||||
$this->SendRequestGetResponse('SUBSCRIBE',
|
||||
array($this->EscapeFolderName($sFolderName)));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderUnsubscribe(string $sFolderName) : self
|
||||
{
|
||||
$this->SendRequestGetResponse('UNSUBSCRIBE',
|
||||
array($this->EscapeFolderName($sFolderName)));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderRename(string $sOldFolderName, string $sNewFolderName) : self
|
||||
{
|
||||
$this->SendRequestGetResponse('RENAME', array(
|
||||
$this->EscapeFolderName($sOldFolderName),
|
||||
$this->EscapeFolderName($sNewFolderName)));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderStatus(string $sFolderName, array $aStatusItems) : ?array
|
||||
{
|
||||
if (!\count($aStatusItems)) {
|
||||
return null;
|
||||
}
|
||||
$oFolderInfo = $this->oCurrentFolderInfo;
|
||||
$bReselect = false;
|
||||
$bWritable = false;
|
||||
if ($oFolderInfo && $sFolderName === $oFolderInfo->FolderName) {
|
||||
/**
|
||||
* There's a long standing IMAP CLIENTBUG where STATUS command is executed
|
||||
* after SELECT/EXAMINE on same folder (it should not).
|
||||
* So we must unselect the folder to be able to get the APPENDLIMIT and UNSEEN.
|
||||
*/
|
||||
/*
|
||||
if ($this->IsSupported('ESEARCH')) {
|
||||
$aResult = $oFolderInfo->getStatusItems();
|
||||
// SELECT or EXAMINE command then UNSEEN is the message sequence number of the first unseen message
|
||||
$aResult['UNSEEN'] = $this->MessageSimpleESearch('UNSEEN', ['COUNT'])['COUNT'];
|
||||
return $aResult;
|
||||
}
|
||||
*/
|
||||
$bWritable = $oFolderInfo->IsWritable;
|
||||
$bReselect = true;
|
||||
$this->FolderUnselect();
|
||||
}
|
||||
|
||||
$oInfo = new FolderInformation($sFolderName, false);
|
||||
$this->SendRequest('STATUS', array($this->EscapeFolderName($sFolderName), $aStatusItems));
|
||||
foreach ($this->yieldUntaggedResponses() as $oResponse) {
|
||||
$oInfo->setStatusFromResponse($oResponse);
|
||||
}
|
||||
|
||||
if ($bReselect) {
|
||||
$this->selectOrExamineFolder($sFolderName, $bWritable, false);
|
||||
}
|
||||
return $oInfo->getStatusItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderCheck() : self
|
||||
{
|
||||
if ($this->IsSelected()) {
|
||||
$this->SendRequestGetResponse('CHECK');
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This also expunge the mailbox
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderClose() : self
|
||||
{
|
||||
if ($this->IsSelected()) {
|
||||
$this->SendRequestGetResponse('CLOSE');
|
||||
$this->oCurrentFolderInfo = null;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderUnselect() : self
|
||||
{
|
||||
if ($this->IsSelected()) {
|
||||
if ($this->IsSupported('UNSELECT')) {
|
||||
$this->SendRequestGetResponse('UNSELECT');
|
||||
$this->oCurrentFolderInfo = null;
|
||||
} else {
|
||||
try {
|
||||
$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()) {
|
||||
$this->oCurrentFolderInfo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The EXPUNGE command permanently removes all messages that have the
|
||||
* \Deleted flag set from the currently selected mailbox.
|
||||
*
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderExpunge(SequenceSet $oUidRange = null) : self
|
||||
{
|
||||
$sCmd = 'EXPUNGE';
|
||||
$aArguments = array();
|
||||
|
||||
if ($oUidRange && \count($oUidRange) && $oUidRange->UID && $this->IsSupported('UIDPLUS')) {
|
||||
$sCmd = 'UID '.$sCmd;
|
||||
$aArguments = array((string) $oUidRange);
|
||||
}
|
||||
|
||||
$this->SendRequestGetResponse($sCmd, $aArguments);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderHierarchyDelimiter(string $sFolderName = '') : ?string
|
||||
{
|
||||
$oResponse = $this->SendRequestGetResponse('LIST', ['""', $this->EscapeFolderName($sFolderName)]);
|
||||
return ('LIST' === $oResponse[0]->ResponseList[1]) ? $oResponse[0]->ResponseList[3] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderSelect(string $sFolderName, bool $bReSelectSameFolders = false) : FolderInformation
|
||||
{
|
||||
return $this->selectOrExamineFolder($sFolderName, true, $bReSelectSameFolders);
|
||||
}
|
||||
|
||||
/**
|
||||
* The EXAMINE command is identical to SELECT and returns the same output;
|
||||
* however, the selected mailbox is identified as read-only.
|
||||
* No changes to the permanent state of the mailbox, including per-user state,
|
||||
* are permitted; in particular, EXAMINE MUST NOT cause messages to lose the \Recent flag.
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderExamine(string $sFolderName, bool $bReSelectSameFolders = false) : FolderInformation
|
||||
{
|
||||
return $this->selectOrExamineFolder($sFolderName, $this->__FORCE_SELECT_ON_EXAMINE__, $bReSelectSameFolders);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
protected function selectOrExamineFolder(string $sFolderName, bool $bIsWritable, bool $bReSelectSameFolders) : FolderInformation
|
||||
{
|
||||
if (!$bReSelectSameFolders
|
||||
&& $this->oCurrentFolderInfo
|
||||
&& $sFolderName === $this->oCurrentFolderInfo->FolderName
|
||||
&& $bIsWritable === $this->oCurrentFolderInfo->IsWritable
|
||||
) {
|
||||
return $this->oCurrentFolderInfo;
|
||||
}
|
||||
|
||||
if (!\strlen(\trim($sFolderName)))
|
||||
{
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException;
|
||||
}
|
||||
|
||||
$aSelectParams = array();
|
||||
/*
|
||||
if ($this->IsSupported('CONDSTORE')) {
|
||||
$aSelectParams[] = 'CONDSTORE';
|
||||
}
|
||||
// RFC 5738
|
||||
if ($this->UTF8) {
|
||||
$aSelectParams[] = 'UTF8';
|
||||
}
|
||||
*/
|
||||
|
||||
$aParams = array(
|
||||
$this->EscapeFolderName($sFolderName)
|
||||
);
|
||||
if ($aSelectParams) {
|
||||
$aParams[] = $aSelectParams;
|
||||
}
|
||||
|
||||
$oResult = new FolderInformation($sFolderName, $bIsWritable);
|
||||
|
||||
/**
|
||||
* IMAP4rev2 SELECT/EXAMINE are now required to return an untagged LIST response.
|
||||
*/
|
||||
$this->SendRequest($bIsWritable ? 'SELECT' : 'EXAMINE', $aParams);
|
||||
foreach ($this->yieldUntaggedResponses() as $oResponse) {
|
||||
if (!$oResult->setStatusFromResponse($oResponse)) {
|
||||
// OK untagged responses
|
||||
if (\is_array($oResponse->OptionalResponse)) {
|
||||
$key = $oResponse->OptionalResponse[0];
|
||||
if (\count($oResponse->OptionalResponse) > 1) {
|
||||
if ('PERMANENTFLAGS' === $key && \is_array($oResponse->OptionalResponse[1])) {
|
||||
$oResult->PermanentFlags = $oResponse->OptionalResponse[1];
|
||||
}
|
||||
} else if ('READ-ONLY' === $key) {
|
||||
// $oResult->IsWritable = false;
|
||||
} else if ('READ-WRITE' === $key) {
|
||||
// $oResult->IsWritable = true;
|
||||
} else if ('NOMODSEQ' === $key) {
|
||||
// https://datatracker.ietf.org/doc/html/rfc4551#section-3.1.2
|
||||
}
|
||||
}
|
||||
|
||||
// untagged responses
|
||||
else if (\count($oResponse->ResponseList) > 2
|
||||
&& 'FLAGS' === $oResponse->ResponseList[1]
|
||||
&& \is_array($oResponse->ResponseList[2])) {
|
||||
$oResult->Flags = $oResponse->ResponseList[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->oCurrentFolderInfo = $oResult;
|
||||
|
||||
return $oResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderList(string $sParentFolderName, string $sListPattern, bool $bIsSubscribeList = false, bool $bUseListStatus = false) : array
|
||||
{
|
||||
$sCmd = 'LIST';
|
||||
|
||||
$aParameters = array();
|
||||
$aReturnParams = array();
|
||||
|
||||
if ($bIsSubscribeList) {
|
||||
// IMAP4rev2 deprecated
|
||||
$sCmd = 'LSUB';
|
||||
} else if ($this->IsSupported('LIST-EXTENDED')) {
|
||||
// RFC 5258
|
||||
$aReturnParams[] = 'SUBSCRIBED';
|
||||
// $aReturnParams[] = 'CHILDREN';
|
||||
if ($bIsSubscribeList) {
|
||||
$aParameters[] = ['SUBSCRIBED'/*,'REMOTE','RECURSIVEMATCH'*/];
|
||||
} else {
|
||||
// $aParameters[0] = '()';
|
||||
}
|
||||
// RFC 6154
|
||||
if ($this->IsSupported('SPECIAL-USE')) {
|
||||
$aReturnParams[] = 'SPECIAL-USE';
|
||||
}
|
||||
}
|
||||
|
||||
$aParameters[] = $this->EscapeFolderName($sParentFolderName);
|
||||
$aParameters[] = $this->EscapeString(\trim($sListPattern));
|
||||
// $aParameters[] = $this->EscapeString(\strlen(\trim($sListPattern)) ? $sListPattern : '*');
|
||||
|
||||
// RFC 5819
|
||||
if ($bUseListStatus && !$bIsSubscribeList && $this->IsSupported('LIST-STATUS'))
|
||||
{
|
||||
$aL = array(
|
||||
FolderStatus::MESSAGES,
|
||||
FolderStatus::UNSEEN,
|
||||
FolderStatus::UIDNEXT
|
||||
);
|
||||
// RFC 4551
|
||||
if ($this->IsSupported('CONDSTORE')) {
|
||||
$aL[] = FolderStatus::HIGHESTMODSEQ;
|
||||
}
|
||||
// RFC 7889
|
||||
if ($this->IsSupported('APPENDLIMIT')) {
|
||||
$aL[] = FolderStatus::APPENDLIMIT;
|
||||
}
|
||||
// RFC 8474
|
||||
if ($this->IsSupported('OBJECTID')) {
|
||||
$aTypes[] = FolderStatus::MAILBOXID;
|
||||
}
|
||||
|
||||
$aReturnParams[] = 'STATUS';
|
||||
$aReturnParams[] = $aL;
|
||||
}
|
||||
/*
|
||||
// RFC 5738
|
||||
if ($this->UTF8) {
|
||||
$aReturnParams[] = 'UTF8'; // 'UTF8ONLY';
|
||||
}
|
||||
*/
|
||||
if ($aReturnParams) {
|
||||
$aParameters[] = 'RETURN';
|
||||
$aParameters[] = $aReturnParams;
|
||||
}
|
||||
|
||||
$bPassthru = false;
|
||||
$aReturn = array();
|
||||
|
||||
// RFC 5464
|
||||
$bMetadata = !$bIsSubscribeList && $this->IsSupported('METADATA');
|
||||
$aMetadata = null;
|
||||
if ($bMetadata) {
|
||||
// Dovecot supports fetching all METADATA at once
|
||||
$aMetadata = $this->getAllMetadata();
|
||||
}
|
||||
|
||||
$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);
|
||||
}
|
||||
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] = $oFolder;
|
||||
}
|
||||
catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException)
|
||||
{
|
||||
$this->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
|
||||
}
|
||||
catch (\Throwable $oException)
|
||||
{
|
||||
$this->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bInbox && !$sParentFolderName && !isset($aReturn['INBOX'])) {
|
||||
$aReturn['INBOX'] = new Folder('INBOX', $sDelimiter);
|
||||
}
|
||||
}
|
||||
|
||||
// RFC 5464
|
||||
if ($bMetadata && !$aMetadata) {
|
||||
foreach ($aReturn as $oFolder) {
|
||||
try {
|
||||
$oFolder->SetAllMetadata(
|
||||
$this->getMetadata($oFolder->FullName(), ['/shared', '/private'], ['DEPTH'=>'infinity'])
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
// Ignore error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderSubscribeList(string $sParentFolderName, string $sListPattern) : array
|
||||
{
|
||||
return $this->FolderList($sParentFolderName, $sListPattern, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderStatusList(string $sParentFolderName, string $sListPattern) : array
|
||||
{
|
||||
return $this->FolderList($sParentFolderName, $sListPattern, false, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
{
|
||||
use Traits\ResponseParser;
|
||||
// use Commands\ACL;
|
||||
use Commands\Folders;
|
||||
use Commands\Messages;
|
||||
use Commands\Metadata;
|
||||
use Commands\Quota;
|
||||
|
|
@ -386,466 +387,6 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderCreate(string $sFolderName) : self
|
||||
{
|
||||
$this->SendRequestGetResponse('CREATE',
|
||||
array($this->EscapeFolderName($sFolderName)));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderDelete(string $sFolderName) : self
|
||||
{
|
||||
// Uncomment will work issue #124 ?
|
||||
// $this->selectOrExamineFolder($sFolderName, true);
|
||||
$this->SendRequestGetResponse('DELETE',
|
||||
array($this->EscapeFolderName($sFolderName)));
|
||||
// $this->FolderCheck();
|
||||
// $this->FolderUnSelect();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderSubscribe(string $sFolderName) : self
|
||||
{
|
||||
$this->SendRequestGetResponse('SUBSCRIBE',
|
||||
array($this->EscapeFolderName($sFolderName)));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderUnSubscribe(string $sFolderName) : self
|
||||
{
|
||||
$this->SendRequestGetResponse('UNSUBSCRIBE',
|
||||
array($this->EscapeFolderName($sFolderName)));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderRename(string $sOldFolderName, string $sNewFolderName) : self
|
||||
{
|
||||
$this->SendRequestGetResponse('RENAME', array(
|
||||
$this->EscapeFolderName($sOldFolderName),
|
||||
$this->EscapeFolderName($sNewFolderName)));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderStatus(string $sFolderName, array $aStatusItems) : ?array
|
||||
{
|
||||
if (!\count($aStatusItems)) {
|
||||
return null;
|
||||
}
|
||||
$oFolderInfo = $this->oCurrentFolderInfo;
|
||||
$bReselect = false;
|
||||
$bWritable = false;
|
||||
if ($oFolderInfo && $sFolderName === $oFolderInfo->FolderName) {
|
||||
/**
|
||||
* There's a long standing IMAP CLIENTBUG where STATUS command is executed
|
||||
* after SELECT/EXAMINE on same folder (it should not).
|
||||
* So we must unselect the folder to be able to get the APPENDLIMIT and UNSEEN.
|
||||
*/
|
||||
/*
|
||||
if ($this->IsSupported('ESEARCH')) {
|
||||
$aResult = $oFolderInfo->getStatusItems();
|
||||
// SELECT or EXAMINE command then UNSEEN is the message sequence number of the first unseen message
|
||||
$aResult['UNSEEN'] = $this->MessageSimpleESearch('UNSEEN', ['COUNT'])['COUNT'];
|
||||
return $aResult;
|
||||
}
|
||||
*/
|
||||
$bWritable = $oFolderInfo->IsWritable;
|
||||
$bReselect = true;
|
||||
$this->FolderUnSelect();
|
||||
}
|
||||
|
||||
$oInfo = new FolderInformation($sFolderName, false);
|
||||
$this->SendRequest('STATUS', array($this->EscapeFolderName($sFolderName), $aStatusItems));
|
||||
foreach ($this->yieldUntaggedResponses() as $oResponse) {
|
||||
$oInfo->setStatusFromResponse($oResponse);
|
||||
}
|
||||
|
||||
if ($bReselect) {
|
||||
$this->selectOrExamineFolder($sFolderName, $bWritable, false);
|
||||
}
|
||||
return $oInfo->getStatusItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
protected function specificFolderList(bool $bIsSubscribeList, string $sParentFolderName = '', string $sListPattern = '*', bool $bUseListStatus = false) : array
|
||||
{
|
||||
$sCmd = 'LIST';
|
||||
|
||||
$aParameters = array();
|
||||
$aReturnParams = array();
|
||||
|
||||
if ($bIsSubscribeList) {
|
||||
// IMAP4rev2 deprecated
|
||||
$sCmd = 'LSUB';
|
||||
} else if ($this->IsSupported('LIST-EXTENDED')) {
|
||||
// RFC 5258
|
||||
$aReturnParams[] = 'SUBSCRIBED';
|
||||
// $aReturnParams[] = 'CHILDREN';
|
||||
if ($bIsSubscribeList) {
|
||||
$aParameters[] = ['SUBSCRIBED'/*,'REMOTE','RECURSIVEMATCH'*/];
|
||||
} else {
|
||||
// $aParameters[0] = '()';
|
||||
}
|
||||
// RFC 6154
|
||||
if ($this->IsSupported('SPECIAL-USE')) {
|
||||
$aReturnParams[] = 'SPECIAL-USE';
|
||||
}
|
||||
}
|
||||
|
||||
$aParameters[] = $this->EscapeFolderName($sParentFolderName);
|
||||
$aParameters[] = $this->EscapeString(\strlen(\trim($sListPattern)) ? $sListPattern : '*');
|
||||
|
||||
// RFC 5819
|
||||
if ($bUseListStatus && !$bIsSubscribeList && $this->IsSupported('LIST-STATUS'))
|
||||
{
|
||||
$aL = array(
|
||||
Enumerations\FolderStatus::MESSAGES,
|
||||
Enumerations\FolderStatus::UNSEEN,
|
||||
Enumerations\FolderStatus::UIDNEXT
|
||||
);
|
||||
// RFC 4551
|
||||
if ($this->IsSupported('CONDSTORE')) {
|
||||
$aL[] = Enumerations\FolderStatus::HIGHESTMODSEQ;
|
||||
}
|
||||
// RFC 7889
|
||||
if ($this->IsSupported('APPENDLIMIT')) {
|
||||
$aL[] = Enumerations\FolderStatus::APPENDLIMIT;
|
||||
}
|
||||
// RFC 8474
|
||||
if ($this->IsSupported('OBJECTID')) {
|
||||
$aTypes[] = Enumerations\FolderStatus::MAILBOXID;
|
||||
}
|
||||
|
||||
$aReturnParams[] = 'STATUS';
|
||||
$aReturnParams[] = $aL;
|
||||
}
|
||||
/*
|
||||
// RFC 5738
|
||||
if ($this->UTF8) {
|
||||
$aReturnParams[] = 'UTF8'; // 'UTF8ONLY';
|
||||
}
|
||||
*/
|
||||
if ($aReturnParams) {
|
||||
$aParameters[] = 'RETURN';
|
||||
$aParameters[] = $aReturnParams;
|
||||
}
|
||||
|
||||
$bPassthru = false;
|
||||
$aReturn = array();
|
||||
|
||||
// RFC 5464
|
||||
$bMetadata = !$bIsSubscribeList && $this->IsSupported('METADATA');
|
||||
$aMetadata = null;
|
||||
if ($bMetadata) {
|
||||
// Dovecot supports fetching all METADATA at once
|
||||
$aMetadata = $this->getAllMetadata();
|
||||
}
|
||||
|
||||
$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);
|
||||
}
|
||||
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] = $oFolder;
|
||||
}
|
||||
catch (\MailSo\Base\Exceptions\InvalidArgumentException $oException)
|
||||
{
|
||||
$this->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
|
||||
}
|
||||
catch (\Throwable $oException)
|
||||
{
|
||||
$this->writeLogException($oException, \MailSo\Log\Enumerations\Type::WARNING, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bInbox && !$sParentFolderName && !isset($aReturn['INBOX'])) {
|
||||
$aReturn['INBOX'] = new Folder('INBOX', $sDelimiter);
|
||||
}
|
||||
}
|
||||
|
||||
// RFC 5464
|
||||
if ($bMetadata && !$aMetadata) {
|
||||
foreach ($aReturn as $oFolder) {
|
||||
try {
|
||||
$oFolder->SetAllMetadata(
|
||||
$this->getMetadata($oFolder->FullName(), ['/shared', '/private'], ['DEPTH'=>'infinity'])
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
// Ignore error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderList(string $sParentFolderName = '', string $sListPattern = '*') : array
|
||||
{
|
||||
return $this->specificFolderList(false, $sParentFolderName, $sListPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderSubscribeList(string $sParentFolderName = '', string $sListPattern = '*') : array
|
||||
{
|
||||
return $this->specificFolderList(true, $sParentFolderName, $sListPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderStatusList(string $sParentFolderName = '', string $sListPattern = '*') : array
|
||||
{
|
||||
return $this->specificFolderList(false, $sParentFolderName, $sListPattern, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderHierarchyDelimiter(string $sFolderName = '') : ?string
|
||||
{
|
||||
$oResponse = $this->SendRequestGetResponse('LIST', ['""', $this->EscapeFolderName($sFolderName)]);
|
||||
return ('LIST' === $oResponse[0]->ResponseList[1]) ? $oResponse[0]->ResponseList[3] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
protected function selectOrExamineFolder(string $sFolderName, bool $bIsWritable, bool $bReSelectSameFolders) : self
|
||||
{
|
||||
if (!$bReSelectSameFolders)
|
||||
{
|
||||
if ($this->oCurrentFolderInfo &&
|
||||
$sFolderName === $this->oCurrentFolderInfo->FolderName &&
|
||||
$bIsWritable === $this->oCurrentFolderInfo->IsWritable)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
if (!\strlen(\trim($sFolderName)))
|
||||
{
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException;
|
||||
}
|
||||
|
||||
$aSelectParams = array();
|
||||
/*
|
||||
if ($this->IsSupported('CONDSTORE')) {
|
||||
$aSelectParams[] = 'CONDSTORE';
|
||||
}
|
||||
// RFC 5738
|
||||
if ($this->UTF8) {
|
||||
$aSelectParams[] = 'UTF8';
|
||||
}
|
||||
*/
|
||||
|
||||
$aParams = array(
|
||||
$this->EscapeFolderName($sFolderName)
|
||||
);
|
||||
if ($aSelectParams) {
|
||||
$aParams[] = $aSelectParams;
|
||||
}
|
||||
|
||||
$oResult = new FolderInformation($sFolderName, $bIsWritable);
|
||||
|
||||
/**
|
||||
* IMAP4rev2 SELECT/EXAMINE are now required to return an untagged LIST response.
|
||||
*/
|
||||
$this->SendRequest($bIsWritable ? 'SELECT' : 'EXAMINE', $aParams);
|
||||
foreach ($this->yieldUntaggedResponses() as $oResponse) {
|
||||
if (!$oResult->setStatusFromResponse($oResponse)) {
|
||||
// OK untagged responses
|
||||
if (\is_array($oResponse->OptionalResponse)) {
|
||||
$key = $oResponse->OptionalResponse[0];
|
||||
if (\count($oResponse->OptionalResponse) > 1) {
|
||||
if ('PERMANENTFLAGS' === $key && \is_array($oResponse->OptionalResponse[1])) {
|
||||
$oResult->PermanentFlags = $oResponse->OptionalResponse[1];
|
||||
}
|
||||
} else if ('READ-ONLY' === $key) {
|
||||
// $oResult->IsWritable = false;
|
||||
} else if ('READ-WRITE' === $key) {
|
||||
// $oResult->IsWritable = true;
|
||||
} else if ('NOMODSEQ' === $key) {
|
||||
// https://datatracker.ietf.org/doc/html/rfc4551#section-3.1.2
|
||||
}
|
||||
}
|
||||
|
||||
// untagged responses
|
||||
else if (\count($oResponse->ResponseList) > 2
|
||||
&& 'FLAGS' === $oResponse->ResponseList[1]
|
||||
&& \is_array($oResponse->ResponseList[2])) {
|
||||
$oResult->Flags = $oResponse->ResponseList[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->oCurrentFolderInfo = $oResult;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderSelect(string $sFolderName, bool $bReSelectSameFolders = false) : self
|
||||
{
|
||||
return $this->selectOrExamineFolder($sFolderName, true, $bReSelectSameFolders);
|
||||
}
|
||||
|
||||
/**
|
||||
* The EXAMINE command is identical to SELECT and returns the same output;
|
||||
* however, the selected mailbox is identified as read-only.
|
||||
* No changes to the permanent state of the mailbox, including per-user state,
|
||||
* are permitted; in particular, EXAMINE MUST NOT cause messages to lose the \Recent flag.
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderExamine(string $sFolderName, bool $bReSelectSameFolders = false) : self
|
||||
{
|
||||
return $this->selectOrExamineFolder($sFolderName, $this->__FORCE_SELECT_ON_EXAMINE__, $bReSelectSameFolders);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderCheck() : self
|
||||
{
|
||||
if ($this->IsSelected()) {
|
||||
$this->SendRequestGetResponse('CHECK');
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This also expunge the mailbox
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderClose() : self
|
||||
{
|
||||
if ($this->IsSelected()) {
|
||||
$this->SendRequestGetResponse('CLOSE');
|
||||
$this->oCurrentFolderInfo = null;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderUnSelect() : self
|
||||
{
|
||||
if ($this->IsSelected()) {
|
||||
if ($this->IsSupported('UNSELECT')) {
|
||||
$this->SendRequestGetResponse('UNSELECT');
|
||||
$this->oCurrentFolderInfo = null;
|
||||
} else {
|
||||
try {
|
||||
$this->SendRequestGetResponse('SELECT', ['""']);
|
||||
// * OK [CLOSED] Previous mailbox closed.
|
||||
// 3 NO [CANNOT] Invalid mailbox name: Name is empty
|
||||
} catch (Exceptions\NegativeResponseException $e) {
|
||||
if ('NO' === $e->GetResponseStatus()) {
|
||||
$this->oCurrentFolderInfo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
|
|
@ -928,32 +469,6 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* The EXPUNGE command permanently removes all messages that have the
|
||||
* \Deleted flag set from the currently selected mailbox.
|
||||
*
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderExpunge(SequenceSet $oUidRange = null) : self
|
||||
{
|
||||
$sCmd = 'EXPUNGE';
|
||||
$aArguments = array();
|
||||
|
||||
if ($oUidRange && \count($oUidRange) && $oUidRange->UID && $this->IsSupported('UIDPLUS')) {
|
||||
$sCmd = 'UID '.$sCmd;
|
||||
$aArguments = array((string) $oUidRange);
|
||||
}
|
||||
|
||||
$this->SendRequestGetResponse($sCmd, $aArguments);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function FolderCurrentInformation() : ?FolderInformation
|
||||
{
|
||||
return $this->oCurrentFolderInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
|
|
|
|||
|
|
@ -124,10 +124,8 @@ class MailClient
|
|||
*/
|
||||
public function MessageSetFlagToAll(string $sFolderName, string $sMessageFlag, bool $bSetAction = true, bool $bSkipUnsupportedFlag = false, ?array $aCustomUids = null) : void
|
||||
{
|
||||
$this->oImapClient->FolderSelect($sFolderName);
|
||||
|
||||
$oFolderInfo = $this->oImapClient->FolderCurrentInformation();
|
||||
if (!$oFolderInfo || !$oFolderInfo->IsFlagSupported($sMessageFlag))
|
||||
$oFolderInfo = $this->oImapClient->FolderSelect($sFolderName);
|
||||
if (!$oFolderInfo->IsFlagSupported($sMessageFlag))
|
||||
{
|
||||
if (!$bSkipUnsupportedFlag)
|
||||
{
|
||||
|
|
@ -161,10 +159,8 @@ class MailClient
|
|||
*/
|
||||
public function MessageSetFlag(string $sFolderName, SequenceSet $oRange, string $sMessageFlag, bool $bSetAction = true, bool $bSkipUnsupportedFlag = false) : void
|
||||
{
|
||||
$this->oImapClient->FolderSelect($sFolderName);
|
||||
|
||||
$oFolderInfo = $this->oImapClient->FolderCurrentInformation();
|
||||
if (!$oFolderInfo || !$oFolderInfo->IsFlagSupported($sMessageFlag))
|
||||
$oFolderInfo = $this->oImapClient->FolderSelect($sFolderName);
|
||||
if (!$oFolderInfo->IsFlagSupported($sMessageFlag))
|
||||
{
|
||||
if (!$bSkipUnsupportedFlag)
|
||||
{
|
||||
|
|
@ -449,11 +445,11 @@ class MailClient
|
|||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function FolderUnSelect() : self
|
||||
public function FolderUnselect() : self
|
||||
{
|
||||
if ($this->oImapClient->IsSelected())
|
||||
{
|
||||
$this->oImapClient->FolderUnSelect();
|
||||
$this->oImapClient->FolderUnselect();
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
|
@ -1321,7 +1317,7 @@ class MailClient
|
|||
$aSubscribeFolders = $this->oImapClient->FolderSubscribeList($sPrevFolderFullName, '*');
|
||||
foreach ($aSubscribeFolders as /* @var $oFolder \MailSo\Imap\Folder */ $oFolder)
|
||||
{
|
||||
$this->oImapClient->FolderUnSubscribe($oFolder->FullName());
|
||||
$this->oImapClient->FolderUnsubscribe($oFolder->FullName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1365,7 +1361,7 @@ class MailClient
|
|||
|
||||
if ($bUnsubscribeOnDeletion)
|
||||
{
|
||||
$this->oImapClient->FolderUnSubscribe($sFolderFullName);
|
||||
$this->oImapClient->FolderUnsubscribe($sFolderFullName);
|
||||
}
|
||||
|
||||
$this->oImapClient->FolderDelete($sFolderFullName);
|
||||
|
|
@ -1378,10 +1374,8 @@ class MailClient
|
|||
*/
|
||||
public function FolderClear(string $sFolderFullName) : self
|
||||
{
|
||||
$this->oImapClient->FolderSelect($sFolderFullName);
|
||||
|
||||
$oFolderInformation = $this->oImapClient->FolderCurrentInformation();
|
||||
if ($oFolderInformation && 0 < $oFolderInformation->MESSAGES)
|
||||
$oFolderInformation = $this->oImapClient->FolderSelect($sFolderFullName);
|
||||
if (0 < $oFolderInformation->MESSAGES)
|
||||
{
|
||||
$this->oImapClient->MessageStoreFlag(new SequenceSet('1:*', false),
|
||||
array(\MailSo\Imap\Enumerations\MessageFlag::DELETED),
|
||||
|
|
@ -1404,7 +1398,7 @@ class MailClient
|
|||
throw new \MailSo\Base\Exceptions\InvalidArgumentException;
|
||||
}
|
||||
|
||||
$this->oImapClient->{$bSubscribe ? 'FolderSubscribe' : 'FolderUnSubscribe'}($sFolderFullName);
|
||||
$this->oImapClient->{$bSubscribe ? 'FolderSubscribe' : 'FolderUnsubscribe'}($sFolderFullName);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ trait Messages
|
|||
{
|
||||
try
|
||||
{
|
||||
$this->MailClient()->FolderUnSelect();
|
||||
$this->MailClient()->FolderUnselect();
|
||||
}
|
||||
catch (\Throwable $oException)
|
||||
{
|
||||
|
|
@ -554,7 +554,7 @@ trait Messages
|
|||
{
|
||||
try
|
||||
{
|
||||
$this->MailClient()->FolderUnSelect();
|
||||
$this->MailClient()->FolderUnselect();
|
||||
}
|
||||
catch (\Throwable $oException)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue