mail.niikn.com: DNS настроен, сценарий задокументирован для dttb.ru
- README НИИКН: обновлён Mailcow (пароль, DNS, порты, ящик) - changelog: добавлена запись о настройке mail.niikn.com - credentials: добавлены Spaceweb, Mailcow НИИКН, NPM НИИКН - decisions: сценарий настройки почтового сервера (шаблон для dttb.ru) - snippets: скрипт spaceweb-dns-api.py для управления DNS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
97
decisions/2026-03-03-mailserver-setup-scenario.md
Normal file
97
decisions/2026-03-03-mailserver-setup-scenario.md
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# Сценарий настройки почтового сервера (Mailcow)
|
||||||
|
|
||||||
|
> Отработан на niikn.com (2026-03-03). Следующий: dttb.ru.
|
||||||
|
|
||||||
|
## Предусловия
|
||||||
|
- Mailcow установлен и запущен (docker compose)
|
||||||
|
- Белый IP есть
|
||||||
|
- Домен на Spaceweb DNS
|
||||||
|
|
||||||
|
## Шаги
|
||||||
|
|
||||||
|
### 1. MikroTik — проброс почтовых портов
|
||||||
|
```
|
||||||
|
/ip firewall nat add chain=dstnat dst-port=25 protocol=tcp action=dst-nat to-addresses=<MAILCOW_IP> comment="SMTP"
|
||||||
|
/ip firewall nat add chain=dstnat dst-port=465 protocol=tcp action=dst-nat to-addresses=<MAILCOW_IP> comment="SMTPS"
|
||||||
|
/ip firewall nat add chain=dstnat dst-port=587 protocol=tcp action=dst-nat to-addresses=<MAILCOW_IP> comment="Submission"
|
||||||
|
/ip firewall nat add chain=dstnat dst-port=993 protocol=tcp action=dst-nat to-addresses=<MAILCOW_IP> comment="IMAPS"
|
||||||
|
/ip firewall nat add chain=dstnat dst-port=995 protocol=tcp action=dst-nat to-addresses=<MAILCOW_IP> comment="POP3S"
|
||||||
|
/ip firewall nat add chain=dstnat dst-port=4190 protocol=tcp action=dst-nat to-addresses=<MAILCOW_IP> comment="Sieve"
|
||||||
|
```
|
||||||
|
> Порты 80/443 НЕ пробрасываем если NPM уже занимает их.
|
||||||
|
|
||||||
|
### 2. NPM — proxy host для mail.domain.com
|
||||||
|
- Создать proxy host: `mail.<DOMAIN>` → `https://<MAILCOW_IP>:443`
|
||||||
|
- Scheme: https (Mailcow сам обслуживает HTTPS)
|
||||||
|
- SSL: Let's Encrypt через NPM
|
||||||
|
- ssl_forced: true
|
||||||
|
|
||||||
|
### 3. DNS записи через Spaceweb API
|
||||||
|
Скрипт: `snippets/spaceweb-dns-api.py`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Получить текущие записи
|
||||||
|
python3 spaceweb-dns-api.py info <DOMAIN>
|
||||||
|
|
||||||
|
# A запись для mail (если нет)
|
||||||
|
python3 spaceweb-dns-api.py add-a <DOMAIN> mail <PUBLIC_IP>
|
||||||
|
|
||||||
|
# MX
|
||||||
|
python3 spaceweb-dns-api.py add-mx <DOMAIN> mail.<DOMAIN> 10
|
||||||
|
|
||||||
|
# SPF
|
||||||
|
python3 spaceweb-dns-api.py add-txt <DOMAIN> @ "v=spf1 mx a:mail.<DOMAIN> ~all"
|
||||||
|
|
||||||
|
# DMARC
|
||||||
|
python3 spaceweb-dns-api.py add-txt <DOMAIN> _dmarc "v=DMARC1; p=none; rua=mailto:admin@<DOMAIN>"
|
||||||
|
|
||||||
|
# DKIM (получить ключ из Mailcow → Configuration → ARC/DKIM)
|
||||||
|
python3 spaceweb-dns-api.py add-txt <DOMAIN> dkim._domainkey "<DKIM_KEY>"
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ Капча: после 2-3 запросов подряд нужна новая сессия (перезапустить скрипт).
|
||||||
|
|
||||||
|
### 4. Mailcow — домен и ящики
|
||||||
|
Через API (X-API-Key) или веб-интерфейс:
|
||||||
|
1. Добавить домен
|
||||||
|
2. Получить DKIM ключ (Configuration → ARC/DKIM)
|
||||||
|
3. Создать ящики
|
||||||
|
|
||||||
|
### 5. Пароль admin
|
||||||
|
```bash
|
||||||
|
# Через API:
|
||||||
|
curl -X POST https://mail.<DOMAIN>/api/v1/edit/admin \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "X-API-Key: <API_KEY>" \
|
||||||
|
-d '{"items":["admin"],"attr":{"password":"<PASS>","password2":"<PASS>"}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. PTR (rDNS)
|
||||||
|
Обратиться к провайдеру: `<PUBLIC_IP>` → `mail.<DOMAIN>`
|
||||||
|
|
||||||
|
### 7. Nextcloud SMTP (если есть)
|
||||||
|
Администрирование → Основные параметры → Email:
|
||||||
|
- SMTP, хост: `<MAILCOW_IP>`, порт: 587
|
||||||
|
- STARTTLS, LOGIN auth
|
||||||
|
- Логин: noreply@<DOMAIN>, пароль
|
||||||
|
|
||||||
|
### Проверка
|
||||||
|
```bash
|
||||||
|
dig mail.<DOMAIN> A +short # → <PUBLIC_IP>
|
||||||
|
dig <DOMAIN> MX +short # → mail.<DOMAIN>
|
||||||
|
dig <DOMAIN> TXT +short # → v=spf1 ...
|
||||||
|
dig _dmarc.<DOMAIN> TXT +short # → v=DMARC1 ...
|
||||||
|
dig dkim._domainkey.<DOMAIN> TXT +short # → v=DKIM1 ...
|
||||||
|
```
|
||||||
|
|
||||||
|
https://www.mail-tester.com/ — отправить письмо, проверить оценку.
|
||||||
|
|
||||||
|
## Применение для dttb.ru
|
||||||
|
|
||||||
|
| Параметр | niikn.com (выполнено) | dttb.ru (план) |
|
||||||
|
|----------|----------------------|----------------|
|
||||||
|
| Mailcow IP | 192.168.1.128 | ? (новая VM или LXC) |
|
||||||
|
| MikroTik | 192.168.1.1 (AI/OL260380eg) | 10.0.0.250 или роутер dttb |
|
||||||
|
| NPM | 192.168.1.22 | 10.0.0.195 |
|
||||||
|
| Публичный IP | 85.235.181.190 | ? |
|
||||||
|
| DNS домен | niikn.com | dttb.ru |
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> ⚠️ **КОНФИДЕНЦИАЛЬНО** — не распространять за пределы команды
|
> ⚠️ **КОНФИДЕНЦИАЛЬНО** — не распространять за пределы команды
|
||||||
>
|
>
|
||||||
> Последнее обновление: 2026-02-27
|
> Последнее обновление: 2026-03-03
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -42,6 +42,34 @@
|
|||||||
| Email | `it5870@yandex.ru` |
|
| Email | `it5870@yandex.ru` |
|
||||||
| Пароль | `1qaz!QAZ` |
|
| Пароль | `1qaz!QAZ` |
|
||||||
|
|
||||||
|
## Spaceweb (DNS-хостинг: niikn.com, dttb.ru, itilegent.ru)
|
||||||
|
|
||||||
|
| Параметр | Значение |
|
||||||
|
|----------|----------|
|
||||||
|
| URL | https://vps.sweb.ru |
|
||||||
|
| Логин | `it5870yand` |
|
||||||
|
| Пароль | `1qaz!QAZ` |
|
||||||
|
| API | `https://api.sweb.ru/domains/dns` (JSON-RPC) |
|
||||||
|
| Домены | niikn.com, dttb.ru, itilegent.ru |
|
||||||
|
|
||||||
|
## Mailcow НИИКН (VM106 — 192.168.1.128)
|
||||||
|
|
||||||
|
| Параметр | Значение |
|
||||||
|
|----------|----------|
|
||||||
|
| URL | https://mail.niikn.com |
|
||||||
|
| Admin | `admin` / `1qaz!QAZ` |
|
||||||
|
| API Key | `niikn-mailcow-api-2026` |
|
||||||
|
| DBPASS | `8VcUSgpKEOoxNojIZBRJx0FzMxzm` |
|
||||||
|
| Ящик | `noreply@niikn.com` / `NiIkN-NoReply-2026!` |
|
||||||
|
|
||||||
|
## NPM НИИКН (LXC 102 — 192.168.1.22:81)
|
||||||
|
|
||||||
|
| Параметр | Значение |
|
||||||
|
|----------|----------|
|
||||||
|
| URL | http://192.168.1.22:81 |
|
||||||
|
| Email | `it5870@yandex.ru` |
|
||||||
|
| Пароль | `1qaz!QAZ` |
|
||||||
|
|
||||||
## SSH-ключи и доступы
|
## SSH-ключи и доступы
|
||||||
|
|
||||||
| Хост | Порт | Метод |
|
| Хост | Порт | Метод |
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
## Сервисы
|
## Сервисы
|
||||||
|
|
||||||
- **Nextcloud AIO** — `https://new.niikn.com`, управление: `https://new.niikn.com:8080`
|
- **Nextcloud AIO** — `https://new.niikn.com`, управление: `https://new.niikn.com:8080`
|
||||||
- **Mailcow** — `https://mail.niikn.com`, admin / moohoo (сменить!)
|
- **Mailcow** — `https://mail.niikn.com`, admin / 1qaz!QAZ
|
||||||
- **SMB** — `//192.168.1.79/share`, смонтирован на VM108 как `/mnt/ncsmb`
|
- **SMB** — `//192.168.1.79/share`, смонтирован на VM108 как `/mnt/ncsmb`
|
||||||
|
|
||||||
## Ключевые файлы на VM108
|
## Ключевые файлы на VM108
|
||||||
@@ -24,12 +24,41 @@
|
|||||||
- `/etc/samba/smb-niikn.creds` — учётные данные SMB
|
- `/etc/samba/smb-niikn.creds` — учётные данные SMB
|
||||||
- `/home/cloud/setup-firewall.sh` — скрипт UFW
|
- `/home/cloud/setup-firewall.sh` — скрипт UFW
|
||||||
|
|
||||||
## Ключевые файлы на VM106 (Mailcow)
|
## Mailcow (VM106, 192.168.1.128)
|
||||||
|
|
||||||
- `/opt/mailcow-dockerized/mailcow.conf` — конфиг Mailcow
|
- **Web UI:** `https://mail.niikn.com` (через NPM proxy host #17)
|
||||||
- DBPASS=8VcUSgpKEOoxNojIZBRJx0FzMxzm
|
- **Admin:** admin / 1qaz!QAZ
|
||||||
|
- **API key:** `niikn-mailcow-api-2026`
|
||||||
|
- **DKIM:** selector=dkim, 2048-bit RSA
|
||||||
|
- **Ящик:** noreply@niikn.com (пароль: NiIkN-NoReply-2026!)
|
||||||
|
- **SMTP:** 192.168.1.128:587, STARTTLS, LOGIN auth
|
||||||
|
- **SSL:** Let's Encrypt через NPM (cert ID 50)
|
||||||
|
- **Конфиг:** `/opt/mailcow-dockerized/mailcow.conf` (DBPASS=8VcUSgpKEOoxNojIZBRJx0FzMxzm)
|
||||||
|
|
||||||
## Сброс пароля admin в Mailcow
|
### MikroTik проброс портов → 192.168.1.128
|
||||||
|
| Порт | Протокол | Назначение |
|
||||||
|
|------|----------|------------|
|
||||||
|
| 25 | TCP | SMTP (приём почты) |
|
||||||
|
| 465 | TCP | SMTPS |
|
||||||
|
| 587 | TCP | Submission (отправка) |
|
||||||
|
| 993 | TCP | IMAPS |
|
||||||
|
| 995 | TCP | POP3S |
|
||||||
|
| 4190 | TCP | Sieve |
|
||||||
|
|
||||||
|
### DNS записи (niikn.com → Spaceweb)
|
||||||
|
| Тип | Имя | Значение |
|
||||||
|
|-----|-----|----------|
|
||||||
|
| A | mail | 85.235.181.190 |
|
||||||
|
| MX | @ | mail.niikn.com. (приоритет 10) |
|
||||||
|
| TXT | @ | v=spf1 mx a:mail.niikn.com ~all |
|
||||||
|
| TXT | _dmarc | v=DMARC1; p=none; rua=mailto:admin@niikn.com |
|
||||||
|
| TXT | dkim._domainkey | v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjAN... (2048-bit) |
|
||||||
|
|
||||||
|
### TODO
|
||||||
|
- [ ] PTR запись: 85.235.181.190 → mail.niikn.com (запросить у Комстар/МТС)
|
||||||
|
- [ ] Настроить SMTP в Nextcloud
|
||||||
|
|
||||||
|
### Сброс пароля admin в Mailcow
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /opt/mailcow-dockerized
|
cd /opt/mailcow-dockerized
|
||||||
|
|||||||
@@ -371,6 +371,47 @@ VM 192.168.1.200 также добавлен cloud-init диск (ide0: local-lv
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-03-03 — Настройка почтового сервера mail.niikn.com
|
||||||
|
|
||||||
|
### Выполненные шаги
|
||||||
|
|
||||||
|
1. **MikroTik — проброс портов (192.168.1.1)**
|
||||||
|
- SSH: AI / OL260380eg
|
||||||
|
- Проброшены порты 25, 465, 587, 993, 995, 4190 → 192.168.1.128 (Mailcow)
|
||||||
|
- Порты 80/443 не тронуты — идут на NPM
|
||||||
|
|
||||||
|
2. **NPM — proxy host #17 (192.168.1.22)**
|
||||||
|
- Создан: `mail.niikn.com` → `https://192.168.1.128:443`
|
||||||
|
- SSL: Let's Encrypt (cert ID 50), ssl_forced=true
|
||||||
|
- Mailcow сам обслуживает HTTPS — NPM проксирует на https backend
|
||||||
|
|
||||||
|
3. **DNS записи — Spaceweb API (vps.sweb.ru)**
|
||||||
|
- Логин: it5870yand / 1qaz!QAZ
|
||||||
|
- API: POST https://api.sweb.ru/domains/dns (JSON-RPC, URL-encoded body)
|
||||||
|
- Добавлены: MX (mail.niikn.com, pri 10), SPF, DMARC, DKIM
|
||||||
|
- Все записи распространились и видны через Google/Cloudflare DNS
|
||||||
|
|
||||||
|
4. **Mailcow — домен и ящики (192.168.1.128)**
|
||||||
|
- Домен niikn.com — был уже добавлен
|
||||||
|
- DKIM — был уже сгенерирован (selector=dkim, 2048-bit)
|
||||||
|
- Ящик noreply@niikn.com — был уже создан, пароль установлен: NiIkN-NoReply-2026!
|
||||||
|
- SMTP (587/STARTTLS) проверен — работает, тестовое письмо отправлено
|
||||||
|
|
||||||
|
5. **Пароль admin Mailcow**
|
||||||
|
- Изменён через API: POST /api/v1/edit/admin (X-API-Key: niikn-mailcow-api-2026)
|
||||||
|
- Новый пароль: 1qaz!QAZ
|
||||||
|
|
||||||
|
### Не выполнено
|
||||||
|
- **Nextcloud SMTP** — нет SSH к VM 108, NC API не поддерживает mail_smtp* настройки
|
||||||
|
- Настроить вручную: Администрирование → Email → SMTP 192.168.1.128:587, noreply@niikn.com
|
||||||
|
- **PTR (rDNS)** — текущий: Aquatern.access.comstar.ru → нужен mail.niikn.com
|
||||||
|
- Обратиться к провайдеру Комстар/МТС
|
||||||
|
|
||||||
|
### Spaceweb DNS API — сценарий для повторного использования (dttb.ru)
|
||||||
|
Подробный скрипт: `snippets/spaceweb-dns-api.py`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Что ещё нужно сделать
|
## Что ещё нужно сделать
|
||||||
|
|
||||||
- [x] ~~Перезапустить AIO контейнеры Talk → восстановить signaling_servers~~
|
- [x] ~~Перезапустить AIO контейнеры Talk → восстановить signaling_servers~~
|
||||||
@@ -378,7 +419,8 @@ VM 192.168.1.200 также добавлен cloud-init диск (ide0: local-lv
|
|||||||
- [ ] **После rsync:** создать Groupfolders, назначить права, scan (см. groupfolders-migration.md)
|
- [ ] **После rsync:** создать Groupfolders, назначить права, scan (см. groupfolders-migration.md)
|
||||||
- [ ] **После rsync:** удалить External Storage ID 4 и 5 (SMB пока не удалять)
|
- [ ] **После rsync:** удалить External Storage ID 4 и 5 (SMB пока не удалять)
|
||||||
- [ ] Настроить AIO Backup на VM108
|
- [ ] Настроить AIO Backup на VM108
|
||||||
- [ ] Настроить SMTP для уведомлений Nextcloud (использовать mail.niikn.com после настройки DNS)
|
- [ ] Настроить SMTP для уведомлений Nextcloud (mail.niikn.com готов, нужно вписать в NC вручную)
|
||||||
|
- [ ] PTR запись: 85.235.181.190 → mail.niikn.com (провайдер Комстар/МТС)
|
||||||
- [ ] Проверить работу пользователей на new.niikn.com
|
- [ ] Проверить работу пользователей на new.niikn.com
|
||||||
- [ ] Решить судьбу Linkwarden и FileBrowser (переносить или нет)
|
- [ ] Решить судьбу Linkwarden и FileBrowser (переносить или нет)
|
||||||
- [ ] Зафиксировать статический IP для VM100 (сейчас DHCP 192.168.1.245)
|
- [ ] Зафиксировать статический IP для VM100 (сейчас DHCP 192.168.1.245)
|
||||||
|
|||||||
167
snippets/spaceweb-dns-api.py
Normal file
167
snippets/spaceweb-dns-api.py
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Spaceweb DNS API — управление DNS записями через JSON-RPC.
|
||||||
|
Панель: https://vps.sweb.ru
|
||||||
|
Домены: niikn.com, dttb.ru, itilegent.ru
|
||||||
|
|
||||||
|
Использование:
|
||||||
|
python3 spaceweb-dns-api.py info niikn.com
|
||||||
|
python3 spaceweb-dns-api.py add-mx niikn.com mail.niikn.com 10
|
||||||
|
python3 spaceweb-dns-api.py add-txt niikn.com @ "v=spf1 mx ~all"
|
||||||
|
python3 spaceweb-dns-api.py add-txt niikn.com _dmarc "v=DMARC1; p=none"
|
||||||
|
python3 spaceweb-dns-api.py del niikn.com TXT 1
|
||||||
|
python3 spaceweb-dns-api.py zone niikn.com
|
||||||
|
"""
|
||||||
|
|
||||||
|
import urllib.request
|
||||||
|
import urllib.parse
|
||||||
|
import json
|
||||||
|
import http.cookiejar
|
||||||
|
import sys
|
||||||
|
|
||||||
|
LOGIN = "it5870yand"
|
||||||
|
PASSWORD = "1qaz!QAZ"
|
||||||
|
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
||||||
|
|
||||||
|
|
||||||
|
def create_session():
|
||||||
|
"""Логин в Spaceweb, возвращает opener с куками."""
|
||||||
|
cj = http.cookiejar.CookieJar()
|
||||||
|
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
|
||||||
|
|
||||||
|
# GET login page
|
||||||
|
req = urllib.request.Request("https://mcp.sweb.ru/")
|
||||||
|
req.add_header("User-Agent", UA)
|
||||||
|
opener.open(req)
|
||||||
|
|
||||||
|
# POST auth
|
||||||
|
login_data = urllib.parse.urlencode({
|
||||||
|
"login": LOGIN, "password": PASSWORD,
|
||||||
|
"new_panel": "1", "to": "//mcp.sweb.ru/main/index/", "savepref": ""
|
||||||
|
}).encode()
|
||||||
|
req = urllib.request.Request("https://mcp.sweb.ru/main/auth_submit/",
|
||||||
|
data=login_data, method="POST")
|
||||||
|
req.add_header("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.add_header("User-Agent", UA)
|
||||||
|
req.add_header("Referer", "https://mcp.sweb.ru/main/auth/")
|
||||||
|
resp = opener.open(req)
|
||||||
|
if "vps.sweb.ru" not in resp.url and "mcp.sweb.ru/main/index" not in resp.url:
|
||||||
|
raise RuntimeError(f"Login failed, redirected to: {resp.url}")
|
||||||
|
return opener
|
||||||
|
|
||||||
|
|
||||||
|
def api_call(opener, method, params):
|
||||||
|
"""Вызов JSON-RPC API Spaceweb."""
|
||||||
|
payload = {
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 1,
|
||||||
|
"user": LOGIN,
|
||||||
|
"method": method,
|
||||||
|
"params": params
|
||||||
|
}
|
||||||
|
body = urllib.parse.quote(json.dumps(payload, separators=(",", ":")), safe="").encode()
|
||||||
|
req = urllib.request.Request("https://api.sweb.ru/domains/dns",
|
||||||
|
data=body, method="POST")
|
||||||
|
req.add_header("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.add_header("User-Agent", UA)
|
||||||
|
req.add_header("Origin", "https://vps.sweb.ru")
|
||||||
|
req.add_header("Referer", "https://vps.sweb.ru/")
|
||||||
|
resp = opener.open(req)
|
||||||
|
result = json.loads(resp.read().decode())
|
||||||
|
if "error" in result:
|
||||||
|
raise RuntimeError(f"API error: {result['error']['message']}")
|
||||||
|
return result.get("result")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_info(opener, domain):
|
||||||
|
"""Показать все DNS записи."""
|
||||||
|
records = api_call(opener, "info", {"domain": domain})
|
||||||
|
print(f"DNS записи для {domain}:")
|
||||||
|
for r in records:
|
||||||
|
t = r.get("type", "?")
|
||||||
|
n = r.get("name", "@") or "@"
|
||||||
|
v = r.get("value", "")
|
||||||
|
idx = r.get("index", "?")
|
||||||
|
extra = f" (pri: {r.get('priority')})" if r.get("priority") else ""
|
||||||
|
print(f" [{idx:>2}] {t:5s} {n:30s} → {v[:100]}{extra}")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_zone(opener, domain):
|
||||||
|
"""Показать zone file."""
|
||||||
|
result = api_call(opener, "getFile", {"domain": domain})
|
||||||
|
print(result["content"])
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_add_mx(opener, domain, value, priority="10"):
|
||||||
|
"""Добавить MX запись."""
|
||||||
|
if not value.endswith("."):
|
||||||
|
value += "."
|
||||||
|
result = api_call(opener, "editMx", {
|
||||||
|
"domain": domain, "subDomain": "", "action": "add",
|
||||||
|
"priority": str(priority), "value": value
|
||||||
|
})
|
||||||
|
print(f"MX добавлен: {domain} → {value} (pri {priority}): {result}")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_add_txt(opener, domain, subdomain, value):
|
||||||
|
"""Добавить TXT запись."""
|
||||||
|
result = api_call(opener, "editTxt", {
|
||||||
|
"domain": domain, "action": "add",
|
||||||
|
"subDomain": subdomain, "value": value
|
||||||
|
})
|
||||||
|
print(f"TXT добавлен: {subdomain}.{domain} → {value[:60]}...: {result}")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_add_a(opener, domain, name, ip):
|
||||||
|
"""Добавить A запись (субдомен)."""
|
||||||
|
result = api_call(opener, "editMain", {
|
||||||
|
"domain": domain, "action": "add",
|
||||||
|
"name": name, "type": "A", "value": ip, "prefix": ""
|
||||||
|
})
|
||||||
|
print(f"A добавлен: {name}.{domain} → {ip}: {result}")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_del(opener, domain, record_type, index):
|
||||||
|
"""Удалить запись по типу и индексу."""
|
||||||
|
method_map = {
|
||||||
|
"A": "editMain", "AAAA": "editMain", "CNAME": "editMain",
|
||||||
|
"MX": "editMx", "TXT": "editTxt", "NS": "editNs",
|
||||||
|
"SRV": "editSrv", "CAA": "editCaa"
|
||||||
|
}
|
||||||
|
method = method_map.get(record_type.upper(), "editMain")
|
||||||
|
result = api_call(opener, method, {
|
||||||
|
"domain": domain, "action": "del",
|
||||||
|
"index": int(index), "type": record_type.upper()
|
||||||
|
})
|
||||||
|
print(f"Удалено: {record_type} index={index}: {result}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print(__doc__)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
cmd = sys.argv[1]
|
||||||
|
domain = sys.argv[2]
|
||||||
|
opener = create_session()
|
||||||
|
|
||||||
|
if cmd == "info":
|
||||||
|
cmd_info(opener, domain)
|
||||||
|
elif cmd == "zone":
|
||||||
|
cmd_zone(opener, domain)
|
||||||
|
elif cmd == "add-mx" and len(sys.argv) >= 4:
|
||||||
|
pri = sys.argv[4] if len(sys.argv) > 4 else "10"
|
||||||
|
cmd_add_mx(opener, domain, sys.argv[3], pri)
|
||||||
|
elif cmd == "add-txt" and len(sys.argv) >= 5:
|
||||||
|
cmd_add_txt(opener, domain, sys.argv[3], sys.argv[4])
|
||||||
|
elif cmd == "add-a" and len(sys.argv) >= 5:
|
||||||
|
cmd_add_a(opener, domain, sys.argv[3], sys.argv[4])
|
||||||
|
elif cmd == "del" and len(sys.argv) >= 5:
|
||||||
|
cmd_del(opener, domain, sys.argv[3], sys.argv[4])
|
||||||
|
else:
|
||||||
|
print(__doc__)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user