snappymail/plugins/mailbox-detect/index.php

228 lines
6.9 KiB
PHP

<?php
use MailSo\Imap\Enumerations\FolderType;
use MailSo\Imap\Enumerations\MetadataKeys;
class MailboxDetectPlugin extends \RainLoop\Plugins\AbstractPlugin
{
const
NAME = 'MailboxDetect',
AUTHOR = 'SnappyMail',
URL = 'https://snappymail.eu/',
VERSION = '2.6',
RELEASE = '2023-03-13',
REQUIRED = '2.27.0',
CATEGORY = 'General',
LICENSE = 'MIT',
DESCRIPTION = 'Autodetect system folders and/or create them when needed';
public function Init() : void
{
$this->addHook('json.after-folders', 'AfterFolders');
}
protected function configMapping() : array
{
return array(
\RainLoop\Plugins\Property::NewInstance('autocreate_system_folders')->SetLabel('Autocreate system folders')
->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL)
->SetDefaultValue(false),
);
}
protected function Logger() : \MailSo\Log\Logger
{
return $this->Manager()->Actions()->Logger();
}
public function AfterFolders(array &$aResponse)
{
if (!empty($aResponse['Result']['@Collection'])) {
$oActions = \RainLoop\Api::Actions();
$oAccount = $oActions->getAccountFromToken();
if (!$oAccount) {
$this->Logger()->Write('No Account');
return;
}
$oSettingsLocal = $oActions->SettingsProvider(true)->Load($oAccount);
$roles = [
'inbox' => false,
'sent' => !!$oSettingsLocal->GetConf('SentFolder', ''),
'drafts' => !!$oSettingsLocal->GetConf('DraftsFolder', ''),
'junk' => !!$oSettingsLocal->GetConf('JunkFolder', ''),
'trash' => !!$oSettingsLocal->GetConf('TrashFolder', ''),
'archive' => !!$oSettingsLocal->GetConf('ArchiveFolder', '')
];
$types = [
FolderType::SENT => 'sent',
FolderType::DRAFTS => 'drafts',
FolderType::JUNK => 'junk',
FolderType::TRASH => 'trash',
FolderType::ARCHIVE => 'archive'
];
$found = [
'inbox' => [],
'sent' => [],
'drafts' => [],
'junk' => [],
'trash' => [],
'archive' => []
];
$aMap = $this->systemFoldersNames($oAccount);
$sDelimiter = '';
foreach ($aResponse['Result']['@Collection'] as $i => $folder) {
$sDelimiter || ($sDelimiter = $folder['delimiter']);
if ($folder['role']) {
$roles[$folder['role']] = true;
} else if (\in_array('\\sentmail', $folder['attributes'])) {
$found['sent'][] = $i;
} else if (\in_array('\\spam', $folder['attributes'])) {
$found['junk'][] = $i;
} else if (\in_array('\\bin', $folder['attributes'])) {
$found['trash'][] = $i;
} else if (\in_array('\\starred', $folder['attributes'])) {
$found['flagged'][] = $i;
} else {
// Kolab
$kolab = $folder['metadata'][MetadataKeys::KOLAB_CTYPE]
?? $folder['metadata'][MetadataKeys::KOLAB_CTYPE_SHARED]
?? '';
if ('mail.inbox' === $kolab) {
$found['inbox'][] = $i;
} else if ('mail.sentitems' === $kolab /*|| 'mail.outbox' === $kolab*/) {
$found['sent'][] = $i;
} else if ('mail.drafts' === $kolab) {
$found['drafts'][] = $i;
} else if ('mail.junkemail' === $kolab) {
$found['junk'][] = $i;
} else if ('mail.wastebasket' === $kolab) {
$found['trash'][] = $i;
} else {
$iFolderType = 0;
if (isset($aMap[$folder['fullName']])) {
$iFolderType = $aMap[$folder['fullName']];
} else if (isset($aMap[$folder['name']]) || isset($aMap["INBOX{$folder['delimiter']}{$folder['name']}"])) {
$iFolderType = $aMap[$folder['name']];
}
if ($iFolderType && isset($types[$iFolderType])) {
$found[$types[$iFolderType]][] = $i;
}
}
}
}
foreach ($roles as $role => $hasRole) {
if ($hasRole) {
unset($found[$role]);
}
}
if ($found) {
foreach ($found as $role => $folders) {
if (isset($folders[0])) {
// Set the first as default
$aFolder = &$aResponse['Result']['@Collection'][$folders[0]];
$this->Logger()->Write("Set {$role} mailbox to {$aFolder['fullName']}");
$aFolder['role'] = $role;
} else if ($this->Config()->Get('plugin', 'autocreate_system_folders', false)) {
try
{
$sParent = \substr($aResponse['Result']['namespace'], 0, -1);
$sFolderNameToCreate = \ucfirst($role);
/*
$this->Manager()->RunHook('filter.folders-system-types', array($oAccount, &$aList));
$iPos = \strrpos($sFolderNameToCreate, $sDelimiter);
if (false !== $iPos) {
$mNewParent = \substr($sFolderNameToCreate, 0, $iPos);
$mNewFolderNameToCreate = \substr($sFolderNameToCreate, $iPos + 1);
if (\strlen($mNewFolderNameToCreate)) {
$sFolderNameToCreate = $mNewFolderNameToCreate;
}
if (\strlen($mNewParent)) {
$sParent = \strlen($sParent) ? $sParent.$sDelimiter.$mNewParent : $mNewParent;
}
}
*/
$this->Logger()->Write("Create {$role} mailbox {$sFolderNameToCreate}");
$aFolder = $oActions->MailClient()->FolderCreate(
$sFolderNameToCreate,
$sParent,
true,
$sDelimiter
)->jsonSerialize();
$aFolder['role'] = $role;
$aResponse['Result']['@Collection'][] = $aFolder;
}
catch (\Throwable $oException)
{
$this->Logger()->WriteException($oException);
}
} else {
$this->Logger()->Write("Mailbox for {$role} not created");
}
}
}
}
}
/**
* @staticvar array $aCache
*/
private function systemFoldersNames(\RainLoop\Model\Account $oAccount) : array
{
static $aCache = null;
if (null === $aCache) {
$aCache = array(
'Sent' => FolderType::SENT,
'Send' => FolderType::SENT,
'Outbox' => FolderType::SENT,
'Out box' => FolderType::SENT,
'Sent Item' => FolderType::SENT,
'Sent Items' => FolderType::SENT,
'Send Item' => FolderType::SENT,
'Send Items' => FolderType::SENT,
'Sent Mail' => FolderType::SENT,
'Sent Mails' => FolderType::SENT,
'Send Mail' => FolderType::SENT,
'Send Mails' => FolderType::SENT,
'Drafts' => FolderType::DRAFTS,
'Draft' => FolderType::DRAFTS,
'Draft Mail' => FolderType::DRAFTS,
'Draft Mails' => FolderType::DRAFTS,
'Drafts Mail' => FolderType::DRAFTS,
'Drafts Mails' => FolderType::DRAFTS,
'Junk' => FolderType::JUNK,
'Junk E-mail' => FolderType::JUNK,
'Spam' => FolderType::JUNK,
'Spams' => FolderType::JUNK,
'Bulk Mail' => FolderType::JUNK,
'Bulk Mails' => FolderType::JUNK,
'Trash' => FolderType::TRASH,
'Deleted' => FolderType::TRASH,
'Deleted Items' => FolderType::TRASH,
'Bin' => FolderType::TRASH,
'Archive' => FolderType::ARCHIVE,
'Archives' => FolderType::ARCHIVE,
'All' => FolderType::ALL,
'All Mail' => FolderType::ALL,
'All Mails' => FolderType::ALL,
);
$aNewCache = array();
foreach ($aCache as $sKey => $iType) {
$aNewCache[$sKey] = $iType;
$aNewCache[\str_replace(' ', '', $sKey)] = $iType;
}
$aCache = $aNewCache;
$this->Manager()->RunHook('filter.system-folders-names', array($oAccount, &$aCache));
}
return $aCache;
}
}