1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\Modules\MailScheduledMessages;
9:
10: /**
11: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
12: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
13: * @copyright Copyright (c) 2023, Afterlogic Corp.
14: *
15: * @package Modules
16: */
17: class Module extends \Aurora\System\Module\AbstractModule
18: {
19: protected $aRequireModules = ['Mail'];
20:
21: public $oManager = null;
22:
23: public $sScheduledFolderName = 'Scheduled';
24:
25: public $oMailModuleAccountsManager = null;
26:
27: public $oMailModuleMailManager = null;
28:
29: public function init()
30: {
31: $this->oManager = new Manager($this);
32:
33: $this->subscribeEvent('Mail::GetFolders::before', array($this, 'onBeforeGetFolders'));
34: $this->subscribeEvent('Mail::GetFolders::after', array($this, 'onAfterGetFolders'));
35: $this->subscribeEvent('Mail::GetMessage::after', array($this, 'onAfterGetMessage'));
36: $this->subscribeEvent('Mail::MoveMessages::after', array($this, 'onMoveOrDeleteMessages'));
37: $this->subscribeEvent('Mail::DeleteMessages::after', array($this, 'onMoveOrDeleteMessages'));
38: $this->subscribeEvent('Core::CreateTables::after', array($this, 'onAfterCreateTables'));
39:
40: $this->denyMethodsCallByWebApi([
41: 'GetMessagesForSend',
42: 'GetMessage',
43: 'RemoveMessage'
44: ]);
45:
46: $oMailModule = \Aurora\Modules\Mail\Module::getInstance();
47: $this->oMailModuleAccountsManager = $oMailModule->getAccountsManager();
48: $this->oMailModuleMailManager = $oMailModule->getMailManager();
49: }
50:
51: protected function getScheduledFolderFullName($oAccount)
52: {
53: $oNamespace = \Aurora\Modules\Mail\Module::getInstance()->getMailManager()->getFoldersNamespace($oAccount);
54: $sNamespace = $oNamespace ? $oNamespace->GetPersonalNamespace() : '';
55: return $sNamespace . $this->sScheduledFolderName;
56: }
57:
58: public function onBeforeGetFolders(&$aArgs, &$mResult)
59: {
60: $iAccountID = $aArgs['AccountID'];
61: $oAccount = $this->oMailModuleAccountsManager->getAccountById($iAccountID);
62: if ($oAccount) {
63: $sScheduledFolderFullName = $this->getScheduledFolderFullName($oAccount);
64: $aResult = $this->oMailModuleMailManager->getFolderListInformation($oAccount, array($sScheduledFolderFullName), false);
65: if (empty($aResult)) {
66: try {
67: \Aurora\Modules\Mail\Module::Decorator()->CreateFolder($iAccountID, $sScheduledFolderFullName, '', '/');
68: } catch (\Exception $oException) {
69: }
70: }
71: }
72: }
73:
74: public function onAfterGetFolders(&$aArgs, &$mResult)
75: {
76: $oFolderCollection =& $mResult['Folders'];
77:
78: $aList =& $oFolderCollection->GetAsArray();
79: $iSentPos = 0;
80: $sNamespace = $oFolderCollection->getNamespace();
81: if (!empty($sNamespace)) {
82: $sNamespaceFolderName = substr($sNamespace, 0, -1);
83: $oNamespaceFolder =& $oFolderCollection->getFolder($sNamespaceFolderName, true);
84: if ($oNamespaceFolder) {
85: $aList =& $oNamespaceFolder->getSubFolders()->GetAsArray();
86: }
87: }
88:
89: foreach ($aList as $iKey => $oFolder) {
90: if ($oFolder->getType() == \Aurora\Modules\Mail\Enums\FolderType::Sent) {
91: $iSentPos = $iKey;
92: break;
93: }
94: }
95:
96: $oScheduledFolder = null;
97: foreach ($aList as $iKey => $oFolder) {
98: if ($oFolder->getName() === $this->sScheduledFolderName) {
99: $oScheduledFolder = $oFolder;
100: unset($aList[$iKey]);
101: break;
102: }
103: }
104:
105: if ($oScheduledFolder) {
106: array_splice($aList, $iSentPos + 1, 0, [$oScheduledFolder]);
107: }
108: }
109:
110: public function onAfterGetMessage($aArgs, &$mResult)
111: {
112: if ($mResult instanceof \Aurora\Modules\Mail\Classes\Message) {
113: $iAccountID = $aArgs['AccountID'];
114: $aMessage = $this->oManager->getMessage($iAccountID, $mResult->getFolder(), $mResult->getUid());
115: if ($aMessage !== false) {
116: $mResult->addExtend('ScheduleTimestamp', ['ScheduleTimestamp' => $aMessage['ScheduleTimestamp']]);
117: }
118: }
119: }
120:
121: public function onMoveOrDeleteMessages($aArgs, &$mResult)
122: {
123: if ($mResult) {
124: $iAccountID = $aArgs['AccountID'];
125: $oAccount = $this->oMailModuleAccountsManager->getAccountById($iAccountID);
126: $sFolder = $aArgs['Folder'];
127: if ($sFolder === $this->getScheduledFolderFullName($oAccount)) {
128: $sUids = $aArgs['Uids'];
129: $aUids = \Aurora\System\Utils::ExplodeIntUids((string) $sUids);
130: foreach ($aUids as $sUid) {
131: $this->oManager->removeMessage($iAccountID, $sFolder, $sUid);
132: }
133: }
134: }
135: }
136:
137: /**
138: * Creates tables required for module work. Called by event subscribe.
139: *
140: * @ignore
141: * @param array $aParams Parameters
142: */
143: public function onAfterCreateTables($aParams, &$mResult)
144: {
145: // if ($mResult)
146: // {
147: // $mResult = $this->oManager->createTablesFromFile();
148: // if ($mResult)
149: // {
150: // $mResult = $this->oManager->updateTables();
151: // }
152: // }
153: }
154:
155: public function GetSettings()
156: {
157: return [
158: 'ScheduledFolderName' => $this->sScheduledFolderName,
159: 'PredefinedSchedule' => $this->getConfig('PredefinedSchedule', [])
160: ];
161: }
162:
163: public function SaveScheduledMessage(
164: $AccountID,
165: $Fetcher = null,
166: $Alias = null,
167: $IdentityID = 0,
168: $To = "",
169: $Cc = "",
170: $Bcc = "",
171: $Recipients = array(),
172: $Subject = "",
173: $Text = "",
174: $IsHtml = false,
175: $Importance = \MailSo\Mime\Enumerations\MessagePriority::NORMAL,
176: $SendReadingConfirmation = false,
177: $Attachments = array(),
178: $InReplyTo = "",
179: $References = "",
180: $Sensitivity = \MailSo\Mime\Enumerations\Sensitivity::NOTHING,
181: $DraftFolder = "",
182: $DraftUid = "",
183: $CustomHeaders = [],
184: $ScheduleDateTime = null
185: )
186: {
187: $iNewUid = 0;
188: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
189:
190: $oAccount = $this->oMailModuleAccountsManager->getAccountById($AccountID);
191:
192: \Aurora\Modules\Mail\Module::checkAccess($oAccount);
193:
194: $oIdentity = $IdentityID !== 0 ? \Aurora\Modules\Mail\Module::getInstance()->getIdentitiesManager()->getIdentity($IdentityID) : null;
195: $oMessage = \Aurora\Modules\Mail\Module::Decorator()->BuildMessage(
196: $oAccount,
197: $To,
198: $Cc,
199: $Bcc,
200: $Subject,
201: $IsHtml,
202: $Text,
203: $Attachments,
204: null,
205: $InReplyTo,
206: $References,
207: $Importance,
208: $Sensitivity,
209: $SendReadingConfirmation,
210: $Fetcher,
211: $Alias,
212: false,
213: $oIdentity,
214: $CustomHeaders
215: );
216: if ($oMessage) {
217: $oMessage->SetDate($ScheduleDateTime);
218: $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
219: $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter($oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true);
220:
221: $FolderFullName = $this->getScheduledFolderFullName($oAccount);
222: $this->oMailModuleMailManager->appendMessageFromStream($oAccount, $rMessageStream, $FolderFullName, $iMessageStreamSize, $iNewUid);
223: $this->oMailModuleMailManager->setMessageFlag($oAccount, $FolderFullName, [$iNewUid], \MailSo\Imap\Enumerations\MessageFlag::SEEN, \Aurora\Modules\Mail\Enums\MessageStoreAction::Add);
224:
225: if (0 < strlen($DraftFolder) && 0 < strlen($DraftUid)) {
226: try {
227: $this->oMailModuleMailManager->deleteMessage($oAccount, $DraftFolder, array($DraftUid));
228: } catch (\Exception $oException) {
229: }
230: }
231:
232: $this->oManager->removeMessage($oAccount->Id, $FolderFullName, $iNewUid);
233: $this->oManager->addMessage($oAccount->Id, $FolderFullName, $iNewUid, $ScheduleDateTime);
234: }
235:
236: return $iNewUid;
237: }
238:
239: public function GetMessagesForSend($ScheduledTimestamp)
240: {
241: return $this->oManager->getMessagesForSend($ScheduledTimestamp);
242: }
243:
244: public function GetMessage($AccountID, $FolderFullName, $MessageUid)
245: {
246: return $this->oManager->getMessage($AccountID, $FolderFullName, $MessageUid);
247: }
248:
249: public function RemoveMessage($AccountID, $FolderFullName, $MessageUid)
250: {
251: return $this->oManager->removeMessage($AccountID, $FolderFullName, $MessageUid);
252: }
253: }
254: