Найти тему
Ржавый код

Напишите собственный сервер электронной почты

Оглавление

Пошаговое руководство по внедрению и развертыванию собственного одноразового сервера электронной почты с нуля.

Как пользователь 10-минутной электронной почты, я всегда задавался вопросом, насколько трудно будет внедрить и настроить свой собственный одноразовый сервер электронной почты - тот, который используется исключительно для размещения вашего адреса электронной почты на одном из сторонних серверов. Как выясняется, внедрение такого сервера - удивительно гладкий и отрадный опыт!

Результатом этого небольшого личного хакатона является электронная почта, сервер одноразовой электронной почты с открытым исходным кодом. В этом сообщении вы увидите, как написать и развернуть его самостоятельно. Здесь размещен открытый экземпляр электронной почты.

Сведения о SMTP

Протокол SMTP устарел. Я также был удивлен, обнаружив, что для такого проверенного боем и надежного протокола не так много ресурсов, чтобы узнать о его деталях, особенно если вы хотели бы реализовать его самостоятельно. Фактически, все учебные пособия по «созданию собственного SMTP» в основном начинаются с «установки Postfix» - полноценного SMTP-сервера производственного уровня! Давайте начнем с основ.

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

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

-2

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

Внедрение

Название проекта - edgemail, что является данью тому факту, что он обеспечивает низкую задержку для своих пользователей благодаря использованию базы данных edge-native. Подробнее в нескольких абзацах!

Сервер будет реализован в виде 3 отдельных уровней:

  1. Конечный автомат SMTP, ответственный за обработку связи SMTP
  2. База данных для хранения почты
  3. Клиент для просмотра почты

Конечный автомат SMTP

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

-3

После установления соединения сервер представляет себя, а затем выполняет квитирование, принимая сообщение HELO или EHLO (extended-hello). После подтверждения связи сервер ожидает выполнения команды MAIL, которая содержит информацию о том, кто отправил сообщение электронной почты, а затем команды RCPT с информацией обо всех получателях. Как только отправитель и получатели известны, сервер принимает команду DATA, которая позволяет ему получать текст сообщения электронной почты. После этого выполняется процедура прощания и транзакция.

-4
-5
-6
-7

TCP-сервер

Как только у нас будет конечный автомат SMTP, пришло время подключить его к серверу TCP. Работа сервера будет чрезвычайно простой:

  1. Принять новое подключение
  2. Отправить приветствие SMTP
  3. Получение команды SMTP
  4. Обработка команды с помощью конечного автомата SMTP
  5. Возврат ответа пользователю
  6. Если почта была получена, сохранить ее в базе данных

С крейтом Tokio реализация такого TCP-сервера будет ветерком.

Поскольку наш сервер предназначен для использования в качестве временного почтового ящика для одного человека, мы не будем беспокоиться об управлении пользователями. Вместо этого сервер будет принимать все сообщения и сохранять их в базе данных. Чтобы не переполнить хранилище, старая почта будет периодически очищаться.

-8
-9

База данных

Для хранения всех почтовых отправлений мы будем использовать Turso - базу данных SQL Turso может получать запросы через HTTP, что позволяет выполнять запросы прямо из браузера, и это делает ответы до смешного быстрыми.

Чтобы создать новую базу данных, начните с установки инструмента командной строки turso.

Как только вы закончите, создайте новую базу данных - назовем ее edgemaildb - с помощью:

-10

Схема хранения почты будет простой, так как вся почта хранится в одной таблице. Эта таблица будет автоматически создана при запуске сервера электронной почты, если она не существует:

-11

Для ускорения запросов к почтовой таблице можно создать следующие индексы. Они также будут автоматически созданы при запуске электронной почты, если они отсутствуют:

-12

Подключение к базе данных из Rust

Turso совместим с драйвером libSQL Rust. Для работы драйвера требуется только две части информации:

  1. URL-адрес базы данных.
  2. Маркер аутентификации, который требуется только при подключении к удаленному экземпляру Turso.

Они могут быть определены как переменные среды. К экземпляру Turso подключится следующая конфигурация:

-13

… но вы также можете указать локальный файл для использования в целях разработки - не нужно ни на что подписываться!

-14

В электронной почте ситуация еще проще. Если URL-адрес не указан, сервер автоматически запустится с локальной базы данных, хранящейся в файле `edgemail.db`, размещенном во временном каталоге системы:

-15

После перехода к производству и хранения сообщений электронной почты на edge достаточно указать переменную `LIBSQL_CLIENT_URL` на URL-адрес базы данных Turso и `LIBSQL_CLIENT_TOKEN` на маркер аутентификации.

Можно проверить URL-адрес базы данных, выполнив следующую команду:

-16

Чтобы создать маркер проверки подлинности, выполните следующую команду:

-17

Клиент

Так как Turso работает по HTTP, наш клиент будет статической веб-страницой, которая может быть размещена бесплатно в множестве мест, как GitHub Pages. Если вас беспокоит утечка маркеров доступа к базе данных после публикации на веб-странице - не бойтесь. С помощью Turso можно создавать маркеры только для чтения базы данных:

-18

Они предоставляют доступ только для чтения к базе данных. В этом конкретном случае хорошо «прокинуть» токены в браузеры пользователей, потому что вся база данных, по замыслу, читаема всеми. Отправка запросов базы данных прямо из браузера также отлично подходит для вашего ожидания - ваш браузер собирается получить данные непосредственно из базы данных, без участия посредников.

Клиент будет разделен на две страницы: главную страницу для выбора имени пользователя и папку «Входящие».

Главная страница представляет собой простую форму, которая позволяет пользователям выбрать любое имя пользователя, которое они хотели бы использовать. SMTP-сервер в любом случае принимает всю входящую почту, поэтому можно выбрать любое имя пользователя. Для не определившихся простой псевдослучайный генератор имен пользователей предложит подсказку.

После выбора имени пользователя пользователи переходят на страницу «Входящие», где происходит вся магия.

Страница «Входящие» извлекает всю почту, адресованную данному пользователю, непосредственно из базы данных, по существу, отправляя следующий SQL-запрос:

-19

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

Исходный код

Весь исходный код, включая сервер, клиент и тесты, является открытым и доступен здесь. Наслаждайтесь! Чтобы запустить сервер, выполните cargo run. Испытания могут проводиться с cargo test.

Развертывание

SMTP-сервер

Теперь, когда сервер реализован, пришло время сделать его общедоступным. Для этого вам понадобится любой компьютер с открытым IPv4-адресом и портом 25, открытым для входящего трафика. С технической точки зрения SMTP работает также и на IPv6, но на практике поставщики электронной почты часто отказываются работать с IPv6-серверами в качестве предотвращения нежелательной почты. Адресное пространство IPv6 является слишком широким и слишком нерегулируемым, чтобы его было так же легко проверить, как IPv4, поэтому лучше придерживаться этого. SMTP-серверы часто прослушивают соединения на других номерах портов, включая 465 и даже 2525, но поскольку 25 поддерживается всеми поставщиками электронной почты, достаточно придерживаться этого.

Сервер электронной почты весит меньше, чем 5MiB целом, и работает просто прекрасно на моем древнем Raspberry Pi 2 - если он доступен через общедоступный IPv4-адрес в порту 25, вы готовы.

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

Чтобы стать поставщиком почтовых ящиков, необходим домен. К счастью, с таким количеством доступных доменов верхнего уровня, вы можете получить один по действительно доступной цене.

Как только вы становитесь гордым владельцем домена Интернета, необходимо настроить две записи DNS, чтобы сделать ваш сервер работоспособным. Ниже приведены примеры настройки домена idont.date и IP-адреса машины, которую я использую, поэтому убедитесь, что вы соответственно заменили их своим именем домена и IP-адресом.

  1. Запись A, указывающая на IP-адрес сервера, например `[A] [smtp.idont.date] [3.143.135.0]`
  2. Запись MX (обмен почтой), которая указывает на запись A выше, например `[MX] [idont.date] [smtp.idont.date]`

С этими двумя записями, серверы, которые собираются отправить вам почту, смогут узнать, куда направить информацию. Сервер электронной почты просто разрешит записи DNS и выяснит, на какой IP-адрес он должен отправить всю информацию.

Вот и все! После настройки сервера и DNS сервера всё готово к приему почты. Вы можете попробовать это, отправив электронное письмо на ваш новый домен или подписавшись на ту рассылку, которую вы всегда так ненавидели.

Статья на list-site.