Просмотр файла delta_framework-main/core/lib/Core/Helpers/Mail.class.php

Размер файла: 9.13Kb
<?php
    /**
     * Copyright (c) 2022 Roman Grinko <rsgrinko@gmail.com>
     * Permission is hereby granted, free of charge, to any person obtaining
     * a copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     */

    namespace Core\Helpers;

    use Core\CoreException;
    use Core\DataBases\DB;
    use Core\Models\User;
    use Core\SystemConfig;
    use Throwable;

    /**
     * Класс для отправки E-mail
     */
    class Mail
    {
        /**
         * От кого
         */
        public $fromEmail = '';

        public $fromName  = '';

        /**
         * Кому
         */
        public $toEmail = '';

        public $toName  = '';

        /**
         * Тема
         */
        public $subject = '';

        /**
         * Текст
         */
        public $body = '';

        /**
         * Массив заголовков файлов
         */
        private $_files = [];

        /**
         * Почтовый шаблон
         */
        private $templateName = null;

        /**
         * Массив переменных шаблона
         */
        private $templateVars = [];

        /**
         * @var User|null $user Объект пользователя
         */
        private $user = null;

        /** @var string TABLE Таблица с логами отправки */
        private const TABLE = DB_TABLE_PREFIX . 'mail_history';

        /**
         * Конструктор
         */
        public function __construct(User $user = null) {
            if($user !== null) {
                $this->user = $user;
                $this->setFrom(SERVER_EMAIL, SERVER_EMAIL_NAME)
                     ->setTo($user->getEmail(), $user->getName())
                     ->setTemplate(SystemConfig::getValue('MAIL_TEMPLATE_DEFAULT'));
            }
        }

        /**
         * Использовать шаблон
         *
         * @param string $templateName Имя шаблона
         *
         * @return self
         */
        public function setTemplate(string $templateName): self
        {
            $this->templateName = $templateName;
            if (!file_exists(MAIL_TEMPLATES_PATH . '/' . $templateName . '.html')) {
                $this->templateName = 'default';
            }

            return $this;
        }

        /**
         * Определение переменных шаблона
         *
         * @param array $templateVars Массив переменных шаблона
         *
         * @return self
         */
        public function setTemplateVars(array $templateVars): self
        {
            foreach($templateVars as $key => $value){
                $this->templateVars['{' . $key . '}'] =  $value;
            }

            return $this;
        }

        private function messageConversionForTemplate(): self
        {
            $mailTemplate = file_get_contents(MAIL_TEMPLATES_PATH . '/' . $this->templateName . '.html');
            $this->body = str_replace("\r\n", PHP_EOL, $this->body);
            $this->body = str_replace("\n\n", PHP_EOL, $this->body);
            $this->body = str_replace(PHP_EOL, '<br>', $this->body);
            $this->templateVars['{BODY}'] = $this->body;
            $this->body = str_replace(array_keys($this->templateVars), array_values($this->templateVars), $mailTemplate);
            return $this;
        }

        /**
         * От кого
         *
         * @return self
         */
        public function setFrom($email, $name = null): self
        {
            $this->fromEmail = $email;
            $this->fromName  = $name;
            return $this;
        }

        /**
         * Кому
         *
         * @return self
         */
        public function setTo($email, $name = null): self
        {
            $this->toEmail = $email;
            $this->toName  = $name;
            return $this;
        }

        /**
         * Тема
         *
         * @return self
         */
        public function setSubject($subject = null): self
        {
            $this->subject = $subject;
            return $this;
        }

        /**
         * Тело письма
         *
         * @return self
         */
        public function setBody($body = null): self
        {
            $this->body = $body;
            return $this;
        }

        /**
         * Добавление файла к письму
         *
         * @return self
         */
        public function addFile($filename): self
        {
            if (is_file($filename)) {
                $name = basename($filename);
                $fp   = fopen($filename, 'rb');
                $file = fread($fp, filesize($filename));
                fclose($fp);
                $this->_files[] = [
                    'Content-Type: application/octet-stream; name="' . $name . '"',
                    'Content-Transfer-Encoding: base64',
                    'Content-Disposition: attachment; filename="' . $name . '"',
                    '',
                    chunk_split(base64_encode($file)),
                ];
            }
            return $this;
        }

        /**
         * Отправка
         */
        public function send()
        {
            if (empty($this->toEmail)) {
                return false;
            }

            $from = (empty($this->fromName)) ? $this->fromEmail : '=?UTF-8?B?' . base64_encode($this->fromName) . '?= <' . $this->fromEmail . '>';

            $array_to = [];
            foreach (explode(',', $this->toEmail) as $row) {
                $row = trim($row);
                if (!empty($row)) {
                    $array_to[] = (empty($this->toName)) ? $row : '=?UTF-8?B?' . base64_encode($this->toName) . '?= <' . $row . '>';
                }
            }

            $subject  = (empty($this->subject)) ? 'No subject' : $this->subject;
            if($this->templateName !== null) {
                $this->messageConversionForTemplate();
            }
            $body     = $this->body;
            $boundary = md5(uniqid(time(), true));
            $headers  = [
                'Content-Type: multipart/mixed; boundary="' . $boundary . '"',
                'Content-Transfer-Encoding: 7bit',
                'MIME-Version: 1.0',
                'From: ' . $from,
                'Date: ' . date('r'),
            ];
            $message  = [
                '--' . $boundary,
                'Content-Type: text/html; charset=UTF-8',
                'Content-Transfer-Encoding: base64',
                '',
                chunk_split(base64_encode($body)),
            ];

            if (!empty($this->_files)) {
                foreach ($this->_files as $row) {
                    $message = array_merge($message, ['', '--' . $boundary], $row);
                }
            }

            $message[] = '';
            $message[] = '--' . $boundary . '--';
            $res       = [];

            /** @var DB $DB */
            $DB = DB::getInstance();

            foreach ($array_to as $to) {
                $result = mb_send_mail($to, $subject, implode("\r\n", $message), implode("\r\n", $headers));
                $res[] = $result;

                try {
                    $DB->addItem(self::TABLE, [
                        'to_mail'       => $this->toEmail,
                        'to_name'       => $this->toName,
                        'from_mail'     => $this->fromEmail,
                        'from_name'     => $this->fromName,
                        'subject'       => $this->subject,
                        'send'          => $result ? CODE_VALUE_Y : CODE_VALUE_N,
                        'template'      => $this->templateName,
                        'template_vars' => json_encode($this->templateVars, JSON_UNESCAPED_UNICODE),
                        'body'          => $this->body,
                    ]);
                } catch (Throwable $e) {
                    // TODO Просто глушим, однако наверное надо залогировать в файл...
                }

            }

            Log::logToFile('Отправлено письмо', 'Mail.log', ['to' => $this->toEmail, 'subject' => $subject, 'body' => implode(' ', $message)]);
            return $res;
        }
    }