3namespace Bitrix\Main\Mail;
7use Bitrix\Main\Engine\CurrentUser;
8use Bitrix\Main\ORM\Data\UpdateResult;
9use Bitrix\Main\Localization\Loc;
10use Bitrix\Main\Mail\Internal\SenderTable;
12use Bitrix\Main\Mail\Sender\UserSenderDataProvider;
17 private const MAIN_SENDER_SMTP_SERVER_PATTERN =
'/^([a-z0-9-]+\.)+[a-z0-9-]{2,20}$/i';
27 $checkResult = self::checkSenderNameCharacters(
$fields[
'NAME']);
28 if (!$checkResult->isSuccess())
30 'errors' => $checkResult->getErrorCollection(),
45 if (empty(
$fields[
'IS_CONFIRMED']))
48 $fields[
'OPTIONS'][
'confirm_time'] = time();
58 if (empty(
$fields[
'IS_CONFIRMED']))
60 $mailEventFields =
array(
61 'DEFAULT_EMAIL_FROM' =>
$fields[
'EMAIL'],
63 'MESSAGE_SUBJECT' => Loc::getMessage(
'MAIN_MAIL_CONFIRM_MESSAGE_SUBJECT'),
64 'CONFIRM_CODE' => mb_strtoupper(
$fields[
'OPTIONS'][
'confirm_code']),
67 if (!empty($smtpConfig))
79 \CEvent::sendImmediate(
'MAIN_MAIL_CONFIRM_CODE',
SITE_ID, $mailEventFields);
83 if (isset(
$fields[
'OPTIONS'][
'__replaces']) &&
$fields[
'OPTIONS'][
'__replaces'] > 0)
86 (
int)
$fields[
'OPTIONS'][
'__replaces']
91 return [
'senderId' => $senderId,
'confirmed' => !empty(
$fields[
'IS_CONFIRMED'])];
99 if ($checkSenderAccess)
101 $checkResult = self::canEditSender($senderId);
102 if (!$checkResult->isSuccess())
104 $result->addErrors($checkResult->getErrors());
112 if (!empty(
$fields[
'EMAIL']) &&
$fields[
'EMAIL'] !== $sender[
'EMAIL'])
114 $updateFields[
'EMAIL'] = (string)
$fields[
'EMAIL'];
117 if (!empty(
$fields[
'IS_PUBLIC']) &&
$fields[
'IS_PUBLIC'] !== $sender[
'IS_PUBLIC'])
119 $updateFields[
'IS_PUBLIC'] = (int)
$fields[
'IS_PUBLIC'] === 1 ? 1 : 0;
122 if (!empty(
$fields[
'OPTIONS'][
'smtp']) && empty(
$fields[
'OPTIONS'][
'smtp'][
'password']))
124 $fields[
'OPTIONS'][
'smtp'][
'password'] = $sender[
'OPTIONS'][
'smtp'][
'password'];
127 !empty(
$fields[
'OPTIONS'][
'smtp'])
128 &&
$fields[
'OPTIONS'][
'smtp'] !== $sender[
'OPTIONS'][
'smtp']
131 $smtp =
$fields[
'OPTIONS'][
'smtp'];
132 $checkResult = self::prepareSmtpConfigForSender($smtp);
133 if (!$checkResult->isSuccess())
135 $result->addErrors($checkResult->getErrors());
139 $sender[
'OPTIONS'][
'smtp'] = $smtp;
140 $updateFields[
'OPTIONS'] = $sender[
'OPTIONS'];
145 &&
$fields[
'NAME'] !== $sender[
'NAME']
149 $checkResult = self::checkSenderNameCharacters(
$name);
150 if (!$checkResult->isSuccess())
152 $result->addErrors($checkResult->getErrors());
159 $result = \Bitrix\Mail\MailboxTable::update($sender[
'PARENT_ID'], [
'USERNAME' =>
$name]);
165 $updateFields[
'NAME'] =
$name;
168 if (!empty($updateFields))
172 if (!empty($updateFields[
'OPTIONS'][
'smtp'][
'limit']))
174 self::setEmailLimit($sender[
'EMAIL'], $updateFields[
'OPTIONS'][
'smtp'][
'limit']);
190 if (empty(
$fields[
'IS_CONFIRMED']) && !empty(
$fields[
'OPTIONS'][
'smtp']))
192 $smtpConfig =
$fields[
'OPTIONS'][
'smtp'];
195 'host' => $smtpConfig[
'server'],
196 'port' => $smtpConfig[
'port'],
197 'protocol' => $smtpConfig[
'protocol'],
198 'login' => $smtpConfig[
'login'],
199 'password' => $smtpConfig[
'password'],
200 'isOauth' => $smtpConfig[
'isOauth'] ??
false,
203 if ($smtpConfig->canCheck())
207 $fields[
'IS_CONFIRMED'] =
true;
219 '@ID' => (
array) $ids,
223 while ($item =
$res->fetch())
228 'IS_CONFIRMED' =>
true,
232 if (isset($item[
'OPTIONS'][
'__replaces']) && $item[
'OPTIONS'][
'__replaces'] > 0)
235 (
int) $item[
'OPTIONS'][
'__replaces']
251 '=PARENT_MODULE_ID' =>
'mail',
252 '=PARENT_ID' => $mailboxId,
258 self::delete([(
int)$sender[
'ID']]);
262 public static function delete(
array $sendersId): void
264 foreach ($sendersId as $senderId)
266 $id = (int)$senderId;
280 $aliasesForPossibleDeletion = [];
281 if (!empty($currentSender[
'OPTIONS'][
'smtp'][
'server']) && empty(self::getPublicSmtpSenderByEmail($currentSender[
'EMAIL'], $id)) && $currentSender[
'USER_ID'])
285 '=EMAIL' => $currentSender[
'EMAIL'],
286 '=USER_ID' => $currentSender[
'USER_ID'],
290 while ($sender =
$res->fetch())
292 $aliasesForPossibleDeletion[$sender[
'USER_ID']][] = $sender;
296 if (!$aliasesForPossibleDeletion)
301 foreach ($aliasesForPossibleDeletion as
$userId => $aliases)
303 if (self::hasUserAvailableSmtpSenderByEmail($currentSender[
'EMAIL'],
$userId,
true))
308 foreach ($aliases as $alias)
262 public static function delete(
array $sendersId): void {
…}
318 $cache = new \CPHPCache();
319 $cache->clean(
$email,
'/main/mail/smtp');
324 static $smtp =
array();
326 if (!isset($smtp[
$email]))
330 $cache = new \CPHPCache();
332 if ($cache->initCache(30*24*3600,
$email,
'/main/mail/smtp'))
340 'IS_CONFIRMED' =>
true,
347 while ($item =
$res->fetch())
349 if (!empty($item[
'OPTIONS'][
'smtp'][
'server']) && empty($item[
'OPTIONS'][
'smtp'][
'encrypted']))
351 $config = $item[
'OPTIONS'][
'smtp'];
356 $cache->startDataCache();
366 'protocol' =>
$config[
'protocol'],
368 'password' =>
$config[
'password'],
369 'isOauth' =>
$config[
'isOauth'],
391 $address = new \Bitrix\Main\Mail\Address(
$email);
393 if (!$address->validate())
398 $email = $address->getEmail();
399 static $mailLimit =
array();
401 if (!isset($mailLimit[
$email]))
403 $cache = new \CPHPCache();
405 if ($cache->initCache(3600,
$email,
'/main/mail/limit'))
407 $mailLimit[
$email] = $cache->getVars();
413 'IS_CONFIRMED' =>
true,
421 while ($item =
$res->fetch())
423 if ($item[
'OPTIONS'][
'smtp'][
'limit'] !==
null)
425 $limit = (int)$item[
'OPTIONS'][
'smtp'][
'limit'];
430 $mailLimit[
$email] = $limit;
432 $cache->startDataCache();
433 $cache->endDataCache($mailLimit[
$email]);
453 $address = new \Bitrix\Main\Mail\Address(
$email);
455 if (!$address->validate())
460 $email = $address->getEmail();
462 $cache = new \CPHPCache();
463 $cache->clean(
$email,
'/main/mail/limit');
467 'IS_CONFIRMED' =>
true,
481 while ($item =
$res->fetch())
483 $oldLimit = (int)($item[
'OPTIONS'][
'smtp'][
'limit'] ?? 0);
484 if ($item[
'OPTIONS'][
'smtp'] && $limit !== $oldLimit)
486 $item[
'OPTIONS'][
'smtp'][
'limit'] = $limit;
489 if (!$quite && ($limit < $oldLimit || $oldLimit <= 0) && $updateResult->isSuccess())
491 $event =
new Event(
'main', self::MAIN_SENDER_SMTP_LIMIT_DECREASE, [
'EMAIL'=>
$email]);
510 $address = new \Bitrix\Main\Mail\Address(
$email);
512 if (!$address->validate())
517 $email = $address->getEmail();
518 $cache = new \CPHPCache();
519 $cache->clean(
$email,
'/main/mail/limit');
523 'IS_CONFIRMED' =>
true,
531 while ($item =
$res->fetch())
533 if (isset($item[
'OPTIONS'][
'smtp'][
'limit']))
535 unset($item[
'OPTIONS'][
'smtp'][
'limit']);
545 $headers =
$event->getParameter(
'arguments')->additional_headers;
558 if (preg_match(
'/X-Bitrix-Mail-SMTP-Host:/i', $headers))
564 $eolh = preg_replace(
'/([a-f0-9]{2})/i',
'\x\1', bin2hex($eol));
566 if (preg_match(sprintf(
'/(^|%1$s)From:(.+?)(%1$s([^\s]|$)|$)/is', $eolh), $headers,
$matches))
568 $address =
new Address(preg_replace(sprintf(
'/%s\s+/', $eolh),
'',
$matches[2]));
569 if ($address->validate())
571 if ($customSmtp = static::getCustomSmtp($address->getEmail()))
583 static $mailboxes =
array();
587 if (is_object(
$USER) &&
$USER->isAuthorized())
605 if (!empty($smtp[
'limit']))
607 $limit = (int)$smtp[
'limit'];
608 $limit = max($limit, 0);
611 $smtp[
'protocol'] = self::isSmtpsConfigured($smtp) ?
'smtps' :
'smtp';
614 'server' => mb_strtolower(trim($smtp[
'server'] ??
'')),
615 'port' => (int)($smtp[
'port'] ?? 0),
616 'protocol' => $smtp[
'protocol'],
617 'login' => $smtp[
'login'] ??
'',
618 'password' => $smtp[
'password'] ??
'',
619 'isOauth' => (bool)$smtp[
'isOauth'] ??
false,
620 'limit' => $limit ??
null,
623 if (!preg_match(self::MAIN_SENDER_SMTP_SERVER_PATTERN, $smtp[
'server']))
626 empty($smtp[
'server'])
627 ?
'MAIN_SENDER_EMPTY_SMTP_SERVER'
628 :
'MAIN_SENDER_INVALID_SMTP_SERVER'
634 if (!preg_match(
'/^[0-9]+$/i', $smtp[
'port']) || $smtp[
'port'] < 1 || $smtp[
'port'] > 65535)
638 ?
'MAIN_SENDER_EMPTY_SMTP_PORT'
639 :
'MAIN_SENDER_INVALID_SMTP_PORT'
645 if (empty($smtp[
'login']))
647 $errorMessage = Loc::getMessage(
'MAIN_SENDER_EMPTY_SMTP_LOGIN');
652 if (empty($smtp[
'password']))
654 $errorMessage = Loc::getMessage(
'MAIN_MAIL_CONFIRM_EMPTY_SMTP_PASSWORD');
659 if (preg_match(
'/^\^/', $smtp[
'password']))
661 $errorMessage = Loc::getMessage(
'MAIN_SENDER_INVALID_SMTP_PASSWORD');
667 'from' => $smtp[
'login'],
668 'host' => $smtp[
'server'],
669 'port' => $smtp[
'port'],
670 'protocol' => $smtp[
'protocol'],
671 'login' => $smtp[
'login'],
672 'password' => $smtp[
'password'],
673 'isOauth' => $smtp[
'isOauth'],
676 if ($smtpConfig->canCheck())
702 if (is_object(
$USER) &&
$USER->isAuthorized())
709 '=IS_CONFIRMED' =>
true,
712 '=PARENT_MODULE_ID' =>
'main',
719 while ($item =
$res->fetch())
721 if (!empty($item[
'OPTIONS'][
'smtp'][
'server']))
737 $result->addError(
new Error(Loc::getMessage(
'MAIN_MAIL_SENDER_UNKNOWN_SENDER_ERROR')));
742 $userId = (int)CurrentUser::get()->getId();
751 (
int)$sender[
'USER_ID'] !==
$userId
755 $result->addError(
new Error(Loc::getMessage(
'MAIN_MAIL_SENDER_EDIT_ERROR')));
767 '=IS_CONFIRMED' =>
true,
769 '=IS_PUBLIC' =>
true,
777 while ($item =
$res->fetch()) {
779 (!empty($item[
'OPTIONS'][
'smtp'][
'server']) && empty($item[
'OPTIONS'][
'smtp'][
'encrypted']))
792 if (self::getPublicSmtpSenderByEmail(
$email, onlyWithSmtp: $onlyWithSmtp))
804 foreach ($senders as $sender)
806 if (in_array($sender[
'type'],$requiredTypes) || !$onlyWithSmtp)
826 $pattern =
'/[^\p{L}\p{N}\p{Zs}\-.\'(),]+/u';
829 $result->addError(
new Error(Loc::getMessage(
'MAIN_MAIL_SENDER_INVALID_NAME')));
835 private static function isSmtpsConfigured(
array $smtpSettings): bool
838 ($smtpSettings[
'protocol'] ??
'') ===
'smtps'
839 || ($smtpSettings[
'ssl'] ??
'') ===
'Y'
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
static includeModule($moduleName)
static getUserAvailableSenders(?int $userId=null)
static getUserFormattedName(?int $userId=null)
const MAILBOX_SENDER_TYPE
static getUserAvailableSendersByEmail(string $email, int $userId=null)
static updateSender(int $senderId, array $fields, bool $checkSenderAccess=true)
static checkSenderNameCharacters(string $name)
static removeEmailLimit(string $email)
static hasUserSenderWithEmail(string $email, int $userId=null)
static getPublicSmtpSenderByEmail(string $email, int $senderId=null, bool $onlyWithSmtp=true)
static checkEmail(&$fields, &$error=null, Main\ErrorCollection &$errors=null)
static hasUserAvailableSmtpSenderByEmail(string $email, int $userId, bool $onlyWithSmtp=false)
static prepareSmtpConfigForSender(array &$smtp)
static deleteSenderByMailboxId(int $mailboxId)
static getEmailLimit($email)
static getCustomSmtp($email)
const MAIN_SENDER_SMTP_LIMIT_DECREASE
static add(array $fields)
static prepareUserMailboxes($userId=null)
static clearCustomSmtpCache($email)
static setEmailLimit(string $email, int $limit, bool $quite=true)
static applyCustomSmtp($event)
static canEditSender(int $senderId)
static getList(array $parameters=array())
static update($primary, array $data)
static getStringByCharsets($length, $charsetList)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
while($arParentIBlockProperty=$dbParentIBlockProperty->Fetch()) $errorMessage
if(!Loader::includeModule('sale')) $pattern