252 lines
6.5 KiB
PHP
252 lines
6.5 KiB
PHP
<?php
|
||
|
||
/**
|
||
* Класс для работы с почтой
|
||
* http://en.wikipedia.org/wiki/MIME
|
||
*/
|
||
|
||
namespace ctiso;
|
||
|
||
use ctiso\Path,
|
||
Exception;
|
||
|
||
class Mail
|
||
{
|
||
/** @var string */
|
||
public $_from;
|
||
/** @var string */
|
||
public $_to;
|
||
/** @var string */
|
||
public $_subject;
|
||
/** @var string */
|
||
public $content;
|
||
/** @var string */
|
||
public $copy;
|
||
|
||
/** @var string */
|
||
private $encoding;
|
||
/** @var string */
|
||
private $_notify = null;
|
||
|
||
/** @var array */
|
||
protected $attachment = array();
|
||
/** @var string */
|
||
protected $uniqid;
|
||
/** @var string */
|
||
protected $type = "text/plain";
|
||
|
||
function __construct()
|
||
{
|
||
$this->setEncoding("UTF-8");
|
||
$this->uniqid = strtoupper(uniqid((string)time())); // Идентефикатор разделителя
|
||
}
|
||
|
||
/**
|
||
* Установка отправителя
|
||
*/
|
||
function from(string $name): void
|
||
{
|
||
// filter_var($name, FILTER_VALIDATE_EMAIL);
|
||
$this->_from = $name;
|
||
}
|
||
|
||
/**
|
||
* Установка получателя
|
||
*/
|
||
function to(string $name): void
|
||
{
|
||
$this->_to = $name;
|
||
}
|
||
|
||
/**
|
||
* @param string $name
|
||
*/
|
||
function replyTo($name): void
|
||
{}
|
||
|
||
/**
|
||
* Установка получателей копии
|
||
*/
|
||
function copy(string $name): void
|
||
{
|
||
$this->copy = $name;
|
||
}
|
||
|
||
function notify(string $notify): void
|
||
{
|
||
$this->_notify = $notify;
|
||
}
|
||
|
||
/**
|
||
* Тема письма
|
||
*/
|
||
function subject(string $subject): void
|
||
{
|
||
$this->_subject = $subject;
|
||
}
|
||
|
||
/**
|
||
* Текст письма
|
||
*/
|
||
function setContent(string $text): void
|
||
{
|
||
$this->content = $text;
|
||
}
|
||
|
||
/**
|
||
* Кодировка текста в письме
|
||
*/
|
||
function setEncoding(string $encoding): void
|
||
{
|
||
$this->encoding = $encoding;
|
||
}
|
||
|
||
/**
|
||
* Добавление вложения из файла
|
||
* @param string $filename
|
||
* @param string|false $name
|
||
*/
|
||
function addAttachment(string $filename, $name = false): void
|
||
{
|
||
if (file_exists($filename)) {
|
||
$file = fopen($filename, "rb");
|
||
if (is_resource($file)) {
|
||
$data = fread($file, filesize($filename));
|
||
$this->attachment[] = ($name) ? [$data, $name] : [$data, basename($filename)];
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Установка типа содержимого
|
||
* @param string $type
|
||
*/
|
||
function setType($type): void
|
||
{
|
||
$this->type = $type;
|
||
}
|
||
|
||
/**
|
||
* Добавление вложения из строки с указанием имени файла
|
||
* @param string $data
|
||
* @param string $name
|
||
*/
|
||
function addAttachmentRaw($data, string $name): void
|
||
{
|
||
$this->attachment[] = [$data, $name];
|
||
}
|
||
|
||
/**
|
||
* @param string $var
|
||
* @param string $val
|
||
*/
|
||
function quote($var, $val): string
|
||
{
|
||
return ";" . PHP_EOL . "\t" . $var . "=\"" . $val . "\"";
|
||
}
|
||
|
||
/**
|
||
* Общий формат тегов MIME
|
||
* @see http://tools.ietf.org/html/rfc2045
|
||
*
|
||
* @param string $name
|
||
* @param string $value
|
||
* @param array $args
|
||
*/
|
||
function mimeTag($name, $value, array $args = []): string
|
||
{
|
||
assert(is_string($name));
|
||
assert(is_string($value));
|
||
|
||
return $name . ": " . $value . implode("", array_map([$this, 'quote'], array_keys($args), array_values($args))) . PHP_EOL;
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @see http://tools.ietf.org/html/rfc2047
|
||
*/
|
||
function encodedWord(string $text, string $encoding = 'B'): string
|
||
{
|
||
return "=?{$this->encoding}?$encoding?" . base64_encode($text) . "?=";
|
||
}
|
||
|
||
/**
|
||
* Тело сообщения
|
||
*/
|
||
function getMessage(): string
|
||
{
|
||
$message = "--" . $this->uniqid . PHP_EOL;
|
||
$message .= $this->mimeTag("Content-Type", $this->type, ['charset' => $this->encoding]);
|
||
$message .= $this->mimeTag("Content-Transfer-Encoding", "8bit");
|
||
$message .= PHP_EOL . $this->content . PHP_EOL . PHP_EOL;
|
||
|
||
/*
|
||
* Вложения
|
||
* http://tools.ietf.org/html/rfc2046#section-5.1.3
|
||
*/
|
||
foreach ($this->attachment as $value) {
|
||
list($data, $name) = $value;
|
||
$message .= "--" . $this->uniqid . PHP_EOL;
|
||
$message .= $this->mimeTag("Content-Type", "application/octet-stream", ['name' => basename($name)]);
|
||
$message .= $this->mimeTag("Content-Transfer-Encoding", "base64");
|
||
$message .= $this->mimeTag("Content-Disposition", "attachment", ['filename' => basename($name)]);
|
||
$message .= PHP_EOL . chunk_split(base64_encode($data)) . PHP_EOL;
|
||
}
|
||
|
||
return $message;
|
||
}
|
||
|
||
/**
|
||
* Заголовок сообщения
|
||
*/
|
||
function getHeader(): string
|
||
{
|
||
$head = $this->mimeTag("MIME-Version", "1.0");
|
||
$head .= $this->mimeTag("From", $this->_from);
|
||
$head .= $this->mimeTag("X-Mailer", "CMS Tool");
|
||
$head .= $this->mimeTag("Reply-To", $this->_from);
|
||
if (is_string($this->_notify)) {
|
||
$head .= $this->mimeTag("Disposition-Notification-To", "\"" . $this->_notify . "\" <" . $this->_from . ">");
|
||
}
|
||
$head .= $this->mimeTag("Content-Type", "multipart/mixed", ["boundary" => $this->uniqid]);
|
||
if ($this->copy) {
|
||
$head .= $this->mimeTag("BCC", $this->copy);
|
||
}
|
||
$head .= PHP_EOL;
|
||
return $head;
|
||
}
|
||
|
||
function getSubject(): string
|
||
{
|
||
return $this->encodedWord($this->_subject);
|
||
}
|
||
|
||
/**
|
||
* Вывод строки для сохранения в формате .eml
|
||
*/
|
||
function eml(): string
|
||
{
|
||
return "To: " . $this->_to . PHP_EOL . "Subject: {$this->getSubject()}" . PHP_EOL . $this->getHeader() . $this->getMessage();
|
||
}
|
||
|
||
/**
|
||
* Отправка почты
|
||
*/
|
||
function send(): bool
|
||
{
|
||
$result = mail($this->_to, $this->getSubject(), $this->getMessage(), $this->getHeader());
|
||
if (! $result) {
|
||
file_put_contents(Path::resolveFile("send.eml"), $this->eml());
|
||
throw new Exception('Невозможно отправить почту');
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
function clear(): void
|
||
{
|
||
foreach ($this->attachment as $key => &$value) {
|
||
unset($this->attachment[$key]);
|
||
}
|
||
$this->attachment = [];
|
||
}
|
||
}
|