Система управления «Сайт PRO»
Версия 20240107

Класс Email

Объект $Email: Cms\Root\Email наследует Cms\Site\Base

Объект для работы с почтой

Исходный код
class Email extends \Cms\Site\Base { … }

Свойства

$head

$Email->head
Исходный код
    var $head;

$body

$Email->body
Исходный код
    var $body;

$param

$Email->param
Исходный код
    var $param;

$boundary

$Email->boundary
Исходный код
    var $boundary;

$attach

$Email->attach = array();
Исходный код
    var $attach = array();

$debug

$Email->debug
Исходный код
    var $debug;

Методы

send()

$Email->send($to, $subject, $text, $_param=null);

Отправка сообщения

Параметры:

ИмяОписание
$to

кому

$subject

тема

$text

текст

$_param

параметры

Исходный код
    function send($to, $subject, $text, $_param = null) {
        if (!is_array($_param)) {
            $param = array();
            $count = func_num_args();
            if ($count > 3) if (($value = func_get_arg(3)) !== null) $param['from'] = $value;
            if ($count > 4) if (($value = func_get_arg(4)) !== null) $param['type'] = $value;
            if ($count > 5) if (($value = func_get_arg(5)) !== null) $param['attach'] = $value;
            if ($count > 6) if (($value = func_get_arg(6)) !== null) $param['cleanup'] = $value;
        } else {
            $param = $_param;
        }
        if (!isset($param['from'])) $param['from'] = $this->defaultFrom();
        if (!isset($param['type']) || $param['type'] == "html") $param['type'] = "text/html";
        if (!isset($param['type']) || $param['type'] == "text") $param['type'] = "text/plain";
        $param['text'] = $text;
        if (isset($this->param)
            && $this->param['text'] === $param['text']
            && $this->param['from'] === $param['from']
            && $this->param['type'] === $param['type']
            && $this->param['attach'] === $param['attach']
            && $this->param['cleanup'] === $param['cleanup']
        ) {
            $body = $this->body;
            $head = $this->head;
        } else {
            $this->param = $param;
            $body = $this->body = $this->body();
            $head = $this->head = $this->head();
        }
        $a = array();
        foreach (preg_split("~[;,]~", $to, -1, PREG_SPLIT_NO_EMPTY) as $to) {
            if (strpos($to, "@") === false) {
                foreach ($this->expandTo($to) as $email => $title) $a[$email] = $title;
            } else {
                $a[$to] = $to;
            }
        }
        $subject = $this->quote($subject);
        $r = 0;
        if ($a) foreach ($a as $to) if ($this->sendmail($to, $subject, $body, $head)) $r ++;
        if ($param['cleanup']) $this->cleanup();
        return $r;
    }

sendmail()

$Email->sendmail($to, $subject, $body, $head);
Исходный код
    function sendmail($to, $subject, $body, $head) {
        if (is_array($head)) {
            $a = array();
            foreach ($head as $k => $v) if (isset($v)) $a[] = "$k: $v";
            $head = implode("\n", $a);
        }
        if ($this->debug) {
            print "<pre>\n" . "mail(" . var_export($to, true) . ", " . var_export($subject, true) . ", " . var_export($body, true) . ", " . var_export($head, true) . ");\n</pre>\n";
            return true;
        } else {
            return mail($to, $subject, $body, $head);
        }
    }

reset()

$Email->reset();
Исходный код
    function reset() {
        $this->head = null;
        $this->body = null;
        $this->param = null;
        $this->attach = array();
        $this->boundary = null;
    }

defaultFrom()

$Email->defaultFrom();
Исходный код
    function defaultFrom() {
        $Conf = $this->Conf();
        $Main = $this->Main();
        $Request = $Main->Request();
        if (strlen($from = $Conf->get("email_from"))) return $from;
        elseif (strlen($host = $Request->stripWww($Request->getHost()))) return "www@$host";
        else return "www";
    }

expandTo()

$Email->expandTo($to);
Исходный код
    function expandTo($to) {
        $Conf = $this->Conf();
        $Data = $this->Data();
        $r = array();
        $qto = $Data->quote($to);
        $qlto = $Data->qLike($to);
        if ($row = $Data->getRow("SELECT * FROM `user` WHERE `id`=$qto")) {
            $r[$row['email']] = $this->quote($row['title']) . " <" . $row['email'] . ">";
        } elseif ($Data->getRow("SELECT * FROM `group` WHERE `id`={$Data->quote($to)}")) {
            # 2014-03-21
            # Если "root", то письмо отправляется всем Администраторам.
            # Чтобы не отправлялось, в Настройках: 'admin_email_group_root' => ''
            if ($to != "root" || $Conf->get("admin_email_group_root", "Y"))
            foreach ($Data->getRows(""
             . "SELECT * FROM `user` WHERE `active`='Y' AND `email` LIKE '%@%' AND (`group`=$qto OR `group` LIKE '$qlto|%' OR `group` LIKE '%|$qlto' OR `group` LIKE '%|$qlto|%') ORDER BY `title`"
            ) as $row) {
                $r[$row['email']] = $this->quote($row['title']) . " <" . $row['email'] . ">";
            }
        }
        if ($to == "root" || $to == "admin") foreach (preg_split("~[;,]~", $Conf->get("admin_email"), -1, PREG_SPLIT_NO_EMPTY) as $to) {
            $r[$to] = $to;
        }
        return $r;
    }

head()

$Email->head();
Исходный код
    function head() {
        $r = array();
        $r['MIME-Version'] = "1.0";
        $r['Content-Type'] = $this->param['type'] . "; charset=UTF-8";
        if ($this->attach) $r['Content-Type'] = "multipart/related; boundary=\"{$this->boundary()}\"";
        else $r['Content-Transfer-Encoding'] = "base64";
        $r['From'] = $this->param['from'];
        return $r;
    }

body()

$Email->body();
Исходный код
    function body() {
        extract($this->param);
        $root = $this->root();
        $Main = $this->Main();
        $this->attach = array();
        $boundary = $this->boundary();
        if ($type == "text/html") {
            if (strpos($text, "<html") === false && strpos($text, "<HTML") === false) {
                $text = $Main->callTemplate("template", "email", $this, $this->param);
            } elseif (strpos($text, "<style") === false && strpos($text, "<STYLE") === false && file_exists("$root/email.css")) {
                $text = "<style type=\"text/css\"><!--\n" . trim(file_get_contents("$root/email.css")) . "\n--></style>\n" . $text;
            }
        }
        if (is_string($attach)) $attach = array($attach);
        if (is_array($attach)) foreach ($attach as $file) $this->attach($file);
        if ($count = preg_match_all("~src\s*=\s*(('[^'']+')|(\"[^\"\"]+\")|([^''\"\"\s]+))~si", $text, $m)) for ($i = 0; $i < $count; $i ++) {
            $qsrc = $m[1][$i];
            $q = $qsrc[0];
            if ($q == "'" || $q == '"') $src = trim($qsrc, $q);
            else $q = "";
            $cid = $this->attach($src, "inline");
            if (strlen($cid)) $text = str_replace($qsrc, $q . "cid:$cid" . $q, $text);
        }
        if ($this->attach) {
            $body = ""
             . "--$boundary\n"
             . "Content-Type: $type; charset=UTF-8\n"
             . "Content-Transfer-Encoding: base64\n"
             . "\n" . chunk_split(base64_encode($text), 76, "\n")
            ;
            foreach ($this->attach as $a) $body .= $a['part'];
            $body .= "--$boundary--\n";
        } else {
            $body = chunk_split(base64_encode($text), 76, "\n");
        }
        return $body;
    }

boundary()

$Email->boundary();
Исходный код
    function boundary() {
        if (isset($this->boundary)) return $this->boundary;
        else return $this->boundary = strtoupper(uniqid("----------"));
    }

attach()

$Email->attach($file, $param=null);
Исходный код
    function attach($file, $param = null) {
        if (is_array($file)) {
            if (isset($file['file'])) {
                $param = $file;
                $file = $file['file'];
            } elseif (isset($file[0])) {
                $param = $file;
                $file = $file[0];
            }
        }
        $root = $this->root();
        if (strpos($file, "://") === false) if (substr($file, 0, strlen($root)) != $root) $file = $root . "/" . ltrim($file, "/");
        $name = basename($file);
        $type = "application/octet-stream";
        $disposition = "attachment";
        $data = @file_get_contents($file);
        if (is_string($param) && strpos($param, ".") !== false) $name = basename($param);
        if (is_string($param) && $param == "inline") $disposition = "inline";
        switch (strtolower(substr($name, -4))) {
            case "jpeg": $type = "image/jpeg"; break;
            case ".jpg": $type = "image/jpeg"; break;
            case ".png": $type = "image/png"; break;
            case ".gif": $type = "image/gif"; break;
            case ".svg": $type = "image/svg+xml"; break;
        }
        if (!strlen($data) && strpos($file, "://") === false) {
            $data = @file_get_contents($this->Main()->Request()->absoluteUrl($file));
            if (!strlen($data)) return;
        }
        if (is_array($param)) extract($param);
        $cid = strtoupper(md5($data));
        $qname = $this->quote($name);
        $boundary = $this->boundary();
        $part = ""
         . "--$boundary\n"
         . ($disposition === 'attachment' ? '' : "Content-ID: <$cid>\n")
         . "Content-Type: $type; name=\"$qname\"\n"
         . "Content-Disposition: $disposition; filename=\"$qname\"\n"
         . "Content-Transfer-Encoding: base64\n"
         . "\n" . chunk_split(base64_encode($data), 76, "\n")
        ;
        $this->attach[$cid] = array(
            "cid" => $cid,
            "file" => $file,
            "name" => $name,
            "type" => $type,
            "part" => $part,
            "qname" => $qname,
            "disposition" => $disposition,
        );
        return $cid;
    }

cleanup()

$Email->cleanup();
Исходный код
    function cleanup() {
        foreach ($this->attach as $a) if (strlen($file = $a['file']) && strpos($file, "/upload/") !== false) @unlink($file);
        $root = $this->root();
        $till = 100000;
        $time = time();
        if ($D = @opendir($folder = "$root/upload")) {
            while (($file = readdir($D)) !== false) if ($file[0] !== '.') if (@is_file("$folder/$file") && $time - @filemtime("$folder/$file") > $till) @unlink("$folder/$file");
            closedir($D);
        }
    }

compose()

$Email->compose($to, $Page, $template);

Отправка сообщения по шаблону

Параметры:

ИмяОписание
$to

кому

$Page

страница

$template

шаблон

Исходный код
    function compose($to, $Page, $template) {
        $text = $this->Main()->Display->callTemplate("email", $template, $Page);
        if (strlen($text)) {
            global $_RESULT;
            if (strlen($_RESULT['subject'])) $subject = $_RESULT['subject'];
            if (strlen($Page->email_subject)) $subject = $Page->email_subject;
            return $this->send(
                $to, $subject, $text,
                $Page->email_from ? $Page->email_from : null,
                $Page->email_type ? $Page->email_type : "text/html",
                $Page->email_attach ? $Page->email_attach : null,
                $Page->email_cleanup ? $Page->email_cleanup : false
            );
        }
    }

quote()

$Email->quote($text);

Форматирование строки для передачи в заголовке

Параметры:

ИмяОписание
$text

string строка

Возвращает: string

Исходный код
    function quote($text) {
        $l = strlen($text);
        for ($i = 0; $i < $l; $i ++) if (ord($text[$i]) >= 0x80) return "=?UTF-8?b?" . base64_encode($text) . "?=";
        return $text;
    }

getSignature()

$Email->getSignature();
Исходный код
    function getSignature() {
        return '<div class="signature">С уважением,<br>Администрация сайта «<a href="' . $this->Main()->Request()->absoluteURL("/") . '" target="_blank">' . $this->Conf()->get("title") . '</a>»</p>';
    }