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: * @property Settings $oModuleSettings
16: *
17: * @package Modules
18: */
19: class Module extends \Aurora\System\Module\AbstractModule
20: {
21: protected $aRequireModules = ['Mail'];
22:
23: /**
24: * @var Manager
25: */
26: public $oManager = null;
27:
28: public $sScheduledFolderName = 'Scheduled';
29:
30: public $oMailModuleAccountsManager = null;
31:
32: public $oMailModuleMailManager = null;
33:
34: /**
35: * @return Module
36: */
37: public static function getInstance()
38: {
39: return parent::getInstance();
40: }
41:
42: /**
43: * @return Module
44: */
45: public static function Decorator()
46: {
47: return parent::Decorator();
48: }
49:
50: /**
51: * @return Settings
52: */
53: public function getModuleSettings()
54: {
55: return $this->oModuleSettings;
56: }
57:
58: public function init()
59: {
60: $this->oManager = new Manager($this);
61:
62: $this->subscribeEvent('Mail::GetFolders::before', array($this, 'onBeforeGetFolders'));
63: $this->subscribeEvent('Mail::GetFolders::after', array($this, 'onAfterGetFolders'));
64: $this->subscribeEvent('Mail::GetMessage::after', array($this, 'onAfterGetMessage'));
65: $this->subscribeEvent('Mail::MoveMessages::after', array($this, 'onMoveOrDeleteMessages'));
66: $this->subscribeEvent('Mail::DeleteMessages::after', array($this, 'onMoveOrDeleteMessages'));
67: $this->subscribeEvent('Mail::DeleteAccount::after', array($this, 'onAfterDeleteAccount'));
68:
69: $this->denyMethodsCallByWebApi([
70: 'GetMessagesForSend',
71: 'GetMessage',
72: 'RemoveMessage'
73: ]);
74:
75: $oMailModule = \Aurora\Modules\Mail\Module::getInstance();
76: $this->oMailModuleAccountsManager = $oMailModule->getAccountsManager();
77: $this->oMailModuleMailManager = $oMailModule->getMailManager();
78: }
79:
80: protected function getScheduledFolderFullName($oAccount)
81: {
82: $oNamespace = \Aurora\Modules\Mail\Module::getInstance()->getMailManager()->getFoldersNamespace($oAccount);
83: $sNamespace = $oNamespace ? $oNamespace->GetPersonalNamespace() : '';
84: return $sNamespace . $this->sScheduledFolderName;
85: }
86:
87: public function onBeforeGetFolders(&$aArgs, &$mResult)
88: {
89: $iAccountID = $aArgs['AccountID'];
90: $oAccount = $this->oMailModuleAccountsManager->getAccountById($iAccountID);
91: if ($oAccount) {
92: $sScheduledFolderFullName = $this->getScheduledFolderFullName($oAccount);
93: $aResult = \Aurora\Modules\Mail\Module::Decorator()->GetRelevantFoldersInformation($iAccountID, array($sScheduledFolderFullName), false);
94: if (empty($aResult['Counts'])) {
95: try {
96: \Aurora\Modules\Mail\Module::Decorator()->CreateFolder($iAccountID, $sScheduledFolderFullName, '', '/');
97: } catch (\Exception $oException) {
98: }
99: }
100: }
101: }
102:
103: public function onAfterGetFolders(&$aArgs, &$mResult)
104: {
105: $oFolderCollection = &$mResult['Folders'];
106:
107: $aList = &$oFolderCollection->GetAsArray();
108: $iSentPos = 0;
109: $sNamespace = $oFolderCollection->getNamespace();
110: if (!empty($sNamespace)) {
111: $sNamespaceFolderName = substr($sNamespace, 0, -1);
112: $oNamespaceFolder = &$oFolderCollection->getFolder($sNamespaceFolderName, true);
113: if ($oNamespaceFolder) {
114: $aList = &$oNamespaceFolder->getSubFolders()->GetAsArray();
115: }
116: }
117:
118: foreach ($aList as $iKey => $oFolder) {
119: if ($oFolder->getType() == \Aurora\Modules\Mail\Enums\FolderType::Sent) {
120: $iSentPos = $iKey;
121: break;
122: }
123: }
124:
125: $oScheduledFolder = null;
126: foreach ($aList as $iKey => $oFolder) {
127: if ($oFolder->getName() === $this->sScheduledFolderName) {
128: $oScheduledFolder = $oFolder;
129: unset($aList[$iKey]);
130: break;
131: }
132: }
133:
134: if ($oScheduledFolder) {
135: array_splice($aList, $iSentPos + 1, 0, [$oScheduledFolder]);
136: }
137: }
138:
139: public function onAfterGetMessage($aArgs, &$mResult)
140: {
141: if ($mResult instanceof \Aurora\Modules\Mail\Classes\Message) {
142: $iAccountID = $aArgs['AccountID'];
143: $aMessage = $this->oManager->getMessage($iAccountID, $mResult->getFolder(), $mResult->getUid());
144: if ($aMessage !== false) {
145: $mResult->addExtend('ScheduleTimestamp', ['ScheduleTimestamp' => $aMessage['ScheduleTimestamp']]);
146: }
147: }
148: }
149:
150: public function onMoveOrDeleteMessages($aArgs, &$mResult)
151: {
152: if ($mResult) {
153: $iAccountID = $aArgs['AccountID'];
154: $oAccount = $this->oMailModuleAccountsManager->getAccountById($iAccountID);
155: $sFolder = $aArgs['Folder'];
156: if ($sFolder === $this->getScheduledFolderFullName($oAccount)) {
157: $sUids = $aArgs['Uids'];
158: $aUids = \Aurora\System\Utils::ExplodeIntUids((string) $sUids);
159: foreach ($aUids as $sUid) {
160: $this->oManager->removeMessage($iAccountID, $sFolder, $sUid);
161: }
162: }
163: }
164: }
165: public function onAfterDeleteAccount($aArgs, &$mResult)
166: {
167: if ($mResult) {
168: $this->oManager->removeAccountMessages($aArgs['AccountID']);
169: }
170: }
171:
172: public function GetSettings()
173: {
174: return [
175: 'ScheduledFolderName' => $this->sScheduledFolderName,
176: 'PredefinedSchedule' => $this->oModuleSettings->PredefinedSchedule
177: ];
178: }
179:
180: public function SaveScheduledMessage(
181: $AccountID,
182: $Fetcher = null,
183: $Alias = null,
184: $IdentityID = 0,
185: $To = "",
186: $Cc = "",
187: $Bcc = "",
188: $Recipients = array(),
189: $Subject = "",
190: $Text = "",
191: $IsHtml = false,
192: $Importance = \MailSo\Mime\Enumerations\MessagePriority::NORMAL,
193: $SendReadingConfirmation = false,
194: $Attachments = array(),
195: $InReplyTo = "",
196: $References = "",
197: $Sensitivity = \MailSo\Mime\Enumerations\Sensitivity::NOTHING,
198: $DraftFolder = "",
199: $DraftUid = "",
200: $CustomHeaders = [],
201: $ScheduleDateTime = null
202: ) {
203: $iNewUid = 0;
204: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
205:
206: $oAccount = $this->oMailModuleAccountsManager->getAccountById($AccountID);
207:
208: \Aurora\Modules\Mail\Module::checkAccountAccess($oAccount);
209:
210: $oIdentity = $IdentityID !== 0 ? \Aurora\Modules\Mail\Module::getInstance()->getIdentitiesManager()->getIdentity($IdentityID, $AccountID) : null;
211: $oMessage = \Aurora\Modules\Mail\Module::Decorator()->BuildMessage(
212: $oAccount,
213: $To,
214: $Cc,
215: $Bcc,
216: $Subject,
217: $IsHtml,
218: $Text,
219: $Attachments,
220: null,
221: $InReplyTo,
222: $References,
223: $Importance,
224: $Sensitivity,
225: $SendReadingConfirmation,
226: $Fetcher,
227: $Alias,
228: false,
229: $oIdentity,
230: $CustomHeaders
231: );
232: if ($oMessage) {
233: $oMessage->SetDate($ScheduleDateTime);
234: $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
235: $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter($oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true);
236:
237: $FolderFullName = $this->getScheduledFolderFullName($oAccount);
238: $this->oMailModuleMailManager->appendMessageFromStream($oAccount, $rMessageStream, $FolderFullName, $iMessageStreamSize, $iNewUid);
239: $this->oMailModuleMailManager->setMessageFlag($oAccount, $FolderFullName, [$iNewUid], \MailSo\Imap\Enumerations\MessageFlag::SEEN, \Aurora\Modules\Mail\Enums\MessageStoreAction::Add);
240:
241: if (0 < strlen($DraftFolder) && 0 < strlen($DraftUid)) {
242: try {
243: $this->oMailModuleMailManager->deleteMessage($oAccount, $DraftFolder, array($DraftUid));
244: } catch (\Exception $oException) {
245: }
246: }
247:
248: $this->oManager->removeMessage($oAccount->Id, $FolderFullName, $iNewUid);
249: $this->oManager->addMessage($oAccount->Id, $FolderFullName, $iNewUid, $ScheduleDateTime);
250: }
251:
252: return $iNewUid;
253: }
254:
255: public function GetMessagesForSend($ScheduledTimestamp)
256: {
257: return $this->oManager->getMessagesForSend($ScheduledTimestamp);
258: }
259:
260: public function GetMessage($AccountID, $FolderFullName, $MessageUid)
261: {
262: return $this->oManager->getMessage($AccountID, $FolderFullName, $MessageUid);
263: }
264:
265: public function RemoveMessage($AccountID, $FolderFullName, $MessageUid)
266: {
267: return $this->oManager->removeMessage($AccountID, $FolderFullName, $MessageUid);
268: }
269: }
270: