A small API to validate the SaaS DNS from forward.haltman.io
- JavaScript 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| app | ||
| scripts | ||
| sql | ||
| .env.example | ||
| .gitignore | ||
| agmh.txt | ||
| api.md | ||
| ecosystem.config.js | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
Mail Forwarding Domain Check (Simple)
Simple Node.js service that accepts DNS validation requests and polls DNS until the requirements are met or the request expires.
Setup
- Install dependencies:
npm install
- Create the database table:
# adjust credentials/host as needed
mariadb -u root -p your_db_name < sql/schema.sql
- Create
.envfrom.env.exampleand fill in values.
Security Notes
- Use a dedicated MariaDB user with least privilege. Grant only
SELECT,INSERT, andUPDATEon the specific database/table used by this service. - Optionally set
CHECKDNS_TOKENto require anx-api-keyheader for/api/checkdns/:target.
Run
# production
npm start
# development (Node 20+)
npm run dev
Optional sanity check:
npm run sanity:domain
API
Request UI validation (CNAME only)
curl -X POST http://localhost:3000/request/ui \
-H "Content-Type: application/json" \
-d '{"target":"example.com"}'
Request Email forwarding validation (MX + SPF + DMARC + DKIM)
curl -X POST http://localhost:3000/request/email \
-H "Content-Type: application/json" \
-d '{"target":"example.com"}'
Poll status for a target
curl http://localhost:3000/api/checkdns/example.com
DNS Polling Behavior
- Requests are inserted with status
PENDINGandexpires_at = now + DNS_JOB_MAX_AGE_HOURS(default 24h). - A new request for an existing
target+typerefreshes the existing row, clears stale DNS results, resets it toPENDING, extendsexpires_at, and immediately runs a fresh DNS check. - An in-process background job checks DNS every
DNS_POLL_INTERVAL_SECONDS. - Jobs stop when the request becomes
ACTIVEorEXPIRED. - On restart, any pending, non-expired requests are resumed.
- The process logs every DNS check with the configured/system DNS servers, found records, pending requirements, and partial resolver errors.
- The process logs a general status summary every
DNS_STATUS_LOG_INTERVAL_SECONDSseconds. Set it to0to disable.
/api/checkdns/:target
- Polling endpoint for UI and/or EMAIL validation for the target.
- Returns the existing
uiandemailrecords and their missing items. - If a row exists but has no
last_check_result_jsonyet, the endpoint performs a single DNS lookup for that row type, stores the result, and returns a best-effortmissinglist. It does not create requests or start jobs. - If a
PENDINGrow has an existing result butnext_check_athas already passed, the endpoint rechecks DNS once for that row type, stores the fresh result, and marks that rowACTIVEwhen its requirements are satisfied.
What ACTIVE Means
- UI: The target domain satisfies:
- CNAME record for
<target>matchingUI_CNAME_EXPECTEDor resolving toUI_CNAME_AUTHORIZED_IPSwhen set
- CNAME record for
- EMAIL: The target domain satisfies all of:
- MX record with
EMAIL_MX_EXPECTED_HOSTandEMAIL_MX_EXPECTED_PRIORITY - SPF TXT record exactly matching
EMAIL_SPF_EXPECTED - DMARC TXT record at
_dmarc.<target>exactly matchingEMAIL_DMARC_EXPECTED - DKIM CNAME record at
<EMAIL_DKIM_SELECTOR>._domainkey.<target>matchingEMAIL_DKIM_CNAME_EXPECTED
- MX record with