Skip to content

Add DigitalOcean provider support #9

Description

@rtanglao

Add DigitalOcean provider support

Add digitalocean as a remediation provider in records.json so both the CLI
(--provider digitalocean) and the web app emit DigitalOcean-control-panel-specific
fix instructions for the 13-record Thundermail set (1 MX, 5 SRV, 4 TXT, 3 DKIM CNAME).

Internal ticket: TBPRO 7012
(7012_DNS_DIGITAL_OCEAN).

⚠️ Ship as UNVERIFIED first. The SRV field layout below is confirmed from a
screenshot of the live DigitalOcean Create a record dialog; the MX/TXT/CNAME field
labels come from DigitalOcean's official
How to Create, Edit, and Delete DNS Records
docs, not a live add-record screenshot. Follow the godaddy/ionos/ovh/hover precedent:
prefix each header string UNVERIFIED — until confirmed end-to-end, then drop the
prefix.

🎯 example.com is the verification target — it's DigitalOcean-hosted
(ns1/ns2/ns3.digitalocean.com). Query it authoritatively with
--resolver ns1.digitalocean.com.

The trailing-dot rule is now confirmed live on example.com. Its 5 SRV records were
entered without a trailing dot, so DigitalOcean appended the zone name to the target:

$ dig +short SRV _jmap._tcp.example.com
0 1 443 mail.thundermail.com.example.com.      # should be mail.thundermail.com

This proves DigitalOcean SRV targets must be entered as {target}. with the trailing
dot. (Its MX target came back correctly as mail.thundermail.com., so confirm whether MX
tolerates a missing dot or was simply entered with one.) ⚠️ Note the checker currently
reports example.com as a false 13/13 because of an unanchored substring match — see
#10; that bug should be fixed so these broken SRV targets show as FAIL.

Add-record model

DigitalOcean uses a single "Create a record" dialog with a Record Type dropdown (like
bunny/godaddy/hover, not per-type sections like cosmotown).

Path: Control Panel → Networking → Domains → select your domain → Create a record →
choose Record Type
, fill fields, Create Record. TTL defaults to 3600.

Key conventions (from the docs + the live SRV screenshot):

  • Apex host = literal @ for MX and TXT ("Use @ to create the record at the domain
    root"). This is the {host}/@ pattern like godaddy/ionos/hover, not the
    blank-apex pattern of bunny/cosmotown/ovh.
  • SRV keeps the _service._protocol label combined in the Hostname field (the
    screenshot placeholder is literally e.g. _service._protocol, one field). DigitalOcean
    does NOT split Service/Protocol into separate inputs the way godaddy/ionos/hover
    do — so use {host} and not the {service}/{protocol} tokens.
  • ⚠️ Targets require a trailing dot. The SRV Will direct to doc is explicit: an FQDN
    must be entered "with a period (.) at the end. This distinguishes it from a subdomain
    prefix" — otherwise DigitalOcean appends your domain. Since all our targets are external
    FQDNs (mail.thundermail.com, tmN.<domain>.dkim.thunderhosted.com), encode targets as
    {target}. (same trailing-dot handling as ovh). Confirm this also applies to the MX
    "Mail provider's mail server" and CNAME "Is an alias of" fields
    (the docs only spell it
    out for SRV, but DO's general behaviour is to append the domain when no dot is present).
  • No new interpreter token needed{host}, {target}, {value}, {priority},
    {weight}, {port} already cover everything.

Field mapping

SRV field order matches the screenshot (Record Type → Hostname → Will direct to → Port →
Priority → Weight → TTL):

Type Fields (DigitalOcean label → value)
MX Type=MX, Hostname={host} (@), Mail provider's mail server={target}., Priority={priority}
SRV Type=SRV, Hostname={host} (_jmap._tcp), Will direct to={target}., Port={port}, Priority={priority}, Weight={weight}
TXT Type=TXT, Hostname={host} (@), TXT Value={value}
CNAME Type=CNAME, Hostname={host}, Is an alias of={target}.

Note: SPF, MTA-STS, TLSRPT and DMARC are all plain TXT records on DigitalOcean (the
docs note SPF/DKIM are "special TXT records" created via the TXT option) — DKIM here is a
CNAME, so it uses the CNAME form.

Work items

  • Add the digitalocean provider block to records.json (headers UNVERIFIED —
    prefixed), using {host} for apex/SRV and {target}. for MX/SRV/CNAME targets.
  • Confirm no interpreter change is needed (existing tokens cover DigitalOcean).
  • uv run verify_thundermail_dns.py example.com --provider digitalocean renders all 13
    records in both --fix-format table and long without error.
  • Web app "DigitalOcean" provider mirrors the CLI output (table + detailed).
  • Update README.md provider list + RELEASE_NOTES / RELEASE_NOTES.html.
  • Update CLAUDE.md crucial-decisions with DigitalOcean's quirks (combined SRV
    Hostname, @ apex, trailing-dot targets).
  • Verify against example.com (--resolver ns1.digitalocean.com): confirm the
    trailing-dot rule on MX/CNAME targets against a live panel (SRV already confirmed),
    then drop the UNVERIFIED — prefixes. NB: example.com's SRV records are currently
    broken (target has .example.com appended) — fixing them there is itself a good live
    test of the emitted digitalocean SRV fix strings.

Reference docs

Local source: THUNDERBIRD_2023/TBPRO/7012_DNS_DIGITAL_OCEAN/7012-DNS-digitalocean-srv.png
(live SRV Create a record dialog).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions