Второй PR почты по согласованной схеме. Сначала мерж #26 — этот PR построен на нём (его коммит тоже виден здесь; после мержа #26 останется только свой).
Что делает
Несколько ящиков у одного логина: слева в меню MAILBOXES — свой, общие (участник), подключённые (⊕: адрес + пароль того ящика, с LoginGuard). Клик — переключиться (сессия ящика, JWT с by = логин), × — убрать из меню. Непрочитанные — INBOX + свои папки.
Общий ящик (support@, billing@): галочка «shared» при создании, кнопка group — участники. Своего входа нет (веб, SMTP, IMAP — отказ), «прочитано» общее, у письма «Answered by …» (ответ из веб-почты).
Почтовые программы: ящик*свой_логин + свой пароль — IMAP и SMTP (письма от имени общего ящика; MAIL FROM чужого адреса — 553).
В открытом чужом ящике (общий / подключённый / OPEN админа) профиль и пароль не меняются — 403.
Служебное API: PUT /api/service/shared/{address}{displayName, members[]}; выключение аккаунта убирает и из рассылок, и из общих ящиков.
README: несколько ящиков, общие, ящик*логин.
Проверено
88 тестов (ImapServerTest один раз упал на STARTTLS — флак, 2 перезапуска зелёные, полный прогон зелёный).
Живой прогон jar на Postgres 17 с апгрейдом V6→V7 на данных первого прогона: shared создан с участниками; вход общим ящиком — отказ (веб, SMTP 535); support*bob SMTP OK, MAIL FROM bob в этой сессии — 553, отправка от support OK; IMAP support*bob OK, без доступа — отказ; сессия чужого ящика без доступа — 403; смена пароля в открытом ящике — 403; bob ответил из support → у jambotronpw в support видно answeredBy=bob; подключить staging@ (неверный пароль 400, верный — ATTACHED с непрочитанными), убрать — 204.
Скриншоты UI (левое меню с support@ и счётчиком, настройки: SHARED, участники, LISTS). ng build OK.
Дальше: PR Jambotron (роль → ящик <username>@, назначения → рассылки → роли, раздел чеклиста), Kuma → alerts-prod@/alerts-staging@.
Второй PR почты по согласованной схеме. **Сначала мерж #26** — этот PR построен на нём (его коммит тоже виден здесь; после мержа #26 останется только свой).
**Что делает**
- **Несколько ящиков у одного логина**: слева в меню **MAILBOXES** — свой, общие (участник), подключённые (⊕: адрес + пароль того ящика, с LoginGuard). Клик — переключиться (сессия ящика, JWT с `by` = логин), × — убрать из меню. Непрочитанные — INBOX + свои папки.
- **Общий ящик** (`support@`, `billing@`): галочка «shared» при создании, кнопка `group` — участники. Своего входа нет (веб, SMTP, IMAP — отказ), «прочитано» общее, у письма **«Answered by …»** (ответ из веб-почты).
- **Почтовые программы**: `ящик*свой_логин` + свой пароль — IMAP и SMTP (письма от имени общего ящика; MAIL FROM чужого адреса — 553).
- В открытом чужом ящике (общий / подключённый / OPEN админа) профиль и пароль не меняются — 403.
- Служебное API: `PUT /api/service/shared/{address}` `{displayName, members[]}`; выключение аккаунта убирает и из рассылок, и из общих ящиков.
- README: несколько ящиков, общие, `ящик*логин`.
**Проверено**
- 88 тестов (ImapServerTest один раз упал на STARTTLS — флак, 2 перезапуска зелёные, полный прогон зелёный).
- Живой прогон jar на Postgres 17 с **апгрейдом V6→V7 на данных** первого прогона: shared создан с участниками; вход общим ящиком — отказ (веб, SMTP 535); `support*bob` SMTP OK, MAIL FROM bob в этой сессии — 553, отправка от support OK; IMAP `support*bob` OK, без доступа — отказ; сессия чужого ящика без доступа — 403; смена пароля в открытом ящике — 403; bob ответил из support → у jambotronpw в support видно `answeredBy=bob`; подключить staging@ (неверный пароль 400, верный — ATTACHED с непрочитанными), убрать — 204.
- Скриншоты UI (левое меню с support@ и счётчиком, настройки: SHARED, участники, LISTS). `ng build` OK.
**Дальше**: PR Jambotron (роль → ящик `<username>@`, назначения → рассылки → роли, раздел чеклиста), Kuma → `alerts-prod@`/`alerts-staging@`.
α
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- V6 mail_lists + mail_list_members: письмо на alerts-prod@ → каждому участнику своя копия в папку рассылки;
закрытая рассылка — только от вошедших отправителей (550 снаружи)
- bob+prod@ → ящик bob@, папка prod (создаётся сама; системные папки нельзя)
- TRAP: чужие адреса → одна копия в INBOX отправителя; наши ящики и рассылки доставляются
- /api/service/** (SERVICE_TOKEN из secrets-init): аккаунты (пароль один раз, выключение → вон из рассылок), рассылки
- MailDirectory: одно пространство адресов для ящиков и рассылок, без «+» в именах
- Настройки → LISTS для администраторов
- 86 тестов; живой прогон на Postgres 17: миграции V1–V6, API, SMTP (рассылка/метка/ловушка)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- V7: users.is_shared, mailbox_access (MEMBER от админа/Jambotron, ATTACHED по паролю ящика), messages.answered_by
- /api/mailboxes: мои ящики с непрочитанными, сессия другого ящика (JWT с claim by), подключить по паролю
(LoginGuard), убрать из меню
- общий ящик: без своего входа (веб/SMTP/IMAP), участники открывают; «прочитано» общее; ответ из веба → answered_by
- SMTP/IMAP: ящик*логин + пароль логина (как master user в Dovecot)
- открытый чужой ящик (общий, подключённый, OPEN админа): профиль и пароль не меняются (403)
- админ: создать shared, участники ящика (PUT /{id}/members); служебное API: PUT /shared/{address};
выключение аккаунта убирает и из общих ящиков
- UI: MAILBOXES в левом меню (переключение, ⊕ подключить, × убрать), shared/участники в настройках,
«Answered by» у письма
- 88 тестов; живой прогон на Postgres 17 (апгрейд V6→V7 на данных), скриншоты UI
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Второй PR почты по согласованной схеме. Сначала мерж #26 — этот PR построен на нём (его коммит тоже виден здесь; после мержа #26 останется только свой).
Что делает
by= логин), × — убрать из меню. Непрочитанные — INBOX + свои папки.support@,billing@): галочка «shared» при создании, кнопкаgroup— участники. Своего входа нет (веб, SMTP, IMAP — отказ), «прочитано» общее, у письма «Answered by …» (ответ из веб-почты).ящик*свой_логин+ свой пароль — IMAP и SMTP (письма от имени общего ящика; MAIL FROM чужого адреса — 553).PUT /api/service/shared/{address}{displayName, members[]}; выключение аккаунта убирает и из рассылок, и из общих ящиков.ящик*логин.Проверено
support*bobSMTP OK, MAIL FROM bob в этой сессии — 553, отправка от support OK; IMAPsupport*bobOK, без доступа — отказ; сессия чужого ящика без доступа — 403; смена пароля в открытом ящике — 403; bob ответил из support → у jambotronpw в support видноansweredBy=bob; подключить staging@ (неверный пароль 400, верный — ATTACHED с непрочитанными), убрать — 204.ng buildOK.Дальше: PR Jambotron (роль → ящик
<username>@, назначения → рассылки → роли, раздел чеклиста), Kuma →alerts-prod@/alerts-staging@.α
🤖 Generated with Claude Code
- V7: users.is_shared, mailbox_access (MEMBER от админа/Jambotron, ATTACHED по паролю ящика), messages.answered_by - /api/mailboxes: мои ящики с непрочитанными, сессия другого ящика (JWT с claim by), подключить по паролю (LoginGuard), убрать из меню - общий ящик: без своего входа (веб/SMTP/IMAP), участники открывают; «прочитано» общее; ответ из веба → answered_by - SMTP/IMAP: ящик*логин + пароль логина (как master user в Dovecot) - открытый чужой ящик (общий, подключённый, OPEN админа): профиль и пароль не меняются (403) - админ: создать shared, участники ящика (PUT /{id}/members); служебное API: PUT /shared/{address}; выключение аккаунта убирает и из общих ящиков - UI: MAILBOXES в левом меню (переключение, ⊕ подключить, × убрать), shared/участники в настройках, «Answered by» у письма - 88 тестов; живой прогон на Postgres 17 (апгрейд V6→V7 на данных), скриншоты UI Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>