Migadu Email Infrastructure — Add Domain & Alias Guide
Migadu Email Infrastructure — Alias & Mailbox Management
MC #100300 — 2026-05-10 | Owner: FlowForge (kelsey-hightower)
Replaces: CF Email Routing alias pattern. Migadu Mini ($90/yr) is now canonical for all ALAI email.
Account & API
- Migadu account: alem@alai.no (admin)
- API base URL: https://api.migadu.com/v1/
- Auth: HTTP Basic — username=alem@alai.no, password=API token (BW item: 78a41da0-b36f-46b9-b6e2-509b39768cec)
- IMAP: imap.migadu.com:993 (SSL)
- SMTP: smtp.migadu.com:465 (SSL)
Registered Domains (7)
alai.no | bilko.io | bilko.cloud | bilko.company | basicconsulting.no | basicfakta.no | getdrop.no
Active Mailboxes (5)
| Address | BW Item Name | Purpose |
|---|---|---|
| alem@alai.no | Migadu — alem@alai.no | CEO primary inbox |
| sales@bilko.io | Migadu — sales@bilko.io | Bilko SR sales/lead |
| sales@bilko.cloud | Migadu — sales@bilko.cloud | Bilko HR sales/lead |
| sales@bilko.company | Migadu — sales@bilko.company | Bilko BA sales/lead |
| privacy@bilko.io | Migadu — privacy@bilko.io | Bilko privacy requests |
How to Add a New Alias
An alias delivers to an existing mailbox without creating a new inbox.
# 1. Get Migadu token from Bitwarden
BW_SESSION=$(cat /tmp/bw-session)
TOKEN=$(bw get password "78a41da0-b36f-46b9-b6e2-509b39768cec" --session "$BW_SESSION")
# 2. Create forwarding (alias) on an existing mailbox
# This adds contact@bilko.io -> delivered to sales@bilko.io mailbox
curl -X POST "https://api.migadu.com/v1/domains/bilko.io/mailboxes/sales/forwardings/" \
-u "alem@alai.no:${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"address":"contact@bilko.io","name":"Contact Alias"}'
# 3. Verify
curl -s "https://api.migadu.com/v1/domains/bilko.io/mailboxes/sales" \
-u "alem@alai.no:${TOKEN}" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('forwardings', []))"
How to Add a New Mailbox
TOKEN=$(bw get password "78a41da0-b36f-46b9-b6e2-509b39768cec" --session "$(cat /tmp/bw-session)")
# Create new mailbox
curl -X POST "https://api.migadu.com/v1/domains/alai.no/mailboxes/" \
-u "alem@alai.no:${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"local_part":"hr","name":"HR Team","password":"","password_recovery_email":"alem@alai.no"}'
# Save password to Bitwarden immediately
echo '{"object":"item","type":1,"name":"Migadu — hr@alai.no","notes":"IMAP: imap.migadu.com:993 | SMTP: smtp.migadu.com:465","login":{"username":"hr@alai.no","password":"","uris":[]}}' | \
bw encode | bw create item --session "$(cat /tmp/bw-session)"
How to Add a New Domain
TOKEN=$(bw get password "78a41da0-b36f-46b9-b6e2-509b39768cec" --session "$(cat /tmp/bw-session)")
# 1. Register domain
curl -X POST "https://api.migadu.com/v1/domains/" \
-u "alem@alai.no:${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name":"newdomain.com"}'
# 2. Add DNS via CF (replace ZONE_ID):
CF_EMAIL="john@basicconsulting.no"
CF_KEY=$(bw get password "Cloudflare Global API Key" --session "$(cat /tmp/bw-session)")
ZONE_ID=""
DOMAIN="newdomain.com"
# MX records
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "X-Auth-Email: ${CF_EMAIL}" -H "X-Auth-Key: ${CF_KEY}" -H "Content-Type: application/json" \
-d "{\"type\":\"MX\",\"name\":\"${DOMAIN}\",\"content\":\"aspmx1.migadu.com\",\"priority\":10,\"ttl\":300}"
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "X-Auth-Email: ${CF_EMAIL}" -H "X-Auth-Key: ${CF_KEY}" -H "Content-Type: application/json" \
-d "{\"type\":\"MX\",\"name\":\"${DOMAIN}\",\"content\":\"aspmx2.migadu.com\",\"priority\":20,\"ttl\":300}"
# SPF
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "X-Auth-Email: ${CF_EMAIL}" -H "X-Auth-Key: ${CF_KEY}" -H "Content-Type: application/json" \
-d "{\"type\":\"TXT\",\"name\":\"${DOMAIN}\",\"content\":\"v=spf1 include:spf.migadu.com ~all\",\"ttl\":300}"
# DMARC
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "X-Auth-Email: ${CF_EMAIL}" -H "X-Auth-Key: ${CF_KEY}" -H "Content-Type: application/json" \
-d "{\"type\":\"TXT\",\"name\":\"_dmarc.${DOMAIN}\",\"content\":\"v=DMARC1; p=none; rua=mailto:postmaster@${DOMAIN}\",\"ttl\":300}"
# DKIM CNAMEs (x3)
for key in key1 key2 key3; do
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
-H "X-Auth-Email: ${CF_EMAIL}" -H "X-Auth-Key: ${CF_KEY}" -H "Content-Type: application/json" \
-d "{\"type\":\"CNAME\",\"name\":\"${key}._domainkey.${DOMAIN}\",\"content\":\"${key}.${DOMAIN}._domainkey.migadu.com\",\"ttl\":300}"
done
# 3. Poll until verified (typically 30-120 min)
watch -n 60 "curl -s https://api.migadu.com/v1/domains/${DOMAIN} -u alem@alai.no:\${TOKEN} | python3 -c \"import sys,json; d=json.load(sys.stdin); print(d.get('can_receive'))\""
Check Domain Verification
TOKEN=$(bw get password "78a41da0-b36f-46b9-b6e2-509b39768cec" --session "$(cat /tmp/bw-session)")
# All domains
curl -s "https://api.migadu.com/v1/domains/" -u "alem@alai.no:${TOKEN}" | \
python3 -c "import sys,json; [print(f\"{d['name']}: state={d['state']}, can_receive={d['can_receive']}\") for d in json.load(sys.stdin)[\domains']]"
CF Email Routing (DISABLED)
CF Email Routing has been disabled on bilko.io, bilko.cloud, bilko.company (2026-05-10). Do NOT re-enable. MX is now Migadu. Old routing rules are inactive.
IMAP History Migration (imapsync)
Script: /Users/makinja/business/ALAI-Holding-AS/infrastructure/email-migadu-migration.sh
Run after all domains show can_receive=True. Source: imap.one.com:993 | 876 messages baseline (2026-05-10).
one.com Cancellation (CEO action)
- Confirm all Migadu domains active + 48h dual-host complete (2026-05-12T20:39Z)
- Remove one.com MX records from CF zones: alai.no (id: 2d2028ebbe8fe433390a894111f56016) + basicconsulting.no (ids: 6b5c01115411ed28165fe294141c17bc, e5f35554bf4976bc6d5a85d4a309ff05, ce32445b537e1fbfc9c1f7cc9f051092, 614c98d0c34862cb28a8b9eb48b29823)
- CEO logs into one.com -> My Products -> Cancel Email subscription