@push.rocks/smartjmap 1.0.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/.smartconfig.json +56 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.jmapclient.d.ts +236 -0
- package/dist_ts/classes.jmapclient.js +650 -0
- package/dist_ts/classes.jmapserver.d.ts +110 -0
- package/dist_ts/classes.jmapserver.js +873 -0
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +3 -0
- package/dist_ts/smartjmap.plugins.d.ts +4 -0
- package/dist_ts/smartjmap.plugins.js +6 -0
- package/license +19 -0
- package/npmextra.json +39 -0
- package/package.json +68 -0
- package/readme.hints.md +34 -0
- package/readme.md +287 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.jmapclient.ts +872 -0
- package/ts/classes.jmapserver.ts +1019 -0
- package/ts/index.ts +2 -0
- package/ts/smartjmap.plugins.ts +10 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@git.zone/cli": {
|
|
3
|
+
"projectType": "npm",
|
|
4
|
+
"module": {
|
|
5
|
+
"githost": "code.foss.global",
|
|
6
|
+
"gitscope": "push.rocks",
|
|
7
|
+
"gitrepo": "smartjmap",
|
|
8
|
+
"shortDescription": "JMAP client for mail (RFC 8620/8621)",
|
|
9
|
+
"description": "A TypeScript JMAP client for reading, sending, and watching mail via the JSON Meta Application Protocol (RFC 8620/8621), with a bundled test server for offline testing.",
|
|
10
|
+
"npmPackagename": "@push.rocks/smartjmap",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"projectDomain": "push.rocks",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"jmap",
|
|
15
|
+
"email",
|
|
16
|
+
"mail",
|
|
17
|
+
"rfc8620",
|
|
18
|
+
"rfc8621",
|
|
19
|
+
"fastmail",
|
|
20
|
+
"stalwart",
|
|
21
|
+
"json",
|
|
22
|
+
"http",
|
|
23
|
+
"client",
|
|
24
|
+
"typescript",
|
|
25
|
+
"event-driven",
|
|
26
|
+
"push",
|
|
27
|
+
"eventsource",
|
|
28
|
+
"message processing"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
"release": {
|
|
32
|
+
"targets": {
|
|
33
|
+
"git": {
|
|
34
|
+
"enabled": true,
|
|
35
|
+
"remote": "origin"
|
|
36
|
+
},
|
|
37
|
+
"npm": {
|
|
38
|
+
"enabled": true,
|
|
39
|
+
"registries": [
|
|
40
|
+
"https://verdaccio.lossless.digital",
|
|
41
|
+
"https://registry.npmjs.org"
|
|
42
|
+
],
|
|
43
|
+
"accessLevel": "public"
|
|
44
|
+
},
|
|
45
|
+
"docker": {
|
|
46
|
+
"enabled": false,
|
|
47
|
+
"engine": "tsdocker"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"@ship.zone/szci": {
|
|
53
|
+
"npmGlobalTools": [],
|
|
54
|
+
"npmRegistryUrl": "registry.npmjs.org"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
|
+
*/
|
|
4
|
+
export const commitinfo = {
|
|
5
|
+
name: '@push.rocks/smartjmap',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
description: 'A TypeScript JMAP client for reading, sending, and watching mail via the JSON Meta Application Protocol (RFC 8620/8621), with a bundled test server for offline testing.'
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx1QkFBdUI7SUFDN0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDBLQUEwSztDQUN4TCxDQUFBIn0=
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import * as plugins from './smartjmap.plugins.js';
|
|
2
|
+
export declare const JMAP_CORE_CAPABILITY = "urn:ietf:params:jmap:core";
|
|
3
|
+
export declare const JMAP_MAIL_CAPABILITY = "urn:ietf:params:jmap:mail";
|
|
4
|
+
export declare const JMAP_SUBMISSION_CAPABILITY = "urn:ietf:params:jmap:submission";
|
|
5
|
+
export interface IJmapClientAuthBearer {
|
|
6
|
+
/** OAuth2 / API access token sent as `Authorization: Bearer <token>`. */
|
|
7
|
+
accessToken: string;
|
|
8
|
+
}
|
|
9
|
+
export interface IJmapClientAuthBasic {
|
|
10
|
+
user: string;
|
|
11
|
+
pass: string;
|
|
12
|
+
}
|
|
13
|
+
export type TJmapClientAuth = IJmapClientAuthBearer | IJmapClientAuthBasic;
|
|
14
|
+
export interface IJmapClientConfig {
|
|
15
|
+
/**
|
|
16
|
+
* URL of the JMAP session resource.
|
|
17
|
+
* Callers can pass the autodiscovery endpoint, e.g. `https://host/.well-known/jmap`;
|
|
18
|
+
* relative URLs inside the session object are resolved against this URL.
|
|
19
|
+
*/
|
|
20
|
+
sessionUrl: string;
|
|
21
|
+
/** Either `{ accessToken }` (Bearer) or `{ user, pass }` (Basic) — exactly one shape. */
|
|
22
|
+
auth: TJmapClientAuth;
|
|
23
|
+
/**
|
|
24
|
+
* Mailbox to watch for new messages. Defaults to 'INBOX' semantics:
|
|
25
|
+
* resolved via the Mailbox with role 'inbox', falling back to a
|
|
26
|
+
* case-insensitive name match.
|
|
27
|
+
*/
|
|
28
|
+
mailbox?: string;
|
|
29
|
+
/** Fallback polling cadence in ms, used when the event stream is unavailable. Default 30000. */
|
|
30
|
+
pollIntervalMs?: number;
|
|
31
|
+
}
|
|
32
|
+
/** A single JMAP method call: [methodName, arguments, methodCallId] (RFC 8620 §3.2). */
|
|
33
|
+
export type TJmapMethodCall = [string, Record<string, any>, string];
|
|
34
|
+
/** A single JMAP method response: [methodName, arguments, methodCallId] (RFC 8620 §3.4). */
|
|
35
|
+
export type TJmapMethodResponse = [string, Record<string, any>, string];
|
|
36
|
+
export interface IJmapSession {
|
|
37
|
+
capabilities: Record<string, any>;
|
|
38
|
+
accounts: Record<string, any>;
|
|
39
|
+
primaryAccounts: Record<string, string>;
|
|
40
|
+
username?: string;
|
|
41
|
+
apiUrl: string;
|
|
42
|
+
downloadUrl: string;
|
|
43
|
+
uploadUrl?: string;
|
|
44
|
+
eventSourceUrl?: string;
|
|
45
|
+
state?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface IJmapMailbox {
|
|
48
|
+
id: string;
|
|
49
|
+
name: string;
|
|
50
|
+
role?: string | null;
|
|
51
|
+
parentId?: string | null;
|
|
52
|
+
sortOrder?: number;
|
|
53
|
+
totalEmails?: number;
|
|
54
|
+
unreadEmails?: number;
|
|
55
|
+
totalThreads?: number;
|
|
56
|
+
unreadThreads?: number;
|
|
57
|
+
}
|
|
58
|
+
export interface IJmapEmailAddress {
|
|
59
|
+
name?: string | null;
|
|
60
|
+
email: string;
|
|
61
|
+
}
|
|
62
|
+
export interface IJmapEmailBodyPart {
|
|
63
|
+
partId?: string | null;
|
|
64
|
+
blobId?: string;
|
|
65
|
+
size?: number;
|
|
66
|
+
name?: string | null;
|
|
67
|
+
type?: string;
|
|
68
|
+
charset?: string | null;
|
|
69
|
+
disposition?: string | null;
|
|
70
|
+
cid?: string | null;
|
|
71
|
+
}
|
|
72
|
+
export interface IJmapEmailBodyValue {
|
|
73
|
+
value: string;
|
|
74
|
+
isTruncated?: boolean;
|
|
75
|
+
isEncodingProblem?: boolean;
|
|
76
|
+
}
|
|
77
|
+
/** The raw JMAP Email object (RFC 8621 §4) — the subset of properties this client requests. */
|
|
78
|
+
export interface IJmapEmail {
|
|
79
|
+
id: string;
|
|
80
|
+
blobId: string;
|
|
81
|
+
threadId: string;
|
|
82
|
+
mailboxIds: Record<string, boolean>;
|
|
83
|
+
keywords: Record<string, boolean>;
|
|
84
|
+
size?: number;
|
|
85
|
+
receivedAt?: string;
|
|
86
|
+
sentAt?: string | null;
|
|
87
|
+
subject?: string | null;
|
|
88
|
+
from?: IJmapEmailAddress[] | null;
|
|
89
|
+
to?: IJmapEmailAddress[] | null;
|
|
90
|
+
cc?: IJmapEmailAddress[] | null;
|
|
91
|
+
bcc?: IJmapEmailAddress[] | null;
|
|
92
|
+
replyTo?: IJmapEmailAddress[] | null;
|
|
93
|
+
hasAttachment?: boolean;
|
|
94
|
+
preview?: string;
|
|
95
|
+
bodyValues?: Record<string, IJmapEmailBodyValue>;
|
|
96
|
+
textBody?: IJmapEmailBodyPart[];
|
|
97
|
+
htmlBody?: IJmapEmailBodyPart[];
|
|
98
|
+
attachments?: IJmapEmailBodyPart[];
|
|
99
|
+
}
|
|
100
|
+
export interface IJmapAttachment {
|
|
101
|
+
blobId: string;
|
|
102
|
+
name?: string;
|
|
103
|
+
type?: string;
|
|
104
|
+
size?: number;
|
|
105
|
+
}
|
|
106
|
+
/** The message shape emitted on 'message' events and returned by the query/get helpers. */
|
|
107
|
+
export interface ISmartJmapMessage {
|
|
108
|
+
id: string;
|
|
109
|
+
blobId: string;
|
|
110
|
+
threadId: string;
|
|
111
|
+
mailboxIds: Record<string, boolean>;
|
|
112
|
+
keywords: Record<string, boolean>;
|
|
113
|
+
from: IJmapEmailAddress[];
|
|
114
|
+
to: IJmapEmailAddress[];
|
|
115
|
+
cc: IJmapEmailAddress[];
|
|
116
|
+
bcc: IJmapEmailAddress[];
|
|
117
|
+
replyTo: IJmapEmailAddress[];
|
|
118
|
+
subject?: string;
|
|
119
|
+
receivedAt?: string;
|
|
120
|
+
/** Plain-text body, resolved from the JMAP bodyValues. */
|
|
121
|
+
textBody: string;
|
|
122
|
+
/** HTML body, resolved from the JMAP bodyValues; undefined when the email has no text/html part. */
|
|
123
|
+
htmlBody?: string;
|
|
124
|
+
attachments: IJmapAttachment[];
|
|
125
|
+
/** The full raw JMAP Email object as returned by Email/get. */
|
|
126
|
+
raw: IJmapEmail;
|
|
127
|
+
}
|
|
128
|
+
export interface IJmapOutgoingEmail {
|
|
129
|
+
/** Sender; defaults to the address of the account's first JMAP Identity. */
|
|
130
|
+
from?: IJmapEmailAddress;
|
|
131
|
+
to: IJmapEmailAddress[];
|
|
132
|
+
cc?: IJmapEmailAddress[];
|
|
133
|
+
bcc?: IJmapEmailAddress[];
|
|
134
|
+
subject?: string;
|
|
135
|
+
textBody?: string;
|
|
136
|
+
htmlBody?: string;
|
|
137
|
+
}
|
|
138
|
+
export interface IJmapSendResult {
|
|
139
|
+
emailId: string;
|
|
140
|
+
submissionId: string;
|
|
141
|
+
}
|
|
142
|
+
/** Error thrown for HTTP-level (RFC 7807 problem details) and JMAP method-level errors. */
|
|
143
|
+
export declare class JmapError extends Error {
|
|
144
|
+
httpStatus?: number;
|
|
145
|
+
problemType?: string;
|
|
146
|
+
problemDetail?: string;
|
|
147
|
+
jmapErrorType?: string;
|
|
148
|
+
jmapErrorDescription?: string;
|
|
149
|
+
jmapCallId?: string;
|
|
150
|
+
constructor(message: string, fields?: Partial<JmapError>);
|
|
151
|
+
}
|
|
152
|
+
export declare class JmapClient extends plugins.events.EventEmitter {
|
|
153
|
+
private config;
|
|
154
|
+
private session;
|
|
155
|
+
private accountId;
|
|
156
|
+
private apiUrl;
|
|
157
|
+
private mailbox;
|
|
158
|
+
private connected;
|
|
159
|
+
private stopped;
|
|
160
|
+
private lastEmailState;
|
|
161
|
+
private seenEmailIds;
|
|
162
|
+
private pollTimer;
|
|
163
|
+
private sseAbortController;
|
|
164
|
+
private fetchingDeltas;
|
|
165
|
+
private deltaQueued;
|
|
166
|
+
constructor(config: IJmapClientConfig);
|
|
167
|
+
/**
|
|
168
|
+
* Fetches and validates the JMAP session, resolves the target mailbox,
|
|
169
|
+
* emits 'connected', emits 'message' for every email currently in the
|
|
170
|
+
* mailbox, then watches for new mail via the JMAP event source (SSE),
|
|
171
|
+
* falling back to polling when the event stream is unavailable.
|
|
172
|
+
* Failures are emitted as 'error' events; connect() does not throw.
|
|
173
|
+
*/
|
|
174
|
+
connect(): Promise<void>;
|
|
175
|
+
/**
|
|
176
|
+
* Stops watching (event stream and/or polling timer) and emits
|
|
177
|
+
* 'disconnected' when the client was connected. Leaves no open handles.
|
|
178
|
+
*/
|
|
179
|
+
disconnect(): Promise<void>;
|
|
180
|
+
/**
|
|
181
|
+
* Core JMAP method-call helper (RFC 8620 §3.2): POSTs { using, methodCalls }
|
|
182
|
+
* to the session's apiUrl and returns the methodResponses. HTTP problem
|
|
183
|
+
* details (RFC 7807) and JMAP `error` method responses are thrown as
|
|
184
|
+
* JmapError with `httpStatus`/`problemType`/`jmapErrorType` fields.
|
|
185
|
+
*/
|
|
186
|
+
request(methodCalls: TJmapMethodCall[]): Promise<TJmapMethodResponse[]>;
|
|
187
|
+
/** Returns all mailboxes of the account (Mailbox/get with ids: null). */
|
|
188
|
+
getMailboxes(): Promise<IJmapMailbox[]>;
|
|
189
|
+
/**
|
|
190
|
+
* Runs Email/query (default filter: the watched mailbox) followed by a full
|
|
191
|
+
* Email/get and returns resolved messages, newest first.
|
|
192
|
+
*/
|
|
193
|
+
queryEmails(filter?: Record<string, any>, limit?: number): Promise<ISmartJmapMessage[]>;
|
|
194
|
+
/** Fetches a single email with all body values resolved (RFC 8621 §4.2, fetchAllBodyValues). */
|
|
195
|
+
getEmail(id: string): Promise<ISmartJmapMessage>;
|
|
196
|
+
/** Replaces the full keywords object of an email via Email/set. */
|
|
197
|
+
setKeywords(emailId: string, keywords: Record<string, boolean>): Promise<void>;
|
|
198
|
+
/** Convenience: sets the $seen keyword via an Email/set keywords patch. */
|
|
199
|
+
markSeen(emailId: string): Promise<void>;
|
|
200
|
+
/**
|
|
201
|
+
* Sends an email: Identity/get lookup, Email/set create (into the mailbox
|
|
202
|
+
* with role 'sent', falling back to 'drafts', then the watched mailbox) and
|
|
203
|
+
* EmailSubmission/set referencing the created email.
|
|
204
|
+
*/
|
|
205
|
+
sendEmail(outgoing: IJmapOutgoingEmail): Promise<IJmapSendResult>;
|
|
206
|
+
/**
|
|
207
|
+
* Downloads a blob's raw bytes using the session downloadUrl template
|
|
208
|
+
* (RFC 8620 §6.2: {accountId}, {blobId}, {type}, {name}).
|
|
209
|
+
*/
|
|
210
|
+
downloadBlob(blobId: string, type?: string, name?: string): Promise<Uint8Array>;
|
|
211
|
+
private getAuthHeader;
|
|
212
|
+
private createHttpError;
|
|
213
|
+
private resolveMailbox;
|
|
214
|
+
private fetchEmailState;
|
|
215
|
+
private getEmailObjects;
|
|
216
|
+
private updateEmail;
|
|
217
|
+
private toMessage;
|
|
218
|
+
private emitMessage;
|
|
219
|
+
private emitInitialEmails;
|
|
220
|
+
private startWatching;
|
|
221
|
+
/**
|
|
222
|
+
* Watches the JMAP event source (RFC 8620 §7.3) by parsing SSE frames from
|
|
223
|
+
* a fetch body stream. A hand-rolled parser is used instead of the global
|
|
224
|
+
* EventSource because JMAP requires an Authorization header, which the
|
|
225
|
+
* WHATWG EventSource API cannot send.
|
|
226
|
+
*/
|
|
227
|
+
private startEventStream;
|
|
228
|
+
private runEventStream;
|
|
229
|
+
private handleEventStreamEvent;
|
|
230
|
+
private startPolling;
|
|
231
|
+
private fetchDeltas;
|
|
232
|
+
private fetchDeltasOnce;
|
|
233
|
+
/** Full resync fallback when the server cannot calculate changes. */
|
|
234
|
+
private resyncViaQuery;
|
|
235
|
+
private teardownWatchers;
|
|
236
|
+
}
|