diff --git a/CLAUDE.md b/CLAUDE.md index 0ae414f..46b8d36 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,7 +48,7 @@ gofmt -l . # список неотформатированных файл 1. `parseCSV` → `validateRow` — структурная проверка без сети (email, пароль, дубликаты в файле). 2. `enrichRow` — сверка с живым mailcow: несуществующий домен → `error`, существующий ящик → `exists` (пропуск). Работает только если заданы креды. 3. `checkDomainQuota` — воспроизводит проверку mailcow: свободная квота домена = `max_quota_for_domain` − Σ(выделенных квот существующих ящиков). Если Σ квот импортируемых строк домена превышает свободную — возвращает `quotaWarn` (в МиБ). UI показывает предупреждение и **блокирует** импорт до подъёма квоты домена (домены с квотой 0 = безлимит пропускаются). -4. `handleImport` — POST на `/api/v1/add/mailbox`, ответ разбирается `parseMailcowMsg`. Используется **только** `add` — существующие ящики никогда не модифицируются (идемпотентность). +4. `handleImport` — POST на `/api/v1/add/mailbox`, ответ разбирается `parseMailcowMsg`. Используется **только** `add` — существующие ящики никогда не модифицируются (идемпотентность). Payload **явно** задаёт `imap_access`/`pop3_access`/`smtp_access`/`sieve_access`/`sogo_access` = `1`: иначе mailcow берёт их из серверного `$MAILBOX_DEFAULT_ATTRIBUTES`, и при переопределённых дефолтах ящик создаётся, но логин не проходит (симптом «пароль не подходит»). Пароль mailcow хеширует как есть — искажения нет. ### Ключевые соглашения diff --git a/README.md b/README.md index 028dd31..a9a5cd0 100644 --- a/README.md +++ b/README.md @@ -111,3 +111,13 @@ curl -sk -X POST https://mail.dom.ru/api/v1/edit/domain \ - Публикация порта в примере — только на `127.0.0.1`. - Слабые пароли mailcow отклонит по политике; такие строки видны в предпросмотре как предупреждение и в журнале как `danger: password_complexity`. + +## Доступы новых ящиков + +При создании инструмент явно включает IMAP/POP3/SMTP/Sieve/SOGo-доступ, а не +полагается на серверные дефолты (`$MAILBOX_DEFAULT_ATTRIBUTES`). Иначе на +инстансе с переопределёнными дефолтами ящик создаётся «успешно», но вход не +проходит — выглядит как «пароль не подходит», хотя пароль верный. Флаг +`force_pw_update` управляется галкой «Требовать смену пароля при входе» (по +умолчанию выключена — иначе клиенты IMAP/SMTP получат отказ до смены пароля +через веб-интерфейс). diff --git a/main.go b/main.go index 2e91fea..84a065e 100644 --- a/main.go +++ b/main.go @@ -265,6 +265,15 @@ func handleImport(w http.ResponseWriter, r *http.Request) { "force_pw_update": force, "tls_enforce_in": "0", "tls_enforce_out": "0", + // Явно открываем протоколы доступа, а не полагаемся на серверные + // $MAILBOX_DEFAULT_ATTRIBUTES: если админ инстанса переопределил их + // в 0, ящик создаётся «успешно», но логин по IMAP/SMTP не проходит + // (выглядит как «пароль не подходит»). UI mailcow эти галки включает. + "imap_access": "1", + "pop3_access": "1", + "smtp_access": "1", + "sieve_access": "1", + "sogo_access": "1", } ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) code, body, err := mcDo(ctx, base, key, "POST", "/api/v1/add/mailbox", payload)