Як спуліти електронні листи

Дата оновлення перекладу 2023-06-22

Як спуліти електронні листи

Поведінка поштової програми Symfony за замовчуванням - надсилати листи негайно. Однак, ви можете хотіти уникнути навантаження продуктивності комунікацій із поштовим сервером, яке може спричинити очікування користувачем завантаження наступної сторінки, поки надсилаються листи. Цього можна уникнути, обравши "спулінг" листів, замість їх прямого надсилання.

Це змушує поштовий сервіс не намагатися відправити лист, а замість цього зберегти його кудись, наприклад, у файл. Інший процес потім може зчитати зі спулу і подбати про надсилання листів у спулі. На даний момент підтримується тільки спулінг у файл або пам'ять.

Спулінг з використанням памʼяті

Коли ви використовуєте спулінг для збереження електронних листів у пам'яті, вони будуть відправлені прямо перед завершенням ядра. Це означає, що лист буде відправлено тільки в разі, якщо запит був повністю виконаний без помилок і невирішених виключень. Щоб сконфігурувати цей спул, використовуйте таку конфігурацію:

1
2
3
4
# config/packages/swiftmailer.yaml
swiftmailer:
    # ...
    spool: { type: memory }

Спулінг з використанням файлів

Коли ви використовуєте файлову систему для спулінгу, Symfony створює папку в заданому шляху для кожного сервісу пошти (наприклад, "default" для сервісу за замовчуванням). Ця папка міститиме файли для кожного листа в спулі. Тож переконайтеся, що цей каталог може бути написаний Symfony (або вашим веб-сервером/php)!

Щоб використати спул із файлами, використовуйте таку конфігурацію:

1
2
3
4
5
6
# config/packages/swiftmailer.yaml
swiftmailer:
    # ...
    spool:
        type: file
        path: /path/to/spooldir

Tip

Якщо ви хочете зберігати спул де-небудь у каталозі вашого проекту, пам'ятайте, що ви можете використовувати параметр %kernel.project_dir% для відсилання до кореня проєкту:

1
path: '%kernel.project_dir%/var/spool'

Тепер, коли ваш додаток надсилає електронний лист, він насправді не буде відправлений, а буде доданий до спулу. Надсилання повідомлень зі спулу відбувається окремо. Існує консольна команда для надсилання листів зі спулу:

1
$ php bin/console swiftmailer:spool:send --env=prod

Вона має опцію для лімітування кількості листів, які будуть надіслані:

1
$ php bin/console swiftmailer:spool:send --message-limit=10 --env=prod

Ви також можете встановити часове обмеження у секундах:

1
$ php bin/console swiftmailer:spool:send --time-limit=10 --env=prod

Звичайно вам не захочеться запускати це вручну у реальному житті. Замість цього, консольна команда повинна викликатися роботою крона або запланованим завданням і виконуватися з регулярними інтервалами.

Caution

Коли ви створюєте лист зі SwiftMailer, він генерує клас Swift_Message. Якщо сервіс swiftmailer був завантажений ліниво, він генерує замість цього клас проксі під назвою Swift_Message_<someRandomCharacters>.

Якщо для спулу ви використовуєте пам'ять, ця зміна прозора і не має жодного впливу. Але при використанні файлової системи для спулу, клас повідомлення перетворюється в послідовну форму у файлі з випадковим ім'ям класу. Проблема в тому, що це випадкове ім'я класу змінюється під час кожного очищення кешу. Тож якщо ви відправляєте лист, а потім очищаєте кеш, то лист не буде перетворено в послідовну форму.

При наступному виконанні swiftmailer:spool:send буде виникати помилка, оскільки клас Swift_Message_<someRandomCharacters> не існує (більше).

Рішенням може бути або використання пам'яті для спулу, або завантаження сервісу swiftmailer без опції lazy (див. Ліниві сервіси).