aamp-sdk 0.1.5
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 +43 -0
- package/dist/client.d.ts +91 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +196 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/jmap-push.d.ts +104 -0
- package/dist/jmap-push.d.ts.map +1 -0
- package/dist/jmap-push.js +634 -0
- package/dist/jmap-push.js.map +1 -0
- package/dist/parser.d.ts +65 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +187 -0
- package/dist/parser.js.map +1 -0
- package/dist/smtp-sender.d.ts +57 -0
- package/dist/smtp-sender.d.ts.map +1 -0
- package/dist/smtp-sender.js +282 -0
- package/dist/smtp-sender.js.map +1 -0
- package/dist/types.d.ts +168 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AAMP Header Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses AAMP protocol headers from email messages.
|
|
5
|
+
* Works with both raw header objects and JMAP Email objects.
|
|
6
|
+
*
|
|
7
|
+
* Headers are case-insensitive; we normalize to lowercase for lookup.
|
|
8
|
+
*/
|
|
9
|
+
import { type AampMessage, type TaskResult } from './types.js';
|
|
10
|
+
type RawHeaders = Record<string, string | string[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Normalize a header map to lowercase keys with string values
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizeHeaders(headers: RawHeaders): Record<string, string>;
|
|
15
|
+
export interface EmailMetadata {
|
|
16
|
+
from: string;
|
|
17
|
+
to: string;
|
|
18
|
+
messageId: string;
|
|
19
|
+
subject: string;
|
|
20
|
+
headers: RawHeaders;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parse AAMP headers from an email's header map.
|
|
24
|
+
* Returns null if this email is not an AAMP message.
|
|
25
|
+
*
|
|
26
|
+
* @param meta - Email metadata (from, to, messageId, subject, headers)
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseAampHeaders(meta: EmailMetadata): AampMessage | null;
|
|
29
|
+
/**
|
|
30
|
+
* Build AAMP headers for a task.dispatch email
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildDispatchHeaders(params: {
|
|
33
|
+
taskId: string;
|
|
34
|
+
/** Omit or pass undefined/null to send without a deadline */
|
|
35
|
+
timeoutSecs?: number | null;
|
|
36
|
+
contextLinks: string[];
|
|
37
|
+
parentTaskId?: string;
|
|
38
|
+
}): Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* Build AAMP headers for a task.ack email
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildAckHeaders(opts: {
|
|
43
|
+
taskId: string;
|
|
44
|
+
}): Record<string, string>;
|
|
45
|
+
/**
|
|
46
|
+
* Build AAMP headers for a task.result email
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildResultHeaders(params: {
|
|
49
|
+
taskId: string;
|
|
50
|
+
status: 'completed' | 'rejected';
|
|
51
|
+
output: string;
|
|
52
|
+
errorMsg?: string;
|
|
53
|
+
structuredResult?: TaskResult['structuredResult'];
|
|
54
|
+
}): Record<string, string>;
|
|
55
|
+
/**
|
|
56
|
+
* Build AAMP headers for a task.help email
|
|
57
|
+
*/
|
|
58
|
+
export declare function buildHelpHeaders(params: {
|
|
59
|
+
taskId: string;
|
|
60
|
+
question: string;
|
|
61
|
+
blockedReason: string;
|
|
62
|
+
suggestedOptions: string[];
|
|
63
|
+
}): Record<string, string>;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAe,KAAK,WAAW,EAAqB,KAAK,UAAU,EAA+B,MAAM,YAAY,CAAA;AAE3H,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;AAEnD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO5E;AAkCD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,UAAU,CAAA;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,WAAW,GAAG,IAAI,CAwFxE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAezB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKhF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,GAAG,UAAU,CAAA;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,UAAU,CAAC,kBAAkB,CAAC,CAAA;CAClD,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAezB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC3B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQzB"}
|
package/dist/parser.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AAMP Header Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses AAMP protocol headers from email messages.
|
|
5
|
+
* Works with both raw header objects and JMAP Email objects.
|
|
6
|
+
*
|
|
7
|
+
* Headers are case-insensitive; we normalize to lowercase for lookup.
|
|
8
|
+
*/
|
|
9
|
+
import { AAMP_HEADER } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Normalize a header map to lowercase keys with string values
|
|
12
|
+
*/
|
|
13
|
+
export function normalizeHeaders(headers) {
|
|
14
|
+
return Object.fromEntries(Object.entries(headers).map(([k, v]) => [
|
|
15
|
+
k.toLowerCase(),
|
|
16
|
+
Array.isArray(v) ? v[0] : v,
|
|
17
|
+
]));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get a header value by its X-AAMP-* name (case-insensitive)
|
|
21
|
+
*/
|
|
22
|
+
function getAampHeader(headers, headerName) {
|
|
23
|
+
return headers[headerName.toLowerCase()];
|
|
24
|
+
}
|
|
25
|
+
function decodeStructuredResult(value) {
|
|
26
|
+
if (!value)
|
|
27
|
+
return undefined;
|
|
28
|
+
try {
|
|
29
|
+
const normalized = value.replace(/-/g, '+').replace(/_/g, '/');
|
|
30
|
+
const padding = normalized.length % 4 === 0 ? '' : '='.repeat(4 - (normalized.length % 4));
|
|
31
|
+
const decoded = Buffer.from(normalized + padding, 'base64').toString('utf-8');
|
|
32
|
+
return JSON.parse(decoded);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function encodeStructuredResult(value) {
|
|
39
|
+
if (!value)
|
|
40
|
+
return undefined;
|
|
41
|
+
const json = JSON.stringify(value);
|
|
42
|
+
return Buffer.from(json, 'utf-8')
|
|
43
|
+
.toString('base64')
|
|
44
|
+
.replace(/\+/g, '-')
|
|
45
|
+
.replace(/\//g, '_')
|
|
46
|
+
.replace(/=+$/g, '');
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse AAMP headers from an email's header map.
|
|
50
|
+
* Returns null if this email is not an AAMP message.
|
|
51
|
+
*
|
|
52
|
+
* @param meta - Email metadata (from, to, messageId, subject, headers)
|
|
53
|
+
*/
|
|
54
|
+
export function parseAampHeaders(meta) {
|
|
55
|
+
const headers = normalizeHeaders(meta.headers);
|
|
56
|
+
const intent = getAampHeader(headers, AAMP_HEADER.INTENT);
|
|
57
|
+
const taskId = getAampHeader(headers, AAMP_HEADER.TASK_ID);
|
|
58
|
+
if (!intent || !taskId)
|
|
59
|
+
return null;
|
|
60
|
+
const from = meta.from.replace(/^<|>$/g, '');
|
|
61
|
+
const to = meta.to.replace(/^<|>$/g, '');
|
|
62
|
+
if (intent === 'task.dispatch') {
|
|
63
|
+
const timeoutStr = getAampHeader(headers, AAMP_HEADER.TIMEOUT) ?? '300';
|
|
64
|
+
const contextLinksStr = getAampHeader(headers, AAMP_HEADER.CONTEXT_LINKS) ?? '';
|
|
65
|
+
const parentTaskId = getAampHeader(headers, AAMP_HEADER.PARENT_TASK_ID);
|
|
66
|
+
const dispatch = {
|
|
67
|
+
intent: 'task.dispatch',
|
|
68
|
+
taskId,
|
|
69
|
+
title: meta.subject.replace(/^\[AAMP Task\]\s*/, '').trim() || 'Untitled Task',
|
|
70
|
+
timeoutSecs: parseInt(timeoutStr, 10) || 300,
|
|
71
|
+
contextLinks: contextLinksStr
|
|
72
|
+
? contextLinksStr.split(',').map((s) => s.trim()).filter(Boolean)
|
|
73
|
+
: [],
|
|
74
|
+
...(parentTaskId ? { parentTaskId } : {}),
|
|
75
|
+
from,
|
|
76
|
+
to,
|
|
77
|
+
messageId: meta.messageId,
|
|
78
|
+
subject: meta.subject,
|
|
79
|
+
bodyText: '', // filled in by jmap-push.ts after parsing
|
|
80
|
+
};
|
|
81
|
+
return dispatch;
|
|
82
|
+
}
|
|
83
|
+
if (intent === 'task.result') {
|
|
84
|
+
const status = (getAampHeader(headers, AAMP_HEADER.STATUS) ?? 'completed');
|
|
85
|
+
const output = getAampHeader(headers, AAMP_HEADER.OUTPUT) ?? '';
|
|
86
|
+
const errorMsg = getAampHeader(headers, AAMP_HEADER.ERROR_MSG);
|
|
87
|
+
const structuredResult = decodeStructuredResult(getAampHeader(headers, AAMP_HEADER.STRUCTURED_RESULT));
|
|
88
|
+
const result = {
|
|
89
|
+
intent: 'task.result',
|
|
90
|
+
taskId,
|
|
91
|
+
status,
|
|
92
|
+
output,
|
|
93
|
+
errorMsg,
|
|
94
|
+
structuredResult,
|
|
95
|
+
from,
|
|
96
|
+
to,
|
|
97
|
+
};
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
if (intent === 'task.help') {
|
|
101
|
+
const question = getAampHeader(headers, AAMP_HEADER.QUESTION) ?? '';
|
|
102
|
+
const blockedReason = getAampHeader(headers, AAMP_HEADER.BLOCKED_REASON) ?? '';
|
|
103
|
+
const suggestedOptionsStr = getAampHeader(headers, AAMP_HEADER.SUGGESTED_OPTIONS) ?? '';
|
|
104
|
+
const help = {
|
|
105
|
+
intent: 'task.help',
|
|
106
|
+
taskId,
|
|
107
|
+
question,
|
|
108
|
+
blockedReason,
|
|
109
|
+
suggestedOptions: suggestedOptionsStr
|
|
110
|
+
? suggestedOptionsStr.split('|').map((s) => s.trim()).filter(Boolean)
|
|
111
|
+
: [],
|
|
112
|
+
from,
|
|
113
|
+
to,
|
|
114
|
+
};
|
|
115
|
+
return help;
|
|
116
|
+
}
|
|
117
|
+
if (intent === 'task.ack') {
|
|
118
|
+
const ack = {
|
|
119
|
+
intent: 'task.ack',
|
|
120
|
+
taskId,
|
|
121
|
+
from,
|
|
122
|
+
to,
|
|
123
|
+
};
|
|
124
|
+
return ack;
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Build AAMP headers for a task.dispatch email
|
|
130
|
+
*/
|
|
131
|
+
export function buildDispatchHeaders(params) {
|
|
132
|
+
const headers = {
|
|
133
|
+
[AAMP_HEADER.INTENT]: 'task.dispatch',
|
|
134
|
+
[AAMP_HEADER.TASK_ID]: params.taskId,
|
|
135
|
+
};
|
|
136
|
+
if (params.timeoutSecs != null) {
|
|
137
|
+
headers[AAMP_HEADER.TIMEOUT] = String(params.timeoutSecs);
|
|
138
|
+
}
|
|
139
|
+
if (params.contextLinks.length > 0) {
|
|
140
|
+
headers[AAMP_HEADER.CONTEXT_LINKS] = params.contextLinks.join(',');
|
|
141
|
+
}
|
|
142
|
+
if (params.parentTaskId) {
|
|
143
|
+
headers[AAMP_HEADER.PARENT_TASK_ID] = params.parentTaskId;
|
|
144
|
+
}
|
|
145
|
+
return headers;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Build AAMP headers for a task.ack email
|
|
149
|
+
*/
|
|
150
|
+
export function buildAckHeaders(opts) {
|
|
151
|
+
return {
|
|
152
|
+
[AAMP_HEADER.INTENT]: 'task.ack',
|
|
153
|
+
[AAMP_HEADER.TASK_ID]: opts.taskId,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Build AAMP headers for a task.result email
|
|
158
|
+
*/
|
|
159
|
+
export function buildResultHeaders(params) {
|
|
160
|
+
const headers = {
|
|
161
|
+
[AAMP_HEADER.INTENT]: 'task.result',
|
|
162
|
+
[AAMP_HEADER.TASK_ID]: params.taskId,
|
|
163
|
+
[AAMP_HEADER.STATUS]: params.status,
|
|
164
|
+
[AAMP_HEADER.OUTPUT]: params.output,
|
|
165
|
+
};
|
|
166
|
+
if (params.errorMsg) {
|
|
167
|
+
headers[AAMP_HEADER.ERROR_MSG] = params.errorMsg;
|
|
168
|
+
}
|
|
169
|
+
const structuredResult = encodeStructuredResult(params.structuredResult);
|
|
170
|
+
if (structuredResult) {
|
|
171
|
+
headers[AAMP_HEADER.STRUCTURED_RESULT] = structuredResult;
|
|
172
|
+
}
|
|
173
|
+
return headers;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Build AAMP headers for a task.help email
|
|
177
|
+
*/
|
|
178
|
+
export function buildHelpHeaders(params) {
|
|
179
|
+
return {
|
|
180
|
+
[AAMP_HEADER.INTENT]: 'task.help',
|
|
181
|
+
[AAMP_HEADER.TASK_ID]: params.taskId,
|
|
182
|
+
[AAMP_HEADER.QUESTION]: params.question,
|
|
183
|
+
[AAMP_HEADER.BLOCKED_REASON]: params.blockedReason,
|
|
184
|
+
[AAMP_HEADER.SUGGESTED_OPTIONS]: params.suggestedOptions.join('|'),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMTP Sender
|
|
3
|
+
*
|
|
4
|
+
* Sends AAMP protocol emails via SMTP (Stalwart submission port 587).
|
|
5
|
+
*/
|
|
6
|
+
import type { SendTaskOptions, SendResultOptions, SendHelpOptions } from './types.js';
|
|
7
|
+
export interface SmtpConfig {
|
|
8
|
+
host: string;
|
|
9
|
+
port: number;
|
|
10
|
+
user: string;
|
|
11
|
+
password: string;
|
|
12
|
+
httpBaseUrl?: string;
|
|
13
|
+
authToken?: string;
|
|
14
|
+
secure?: boolean;
|
|
15
|
+
/** Whether to reject unauthorized TLS certificates (default: true) */
|
|
16
|
+
rejectUnauthorized?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare class SmtpSender {
|
|
19
|
+
private readonly config;
|
|
20
|
+
private transport;
|
|
21
|
+
constructor(config: SmtpConfig);
|
|
22
|
+
private senderDomain;
|
|
23
|
+
private recipientDomain;
|
|
24
|
+
private shouldUseHttpFallback;
|
|
25
|
+
private sendViaHttp;
|
|
26
|
+
/**
|
|
27
|
+
* Send a task.dispatch email.
|
|
28
|
+
* Returns both the generated taskId and the SMTP Message-ID so callers can
|
|
29
|
+
* store a reverse-index (messageId → taskId) for In-Reply-To thread routing.
|
|
30
|
+
*/
|
|
31
|
+
sendTask(opts: SendTaskOptions): Promise<{
|
|
32
|
+
taskId: string;
|
|
33
|
+
messageId: string;
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Send a task.result email back to the dispatcher
|
|
37
|
+
*/
|
|
38
|
+
sendResult(opts: SendResultOptions): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Send a task.help email when the agent is blocked
|
|
41
|
+
*/
|
|
42
|
+
sendHelp(opts: SendHelpOptions): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Send a task.ack email to confirm receipt of a dispatch
|
|
45
|
+
*/
|
|
46
|
+
sendAck(opts: {
|
|
47
|
+
to: string;
|
|
48
|
+
taskId: string;
|
|
49
|
+
inReplyTo?: string;
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Verify SMTP connection
|
|
53
|
+
*/
|
|
54
|
+
verify(): Promise<boolean>;
|
|
55
|
+
close(): void;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=smtp-sender.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smtp-sender.d.ts","sourceRoot":"","sources":["../src/smtp-sender.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,eAAe,EAChB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED,qBAAa,UAAU;IAGT,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,SAAS,CAAa;gBAED,MAAM,EAAE,UAAU;IAe/C,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,qBAAqB;YASf,WAAW;IAsCzB;;;;OAIG;IACG,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAwDrF;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwDxD;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA0DpD;;OAEG;IACG,OAAO,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BtF;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAShC,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMTP Sender
|
|
3
|
+
*
|
|
4
|
+
* Sends AAMP protocol emails via SMTP (Stalwart submission port 587).
|
|
5
|
+
*/
|
|
6
|
+
import { createTransport } from 'nodemailer';
|
|
7
|
+
import { randomUUID } from 'crypto';
|
|
8
|
+
/** Strip CR/LF to prevent email header injection */
|
|
9
|
+
const sanitize = (s) => s.replace(/[\r\n]/g, ' ').trim();
|
|
10
|
+
import { buildDispatchHeaders, buildResultHeaders, buildHelpHeaders, buildAckHeaders } from './parser.js';
|
|
11
|
+
export class SmtpSender {
|
|
12
|
+
config;
|
|
13
|
+
transport;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
this.transport = createTransport({
|
|
17
|
+
host: config.host,
|
|
18
|
+
port: config.port,
|
|
19
|
+
secure: config.secure ?? false,
|
|
20
|
+
auth: {
|
|
21
|
+
user: config.user,
|
|
22
|
+
pass: config.password,
|
|
23
|
+
},
|
|
24
|
+
tls: {
|
|
25
|
+
rejectUnauthorized: config.rejectUnauthorized ?? true,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
senderDomain() {
|
|
30
|
+
return this.config.user.split('@')[1]?.toLowerCase() ?? '';
|
|
31
|
+
}
|
|
32
|
+
recipientDomain(email) {
|
|
33
|
+
return email.split('@')[1]?.toLowerCase() ?? '';
|
|
34
|
+
}
|
|
35
|
+
shouldUseHttpFallback(to) {
|
|
36
|
+
return Boolean(this.config.httpBaseUrl
|
|
37
|
+
&& this.config.authToken
|
|
38
|
+
&& this.senderDomain()
|
|
39
|
+
&& this.senderDomain() === this.recipientDomain(to));
|
|
40
|
+
}
|
|
41
|
+
async sendViaHttp(opts) {
|
|
42
|
+
const base = this.config.httpBaseUrl?.replace(/\/$/, '');
|
|
43
|
+
if (!base || !this.config.authToken) {
|
|
44
|
+
throw new Error('HTTP send fallback is not configured');
|
|
45
|
+
}
|
|
46
|
+
const res = await fetch(`${base}/api/send`, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: {
|
|
49
|
+
Authorization: `Basic ${this.config.authToken}`,
|
|
50
|
+
'Content-Type': 'application/json',
|
|
51
|
+
},
|
|
52
|
+
body: JSON.stringify({
|
|
53
|
+
to: opts.to,
|
|
54
|
+
subject: opts.subject,
|
|
55
|
+
text: opts.text,
|
|
56
|
+
aampHeaders: opts.aampHeaders,
|
|
57
|
+
attachments: opts.attachments?.map((a) => ({
|
|
58
|
+
filename: a.filename,
|
|
59
|
+
contentType: a.contentType,
|
|
60
|
+
content: typeof a.content === 'string' ? a.content : a.content.toString('base64'),
|
|
61
|
+
})),
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
64
|
+
const data = await res.json().catch(() => ({}));
|
|
65
|
+
if (!res.ok) {
|
|
66
|
+
throw new Error(data.details || `HTTP send failed: ${res.status}`);
|
|
67
|
+
}
|
|
68
|
+
return { messageId: data.messageId };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Send a task.dispatch email.
|
|
72
|
+
* Returns both the generated taskId and the SMTP Message-ID so callers can
|
|
73
|
+
* store a reverse-index (messageId → taskId) for In-Reply-To thread routing.
|
|
74
|
+
*/
|
|
75
|
+
async sendTask(opts) {
|
|
76
|
+
const taskId = randomUUID();
|
|
77
|
+
const aampHeaders = buildDispatchHeaders({
|
|
78
|
+
taskId,
|
|
79
|
+
timeoutSecs: opts.timeoutSecs,
|
|
80
|
+
contextLinks: opts.contextLinks ?? [],
|
|
81
|
+
parentTaskId: opts.parentTaskId,
|
|
82
|
+
});
|
|
83
|
+
const sendMailOpts = {
|
|
84
|
+
from: this.config.user,
|
|
85
|
+
to: opts.to,
|
|
86
|
+
subject: `[AAMP Task] ${sanitize(opts.title)}`,
|
|
87
|
+
text: [
|
|
88
|
+
`Task: ${opts.title}`,
|
|
89
|
+
`Task ID: ${taskId}`,
|
|
90
|
+
opts.timeoutSecs ? `Deadline: ${opts.timeoutSecs}s` : `Deadline: none`,
|
|
91
|
+
opts.contextLinks?.length
|
|
92
|
+
? `Context:\n${opts.contextLinks.map((l) => ` ${l}`).join('\n')}`
|
|
93
|
+
: '',
|
|
94
|
+
``,
|
|
95
|
+
`--- This email was sent by AAMP. Reply directly to submit your result. ---`,
|
|
96
|
+
]
|
|
97
|
+
.filter(Boolean)
|
|
98
|
+
.join('\n'),
|
|
99
|
+
headers: aampHeaders,
|
|
100
|
+
};
|
|
101
|
+
if (opts.attachments?.length) {
|
|
102
|
+
sendMailOpts.attachments = opts.attachments.map(a => ({
|
|
103
|
+
filename: a.filename,
|
|
104
|
+
content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,
|
|
105
|
+
contentType: a.contentType,
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
if (this.shouldUseHttpFallback(opts.to)) {
|
|
109
|
+
const info = await this.sendViaHttp({
|
|
110
|
+
to: opts.to,
|
|
111
|
+
subject: sendMailOpts.subject,
|
|
112
|
+
text: sendMailOpts.text,
|
|
113
|
+
aampHeaders,
|
|
114
|
+
attachments: opts.attachments?.map(a => ({
|
|
115
|
+
filename: a.filename,
|
|
116
|
+
contentType: a.contentType,
|
|
117
|
+
content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,
|
|
118
|
+
})),
|
|
119
|
+
});
|
|
120
|
+
return { taskId, messageId: info.messageId ?? '' };
|
|
121
|
+
}
|
|
122
|
+
const info = await this.transport.sendMail(sendMailOpts);
|
|
123
|
+
return { taskId, messageId: info.messageId ?? '' };
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Send a task.result email back to the dispatcher
|
|
127
|
+
*/
|
|
128
|
+
async sendResult(opts) {
|
|
129
|
+
const aampHeaders = buildResultHeaders({
|
|
130
|
+
taskId: opts.taskId,
|
|
131
|
+
status: opts.status,
|
|
132
|
+
output: opts.output,
|
|
133
|
+
errorMsg: opts.errorMsg,
|
|
134
|
+
structuredResult: opts.structuredResult,
|
|
135
|
+
});
|
|
136
|
+
const mailOpts = {
|
|
137
|
+
from: this.config.user,
|
|
138
|
+
to: opts.to,
|
|
139
|
+
subject: `[AAMP Result] Task ${opts.taskId} — ${opts.status}`,
|
|
140
|
+
text: [
|
|
141
|
+
`AAMP Task Result`,
|
|
142
|
+
``,
|
|
143
|
+
`Task ID: ${opts.taskId}`,
|
|
144
|
+
`Status: ${opts.status}`,
|
|
145
|
+
``,
|
|
146
|
+
`Output:`,
|
|
147
|
+
opts.output,
|
|
148
|
+
opts.errorMsg ? `\nError: ${opts.errorMsg}` : '',
|
|
149
|
+
]
|
|
150
|
+
.filter((s) => s !== '')
|
|
151
|
+
.join('\n'),
|
|
152
|
+
headers: aampHeaders,
|
|
153
|
+
};
|
|
154
|
+
if (opts.inReplyTo) {
|
|
155
|
+
mailOpts.inReplyTo = opts.inReplyTo;
|
|
156
|
+
mailOpts.references = opts.inReplyTo;
|
|
157
|
+
}
|
|
158
|
+
if (opts.attachments?.length) {
|
|
159
|
+
mailOpts.attachments = opts.attachments.map(a => ({
|
|
160
|
+
filename: a.filename,
|
|
161
|
+
content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,
|
|
162
|
+
contentType: a.contentType,
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
if (this.shouldUseHttpFallback(opts.to)) {
|
|
166
|
+
await this.sendViaHttp({
|
|
167
|
+
to: opts.to,
|
|
168
|
+
subject: mailOpts.subject,
|
|
169
|
+
text: mailOpts.text,
|
|
170
|
+
aampHeaders,
|
|
171
|
+
attachments: opts.attachments?.map(a => ({
|
|
172
|
+
filename: a.filename,
|
|
173
|
+
contentType: a.contentType,
|
|
174
|
+
content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,
|
|
175
|
+
})),
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
await this.transport.sendMail(mailOpts);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Send a task.help email when the agent is blocked
|
|
183
|
+
*/
|
|
184
|
+
async sendHelp(opts) {
|
|
185
|
+
const aampHeaders = buildHelpHeaders({
|
|
186
|
+
taskId: opts.taskId,
|
|
187
|
+
question: opts.question,
|
|
188
|
+
blockedReason: opts.blockedReason,
|
|
189
|
+
suggestedOptions: opts.suggestedOptions,
|
|
190
|
+
});
|
|
191
|
+
const helpMailOpts = {
|
|
192
|
+
from: this.config.user,
|
|
193
|
+
to: opts.to,
|
|
194
|
+
subject: `[AAMP Help] Task ${opts.taskId} needs assistance`,
|
|
195
|
+
text: [
|
|
196
|
+
`AAMP Task Help Request`,
|
|
197
|
+
``,
|
|
198
|
+
`Task ID: ${opts.taskId}`,
|
|
199
|
+
``,
|
|
200
|
+
`Question: ${opts.question}`,
|
|
201
|
+
``,
|
|
202
|
+
`Blocked reason: ${opts.blockedReason}`,
|
|
203
|
+
``,
|
|
204
|
+
opts.suggestedOptions.length
|
|
205
|
+
? `Suggested options:\n${opts.suggestedOptions.map((o, i) => ` ${i + 1}. ${o}`).join('\n')}`
|
|
206
|
+
: '',
|
|
207
|
+
]
|
|
208
|
+
.filter(Boolean)
|
|
209
|
+
.join('\n'),
|
|
210
|
+
headers: aampHeaders,
|
|
211
|
+
};
|
|
212
|
+
if (opts.inReplyTo) {
|
|
213
|
+
helpMailOpts.inReplyTo = opts.inReplyTo;
|
|
214
|
+
helpMailOpts.references = opts.inReplyTo;
|
|
215
|
+
}
|
|
216
|
+
if (opts.attachments?.length) {
|
|
217
|
+
helpMailOpts.attachments = opts.attachments.map(a => ({
|
|
218
|
+
filename: a.filename,
|
|
219
|
+
content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,
|
|
220
|
+
contentType: a.contentType,
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
223
|
+
if (this.shouldUseHttpFallback(opts.to)) {
|
|
224
|
+
await this.sendViaHttp({
|
|
225
|
+
to: opts.to,
|
|
226
|
+
subject: helpMailOpts.subject,
|
|
227
|
+
text: helpMailOpts.text,
|
|
228
|
+
aampHeaders,
|
|
229
|
+
attachments: opts.attachments?.map(a => ({
|
|
230
|
+
filename: a.filename,
|
|
231
|
+
contentType: a.contentType,
|
|
232
|
+
content: typeof a.content === 'string' ? Buffer.from(a.content, 'base64') : a.content,
|
|
233
|
+
})),
|
|
234
|
+
});
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
await this.transport.sendMail(helpMailOpts);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Send a task.ack email to confirm receipt of a dispatch
|
|
241
|
+
*/
|
|
242
|
+
async sendAck(opts) {
|
|
243
|
+
const aampHeaders = buildAckHeaders({ taskId: opts.taskId });
|
|
244
|
+
const mailOpts = {
|
|
245
|
+
from: this.config.user,
|
|
246
|
+
to: opts.to,
|
|
247
|
+
subject: `[AAMP ACK] Task ${opts.taskId}`,
|
|
248
|
+
text: '',
|
|
249
|
+
headers: aampHeaders,
|
|
250
|
+
};
|
|
251
|
+
if (opts.inReplyTo) {
|
|
252
|
+
mailOpts.inReplyTo = opts.inReplyTo;
|
|
253
|
+
mailOpts.references = opts.inReplyTo;
|
|
254
|
+
}
|
|
255
|
+
if (this.shouldUseHttpFallback(opts.to)) {
|
|
256
|
+
await this.sendViaHttp({
|
|
257
|
+
to: opts.to,
|
|
258
|
+
subject: mailOpts.subject,
|
|
259
|
+
text: mailOpts.text,
|
|
260
|
+
aampHeaders,
|
|
261
|
+
});
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
await this.transport.sendMail(mailOpts);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Verify SMTP connection
|
|
268
|
+
*/
|
|
269
|
+
async verify() {
|
|
270
|
+
try {
|
|
271
|
+
await this.transport.verify();
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
close() {
|
|
279
|
+
this.transport.close();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=smtp-sender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smtp-sender.js","sourceRoot":"","sources":["../src/smtp-sender.ts"],"names":[],"mappings":"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"}
|