fix
This commit is contained in:
@@ -48,7 +48,7 @@ gofmt -l . # список неотформатированных файл
|
|||||||
1. `parseCSV` → `validateRow` — структурная проверка без сети (email, пароль, дубликаты в файле).
|
1. `parseCSV` → `validateRow` — структурная проверка без сети (email, пароль, дубликаты в файле).
|
||||||
2. `enrichRow` — сверка с живым mailcow: несуществующий домен → `error`, существующий ящик → `exists` (пропуск). Работает только если заданы креды.
|
2. `enrichRow` — сверка с живым mailcow: несуществующий домен → `error`, существующий ящик → `exists` (пропуск). Работает только если заданы креды.
|
||||||
3. `checkDomainQuota` — воспроизводит проверку mailcow: свободная квота домена = `max_quota_for_domain` − Σ(выделенных квот существующих ящиков). Если Σ квот импортируемых строк домена превышает свободную — возвращает `quotaWarn` (в МиБ). UI показывает предупреждение и **блокирует** импорт до подъёма квоты домена (домены с квотой 0 = безлимит пропускаются).
|
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 хеширует как есть — искажения нет.
|
||||||
|
|
||||||
### Ключевые соглашения
|
### Ключевые соглашения
|
||||||
|
|
||||||
|
|||||||
@@ -111,3 +111,13 @@ curl -sk -X POST https://mail.dom.ru/api/v1/edit/domain \
|
|||||||
- Публикация порта в примере — только на `127.0.0.1`.
|
- Публикация порта в примере — только на `127.0.0.1`.
|
||||||
- Слабые пароли mailcow отклонит по политике; такие строки видны в предпросмотре
|
- Слабые пароли mailcow отклонит по политике; такие строки видны в предпросмотре
|
||||||
как предупреждение и в журнале как `danger: password_complexity`.
|
как предупреждение и в журнале как `danger: password_complexity`.
|
||||||
|
|
||||||
|
## Доступы новых ящиков
|
||||||
|
|
||||||
|
При создании инструмент явно включает IMAP/POP3/SMTP/Sieve/SOGo-доступ, а не
|
||||||
|
полагается на серверные дефолты (`$MAILBOX_DEFAULT_ATTRIBUTES`). Иначе на
|
||||||
|
инстансе с переопределёнными дефолтами ящик создаётся «успешно», но вход не
|
||||||
|
проходит — выглядит как «пароль не подходит», хотя пароль верный. Флаг
|
||||||
|
`force_pw_update` управляется галкой «Требовать смену пароля при входе» (по
|
||||||
|
умолчанию выключена — иначе клиенты IMAP/SMTP получат отказ до смены пароля
|
||||||
|
через веб-интерфейс).
|
||||||
|
|||||||
@@ -265,6 +265,15 @@ func handleImport(w http.ResponseWriter, r *http.Request) {
|
|||||||
"force_pw_update": force,
|
"force_pw_update": force,
|
||||||
"tls_enforce_in": "0",
|
"tls_enforce_in": "0",
|
||||||
"tls_enforce_out": "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)
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||||
code, body, err := mcDo(ctx, base, key, "POST", "/api/v1/add/mailbox", payload)
|
code, body, err := mcDo(ctx, base, key, "POST", "/api/v1/add/mailbox", payload)
|
||||||
|
|||||||
Reference in New Issue
Block a user