Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: Built-in services

Built-in services

The dev inbox and the health score

On this page

jadpo dev keeps every email your app sends in a local inbox, and scores each one for the common mistakes that send mail to spam. This topic is how the inbox, its commands and the score work (Email has the overview).

One catcher, kept on disk

jadpo dev gives the connection email: names the same catching driver a test's host gives it, so each message is handed over whole, a mail package's included. Each is kept in build/dev/inbox/ as a JSON file, with its attachments' bytes beside it, written whole and then renamed. jadpo email reads the inbox from another terminal, while jadpo dev runs or after.

The last 200 mails are kept. Their ids are mail_<n>, and an id is never given twice, even after jadpo email clear. A mail package's other operations still go to its fake. An SMTP connection's settings that nothing gives get stand-ins, as a provider's do, since its server is never reached.

A mail is kept whole, its sign-in link and code included, because development needs them. jadpo dev's line for a caught mail names its id, its email and its address, never its subject or its words, and the call log never sees it.

The inbox page

jadpo dev serves the page on 127.0.0.1, on the port after the app's, or on one the system chooses when that is taken. Its address is on the ready screen once the app sends mail, and it answers only requests addressed to localhost. The page is read-only, as the console is (The developer console and MCP).

It lists the mail newest first. The mail you choose is shown with its HTML in a sandboxed frame on white, its links opening a new tab, then its text, its links numbered with the jadpo email open command for each, its attachments and its health. It looks for new mail every two seconds. It shows the id of the trace that sent each mail; the link to the trace comes with jadpo trace (The request timeline in jadpo dev).

jadpo email

  • list, the default, shows the mail oldest first, and --to narrows it.
  • show <id> shows the text part, or the HTML with --html or when there is no text.
  • links <id> lists the links, numbered from 1.
  • open <id> <link> opens a link, by number or written out, in $BROWSER or the system's opener. It opens only http:// and https:// links.
  • clear empties the inbox.

An id is written mail_3 or 3.

The score's checks

The score runs seven checks. Each gives the same answer every time, and each comes with its fix:

  1. No plain-text part beside the HTML.
  2. Images with fewer than 20 characters of text.
  3. HTML that doesn't parse cleanly: an end tag that closes nothing or closes another element first, an element never closed (other than those HTML lets a writer leave open), or a tag never finished.
  4. A link that isn't absolute https://. This covers every href and every web address in the text. mailto:, tel: and sms: pass, and in the dev inbox so do links to this machine.
  5. A link through a shared shortener, from a fixed list.
  6. A subject of four or more letters that have a case, none of them lower case.
  7. HTML over 102 KB.

A score is the problems found and "N of 7 checks pass", with the note that it can't predict inbox placement. The check for an unsubscribe header waits for bulk mail, which no email is yet. SpamAssassin in the health score adds SpamAssassin's rules.

What jadpo check scores

jadpo check scores what a template's own text answers, as email.health_problem, which you can decline on the email's or partial's type:

  • an .html with no .txt;
  • a link written out whole, not built inside {{ }}, links to this machine included;
  • the HTML's structure with its {{ }} left out, only in a template with no {{ if }}, since a condition may open an element in one branch and close it in another;
  • an email's own HTML with images and neither text nor a value written as text;
  • a template over 102 KB;
  • a subject whose words, as a locale writes them, are in capitals.

What a template writes from its fields is scored once it is rendered, in the dev inbox. One decline above the type answers every finding there, as a decline covers its rule on its declaration (Declining a judgement call).

jadpo email check-domain

jadpo email check-domain reads the domain you give it. Without one it reads email: { from: }'s: the address written out, or the setting's value from the environment, .env.local or its default. It checks:

  • SPF, at the domain: one v=spf1 record, ending -all or ~all, its own terms needing at most 10 lookups. +all fails, and no record, or ?all, is an alert.
  • DKIM, at <selector>._domainkey.<domain>, only with --selector: a key with a p= that isn't empty.
  • DMARC, at _dmarc.<domain>: one v=DMARC1 record. p=quarantine or p=reject passes, and p=none is an alert.

What a provider needs beyond these, such as its include and its selector, waits for a mail package to declare it. The records are asked of the name server /etc/resolv.conf names, over UDP, then over TCP when the answer is cut short, behind a seam its tests fake. The command exits 0 with its verdicts, and --json says whether every record passed.

Markdown for agents: /docs/the-dev-inbox-and-the-health-score.md.Built from Jadpo main at a707efb.