{"_id":"@bobfrankston/smtp-direct","_rev":"7-239fa8168d5107acda6c5ce5d48ccc27","name":"@bobfrankston/smtp-direct","dist-tags":{"latest":"0.1.9"},"versions":{"0.1.2":{"name":"@bobfrankston/smtp-direct","version":"0.1.2","keywords":["smtp","email","browser","transport-agnostic"],"author":{"name":"Bob Frankston"},"license":"ISC","_id":"@bobfrankston/smtp-direct@0.1.2","maintainers":[{"name":"bobfrankston","email":"npm@bob.ma"}],"homepage":"https://github.com/BobFrankston/smtp-direct#readme","bugs":{"url":"https://github.com/BobFrankston/smtp-direct/issues"},"dist":{"shasum":"2e2220c25c596ae8c8c81eb85d66304a71bf33d0","tarball":"https://registry.npmjs.org/@bobfrankston/smtp-direct/-/smtp-direct-0.1.2.tgz","fileCount":8,"integrity":"sha512-Lc4mVX2ikdcaA2z+HNKxW5SfFgTTt401MuQaQvn6IwDfKc0Yt4XzIfQaHBpGGcb06GLzg7ZRCltnw3sJjXiGyQ==","signatures":[{"sig":"MEQCIFDkptIxELd2GS+KLKFvqE7yoHF8hOrfJLxFtYwXzA1WAiA+I/HXay6kVykyYmGWgTau21+V/uTvk60zx+V03g3V/g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28561},"main":"index.js","type":"module","_from":"file:bobfrankston-smtp-direct-0.1.2.tgz","types":"index.ts","exports":{".":{"types":"./index.ts","default":"./index.js"},"./types":{"types":"./types.ts","default":"./types.js"}},"scripts":{"build":"tsc","check":"tsc --noEmit","watch":"tsc -watch"},"_npmUser":{"name":"bobfrankston","email":"npm@bob.ma"},"_resolved":"Y:\\dev\\email\\MailApps\\smtp-direct\\bobfrankston-smtp-direct-0.1.2.tgz","_integrity":"sha512-Lc4mVX2ikdcaA2z+HNKxW5SfFgTTt401MuQaQvn6IwDfKc0Yt4XzIfQaHBpGGcb06GLzg7ZRCltnw3sJjXiGyQ==","repository":{"url":"git+https://github.com/BobFrankston/smtp-direct.git","type":"git"},"_npmVersion":"11.11.1","description":"Direct SMTP client — transport-agnostic, no Node.js dependencies, browser-ready","directories":{},"_nodeVersion":"25.8.2","dependencies":{"@bobfrankston/tcp-transport":"^0.1.3"},".dependencies":{"@bobfrankston/tcp-transport":"file:../tcp-transport"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,".transformedSnapshot":{"dependencies":{"@bobfrankston/tcp-transport":"^0.1.3"}},"_npmOperationalInternal":{"tmp":"tmp/smtp-direct_0.1.2_1776126630104_0.6400105824690077","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@bobfrankston/smtp-direct","version":"0.1.3","keywords":["smtp","email","browser","transport-agnostic"],"author":{"name":"Bob Frankston"},"license":"ISC","_id":"@bobfrankston/smtp-direct@0.1.3","maintainers":[{"name":"bobfrankston","email":"npm@bob.ma"}],"homepage":"https://github.com/BobFrankston/smtp-direct#readme","bugs":{"url":"https://github.com/BobFrankston/smtp-direct/issues"},"dist":{"shasum":"665b037c57203fdfa87cdf1c789968eb4352623a","tarball":"https://registry.npmjs.org/@bobfrankston/smtp-direct/-/smtp-direct-0.1.3.tgz","fileCount":8,"integrity":"sha512-Q8gq4cu8hQjS0TrSqmMUXdNJHLwPr/m/1Dn3qkTUFqLYKqnSN8BURVbT9QWC1l1canajjA6/7mEdHhBdVabepQ==","signatures":[{"sig":"MEYCIQC+2FoVbUBnNLgGppIv8Nim/TE8u1r0t+Dzz/qH87UXLQIhAKF1AdqNcAlS7WFOi98DhZifCEZe6rjZbacyD9iRKL70","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28618},"main":"index.js","type":"module","_from":"file:bobfrankston-smtp-direct-0.1.3.tgz","types":"index.ts","exports":{".":{"types":"./index.ts","default":"./index.js"},"./types":{"types":"./types.ts","default":"./types.js"}},"scripts":{"build":"tsc","check":"tsc --noEmit","watch":"tsc -watch"},"_npmUser":{"name":"bobfrankston","email":"npm@bob.ma"},"_resolved":"Y:\\dev\\email\\MailApps\\smtp-direct\\bobfrankston-smtp-direct-0.1.3.tgz","_integrity":"sha512-Q8gq4cu8hQjS0TrSqmMUXdNJHLwPr/m/1Dn3qkTUFqLYKqnSN8BURVbT9QWC1l1canajjA6/7mEdHhBdVabepQ==","repository":{"url":"git+https://github.com/BobFrankston/smtp-direct.git","type":"git"},"_npmVersion":"11.12.1","description":"Direct SMTP client — transport-agnostic, no Node.js dependencies, browser-ready","directories":{},"_nodeVersion":"25.9.0","dependencies":{"@bobfrankston/tcp-transport":"^0.1.4"},".dependencies":{"@bobfrankston/tcp-transport":"file:../tcp-transport"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^25.6.0"},".transformedSnapshot":{"dependencies":{"@bobfrankston/tcp-transport":"^0.1.4"}},"_npmOperationalInternal":{"tmp":"tmp/smtp-direct_0.1.3_1776312673311_0.7315793816734726","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@bobfrankston/smtp-direct","version":"0.1.4","keywords":["smtp","email","browser","transport-agnostic"],"author":{"name":"Bob Frankston"},"license":"ISC","_id":"@bobfrankston/smtp-direct@0.1.4","maintainers":[{"name":"bobfrankston","email":"npm@bob.ma"}],"homepage":"https://github.com/BobFrankston/smtp-direct#readme","bugs":{"url":"https://github.com/BobFrankston/smtp-direct/issues"},"dist":{"shasum":"9c28744f23c8774a9d5a8cfb9525d5c3766d4e76","tarball":"https://registry.npmjs.org/@bobfrankston/smtp-direct/-/smtp-direct-0.1.4.tgz","fileCount":8,"integrity":"sha512-yb/HhoRqEW02cIe35hAo8qe0t2raxaRDcqezp7XWJUslAbTnAXOMZSo+KjIxnBGTf4JtAaU5I5lAk00/iGDWXA==","signatures":[{"sig":"MEQCIFcL3auzQ7Aj7NAS9+hVFRKKhtqHhHi17z7G01dvTkWyAiAoIQkOAhLGd8Mw3u6rBIxgzVMPtii0h6TXyyuuw6jVVQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28618},"main":"index.js","type":"module","_from":"file:bobfrankston-smtp-direct-0.1.4.tgz","types":"index.ts","exports":{".":{"types":"./index.ts","default":"./index.js"},"./types":{"types":"./types.ts","default":"./types.js"}},"scripts":{"build":"tsc","check":"tsc --noEmit","watch":"tsc -watch"},"_npmUser":{"name":"bobfrankston","email":"npm@bob.ma"},"_resolved":"Y:\\dev\\email\\MailApps\\smtp-direct\\bobfrankston-smtp-direct-0.1.4.tgz","_integrity":"sha512-yb/HhoRqEW02cIe35hAo8qe0t2raxaRDcqezp7XWJUslAbTnAXOMZSo+KjIxnBGTf4JtAaU5I5lAk00/iGDWXA==","repository":{"url":"git+https://github.com/BobFrankston/smtp-direct.git","type":"git"},"_npmVersion":"11.12.1","description":"Direct SMTP client — transport-agnostic, no Node.js dependencies, browser-ready","directories":{},"_nodeVersion":"25.9.0","dependencies":{"@bobfrankston/tcp-transport":"^0.1.4"},".dependencies":{"@bobfrankston/tcp-transport":"file:../tcp-transport"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^25.6.0"},".transformedSnapshot":{"dependencies":{"@bobfrankston/tcp-transport":"^0.1.4"}},"_npmOperationalInternal":{"tmp":"tmp/smtp-direct_0.1.4_1776374189951_0.23663341436758323","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@bobfrankston/smtp-direct","version":"0.1.5","keywords":["smtp","email","browser","transport-agnostic"],"author":{"name":"Bob Frankston"},"license":"ISC","_id":"@bobfrankston/smtp-direct@0.1.5","maintainers":[{"name":"bobfrankston","email":"npm@bob.ma"}],"homepage":"https://github.com/BobFrankston/smtp-direct#readme","bugs":{"url":"https://github.com/BobFrankston/smtp-direct/issues"},"dist":{"shasum":"2ed6ca70e6c39962ebebe22151059a77a9a7ee24","tarball":"https://registry.npmjs.org/@bobfrankston/smtp-direct/-/smtp-direct-0.1.5.tgz","fileCount":8,"integrity":"sha512-XDxRhBjxbJlc8ziGHNykAOPRVoUBxAjfOgQoklKtzCkFQJO0jMYIRoqbf3LpAJhTYhKp2ZQ+QAqDSD205snMQQ==","signatures":[{"sig":"MEUCIA+S+cKtnhgYCB1sOEJKdvRd7SuJfwrYBYVUiHr8gUTMAiEA/RdAjyrViMmQZMZpJGxbD2TiaZOogrolXGsMCGlFhtI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28618},"main":"index.js","type":"module","_from":"file:bobfrankston-smtp-direct-0.1.5.tgz","types":"index.ts","exports":{".":{"types":"./index.ts","default":"./index.js"},"./types":{"types":"./types.ts","default":"./types.js"}},"scripts":{"build":"tsc","check":"tsc --noEmit","watch":"tsc -watch"},"_npmUser":{"name":"bobfrankston","email":"npm@bob.ma"},"_resolved":"Y:\\dev\\email\\MailApps\\smtp-direct\\bobfrankston-smtp-direct-0.1.5.tgz","_integrity":"sha512-XDxRhBjxbJlc8ziGHNykAOPRVoUBxAjfOgQoklKtzCkFQJO0jMYIRoqbf3LpAJhTYhKp2ZQ+QAqDSD205snMQQ==","repository":{"url":"git+https://github.com/BobFrankston/smtp-direct.git","type":"git"},"_npmVersion":"11.12.1","description":"Direct SMTP client — transport-agnostic, no Node.js dependencies, browser-ready","directories":{},"_nodeVersion":"25.9.0","dependencies":{"@bobfrankston/tcp-transport":"^0.1.5"},".dependencies":{"@bobfrankston/tcp-transport":"file:../tcp-transport"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^25.6.0"},".transformedSnapshot":{"dependencies":{"@bobfrankston/tcp-transport":"^0.1.5"}},"_npmOperationalInternal":{"tmp":"tmp/smtp-direct_0.1.5_1777075169242_0.8284186209996194","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@bobfrankston/smtp-direct","version":"0.1.7","keywords":["smtp","email","browser","transport-agnostic"],"author":{"name":"Bob Frankston"},"license":"ISC","_id":"@bobfrankston/smtp-direct@0.1.7","maintainers":[{"name":"bobfrankston","email":"npm@bob.ma"}],"homepage":"https://github.com/BobFrankston/smtp-direct#readme","bugs":{"url":"https://github.com/BobFrankston/smtp-direct/issues"},"dist":{"shasum":"22167a90e3047052c7020845f7756425e49fdc6a","tarball":"https://registry.npmjs.org/@bobfrankston/smtp-direct/-/smtp-direct-0.1.7.tgz","fileCount":8,"integrity":"sha512-z3I7eg1ZgUpiCT+n1dxv879TwcxDb5MWZA6rd3m5AjmUHHVTo9luZjp63oFfAKCTKDxemAi9Az4OmpFoVYu1Pg==","signatures":[{"sig":"MEUCICqzaM4FZebMAdnsohNZsWcr/7eG5jxm7cjK/Vft8sMmAiEAmOEF8EMfljM19b6PXxDHCQ4IY1KybgorT1H7IWNMMxQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28999},"main":"index.js","type":"module","_from":"file:bobfrankston-smtp-direct-0.1.7.tgz","types":"index.ts","exports":{".":{"types":"./index.ts","default":"./index.js"},"./types":{"types":"./types.ts","default":"./types.js"}},"scripts":{"build":"tsc","check":"tsc --noEmit","watch":"tsc -watch"},"_npmUser":{"name":"bobfrankston","email":"npm@bob.ma"},"_resolved":"Y:\\dev\\email\\MailApps\\smtp-direct\\bobfrankston-smtp-direct-0.1.7.tgz","_integrity":"sha512-z3I7eg1ZgUpiCT+n1dxv879TwcxDb5MWZA6rd3m5AjmUHHVTo9luZjp63oFfAKCTKDxemAi9Az4OmpFoVYu1Pg==","repository":{"url":"git+https://github.com/BobFrankston/smtp-direct.git","type":"git"},"_npmVersion":"11.13.0","description":"Direct SMTP client — transport-agnostic, no Node.js dependencies, browser-ready","directories":{},"_nodeVersion":"25.9.0","dependencies":{"@bobfrankston/tcp-transport":"^0.1.6"},".dependencies":{"@bobfrankston/tcp-transport":"file:../tcp-transport"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^25.6.0"},".transformedSnapshot":{"dependencies":{"@bobfrankston/tcp-transport":"^0.1.6"}},"_npmOperationalInternal":{"tmp":"tmp/smtp-direct_0.1.7_1778275776211_0.5666915336001037","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@bobfrankston/smtp-direct","version":"0.1.8","keywords":["smtp","email","browser","transport-agnostic"],"author":{"name":"Bob Frankston"},"license":"ISC","_id":"@bobfrankston/smtp-direct@0.1.8","maintainers":[{"name":"bobfrankston","email":"npm@bob.ma"}],"homepage":"https://github.com/BobFrankston/smtp-direct#readme","bugs":{"url":"https://github.com/BobFrankston/smtp-direct/issues"},"dist":{"shasum":"54ee38d7fc04500a9e45affee89f8264be7a96b4","tarball":"https://registry.npmjs.org/@bobfrankston/smtp-direct/-/smtp-direct-0.1.8.tgz","fileCount":8,"integrity":"sha512-ta25OLlJ2F2ggegDgKhF7ur36p+I+06QiToqxTqsyA09LNPL45oSMTjUoCnjcMnc/838oaQDrkdliS/G2Bb/Xg==","signatures":[{"sig":"MEQCIB4AJl3aIyMfMLuSyrPJ6qd0ijh1UulvAGbtvfoYa2RxAiAOU1i11tTAchQIlmICZGdTgWMnfoRBRJypHHlRum6GEw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28999},"main":"index.js","type":"module","_from":"file:bobfrankston-smtp-direct-0.1.8.tgz","types":"index.ts","exports":{".":{"types":"./index.ts","default":"./index.js"},"./types":{"types":"./types.ts","default":"./types.js"}},"scripts":{"build":"tsc","check":"tsc --noEmit","watch":"tsc -watch"},"_npmUser":{"name":"bobfrankston","email":"npm@bob.ma"},"_resolved":"Y:\\dev\\email\\MailApps\\smtp-direct\\bobfrankston-smtp-direct-0.1.8.tgz","_integrity":"sha512-ta25OLlJ2F2ggegDgKhF7ur36p+I+06QiToqxTqsyA09LNPL45oSMTjUoCnjcMnc/838oaQDrkdliS/G2Bb/Xg==","repository":{"url":"git+https://github.com/BobFrankston/smtp-direct.git","type":"git"},"_npmVersion":"11.13.0","description":"Direct SMTP client — transport-agnostic, no Node.js dependencies, browser-ready","directories":{},"_nodeVersion":"25.9.0","dependencies":{"@bobfrankston/tcp-transport":"^0.1.6"},".dependencies":{"@bobfrankston/tcp-transport":"file:../tcp-transport"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^25.6.0"},".transformedSnapshot":{"dependencies":{"@bobfrankston/tcp-transport":"^0.1.6"}},"_npmOperationalInternal":{"tmp":"tmp/smtp-direct_0.1.8_1778275858688_0.9902879250307801","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"name":"@bobfrankston/smtp-direct","version":"0.1.9","description":"Direct SMTP client — transport-agnostic, no Node.js dependencies, browser-ready","main":"index.js","types":"index.ts","type":"module","scripts":{"build":"tsc","watch":"tsc -watch","check":"tsc --noEmit"},"keywords":["smtp","email","browser","transport-agnostic"],"author":{"name":"Bob Frankston"},"license":"ISC","dependencies":{"@bobfrankston/tcp-transport":"^0.1.7"},"exports":{".":{"types":"./index.ts","default":"./index.js"},"./types":{"types":"./types.ts","default":"./types.js"}},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/BobFrankston/smtp-direct.git"},"devDependencies":{"@types/node":"^25.6.0"},".dependencies":{"@bobfrankston/tcp-transport":"file:../tcp-transport"},".transformedSnapshot":{"dependencies":{"@bobfrankston/tcp-transport":"^0.1.7"}},"_id":"@bobfrankston/smtp-direct@0.1.9","bugs":{"url":"https://github.com/BobFrankston/smtp-direct/issues"},"homepage":"https://github.com/BobFrankston/smtp-direct#readme","_integrity":"sha512-jC0VyiVhNq8wfanGx+o0q4yBeNHTyFr0jvAV0z3eJ+b7IMRTwolN1/u2+dMXSwn30GMHalsIg/UDtAQCzFtpuQ==","_resolved":"Y:\\dev\\email\\MailApps\\smtp-direct\\bobfrankston-smtp-direct-0.1.9.tgz","_from":"file:bobfrankston-smtp-direct-0.1.9.tgz","_nodeVersion":"26.1.0","_npmVersion":"11.14.1","dist":{"integrity":"sha512-jC0VyiVhNq8wfanGx+o0q4yBeNHTyFr0jvAV0z3eJ+b7IMRTwolN1/u2+dMXSwn30GMHalsIg/UDtAQCzFtpuQ==","shasum":"2f707e4eceb172431288367b2a789f9fc3cba399","tarball":"https://registry.npmjs.org/@bobfrankston/smtp-direct/-/smtp-direct-0.1.9.tgz","fileCount":8,"unpackedSize":28999,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCHOFyFdtDe9+qtZFK53wh2ZS5QCM9QyV9jFCSkhrkQCwIhAL8YvuttwAd+dNiikdl6v83TkkvzFIH4t++8ma3wZQZT"}]},"_npmUser":{"name":"bobfrankston","email":"npm@bob.ma"},"directories":{},"maintainers":[{"name":"bobfrankston","email":"npm@bob.ma"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/smtp-direct_0.1.9_1781025033149_0.33685423097829403"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-14T00:30:30.016Z","modified":"2026-06-09T17:10:33.435Z","0.1.2":"2026-04-14T00:30:30.246Z","0.1.3":"2026-04-16T04:11:13.477Z","0.1.4":"2026-04-16T21:16:30.085Z","0.1.5":"2026-04-24T23:59:29.403Z","0.1.7":"2026-05-08T21:29:36.369Z","0.1.8":"2026-05-08T21:30:58.830Z","0.1.9":"2026-06-09T17:10:33.306Z"},"bugs":{"url":"https://github.com/BobFrankston/smtp-direct/issues"},"author":{"name":"Bob Frankston"},"license":"ISC","homepage":"https://github.com/BobFrankston/smtp-direct#readme","keywords":["smtp","email","browser","transport-agnostic"],"repository":{"type":"git","url":"git+https://github.com/BobFrankston/smtp-direct.git"},"description":"Direct SMTP client — transport-agnostic, no Node.js dependencies, browser-ready","maintainers":[{"name":"bobfrankston","email":"npm@bob.ma"}],"readme":"# @bobfrankston/smtp-direct\n\nDirect SMTP client. Transport-agnostic, no Node.js dependencies, browser-ready.\n\nSibling to [`@bobfrankston/iflow-direct`](../iflow-direct/) (IMAP). They share the TCP transport interface (`ImapTransport` / `TransportFactory`) but the protocols themselves have nothing in common, so they remain separate packages.\n\n## Why\n\nThe Node.js SMTP libraries (nodemailer, smtp-connection) hard-depend on `node:net`/`node:tls` and won't run in a WebView, browser, or any non-Node host. `smtp-direct` is a clean-room ~250-line implementation that takes a TCP byte-stream from the caller and speaks SMTP over it. The same code runs unmodified on:\n\n- Desktop / Node — inject `NodeTransport` from `@bobfrankston/iflow-node`.\n- Android (MAUI WebView) / browser — inject `BridgeTransport` from `@bobfrankston/iflow-direct` (talks to the native shell's `msgapi.tcp`).\n\nThis means mailx-desktop, mailx-android, the resender server, and any future `msgapi.tcp`-capable host can share one SMTP code path.\n\n## What it implements\n\n- RFC 5321 — SMTP (EHLO, MAIL, RCPT, DATA, QUIT, RSET)\n- RFC 3207 — STARTTLS upgrade on port 587\n- Implicit TLS on port 465\n- RFC 4954 + 4616 — AUTH PLAIN\n- AUTH LOGIN (legacy, two-step base64 prompt)\n- RFC 4752 — AUTH XOAUTH2 (Google's bearer-token variant; same mechanism Gmail/Outlook use)\n- Multi-line server replies (`NNN-...` continuation, final `NNN ...`)\n- Per-recipient RCPT errors (partial accept = success)\n- Dot-stuffing per RFC 5321 §4.5.2\n- SIZE extension hint when the server advertises it\n\n## What it doesn't do (by design)\n\n- MIME assembly. Caller passes a complete RFC 2822 message; `smtp-direct` only handles the wire protocol.\n- Connection pooling / keep-alive. One client = one connection. For batch sends, reuse the client across `sendMail()` calls before `quit()`.\n- Retry / queue logic. Caller's outbox owns retry policy.\n- Raw TCP / TLS. Delegated to the injected `Transport`.\n\n## Install\n\n```jsonc\n{\n    \"dependencies\": {\n        \"@bobfrankston/smtp-direct\": \"file:../path/to/smtp-direct\",\n        \"@bobfrankston/iflow-direct\": \"file:../path/to/iflow-direct\",\n        \"@bobfrankston/iflow-node\": \"file:../path/to/iflow-node\"   // desktop only\n    }\n}\n```\n\n## Quick start — desktop\n\n```ts\nimport { SmtpClient } from \"@bobfrankston/smtp-direct\";\nimport { NodeTransport } from \"@bobfrankston/iflow-node\";\n\nconst smtp = new SmtpClient({\n    host: \"smtp.gmail.com\",\n    port: 587,                                  // STARTTLS submission\n    auth: { method: \"XOAUTH2\", user: \"me@gmail.com\", token: bearerToken },\n    localname: \"mybox.example.com\",\n    verbose: true,\n}, () => new NodeTransport());\n\nawait smtp.connect();\n\nconst result = await smtp.sendMail(\n    { from: \"me@gmail.com\", to: [\"a@example.com\", \"b@example.com\"] },\n    rawRfc822Message,\n);\nconsole.log(`accepted=${result.accepted.length} rejected=${result.rejected.length}`);\n\nawait smtp.quit();\n```\n\n## Quick start — Android / WebView\n\n```ts\nimport { SmtpClient } from \"@bobfrankston/smtp-direct\";\nimport { BridgeTransport } from \"@bobfrankston/iflow-direct\";\n\nconst smtp = new SmtpClient({\n    host: \"smtp.example.com\", port: 587,\n    auth: { method: \"PLAIN\", user: \"me\", pass: \"secret\" },\n}, () => new BridgeTransport());\n\nawait smtp.connect();\nawait smtp.sendMail({ from: \"me@example.com\", to: [\"you@example.com\"] }, raw);\nawait smtp.quit();\n```\n\nThe WebView host (msger / msga / Android MAUI shell) must expose `msgapi.tcp` — `BridgeTransport` calls `msgapi.tcp.connect`, `msgapi.tcp.upgradeTLS`, etc. All of msger's hosts already do this.\n\n## Config\n\n```ts\ninterface SmtpClientConfig {\n    host: string;\n    port: number;             // 587 (STARTTLS), 465 (implicit TLS), 25 (relay)\n    secure?: boolean;         // implicit TLS at connect. Default: port===465\n    auth?: SmtpAuth;          // omit for relay / unauthenticated server-to-server\n    localname?: string;       // EHLO name. Default: \"localhost\"\n    timeoutMs?: number;       // per-command inactivity. Default: 30000\n    verbose?: boolean;        // log SMTP traffic (auth lines redacted)\n}\n\ntype SmtpAuth =\n    | { method: \"PLAIN\";    user: string; pass: string }\n    | { method: \"LOGIN\";    user: string; pass: string }\n    | { method: \"XOAUTH2\";  user: string; token: string };\n```\n\n## sendMail result\n\n```ts\ninterface SmtpSendResult {\n    accepted: string[];\n    rejected: { address: string; code: number; message: string }[];\n    response: string;          // server's final 250 OK after DATA\n}\n```\n\n`sendMail` resolves whenever **at least one** recipient was accepted. Per-RCPT errors are reported in `result.rejected`. Only when **all** recipients are rejected does `sendMail` throw; the connection is `RSET` so it can be reused for the next send.\n\nA `MAIL FROM` rejection or a final `DATA` rejection always throws.\n\n## Reusing a connection\n\n`sendMail` can be called repeatedly between `connect()` and `quit()`:\n\n```ts\nawait smtp.connect();\nfor (const msg of queue) {\n    try {\n        await smtp.sendMail(msg.envelope, msg.raw);\n    } catch (e) {\n        console.error(`send failed: ${e}`);\n        // connection still usable — RSET was sent on partial-failure path\n    }\n}\nawait smtp.quit();\n```\n\nFor long sessions, watch the server's idle policy — most servers drop idle SMTP connections after 5 minutes.\n\n## Server compatibility tested against\n\n- Gmail (smtp.gmail.com:587, XOAUTH2) — primary target\n- Office 365 / Outlook (smtp.office365.com:587, XOAUTH2 or PLAIN) — works\n- Generic Dovecot+Postfix (any:587, PLAIN/LOGIN with STARTTLS) — works\n- Implicit TLS submission (any:465) — works\n\n## Caveats\n\n- One command at a time per connection. SMTP is synchronous; pipelining isn't implemented.\n- TLS certificate validation is the transport's job. `NodeTransport`/`BridgeTransport` decide whether to verify the server cert.\n- AUTH XOAUTH2 failure surfaces as a generic \"AUTH XOAUTH2 failed\". The server's base64 error JSON is consumed but not parsed.\n- No SASL mechanism negotiation beyond what the caller specifies. If the server doesn't advertise the chosen `AUTH=METHOD`, you'll get a 504 from the server rather than a pre-flight error from `smtp-direct`.\n\n## Layout\n\n```\nsmtp-direct/\n  index.ts          # public exports\n  smtp-client.ts    # SmtpClient class, dotStuff helper\n  types.ts          # SmtpClientConfig, SmtpAuth, SmtpSendResult, ...\n  package.json\n  tsconfig.json\n```\n\n## License\n\nISC\n","readmeFilename":"README.md"}