Email

Предупреждение

До версии 3.1 классы Email и Transport находились в пространстве имён Cake\Network\Email вместо пространства Cake\Mailer.

class Cake\Mailer\Email(mixed $profile = null)

Email это новый класс для отправки электронной почты. С помощью этого класса вы можете отправлять электронную почту из любого места внутри вашего приложения.

Основное использование

Прежде всего, вы должны убедиться, что класс загружен:

use Cake\Mailer\Email;

После того, как вы загрузили класс Email, вы можете сразу отправить электронное письмо следующим образом:

$email = new Email('default');
$email->from(['me@example.com' => 'My Site'])
    ->to('you@example.com')
    ->subject('About')
    ->send('My message');

Поскольку методы setter класса Email возвращают экземпляр класса, вы можете установить его свойства с помощью цепочки методов.

Email имеет несколько методов для определения получателей - to(), cc(), bcc(), addTo(), addCc() и addBcc(). Основное отличие состоит в том, что первые три будут перезаписывать то, что уже было установлено, а последние три просто добавят больше получателей в соответствующее поле:

$email = new Email();
$email->to('to@example.com', 'To Example');
$email->addTo('to2@example.com', 'To2 Example');
// Получатели электронной почты: to@example.com and to2@example.com
$email->to('test@example.com', 'ToTest Example');
// Получатель электронной почты: test@example.com

Не рекомендуется, начиная с версии 3.4.0: Вместо этого используйте setFrom(), setTo(), setCc() , setBcc() и setSubject() соответственно.

Выбор отправителя

При отправке электронной почты, от имени других людей, часто бывает полезно определить первоначального отправителя, используя заголовок отправителя. Вы можете сделать это, используя sender():

$email = new Email();
$email->sender('app@example.com', 'MyApp emailer');

Примечание

Также рекомендуется установить отправителя письма при отправке почты от имени другого лица. Это не позволяет им получать сообщения о доступности.

Не рекомендуется, начиная с версии 3.4.0: Используйте setSender().

Конфигурация

Конфигурация для Email по умолчанию создаётся с помощью config() и configTransport(). Вы должны поместить свои настройки электронной почты в файл config/app.php. Файл config/app.default.php является примером такого файла. Определять конфигурацию электронной почты в config/app.php не обязательно. Email можно использовать без config() и использовать соответствующие методы для установки всех конфигураций отдельно или загрузки массива конфигураций.

Определяя профили и транспорты, вы можете сохранить код приложения чистым, и избежать дублирования, чтобы не затруднять обслуживание и развертывание.

Чтобы загрузить предопределённую конфигурацию, вы можете использовать метод profile() или передать его конструктору Email:

$email = new Email();
$email->profile('default');

// Или в конструкторе
$email = new Email('default');

Вместо передачи строки, которая соответствует предварительно настроенному имени конфигурации, вы также можете просто загрузить массив параметров:

$email = new Email();
$email->profile(['from' => 'me@example.org', 'transport' => 'my_custom']);

// Или в конструкторе
$email = new Email(['from' => 'me@example.org', 'transport' => 'my_custom']);

Изменено в версии 3.1: Профиль электронной почты default автоматически устанавливается при создании экземпляра Email.

Не рекомендуется, начиная с версии 3.4.0: Используйте setProfile() вместо profile().

Настройка транспорта

static Cake\Mailer\Email::configTransport($key, $config)

Сообщения электронной почты доставляются транспортом. Различные транспорты позволяют отправлять сообщения через PHP функцию mail(), SMTP-серверы или вообще не использовать, что полезно для отладки. Настройка транспортов позволяет сохранять данные конфигурации из кода приложения и упрощает развёртывание, поскольку вы можете просто изменить данные конфигурации. Пример транспортной конфигурации выглядит так:

use Cake\Mailer\Email;

// Пример настройки почты
Email::configTransport('default', [
    'className' => 'Mail'
]);

// Пример настройки SMTP
Email::configTransport('gmail', [
    'host' => 'ssl://smtp.gmail.com',
    'port' => 465,
    'username' => 'my@gmail.com',
    'password' => 'secret',
    'className' => 'Smtp'
]);

Вы можете настроить SSL SMTP-серверы, например Gmail. Для этого поставьте префикс ssl:// в хост и соответствующим образом настройте значение порта. Вы также можете включить SMTP TLS с помощью опции tls:

use Cake\Mailer\Email;

Email::configTransport('gmail', [
    'host' => 'smtp.gmail.com',
    'port' => 587,
    'username' => 'my@gmail.com',
    'password' => 'secret',
    'className' => 'Smtp',
    'tls' => true
]);

Вышеприведённая конфигурация позволит использовать TLS для сообщений электронной почты.

Предупреждение

Для этого вам потребуется разрешить доступ для менее безопасных приложений, к вашему аккаунту Google.: Как разрешить ненадежным приложениям доступ к аккаунту.

Примечание

SMTP настройки для Gmail.

Примечание

Чтобы использовать SSL + SMTP, вам необходимо настроить SSL в вашей PHP-установке.

Параметры конфигурации также могут предоставляться как строка DSN. Это полезно при работе с переменными окружения или провайдерами PaaS:

Email::configTransport('default', [
    'url' => 'smtp://my@gmail.com:secret@smtp.gmail.com:587?tls=true',
]);

При использовании строки DSN, вы можете определить любые дополнительные параметры/опции в качестве аргументов строки запроса.

Не рекомендуется, начиная с версии 3.4.0: Используйте setConfigTransport() вместо configTransport().

static Cake\Mailer\Email::dropTransport($key)

После настройки транспорты изменить нельзя. Чтобы изменить транспорт, вы должны сначала его сбросить, а затем переконфигурировать.

Конфигурационные профили

Определение профилей доставки позволяет объединить общие настройки электронной почты в профили многократного использования. Ваше приложение может иметь столько профилей, сколько необходимо. Используются следующие конфигурационные:

  • 'from': Электронная почта или массив отправителей. Смотрите Email::from().
  • 'sender': Электронная почта или массив реальных отправителей. Смотрите Email::sender().
  • 'to': Электронная почта или массив назначений. Смотрите Email::to().
  • 'cc': Электронная почта или массив копий. Смотрите Email::cc().
  • 'bcc': Электронная почта или массив копированных копии. Смотрите Email::bcc().
  • 'replyTo': Электронная почта или массив, для ответов на e-mail. Смотрите Email::replyTo().
  • 'readReceipt': Адрес электронной почты или массив адресов получателей. Смотрите Email::readReceipt().
  • 'returnPath': Адрес электронной почты или массив адресов для возврата, если возникнет ошибка. Смотрите Email::returnPath().
  • 'messageId': ID идентификатор сообщения электронной почты. Смотрите Email::messageId().
  • 'subject': Тема сообщения. Смотрите Email::subject().
  • 'message': Содержание сообщения. Не устанавливайте это поле, если вы используете отображаемый контент.
  • 'priority': Приоритет электронной почты как числового значения (обычно от 1 до 5, причем 1 является наивысшим).
  • 'headers': Вкладываемые заголовки. Смотрите Email::headers().
  • 'viewRender': Если вы используете отображаемый контент, задайте имя класса Вида. Смотрите Email::viewRender().
  • 'template': Если вы используете отображаемый контент, задайте имя шаблона. Смотрите Email::template().
  • 'theme': Тема, используемая при создании шаблона. Смотрите Email::theme().
  • 'layout': Если вы используете отображаемый контент, установите макет для рендеринга. Если вы хотите отобразить шаблон без макета, установите для этого поля значение null. Смотрите Email::template().
  • 'viewVars': Если вы используете отображаемый контент, задайте массив с переменными, которые будут использоваться в представлении. Смотрите Email::viewVars().
  • 'attachments': List of files to attach. Смотрите Email::attachments().
  • 'emailFormat': Format of email (html, text or both). Смотрите Email::emailFormat().
  • 'transport': Название конфигурации транспорта. Смотрите Mailer\Email::configTransport().
  • 'log': Уровень журнала для регистрации заголовков и сообщений электронной почты. true если используете LOG_DEBUG. Смотрите так же Using Levels.
  • 'helpers': Массив помощников, используемых в шаблоне электронной почты. Email::helpers().

Все эти конфигурации являются необязательными, кроме 'from'.

Примечание

Значения вышеуказанных ключей с использованием электронной почты или массива, например from, to, cc и т. д., будут переданы в качестве первого параметра соответствующих методов. Эквивалент для: Email::from('my@example.com', 'My Site') в вашем конфиге будет определяться как 'from' => ['my@example.com' => 'My Site']

Настройка заголовков

В Email вы можете устанавливать любые заголовки, которые захотите. При переносе на использование электронной почты не забудьте поставить в свои заголовки префикс X-.

Смотрите Email::headers() и Email::addHeaders()

Не рекомендуется, начиная с версии 3.4.0: Используйте setHeaders() вместо headers().

Отправка шаблонных писем

Электронная почта часто намного больше, чем просто текстовое сообщение. Чтобы облегчить это, CakePHP предоставляет способ отправки писем с использованием view layer.

Шаблоны для электронных писем хранятся в специальной папке в каталоге Template вашего приложения под названием Email. Представления электронной почты также могут использовать макеты и элементы, аналогичные нормальным представлениям:

$email = new Email();
$email
    ->template('welcome', 'fancy')
    ->emailFormat('html')
    ->to('bob@example.com')
    ->from('app@domain.com')
    ->send();

Вышеизложенное будет использовать src/Template/Email/html/welcome.ctp для представления и src/Template/Layout/Email/html/fancy.ctp для макета(лейаута). Вы также можете отправить многостраничные шаблонные сообщения электронной почты:

$email = new Email();
$email
    ->template('welcome', 'fancy')
    ->emailFormat('both')
    ->to('bob@example.com')
    ->from('app@domain.com')
    ->send();

Это будет использовать следующие файлы шаблонов:

  • src/Template/Email/text/welcome.ctp
  • src/Template/Layout/Email/text/fancy.ctp
  • src/Template/Email/html/welcome.ctp
  • src/Template/Layout/Email/html/fancy.ctp

При отправке шаблонных писем у вас есть возможность отправить либо text, html или both.

Вы можете установить переменные вида с помощью Email::viewVars():

$email = new Email('templated');
$email->viewVars(['value' => 12345]);

В шаблонах электронной почты вы можете использовать:

<p>Here is your value: <b><?= $value ?></b></p>

Вы также можете использовать Помощников в электронных письмах, как и в обычных файлах шаблонов. По умолчанию загружается только HtmlHelper. Вы можете загрузить дополнительные помощники с помощью метода helpers():

$email->helpers(['Html', 'Custom', 'Text']);

При настройке помощников обязательно укажите „Html“ или он будет удалён из помощников, загруженных в ваш шаблон электронной почты.

Если вы хотите отправить письмо с помощью шаблонов в плагине, вы можете использовать знакомый plugin syntax делая это так:

$email = new Email();
$email->template('Blog.new_comment', 'Blog.auto_message');

Вышеупомянутый пример будет использовать шаблон и макет из плагина Blog.

В некоторых случаях вам может потребоваться переопределить шаблон по умолчанию, предоставляемый плагинами. Вы можете сделать это с помощью Тем, указав Email для которого будет использоваться соответствующая тема, для этого используйте метод Email::theme():

$email = new Email();
$email->template('Blog.new_comment', 'Blog.auto_message');
$email->theme('TestTheme');

Это позволяет вам переопределить шаблон new_comment в своей теме, не изменяя плагин Blog. Файл шаблона должен быть создан по следующему пути: src/Template/Plugin/TestTheme/Plugin/Blog/Email/text/new_comment.ctp.

Не рекомендуется, начиная с версии 3.4.0: Используйте setTemplate() вместо template(). Используйте setLayout() вместо аргумента макета template(). Используйте setTheme() вместо theme().

Отправка вложений

Cake\Mailer\Email::attachments($attachments)

Существует несколько разных форматов в зависимости от того, какие файлы у вас есть, и как вы хотите, чтобы имена файлов отображались в почтовом клиенте получателя:

  1. Строка: $email->attachments('/full/file/path/file.png') будет прикреплять файл с именем file.png

  2. Массив: $email->attachments(['/full/file/path/file.png']) будет иметь такое же поведение, как использование строки

  3. Массив с ключом: $email->attachments(['photo.png' => '/full/some_hash.png']) будет прикреплён файл some_hash.png с именем photo.png. Получатель увидит photo.png, а не some_hash.png

  4. Вложенные массивы:

    $email->attachments([
        'photo.png' => [
            'file' => '/full/some_hash.png',
            'mimetype' => 'image/png',
            'contentId' => 'my-unique-id'
        ]
    ]);
    

    Вышеприведённый файл будет прикреплён к файлу с другим типом mimetype и с пользовательским идентификатором содержимого (при установке ID идентификатора содержимого, которое будет приложением преобразовано во встроенный). Mimetype и contentId не являются обязательными в этой форме.

    4.1. Когда вы используете contentId, вы можете использовать этот файл в теле HTML, например <img src="cid:my-content-id">.

    4.2. Вы можете использовать опцию contentDisposition, чтобы отключить заголовок Content-Disposition для вложения. Это полезно при отправке ваших приглашений клиентам с использованием Outlook.

    4.3 Вместо параметра file вы можете предоставить содержимое файла в виде строки, используя опцию data. Это позволит вам прикреплять файлы, не требуя для них пути к файлам.

Не рекомендуется, начиная с версии 3.4.0: Используйте setAttachments() вместо attachments().

Использование транспорта

Транспорты - это классы, предназначенные для отправки электронной почты по некоторому протоколу или методу. CakePHP поддерживает сообщения Mail (по умолчанию), Debug и SMTP.

Чтобы настроить свой метод, вы должны использовать метод Cake\Mailer\Email::transport() или иметь транспорт в вашей конфигурации:

$email = new Email();

// Использовать именованный транспорт, уже настроенный с
// использованием электронной почты::configTransport()
$email->transport('gmail');

// Использовать построенный объект
$transport = new DebugTransport();
$email->transport($transport);

Не рекомендуется, начиная с версии 3.4.0: Используйте setTransport() вместо transport().

Создание пользовательских транспортов

Вы можете создавать свои пользовательские транспорты для интеграции с другими системами электронной почты (например, SwiftMailer). Чтобы создать транспорт, сначала создайте файл src/Mailer/Transport/ExampleTransport.php (где Example - это название вашего транспорта). Для начала ваш файл должен выглядеть так:

namespace App\Mailer\Transport;

use Cake\Mailer\AbstractTransport;
use Cake\Mailer\Email;

class ExampleTransport extends AbstractTransport
{
    public function send(Email $email)
    {
        // Тут что нибудь делаем
    }
}

Вы должны реализовать метод send(Email $email) с вашей пользовательской логикой. При желании вы можете реализовать метод config($config). config() вызывается перед send() и позволяет принимать пользовательские конфигурации. По умолчанию этот метод помещает конфигурацию в защищённый атрибут $ _config.

Если вам нужно вызвать дополнительные методы транспорта перед отправкой, вы можете использовать Cake\Mailer\Email::getTransport() для получения экземпляра транспортного объекта. Например:

$yourInstance = $email->getTransport()->transportClass();
$yourInstance->myCustomMethod();
$email->send();

Правила валидации e-mail адресов

Cake\Mailer\Email::emailPattern($pattern)

Если у вас возникли проблемы с отправкой, при проверке на несовместимые адреса, вы можете изменить шаблон, используемый для проверки адресов электронной почты. Это иногда необходимо при работе с некоторыми провайдерами:

$email = new Email('default');

// Сменить шаблон электронной почты, чтобы вы могли отправлять письма
    // на соответствующие адреса.
$email->emailPattern($newPattern);

Не рекомендуется, начиная с версии 3.4.0: Используйте setEmailPattern() вместо emailPattern().

Быстрая отправка сообщений

Иногда вам нужен быстрый способ отправить электронную почту, и вам не обязательно заранее устанавливать конфигурацию. Cake\Mailer\Email::deliver() предназначен для этой цели.

Вы можете создать свою конфигурацию, используя Cake\Mailer\Email::config(), или используйте массив со всеми необходимыми параметрами и используйте статический метод Email::deliver(). Например:

Email::deliver('you@example.com', 'Subject', 'Message', ['from' => 'me@example.com']);

Этот метод отправит электронное письмо на адрес «you@example.com», от «me@example.com» с пометкой «Subject» и контентом «Message».

Возврат метода deliver() является экземпляром Cake\Mailer\Email со всеми установленными конфигурациями. Если вы не хотите отправлять электронную почту сразу и хотите настроить несколько вещей перед отправкой, вы можете передать 5-й параметр как false.

3ий параметр - это содержимое сообщения или массив с переменными (при использовании визуализированного содержимого).

4ым параметром может быть массив с конфигурациями или строка с именем конфигурации в Configure.

Если вы хотите, вы можете передать объект, тему и сообщение как null и выполнить все конфигурации в 4-м параметре (в виде массива или с помощью Configure). Проверьте список configurations, чтобы увидеть все доступные конфиги.

Отправка писем из CLI (командной строки)

При отправке писем в сценарии CLI (оболочки, задачи, …) вы должны вручную указать имя домена для использования электронной почты. Он будет служить именем хоста для идентификатора сообщения (поскольку в среде CLI нет имени хоста)

$email->domain('www.example.org');
// Результаты в идентификаторах сообщений, таких как ``<UUID@www.example.org>`` (валидный)
// Вместо `<UUID@>`` (не валидного)

Действительный идентификатор сообщения может помочь предотвратить попадание писем в папки спама.

Не рекомендуется, начиная с версии 3.4.0: Используйте setDomain() вместо domain().

Создание многоразовых писем

Добавлено в версии 3.1.0.

Mailers позволяют создавать повторно используемые письма во всём приложении. Они также могут использоваться для хранения нескольких конфигураций электронной почты в одном месте. Это помогает сохранить код DRY(чистым) и устраняет помехи конфигурации электронной почты из других областей вашего приложения.

В этом примере мы создадим Mailer, который содержит связанные с пользователем электронные письма. Чтобы создать наш UserMailer, создайте файл src/Mailer/UserMailer.php. Содержимое файла должно выглядеть следующим образом:

namespace App\Mailer;

use Cake\Mailer\Mailer;

class UserMailer extends Mailer
{
    public function welcome($user)
    {
        $this
            ->to($user->email)
            ->subject(sprintf('Welcome %s', $user->name))
            ->template('welcome_mail', 'custom'); // По умолчанию используется шаблон с тем же именем, что и имя метода.
    }

    public function resetPassword($user)
    {
        $this
            ->to($user->email)
            ->subject('Reset password')
            ->set(['token' => $user->token]);
    }
}

В нашем примере мы создали два метода: один для отправки приветственного сообщения, а другой - для отправки пароля для сброса пароля. Каждый из этих методов ожидает пользователя Entity и использует его свойства для настройки каждого электронного письма.

Теперь мы можем использовать наш UserMailer для отправки наших писем, связанных с пользователем, из любого места нашего приложения. Например, если мы хотим отправить приветственное письмо, мы можем сделать следующее:

namespace App\Controller;

use Cake\Mailer\MailerAwareTrait;

class UsersController extends AppController
{
    use MailerAwareTrait;

    public function register()
    {
        $user = $this->Users->newEntity();
        if ($this->request->is('post')) {
            $user = $this->Users->patchEntity($user, $this->request->getData())
            if ($this->Users->save($user)) {
                $this->getMailer('User')->send('welcome', [$user]);
            }
        }
        $this->set('user', $user);
    }
}

Если бы мы хотели полностью отделить отправку пользователю приветственного письма от кода нашего приложения, мы можем подписывать UserMailer на событие Model.afterSave. Подписавшись на мероприятие, мы можем полностью закрывать пользовательские классы нашего приложения, не связанные с электронной логикой и инструкциями, связанными с электронной почтой. Например, мы могли бы добавить следующее к нашему UserMailer:

public function implementedEvents()
{
    return [
        'Model.afterSave' => 'onRegistration'
    ];
}

public function onRegistration(Event $event, EntityInterface $entity, ArrayObject $options)
{
    if ($entity->isNew()) {
        $this->send('welcome', [$entity]);
    }
}

Теперь объект почтовой программы можно зарегистрировать как прослушиватель событий, а метод onRegistration() будет вызываться каждый раз, когда будет запущено событие Model.afterSave. Информацию о том, как регистрировать объекты прослушивателя событий, см. в документации registering-event-listeners.