25 private static $instances = [];
29 private const HEADER_FROM_REGEX =
'/(?<=From:).*?(?=\\n)/iu';
30 private const HEADER_CC_REGEX =
'/^\s*cc:(?<emails>.+)/im';
31 private const HEADER_BCC_REGEX =
'/^\s*bcc:(?<emails>.+)/im';
33 private $configuration;
37 $configuration = \Bitrix\Main\Config\Configuration::getValue(
'smtp');
38 if ($context->getSmtp())
41 'host' => $context->getSmtp()->getHost(),
42 'port' => $context->getSmtp()->getPort(),
43 'encryption_type' => $context->getSmtp()->getProtocol() ??
'smtp',
44 'login' => $context->getSmtp()->getLogin(),
45 'password' => $context->getSmtp()->getPassword(),
46 'from' => $context->getSmtp()->getFrom(),
47 'debug' => $configuration[
'debug'] ??
false,
48 'force_from' => $configuration[
'force_from'] ??
false,
49 'logFile' => $configuration[
'log_file'] ??
null,
50 'isOauth' => $context->getSmtp()->getIsOauth(),
54 return $configuration ?? [];
67 $this->SMTPDebug = $this->configuration[
'debug'] ??
false;
71 $configuration = $this->configuration;
72 $this->Debugoutput =
function ($logMessage) use ($configuration) {
74 $configuration[
'logFile'] ?? (($_SERVER[
'DOCUMENT_ROOT'] ?? __DIR__) .
'/mailer.log')
76 $logger->info($logMessage);
81 $this->SMTPAuth = (bool)$this->configuration[
'password'];
82 $this->prepareOauthConfiguration();
85 !$this->configuration[
'host']
86 || !$this->configuration[
'login']
92 $this->From = $this->configuration[
'from'];
93 $this->Host = $this->configuration[
'host'];
94 $this->Username = $this->configuration[
'login'];
95 $this->
Password = $this->configuration[
'password'] ??
'';
96 $this->Port = $this->configuration[
'port'] ?? 465;
99 'smtps' === $this->configuration[
'encryption_type']
100 || (
'smtp' !== $this->configuration[
'encryption_type'] && 465 === $this->port))
102 $this->SMTPSecure = $this->Port == 465 ? PHPMailer::ENCRYPTION_SMTPS : PHPMailer::ENCRYPTION_STARTTLS;
105 $this->Timeout = $this->configuration[
'connection_timeout'] ?? 30;
115 private function prepareOauthConfiguration(): void
117 if (!empty($this->configuration[
'isOauth']))
119 $this->AuthType =
'XOAUTH2';
121 'userName' => $this->configuration[
'login'],
122 'token' => $this->configuration[
'password'],
133 $this->MIMEBody = $body;
142 $this->MIMEHeader = $headers;
160 string $additional_headers,
161 string $additional_parameters
165 $addresses = Mailer::parseAddresses($sourceTo)??[];
166 if (empty($addresses))
171 $eol = \Bitrix\Main\Mail\Mail::getMailEol();
173 if ($subject && $additional_headers)
175 $this->Subject = $subject;
176 $additional_headers .= $eol .
'Subject: ' . $subject;
179 preg_match(self::HEADER_FROM_REGEX, $additional_headers, $headerFrom);;
180 if ($this->configuration[
'force_from'] && $headerFrom)
182 $additional_headers = preg_replace(
183 self::HEADER_FROM_REGEX,
184 $this->configuration[
'from'],
191 $additional_headers .= $eol .
'From: ' . $this->configuration[
'from'];
194 $this->clearAllRecipients();
195 foreach ($addresses as $to)
201 $this->addAddress($to[
'address'], $to[
'name']);
204 $additional_headers .= $eol .
'To: ' . $sourceTo;
206 $this->prepareBCCRecipients($additional_headers);
207 $this->prepareCCRecipients($additional_headers);
212 $canSend = $this->checkLimit();
218 $sendResult = $this->postSend();
222 $this->increaseLimit();
228 private function prepareCCRecipients($additional_headers)
230 preg_match(self::HEADER_CC_REGEX, $additional_headers, $matches);
234 $recipients = explode(
',', trim($matches[
'emails']));
236 foreach ($recipients as $to)
238 $to = self::parseAddresses($to) ?? [];
243 $this->addCC($to[0][
'address'], $to[0][
'name']);
248 private function prepareBCCRecipients($additional_headers)
250 preg_match(self::HEADER_BCC_REGEX, $additional_headers, $matches);
254 $recipients = explode(
',', trim($matches[
'emails']));
256 foreach ($recipients as $to)
258 $to = self::parseAddresses($to) ?? [];
263 $this->addBCC($to[0][
'address'], $to[0][
'name']);
277 $key = hash(
'sha256', serialize($context));
278 if (!static::$instances[$key])
281 if (!$mail->prepareConfiguration($context))
286 if ($context->getSmtp())
288 $mail->setFrom($context->getSmtp()->getFrom());
291 switch ($context->getKeepAlive())
295 $mail->SMTPKeepAlive =
false;
298 $mail->SMTPKeepAlive =
true;
300 function () use ($mail)
306 $mail->SMTPKeepAlive =
true;
310 static::$instances[$key] = $mail;
313 return static::$instances[$key];
331 $ip = \Bitrix\Main\Web\IpAddress::createByName($context->getSmtp()->getHost());
332 if ($ip->isPrivate())
334 $errors->setError(
new Error(
'SMTP server address is invalid'));
339 if (!$mail->prepareConfiguration($context))
344 if ($mail->smtpConnect())
354 private function checkLimit(): bool
356 $from = self::parseAddresses($this->From)[0][
'address'];
357 $count = count($this->getAllRecipientAddresses());
362 && ($emailCounter->get($from) + $count) > $emailDailyLimit)
371 private function increaseLimit()
373 $from = self::parseAddresses($this->From)[0][
'address'];
376 if (!$emailDailyLimit)
381 $emailCounter =
new SenderSendCounter();
382 $count = count($this->getAllRecipientAddresses());
384 $emailCounter->increment($from, $count);
392 foreach (static::$instances as $instance)
394 $instance->smtpClose();
static getMessage($code, $replace=null, $language=null)
static getEmailLimit($email)
const KEEP_ALIVE_OPTIONAL
static getInstance(Context $context)
static checkConnect(Context $context, \Bitrix\Main\ErrorCollection $errors)
static closeConnections()
getActualConfiguration(Context $context)
prepareConfiguration(Context $context)
sendMailBySmtp(string $sourceTo, string $subject, string $message, string $additional_headers, string $additional_parameters)
static isModuleInstalled($moduleName)