agentmail-clone-v1 0.1.0
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/.env.example +20 -0
- package/.github/workflows/docs-deploy.yml +37 -0
- package/.github/workflows/landing-preview.yml +43 -0
- package/.github/workflows/openapi-lint.yml +31 -0
- package/.github/workflows/sdk-generate-check.yml +66 -0
- package/.github/workflows/sdk-release.yml +62 -0
- package/CHANGELOG.md +10 -0
- package/README.md +208 -0
- package/RELEASING.md +43 -0
- package/docs/api-reference/api-keys.mdx +11 -0
- package/docs/api-reference/domains.mdx +13 -0
- package/docs/api-reference/emails.mdx +26 -0
- package/docs/api-reference/inboxes.mdx +13 -0
- package/docs/api-reference/metrics.mdx +10 -0
- package/docs/authentication.mdx +25 -0
- package/docs/docs.json +35 -0
- package/docs/errors.mdx +34 -0
- package/docs/favicon.svg +5 -0
- package/docs/idempotency.mdx +18 -0
- package/docs/index.mdx +24 -0
- package/docs/quickstart.mdx +134 -0
- package/landing/DEPLOYING.md +33 -0
- package/landing/favicon.svg +5 -0
- package/landing/index.html +129 -0
- package/landing/main.js +45 -0
- package/landing/privacy.html +29 -0
- package/landing/styles.css +356 -0
- package/landing/terms.html +29 -0
- package/netlify.toml +15 -0
- package/openapi/openapi.yaml +1016 -0
- package/package.json +34 -0
- package/render.yaml +48 -0
- package/scripts/generate-sdk-py.sh +16 -0
- package/scripts/generate-sdk-ts.sh +16 -0
- package/scripts/migrate.js +66 -0
- package/scripts/validate-docs.js +56 -0
- package/scripts/validate-landing.js +39 -0
- package/sdks/python/README.md +40 -0
- package/sdks/python/emailagent_sdk/__init__.py +157 -0
- package/sdks/python/generated/.openapi-generator/FILES +101 -0
- package/sdks/python/generated/.openapi-generator/VERSION +1 -0
- package/sdks/python/generated/.openapi-generator-ignore +23 -0
- package/sdks/python/generated/emailagent_sdk_generated/__init__.py +105 -0
- package/sdks/python/generated/emailagent_sdk_generated/api/__init__.py +9 -0
- package/sdks/python/generated/emailagent_sdk_generated/api/api_keys_api.py +1162 -0
- package/sdks/python/generated/emailagent_sdk_generated/api/domains_api.py +1168 -0
- package/sdks/python/generated/emailagent_sdk_generated/api/emails_api.py +1232 -0
- package/sdks/python/generated/emailagent_sdk_generated/api/inboxes_api.py +1191 -0
- package/sdks/python/generated/emailagent_sdk_generated/api/metrics_api.py +285 -0
- package/sdks/python/generated/emailagent_sdk_generated/api_client.py +801 -0
- package/sdks/python/generated/emailagent_sdk_generated/api_response.py +21 -0
- package/sdks/python/generated/emailagent_sdk_generated/configuration.py +586 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/APIKeysApi.md +334 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/ApiKeyCreated.md +35 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/ApiKeyCreatedResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/ApiKeyListItem.md +35 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/ApiKeyListResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/CreateApiKeyRequest.md +30 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/CreateApiKeyRequestScopes.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/CreateDomainRequest.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/CreateInboxRequest.md +31 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/Domain.md +37 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/DomainListResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/DomainResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/DomainsApi.md +336 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/Email.md +43 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/EmailListResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/EmailResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/EmailsApi.md +353 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/ErrorResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/Inbox.md +38 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/InboxListResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/InboxResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/InboxesApi.md +337 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/MetricsApi.md +83 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/MetricsData.md +35 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/MetricsResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/OkResponse.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/PlanLimits.md +32 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/SendEmailRequest.md +32 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/UpdateEmailReadRequest.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/docs/UpdateInboxRequest.md +29 -0
- package/sdks/python/generated/emailagent_sdk_generated/exceptions.py +216 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/__init__.py +41 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/api_key_created.py +113 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/api_key_created_response.py +91 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/api_key_list_item.py +123 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/api_key_list_response.py +95 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/create_api_key_request.py +93 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/create_api_key_request_scopes.py +143 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/create_domain_request.py +87 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/create_inbox_request.py +91 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/domain.py +134 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/domain_list_response.py +95 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/domain_response.py +91 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/email.py +175 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/email_list_response.py +95 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/email_response.py +91 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/error_response.py +87 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/inbox.py +136 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/inbox_list_response.py +95 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/inbox_response.py +91 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/metrics_data.py +110 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/metrics_response.py +91 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/ok_response.py +87 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/plan_limits.py +93 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/send_email_request.py +93 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/update_email_read_request.py +87 -0
- package/sdks/python/generated/emailagent_sdk_generated/models/update_inbox_request.py +92 -0
- package/sdks/python/generated/emailagent_sdk_generated/rest.py +258 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/__init__.py +0 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_api_key_created.py +68 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_api_key_created_response.py +52 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_api_key_list_item.py +66 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_api_key_list_response.py +56 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_api_keys_api.py +59 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_create_api_key_request.py +53 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_create_api_key_request_scopes.py +50 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_create_domain_request.py +52 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_create_inbox_request.py +54 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_domain.py +70 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_domain_list_response.py +56 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_domain_response.py +52 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_domains_api.py +59 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_email.py +79 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_email_list_response.py +56 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_email_response.py +52 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_emails_api.py +59 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_error_response.py +52 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_inbox.py +68 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_inbox_list_response.py +56 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_inbox_response.py +52 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_inboxes_api.py +59 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_metrics_api.py +38 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_metrics_data.py +72 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_metrics_response.py +74 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_ok_response.py +52 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_plan_limits.py +58 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_send_email_request.py +56 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_update_email_read_request.py +52 -0
- package/sdks/python/generated/emailagent_sdk_generated/test/test_update_inbox_request.py +52 -0
- package/sdks/python/generated/emailagent_sdk_generated_README.md +140 -0
- package/sdks/python/openapitools.json +7 -0
- package/sdks/python/pyproject.toml +19 -0
- package/sdks/typescript/README.md +41 -0
- package/sdks/typescript/generated/.openapi-generator/FILES +41 -0
- package/sdks/typescript/generated/.openapi-generator/VERSION +1 -0
- package/sdks/typescript/generated/.openapi-generator-ignore +23 -0
- package/sdks/typescript/generated/package.json +21 -0
- package/sdks/typescript/generated/src/apis/APIKeysApi.ts +314 -0
- package/sdks/typescript/generated/src/apis/DomainsApi.ts +314 -0
- package/sdks/typescript/generated/src/apis/EmailsApi.ts +350 -0
- package/sdks/typescript/generated/src/apis/InboxesApi.ts +329 -0
- package/sdks/typescript/generated/src/apis/MetricsApi.ts +93 -0
- package/sdks/typescript/generated/src/apis/index.ts +7 -0
- package/sdks/typescript/generated/src/index.ts +5 -0
- package/sdks/typescript/generated/src/models/ApiKeyCreated.ts +123 -0
- package/sdks/typescript/generated/src/models/ApiKeyCreatedResponse.ts +74 -0
- package/sdks/typescript/generated/src/models/ApiKeyListItem.ts +121 -0
- package/sdks/typescript/generated/src/models/ApiKeyListResponse.ts +74 -0
- package/sdks/typescript/generated/src/models/CreateApiKeyRequest.ts +82 -0
- package/sdks/typescript/generated/src/models/CreateApiKeyRequestScopes.ts +45 -0
- package/sdks/typescript/generated/src/models/CreateDomainRequest.ts +66 -0
- package/sdks/typescript/generated/src/models/CreateInboxRequest.ts +82 -0
- package/sdks/typescript/generated/src/models/Domain.ts +152 -0
- package/sdks/typescript/generated/src/models/DomainListResponse.ts +74 -0
- package/sdks/typescript/generated/src/models/DomainResponse.ts +74 -0
- package/sdks/typescript/generated/src/models/Email.ts +222 -0
- package/sdks/typescript/generated/src/models/EmailListResponse.ts +74 -0
- package/sdks/typescript/generated/src/models/EmailResponse.ts +74 -0
- package/sdks/typescript/generated/src/models/ErrorResponse.ts +66 -0
- package/sdks/typescript/generated/src/models/Inbox.ts +159 -0
- package/sdks/typescript/generated/src/models/InboxListResponse.ts +74 -0
- package/sdks/typescript/generated/src/models/InboxResponse.ts +74 -0
- package/sdks/typescript/generated/src/models/MetricsData.ts +139 -0
- package/sdks/typescript/generated/src/models/MetricsResponse.ts +74 -0
- package/sdks/typescript/generated/src/models/OkResponse.ts +66 -0
- package/sdks/typescript/generated/src/models/PlanLimits.ts +93 -0
- package/sdks/typescript/generated/src/models/SendEmailRequest.ts +91 -0
- package/sdks/typescript/generated/src/models/UpdateEmailReadRequest.ts +66 -0
- package/sdks/typescript/generated/src/models/UpdateInboxRequest.ts +66 -0
- package/sdks/typescript/generated/src/models/index.ts +27 -0
- package/sdks/typescript/generated/src/runtime.ts +432 -0
- package/sdks/typescript/generated/tsconfig.esm.json +7 -0
- package/sdks/typescript/generated/tsconfig.json +16 -0
- package/sdks/typescript/openapitools.json +8 -0
- package/sdks/typescript/package.json +27 -0
- package/sdks/typescript/src/index.ts +138 -0
- package/sdks/typescript/tsconfig.json +14 -0
- package/sql/001_init.sql +143 -0
- package/sql/002_local_auth.sql +38 -0
- package/sql/003_domain_routes.sql +2 -0
- package/sql/004_reliability_primitives.sql +75 -0
- package/sql/005_auth_email_flows.sql +22 -0
- package/src/config.js +30 -0
- package/src/db.js +25 -0
- package/src/lib/api-auth.js +55 -0
- package/src/lib/auth.js +71 -0
- package/src/lib/csrf.js +46 -0
- package/src/lib/dodo.js +67 -0
- package/src/lib/email-templates.js +67 -0
- package/src/lib/idempotency.js +85 -0
- package/src/lib/mailgun.js +188 -0
- package/src/lib/plan.js +24 -0
- package/src/lib/rate-limit.js +43 -0
- package/src/lib/security.js +62 -0
- package/src/lib/session.js +21 -0
- package/src/lib/store.js +638 -0
- package/src/lib/transactional-mailer.js +54 -0
- package/src/lib/validation.js +30 -0
- package/src/routes/api.js +485 -0
- package/src/routes/app.js +699 -0
- package/src/routes/auth.js +404 -0
- package/src/routes/webhooks.js +257 -0
- package/src/server.js +79 -0
- package/src/views/pages/admin.ejs +58 -0
- package/src/views/pages/api-keys.ejs +56 -0
- package/src/views/pages/billing.ejs +71 -0
- package/src/views/pages/domains.ejs +106 -0
- package/src/views/pages/inboxes.ejs +127 -0
- package/src/views/pages/login.ejs +57 -0
- package/src/views/pages/metrics.ejs +34 -0
- package/src/views/pages/reset-password.ejs +19 -0
- package/src/views/partials/bottom.ejs +3 -0
- package/src/views/partials/csrf-field.ejs +3 -0
- package/src/views/partials/flash.ejs +3 -0
- package/src/views/partials/top.ejs +130 -0
package/docs/errors.mdx
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Errors
|
|
3
|
+
description: Error format and status code guidance.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Error response shape:
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"error": "message"
|
|
11
|
+
}
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Common status codes:
|
|
15
|
+
|
|
16
|
+
- `400` invalid request
|
|
17
|
+
- `401` missing/invalid bearer token
|
|
18
|
+
- `403` missing scope
|
|
19
|
+
- `404` resource not found
|
|
20
|
+
- `409` idempotency conflict
|
|
21
|
+
- `422` plan/validation limits
|
|
22
|
+
- `429` rate limited
|
|
23
|
+
- `500` provider/internal failure
|
|
24
|
+
|
|
25
|
+
Use idempotency keys and exponential backoff for retryable failures.
|
|
26
|
+
|
|
27
|
+
## Inbound webhook statuses
|
|
28
|
+
|
|
29
|
+
When Mailgun forwards inbound mail to `/webhooks/mailgun/inbound`:
|
|
30
|
+
|
|
31
|
+
- `200` with `{"ok": true}`: inbound accepted and saved.
|
|
32
|
+
- `200` with `{"ok": true, "duplicate": true}`: duplicate delivery ignored.
|
|
33
|
+
- `202` with `{"ok": true, "ignored": true}`: recipient inbox not found.
|
|
34
|
+
- `401`: signature verification failed (`MAILGUN_WEBHOOK_SIGNING_KEY` mismatch).
|
package/docs/favicon.svg
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
|
2
|
+
<rect width="64" height="64" rx="14" fill="#0c6f5c"/>
|
|
3
|
+
<path d="M16 22h32v20H16V22zm2 2v16h28V24H18z" fill="#ffffff"/>
|
|
4
|
+
<path d="M18 24l14 10 14-10" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Idempotency
|
|
3
|
+
description: Safe retries for mutating operations.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
For mutating endpoints (`POST`, `PATCH`, `DELETE`), send:
|
|
7
|
+
|
|
8
|
+
```http
|
|
9
|
+
Idempotency-Key: <unique_operation_key>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Behavior:
|
|
13
|
+
|
|
14
|
+
- Same key + same payload: original response is replayed.
|
|
15
|
+
- Same key + different payload: `409` conflict.
|
|
16
|
+
- In-progress duplicate: `409` conflict.
|
|
17
|
+
|
|
18
|
+
Use deterministic keys from your agent action IDs for safe retries.
|
package/docs/index.mdx
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: EmailAgent API
|
|
3
|
+
description: Email operations infrastructure for AI agents.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
EmailAgent gives agents a simple API to:
|
|
7
|
+
|
|
8
|
+
- Create and manage inboxes
|
|
9
|
+
- Send outbound emails
|
|
10
|
+
- Onboard and verify custom domains
|
|
11
|
+
- Manage API keys and scopes
|
|
12
|
+
- Track usage metrics
|
|
13
|
+
|
|
14
|
+
The canonical API contract is generated from:
|
|
15
|
+
|
|
16
|
+
- `openapi/openapi.yaml`
|
|
17
|
+
|
|
18
|
+
Base domains:
|
|
19
|
+
|
|
20
|
+
- App UI: `https://app.emailagent.dev`
|
|
21
|
+
- API: `https://api.emailagent.dev`
|
|
22
|
+
- Docs: `https://docs.emailagent.dev`
|
|
23
|
+
|
|
24
|
+
Start with [Quickstart](./quickstart).
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Quickstart
|
|
3
|
+
description: Create an API key, send email, and consume inbound email records.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## 0. Install SDKs (optional)
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install emailagent-sdk@0.1.0
|
|
10
|
+
pip install emailagent-sdk==0.1.0
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 1. Authenticate
|
|
14
|
+
|
|
15
|
+
Use a bearer API key from the dashboard.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
curl -X GET "https://api.emailagent.dev/api/v1/inboxes" \
|
|
19
|
+
-H "Authorization: Bearer <api_key>"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 2. Create inbox
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
curl -X POST "https://api.emailagent.dev/api/v1/inboxes" \
|
|
26
|
+
-H "Authorization: Bearer <api_key>" \
|
|
27
|
+
-H "Content-Type: application/json" \
|
|
28
|
+
-H "Idempotency-Key: create-inbox-agent-1" \
|
|
29
|
+
-d '{
|
|
30
|
+
"localPart": "agent-1",
|
|
31
|
+
"displayName": "Agent One"
|
|
32
|
+
}'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 3. Send email
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
curl -X POST "https://api.emailagent.dev/api/v1/emails/send" \
|
|
39
|
+
-H "Authorization: Bearer <api_key>" \
|
|
40
|
+
-H "Content-Type: application/json" \
|
|
41
|
+
-H "Idempotency-Key: send-welcome-001" \
|
|
42
|
+
-d '{
|
|
43
|
+
"inboxId": "<inbox_uuid>",
|
|
44
|
+
"to": "alice@example.com",
|
|
45
|
+
"subject": "Hello",
|
|
46
|
+
"text": "Welcome from your AI agent"
|
|
47
|
+
}'
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 4. List and mark inbound email
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
curl -X GET "https://api.emailagent.dev/api/v1/emails?inboxId=<inbox_uuid>" \
|
|
54
|
+
-H "Authorization: Bearer <api_key>"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
curl -X PATCH "https://api.emailagent.dev/api/v1/emails/<email_uuid>/read" \
|
|
59
|
+
-H "Authorization: Bearer <api_key>" \
|
|
60
|
+
-H "Content-Type: application/json" \
|
|
61
|
+
-H "Idempotency-Key: mark-read-001" \
|
|
62
|
+
-d '{"isRead": true}'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 5. SDK examples
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { EmailAgentClient } from 'emailagent-sdk';
|
|
69
|
+
|
|
70
|
+
const client = new EmailAgentClient({
|
|
71
|
+
apiKey: process.env.EMAILAGENT_API_KEY!,
|
|
72
|
+
baseUrl: 'https://api.emailagent.dev'
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const inboxes = await client.listInboxes();
|
|
76
|
+
const inboxId = inboxes.data[0].id;
|
|
77
|
+
const emails = await client.listEmails({ inboxId });
|
|
78
|
+
if (emails.data.length) {
|
|
79
|
+
await client.updateEmailRead(emails.data[0].id, true, { idempotencyKey: 'mark-read-001' });
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from emailagent_sdk import EmailAgentClient
|
|
85
|
+
|
|
86
|
+
client = EmailAgentClient(api_key="<api_key>", base_url="https://api.emailagent.dev")
|
|
87
|
+
inboxes = client.list_inboxes()
|
|
88
|
+
inbox_id = inboxes["data"][0]["id"]
|
|
89
|
+
emails = client.list_emails(inbox_id=inbox_id)
|
|
90
|
+
if emails["data"]:
|
|
91
|
+
client.update_email_read(
|
|
92
|
+
email_id=emails["data"][0]["id"],
|
|
93
|
+
is_read=True,
|
|
94
|
+
idempotency_key="mark-read-001",
|
|
95
|
+
)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 6. Shared-domain inbound route (manual setup)
|
|
99
|
+
|
|
100
|
+
For shared-domain inboxes (for example `agent@emailagent.dev`), configure this in Mailgun Routes:
|
|
101
|
+
|
|
102
|
+
- Expression: `match_recipient('.*@emailagent.dev')`
|
|
103
|
+
- Action 1: `forward('https://app.emailagent.dev/webhooks/mailgun/inbound')`
|
|
104
|
+
- Action 2: `stop()`
|
|
105
|
+
|
|
106
|
+
Also set `MAILGUN_WEBHOOK_SIGNING_KEY` in app environment to enforce webhook signature validation.
|
|
107
|
+
|
|
108
|
+
Expected successful webhook response:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{"ok": true}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 7. Inbound troubleshooting
|
|
115
|
+
|
|
116
|
+
| Webhook response | Meaning | Action |
|
|
117
|
+
| --- | --- | --- |
|
|
118
|
+
| `401` | Invalid signature | Verify `MAILGUN_WEBHOOK_SIGNING_KEY` matches Mailgun webhook signing key |
|
|
119
|
+
| `202` with `ignored: true` | Recipient does not map to active inbox | Create/check inbox local part and domain in app |
|
|
120
|
+
| `200` with `duplicate: true` | Duplicate event received | No action needed; dedupe is working |
|
|
121
|
+
|
|
122
|
+
## 8. Inbound smoke test
|
|
123
|
+
|
|
124
|
+
1. Create inbox `agent@emailagent.dev` in app.
|
|
125
|
+
2. Send email from external mailbox to that inbox.
|
|
126
|
+
3. Confirm message appears in dashboard inbox view.
|
|
127
|
+
4. Confirm same message appears via `GET /api/v1/emails?inboxId=<inbox_uuid>`.
|
|
128
|
+
|
|
129
|
+
## 9. Check metrics
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
curl -X GET "https://api.emailagent.dev/api/v1/metrics" \
|
|
133
|
+
-H "Authorization: Bearer <api_key>"
|
|
134
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Landing Deployment (Netlify)
|
|
2
|
+
|
|
3
|
+
This project hosts the public landing page on the root domain.
|
|
4
|
+
|
|
5
|
+
## Host mapping
|
|
6
|
+
- `emailagent.dev` -> Netlify landing site
|
|
7
|
+
- `www.emailagent.dev` -> redirect to `emailagent.dev`
|
|
8
|
+
- `app.emailagent.dev` -> Render app
|
|
9
|
+
- `api.emailagent.dev` -> Render API
|
|
10
|
+
- `docs.emailagent.dev` -> Docs host
|
|
11
|
+
|
|
12
|
+
## Netlify setup
|
|
13
|
+
1. Connect this GitHub repo to Netlify.
|
|
14
|
+
2. Build settings:
|
|
15
|
+
- Build command: (leave empty)
|
|
16
|
+
- Publish directory: `landing`
|
|
17
|
+
3. Add custom domain `emailagent.dev`.
|
|
18
|
+
4. Add `www.emailagent.dev` and configure redirect to apex.
|
|
19
|
+
5. In DNS provider, point apex and `www` records to Netlify targets.
|
|
20
|
+
|
|
21
|
+
## Optional PR previews from GitHub Actions
|
|
22
|
+
Set these GitHub repository secrets:
|
|
23
|
+
- `NETLIFY_AUTH_TOKEN`
|
|
24
|
+
- `NETLIFY_SITE_ID`
|
|
25
|
+
|
|
26
|
+
When configured, pull requests touching `landing/**` trigger preview deploys.
|
|
27
|
+
|
|
28
|
+
## Analytics setup
|
|
29
|
+
Edit `landing/index.html` and set values in `window.__landingAnalytics`:
|
|
30
|
+
- `plausibleDomain` for Plausible
|
|
31
|
+
- `ga4MeasurementId` for Google Analytics 4
|
|
32
|
+
|
|
33
|
+
`landing/main.js` tracks CTA events (`cta_click`) for both providers when available.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
|
2
|
+
<rect width="64" height="64" rx="14" fill="#0e7c66"/>
|
|
3
|
+
<path d="M14 22h36v20H14V22zm2 2v16h32V24H16z" fill="#fff"/>
|
|
4
|
+
<path d="M16 24l16 11 16-11" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>EmailAgent | Email Infrastructure for AI Agents</title>
|
|
7
|
+
<meta name="description" content="Provision inboxes, custom domains, API keys, and usage controls for AI agents with a simple API." />
|
|
8
|
+
<link rel="canonical" href="https://emailagent.dev" />
|
|
9
|
+
<meta property="og:title" content="EmailAgent" />
|
|
10
|
+
<meta property="og:description" content="Email infrastructure for AI agents." />
|
|
11
|
+
<meta property="og:type" content="website" />
|
|
12
|
+
<meta property="og:url" content="https://emailagent.dev" />
|
|
13
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
14
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
15
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
16
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
17
|
+
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Sora:wght@500;600;700&display=swap" rel="stylesheet" />
|
|
18
|
+
<link rel="stylesheet" href="./styles.css" />
|
|
19
|
+
<script>
|
|
20
|
+
window.__landingAnalytics = {
|
|
21
|
+
plausibleDomain: "",
|
|
22
|
+
ga4MeasurementId: ""
|
|
23
|
+
};
|
|
24
|
+
</script>
|
|
25
|
+
<script defer src="./main.js"></script>
|
|
26
|
+
</head>
|
|
27
|
+
<body>
|
|
28
|
+
<div class="noise"></div>
|
|
29
|
+
<header class="topbar">
|
|
30
|
+
<a href="/" class="brand">EmailAgent</a>
|
|
31
|
+
<nav class="topnav">
|
|
32
|
+
<a href="#pricing">Pricing</a>
|
|
33
|
+
<a href="https://docs.emailagent.dev" data-cta="docs-nav">Docs</a>
|
|
34
|
+
<a class="button ghost" href="https://app.emailagent.dev/" data-cta="login-nav">Log in</a>
|
|
35
|
+
</nav>
|
|
36
|
+
</header>
|
|
37
|
+
|
|
38
|
+
<main>
|
|
39
|
+
<section class="hero">
|
|
40
|
+
<p class="eyebrow">Built for API-first teams</p>
|
|
41
|
+
<h1>Email infrastructure for AI agents</h1>
|
|
42
|
+
<p class="lead">
|
|
43
|
+
Create agent inboxes, send and receive emails, manage custom domains, and issue scoped API keys.
|
|
44
|
+
No mailbox UI complexity. Just reliable primitives your agents can call.
|
|
45
|
+
</p>
|
|
46
|
+
<div class="cta-row">
|
|
47
|
+
<a class="button primary" href="https://app.emailagent.dev/" data-cta="start-free-hero">Start for free</a>
|
|
48
|
+
<a class="button secondary" href="https://docs.emailagent.dev" data-cta="docs-hero">Read API docs</a>
|
|
49
|
+
</div>
|
|
50
|
+
<p class="status-note">Built for agent workflows, not human mailbox clients.</p>
|
|
51
|
+
</section>
|
|
52
|
+
|
|
53
|
+
<section class="features" aria-label="Core product features">
|
|
54
|
+
<article>
|
|
55
|
+
<h2>Inbox provisioning</h2>
|
|
56
|
+
<p>Programmatically create and manage inbox identities for each agent persona.</p>
|
|
57
|
+
</article>
|
|
58
|
+
<article>
|
|
59
|
+
<h2>Custom domains</h2>
|
|
60
|
+
<p>Onboard and verify domains with DNS mapping and Mailgun-backed deliverability.</p>
|
|
61
|
+
</article>
|
|
62
|
+
<article>
|
|
63
|
+
<h2>API keys + scopes</h2>
|
|
64
|
+
<p>Issue scoped keys for tools and agents with explicit permission boundaries.</p>
|
|
65
|
+
</article>
|
|
66
|
+
<article>
|
|
67
|
+
<h2>Usage controls</h2>
|
|
68
|
+
<p>Track limits and metrics so your agent workflows stay predictable and cost-aware.</p>
|
|
69
|
+
</article>
|
|
70
|
+
</section>
|
|
71
|
+
|
|
72
|
+
<section class="api-first">
|
|
73
|
+
<div>
|
|
74
|
+
<h2>API-first by design</h2>
|
|
75
|
+
<p>
|
|
76
|
+
Base your integration on OpenAPI and use official SDKs for TypeScript and Python.
|
|
77
|
+
Build fast, then scale reliably.
|
|
78
|
+
</p>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="api-links">
|
|
81
|
+
<a href="https://docs.emailagent.dev" data-cta="docs-api-section">Open API documentation</a>
|
|
82
|
+
<a href="https://www.npmjs.com/package/emailagent-sdk" data-cta="npm-sdk">TypeScript SDK on npm</a>
|
|
83
|
+
<a href="https://pypi.org/project/emailagent-sdk/" data-cta="pypi-sdk">Python SDK on PyPI</a>
|
|
84
|
+
</div>
|
|
85
|
+
</section>
|
|
86
|
+
|
|
87
|
+
<section id="pricing" class="pricing">
|
|
88
|
+
<h2>Simple pricing</h2>
|
|
89
|
+
<div class="pricing-grid">
|
|
90
|
+
<article class="plan">
|
|
91
|
+
<h3>Free</h3>
|
|
92
|
+
<p class="price">$0<span>/month</span></p>
|
|
93
|
+
<ul>
|
|
94
|
+
<li>1 inbox on shared domain</li>
|
|
95
|
+
<li>0 custom domains</li>
|
|
96
|
+
<li>1,000 outbound emails/month</li>
|
|
97
|
+
<li>API access included</li>
|
|
98
|
+
</ul>
|
|
99
|
+
<a class="button secondary" href="https://app.emailagent.dev/" data-cta="start-free-pricing">Start free</a>
|
|
100
|
+
</article>
|
|
101
|
+
<article class="plan featured">
|
|
102
|
+
<p class="badge">Most popular</p>
|
|
103
|
+
<h3>Paid</h3>
|
|
104
|
+
<p class="price">$10<span>/month</span></p>
|
|
105
|
+
<ul>
|
|
106
|
+
<li>10 inboxes</li>
|
|
107
|
+
<li>1 custom domain</li>
|
|
108
|
+
<li>10,000 outbound emails/month</li>
|
|
109
|
+
<li>Upgrade in-app with Dodo Payments</li>
|
|
110
|
+
</ul>
|
|
111
|
+
<a class="button primary" href="https://app.emailagent.dev/app/billing" data-cta="upgrade-pricing">Upgrade</a>
|
|
112
|
+
</article>
|
|
113
|
+
</div>
|
|
114
|
+
</section>
|
|
115
|
+
</main>
|
|
116
|
+
|
|
117
|
+
<footer class="footer">
|
|
118
|
+
<div>
|
|
119
|
+
<strong>EmailAgent</strong>
|
|
120
|
+
<p>Email infrastructure for AI agents.</p>
|
|
121
|
+
</div>
|
|
122
|
+
<div class="footer-links">
|
|
123
|
+
<a href="/privacy.html" data-cta="privacy">Privacy</a>
|
|
124
|
+
<a href="/terms.html" data-cta="terms">Terms</a>
|
|
125
|
+
<a href="mailto:support@emailagent.dev" data-cta="support">support@emailagent.dev</a>
|
|
126
|
+
</div>
|
|
127
|
+
</footer>
|
|
128
|
+
</body>
|
|
129
|
+
</html>
|
package/landing/main.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
const analytics = window.__landingAnalytics || {};
|
|
3
|
+
|
|
4
|
+
function loadScript(src, attrs) {
|
|
5
|
+
const script = document.createElement('script');
|
|
6
|
+
script.src = src;
|
|
7
|
+
script.async = true;
|
|
8
|
+
Object.entries(attrs || {}).forEach(([k, v]) => script.setAttribute(k, v));
|
|
9
|
+
document.head.appendChild(script);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (analytics.plausibleDomain) {
|
|
13
|
+
loadScript('https://plausible.io/js/script.js', {
|
|
14
|
+
defer: 'defer',
|
|
15
|
+
'data-domain': analytics.plausibleDomain
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (analytics.ga4MeasurementId) {
|
|
20
|
+
const id = analytics.ga4MeasurementId;
|
|
21
|
+
loadScript(`https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(id)}`);
|
|
22
|
+
window.dataLayer = window.dataLayer || [];
|
|
23
|
+
window.gtag = window.gtag || function gtag() {
|
|
24
|
+
window.dataLayer.push(arguments);
|
|
25
|
+
};
|
|
26
|
+
window.gtag('js', new Date());
|
|
27
|
+
window.gtag('config', id);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function trackCta(label) {
|
|
31
|
+
if (window.plausible) {
|
|
32
|
+
window.plausible('cta_click', { props: { label: label } });
|
|
33
|
+
}
|
|
34
|
+
if (window.gtag) {
|
|
35
|
+
window.gtag('event', 'cta_click', { label: label });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
document.querySelectorAll('[data-cta]').forEach((node) => {
|
|
40
|
+
node.addEventListener('click', function onClick() {
|
|
41
|
+
const label = node.getAttribute('data-cta') || 'unknown';
|
|
42
|
+
trackCta(label);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
})();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Privacy Policy | EmailAgent</title>
|
|
7
|
+
<meta name="description" content="Privacy policy for EmailAgent." />
|
|
8
|
+
<link rel="canonical" href="https://emailagent.dev/privacy.html" />
|
|
9
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
10
|
+
<link rel="stylesheet" href="./styles.css" />
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<main style="max-width:900px;padding-top:28px;">
|
|
14
|
+
<a href="/" class="button ghost" style="display:inline-flex;margin-bottom:14px;">Back to home</a>
|
|
15
|
+
<section class="hero" style="padding:30px;">
|
|
16
|
+
<h1 style="font-size:40px;">Privacy Policy</h1>
|
|
17
|
+
<p class="lead">Last updated: February 9, 2026</p>
|
|
18
|
+
<h2 style="font-size:24px;">What we collect</h2>
|
|
19
|
+
<p class="lead">We collect account information (name, email), billing metadata, and email infrastructure metadata required to operate the service. We do not position EmailAgent as a personal email client.</p>
|
|
20
|
+
<h2 style="font-size:24px;">How we use data</h2>
|
|
21
|
+
<p class="lead">Data is used to provide inbox provisioning, domain onboarding, API key management, usage accounting, and abuse prevention.</p>
|
|
22
|
+
<h2 style="font-size:24px;">Subprocessors</h2>
|
|
23
|
+
<p class="lead">Email delivery and domain operations are handled through Mailgun. Billing is handled through Dodo Payments.</p>
|
|
24
|
+
<h2 style="font-size:24px;">Contact</h2>
|
|
25
|
+
<p class="lead">Questions: <a href="mailto:support@emailagent.dev">support@emailagent.dev</a></p>
|
|
26
|
+
</section>
|
|
27
|
+
</main>
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|