ident
All repositories: gitoria
3.4 KB
\* hl:smtp — the SMTP submission client.import { Mailer } from 'hl:smtp'm = new Mailer('mail.example.com', 587, {user = '[email protected]'pass = '…'from = '[email protected]'})m.send({ to = '[email protected]' subject = 'Hello' text = 'Hi' })Non-blocking: send() answers a job id, the OUTCOME arrives later — drainit with `for (r of m.results())`, or deliver() it as the declared eventsbelow while the program keeps running. *\/* The first three declared properties ARE the positional signature (SPEC.md"The file root is the constructor"), so `new Mailer(host, port, options)`reads as written. */\* One send was ACCEPTED by the server. r = { id, ok, code, stage, message,secure, to }. *\emit sent(Hybrid r \\ the result record for one message)\* One send FAILED — refused, TLS problem, timeout. Same record shape;`stage` names where it died. *\emit failed(Hybrid r \\ the result record for one message)String host = "127.0.0.1" \\ the submission serverNumber port = 587 \\ 587 STARTTLS, 465 implicit TLSHybrid options = null \\ { user, pass, from, … } — credentials and defaults\* The plugin's handle for this mailer — set by the run body; a send() beforeconstruction finished is impossible, the root IS the constructor. *\Number handle = 0\* SEND — non-blocking. Validated and rendered HERE, on this thread, so arefusal (a line break in to/subject, a missing recipient, an addresswithout an @) is a located error at YOUR line, through `on Error` like anyplugin failure. Answers the job id; the outcome arrives on the resultsource. msg: { to (String or list), subject, text, html, from }. *\send(Hybrid msg \\ the message — to/subject/text/html/from) {return __native("smtp.send", handle, msg)}\* THE RESULT SOURCE, drained: `for (r of m.results())` yields one result peraccepted send and ENDS when every send is answered — which is what lets ascript that only sends mail terminate. *\results() {return __native("smtp.results", handle)}\* THE RESULT SOURCE, delivered: results arrive as the declared sent/failedevents while the program goes on — a server keeps serving with mail inflight. Use this OR results(), never both: they take from one queue. *\deliver() {__native("smtp.mark_registered", handle)__native("eventloop.register", __native("smtp.results", handle), "mail")}\* How many sends have not been answered yet. *\pending() {return __native("smtp.pending", handle)}\* Stop the sender thread. A job already in conversation finishes. *\close() {__native("smtp.close", handle)handle = 0}// The split every caller of deliver() wants: one event per outcome. `mail`// is delivered at THIS instance by the loop, and the re-emit dispatches at// it too, so an instance-scoped `on m.sent(r)` in the constructing program// hears it.on mail(r) {if (r.ok == true) {emit sent(r)} else {emit failed(r)}}// Open the mailer and start its sender thread. A METHOD, called from the run// body — never a root assignment: a bare `handle = …` at the root would be a// property INITIALIZER, and initializers run BEFORE positional args bind// (construction order 1 vs 4) — it would open a mailer for the DEFAULT host.// Same shape as hl:http1's listen().open() {handle = __native("smtp.open", host, port, options)}// Run body — the constructor's last act.open()
Branches
- mainmain branch
Latest commits
- 74235815ident mission 009 (4/4): docs (README files map + same-output test, STATUS, LOG), report, tests/letcount.py + realdata-baseline/comparemre
- fe183516ident mission 009 (3/4): let only where reassigned — 293 never-reassigned lets are plain declarations; kept: reassigned, loop bodies, names of a file member, a name declared twice in one function; same outputmre
- d2e7f91bident mission 009 (2/4): one lib file per topic (login, accounts, identities, apps, invites, selector, notify + helpers, util), function routes as thin wrappers in lib/api.hl, project.hl = the map; same outputmre
- 91017164ident mission 009 (1/4): file moves — the root .hl files into lib/ (api.hl → lib/api-helpers.hl), styles.hl → components/styles.hl; imports adjusted, no other changemre
- f8bdcbc2ident: Hybriel master 06617221 (plugin allocators 3a781359 + 413f60e4, mpackdb 2cb7ae5e, http1 773de63e); all gates greenmre
- ff78726cident: Hybriel master 190aa11d (fc838894 GC correctness, #127, #126 closure scopes); gates all greenmre
- a3a7d21aident: Hybriel master 8efba065 (#126 GC by bytes, #48 lambda params copy); session-writing lambdas take &sessionmre
- 98226b41antcolony#40: mission references point to the moved missionsmre
- ff805b9aantcolony#40: history (LOG.md), worker briefs (missions/) and reports moved here from antcolony, numbered per project; old numbers in antcolony docs/mission-map.mdmre
- 51a7bcdfident: Hybriel master 73267707 (#122); /code uses the new page() signature; pending address passed as parameter; once-checksmre
- 836f644fident#24: installable app (manifest, service worker, data-free offline /start), own iconmre
- 8bebbbf2deploy.sh: back up live storage/.sessions/.env before every deploy (newest 5 kept)mre
- cc063ea2deploy.sh: never send .git or .gitignore to Byrodinmre
- 81b15b7bState of 2026-09-27, before the move to gitoriamre