feat(mail): Mailcow provision wrappers, zone override for mail DNS/NPM
- .env.master.example: CLOUDFLARE_ZONE_ID_OVERRIDE, Mailcow vars - provision-d-bis-mail-dns-and-npmplus: optional https upstream, override zone id - scripts/mailcow: defi-oracle.io DNS/NPM wrapper + Mailcow mailbox API helper Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
# - .env: CLOUDFLARE_API_TOKEN (or EMAIL+API_KEY) with Zone:DNS:Edit; for Origin CA also
|
||||
# SSL and Certificates (or use Global API Key for Origin CA — prefer scoped token with
|
||||
# Zone + SSL per Cloudflare dashboard).
|
||||
# - CLOUDFLARE_ZONE_ID_D_BIS_ORG
|
||||
# - Zone id: CLOUDFLARE_ZONE_ID_D_BIS_ORG (d-bis.org) or CLOUDFLARE_ZONE_ID_OVERRIDE / CLOUDFLARE_ZONE_ID for other zones
|
||||
# - NPM_URL, NPM_EMAIL, NPM_PASSWORD for NPMplus API
|
||||
#
|
||||
# Usage:
|
||||
@@ -25,6 +25,7 @@
|
||||
# PROVISION_MX=0 1 = set apex MX to MX_TARGET (default 0: do not change — many zones use Zoho/365)
|
||||
# PROVISION_SPF=0 1 = upsert ONE apex TXT to SPF_TXT (default 0: do not clobber Zoho/legacy TXT)
|
||||
# PROVISION_DMARC=0
|
||||
# MAIL_UPSTREAM_SCHEME=http NPM upstream scheme
|
||||
# IP_MAIL_UPSTREAM=192.168.11.32 PMG / webmail HTTP backend
|
||||
# PORT_MAIL_UPSTREAM=8006
|
||||
# MAIL_NPM_BLOCK_EXPLOITS=0 0 = ModSecurity off for finicky UIs (PMG admin)
|
||||
@@ -50,7 +51,8 @@ fi
|
||||
ZONE_NAME="${ZONE_NAME:-d-bis.org}"
|
||||
MAIL_SUB="${MAIL_SUBDOMAIN:-mail}"
|
||||
MAIL_FQDN="${MAIL_SUB}.${ZONE_NAME}"
|
||||
ZONE_ID="${CLOUDFLARE_ZONE_ID_D_BIS_ORG:-${CLOUDFLARE_ZONE_ID:-}}"
|
||||
# Prefer CLOUDFLARE_ZONE_ID_OVERRIDE when set (e.g. defi-oracle.io + CLOUDFLARE_ZONE_ID_DEFI_ORACLE_IO).
|
||||
ZONE_ID="${CLOUDFLARE_ZONE_ID_OVERRIDE:-${CLOUDFLARE_ZONE_ID_D_BIS_ORG:-${CLOUDFLARE_ZONE_ID:-}}}"
|
||||
PUBLIC_IP="${PUBLIC_IP:-76.53.10.36}"
|
||||
MX_TARGET="${MX_TARGET:-$MAIL_FQDN}"
|
||||
MX_PRI="${MX_PRIORITY:-10}"
|
||||
@@ -62,6 +64,7 @@ PROVISION_DMARC="${PROVISION_DMARC:-0}"
|
||||
MAIL_NPM_BLOCK_EXPLOITS="${MAIL_NPM_BLOCK_EXPLOITS:-0}"
|
||||
IP_MAIL_UP="${IP_MAIL_UPSTREAM:-${IP_PMG:-192.168.11.32}}"
|
||||
PORT_MAIL_UP="${PORT_MAIL_UPSTREAM:-8006}"
|
||||
MAIL_UPSTREAM_SCHEME="${MAIL_UPSTREAM_SCHEME:-http}"
|
||||
PROVISION_CF_ORIGIN_CERT="${PROVISION_CF_ORIGIN_CERT:-0}"
|
||||
PROVISION_NPM="${PROVISION_NPM:-1}"
|
||||
CERT_OUT_DIR="${CERT_OUT_DIR:-$PROJECT_ROOT/backups/certs}"
|
||||
@@ -79,7 +82,7 @@ log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_err() { echo -e "${RED}[ERR]${NC} $1"; }
|
||||
|
||||
if [ -z "$ZONE_ID" ]; then
|
||||
log_err "CLOUDFLARE_ZONE_ID_D_BIS_ORG (or CLOUDFLARE_ZONE_ID) is required"
|
||||
log_err "Set zone id: CLOUDFLARE_ZONE_ID_OVERRIDE, or CLOUDFLARE_ZONE_ID_D_BIS_ORG / CLOUDFLARE_ZONE_ID (see script header)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -213,7 +216,7 @@ if [ "$PROVISION_NPM" != 1 ]; then
|
||||
exit 0
|
||||
fi
|
||||
if [ "$DRY" = 1 ]; then
|
||||
log_info "[dry-run] NPM: would ensure proxy host $MAIL_FQDN → http://${IP_MAIL_UP}:${PORT_MAIL_UP}"
|
||||
log_info "[dry-run] NPM: would ensure proxy host $MAIL_FQDN → ${MAIL_UPSTREAM_SCHEME}://${IP_MAIL_UP}:${PORT_MAIL_UP}"
|
||||
log_ok "Done."
|
||||
exit 0
|
||||
fi
|
||||
@@ -258,13 +261,13 @@ fi
|
||||
|
||||
# Create or update proxy host
|
||||
if [ -z "$HOST_ID" ] || [ "$HOST_ID" = "null" ]; then
|
||||
log_info "Creating proxy host $MAIL_FQDN → http://${IP_MAIL_UP}:${PORT_MAIL_UP} ..."
|
||||
log_info "Creating proxy host $MAIL_FQDN → ${MAIL_UPSTREAM_SCHEME}://${IP_MAIL_UP}:${PORT_MAIL_UP} ..."
|
||||
if [ -n "$CERT_ID_TO_USE" ] && [ "$CERT_ID_TO_USE" != "null" ]; then
|
||||
PH=$(jq -n --arg d "$MAIL_FQDN" --arg h "$IP_MAIL_UP" --argjson p "$PORT_MAIL_UP" --argjson be "$NPM_BLOCK_JSON" --argjson cid "$CERT_ID_TO_USE" \
|
||||
'{domain_names:[$d], forward_scheme:"http", forward_host:$h, forward_port:$p, allow_websocket_upgrade:true, block_exploits:$be, certificate_id:$cid, ssl_forced:true, http2_support:true, hsts_enabled:true, hsts_subdomains:false}')
|
||||
PH=$(jq -n --arg d "$MAIL_FQDN" --arg s "$MAIL_UPSTREAM_SCHEME" --arg h "$IP_MAIL_UP" --argjson p "$PORT_MAIL_UP" --argjson be "$NPM_BLOCK_JSON" --argjson cid "$CERT_ID_TO_USE" \
|
||||
'{domain_names:[$d], forward_scheme:$s, forward_host:$h, forward_port:$p, allow_websocket_upgrade:true, block_exploits:$be, certificate_id:$cid, ssl_forced:true, http2_support:true, hsts_enabled:true, hsts_subdomains:false}')
|
||||
else
|
||||
PH=$(jq -n --arg d "$MAIL_FQDN" --arg h "$IP_MAIL_UP" --argjson p "$PORT_MAIL_UP" --argjson be "$NPM_BLOCK_JSON" \
|
||||
'{domain_names:[$d], forward_scheme:"http", forward_host:$h, forward_port:$p, allow_websocket_upgrade:true, block_exploits:$be, certificate_id:null, ssl_forced:false}')
|
||||
PH=$(jq -n --arg d "$MAIL_FQDN" --arg s "$MAIL_UPSTREAM_SCHEME" --arg h "$IP_MAIL_UP" --argjson p "$PORT_MAIL_UP" --argjson be "$NPM_BLOCK_JSON" \
|
||||
'{domain_names:[$d], forward_scheme:$s, forward_host:$h, forward_port:$p, allow_websocket_upgrade:true, block_exploits:$be, certificate_id:null, ssl_forced:false}')
|
||||
fi
|
||||
|
||||
PR=$(curl_npm -X POST "$NPM_URL/api/nginx/proxy-hosts" -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" -d "$PH")
|
||||
@@ -278,12 +281,12 @@ else
|
||||
log_info "Updating proxy host id $HOST_ID"
|
||||
if [ -n "$CERT_ID_TO_USE" ] && [ "$CERT_ID_TO_USE" != "null" ]; then
|
||||
PAYLOAD=$(curl_npm -X GET "$NPM_URL/api/nginx/proxy-hosts/$HOST_ID" -H "Authorization: Bearer $TOK" | jq \
|
||||
--arg h "$IP_MAIL_UP" --argjson p "$PORT_MAIL_UP" --argjson be "$NPM_BLOCK_JSON" --argjson cid "$CERT_ID_TO_USE" \
|
||||
'.forward_host=$h | .forward_port=$p | .forward_scheme="http" | .block_exploits=$be | .certificate_id=$cid | .ssl_forced=true | .http2_support=true')
|
||||
--arg s "$MAIL_UPSTREAM_SCHEME" --arg h "$IP_MAIL_UP" --argjson p "$PORT_MAIL_UP" --argjson be "$NPM_BLOCK_JSON" --argjson cid "$CERT_ID_TO_USE" \
|
||||
'{domain_names, forward_scheme:$s, forward_host:$h, forward_port:$p, allow_websocket_upgrade:(.allow_websocket_upgrade // true), block_exploits:$be, certificate_id:$cid, ssl_forced:true, http2_support:true, hsts_enabled:(.hsts_enabled // true), hsts_subdomains:(.hsts_subdomains // false), advanced_config:(.advanced_config // ""), locations:(.locations // [])}')
|
||||
else
|
||||
PAYLOAD=$(curl_npm -X GET "$NPM_URL/api/nginx/proxy-hosts/$HOST_ID" -H "Authorization: Bearer $TOK" | jq \
|
||||
--arg h "$IP_MAIL_UP" --argjson p "$PORT_MAIL_UP" --argjson be "$NPM_BLOCK_JSON" \
|
||||
'.forward_host=$h | .forward_port=$p | .forward_scheme="http" | .block_exploits=$be')
|
||||
--arg s "$MAIL_UPSTREAM_SCHEME" --arg h "$IP_MAIL_UP" --argjson p "$PORT_MAIL_UP" --argjson be "$NPM_BLOCK_JSON" \
|
||||
'{domain_names, forward_scheme:$s, forward_host:$h, forward_port:$p, allow_websocket_upgrade:(.allow_websocket_upgrade // true), block_exploits:$be, certificate_id:(.certificate_id // null), ssl_forced:(.ssl_forced // false), http2_support:(.http2_support // true), hsts_enabled:(.hsts_enabled // false), hsts_subdomains:(.hsts_subdomains // false), advanced_config:(.advanced_config // ""), locations:(.locations // [])}')
|
||||
fi
|
||||
PUR=$(curl_npm -X PUT "$NPM_URL/api/nginx/proxy-hosts/$HOST_ID" -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" -d "$PAYLOAD")
|
||||
if echo "$PUR" | jq -e '.id' >/dev/null 2>&1; then
|
||||
|
||||
38
scripts/mailcow/provision-defi-oracle-mail-dns-npm.sh
Executable file
38
scripts/mailcow/provision-defi-oracle-mail-dns-npm.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# Public mail for defi-oracle.io: Cloudflare A for mail.defi-oracle.io + NPMplus → Mailcow HTTP.
|
||||
# Reuses scripts/cloudflare/provision-d-bis-mail-dns-and-npmplus.sh with zone override.
|
||||
#
|
||||
# .env needs:
|
||||
# CLOUDFLARE_ZONE_ID_DEFI_ORACLE_IO (or set CLOUDFLARE_ZONE_ID_OVERRIDE)
|
||||
# CLOUDFLARE_API_TOKEN or CLOUDFLARE_EMAIL + CLOUDFLARE_API_KEY
|
||||
# NPM_EMAIL, NPM_PASSWORD when PROVISION_NPM=1 (default)
|
||||
#
|
||||
# Optional:
|
||||
# PUBLIC_IP (default 76.53.10.36 from your stack)
|
||||
# IP_MAIL_UPSTREAM (default 192.168.11.115 Mailcow)
|
||||
# PORT_MAIL_UPSTREAM (default 443)
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/mailcow/provision-defi-oracle-mail-dns-npm.sh --dry-run
|
||||
# ./scripts/mailcow/provision-defi-oracle-mail-dns-npm.sh
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh"
|
||||
|
||||
export ZONE_NAME="${ZONE_NAME:-defi-oracle.io}"
|
||||
export MAIL_SUBDOMAIN="${MAIL_SUBDOMAIN:-mail}"
|
||||
export CLOUDFLARE_ZONE_ID_OVERRIDE="${CLOUDFLARE_ZONE_ID_OVERRIDE:-${CLOUDFLARE_ZONE_ID_DEFI_ORACLE_IO:-}}"
|
||||
export IP_MAIL_UPSTREAM="${IP_MAIL_UPSTREAM:-${IP_MAILCOW:-192.168.11.115}}"
|
||||
export PORT_MAIL_UPSTREAM="${PORT_MAIL_UPSTREAM:-${PORT_MAILCOW_HTTPS:-443}}"
|
||||
export MAIL_UPSTREAM_SCHEME="${MAIL_UPSTREAM_SCHEME:-https}"
|
||||
|
||||
if [[ -z "$CLOUDFLARE_ZONE_ID_OVERRIDE" ]]; then
|
||||
echo "ERROR: Set CLOUDFLARE_ZONE_ID_DEFI_ORACLE_IO in .env (or export CLOUDFLARE_ZONE_ID_OVERRIDE)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec "${PROJECT_ROOT}/scripts/cloudflare/provision-d-bis-mail-dns-and-npmplus.sh" "$@"
|
||||
162
scripts/mailcow/provision-mailcow-mailbox.sh
Executable file
162
scripts/mailcow/provision-mailcow-mailbox.sh
Executable file
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env bash
|
||||
# Create a mailbox on Mailcow (VMID 10900 / mailcow-dbis) via REST API v1.
|
||||
#
|
||||
# Prerequisites:
|
||||
# - Mailcow UI → System → API: create a read-write API key; allow this host's IP in API_ALLOW_FROM.
|
||||
# - Root .env (or env): MAILCOW_API_KEY
|
||||
#
|
||||
# Optional env:
|
||||
# MAILCOW_BASE_URL default https://192.168.11.115
|
||||
# MAIL_DOMAIN default defi-oracle.io
|
||||
# MAIL_LOCAL_PART default theoracle
|
||||
# MAIL_DISPLAY_NAME default "The Oracle"
|
||||
# MAILBOX_PASSWORD if unset (non-dry-run), a random password is generated and printed once
|
||||
# MAIL_QUOTA_MB default 3072
|
||||
# ENSURE_DOMAIN=1 add MAIL_DOMAIN on Mailcow when missing (default 1)
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/mailcow/provision-mailcow-mailbox.sh --dry-run
|
||||
# MAILBOX_PASSWORD='…' ./scripts/mailcow/provision-mailcow-mailbox.sh
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
# shellcheck source=/dev/null
|
||||
source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh"
|
||||
|
||||
MAILCOW_BASE_URL="${MAILCOW_BASE_URL:-https://192.168.11.115}"
|
||||
MAILCOW_BASE_URL="${MAILCOW_BASE_URL%/}"
|
||||
MAIL_DOMAIN="${MAIL_DOMAIN:-defi-oracle.io}"
|
||||
MAIL_LOCAL_PART="${MAIL_LOCAL_PART:-theoracle}"
|
||||
MAIL_DISPLAY_NAME="${MAIL_DISPLAY_NAME:-The Oracle}"
|
||||
MAIL_QUOTA_MB="${MAIL_QUOTA_MB:-3072}"
|
||||
ENSURE_DOMAIN="${ENSURE_DOMAIN:-1}"
|
||||
|
||||
DRY=0
|
||||
FORCE=0
|
||||
for a in "$@"; do
|
||||
[[ "$a" == "--dry-run" ]] && DRY=1
|
||||
[[ "$a" == "--force" ]] && FORCE=1
|
||||
done
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||||
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||
log_ok() { echo -e "${GREEN}[OK]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_err() { echo -e "${RED}[ERR]${NC} $1"; }
|
||||
|
||||
mc_curl() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
local data="${3:-}"
|
||||
if [[ -n "$data" ]]; then
|
||||
curl -skS --connect-timeout 10 --max-time 120 -X "$method" \
|
||||
-H "X-API-Key: ${MAILCOW_API_KEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$data" \
|
||||
"${MAILCOW_BASE_URL}/api/v1/${path}"
|
||||
else
|
||||
curl -skS --connect-timeout 10 --max-time 120 -X "$method" \
|
||||
-H "X-API-Key: ${MAILCOW_API_KEY}" \
|
||||
"${MAILCOW_BASE_URL}/api/v1/${path}"
|
||||
fi
|
||||
}
|
||||
|
||||
response_ok() {
|
||||
local json="$1"
|
||||
echo "$json" | jq -e '
|
||||
if type == "array" then
|
||||
[.[]? | objects | select(.type == "danger" or .type == "error")] | length == 0
|
||||
elif type == "object" then
|
||||
(.type != "danger" and .type != "error")
|
||||
else true end' >/dev/null 2>&1
|
||||
}
|
||||
|
||||
if [[ "$DRY" != 1 ]] && [[ -z "${MAILCOW_API_KEY:-}" ]]; then
|
||||
log_err "Set MAILCOW_API_KEY (Mailcow → System → API). Example: export MAILCOW_API_KEY='…'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Mailcow: ${MAILCOW_BASE_URL} mailbox: ${MAIL_LOCAL_PART}@${MAIL_DOMAIN}"
|
||||
|
||||
if [[ "$DRY" = 1 ]]; then
|
||||
log_info "[dry-run] GET get/domain/all (check ${MAIL_DOMAIN})"
|
||||
log_info "[dry-run] if missing and ENSURE_DOMAIN=1: POST add/domain …"
|
||||
log_info "[dry-run] GET get/mailbox/all/${MAIL_DOMAIN} (check existing)"
|
||||
log_info "[dry-run] POST add/mailbox for ${MAIL_LOCAL_PART}@${MAIL_DOMAIN}"
|
||||
log_ok "Dry run complete."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Auth probe
|
||||
_auth=$(mc_curl GET "get/status/version" || echo '{"type":"error"}')
|
||||
if echo "$_auth" | jq -e '.type == "error"' >/dev/null 2>&1; then
|
||||
log_err "Mailcow API rejected the key or host is unreachable: $(echo "$_auth" | jq -c . 2>/dev/null || echo "$_auth")"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Domain (list all — single-domain GET is inconsistent across versions)
|
||||
_dom_all=$(mc_curl GET "get/domain/all" || echo '{"type":"error"}')
|
||||
if echo "$_dom_all" | jq -e '.type == "error"' >/dev/null 2>&1; then
|
||||
log_err "get/domain/all failed: $(echo "$_dom_all" | jq -c . 2>/dev/null || echo "$_dom_all")"
|
||||
exit 1
|
||||
fi
|
||||
if echo "$_dom_all" | jq -e --arg d "$MAIL_DOMAIN" '
|
||||
if type == "array" then
|
||||
[(.[]? | objects) | select(.domain == $d or .domain_name == $d)] | length > 0
|
||||
else false end' >/dev/null 2>&1; then
|
||||
log_ok "Domain already on Mailcow: ${MAIL_DOMAIN}"
|
||||
elif [[ "$ENSURE_DOMAIN" == "1" ]]; then
|
||||
log_info "Adding domain ${MAIL_DOMAIN} on Mailcow…"
|
||||
_add_dom=$(jq -n \
|
||||
--arg d "$MAIL_DOMAIN" \
|
||||
'{active:"1",aliases:"400",backupmx:"0",defquota:"3072",description:"provision-mailcow-mailbox.sh",domain:$d,mailboxes:"50",maxquota:"102400",quota:"102400",relay_all_recipients:"0",restart_sogo:"1"}')
|
||||
_dr=$(mc_curl POST "add/domain" "$_add_dom")
|
||||
if ! response_ok "$_dr"; then
|
||||
log_err "add/domain failed: $(echo "$_dr" | jq -c . 2>/dev/null || echo "$_dr")"
|
||||
exit 1
|
||||
fi
|
||||
log_ok "Domain added: ${MAIL_DOMAIN}"
|
||||
else
|
||||
log_err "Domain ${MAIL_DOMAIN} is not configured on Mailcow. Add it in the UI or set ENSURE_DOMAIN=1."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Existing mailbox?
|
||||
_mbs=$(mc_curl GET "get/mailbox/all/${MAIL_DOMAIN}" || echo '[]')
|
||||
if echo "$_mbs" | jq -e 'type == "object" and .type == "error"' >/dev/null 2>&1; then
|
||||
log_err "get/mailbox/all failed: $(echo "$_mbs" | jq -c .)"
|
||||
exit 1
|
||||
fi
|
||||
if echo "$_mbs" | jq -e --arg u "${MAIL_LOCAL_PART}@${MAIL_DOMAIN}" '[.[]? | select(.username == $u)] | length > 0' >/dev/null 2>&1; then
|
||||
if [[ "$FORCE" == "1" ]]; then
|
||||
log_warn "Mailbox exists; --force not implemented (use Mailcow UI to reset password). Exiting."
|
||||
exit 1
|
||||
fi
|
||||
log_ok "Mailbox already exists: ${MAIL_LOCAL_PART}@${MAIL_DOMAIN}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
_pw="${MAILBOX_PASSWORD:-}"
|
||||
if [[ -z "$_pw" ]]; then
|
||||
_pw="$(openssl rand -base64 24 | tr -d '\n' | tr '/+' 'Aa')"
|
||||
log_warn "Generated MAILBOX_PASSWORD (save now; not stored): ${_pw}"
|
||||
fi
|
||||
|
||||
_add_mb=$(jq -n \
|
||||
--arg lp "$MAIL_LOCAL_PART" \
|
||||
--arg d "$MAIL_DOMAIN" \
|
||||
--arg n "$MAIL_DISPLAY_NAME" \
|
||||
--arg p "$_pw" \
|
||||
--argjson q "$MAIL_QUOTA_MB" \
|
||||
'{active:"1",domain:$d,local_part:$lp,name:$n,password:$p,password2:$p,quota:($q|tostring),force_pw_update:"0",tls_enforce_in:"0",tls_enforce_out:"0"}')
|
||||
|
||||
_mr=$(mc_curl POST "add/mailbox" "$_add_mb")
|
||||
if ! response_ok "$_mr"; then
|
||||
log_err "add/mailbox failed: $(echo "$_mr" | jq -c . 2>/dev/null || echo "$_mr")"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_ok "Mailbox created: ${MAIL_LOCAL_PART}@${MAIL_DOMAIN}"
|
||||
log_info "Web UI: ${MAILCOW_BASE_URL}/"
|
||||
Reference in New Issue
Block a user