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: use Aurora\System\EventEmitter;
9:
10: if (PHP_SAPI !== 'cli') {
11: exit("Use the console for running this script");
12: }
13:
14: require_once \dirname(__file__) . "/../../../system/autoload.php";
15: \Aurora\System\Api::Init(true);
16:
17: set_time_limit(0);
18: date_default_timezone_set("UTC");
19:
20: $oMailScheduledMessagesModule = \Aurora\Modules\MailScheduledMessages\Module::Decorator();
21: $oMailModule = \Aurora\Modules\Mail\Module::getInstance();
22:
23: $iTime = time();
24: $aMessagesForSend = [];
25:
26: if ($oMailScheduledMessagesModule) {
27: $aMessagesForSend = $oMailScheduledMessagesModule->GetMessagesForSend($iTime);
28: foreach ($aMessagesForSend as $aMessageForSend) {
29: $mSendResult = false;
30: $directMessageToStreamResult = false;
31: $oAccount = $oMailModule->GetAccount($aMessageForSend['AccountId']);
32:
33: try {
34: $directMessageToStreamResult = $oMailModule->getMailManager()->directMessageToStream(
35: $oAccount,
36: function ($rMessageResourse, $sContentType, $sFileName, $sMimeIndex = '') use ($oAccount, &$mSendResult) {
37: if (\is_resource($rMessageResourse)) {
38: $mSendResult = sendMessage($oAccount, $rMessageResourse);
39: \fclose($rMessageResourse);
40: }
41: },
42: $aMessageForSend['FolderFullName'],
43: $aMessageForSend['MessageUid']
44: );
45: } catch (\Exception $oEx) {
46: \Aurora\System\Api::LogException($oEx);
47: }
48:
49: if ($directMessageToStreamResult && $mSendResult) {
50: $aFolders = $oMailModule->getMailManager()->getFolders($oAccount);
51: $sSentFolder = '';
52: $aFolders->foreachWithSubFolders(function ($oFolder) use (&$sSentFolder) {
53: if ($oFolder->getType() == \Aurora\Modules\Mail\Enums\FolderType::Sent) {
54: $sSentFolder = $oFolder->getRawFullName();
55: return;
56: }
57: });
58:
59: if (!empty($sSentFolder)) {
60: \Aurora\Modules\Mail\Module::Decorator()->MoveMessages($aMessageForSend['AccountId'], $aMessageForSend['FolderFullName'], $sSentFolder, $aMessageForSend['MessageUid']);
61: }
62: $oMailScheduledMessagesModule->RemoveMessage($aMessageForSend['AccountId'], $aMessageForSend['FolderFullName'], $aMessageForSend['MessageUid']);
63: } else {
64: // $oMailScheduledMessagesModule->RemoveMessage($aMessageForSend['AccountId'], $aMessageForSend['FolderFullName'], $aMessageForSend['MessageUid']);
65: }
66: }
67: }
68:
69: function getRcpt($aHeaders)
70: {
71: $oResult = \MailSo\Mime\EmailCollection::NewInstance();
72: if (isset($aHeaders['To'])) {
73: $oResult->MergeWithOtherCollection(
74: \MailSo\Mime\EmailCollection::NewInstance(\ltrim($aHeaders['To']))
75: );
76: }
77: if (isset($aHeaders['Cc'])) {
78: $oResult->MergeWithOtherCollection(
79: \MailSo\Mime\EmailCollection::NewInstance(\ltrim($aHeaders['Cc']))
80: );
81: }
82: if (isset($aHeaders['Bcc'])) {
83: $oResult->MergeWithOtherCollection(
84: \MailSo\Mime\EmailCollection::NewInstance(\ltrim($aHeaders['Bcc']))
85: );
86: }
87:
88: return $oResult->Unique();
89: }
90:
91: function getHeaders($rResource)
92: {
93: $sRawHeaders = '';
94: while (trim($line = fgets($rResource)) !== '') {
95: $sRawHeaders .= $line;
96: }
97:
98: $aHeaders = \explode("\n", \str_replace("\r", '', $sRawHeaders));
99:
100: $sName = null;
101: $sValue = null;
102: $aResult = [];
103: foreach ($aHeaders as $sHeadersValue) {
104: if (0 === strlen($sHeadersValue)) {
105: continue;
106: }
107:
108: $sFirstChar = \substr($sHeadersValue, 0, 1);
109: if ($sFirstChar !== ' ' && $sFirstChar !== "\t" && false === \strpos($sHeadersValue, ':')) {
110: continue;
111: } elseif (null !== $sName && ($sFirstChar === ' ' || $sFirstChar === "\t")) {
112: $sValue = \is_null($sValue) ? '' : $sValue;
113:
114: if ('?=' === \substr(\rtrim($sHeadersValue), -2)) {
115: $sHeadersValue = \rtrim($sHeadersValue);
116: }
117:
118: if ('=?' === \substr(\ltrim($sHeadersValue), 0, 2)) {
119: $sHeadersValue = \ltrim($sHeadersValue);
120: }
121:
122: if ('=?' === \substr($sHeadersValue, 0, 2)) {
123: $sValue .= $sHeadersValue;
124: } else {
125: $sValue .= "\n" . $sHeadersValue;
126: }
127: } else {
128: if (null !== $sName) {
129: $aResult[$sName] = $sValue;
130:
131: $sName = null;
132: $sValue = null;
133: }
134:
135: $aHeaderParts = \explode(':', $sHeadersValue, 2);
136: $sName = $aHeaderParts[0];
137: $sValue = isset($aHeaderParts[1]) ? $aHeaderParts[1] : '';
138:
139: if ('?=' === \substr(\rtrim($sValue), -2)) {
140: $sValue = \rtrim($sValue);
141: }
142: }
143: }
144: if (null !== $sName) {
145: $aResult[$sName] = $sValue;
146: }
147:
148: return $aResult;
149: }
150:
151: function sendMessage($oAccount, $rStream)
152: {
153: if (!$oAccount || !$rStream) {
154: throw new \Aurora\System\Exceptions\InvalidArgumentException();
155: }
156:
157: $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
158:
159: $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
160: $rStream,
161: array($rMessageStream),
162: 8192,
163: true,
164: true,
165: true
166: );
167:
168: $oMailModule = \Aurora\Modules\Mail\Module::getInstance();
169: $oImapClient = &$oMailModule->getMailManager()->_getImapClient($oAccount);
170:
171: $mResult = false;
172: if (is_resource($rMessageStream)) {
173: $aHeaders = getHeaders($rMessageStream);
174: $oRcpt = getRcpt($aHeaders);
175:
176: if ($oRcpt && 0 < $oRcpt->Count()) {
177: $oServer = null;
178: try {
179: $oSettings = &\Aurora\System\Api::GetSettings();
180: $iConnectTimeOut = $oSettings->SocketConnectTimeoutSeconds;
181: $iSocketTimeOut = $oSettings->SocketGetTimeoutSeconds;
182: $bVerifySsl = !!$oSettings->SocketVerifySsl;
183:
184: $oSmtpClient = \MailSo\Smtp\SmtpClient::NewInstance();
185: $oSmtpClient->SetTimeOuts($iConnectTimeOut, $iSocketTimeOut);
186:
187: $oLogger = $oImapClient->Logger();
188: if ($oLogger) {
189: $oSmtpClient->SetLogger($oLogger);
190: }
191:
192: $oServer = $oAccount->getServer();
193: $iSecure = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT;
194: if ($oServer->OutgoingUseSsl) {
195: $iSecure = \MailSo\Net\Enumerations\ConnectionSecurityType::SSL;
196: }
197:
198: $sEhlo = \MailSo\Smtp\SmtpClient::EhloHelper();
199:
200: $oSmtpClient->Connect($oServer->OutgoingServer, $oServer->OutgoingPort, $sEhlo, $iSecure, $bVerifySsl);
201:
202: if ($oServer->SmtpAuthType === \Aurora\Modules\Mail\Enums\SmtpAuthType::UseUserCredentials) {
203: $oSmtpClient->Login($oAccount->IncomingLogin, $oAccount->getPassword());
204: } elseif ($oServer->SmtpAuthType === \Aurora\Modules\Mail\Enums\SmtpAuthType::UseSpecifiedCredentials) {
205: $oSmtpClient->Login($oServer->SmtpLogin, $oServer->SmtpPassword);
206: }
207:
208: $oSmtpClient->MailFrom($oAccount->Email);
209:
210: $aRcpt = &$oRcpt->GetAsArray();
211:
212: foreach ($aRcpt as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) {
213: $sRcptEmail = $oEmail->GetEmail();
214: $oSmtpClient->Rcpt($sRcptEmail);
215: }
216:
217: $aEmails = array();
218: $oRcpt->ForeachList(function ($oEmail) use (&$aEmails) {
219: $aEmails[strtolower($oEmail->GetEmail(true))] = trim($oEmail->GetDisplayName());
220: });
221:
222: if (\is_array($aEmails)) {
223: $aArgs = ['IdUser' => $oAccount->IdUser, 'Emails' => $aEmails];
224: EventEmitter::getInstance()->emit('Mail', 'AfterUseEmails', $aArgs);
225: }
226:
227: \rewind($rMessageStream);
228: $oSmtpClient->DataWithStream($rMessageStream);
229:
230: $oSmtpClient->LogoutAndDisconnect();
231: \fclose($rMessageStream);
232: } catch (\MailSo\Net\Exceptions\ConnectionException $oException) {
233: throw new \Aurora\Modules\Mail\Exceptions\Exception(
234: \Aurora\Modules\Mail\Enums\ErrorCodes::CannotConnectToMailServer,
235: $oException,
236: $oException->getMessage()
237: );
238: } catch (\MailSo\Smtp\Exceptions\LoginException $oException) {
239: throw new \Aurora\Modules\Mail\Exceptions\Exception(
240: \Aurora\Modules\Mail\Enums\ErrorCodes::CannotLoginCredentialsIncorrect,
241: $oException,
242: $oException->getMessage()
243: );
244: } catch (\MailSo\Smtp\Exceptions\NegativeResponseException $oException) {
245: throw new \Aurora\Modules\Mail\Exceptions\Exception(
246: \Aurora\Modules\Mail\Enums\ErrorCodes::CannotSendMessage,
247: $oException,
248: $oException->getMessage()
249: );
250: } catch (\MailSo\Smtp\Exceptions\MailboxUnavailableException $oException) {
251: $iErrorCode = ($oServer && $oServer->SmtpAuthType === \Aurora\Modules\Mail\Enums\SmtpAuthType::UseUserCredentials)
252: ? \Aurora\Modules\Mail\Enums\ErrorCodes::CannotSendMessageToRecipients
253: : \Aurora\Modules\Mail\Enums\ErrorCodes::CannotSendMessageToExternalRecipients;
254: throw new \Aurora\Modules\Mail\Exceptions\Exception(
255: $iErrorCode,
256: $oException,
257: $oException->getMessage()
258: );
259: }
260:
261: $mResult = true;
262: } else {
263: throw new \Aurora\Modules\Mail\Exceptions\Exception(\Aurora\Modules\Mail\Enums\ErrorCodes::CannotSendMessageInvalidRecipients);
264: }
265: }
266:
267: return $mResult;
268: }
269: