Создаём тестовое окружения для тестирования имейл-функциональности при помощи GreenMail.

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

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

  1. Используя сторонние сервисы. Этот вариант чаще всего используют приложения "смотрящие" во внешний интернет. Причин несколько. Как правило такие приложения заточены на работу с большим количеством клиентов (подписчиков), которые дали свое согласие на получение имейл уведомлений либо рассылок от ваших сервисов. Сторонние сервисы рассылки могут в таких случаях решать несколько сопутствующих проблем. Например, письма от таких сервисов с меньшей вероятностью отфильтруются спам-фильтром пользовательских мейл-клиентов. Также такие сервисы часто предлагают довольно мощные аналитические инструменты, при помощи которых можно отслеживать эффективность своей коммуникации.

  2. Используя собственные SMTP, POP3, IMAP сервера. Такой вариант часто используется во внутрикорпоративных приложениях, где анализировать эффективность имейл-коммуникации не нужно, зато нужно обеспечить полный контроль над имейл-трафиком сотрудников и систем.

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

Почему тестирование имейл-коммуникации на реальной инфраструктуре - плохая идея.

Прочитав вступление, вы можете сказать: "И что тут такого? Я всегда тестировал имейлинг на нашем корпоративном SMTP-сервере. И до сих пор не было никаких проблем. Что тут такого?". Это может означать только одно: Вы - везучий человек. Я бы выделил несколько причин, по которым тестировать имейлинг на реальной инфраструктуре не следует.

  1. Первая, и одновременно самая важная - вопрос безопасности. Тестируя функциональность корреспонденции, вы можете случайно отправить письма из тестовой среды реальным пользователям. Это, в свою очередь, может привести у утечке конфиденциальной информации как ваших пользователей, так и вашей компании-разработчика.

  2. Высокая нагрузка на корпоративную почту, не несущая никакой текущей бизнес-ценности. Если ваше приложение генерирует большой объем трафика в малый период времени, есть высокая вероятность "перегреть" ваш мейл-сервер, что может отразиться на сбоях у других пользователей.

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

Таким образом, используя сервер-заглушку, вы сможете повысить надежность и эффективность ваших тестов.

Описание примера

В нашем примере мы установим GreenMail сервер-заглушку, поддерживающую протоколы SMTP, POP3, IMAP и их TLS-обертки. Мы сконцентрируемся на первых двух протоколах, чтобы не усложнять статью.

Мы узнаем как создавать пользовательские аккаунты на сервере, как отправлять и получать письма используя один из популярных мейл-клиентов Mozilla Thunderbird (остальные будут конфигурироваться примерно так же).

Итак, мы почти готовы начать. Осталось соблюсти одно необходимое условие. Так как библиотека написана на языке Java, нам необходимо сперва установить JRE, а также прописать путь до исполняемого файла java/java.exe в переменную окружения PATH. Опционально можно убедиться в том, что порты, которые вы собираетесь использовать для запуска сервера, свободны и доступны из необходимых мест вашей сети (в противном случае, вы сможете взаимодействовать с сервером только локально через localhost).

Быстрая настройка GreenMail

Как я уже упомянул ранее, GreenMail - Java-библиотека. Эта библиотека распространяется как jar-архив. Стоит отметить, что она распространяется в нескольких видах. В зависимости от того для чего вы собираетесь её использовать (как часть вашего автоматизированного решения или как инфраструктуру для ручного тестирования), вам могут понадобиться различные дистрибутивы. Для ручного тестирования нам потребуется standalone-дистрибутив. Этот дистрибутив является самодостаточным исполняемым файлом, который можно запустить простой командой в командной строке. Такой вариант, хоть и является менее гибким, чем запуск из автоматического теста, но зато ваш сервер может быть доступен большему кругу людей и использоваться тестами, написанными на любом языке программирования, а не только на Java.

Так как моя статья рассказывает в основном про #ручное тестирование, мы не будем управлять всем из кода. Вообще-то мы даже не напишем ни одной строчки кода сегодня, а поэтому нам необходимо скачать standalone-дистрибутив. Самые свежие дистрибутивы вы сможете скачать на официальном сайте проекта GreenMail. Вам необходимо перейти по ссылке и скачать файл напротив GreenMail Standalone (только не трогайте ссылку "Docker Hub" - это не то, что нам сейчас нужно). Сохраните скачанный файл в какую-нибудь папку на жестком диске, откуда вам было бы удобно его запускать.

Теперь откройте командную строку, перейдите в каталог со скачанным standalone-дистрибутивом и выполните команду

java -Dgreenmail.setup.test.all -jar greenmail-standalone-1.5.11.jar

Где:

  • java - означает, что вы собираетесь запустить Java-приложение

  • -Dgreenmail.setup.test.all - один из способов, которым Java-приложения получают информацию из внешней среды (это называется системное свойство). -D определяет свойство как "системное", а greenmail.setup.test.all - имя свойства. Вы можете ознакомиться с полным списком поддерживаемых GreenMail свойств на странице официальной документации проекта. Мы коснемся некоторых из них позже в наших примерах. Это конкретное свойство отвечает за запуск всех поддерживаемых протоколов на портах, которые смещены на 3000 от их стандартных значений. Например, протокол SMTP будет запущен на порте 3025, POP3 - на порте 3110 и так далее.

  • greenmail-standalone-1.5.11.jar - имя standalone-дистрибутива GreenMail, который я использую в своей статье (на данный момент - самый свежий), но в вашем случае это имя может отличаться.

Если вам необходимо запустить только некоторые протоколы на "дефолтовых" тестовых портах, вы можете использовать такую команду:

java -Dgreenmail.setup.test.smtp -Dgreenmail.setup.test.pop3 -jar greenmail-standalone-1.5.11.jar

В данном случае, мы запускаем только SMTP и POP3 протоколы на портах 3025 и 3110 соответственно.

Указанные команды запустят "быструю конфигурацию" GreenMail, с которой у вас не будет проблем до тех пор пока вы либо не обнаружите, что тестовые порты заняты, либо вам не понадобится подключаться к GreenMail с какого-то другого компьютера сети.

Настраиваем хост и порты в GreenMail

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

Когда вы передаете системный свойства в приложение, которое распространяется как исполняемый jar-архив, вам необходимо перечислить все свойства до указания имени самого архива. Как показано ниже:

java -Dprop1 -Dprop2 …​ -DpropN -jar yourexecutable.jar

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

  1. Каждый протокол должен быть привязан к какому-то порту и какому-то ip-адресу

  2. Существует привязка к ip-адресу по умолчанию: 127.0.0.1. Такая привязка, правда, не позволит вам присоединяться к вашему сервису с других компьютеров, т.к. обращение к локалхосту с их стороны будет означать попытку приконнектиться к самому себе. Если вам надо использовать ваш сервис с удаленных компьютеров сети, лучше всего привязать протоколы к адресу 0.0.0.0. Это специальный адрес, обозначающий, что сервер будет принимать входящие соединения, вне зависимости от используемого адреса. Конечно же этот адрес будет тем не менее ассоциироваться с физическим хостом. Такая привязка используется если ваша машина имеет несколько сетевых интерфейсов и, как следствие, может иметь несколько ip-адресов в сети. Для изменения адреса привязки по умолчанию существует специально свойство. Пример его использования такой: -Dgreenmail.hostname=0.0.0.0.

  3. Вы можете не указывать хост намеренно, т.к. существует значение по умолчанию. Однако, вы не можете не указывать портов для ваших протоколов. Номер порта конфигурируется для каждого протокола в отдельности, а свойство будет выглядеть так: -Dgreenmail.PROTOCOL.port=1234. Пример для протокола SMTP: -Dgreenmail.smtp.port=2025.

  4. Так же как и в ситуации с портами, разные протоколы могут быть привязаны к разным ip-адресам. Используйте следующий подход: -Dgreenmail.PROTOCOL.hostname=1.2.3.4. Опять же, пример для SMTP будет выглядеть так: -Dgreenmail.smtp.hostname=127.0.0.1.

  5. Более частные значения переписывают более общие. Например вы можете использовать привязку протоколов к ip-адресу по умолчанию, но переопределить её для каких-то конкретных протоколов. В том же ключе, если вы, например, используете свойство -Dgreenmail.setup.test.all, которое устанавливает значения по умолчанию для всего, вы, добавляя более специфичные свойства, можете переопределить значения для каких-то определённых протоколов. Ниже я покажу несколько примеров с объяснениями.

-Dgreenmail.hostname=0.0.0.0 -Dgreenmail.setup.test.smtp -Dgreenmail.setup.test.pop3

Пример выше устанавливает тестовые настройки по умолчанию для протоколов SMTP (-Dgreenmail.setup.test.smtp) и POP3 (-Dgreenmail.setup.test.pop3) но переопределяет привязку к ip-адресу по умолчанию (-Dgreenmail.hostname=0.0.0.0) таким образом, что оба протокола в итоге сохраняют привязки к тестовым портам по умолчанию (те, что со сдвигов на 3000), но привязаны теперь не к т.н. луп-бэк адресу, а к 0.0.0.0 (т.е. ко всем возможным адресам, которые ваш компьютер потенциально может получить в сети). Других протоколов, кроме указанных двух, не запускается.

-Dgreenmail.hostname=0.0.0.0 -Dgreenmail.smtp.port=12345 -Dgreenmail.setup.test.pop3

Пример выше запускает GreenMail с двумя протоколами: SMTP, стартующем на порту 12345 и POP3, стартующем на дефолтном тестовом порту 3110. Оба протокола имеют привязку к "общему" адресу 0.0.0.0 и доступны из внешних узлов сети.

-Dgreenmail.smtp.port=12345 -Dgreenmail.setup.test.pop3

Пример выше практически идентичен предыдущему. За тем лишь исключением, что в данном случае оба протокола привязаны к адресу 127.0.0.1, а значит, могут быть использованы только с того же компьютера, где запускается сам сервис.

-Dgreenmail.smtp.port=12345

Пример выше показывает как можно запустить только протокол SMTP, доступный для подключения только с локальной машины.

-Dgreenmail.smtp.port=12345 -Dgreenmail.smtp.hostname=0.0.0.0 -Dgreenmail.pop3.port=1110

Пример выше показывает как можно запустить только протоколы SMTP и POP3, доступные для подключений извне. Оба протокола запускаются на нестандартных портах.

Настраиваем пользователей

GreenMail - это сервис-песочница, который не предназначен для того, чтобы сохранять своё состояние между перезапусками. Если на вашем сервере в процессе тестирования накопилось какое-то состояние (переписка и/или пользователи), то всё это будет утеряно после остановки сервера. Как мы, в таком случае, настраиваем пользователей на сервере? В GreenMail существует два пути, которыми на сервере могут быть созданы пользовательские аккаунты.

Первый способ - это добавление пользователей при старте через системные свойства (так же как мы настраиваем протоколы и порты). Существует несколько паттернов, которыми можно описать добавляемые пользовательские аккаунты. Я предпочитаю такой:

-Dgreenmail.users=account1:pwd1@emaildomain1,account2:pwd2@emaildomain2,...

Свойство -Dgreenmail.users просто добавляется к остальным системным свойствам при запуске сервера. Не смотря на то, что вы сможете создать пользователя, даже если у вас включен только SMTP-протокол, в нашем примере для демонстрационных целях мы будем также включать протокол POP3 для получения входящих сообщений. Так, используя следующий набор свойств, мы можем запустить протоколы SMTP и POP3 с некоторым тестовым пользовательским аккаунтом:

-Dgreenmail.smtp.port=12345 -Dgreenmail.pop3.port=54321 -Dgreenmail.users=testacc:testpwd@webelement.click

Пример выше запустит протоколы SMTP и POP3 доступные только для локальных соединений, а также сконфигурирует аккаунт с именем пользователя testacc, паролем testpwd и имейл-адресом testacc@webelement.click.

Второй способ - когда вы отправляете имейл на адрес, который не имеет ассоциированного аккаунта на сервере. Если имейл отправляется через SMTP, поднятом на GreenMail, и аккаутна с таким имейлом не существует, то такой аккаунт создается автоматически. В таком случае имя пользователя создается равным самому адресу (в отличие от первого способа, где имя пользователя отличается от имейл-адреса). Пароль устанавливается равным имени пользователя, и, очевидно, самому имейл-адресу. Мы взглянем на эти процессы по-внимательнее в следующем параграфе.

Подключаем имейл-клиент к GreenMail

Ваши тесты не будут надежными и эффективными если вы не будете иметь возможность отправлять и получать письма, используя стандартные имейл-клиенты, такие как, например, Mozilla Thunderbird. На его примере далее мы рассмотрим как отправлять и получать письма внутри GreenMail, а также рассмотрим процесс создания новых пользователей на сервере.

Тут я предполагаю, что у вас уже установлен мейл-клиент так что мы не будем начинать с "чистого листа". Давайте запустим оба протокола: SMTP и POP3 (возможности подключать только локальные соединения будет вполне достаточно для целей демонстрации принципа) так как мы уже делали это в примерах ранее:

java -Dgreenmail.smtp.port=12345 -Dgreenmail.pop3.port=54321 -Dgreenmail.users=testacc:testpwd@webelement.click -jar greenmail-standalone-1.5.11.jar

Здесь вы должны увидеть некоторые лог-сообщения, которые сервер выводит в консоль (если вы конечно не "отцепили" ваш сервер от консоли, что скорее всего вы не делали, т.к. следовали инструкциям из статьи). Лог сам по себе довольно информативен даже не смотря на то, что сейчас сервер запущен в "немногословном" режиме (режим детализации логов также может быть изменен при помощи соответствующего свойства). Из лога можно почерпнуть какие протоколы и на каких портах подняты, а также к каким ip-адресам они привязаны. Теперь мы можем начать настраивать наш мейл-клиент на только что запущенный нами сервер GreenMail.

GreenMail with mail client Step 1

Нажмите кнопку [Email] под строкой "Set up an account". Вы увидите диалог настройки мейл-аккаунта. Его состояние по умолчанию предполагает, что Thunderbird настроит всё автоматически за вас, однако мы всё же действуем внутри некой модели (пусть даже весьма точной) инфраструктуры, поэтому нам придется настраивать всё вручную. Введите имя, имя пользователя (имя аккаунта), имейл адрес и пароль. Вы можете указать какое угодно имя, но имя аккаунта, имейл и пароль должны соответствовать той конфигурации, которую мы задали при старте. Помните, что имя аккаунта - testacc, пароль - testpwd, а адрес электронной почты - testacc@webelement.click. После того, как эти поля заполнены, нажмите кнопку [Manual config].

GreenMail with mail client Step 2

Теперь нам надо указать параметры соединения с нашими сервисами. Поля, которые требуется изменить выделены оранжевой линией. Установить протокол входящих сообщений в POP3, поменяйте "server host name" для обоих протоколов на localhost, измените номера портов так, чтобы они соответствовали указанным портам при запуске сервера: 54321 для POP3 и 12345 для SMTP. Нажмите кнопку [Re-test]. Параметры SSL и Authentication будут запрошены с сервера, и установятся в нашем диалоге автоматически.

GreenMail with mail client Step 3

Нажмите кнопку [Done]. Вы увидите предупреждение о том, что сервер не использует SSL шифрование. Поставьте галочку в чекбокс "I understand the risk" и нажмите [Done]. Поздравляю! Через ваш имейл клиент теперь можно отправлять и принимать почту используя аккаунт testacc.

GreenMail with mail client Step 4

Q: Я отправил письмо по реально существующему адресу. Значит ли это, что владелец этого адреса получит мое письмо?

A: Нет. Реальный владелец адреса не получит вашего письма, потому что GreenMail - это сервер-песочница. Вся переписка живет только внутри самого GreenMail и никогда не выходит наружу. Если вы отправили письмо по этому адресу в первый раз, то на сервере будет создан аккаунт, ассоциированный с данным адресом. Подключившись к серверу от имени этого аккаунта, вы сможете увидеть сообщение во "входящих".

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

Нажмите кнопку [Write] - вы увидите редактор письма. Укажите какой-нибудь несуществующий адрес в поле To:. Таким адресом, например, может быть адрес testacc@webelement.pleasedontclick. Укажите также какую-у тему письма и введите текст в тело письма (также можно добавить вложения). Нажмите кнопку [Send]. Теперь посмотрите в консоль где вы запустили сервер GreenMail. Вы должны увидеть там нечто подобное:

"Created user login testacc@webelement.pleasedontclick for address testacc@webelement.pleasedontclick with password testacc@webelement.pleasedontclick because it didn’t exist before"

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

GreenMail with mail client Step 5

Поля, на которые указывают стрелки (и само поле имейла) должны содержать полное значение имейл адреса (т.е. testacc@webelement.pleasedontclick). Как только вы подтвердите все последующие диалоги, вы увидите, что теперь в списке ваших аккаунтов появился еще один - тот, что мы только что настроили. Вы также заметите, что в ящике входящих писем уже лежит одно письмо. Как раз то, которое мы туда недавно отправили.

GreenMail with mail client Step 6

Теперь вы знаете как настроить полнофункциональное тестовое окружение таким образом чтобы свести риск утечки конфиденциальных данных к нулю. Если у вас остались вопросы, задавайте их тут. Я постараюсь дополнить статью опираясь на ваши замечания.