Отправка (form-)писем со статических веб-сайтов с помощью Go


От HTML к WordPress и Hugo

Более 7 лет я поддерживаю веб-сайт некоммерческой организации. Когда я принял эту задачу от предыдущего веб-мастера, страница представляла собой набор вручную созданных и поддерживаемых HTML-страниц. Поскольку я не хотел вручную писать HTML на каждой странице для каждого изменения, которое необходимо было сделать, я решил перестроить весь сайт на WordPress.

Несмотря на то, что это работало довольно хорошо, с годами мне начал не нравиться WordPress. Кроме того, со всеми необходимыми плагинами сайт стал ужасно медленным (4-5 секунд на запрос — я так и не выяснил, какой именно плагин вызвал такую медлительность). В итоге я решил заменить WordPress на генератор статических страниц: Hugo.

Отправка писем из HTML-форм

Hugo замечательный и быстрый, и мне очень нравится с ним работать. Это было правильное решение. Теперь страница отзывчива, быстра и проста в обслуживании.

Тем не менее, одна вещь, которую я не мог легко сделать с Hugo, это отправка писем из контактных форм — по сути, это рассыльщик форм. В WordPress, поскольку на стороне сервера под капотом PHP, это довольно просто. Но в Hugo страницы — это статический HTML.

Поэтому мне пришлось использовать JavaScript и какой-нибудь почтовик для отправки запросов контактной формы. Существуют сторонние сервисы, такие как https://formspree.io/, которые специализируются на этом, но так как я не хочу вкладывать деньги только для отправки форм, и я также не доверяю конфиденциальности данных таких сервисов (GDPR — большая вещь в ЕС, вы знаете 😉 ), я решил написать свой собственный небольшой веб-сервис для этого.

Представляем js-mailer

js-mailer — это очень простой, но мощный веб-сервис, написанный на Go, который позволяет статическим веб-сайтам отправлять формы через API JavaScript fetch() или XMLHttpRequest.

Это двухэтапный рабочий процесс. Сначала ваш JavaScript запрашивает токен у API, используя конечную точку /api/v1/token. Если запрос действителен и сайт авторизован для запроса токена, API ответит TokenResponseJson. В нем содержатся некоторые данные, которые необходимо включить в вашу форму в качестве скрытых входов. Он также предоставит конечную точку URL отправки /api/v1/send/<formid>/<token>, которая может быть использована в качестве действия в вашей форме. После отправки формы API проверит правильность всех предоставленных данных и отправит данные формы настроенным получателям.

То, что начиналось как быстрый и грязный сервис «я хочу отправлять HTML-формы по почте», быстро превратилось в полноценный веб-сервис. На момент написания этой заметки сервис поддерживает следующие функции:

  • Однобинарный веб-сервис
  • Поддержка нескольких форм
  • Несколько получателей для одной формы
  • Отображение в полученном письме только тех полей формы, которые настроены для данной формы
  • Проверка наличия обязательных полей формы
  • Функциональность Anti-SPAM с помощью встроенного, автоматически истекающего и одноразового маркера безопасности
  • Функциональность Anti-SPAM с помощью полей honeypot
  • Ограничение доступа к форме определенными доменами
  • Конфигурация почтового сервера для каждой формы
  • Поддержка hCaptcha
  • Поддержка reCaptcha v2
  • Валидация типа поля формы (текст, email, число, bool)
  • Подтверждающее письмо на почту
  • Пользовательский заголовок Reply-To на основе почтового адреса отправителя

Это FOSS и его можно найти на Github. Возможно, он поможет вам решить аналогичную проблему.

Отправка писем с помощью Go

В первых итерациях js-mailer я использовал популярный пакет go-gomail/gomail для обработки части отправки почты. К сожалению, этот проект больше не поддерживается и использует довольно устаревшие мнения о том, как работать с отправкой почты.

В связи с вышеупомянутыми причинами и отсутствием подходящих альтернатив я решил написать собственную почтовую библиотеку Go. На длинных выходных я начал работать над wneessen/go-mail и в ночь на воскресенье у меня уже был рабочий прототип, который я реализовал с помощью js-mailer.

Тем временем go-mail вырос до того, что я бы назвал довольно полной библиотекой для всех видов задач «отправки писем с помощью Go», и страница проблем на Github показывает, что люди начинают использовать его и запрашивать вещи, которые они хотели бы видеть частью go-mail. Список возможностей go-mail в настоящее время содержит эти пункты:

  • Зависит только от стандартной библиотеки
  • Современный, идиоматический Go
  • Разумные и безопасные настройки по умолчанию
  • Явная поддержка SSL/TLS
  • Неявная поддержка StartTLS с различными политиками
  • Использует контексты для лучшего потока управления и обработки таймаутов/отказов
  • Поддержка SMTP Auth (LOGIN, PLAIN, CRAM-MD)
  • Проверка почтовых адресов в соответствии с RFC5322
  • Поддержка генерации общих полей почтовых заголовков (Message-ID, Date, Bulk-Precedence, Priority и т.д.)
  • Повторное использование одного и того же SMTP-соединения для отправки нескольких писем
  • Поддержка вложений и встроенных вложений (из файловой системы, io.Reader или embed.FS)
  • Поддержка различных кодировок
  • Поддержка отправки писем через локальную команду sendmail
  • Объект сообщения удовлетворяет интерфейсам io.WriteTo и io.Reader
  • Поддержка html/шаблона и текста/шаблона Go (в качестве тела сообщения, альтернативной части или вложения/вкладыша)
  • Поддержка вывода в файл, что позволяет сохранять почтовые сообщения в виде, например, .eml файлов на диск, чтобы открыть их в MUA.

Так что если вам нужно отправлять почту в Go, я рекомендую взглянуть на него и посмотреть, может ли он помочь вам облегчить выполнение ваших «почтовых задач». Отзывы, сообщения об ошибках, исправления и PR, конечно, всегда приветствуются.

Оцените статью
devanswers.ru
Добавить комментарий