Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Senior: питання на співбесіді з теми «Пошта»

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

2 питання

Більшість причин лежить поза кодом - у DNS і репутації домену, - але частина залежить від застосунку.

Що налаштовується в DNS:

  • SPF - перелік серверів, яким дозволено слати від імені домену.
  • DKIM - криптопідпис листа; без нього провайдер не може підтвердити, що лист не підроблено.
  • DMARC - політика на випадок, коли SPF чи DKIM не зійшлися.

Без цих трьох записів лист від нового домену з високою ймовірністю не дійде до вхідних.

Що залежить від застосунку:

  • Адреса відправника з власного домену. from виду noreply@gmail.com не пройде перевірку - домен у from має збігатися з тим, для якого налаштовані SPF і DKIM.
  • Транзакційне окремо від масового. Розсилка з поганим показником відкриттів псує репутацію домену, і за нею перестають доходити листи про відновлення пароля. Часто для розсилок беруть окремий піддомен.
  • Відписка. Для масових листів заголовок List-Unsubscribe обовʼязковий: без нього люди тиснуть «спам» замість відписки, і це найгірший сигнал.
  • Текстова версія. Лист без text/plain частина фільтрів вважає підозрілим.
  • Обробка bounce. Слати на адресу, що повертає помилку, місяцями - прямий шлях до блокування; провайдери дають вебхуки, які варто слухати.

Практично: транзакційну пошту віддають спеціалізованому сервісу (Mailgun, Postmark, SES), а не SMTP власного сервера, - вони тримають репутацію IP і дають статистику доставки. У Laravel це лише зміна MAIL_MAILER.

Докладніше в документації: Пошта

Пошта - зовнішня залежність: провайдер може лежати, обмежувати частоту, заблокувати акаунт за скарги. Для листів, від яких залежить бізнес (підтвердження, скидання пароля, рахунки), потрібен план на ці випадки.

1. Failover - резервні транспорти:

// config/mail.php
'mailers' => [
    'failover' => [
        'transport' => 'failover',
        'mailers' => ['postmark', 'mailgun', 'sendmail'],
        'retry_after' => 60,
    ],
],
MAIL_MAILER=failover

Якщо postmark повертає помилку, лист іде через mailgun. Транспорт, що впав, позначається недоступним на retry_after секунд - наступні листи одразу йдуть через резервний. Механізм побудований на FailoverTransport із Symfony Mailer.

2. Round robin - розподіл навантаження:

'roundrobin' => [
    'transport' => 'roundrobin',
    'mailers' => ['ses', 'postmark'],
],

Листи розподіляються між провайдерами по черзі, а недоступний пропускається.

Що варто врахувати з кількома провайдерами: кожен потребує налаштованих SPF, DKIM і домену відправника, інакше резервні листи потраплять у спам. Вебхуки про відмови й скарги (bounces, complaints) теж треба приймати від усіх.

3. Різні мейлери для різних листів:

Mail::mailer('postmark')->to($user)->send(new PasswordReset($token));   // транзакційні
Mail::mailer('ses')->to($subscribers)->queue(new Newsletter($issue));   // масові

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

4. Ліміти частоти. Провайдери обмежують кількість листів за секунду чи добу. Laravel не обмежує сам - це робиться на рівні черги:

  • окрема черга mail з фіксованою кількістю воркерів;
  • middleware завдань RateLimited чи Redis::throttle() для листів у черзі;
  • $tries і backoff, щоб тимчасові помилки (429, 5xx) повторювалися з затримкою.

5. Спостереження й налагодження:

  • події MessageSending і MessageSent - для журналу надісланого чи блокування листів за умовою;
  • перегляд у браузері під час розробки: маршрут, що повертає mailable, рендерить його як сторінку;
  • на staging - драйвер log чи Mailpit/Mailtrap, а також Mail::alwaysTo() у середовищі, щоб тестові листи не потрапили справжнім клієнтам.

6. Тести: Mail::fake() і assertQueued перевіряють, що лист поставлено в чергу з правильними даними, а assertSeeInHtml - зміст листа.

Докладніше в документації: Пошта: конфігурація failover