Интеграция электронной почты в мобильное приложение
Отправить письмо из мобильного приложения — задача с несколькими уровнями сложности. Можно открыть нативный почтовый клиент через mailto: и назвать это интеграцией. Можно отправлять транзакционные письма через SMTP прямо с устройства, что в продакшене никто не должен делать. А можно правильно — через API почтового провайдера с сервера, но с удобным интерфейсом в приложении.
Три сценария и их реализация
Сценарий 1: Открытие нативного клиента. Самый простой. На iOS — MFMailComposeViewController из MessageUI.framework, на Android — Intent.ACTION_SENDTO с Uri.parse("mailto:"). Подходит когда нужно просто дать пользователю написать письмо — в поддержку, например.
Подводный камень: MFMailComposeViewController недоступен на симуляторе и на устройствах без настроенной почты. Всегда проверяем MFMailComposeViewController.canSendMail() перед показом, иначе краш.
Сценарий 2: Транзакционные письма через API. Регистрация, сброс пароля, уведомления о заказах — письма отправляются с сервера, приложение только инициирует запрос. Выбор провайдера:
| Провайдер | SDK | Free tier |
|---|---|---|
| SendGrid | REST API + официальный SDK | 100 писем/день |
| Mailgun | REST API | 100 писем/день |
| Amazon SES | AWS SDK | 62k писем/мес (внутри AWS) |
| Postmark | REST API | Нет бесплатного |
Мобильное приложение делает запрос на свой backend (POST /api/send-email), backend вызывает API провайдера. Ключи API никогда не хранятся в приложении.
Сценарий 3: Чтение и отправка почты в интерфейсе приложения. Полноценный почтовый клиент внутри приложения — это IMAP/SMTP или Graph API (Outlook) / Gmail API. Для Gmail: авторизация через OAuth 2.0, получение списка писем через users.messages.list, тела через users.messages.get. Квоты API Gmail — 250 единиц за запрос, лимит 1 млрд единиц в день на проект. При активном использовании нужно следить.
Работа с вложениями
Вложения в мобильном контексте требуют осторожности. На iOS файлы из UIDocumentPickerViewController доступны через security-scoped bookmarks и требуют явного вызова startAccessingSecurityScopedResource() / stopAccessingSecurityScopedResource(). Без этого получаем NSCocoaErrorDomain с кодом 257. На Android с API 30+ прямой доступ к /sdcard закрыт — только через MediaStore или ACTION_OPEN_DOCUMENT.
Для загрузки вложений из письма — потоковая загрузка с прогрессом, URLSession.downloadTask на iOS или OkHttp с ResponseBody.byteStream() на Android. Не буферизуем всё в памяти, если вложение может быть большим.
Пуш-уведомления о новых письмах
Для real-time уведомлений о входящих письмах IMAP IDLE держит TCP-соединение — на мобильном это убивает батарею. Правильный путь: сервер слушает IMAP IDLE, при новом письме отправляет push через FCM/APNs. Приложение получает пуш, делает запрос и обновляет список.
Оценка сроков: простая интеграция отправки транзакционных писем — 2-3 дня. Встроенный почтовый клиент с IMAP/OAuth — от 3 до 6 недель.







