01.10.2026 Технический разбор RU

Волгатех.Коллектив: своя почта для университетского Exchange

В версии 0.5.0 «Почта» стала встроенным клиентом вместо веб-версии в окне приложения. Университетская почта — локальный Exchange без OAuth, поэтому клиенту нужен пароль, а приложение до сих пор обходилось без него. Как это решено, как устроен вход по NTLM и что клиент умеет.

Никита Конкин

Проект Репозиторий Скачать APK
Языковые версии: RU EN

До версии 0.5.0 «Почта» в Волгатех.Коллективе открывала веб-версию почты внутри приложения. Это работало, но оставалось сайтом в окне: без значка непрочитанных, без жестов и с вёрсткой, рассчитанной на компьютер. 30 сентября вышла версия со встроенным почтовым клиентом. На скриншотах здесь и ниже — вымышленные письма и адреса.

Список входящих: группа «Закреплённые», заголовки «Сегодня», «Вчера», «На этой неделе», строки окрашены от бледно-жёлтого до красного по размеру письма
Входящие: заголовки по датам, закреплённые письма сверху, размер каждого письма и цвет строки по размеру.
Строка письма, сдвинутая влево, с красной кнопкой «Удалить»
Свайп влево удаляет письмо, и несколько секунд его можно вернуть; свайп вправо отмечает прочитанным.
Меню почты: «Веб-версия», «Подпись», «Автоответ», «Размер ящика», переключатели «Закреплённые сверху» и «Цвет по размеру», «Выйти из почты»
Меню почты: веб-версия, подпись, автоответ, размер ящика и выход из почты.

Пароль, который всё-таки понадобился

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

Почта университета — локальный Exchange, а не Microsoft 365. У него нет ни OAuth, ни Graph API: клиент может войти только с паролем от почты. Поэтому решение устроено так, чтобы пароль появлялся лишь у тех, кто сам этого захотел:

  • встроенный клиент — в отдельной сборке. Каждый выпуск содержит два набора APK одного приложения: app-mail-* со встроенной почтой и обычные app-*, где почта по-прежнему открывается веб-версией;
  • у обеих сборок одна подпись, поэтому любая ставится поверх другой, и вернуться к веб-версии можно в любой момент;
  • пароль хранится в защищённом хранилище ОС и удаляется пунктом «Выйти из почты».

Сценарий выпуска собирает оба набора и перед публикацией проверяет сертификат подписи у каждого APK — так же, как это делалось для обычной сборки начиная с версии 0.4.2.

Вход по NTLM

Клиент говорит с сервером через Exchange Web Services, а вход по HTTP там выполняется по NTLMv2. Рукопожатие реализовано в самом приложении, по спецификации MS-NLMP. Нужна только его часть, отвечающая за проверку подлинности: протоколу HTTP не требуются подпись и шифрование сообщений, поэтому сеансовый ключ не согласуется.

Самодельная криптография — то место, где ошибку не видно, пока сервер не откажет во входе. Поэтому тесты сверяют вычисления с примером из самой спецификации: хеш NTOWFv2, NTProofStr и ответ LMv2 должны совпасть с опубликованными значениями байт в байт. Отдельно проверено, что логин вида ДОМЕН\имя разбивается на домен и имя, а адрес вида имя@домен передаётся целиком.

Список, похожий на Outlook

Список писем повторяет привычное по Outlook: заголовки «Сегодня», «Вчера», «На этой неделе», точки у непрочитанных, а письма, закреплённые в Outlook, собраны сверху в сворачиваемую группу. Есть поиск, выбор папки с числом непрочитанных, обновление жестом вниз; первая страница сохраняется и открывается без сети. Число непрочитанных показывается значком у пункта «Почта» и на кнопке меню.

Ящик университетской почты ограничен по размеру, поэтому у каждого письма показан размер, а строка окрашивается по нему: бледно-жёлтым от 100 КБ, оранжевым к 1 МБ, красным от 10 МБ. Шкала — последовательная палитра от жёлтого к красному, так что большое письмо видно, не читая цифр. Цвет и группу закреплённых можно отключить в меню.

Чтение без слежки

Письма в HTML показываются в изолированной странице с политикой безопасности содержимого: скрипты запрещены, внешние загрузки тоже. Это отключает пиксели отслеживания и удалённые картинки — письмо не сообщает отправителю, что его открыли. Разрешены только встроенные стили и вложенные изображения: картинки, на которые письмо ссылается через cid:, встраиваются прямо в страницу. Обычный текст экранируется и показывается как есть.

Вложения можно открыть, сохранить на телефон или отправить в другое приложение; по строке отправителя видны все участники переписки; письмо можно перенести в другую папку.

Письмо, автоответ и размер ящика

Экран «Новое письмо»: в поле «Кому» введено «иван», под ним подсказки из трёх вымышленных адресов, ниже тема и текст с подписью
Новое письмо: подсказки из адресной книги университета и подпись, импортированная из веб-версии.
Экран «Размер ящика»: 402,0 МБ из 512,0 МБ, шкала цветов от 100 КБ до 10 МБ и список папок с размерами
Размер ящика: занятое место по папкам, лимит, введённый вручную, и удалённые письма, которые в лимит не входят.

Ответ и пересылка, подсказки из адресной книги университета в полях «Кому» и «Копия», вложения до 18 МБ. Подпись один раз импортируется из веб-версии. После нажатия «Отправить» есть пять секунд, чтобы передумать, а неотправленный текст сохраняется черновиком.

«Автоответ» устанавливается на сервере, как в Outlook, поэтому работает и при выключенном телефоне.

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

Дальше

Следующие шаги — уведомления о новых письмах и закрепление писем прямо из приложения. Обычные сборки с веб-версией почты остаются в каждом выпуске.

Выводы

  1. Принцип «приложение не хранит пароль» стоит нарушать только явно: отдельной сборкой, которую человек выбирает сам, с паролем в хранилище ОС и понятным способом его удалить.
  2. Одна подпись у двух сборок превращает выбор в обратимый: любая ставится поверх другой.
  3. Собственную реализацию протокола проверяют по примерам из спецификации: ошибка в хеше иначе выглядит как «неверный пароль».
  4. Почтовый клиент, который не загружает внешние ресурсы, не сообщает отправителю о прочтении. Такую защиту стоит закладывать с первой версии.
  5. Данные сервера нужно показывать так, как он их считает: удалённые письма, которые не входят в лимит, нельзя прибавлять к занятому месту.

Доступность

Приложение распространяется в виде APK для Android. Для большинства современных телефонов подходят:

  • app-mail-arm64-v8a-release.apk — со встроенным почтовым клиентом;
  • app-arm64-v8a-release.apk — с веб-версией почты, как раньше.

Ссылки:

Теги

программирование flutter dart мобильная-разработка безопасность

Другие обновления по проекту

12.10.2026 Технический разбор Волгатех.Коллектив — мобильный личный кабинет работника ПГТУ

Волгатех.Коллектив: Liquid Glass — стекло, иней и узоры времён года

Как в приложении появилась тема «Liquid Glass»: полупрозрачные панели над цветным фоном, матовое стекло, иней из фрактальных кристаллов и узор по времени года — листья, иней, цв...

12.10.2026 Технический разбор Волгатех.Коллектив — мобильный личный кабинет работника ПГТУ

Волгатех.Коллектив: обновление из приложения, версия для iPhone и компьютеров, напоминания и виджет

Версии 0.5.1 и 0.5.2: приложение само предлагает обновление и проверяет файл перед установкой, работает в браузере — на iPhone без App Store и на компьютере в своей раскладке, н...