agent-mailbox-cli 0.1.0 → 0.1.1
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 +132 -0
- package/dist/api/auth.d.ts +4 -1
- package/dist/api/auth.d.ts.map +1 -1
- package/dist/api/auth.js +33 -2
- package/dist/api/auth.js.map +1 -1
- package/dist/api/routes/auth.d.ts +3 -0
- package/dist/api/routes/auth.d.ts.map +1 -0
- package/dist/api/routes/auth.js +115 -0
- package/dist/api/routes/auth.js.map +1 -0
- package/dist/api/routes/orgs.d.ts.map +1 -1
- package/dist/api/routes/orgs.js +28 -5
- package/dist/api/routes/orgs.js.map +1 -1
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +2 -0
- package/dist/api/server.js.map +1 -1
- package/dist/cli/config.d.ts +9 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +28 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/index.js +141 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -1
- package/dist/db/schema.sql +35 -0
- package/dist/email/send.d.ts +2 -0
- package/dist/email/send.d.ts.map +1 -0
- package/dist/email/send.js +21 -0
- package/dist/email/send.js.map +1 -0
- package/dist/smtp/receiver.d.ts.map +1 -1
- package/dist/smtp/receiver.js +66 -29
- package/dist/smtp/receiver.js.map +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# AgentMailbox
|
|
2
|
+
|
|
3
|
+
Email addresses for AI agents. Zero cost per account.
|
|
4
|
+
|
|
5
|
+
AgentMailbox gives any AI agent its own email address at `@agentmailbox.io`. Agents can receive verification codes, order confirmations, and notifications — no Gmail or Google Workspace fees per account.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g agent-mailbox-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Set your API key
|
|
17
|
+
export AGENT_EMAIL_API_KEY=ae_xxxxx
|
|
18
|
+
|
|
19
|
+
# Create an email account
|
|
20
|
+
agentmailbox account create grocery-bot
|
|
21
|
+
# → grocery-bot@agentmailbox.io created
|
|
22
|
+
|
|
23
|
+
# List inbox
|
|
24
|
+
agentmailbox msg list grocery-bot@agentmailbox.io
|
|
25
|
+
|
|
26
|
+
# Wait for a new email (blocks until one arrives)
|
|
27
|
+
agentmailbox msg wait grocery-bot@agentmailbox.io --timeout 60
|
|
28
|
+
|
|
29
|
+
# Read a message
|
|
30
|
+
agentmailbox msg read grocery-bot@agentmailbox.io <message-id>
|
|
31
|
+
|
|
32
|
+
# Reply
|
|
33
|
+
agentmailbox msg reply grocery-bot@agentmailbox.io <message-id> "Got it, thanks"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
Base URL: `https://agent-email-api-production.up.railway.app`
|
|
39
|
+
|
|
40
|
+
Auth: `Authorization: Bearer ae_xxxxx`
|
|
41
|
+
|
|
42
|
+
### Organizations
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
POST /v1/orgs Create org, get API key
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Accounts
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
POST /v1/accounts Create email account
|
|
52
|
+
GET /v1/accounts List accounts
|
|
53
|
+
DELETE /v1/accounts/:address Delete account
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Messages
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
GET /v1/accounts/:address/messages List inbox
|
|
60
|
+
GET /v1/accounts/:address/messages/:id Read message
|
|
61
|
+
GET /v1/accounts/:address/messages/wait?timeout=30 Wait for new email
|
|
62
|
+
POST /v1/accounts/:address/messages/:id/reply Reply to message
|
|
63
|
+
POST /v1/accounts/:address/send Send new email
|
|
64
|
+
DELETE /v1/accounts/:address/messages/:id Delete message
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Example: Agent Signup Flow
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
const API = 'https://agent-email-api-production.up.railway.app';
|
|
71
|
+
const KEY = 'ae_xxxxx';
|
|
72
|
+
|
|
73
|
+
// 1. Create an email for the agent
|
|
74
|
+
const { account } = await fetch(`${API}/v1/accounts`, {
|
|
75
|
+
method: 'POST',
|
|
76
|
+
headers: { 'Authorization': `Bearer ${KEY}`, 'Content-Type': 'application/json' },
|
|
77
|
+
body: JSON.stringify({ local_part: 'bot-123' })
|
|
78
|
+
}).then(r => r.json());
|
|
79
|
+
// → bot-123@agentmailbox.io
|
|
80
|
+
|
|
81
|
+
// 2. Sign up for a service using that email
|
|
82
|
+
// ... (agent signs up on grocery site with bot-123@agentmailbox.io)
|
|
83
|
+
|
|
84
|
+
// 3. Wait for verification email
|
|
85
|
+
const { message } = await fetch(
|
|
86
|
+
`${API}/v1/accounts/bot-123@agentmailbox.io/messages/wait?timeout=60`,
|
|
87
|
+
{ headers: { 'Authorization': `Bearer ${KEY}` } }
|
|
88
|
+
).then(r => r.json());
|
|
89
|
+
|
|
90
|
+
// 4. Extract verification code
|
|
91
|
+
const code = message.text.match(/\d{6}/)?.[0];
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Architecture
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Internet ──SMTP:25──▶ Fly.io (SMTP receiver) ──▶ PostgreSQL (Railway)
|
|
98
|
+
▲
|
|
99
|
+
Agents ──HTTPS──▶ Railway (REST API) ─────────────────┘
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- **API**: Fastify on Railway
|
|
103
|
+
- **SMTP**: Node.js smtp-server on Fly.io, port 25
|
|
104
|
+
- **Database**: PostgreSQL on Railway
|
|
105
|
+
- **Domain**: agentmailbox.io (Vercel DNS, MX + SPF + DMARC configured)
|
|
106
|
+
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Start Postgres
|
|
111
|
+
docker compose up -d
|
|
112
|
+
|
|
113
|
+
# Init database
|
|
114
|
+
npm run db:init
|
|
115
|
+
|
|
116
|
+
# Run everything locally
|
|
117
|
+
npm run dev
|
|
118
|
+
|
|
119
|
+
# Or run API and SMTP separately
|
|
120
|
+
npm run dev:api
|
|
121
|
+
npm run dev:smtp
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Deploy
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# API → Railway
|
|
128
|
+
railway up -s agent-email-api
|
|
129
|
+
|
|
130
|
+
# SMTP → Fly.io
|
|
131
|
+
fly deploy --app agent-email-smtp
|
|
132
|
+
```
|
package/dist/api/auth.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { FastifyRequest, FastifyReply } from 'fastify';
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function hashToken(key: string): string;
|
|
3
3
|
export declare function generateApiKey(): string;
|
|
4
|
+
export declare function generateMagicToken(): string;
|
|
5
|
+
export declare function generateSessionToken(): string;
|
|
4
6
|
export declare function authenticate(request: FastifyRequest, reply: FastifyReply): Promise<undefined>;
|
|
7
|
+
export declare function authenticateAdmin(request: FastifyRequest, reply: FastifyReply): Promise<undefined>;
|
|
5
8
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/api/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvD,wBAAgB,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAGD,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,YAAY,sBAyBpB;AAGD,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,YAAY,sBAiCpB"}
|
package/dist/api/auth.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import crypto from 'crypto';
|
|
2
2
|
import { pool } from '../db/index.js';
|
|
3
|
-
export function
|
|
3
|
+
export function hashToken(key) {
|
|
4
4
|
return crypto.createHash('sha256').update(key).digest('hex');
|
|
5
5
|
}
|
|
6
6
|
export function generateApiKey() {
|
|
7
7
|
return 'ae_' + crypto.randomBytes(24).toString('hex');
|
|
8
8
|
}
|
|
9
|
+
export function generateMagicToken() {
|
|
10
|
+
return 'ml_' + crypto.randomBytes(16).toString('hex');
|
|
11
|
+
}
|
|
12
|
+
export function generateSessionToken() {
|
|
13
|
+
return 'as_' + crypto.randomBytes(24).toString('hex');
|
|
14
|
+
}
|
|
15
|
+
// Org-level API key auth (existing)
|
|
9
16
|
export async function authenticate(request, reply) {
|
|
10
17
|
const header = request.headers['authorization'] || request.headers['x-api-key'];
|
|
11
18
|
if (!header) {
|
|
@@ -15,11 +22,35 @@ export async function authenticate(request, reply) {
|
|
|
15
22
|
if (!key) {
|
|
16
23
|
return reply.code(401).send({ error: 'Invalid API key' });
|
|
17
24
|
}
|
|
18
|
-
const hash =
|
|
25
|
+
const hash = hashToken(key);
|
|
19
26
|
const result = await pool.query('SELECT id, name FROM orgs WHERE api_key_hash = $1', [hash]);
|
|
20
27
|
if (result.rows.length === 0) {
|
|
21
28
|
return reply.code(401).send({ error: 'Invalid API key' });
|
|
22
29
|
}
|
|
23
30
|
request.org = result.rows[0];
|
|
24
31
|
}
|
|
32
|
+
// Admin session auth
|
|
33
|
+
export async function authenticateAdmin(request, reply) {
|
|
34
|
+
const header = request.headers['authorization'];
|
|
35
|
+
if (!header) {
|
|
36
|
+
return reply.code(401).send({ error: 'Missing session token. Run: agentmailbox login' });
|
|
37
|
+
}
|
|
38
|
+
const token = typeof header === 'string' ? header.replace(/^Bearer\s+/i, '') : '';
|
|
39
|
+
if (!token || !token.startsWith('as_')) {
|
|
40
|
+
return reply.code(401).send({ error: 'Invalid session token' });
|
|
41
|
+
}
|
|
42
|
+
const hash = hashToken(token);
|
|
43
|
+
const result = await pool.query(`SELECT s.id, s.admin_user_id, s.expires_at, u.email
|
|
44
|
+
FROM admin_sessions s
|
|
45
|
+
JOIN admin_users u ON u.id = s.admin_user_id
|
|
46
|
+
WHERE s.token_hash = $1`, [hash]);
|
|
47
|
+
if (result.rows.length === 0 ||
|
|
48
|
+
new Date(result.rows[0].expires_at) < new Date()) {
|
|
49
|
+
return reply.code(401).send({ error: 'Session expired. Run: agentmailbox login' });
|
|
50
|
+
}
|
|
51
|
+
request.admin = {
|
|
52
|
+
id: result.rows[0].admin_user_id,
|
|
53
|
+
email: result.rows[0].email,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
25
56
|
//# sourceMappingURL=auth.js.map
|
package/dist/api/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEtC,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/api/routes/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAkC1C,wBAAsB,UAAU,CAAC,OAAO,EAAE,eAAe,iBA8JxD"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { pool } from '../../db/index.js';
|
|
2
|
+
import { hashToken, generateMagicToken, generateSessionToken, authenticateAdmin, } from '../auth.js';
|
|
3
|
+
import { sendMagicLinkEmail } from '../../email/send.js';
|
|
4
|
+
import { config } from '../../config.js';
|
|
5
|
+
async function sendMagicLink(adminUserId, email) {
|
|
6
|
+
const token = generateMagicToken();
|
|
7
|
+
const hash = hashToken(token);
|
|
8
|
+
const expiresAt = new Date(Date.now() + config.auth.magicLinkTtlMinutes * 60 * 1000);
|
|
9
|
+
await pool.query(`INSERT INTO magic_link_tokens (admin_user_id, token_hash, expires_at) VALUES ($1, $2, $3)`, [adminUserId, hash, expiresAt]);
|
|
10
|
+
try {
|
|
11
|
+
await sendMagicLinkEmail(email, token);
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
console.error('Failed to send magic link email:', err);
|
|
15
|
+
// Return the token directly if email sending fails (dev mode)
|
|
16
|
+
return { emailSent: false, token };
|
|
17
|
+
}
|
|
18
|
+
return { emailSent: true };
|
|
19
|
+
}
|
|
20
|
+
export async function authRoutes(fastify) {
|
|
21
|
+
// Signup
|
|
22
|
+
fastify.post('/v1/auth/signup', async (request, reply) => {
|
|
23
|
+
const { email } = request.body || {};
|
|
24
|
+
if (!email || !email.includes('@')) {
|
|
25
|
+
return reply.code(400).send({ error: 'Valid email is required' });
|
|
26
|
+
}
|
|
27
|
+
const normalized = email.toLowerCase().trim();
|
|
28
|
+
// Check if already exists
|
|
29
|
+
const existing = await pool.query('SELECT id FROM admin_users WHERE email = $1', [normalized]);
|
|
30
|
+
if (existing.rows.length > 0) {
|
|
31
|
+
return reply
|
|
32
|
+
.code(409)
|
|
33
|
+
.send({ error: 'Account already exists. Use: agentmailbox login' });
|
|
34
|
+
}
|
|
35
|
+
const result = await pool.query('INSERT INTO admin_users (email) VALUES ($1) RETURNING id', [normalized]);
|
|
36
|
+
const { emailSent, token } = await sendMagicLink(result.rows[0].id, normalized);
|
|
37
|
+
return reply.code(201).send({
|
|
38
|
+
message: emailSent
|
|
39
|
+
? 'Check your email for a verification code.'
|
|
40
|
+
: 'Email sending failed. Use this code to verify:',
|
|
41
|
+
...(token ? { code: token } : {}),
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
// Login
|
|
45
|
+
fastify.post('/v1/auth/login', async (request, reply) => {
|
|
46
|
+
const { email } = request.body || {};
|
|
47
|
+
if (!email || !email.includes('@')) {
|
|
48
|
+
return reply.code(400).send({ error: 'Valid email is required' });
|
|
49
|
+
}
|
|
50
|
+
const normalized = email.toLowerCase().trim();
|
|
51
|
+
const result = await pool.query('SELECT id FROM admin_users WHERE email = $1', [normalized]);
|
|
52
|
+
if (result.rows.length === 0) {
|
|
53
|
+
return reply
|
|
54
|
+
.code(404)
|
|
55
|
+
.send({ error: 'No account with this email. Run: agentmailbox signup' });
|
|
56
|
+
}
|
|
57
|
+
const { emailSent, token } = await sendMagicLink(result.rows[0].id, normalized);
|
|
58
|
+
return {
|
|
59
|
+
message: emailSent
|
|
60
|
+
? 'Check your email for a verification code.'
|
|
61
|
+
: 'Email sending failed. Use this code to verify:',
|
|
62
|
+
...(token ? { code: token } : {}),
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
// Verify magic link token
|
|
66
|
+
fastify.post('/v1/auth/verify', async (request, reply) => {
|
|
67
|
+
const { token } = request.body || {};
|
|
68
|
+
if (!token) {
|
|
69
|
+
return reply.code(400).send({ error: 'Token is required' });
|
|
70
|
+
}
|
|
71
|
+
const hash = hashToken(token);
|
|
72
|
+
// Atomic: mark used only if valid and unused
|
|
73
|
+
const result = await pool.query(`UPDATE magic_link_tokens
|
|
74
|
+
SET used_at = NOW()
|
|
75
|
+
WHERE token_hash = $1 AND used_at IS NULL AND expires_at > NOW()
|
|
76
|
+
RETURNING admin_user_id`, [hash]);
|
|
77
|
+
if (result.rows.length === 0) {
|
|
78
|
+
return reply
|
|
79
|
+
.code(401)
|
|
80
|
+
.send({ error: 'Invalid or expired code' });
|
|
81
|
+
}
|
|
82
|
+
const adminUserId = result.rows[0].admin_user_id;
|
|
83
|
+
// Create session
|
|
84
|
+
const sessionToken = generateSessionToken();
|
|
85
|
+
const sessionHash = hashToken(sessionToken);
|
|
86
|
+
const expiresAt = new Date(Date.now() + config.auth.sessionTtlDays * 24 * 60 * 60 * 1000);
|
|
87
|
+
await pool.query(`INSERT INTO admin_sessions (admin_user_id, token_hash, expires_at) VALUES ($1, $2, $3)`, [adminUserId, sessionHash, expiresAt]);
|
|
88
|
+
const user = await pool.query('SELECT email FROM admin_users WHERE id = $1', [adminUserId]);
|
|
89
|
+
return {
|
|
90
|
+
session_token: sessionToken,
|
|
91
|
+
admin: { id: adminUserId, email: user.rows[0].email },
|
|
92
|
+
expires_at: expiresAt,
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
// Logout
|
|
96
|
+
fastify.post('/v1/auth/logout', async (request, reply) => {
|
|
97
|
+
const header = request.headers['authorization'];
|
|
98
|
+
if (!header) {
|
|
99
|
+
return reply.code(401).send({ error: 'Missing session token' });
|
|
100
|
+
}
|
|
101
|
+
const token = typeof header === 'string' ? header.replace(/^Bearer\s+/i, '') : '';
|
|
102
|
+
if (!token) {
|
|
103
|
+
return reply.code(401).send({ error: 'Invalid session token' });
|
|
104
|
+
}
|
|
105
|
+
const hash = hashToken(token);
|
|
106
|
+
await pool.query('DELETE FROM admin_sessions WHERE token_hash = $1', [hash]);
|
|
107
|
+
return { message: 'Logged out' };
|
|
108
|
+
});
|
|
109
|
+
// Who am I
|
|
110
|
+
fastify.get('/v1/auth/me', { onRequest: authenticateAdmin }, async (request) => {
|
|
111
|
+
const admin = request.admin;
|
|
112
|
+
return { admin };
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/api/routes/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orgs.d.ts","sourceRoot":"","sources":["../../../src/api/routes/orgs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI1C,wBAAsB,SAAS,CAAC,OAAO,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"orgs.d.ts","sourceRoot":"","sources":["../../../src/api/routes/orgs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI1C,wBAAsB,SAAS,CAAC,OAAO,EAAE,eAAe,iBAqEvD"}
|
package/dist/api/routes/orgs.js
CHANGED
|
@@ -1,20 +1,43 @@
|
|
|
1
1
|
import { pool } from '../../db/index.js';
|
|
2
|
-
import { generateApiKey,
|
|
2
|
+
import { generateApiKey, hashToken, authenticateAdmin } from '../auth.js';
|
|
3
3
|
export async function orgRoutes(fastify) {
|
|
4
|
-
// Create org —
|
|
5
|
-
fastify.post('/v1/orgs', async (request, reply) => {
|
|
4
|
+
// Create org — requires admin auth
|
|
5
|
+
fastify.post('/v1/orgs', { onRequest: authenticateAdmin }, async (request, reply) => {
|
|
6
|
+
const admin = request.admin;
|
|
6
7
|
const { name } = request.body || {};
|
|
7
8
|
if (!name) {
|
|
8
9
|
return reply.code(400).send({ error: 'name is required' });
|
|
9
10
|
}
|
|
10
11
|
const apiKey = generateApiKey();
|
|
11
|
-
const hash =
|
|
12
|
-
const result = await pool.query('INSERT INTO orgs (name, api_key_hash) VALUES ($1, $2) RETURNING id, name, created_at', [name, hash]);
|
|
12
|
+
const hash = hashToken(apiKey);
|
|
13
|
+
const result = await pool.query('INSERT INTO orgs (name, api_key_hash, admin_user_id) VALUES ($1, $2, $3) RETURNING id, name, created_at', [name, hash, admin.id]);
|
|
13
14
|
return reply.code(201).send({
|
|
14
15
|
org: result.rows[0],
|
|
15
16
|
api_key: apiKey,
|
|
16
17
|
note: 'Save this API key — it cannot be retrieved again.',
|
|
17
18
|
});
|
|
18
19
|
});
|
|
20
|
+
// List orgs for admin
|
|
21
|
+
fastify.get('/v1/orgs', { onRequest: authenticateAdmin }, async (request) => {
|
|
22
|
+
const admin = request.admin;
|
|
23
|
+
const result = await pool.query('SELECT id, name, created_at FROM orgs WHERE admin_user_id = $1 ORDER BY created_at DESC', [admin.id]);
|
|
24
|
+
return { orgs: result.rows };
|
|
25
|
+
});
|
|
26
|
+
// Rotate API key
|
|
27
|
+
fastify.post('/v1/orgs/:orgId/rotate-key', { onRequest: authenticateAdmin }, async (request, reply) => {
|
|
28
|
+
const admin = request.admin;
|
|
29
|
+
const { orgId } = request.params;
|
|
30
|
+
const apiKey = generateApiKey();
|
|
31
|
+
const hash = hashToken(apiKey);
|
|
32
|
+
const result = await pool.query('UPDATE orgs SET api_key_hash = $1 WHERE id = $2 AND admin_user_id = $3 RETURNING id, name', [hash, orgId, admin.id]);
|
|
33
|
+
if (result.rows.length === 0) {
|
|
34
|
+
return reply.code(404).send({ error: 'Org not found' });
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
org: result.rows[0],
|
|
38
|
+
api_key: apiKey,
|
|
39
|
+
note: 'Save this API key — it cannot be retrieved again.',
|
|
40
|
+
};
|
|
41
|
+
});
|
|
19
42
|
}
|
|
20
43
|
//# sourceMappingURL=orgs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orgs.js","sourceRoot":"","sources":["../../../src/api/routes/orgs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"orgs.js","sourceRoot":"","sources":["../../../src/api/routes/orgs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAwB;IACtD,mCAAmC;IACnC,OAAO,CAAC,IAAI,CAET,UAAU,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACxE,MAAM,KAAK,GAAI,OAAe,CAAC,KAAK,CAAC;QACrC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B,yGAAyG,EACzG,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CACvB,CAAC;QAEF,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YAC1B,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YACnB,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,mDAAmD;SAC1D,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,sBAAsB;IACtB,OAAO,CAAC,GAAG,CACT,UAAU,EACV,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAChC,KAAK,EAAE,OAAO,EAAE,EAAE;QAChB,MAAM,KAAK,GAAI,OAAe,CAAC,KAAK,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B,yFAAyF,EACzF,CAAC,KAAK,CAAC,EAAE,CAAC,CACX,CAAC;QACF,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC,CACF,CAAC;IAEF,iBAAiB;IACjB,OAAO,CAAC,IAAI,CAGV,4BAA4B,EAC5B,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAChC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvB,MAAM,KAAK,GAAI,OAAe,CAAC,KAAK,CAAC;QACrC,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QAEjC,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QAE/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B,2FAA2F,EAC3F,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CACxB,CAAC;QAEF,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO;YACL,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YACnB,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,mDAAmD;SAC1D,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/dist/api/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAQA,wBAAsB,eAAe;;;GA4BpC"}
|
package/dist/api/server.js
CHANGED
|
@@ -4,6 +4,7 @@ import { config } from '../config.js';
|
|
|
4
4
|
import { orgRoutes } from './routes/orgs.js';
|
|
5
5
|
import { accountRoutes } from './routes/accounts.js';
|
|
6
6
|
import { messageRoutes } from './routes/messages.js';
|
|
7
|
+
import { authRoutes } from './routes/auth.js';
|
|
7
8
|
export async function createApiServer() {
|
|
8
9
|
const fastify = Fastify({
|
|
9
10
|
logger: true,
|
|
@@ -12,6 +13,7 @@ export async function createApiServer() {
|
|
|
12
13
|
// Health check
|
|
13
14
|
fastify.get('/health', async () => ({ status: 'ok' }));
|
|
14
15
|
// Routes
|
|
16
|
+
await fastify.register(authRoutes);
|
|
15
17
|
await fastify.register(orgRoutes);
|
|
16
18
|
await fastify.register(accountRoutes);
|
|
17
19
|
await fastify.register(messageRoutes);
|
package/dist/api/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,eAAe,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,eAAe,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC;QACtB,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE7B,eAAe;IACf,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEvD,SAAS;IACT,MAAM,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACnC,MAAM,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IACtC,MAAM,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAEtC,OAAO;QACL,KAAK,CAAC,KAAK;YACT,MAAM,OAAO,CAAC,MAAM,CAAC;gBACnB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI;gBACrB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI;aACtB,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,2BAA2B,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,KAAK,CAAC,IAAI;YACR,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface CliConfig {
|
|
2
|
+
api_url: string;
|
|
3
|
+
session_token?: string;
|
|
4
|
+
email?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function loadConfig(): CliConfig;
|
|
7
|
+
export declare function saveConfig(config: CliConfig): void;
|
|
8
|
+
export declare function clearSession(): void;
|
|
9
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,UAAU,IAAI,SAAS,CAWtC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAGlD;AAED,wBAAgB,YAAY,IAAI,IAAI,CAKnC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
const CONFIG_DIR = path.join(os.homedir(), '.agentmailbox');
|
|
5
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
6
|
+
export function loadConfig() {
|
|
7
|
+
try {
|
|
8
|
+
const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
9
|
+
return JSON.parse(raw);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return {
|
|
13
|
+
api_url: process.env.AGENT_EMAIL_API_URL ||
|
|
14
|
+
'https://agent-email-api-production.up.railway.app',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function saveConfig(config) {
|
|
19
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
20
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n');
|
|
21
|
+
}
|
|
22
|
+
export function clearSession() {
|
|
23
|
+
const config = loadConfig();
|
|
24
|
+
delete config.session_token;
|
|
25
|
+
delete config.email;
|
|
26
|
+
saveConfig(config);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAQzD,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,OAAO,EACL,OAAO,CAAC,GAAG,CAAC,mBAAmB;gBAC/B,mDAAmD;SACtD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAiB;IAC1C,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,OAAO,MAAM,CAAC,aAAa,CAAC;IAC5B,OAAO,MAAM,CAAC,KAAK,CAAC;IACpB,UAAU,CAAC,MAAM,CAAC,CAAC;AACrB,CAAC"}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
+
import { createInterface } from 'readline';
|
|
4
|
+
import { loadConfig, saveConfig, clearSession } from './config.js';
|
|
3
5
|
const program = new Command();
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
function getApiUrl() {
|
|
7
|
+
return (process.env.AGENT_EMAIL_API_URL ||
|
|
8
|
+
loadConfig().api_url ||
|
|
9
|
+
'https://agent-email-api-production.up.railway.app');
|
|
10
|
+
}
|
|
11
|
+
function getAuthHeader() {
|
|
12
|
+
// API key takes precedence (for org-level ops like accounts/messages)
|
|
13
|
+
const apiKey = process.env.AGENT_EMAIL_API_KEY;
|
|
14
|
+
if (apiKey)
|
|
15
|
+
return `Bearer ${apiKey}`;
|
|
16
|
+
// Fall back to session token (for admin ops like org create)
|
|
17
|
+
const cfg = loadConfig();
|
|
18
|
+
if (cfg.session_token)
|
|
19
|
+
return `Bearer ${cfg.session_token}`;
|
|
20
|
+
return '';
|
|
21
|
+
}
|
|
22
|
+
async function api(method, path, body, authOverride) {
|
|
7
23
|
const headers = {
|
|
8
24
|
'Content-Type': 'application/json',
|
|
9
25
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const res = await fetch(`${
|
|
26
|
+
const auth = authOverride || getAuthHeader();
|
|
27
|
+
if (auth)
|
|
28
|
+
headers['Authorization'] = auth;
|
|
29
|
+
const res = await fetch(`${getApiUrl()}${path}`, {
|
|
14
30
|
method,
|
|
15
31
|
headers,
|
|
16
32
|
body: body ? JSON.stringify(body) : undefined,
|
|
@@ -24,17 +40,100 @@ async function api(method, path, body) {
|
|
|
24
40
|
}
|
|
25
41
|
return data;
|
|
26
42
|
}
|
|
43
|
+
function prompt(question) {
|
|
44
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
rl.question(question, (answer) => {
|
|
47
|
+
rl.close();
|
|
48
|
+
resolve(answer.trim());
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
27
52
|
program
|
|
28
53
|
.name('agentmailbox')
|
|
29
|
-
.description('
|
|
30
|
-
.version('0.
|
|
54
|
+
.description('Email addresses for AI agents')
|
|
55
|
+
.version('0.2.0');
|
|
56
|
+
// Auth commands
|
|
57
|
+
program
|
|
58
|
+
.command('signup')
|
|
59
|
+
.argument('<email>', 'Your email address')
|
|
60
|
+
.description('Create an admin account')
|
|
61
|
+
.action(async (email) => {
|
|
62
|
+
const data = await api('POST', '/v1/auth/signup', { email }, '');
|
|
63
|
+
console.log(data.message);
|
|
64
|
+
if (data.code) {
|
|
65
|
+
console.log(`Code: ${data.code}`);
|
|
66
|
+
}
|
|
67
|
+
const code = await prompt('Paste the code from your email: ');
|
|
68
|
+
const verify = await api('POST', '/v1/auth/verify', { token: code }, '');
|
|
69
|
+
const cfg = loadConfig();
|
|
70
|
+
cfg.session_token = verify.session_token;
|
|
71
|
+
cfg.email = verify.admin.email;
|
|
72
|
+
saveConfig(cfg);
|
|
73
|
+
console.log(`Logged in as ${verify.admin.email}`);
|
|
74
|
+
});
|
|
75
|
+
program
|
|
76
|
+
.command('login')
|
|
77
|
+
.argument('<email>', 'Your email address')
|
|
78
|
+
.description('Log in with magic link')
|
|
79
|
+
.action(async (email) => {
|
|
80
|
+
const data = await api('POST', '/v1/auth/login', { email }, '');
|
|
81
|
+
console.log(data.message);
|
|
82
|
+
if (data.code) {
|
|
83
|
+
console.log(`Code: ${data.code}`);
|
|
84
|
+
}
|
|
85
|
+
const code = await prompt('Paste the code from your email: ');
|
|
86
|
+
const verify = await api('POST', '/v1/auth/verify', { token: code }, '');
|
|
87
|
+
const cfg = loadConfig();
|
|
88
|
+
cfg.session_token = verify.session_token;
|
|
89
|
+
cfg.email = verify.admin.email;
|
|
90
|
+
saveConfig(cfg);
|
|
91
|
+
console.log(`Logged in as ${verify.admin.email}`);
|
|
92
|
+
});
|
|
93
|
+
program
|
|
94
|
+
.command('logout')
|
|
95
|
+
.description('Log out')
|
|
96
|
+
.action(async () => {
|
|
97
|
+
const cfg = loadConfig();
|
|
98
|
+
if (cfg.session_token) {
|
|
99
|
+
try {
|
|
100
|
+
await api('POST', '/v1/auth/logout', undefined, `Bearer ${cfg.session_token}`);
|
|
101
|
+
}
|
|
102
|
+
catch { }
|
|
103
|
+
}
|
|
104
|
+
clearSession();
|
|
105
|
+
console.log('Logged out.');
|
|
106
|
+
});
|
|
107
|
+
program
|
|
108
|
+
.command('whoami')
|
|
109
|
+
.description('Show current user')
|
|
110
|
+
.action(async () => {
|
|
111
|
+
const cfg = loadConfig();
|
|
112
|
+
if (!cfg.session_token) {
|
|
113
|
+
console.log('Not logged in. Run: agentmailbox login <email>');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const data = await api('GET', '/v1/auth/me', undefined, `Bearer ${cfg.session_token}`);
|
|
118
|
+
console.log(`Logged in as ${data.admin.email}`);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
console.log('Session expired. Run: agentmailbox login <email>');
|
|
122
|
+
}
|
|
123
|
+
});
|
|
31
124
|
// Org commands
|
|
32
125
|
const org = program.command('org');
|
|
33
126
|
org
|
|
34
127
|
.command('create')
|
|
35
128
|
.argument('<name>', 'Organization name')
|
|
129
|
+
.description('Create an org and get an API key')
|
|
36
130
|
.action(async (name) => {
|
|
37
|
-
const
|
|
131
|
+
const cfg = loadConfig();
|
|
132
|
+
if (!cfg.session_token) {
|
|
133
|
+
console.error('Not logged in. Run: agentmailbox login <email>');
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
const data = await api('POST', '/v1/orgs', { name }, `Bearer ${cfg.session_token}`);
|
|
38
137
|
console.log('Organization created:');
|
|
39
138
|
console.log(` ID: ${data.org.id}`);
|
|
40
139
|
console.log(` Name: ${data.org.name}`);
|
|
@@ -43,6 +142,38 @@ org
|
|
|
43
142
|
console.log('Save this API key — it cannot be retrieved again.');
|
|
44
143
|
console.log(`Export it: export AGENT_EMAIL_API_KEY=${data.api_key}`);
|
|
45
144
|
});
|
|
145
|
+
org
|
|
146
|
+
.command('list')
|
|
147
|
+
.description('List your orgs')
|
|
148
|
+
.action(async () => {
|
|
149
|
+
const cfg = loadConfig();
|
|
150
|
+
if (!cfg.session_token) {
|
|
151
|
+
console.error('Not logged in. Run: agentmailbox login <email>');
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
const data = await api('GET', '/v1/orgs', undefined, `Bearer ${cfg.session_token}`);
|
|
155
|
+
if (data.orgs.length === 0) {
|
|
156
|
+
console.log('No orgs. Create one: agentmailbox org create <name>');
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
for (const o of data.orgs) {
|
|
160
|
+
console.log(` ${o.id} ${o.name} created ${o.created_at}`);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
org
|
|
164
|
+
.command('rotate-key')
|
|
165
|
+
.argument('<org-id>', 'Org ID')
|
|
166
|
+
.description('Rotate API key for an org')
|
|
167
|
+
.action(async (orgId) => {
|
|
168
|
+
const cfg = loadConfig();
|
|
169
|
+
if (!cfg.session_token) {
|
|
170
|
+
console.error('Not logged in. Run: agentmailbox login <email>');
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
const data = await api('POST', `/v1/orgs/${orgId}/rotate-key`, undefined, `Bearer ${cfg.session_token}`);
|
|
174
|
+
console.log(`New API Key: ${data.api_key}`);
|
|
175
|
+
console.log('Save this API key — the old one is now invalid.');
|
|
176
|
+
});
|
|
46
177
|
// Account commands
|
|
47
178
|
const account = program.command('account');
|
|
48
179
|
account
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -7,11 +7,23 @@ export declare const config: {
|
|
|
7
7
|
port: number;
|
|
8
8
|
host: string;
|
|
9
9
|
domain: string;
|
|
10
|
+
relaySecret: string;
|
|
10
11
|
};
|
|
11
12
|
api: {
|
|
12
13
|
port: number;
|
|
13
14
|
host: string;
|
|
14
15
|
};
|
|
16
|
+
auth: {
|
|
17
|
+
magicLinkTtlMinutes: number;
|
|
18
|
+
sessionTtlDays: number;
|
|
19
|
+
fromAddress: string;
|
|
20
|
+
};
|
|
21
|
+
outboundSmtp: {
|
|
22
|
+
host: string;
|
|
23
|
+
port: number;
|
|
24
|
+
user: string;
|
|
25
|
+
pass: string;
|
|
26
|
+
};
|
|
15
27
|
dkim: {
|
|
16
28
|
selector: string;
|
|
17
29
|
privateKey: string;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAEvB,eAAO,MAAM,MAAM
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAEvB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BlB,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -7,11 +7,23 @@ export const config = {
|
|
|
7
7
|
port: parseInt(process.env.SMTP_PORT || '2525', 10),
|
|
8
8
|
host: process.env.SMTP_HOST || '0.0.0.0',
|
|
9
9
|
domain: process.env.SMTP_DOMAIN || 'agentmailbox.io',
|
|
10
|
+
relaySecret: process.env.SMTP_RELAY_SECRET || '',
|
|
10
11
|
},
|
|
11
12
|
api: {
|
|
12
13
|
port: parseInt(process.env.API_PORT || '3025', 10),
|
|
13
14
|
host: process.env.API_HOST || '0.0.0.0',
|
|
14
15
|
},
|
|
16
|
+
auth: {
|
|
17
|
+
magicLinkTtlMinutes: parseInt(process.env.AUTH_MAGIC_LINK_TTL || '15', 10),
|
|
18
|
+
sessionTtlDays: parseInt(process.env.AUTH_SESSION_TTL_DAYS || '30', 10),
|
|
19
|
+
fromAddress: process.env.AUTH_FROM_ADDRESS || 'auth@agentmailbox.io',
|
|
20
|
+
},
|
|
21
|
+
outboundSmtp: {
|
|
22
|
+
host: process.env.OUTBOUND_SMTP_HOST || 'mail.agentmailbox.io',
|
|
23
|
+
port: parseInt(process.env.OUTBOUND_SMTP_PORT || '25', 10),
|
|
24
|
+
user: process.env.OUTBOUND_SMTP_USER || '',
|
|
25
|
+
pass: process.env.OUTBOUND_SMTP_PASS || '',
|
|
26
|
+
},
|
|
15
27
|
dkim: {
|
|
16
28
|
selector: process.env.DKIM_SELECTOR || 'default',
|
|
17
29
|
privateKey: process.env.DKIM_PRIVATE_KEY || '',
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAEvB,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,QAAQ,EAAE;QACR,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,sCAAsC;KACxE;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,EAAE,EAAE,CAAC;QACnD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,SAAS;QACxC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,iBAAiB;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAEvB,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,QAAQ,EAAE;QACR,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,sCAAsC;KACxE;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,EAAE,EAAE,CAAC;QACnD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,SAAS;QACxC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,iBAAiB;QACpD,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE;KACjD;IACD,GAAG,EAAE;QACH,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,MAAM,EAAE,EAAE,CAAC;QAClD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS;KACxC;IACD,IAAI,EAAE;QACJ,mBAAmB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,EAAE,EAAE,CAAC;QAC1E,cAAc,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,IAAI,EAAE,EAAE,CAAC;QACvE,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,sBAAsB;KACrE;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,sBAAsB;QAC9D,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,EAAE,EAAE,CAAC;QAC1D,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE;QAC1C,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE;KAC3C;IACD,IAAI,EAAE;QACJ,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,SAAS;QAChD,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE;KAC/C;CACF,CAAC"}
|
package/dist/db/schema.sql
CHANGED
|
@@ -36,3 +36,38 @@ CREATE INDEX IF NOT EXISTS idx_messages_account_received ON messages(account_id,
|
|
|
36
36
|
CREATE INDEX IF NOT EXISTS idx_accounts_org ON accounts(org_id);
|
|
37
37
|
CREATE INDEX IF NOT EXISTS idx_accounts_address ON accounts(address);
|
|
38
38
|
CREATE INDEX IF NOT EXISTS idx_orgs_api_key_hash ON orgs(api_key_hash);
|
|
39
|
+
|
|
40
|
+
-- Admin auth
|
|
41
|
+
CREATE TABLE IF NOT EXISTS admin_users (
|
|
42
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
43
|
+
email TEXT NOT NULL UNIQUE,
|
|
44
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
CREATE TABLE IF NOT EXISTS magic_link_tokens (
|
|
48
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
49
|
+
admin_user_id UUID NOT NULL REFERENCES admin_users(id) ON DELETE CASCADE,
|
|
50
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
51
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
52
|
+
used_at TIMESTAMPTZ,
|
|
53
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
CREATE TABLE IF NOT EXISTS admin_sessions (
|
|
57
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
58
|
+
admin_user_id UUID NOT NULL REFERENCES admin_users(id) ON DELETE CASCADE,
|
|
59
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
60
|
+
expires_at TIMESTAMPTZ NOT NULL,
|
|
61
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
-- Add owner to orgs (nullable for backward compat)
|
|
65
|
+
DO $$ BEGIN
|
|
66
|
+
ALTER TABLE orgs ADD COLUMN admin_user_id UUID REFERENCES admin_users(id);
|
|
67
|
+
EXCEPTION WHEN duplicate_column THEN NULL;
|
|
68
|
+
END $$;
|
|
69
|
+
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_admin_users_email ON admin_users(email);
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_magic_link_tokens_hash ON magic_link_tokens(token_hash);
|
|
72
|
+
CREATE INDEX IF NOT EXISTS idx_admin_sessions_hash ON admin_sessions(token_hash);
|
|
73
|
+
CREATE INDEX IF NOT EXISTS idx_orgs_admin ON orgs(admin_user_id);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/email/send.ts"],"names":[],"mappings":"AAaA,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,iBAShE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import nodemailer from 'nodemailer';
|
|
2
|
+
import { config } from '../config.js';
|
|
3
|
+
const transporter = nodemailer.createTransport({
|
|
4
|
+
host: config.outboundSmtp.host,
|
|
5
|
+
port: config.outboundSmtp.port,
|
|
6
|
+
secure: false,
|
|
7
|
+
...(config.outboundSmtp.user
|
|
8
|
+
? { auth: { user: config.outboundSmtp.user, pass: config.outboundSmtp.pass } }
|
|
9
|
+
: {}),
|
|
10
|
+
tls: { rejectUnauthorized: false },
|
|
11
|
+
});
|
|
12
|
+
export async function sendMagicLinkEmail(to, code) {
|
|
13
|
+
const text = `Your AgentMailbox verification code:\n\n${code}\n\nPaste this code in your terminal to complete login.\nThis code expires in ${config.auth.magicLinkTtlMinutes} minutes.`;
|
|
14
|
+
await transporter.sendMail({
|
|
15
|
+
from: `AgentMailbox <${config.auth.fromAddress}>`,
|
|
16
|
+
to,
|
|
17
|
+
subject: `Your login code: ${code}`,
|
|
18
|
+
text,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=send.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/email/send.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,WAAW,GAAG,UAAU,CAAC,eAAe,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI;IAC9B,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI;IAC9B,MAAM,EAAE,KAAK;IACb,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI;QAC1B,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE;QAC9E,CAAC,CAAC,EAAE,CAAC;IACP,GAAG,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE;CAC5B,CAAC,CAAC;AAEV,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAU,EAAE,IAAY;IAC/D,MAAM,IAAI,GAAG,2CAA2C,IAAI,iFAAiF,MAAM,CAAC,IAAI,CAAC,mBAAmB,WAAW,CAAC;IAExL,MAAM,WAAW,CAAC,QAAQ,CAAC;QACzB,IAAI,EAAE,iBAAiB,MAAM,CAAC,IAAI,CAAC,WAAW,GAAG;QACjD,EAAE;QACF,OAAO,EAAE,oBAAoB,IAAI,EAAE;QACnC,IAAI;KACL,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receiver.d.ts","sourceRoot":"","sources":["../../src/smtp/receiver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"receiver.d.ts","sourceRoot":"","sources":["../../src/smtp/receiver.ts"],"names":[],"mappings":"AASA,wBAAgB,kBAAkB;;;EAyFjC"}
|
package/dist/smtp/receiver.js
CHANGED
|
@@ -1,18 +1,35 @@
|
|
|
1
1
|
import { SMTPServer } from 'smtp-server';
|
|
2
2
|
import { simpleParser } from 'mailparser';
|
|
3
|
+
import nodemailer from 'nodemailer';
|
|
3
4
|
import { pool } from '../db/index.js';
|
|
4
5
|
import { config } from '../config.js';
|
|
6
|
+
// Direct transport for relaying to external MX servers
|
|
7
|
+
const directTransport = nodemailer.createTransport({ direct: true });
|
|
5
8
|
export function createSmtpReceiver() {
|
|
6
9
|
const domain = config.smtp.domain;
|
|
10
|
+
const relaySecret = config.smtp.relaySecret;
|
|
7
11
|
const server = new SMTPServer({
|
|
8
12
|
authOptional: true,
|
|
9
|
-
disabledCommands: ['AUTH'],
|
|
10
13
|
banner: `AgentEmail SMTP`,
|
|
11
14
|
size: 10 * 1024 * 1024, // 10MB max
|
|
12
|
-
|
|
15
|
+
onAuth(auth, _session, callback) {
|
|
16
|
+
if (relaySecret &&
|
|
17
|
+
auth.username === 'relay' &&
|
|
18
|
+
auth.password === relaySecret) {
|
|
19
|
+
callback(null, { user: 'relay' });
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
callback(new Error('Invalid credentials'));
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
onRcptTo(address, session, callback) {
|
|
13
26
|
const addr = address.address.toLowerCase();
|
|
27
|
+
const isRelay = session.user === 'relay';
|
|
14
28
|
if (addr.endsWith(`@${domain}`)) {
|
|
15
|
-
callback();
|
|
29
|
+
callback(); // Accept mail for our domain
|
|
30
|
+
}
|
|
31
|
+
else if (isRelay) {
|
|
32
|
+
callback(); // Authenticated relay to external
|
|
16
33
|
}
|
|
17
34
|
else {
|
|
18
35
|
callback(new Error(`Not accepting mail for ${addr}`));
|
|
@@ -25,39 +42,21 @@ export function createSmtpReceiver() {
|
|
|
25
42
|
try {
|
|
26
43
|
const raw = Buffer.concat(chunks).toString('utf-8');
|
|
27
44
|
const parsed = await simpleParser(raw);
|
|
45
|
+
const isRelay = session.user === 'relay';
|
|
28
46
|
const fromAddress = session.envelope.mailFrom &&
|
|
29
47
|
typeof session.envelope.mailFrom === 'object'
|
|
30
48
|
? session.envelope.mailFrom.address
|
|
31
49
|
: '';
|
|
32
50
|
const recipients = session.envelope.rcptTo.map((r) => r.address.toLowerCase());
|
|
33
51
|
for (const toAddress of recipients) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
52
|
+
if (toAddress.endsWith(`@${domain}`)) {
|
|
53
|
+
// Inbound: store in DB
|
|
54
|
+
await storeInbound(parsed, fromAddress, toAddress, raw);
|
|
55
|
+
}
|
|
56
|
+
else if (isRelay) {
|
|
57
|
+
// Relay: deliver to external MX
|
|
58
|
+
await relayOutbound(fromAddress, toAddress, raw);
|
|
38
59
|
}
|
|
39
|
-
const accountId = result.rows[0].id;
|
|
40
|
-
await pool.query(`INSERT INTO messages
|
|
41
|
-
(account_id, message_id, from_address, to_address, subject, text_body, html_body, raw, headers, direction)
|
|
42
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, 'inbound')`, [
|
|
43
|
-
accountId,
|
|
44
|
-
parsed.messageId || null,
|
|
45
|
-
fromAddress,
|
|
46
|
-
toAddress,
|
|
47
|
-
parsed.subject || null,
|
|
48
|
-
parsed.text || null,
|
|
49
|
-
parsed.html || null,
|
|
50
|
-
raw,
|
|
51
|
-
JSON.stringify(parsed.headerLines?.map((h) => ({
|
|
52
|
-
key: h.key,
|
|
53
|
-
line: h.line,
|
|
54
|
-
})) || []),
|
|
55
|
-
]);
|
|
56
|
-
// Notify listeners waiting for new messages
|
|
57
|
-
await pool.query(`SELECT pg_notify('new_message', $1)`, [
|
|
58
|
-
accountId,
|
|
59
|
-
]);
|
|
60
|
-
console.log(`Stored message for ${toAddress} from ${fromAddress}: ${parsed.subject}`);
|
|
61
60
|
}
|
|
62
61
|
callback();
|
|
63
62
|
}
|
|
@@ -85,4 +84,42 @@ export function createSmtpReceiver() {
|
|
|
85
84
|
},
|
|
86
85
|
};
|
|
87
86
|
}
|
|
87
|
+
async function storeInbound(parsed, fromAddress, toAddress, raw) {
|
|
88
|
+
const result = await pool.query('SELECT id FROM accounts WHERE address = $1', [toAddress]);
|
|
89
|
+
if (result.rows.length === 0) {
|
|
90
|
+
console.log(`No account for ${toAddress}, skipping`);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const accountId = result.rows[0].id;
|
|
94
|
+
await pool.query(`INSERT INTO messages
|
|
95
|
+
(account_id, message_id, from_address, to_address, subject, text_body, html_body, raw, headers, direction)
|
|
96
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, 'inbound')`, [
|
|
97
|
+
accountId,
|
|
98
|
+
parsed.messageId || null,
|
|
99
|
+
fromAddress,
|
|
100
|
+
toAddress,
|
|
101
|
+
parsed.subject || null,
|
|
102
|
+
parsed.text || null,
|
|
103
|
+
parsed.html || null,
|
|
104
|
+
raw,
|
|
105
|
+
JSON.stringify(parsed.headerLines?.map((h) => ({
|
|
106
|
+
key: h.key,
|
|
107
|
+
line: h.line,
|
|
108
|
+
})) || []),
|
|
109
|
+
]);
|
|
110
|
+
await pool.query(`SELECT pg_notify('new_message', $1)`, [accountId]);
|
|
111
|
+
console.log(`Stored message for ${toAddress} from ${fromAddress}: ${parsed.subject}`);
|
|
112
|
+
}
|
|
113
|
+
async function relayOutbound(from, to, raw) {
|
|
114
|
+
try {
|
|
115
|
+
await directTransport.sendMail({
|
|
116
|
+
envelope: { from, to: [to] },
|
|
117
|
+
raw,
|
|
118
|
+
});
|
|
119
|
+
console.log(`Relayed email from ${from} to ${to}`);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
console.error(`Failed to relay to ${to}:`, err);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
88
125
|
//# sourceMappingURL=receiver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receiver.js","sourceRoot":"","sources":["../../src/smtp/receiver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"receiver.js","sourceRoot":"","sources":["../../src/smtp/receiver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAqB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,uDAAuD;AACvD,MAAM,eAAe,GAAG,UAAU,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,IAAI,EAAS,CAAC,CAAC;AAE5E,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;IAClC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;IAE5C,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC;QAC5B,YAAY,EAAE,IAAI;QAClB,MAAM,EAAE,iBAAiB;QACzB,IAAI,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,WAAW;QAEnC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ;YAC7B,IACE,WAAW;gBACX,IAAI,CAAC,QAAQ,KAAK,OAAO;gBACzB,IAAI,CAAC,QAAQ,KAAK,WAAW,EAC7B,CAAC;gBACD,QAAQ,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ;YACjC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAI,OAAe,CAAC,IAAI,KAAK,OAAO,CAAC;YAElD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,EAAE,CAAC;gBAChC,QAAQ,EAAE,CAAC,CAAC,6BAA6B;YAC3C,CAAC;iBAAM,IAAI,OAAO,EAAE,CAAC;gBACnB,QAAQ,EAAE,CAAC,CAAC,kCAAkC;YAChD,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ;YAC9B,MAAM,MAAM,GAAa,EAAE,CAAC;YAC5B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACzD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;gBAC1B,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBACpD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;oBACvC,MAAM,OAAO,GAAI,OAAe,CAAC,IAAI,KAAK,OAAO,CAAC;oBAElD,MAAM,WAAW,GACf,OAAO,CAAC,QAAQ,CAAC,QAAQ;wBACzB,OAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ,KAAK,QAAQ;wBAC3C,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO;wBACnC,CAAC,CAAC,EAAE,CAAC;oBACT,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACnD,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CACxB,CAAC;oBAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;wBACnC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,EAAE,CAAC;4BACrC,uBAAuB;4BACvB,MAAM,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;wBAC1D,CAAC;6BAAM,IAAI,OAAO,EAAE,CAAC;4BACnB,gCAAgC;4BAChC,MAAM,aAAa,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;wBACnD,CAAC;oBACH,CAAC;oBAED,QAAQ,EAAE,CAAC;gBACb,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;oBAC9C,QAAQ,CAAC,GAAY,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;IAEH,OAAO;QACL,KAAK;YACH,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC3C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE;oBACrD,OAAO,CAAC,GAAG,CACT,8BAA8B,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,MAAM,EAAE,CACpF,CAAC;oBACF,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC7B,CAAC,CAAC,CAAC;QACL,CAAC;QACD,IAAI;YACF,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBACnC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,MAAW,EACX,WAAmB,EACnB,SAAiB,EACjB,GAAW;IAEX,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B,4CAA4C,EAC5C,CAAC,SAAS,CAAC,CACZ,CAAC;IAEF,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,kBAAkB,SAAS,YAAY,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEpC,MAAM,IAAI,CAAC,KAAK,CACd;;4DAEwD,EACxD;QACE,SAAS;QACT,MAAM,CAAC,SAAS,IAAI,IAAI;QACxB,WAAW;QACX,SAAS;QACT,MAAM,CAAC,OAAO,IAAI,IAAI;QACtB,MAAM,CAAC,IAAI,IAAI,IAAI;QACnB,MAAM,CAAC,IAAI,IAAI,IAAI;QACnB,GAAG;QACH,IAAI,CAAC,SAAS,CACZ,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAgC,EAAE,EAAE,CAAC,CAAC;YAC7D,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,IAAI,EAAE,CAAC,CAAC,IAAI;SACb,CAAC,CAAC,IAAI,EAAE,CACV;KACF,CACF,CAAC;IAEF,MAAM,IAAI,CAAC,KAAK,CAAC,qCAAqC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CACT,sBAAsB,SAAS,SAAS,WAAW,KAAK,MAAM,CAAC,OAAO,EAAE,CACzE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,EAAU,EAAE,GAAW;IAChE,IAAI,CAAC;QACH,MAAM,eAAe,CAAC,QAAQ,CAAC;YAC7B,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE;YAC5B,GAAG;SACJ,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,OAAO,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;AACH,CAAC"}
|