@dbx-tools/shared-email 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -0
- package/index.ts +6 -0
- package/package.json +38 -0
- package/src/email.ts +116 -0
- package/tsconfig.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# @dbx-tools/shared-email
|
|
2
|
+
|
|
3
|
+
Browser-safe email schemas and inferred types.
|
|
4
|
+
|
|
5
|
+
Import this package when a UI, Mastra tool schema, server route, or test needs
|
|
6
|
+
to validate the same email payloads that
|
|
7
|
+
[`@dbx-tools/node-email`](../../node/email) sends.
|
|
8
|
+
|
|
9
|
+
Key features:
|
|
10
|
+
|
|
11
|
+
- Shared `EmailMessage` contract for generated email drafts and direct sends.
|
|
12
|
+
- Attachment schema that supports inline content, file paths, URLs, encoding,
|
|
13
|
+
and content-type hints.
|
|
14
|
+
- Send-result schema for SMTP and outbox responses.
|
|
15
|
+
- Sender-options schema for AppKit routes that expose allowed `From` values to
|
|
16
|
+
a browser client.
|
|
17
|
+
- Model/tool-friendly schemas that avoid JSON Schema constraints known to cause
|
|
18
|
+
problems with some serving endpoints.
|
|
19
|
+
|
|
20
|
+
## Validate A Drafted Message
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { email, type EmailMessage } from "@dbx-tools/shared-email";
|
|
24
|
+
|
|
25
|
+
const message: EmailMessage = email.emailMessageSchema.parse({
|
|
26
|
+
to: ["alice@example.com"],
|
|
27
|
+
subject: "Report",
|
|
28
|
+
body: "# Done\nThe report is attached.",
|
|
29
|
+
attachments: [{ filename: "report.csv", content: "a,b\n1,2\n" }],
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The message schema covers recipients, subject, Markdown body, and attachments.
|
|
34
|
+
Attachments can carry inline content, a local path, a URL, encoding metadata, and
|
|
35
|
+
content type hints.
|
|
36
|
+
|
|
37
|
+
## Validate Send Results
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
const result = email.emailResultSchema.parse(await sendResponse.json());
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`emailResultSchema` is the shared shape for SMTP sends and outbox writes. Use it
|
|
44
|
+
for approval UI state and test assertions.
|
|
45
|
+
|
|
46
|
+
## Render Sender Choices
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const senders = email.emailSendersSchema.parse(
|
|
50
|
+
await fetch("/api/email/senders").then((r) => r.json()),
|
|
51
|
+
);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The sender schema describes the concrete `From` choices for the current user,
|
|
55
|
+
the default sender, and whether the list is restricted by policy.
|
|
56
|
+
|
|
57
|
+
## Module
|
|
58
|
+
|
|
59
|
+
- `email` - `emailAttachmentSchema`, `emailMessageSchema`,
|
|
60
|
+
`emailResultSchema`, `emailSendersSchema`, and flat inferred types:
|
|
61
|
+
`EmailAttachment`, `EmailMessage`, `EmailResult`, and `EmailSenders`.
|
|
62
|
+
|
|
63
|
+
The schemas intentionally avoid array `.min()` constraints so they can be reused
|
|
64
|
+
as model/tool JSON schemas for serving endpoints that reject `minItems`.
|
package/index.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// GENERATED by projen watch - DO NOT EDIT.
|
|
2
|
+
// Regenerated from the exporting modules in ./src.
|
|
3
|
+
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
|
+
|
|
5
|
+
export * as email from "./src/email";
|
|
6
|
+
export type { EmailAttachment, EmailMessage, EmailResult, EmailSenders } from "./src/email";
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dbx-tools/shared-email",
|
|
3
|
+
"devDependencies": {
|
|
4
|
+
"@types/node": "^24.6.0",
|
|
5
|
+
"tsx": "^4.23.0",
|
|
6
|
+
"typescript": "^5.9.3"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"zod": "^4.3.6",
|
|
10
|
+
"@dbx-tools/shared-core": "0.1.2"
|
|
11
|
+
},
|
|
12
|
+
"main": "index.ts",
|
|
13
|
+
"license": "UNLICENSED",
|
|
14
|
+
"version": "0.1.2",
|
|
15
|
+
"types": "index.ts",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": "./index.ts",
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"dbxToolsConfig": {
|
|
22
|
+
"tags": [
|
|
23
|
+
"shared"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"pnpm exec projen\".",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "projen build",
|
|
29
|
+
"compile": "projen compile",
|
|
30
|
+
"default": "projen default",
|
|
31
|
+
"package": "projen package",
|
|
32
|
+
"post-compile": "projen post-compile",
|
|
33
|
+
"pre-compile": "projen pre-compile",
|
|
34
|
+
"test": "projen test",
|
|
35
|
+
"watch": "projen watch",
|
|
36
|
+
"projen": "projen"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/email.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire-format contract for the email add-on: the email a model drafts and the
|
|
3
|
+
* result of dispatching it. Pure (zod + inferred types, no Node-only imports)
|
|
4
|
+
* so the server-side sender, the Mastra tool, and the React approval UI all
|
|
5
|
+
* validate / type against one definition.
|
|
6
|
+
*
|
|
7
|
+
* Array fields intentionally avoid `.min()` / `.nonempty()`: those emit
|
|
8
|
+
* `minItems` in the JSON schema, which some Model Serving endpoints reject
|
|
9
|
+
* ("array types do not support minItems") when the schema is forwarded as a
|
|
10
|
+
* tool definition.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
15
|
+
/** Schema for a single file attached to an outbound email. */
|
|
16
|
+
export const emailAttachmentSchema = z.object({
|
|
17
|
+
filename: z.string().describe('File name shown to the recipient (e.g. "report.pdf").'),
|
|
18
|
+
content: z
|
|
19
|
+
.string()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe(
|
|
22
|
+
'Inline file content as a string. For binary data set `encoding` (e.g. "base64"). Provide this or `path`, not both.',
|
|
23
|
+
),
|
|
24
|
+
encoding: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe(
|
|
28
|
+
'Encoding of `content` (e.g. "base64", "utf-8", "hex"). Defaults to utf-8 when omitted.',
|
|
29
|
+
),
|
|
30
|
+
path: z
|
|
31
|
+
.string()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe(
|
|
34
|
+
"Read the content from here instead of inlining it: a local file path, a data: URI, or an https URL. Provide this or `content`, not both.",
|
|
35
|
+
),
|
|
36
|
+
contentType: z
|
|
37
|
+
.string()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe(
|
|
40
|
+
'MIME type override (e.g. "application/pdf"). Inferred from the filename when omitted.',
|
|
41
|
+
),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
/** A single file attached to an {@link EmailMessage}. */
|
|
45
|
+
export type EmailAttachment = z.infer<typeof emailAttachmentSchema>;
|
|
46
|
+
|
|
47
|
+
/** Schema for the email a model asks to send (the tool input). */
|
|
48
|
+
export const emailMessageSchema = z.object({
|
|
49
|
+
to: z
|
|
50
|
+
.array(z.string())
|
|
51
|
+
.describe(
|
|
52
|
+
'One or more recipient email addresses (e.g. ["alice@example.com", "bob@example.com"]). Provide at least one.',
|
|
53
|
+
),
|
|
54
|
+
subject: z.string().describe("Subject line. Keep it short and specific."),
|
|
55
|
+
body: z
|
|
56
|
+
.string()
|
|
57
|
+
.describe(
|
|
58
|
+
[
|
|
59
|
+
"Email body in GitHub-Flavored Markdown; it is rendered to HTML before sending.",
|
|
60
|
+
"Use real Markdown structure: '#'/'##' headings, '-' or '1.' lists, **bold**/_italic_, '>' blockquotes, and fenced ``` code blocks.",
|
|
61
|
+
"For tabular data, emit a real Markdown table: a header row, then a '| --- | --- |' separator row, then one '| ... |' row per record.",
|
|
62
|
+
"Do NOT format with ASCII art: no '=====' or '-----' divider lines, and never hand-draw tables or bar charts with spaces, pipes, or '#'. Use the Markdown constructs above instead.",
|
|
63
|
+
"Be self-contained: the recipient has none of the chat context.",
|
|
64
|
+
].join(" "),
|
|
65
|
+
),
|
|
66
|
+
cc: z.array(z.string()).optional().describe("Optional CC recipient addresses (one or more)."),
|
|
67
|
+
bcc: z.array(z.string()).optional().describe("Optional BCC recipient addresses (one or more)."),
|
|
68
|
+
attachments: z
|
|
69
|
+
.array(emailAttachmentSchema)
|
|
70
|
+
.optional()
|
|
71
|
+
.describe("Optional file attachments to include with the message."),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
/** A validated outbound email message. */
|
|
75
|
+
export type EmailMessage = z.infer<typeof emailMessageSchema>;
|
|
76
|
+
|
|
77
|
+
/** Schema for the dispatch result returned to the model after a send. */
|
|
78
|
+
export const emailResultSchema = z.object({
|
|
79
|
+
sent: z.boolean().describe("True once the message was handed to the SMTP server."),
|
|
80
|
+
recipient: z
|
|
81
|
+
.string()
|
|
82
|
+
.describe("Echo of the `to` recipients (comma-joined) for confirmation."),
|
|
83
|
+
from: z.string().describe("The resolved sender address the message was actually sent from."),
|
|
84
|
+
messageId: z
|
|
85
|
+
.string()
|
|
86
|
+
.optional()
|
|
87
|
+
.describe("SMTP message id assigned by the server, when one was returned."),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
/** The outcome of dispatching an {@link EmailMessage}. */
|
|
91
|
+
export type EmailResult = z.infer<typeof emailResultSchema>;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Schema for the sender options a UI can offer for the `From` address - the
|
|
95
|
+
* payload of the plugin's `GET /senders` route. When the plugin configures a
|
|
96
|
+
* sender allow-list, `senders` holds the concrete addresses the current user
|
|
97
|
+
* may send as (domain wildcards expanded against the user's local part) and
|
|
98
|
+
* `restricted` is true; a picker should require a choice from the list. When
|
|
99
|
+
* unrestricted, `senders` holds at most the single default address (if one can
|
|
100
|
+
* be resolved) and `restricted` is false, so a UI may allow free entry.
|
|
101
|
+
*/
|
|
102
|
+
export const emailSendersSchema = z.object({
|
|
103
|
+
senders: z
|
|
104
|
+
.array(z.string())
|
|
105
|
+
.describe("Permitted sender addresses to offer as `From` choices."),
|
|
106
|
+
defaultSender: z
|
|
107
|
+
.string()
|
|
108
|
+
.optional()
|
|
109
|
+
.describe("The address a send uses by default (first `senders` entry, if any)."),
|
|
110
|
+
restricted: z
|
|
111
|
+
.boolean()
|
|
112
|
+
.describe("True when `senders` is an enforced allow-list rather than a hint."),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/** Sender options for a `From` picker (see {@link emailSendersSchema}). */
|
|
116
|
+
export type EmailSenders = z.infer<typeof emailSendersSchema>;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// ~~ Generated by projen. To modify, edit .projenrc.js and run "pnpm exec projen".
|
|
2
|
+
{
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "src",
|
|
5
|
+
"outDir": "lib",
|
|
6
|
+
"alwaysStrict": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"experimentalDecorators": true,
|
|
10
|
+
"inlineSourceMap": true,
|
|
11
|
+
"inlineSources": true,
|
|
12
|
+
"lib": [
|
|
13
|
+
"ES2022",
|
|
14
|
+
"WebWorker"
|
|
15
|
+
],
|
|
16
|
+
"module": "ESNext",
|
|
17
|
+
"noEmitOnError": false,
|
|
18
|
+
"noFallthroughCasesInSwitch": true,
|
|
19
|
+
"noImplicitAny": true,
|
|
20
|
+
"noImplicitReturns": true,
|
|
21
|
+
"noImplicitThis": true,
|
|
22
|
+
"noUnusedLocals": true,
|
|
23
|
+
"noUnusedParameters": true,
|
|
24
|
+
"resolveJsonModule": true,
|
|
25
|
+
"strict": true,
|
|
26
|
+
"strictNullChecks": true,
|
|
27
|
+
"strictPropertyInitialization": true,
|
|
28
|
+
"stripInternal": true,
|
|
29
|
+
"target": "ES2022",
|
|
30
|
+
"types": [],
|
|
31
|
+
"moduleResolution": "bundler",
|
|
32
|
+
"skipLibCheck": true
|
|
33
|
+
},
|
|
34
|
+
"include": [
|
|
35
|
+
"src/**/*.ts"
|
|
36
|
+
],
|
|
37
|
+
"exclude": [
|
|
38
|
+
"node_modules"
|
|
39
|
+
]
|
|
40
|
+
}
|