mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-10-04 10:54:21 +08:00
Resolve #744 (not active!!)
This commit is contained in:
parent
8d1290e2c4
commit
94c3fa464d
12 changed files with 276 additions and 41 deletions
|
@ -22,4 +22,22 @@ export class AccountModel extends AbstractModel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports all mail to main account
|
||||||
|
*//*
|
||||||
|
importAll(account) {
|
||||||
|
rl.app.Remote.streamPerLine(line => {
|
||||||
|
try {
|
||||||
|
line = JSON.parse(line);
|
||||||
|
console.dir(line);
|
||||||
|
} catch (e) {
|
||||||
|
// OOPS
|
||||||
|
}
|
||||||
|
}, 'AccountImport', {
|
||||||
|
Action: 'AccountImport',
|
||||||
|
email: account.email
|
||||||
|
});
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,6 +287,7 @@ trait Messages
|
||||||
* @throws \MailSo\RuntimeException
|
* @throws \MailSo\RuntimeException
|
||||||
* @throws \MailSo\Net\Exceptions\*
|
* @throws \MailSo\Net\Exceptions\*
|
||||||
* @throws \MailSo\Imap\Exceptions\*
|
* @throws \MailSo\Imap\Exceptions\*
|
||||||
|
* $sStoreAction = \MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT
|
||||||
*/
|
*/
|
||||||
public function MessageStoreFlag(SequenceSet $oRange, array $aInputStoreItems, string $sStoreAction) : ?ResponseCollection
|
public function MessageStoreFlag(SequenceSet $oRange, array $aInputStoreItems, string $sStoreAction) : ?ResponseCollection
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,20 +20,14 @@ class Folder
|
||||||
// RFC5258 Response data STATUS items when using LIST-EXTENDED
|
// RFC5258 Response data STATUS items when using LIST-EXTENDED
|
||||||
use Traits\Status;
|
use Traits\Status;
|
||||||
|
|
||||||
/**
|
private ?string $sDelimiter;
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $sDelimiter;
|
|
||||||
|
|
||||||
/**
|
private array $aFlagsLowerCase;
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $aFlagsLowerCase;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RFC 5464
|
* RFC 5464
|
||||||
*/
|
*/
|
||||||
private $aMetadata = array();
|
private array $aMetadata = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
|
@ -57,7 +51,7 @@ class Folder
|
||||||
|
|
||||||
public function setFlags(array $aFlags) : void
|
public function setFlags(array $aFlags) : void
|
||||||
{
|
{
|
||||||
$this->aFlagsLowerCase = \array_map('strtolower', $aFlags);
|
$this->aFlagsLowerCase = \array_map('mb_strtolower', $aFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setDelimiter(?string $sDelimiter) : void
|
public function setDelimiter(?string $sDelimiter) : void
|
||||||
|
|
|
@ -26,8 +26,8 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
use Commands\Metadata;
|
use Commands\Metadata;
|
||||||
use Commands\Quota;
|
use Commands\Quota;
|
||||||
|
|
||||||
const
|
public
|
||||||
TAG_PREFIX = 'TAG';
|
$TAG_PREFIX = 'TAG';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
|
@ -606,7 +606,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
||||||
|
|
||||||
protected function getCurrentTag() : string
|
protected function getCurrentTag() : string
|
||||||
{
|
{
|
||||||
return self::TAG_PREFIX.$this->iTagCount;
|
return $this->TAG_PREFIX.$this->iTagCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function EscapeString(?string $sStringForEscape) : string
|
public function EscapeString(?string $sStringForEscape) : string
|
||||||
|
|
|
@ -401,8 +401,7 @@ trait ResponseParser
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rImapLiteralStream =
|
$rImapLiteralStream = \MailSo\Base\StreamWrappers\Literal::CreateStream($this->ConnectionResource(), $iLiteralLen);
|
||||||
\MailSo\Base\StreamWrappers\Literal::CreateStream($this->ConnectionResource(), $iLiteralLen);
|
|
||||||
|
|
||||||
$this->writeLog('Start Callback for '.$sParent.' / '.$sLiteralAtomUpperCase.
|
$this->writeLog('Start Callback for '.$sParent.' / '.$sLiteralAtomUpperCase.
|
||||||
' - try to read '.$iLiteralLen.' bytes.', \LOG_INFO);
|
' - try to read '.$iLiteralLen.' bytes.', \LOG_INFO);
|
||||||
|
@ -411,7 +410,7 @@ trait ResponseParser
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->aFetchCallbacks[$sFetchKey]($sParent, $sLiteralAtomUpperCase, $rImapLiteralStream);
|
$this->aFetchCallbacks[$sFetchKey]($sParent, $sLiteralAtomUpperCase, $rImapLiteralStream, $iLiteralLen);
|
||||||
}
|
}
|
||||||
catch (\Throwable $oException)
|
catch (\Throwable $oException)
|
||||||
{
|
{
|
||||||
|
@ -445,12 +444,10 @@ trait ResponseParser
|
||||||
\fclose($rImapLiteralStream);
|
\fclose($rImapLiteralStream);
|
||||||
|
|
||||||
if (0 < $iNotReadLiteralLen) {
|
if (0 < $iNotReadLiteralLen) {
|
||||||
$this->writeLog('Not read literal size is '.$iNotReadLiteralLen.' bytes.',
|
$this->writeLog('Not read literal size is '.$iNotReadLiteralLen.' bytes.', \LOG_WARNING);
|
||||||
\LOG_WARNING);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->writeLog('Literal stream is not resource after callback.',
|
$this->writeLog('Literal stream is not resource after callback.', \LOG_WARNING);
|
||||||
\LOG_WARNING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->bRunningCallback = false;
|
$this->bRunningCallback = false;
|
||||||
|
|
|
@ -20,20 +20,11 @@ use MailSo\Imap\Enumerations\MetadataKeys;
|
||||||
*/
|
*/
|
||||||
class Folder implements \JsonSerializable
|
class Folder implements \JsonSerializable
|
||||||
{
|
{
|
||||||
/**
|
private bool $bExists;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $bExists;
|
|
||||||
|
|
||||||
/**
|
private bool $bSubscribed;
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $bSubscribed;
|
|
||||||
|
|
||||||
/**
|
private \MailSo\Imap\Folder $oImapFolder;
|
||||||
* @var \MailSo\Imap\Folder
|
|
||||||
*/
|
|
||||||
private $oImapFolder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
|
@ -70,7 +61,7 @@ class Folder implements \JsonSerializable
|
||||||
return $this->oImapFolder->NameRaw();
|
return $this->oImapFolder->NameRaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Delimiter() : string
|
public function Delimiter() : ?string
|
||||||
{
|
{
|
||||||
return $this->oImapFolder->Delimiter();
|
return $this->oImapFolder->Delimiter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1096,7 +1096,7 @@ class Actions
|
||||||
|
|
||||||
if (!$this->MailClient()->IsLoggined()) {
|
if (!$this->MailClient()->IsLoggined()) {
|
||||||
try {
|
try {
|
||||||
$oAccount->ImapConnectAndLoginHelper($this->oPlugins, $this->MailClient(), $this->oConfig);
|
$oAccount->ImapConnectAndLoginHelper($this->oPlugins, $this->MailClient()->ImapClient(), $this->oConfig);
|
||||||
} catch (\MailSo\Net\Exceptions\ConnectionException $oException) {
|
} catch (\MailSo\Net\Exceptions\ConnectionException $oException) {
|
||||||
throw new Exceptions\ClientException(Notifications::ConnectionError, $oException);
|
throw new Exceptions\ClientException(Notifications::ConnectionError, $oException);
|
||||||
} catch (\Throwable $oException) {
|
} catch (\Throwable $oException) {
|
||||||
|
|
|
@ -110,6 +110,47 @@ trait Accounts
|
||||||
return $this->TrueResponse(__FUNCTION__);
|
return $this->TrueResponse(__FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports all mail from AdditionalAccount into MainAccount
|
||||||
|
*/
|
||||||
|
public function DoAccountImport(): array
|
||||||
|
{
|
||||||
|
$sEmail = \MailSo\Base\Utils::IdnToAscii(\trim($this->GetActionParam('email', '')), true);
|
||||||
|
if (!\strlen($sEmail)) {
|
||||||
|
throw new ClientException(Notifications::AccountDoesNotExist);
|
||||||
|
}
|
||||||
|
|
||||||
|
$oMainAccount = $this->getMainAccountFromToken();
|
||||||
|
$oLogger = $this->Logger();
|
||||||
|
|
||||||
|
$aAccounts = $this->GetAccounts($oMainAccount);
|
||||||
|
if (!isset($aAccounts[$sEmail])) {
|
||||||
|
throw new ClientException(Notifications::AccountDoesNotExist);
|
||||||
|
}
|
||||||
|
$oAccount = AdditionalAccount::NewInstanceFromTokenArray(
|
||||||
|
$this, $aAccounts[$sEmail]
|
||||||
|
);
|
||||||
|
if (!$oAccount) {
|
||||||
|
throw new ClientException(Notifications::AccountDoesNotExist);
|
||||||
|
}
|
||||||
|
|
||||||
|
$oImapTarget = new \MailSo\Imap\ImapClient;
|
||||||
|
$oImapTarget->SetLogger($oLogger);
|
||||||
|
$this->imapConnect($oMainAccount, false, $oImapTarget);
|
||||||
|
|
||||||
|
$oImapSource = new \MailSo\Imap\ImapClient;
|
||||||
|
$oImapSource->SetLogger($oLogger);
|
||||||
|
$this->imapConnect($oAccount, false, $oImapSource);
|
||||||
|
|
||||||
|
$oSync = new \SnappyMail\Imap\Sync;
|
||||||
|
$oSync->oImapSource = $oImapSource;
|
||||||
|
$oSync->oImapTarget = $oImapTarget;
|
||||||
|
|
||||||
|
$rootfolder = $this->GetActionParam('rootfolder', '') ?: $sEmail;
|
||||||
|
$oSync->import($rootfolder);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \MailSo\RuntimeException
|
* @throws \MailSo\RuntimeException
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -139,7 +139,7 @@ trait UserAuth
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->CheckMailConnection($oAccount, true);
|
$this->imapConnect($oAccount, true);
|
||||||
if ($bMainAccount) {
|
if ($bMainAccount) {
|
||||||
$bSignMe && $this->SetSignMeToken($oAccount);
|
$bSignMe && $this->SetSignMeToken($oAccount);
|
||||||
$this->StorageProvider()->Put($oAccount, StorageType::SESSION, Utils::GetSessionToken(), 'true');
|
$this->StorageProvider()->Put($oAccount, StorageType::SESSION, Utils::GetSessionToken(), 'true');
|
||||||
|
@ -188,7 +188,8 @@ trait UserAuth
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the login
|
// Test the login
|
||||||
$this->CheckMailConnection($oAccount);
|
$oImapClient = new \MailSo\Imap\ImapClient;
|
||||||
|
$this->imapConnect($oAccount, false, $oImapClient);
|
||||||
|
|
||||||
$this->SetAdditionalAuthToken($oAccount);
|
$this->SetAdditionalAuthToken($oAccount);
|
||||||
return true;
|
return true;
|
||||||
|
@ -380,7 +381,7 @@ trait UserAuth
|
||||||
if (!$oAccount) {
|
if (!$oAccount) {
|
||||||
throw new \RuntimeException('token has no account');
|
throw new \RuntimeException('token has no account');
|
||||||
}
|
}
|
||||||
$this->CheckMailConnection($oAccount);
|
$this->imapConnect($oAccount);
|
||||||
// Update lifetime
|
// Update lifetime
|
||||||
$this->SetSignMeToken($oAccount);
|
$this->SetSignMeToken($oAccount);
|
||||||
return $oAccount;
|
return $oAccount;
|
||||||
|
@ -440,10 +441,13 @@ trait UserAuth
|
||||||
/**
|
/**
|
||||||
* @throws \RainLoop\Exceptions\ClientException
|
* @throws \RainLoop\Exceptions\ClientException
|
||||||
*/
|
*/
|
||||||
protected function CheckMailConnection(Account $oAccount, bool $bAuthLog = false): void
|
protected function imapConnect(Account $oAccount, bool $bAuthLog = false, \MailSo\Imap\ImapClient $oImapClient = null): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$oAccount->ImapConnectAndLoginHelper($this->Plugins(), $this->MailClient(), $this->Config());
|
if (!$oImapClient) {
|
||||||
|
$oImapClient = $this->MailClient()->ImapClient();
|
||||||
|
}
|
||||||
|
$oAccount->ImapConnectAndLoginHelper($this->Plugins(), $oImapClient, $this->Config());
|
||||||
} catch (ClientException $oException) {
|
} catch (ClientException $oException) {
|
||||||
throw $oException;
|
throw $oException;
|
||||||
} catch (\MailSo\Net\Exceptions\ConnectionException $oException) {
|
} catch (\MailSo\Net\Exceptions\ConnectionException $oException) {
|
||||||
|
|
|
@ -216,9 +216,8 @@ abstract class Account implements \JsonSerializable
|
||||||
return $oAccount;
|
return $oAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ImapConnectAndLoginHelper(\RainLoop\Plugins\Manager $oPlugins, \MailSo\Mail\MailClient $oMailClient, \RainLoop\Config\Application $oConfig) : bool
|
public function ImapConnectAndLoginHelper(\RainLoop\Plugins\Manager $oPlugins, \MailSo\Imap\ImapClient $oImapClient, \RainLoop\Config\Application $oConfig) : bool
|
||||||
{
|
{
|
||||||
$oImapClient = $oMailClient->ImapClient();
|
|
||||||
$oImapClient->__FORCE_SELECT_ON_EXAMINE__ = !!$oConfig->Get('imap', 'use_force_selection');
|
$oImapClient->__FORCE_SELECT_ON_EXAMINE__ = !!$oConfig->Get('imap', 'use_force_selection');
|
||||||
$oImapClient->__DISABLE_METADATA = !!$oConfig->Get('imap', 'disable_metadata');
|
$oImapClient->__DISABLE_METADATA = !!$oConfig->Get('imap', 'disable_metadata');
|
||||||
|
|
||||||
|
|
187
snappymail/v/0.0.0/app/libraries/snappymail/imap/sync.php
Normal file
187
snappymail/v/0.0.0/app/libraries/snappymail/imap/sync.php
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SnappyMail\Imap;
|
||||||
|
|
||||||
|
use MailSo\Imap\Enumerations\FetchType;
|
||||||
|
use MailSo\Imap\Enumerations\MessageFlag;
|
||||||
|
use MailSo\Imap\FetchResponse;
|
||||||
|
use MailSo\Mime\Enumerations\Header;
|
||||||
|
|
||||||
|
class Sync
|
||||||
|
{
|
||||||
|
public
|
||||||
|
$oImapSource,
|
||||||
|
$oImapTarget;
|
||||||
|
|
||||||
|
function import(string $sTargetRootFolderName = '')
|
||||||
|
{
|
||||||
|
$sParent = '';
|
||||||
|
$sListPattern = '*';
|
||||||
|
|
||||||
|
$this->oImapSource->TAG_PREFIX = 'S';
|
||||||
|
$this->oImapTarget->TAG_PREFIX = 'T';
|
||||||
|
|
||||||
|
// $this->oImapTarget->Logger()->Write('Get oImapTarget->FolderList');
|
||||||
|
\SnappyMail\Log::notice('SYNC', 'Get oImapTarget->FolderList');
|
||||||
|
$aTargetFolders = $this->oImapTarget->FolderList($sParent, $sListPattern);
|
||||||
|
if (!$aTargetFolders) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$sTargetINBOX = 'INBOX';
|
||||||
|
$sTargetDelimiter = '';
|
||||||
|
foreach ($aTargetFolders as $sFullName => $oImapFolder) {
|
||||||
|
if ($oImapFolder->IsInbox()) {
|
||||||
|
$sTargetINBOX = $sFullName;
|
||||||
|
}
|
||||||
|
if (!$sTargetDelimiter) {
|
||||||
|
$sTargetDelimiter = $oImapFolder->Delimiter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\SnappyMail\Log::notice('SYNC', 'Get oImapSource->FolderList');
|
||||||
|
$bUseListStatus = $this->oImapSource->IsSupported('LIST-EXTENDED');
|
||||||
|
$aSourceFolders = $this->oImapSource->FolderList($sParent, $sListPattern, false, $bUseListStatus);
|
||||||
|
if (!$aSourceFolders) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$sSourceINBOX = 'INBOX';
|
||||||
|
|
||||||
|
\SnappyMail\HTTP\Stream::start();
|
||||||
|
\SnappyMail\HTTP\Stream::JSON([
|
||||||
|
'folders' => \count($aSourceFolders)
|
||||||
|
]);
|
||||||
|
|
||||||
|
$fi = 0;
|
||||||
|
foreach ($aSourceFolders as $sSourceFolderName => $oImapFolder) {
|
||||||
|
++$fi;
|
||||||
|
\SnappyMail\HTTP\Stream::JSON([
|
||||||
|
'index' => $fi,
|
||||||
|
'folder' => $sSourceFolderName
|
||||||
|
]);
|
||||||
|
if ($oImapFolder->IsSelectable()) {
|
||||||
|
if ($oImapFolder->IsInbox()) {
|
||||||
|
$sSourceINBOX = $sSourceFolderName;
|
||||||
|
}
|
||||||
|
// Set mailbox delimiter
|
||||||
|
$sTargetFolderName = $sSourceFolderName;
|
||||||
|
if ($sTargetDelimiter) {
|
||||||
|
$sTargetFolderName = \str_replace($oImapFolder->Delimiter(), $sTargetDelimiter, $sTargetFolderName);
|
||||||
|
$sTargetRootFolderName = \str_replace($sTargetDelimiter, '-', $sTargetRootFolderName);
|
||||||
|
}
|
||||||
|
if ($sTargetRootFolderName) {
|
||||||
|
$sTargetFolderName = $sTargetRootFolderName . ($sTargetDelimiter?:'-') . $sTargetFolderName;
|
||||||
|
}
|
||||||
|
// Create mailbox if not exists
|
||||||
|
if (!isset($aTargetFolders[$sTargetFolderName])) {
|
||||||
|
$this->oImapTarget->FolderCreate($sTargetFolderName);
|
||||||
|
if (!$bUseListStatus || \in_array('\\subscribed', $oImapFolder->FlagsLowerCase())) {
|
||||||
|
$this->oImapTarget->FolderSubscribe($sTargetFolderName);
|
||||||
|
}
|
||||||
|
} else if (!$aTargetFolders[$sTargetFolderName]->IsSelectable()) {
|
||||||
|
// Can't copy messages
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Source metadata on target
|
||||||
|
if ($aMetadata = $oImapFolder->Metadata()) {
|
||||||
|
$this->oImapTarget->FolderSetMetadata($sTargetFolderName, $aMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
$oSourceInfo = $this->oImapSource->FolderSelect($sSourceFolderName);
|
||||||
|
if ($oSourceInfo->MESSAGES) {
|
||||||
|
\SnappyMail\HTTP\Stream::JSON([
|
||||||
|
'index' => $fi,
|
||||||
|
'messages' => $oSourceInfo->MESSAGES
|
||||||
|
]);
|
||||||
|
// All id's to skip from source
|
||||||
|
$oTargetInfo = $this->oImapTarget->FolderSelect($sTargetFolderName);
|
||||||
|
if ($oTargetInfo->MESSAGES) {
|
||||||
|
// Get all existing message id's from target to skip
|
||||||
|
$aTargetMessageIDs = [];
|
||||||
|
$this->oImapTarget->SendRequest('FETCH', [
|
||||||
|
'1:*', [FetchType::BuildBodyCustomHeaderRequest([Header::MESSAGE_ID], true)]
|
||||||
|
]);
|
||||||
|
foreach ($this->oImapTarget->yieldUntaggedResponses() as $oResponse) {
|
||||||
|
if ('FETCH' === $oResponse->ResponseList[2]) {
|
||||||
|
// $oResponse->ResponseList[3][0] == 'BODY[HEADER.FIELDS (MESSAGE-ID)]'
|
||||||
|
// 'Message-ID: ...'
|
||||||
|
$aTargetMessageIDs[] = $oResponse->ResponseList[3][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set all existing id's from source to skip and get all flags
|
||||||
|
$aSourceSkipIDs = [];
|
||||||
|
$aSourceFlags = [];
|
||||||
|
$this->oImapSource->SendRequest('FETCH', [
|
||||||
|
'1:*', [FetchType::FLAGS, FetchType::BuildBodyCustomHeaderRequest([Header::MESSAGE_ID], true)]
|
||||||
|
]);
|
||||||
|
foreach ($this->oImapSource->yieldUntaggedResponses() as $oResponse) {
|
||||||
|
if ('FETCH' === $oResponse->ResponseList[2]
|
||||||
|
&& isset($oResponse->ResponseList[3])
|
||||||
|
&& \is_array($oResponse->ResponseList[3])
|
||||||
|
) {
|
||||||
|
$id = $oResponse->ResponseList[1];
|
||||||
|
foreach ($oResponse->ResponseList[3] as $i => $mItem) {
|
||||||
|
if ('FLAGS' === $mItem) {
|
||||||
|
$aSourceFlags[$id] = $oResponse->ResponseList[3][$i+1];
|
||||||
|
} else if ('MESSAGE-ID' === $mItem && \in_array($oResponse->ResponseList[3][$i+1], $aTargetMessageIDs)) {
|
||||||
|
$aSourceSkipIDs[] = $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aTargetMessageIDs = [];
|
||||||
|
// Now copy each message from source to target
|
||||||
|
for ($i = 1; $i <= $oSourceInfo->MESSAGES; ++$i) {
|
||||||
|
if (!\in_array($i, $aSourceSkipIDs)) {
|
||||||
|
$sPeek = $this->oImapSource->IsSupported('BINARY')
|
||||||
|
? FetchType::BINARY_PEEK
|
||||||
|
: FetchType::BODY_PEEK;
|
||||||
|
$iAppendUid = 0;
|
||||||
|
$aFetchResponse = $this->oImapSource->Fetch(array(
|
||||||
|
array(
|
||||||
|
$sPeek.'[]',
|
||||||
|
function ($sParent, $sLiteralAtomUpperCase, $rLiteralStream, $iLiteralLen)
|
||||||
|
use ($sTargetFolderName, &$iAppendUid, $aSourceFlags, $i) {
|
||||||
|
if (\strlen($sLiteralAtomUpperCase) && \is_resource($rLiteralStream) && 'FETCH' === $sParent) {
|
||||||
|
// $sMessage = \stream_get_contents($rLiteralStream);
|
||||||
|
$iAppendUid = $this->oImapTarget->MessageAppendStream(
|
||||||
|
$sTargetFolderName,
|
||||||
|
$rLiteralStream,
|
||||||
|
$iLiteralLen,
|
||||||
|
isset($aSourceFlags[$i]) ? $aSourceFlags[$i] : []
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)), $i, false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
$aFlags = $aFetchResponse[0]->GetFetchValue('FLAGS');
|
||||||
|
$iAppendUid = $this->oImapTarget->MessageAppendStream(
|
||||||
|
$sTargetFolderName,
|
||||||
|
$rLiteralStream,
|
||||||
|
$iLiteralLen,
|
||||||
|
$aFlags
|
||||||
|
);
|
||||||
|
if ($iAppendUid && $aFlags) {
|
||||||
|
$this->MessageStoreFlag(
|
||||||
|
new SequenceSet([$iAppendUid]),
|
||||||
|
$aFlags,
|
||||||
|
\MailSo\Imap\Enumerations\StoreAction::ADD_FLAGS_SILENT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
\SnappyMail\HTTP\Stream::JSON([
|
||||||
|
'index' => $fi,
|
||||||
|
'message' => $i
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,6 +22,9 @@
|
||||||
<td class="e-action">
|
<td class="e-action">
|
||||||
<span class="account-name" data-bind="text: displayName"></span>
|
<span class="account-name" data-bind="text: displayName"></span>
|
||||||
</td>
|
</td>
|
||||||
|
<!--
|
||||||
|
<td><span class="icon-import" data-bind="click: importAll"></span></td>
|
||||||
|
-->
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete}, click: function(oAccount) { $root.deleteAccount(oAccount); }"
|
<a class="btn btn-small btn-danger button-confirm-delete" data-bind="css: {'delete-access': askDelete}, click: function(oAccount) { $root.deleteAccount(oAccount); }"
|
||||||
data-i18n="GLOBAL/ARE_YOU_SURE"></a>
|
data-i18n="GLOBAL/ARE_YOU_SURE"></a>
|
||||||
|
|
Loading…
Add table
Reference in a new issue