Skip to content

Commit 187d68f

Browse files
committed
Add postfix/bin/mksmtp.sh to create per-app SMTP accounts
Made-with: Cursor
1 parent 1eb32d2 commit 187d68f

1 file changed

Lines changed: 89 additions & 0 deletions

File tree

apps/postfix/bin/mksmtp.sh

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/bin/bash
2+
#
3+
# mksmtp.sh — create a dedicated SMTP auth account for an application.
4+
#
5+
# Usage: mksmtp.sh <app-name>
6+
#
7+
# Creates a Cyrus SASL account USERNAME@DOMAIN inside the running postfix
8+
# container and prints all parameters needed to configure the app.
9+
10+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
11+
POSTFIX_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12+
13+
# ── Argument check ─────────────────────────────────────────────────────────────
14+
if [ "$#" -ne 1 ]; then
15+
echo "Usage: $0 <app-name>" >&2
16+
exit 1
17+
fi
18+
19+
APP="$1"
20+
21+
# ── Dependency check ───────────────────────────────────────────────────────────
22+
if ! command -v pwgen >/dev/null 2>&1; then
23+
echo "pwgen not found — needed to generate a password." >&2
24+
echo "Install with: apt install pwgen" >&2
25+
exit 1
26+
fi
27+
28+
# ── Read postfix config ────────────────────────────────────────────────────────
29+
ENV_FILE="$POSTFIX_DIR/.env"
30+
if [ ! -f "$ENV_FILE" ]; then
31+
echo "Error: $ENV_FILE not found." >&2
32+
echo "Copy .env.example to .env and configure postfix before running this script." >&2
33+
exit 1
34+
fi
35+
36+
# Source only the SASL domain variable to avoid polluting the environment.
37+
SASL_DOMAIN="$(grep '^POSTFIX_smtpd_sasl_local_domain=' "$ENV_FILE" | cut -d= -f2- | tr -d '[:space:]')"
38+
39+
if [ -z "$SASL_DOMAIN" ]; then
40+
echo "Error: POSTFIX_smtpd_sasl_local_domain is not set in $ENV_FILE." >&2
41+
exit 1
42+
fi
43+
44+
SMTP_USER="${APP}@${SASL_DOMAIN}"
45+
SMTP_PASS="$(pwgen 24 1)"
46+
SMTP_HOST="postfix"
47+
SMTP_PORT="587"
48+
SMTP_URL="smtp://${APP}%40${SASL_DOMAIN}:${SMTP_PASS}@${SMTP_HOST}:${SMTP_PORT}"
49+
50+
# ── Check postfix container is running ────────────────────────────────────────
51+
echo "Checking postfix container..."
52+
if ! docker compose -f "$POSTFIX_DIR/docker-compose.yml" ps postfix 2>/dev/null | grep -q "Up"; then
53+
echo "Error: postfix container is not running." >&2
54+
echo "Start it with: docker compose -f $POSTFIX_DIR/docker-compose.yml up -d postfix" >&2
55+
exit 1
56+
fi
57+
echo " ✓ postfix is running"
58+
echo
59+
60+
# ── Create the SASL account ────────────────────────────────────────────────────
61+
echo "Creating SMTP account: ${SMTP_USER}"
62+
if echo "$SMTP_PASS" | docker compose -f "$POSTFIX_DIR/docker-compose.yml" \
63+
exec -T postfix saslpasswd2 -c -u "$SASL_DOMAIN" "$APP"; then
64+
echo " ✓ Account created"
65+
else
66+
echo " ✗ Failed to create account" >&2
67+
exit 1
68+
fi
69+
70+
# ── Output credentials ─────────────────────────────────────────────────────────
71+
echo
72+
echo "================================================================"
73+
echo "SMTP credentials for: ${APP}"
74+
echo "================================================================"
75+
echo " Host: ${SMTP_HOST}"
76+
echo " Port: ${SMTP_PORT}"
77+
echo " Username: ${SMTP_USER}"
78+
echo " Password: ${SMTP_PASS}"
79+
echo " URL: ${SMTP_URL}"
80+
echo "================================================================"
81+
echo
82+
echo "Add to ${APP}/.env:"
83+
echo " SMTP_HOST=${SMTP_HOST}"
84+
echo " SMTP_PORT=${SMTP_PORT}"
85+
echo " SMTP_USER=${SMTP_USER}"
86+
echo " SMTP_PASSWORD=${SMTP_PASS}"
87+
echo " EMAIL_URL=${SMTP_URL}"
88+
echo
89+
echo "Note: the URL uses %40 for the @ in the username."

0 commit comments

Comments
 (0)