@upyo/jmap 0.6.0-dev.351 → 0.6.0-dev.354
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 +3 -1
- package/dist/index.cjs +16 -9
- package/dist/index.js +16 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -163,7 +163,9 @@ factories. Declaring `encoding` reads the source once per successful send;
|
|
|
163
163
|
omitting it adds an analysis pass before upload. Every reader must reproduce
|
|
164
164
|
the same bytes. `7bit` requires ASCII, `8bit` asserts ASCII MIME headers with an
|
|
165
165
|
8-bit body, and `utf8` permits internationalized headers. Automatic analysis
|
|
166
|
-
conservatively selects `utf8` for any non-ASCII byte.
|
|
166
|
+
conservatively selects `utf8` for any non-ASCII byte. With `8bit`, the caller
|
|
167
|
+
must ensure nested MIME headers are ASCII; Upyo checks only top-level headers.
|
|
168
|
+
Use `utf8` or omit `encoding` if unsure. No transcoding occurs.
|
|
167
169
|
|
|
168
170
|
Sources must have CRLF line endings including the final CRLF, nonempty headers,
|
|
169
171
|
no NUL, and no line longer than 998 bytes excluding CRLF. Uploads stream without
|
package/dist/index.cjs
CHANGED
|
@@ -319,15 +319,15 @@ async function uploadRawMessage(config, uploadUrl, accountId, plan, signal) {
|
|
|
319
319
|
body,
|
|
320
320
|
duplex: "half",
|
|
321
321
|
redirect: "error",
|
|
322
|
-
signal:
|
|
322
|
+
signal: outerSignal
|
|
323
323
|
};
|
|
324
324
|
try {
|
|
325
325
|
const response = await fetch(uploadUrl.replace("{accountId}", encodeURIComponent(accountId)), request);
|
|
326
|
-
|
|
326
|
+
outerSignal.throwIfAborted();
|
|
327
|
+
if (!response.ok) throw new JmapApiError(`Raw upload failed: ${response.status}`, response.status, await response.text(), void 0, (0, __upyo_core.parseRetryAfter)(response.headers.get("Retry-After")));
|
|
327
328
|
if (!eof) throw new JmapApiError("Raw upload responded before validated EOF.");
|
|
328
|
-
if (!response.ok) throw new JmapApiError(`Raw upload failed: ${response.status}`, response.status, await response.text());
|
|
329
329
|
const result = await response.json();
|
|
330
|
-
|
|
330
|
+
outerSignal.throwIfAborted();
|
|
331
331
|
if (!isRecord(result) || result.accountId !== accountId || typeof result.blobId !== "string" || !result.blobId || result.size !== size) throw new JmapApiError("Invalid raw upload response.");
|
|
332
332
|
return {
|
|
333
333
|
accountId,
|
|
@@ -338,7 +338,6 @@ async function uploadRawMessage(config, uploadUrl, accountId, plan, signal) {
|
|
|
338
338
|
} catch (error) {
|
|
339
339
|
outerSignal.throwIfAborted();
|
|
340
340
|
if (hasSourceError) throw sourceError;
|
|
341
|
-
owned.throwIfAborted();
|
|
342
341
|
throw error;
|
|
343
342
|
} finally {
|
|
344
343
|
owned.removeEventListener("abort", abort);
|
|
@@ -355,11 +354,17 @@ const using = [
|
|
|
355
354
|
"urn:ietf:params:jmap:mail",
|
|
356
355
|
"urn:ietf:params:jmap:submission"
|
|
357
356
|
];
|
|
358
|
-
function failure(message, stage, retryable, unknown = false) {
|
|
357
|
+
function failure(message, stage, retryable, unknown = false, error) {
|
|
359
358
|
return (0, __upyo_core.createFailedReceipt)(message, {
|
|
360
359
|
provider: "jmap",
|
|
361
360
|
code: `jmap.raw_${stage}_${unknown ? "unknown" : "failed"}`,
|
|
362
|
-
category: unknown ? "unknown" : retryable ? void 0 : "rejected",
|
|
361
|
+
category: unknown ? "unknown" : error?.statusCode !== void 0 || retryable ? void 0 : "rejected",
|
|
362
|
+
statusCode: error?.statusCode,
|
|
363
|
+
retryAfterMilliseconds: error?.retryAfterMilliseconds,
|
|
364
|
+
providerDetails: error ? {
|
|
365
|
+
responseBody: error.responseBody,
|
|
366
|
+
jmapErrorType: error.jmapErrorType
|
|
367
|
+
} : void 0,
|
|
363
368
|
retryable,
|
|
364
369
|
attempts: 1
|
|
365
370
|
});
|
|
@@ -390,7 +395,9 @@ function errorDescription(error) {
|
|
|
390
395
|
return `Raw JMAP operation rejected: ${String(error.type)}${typeof error.description === "string" ? `: ${error.description}` : ""}`;
|
|
391
396
|
}
|
|
392
397
|
function isRequestRejection(error) {
|
|
393
|
-
if (!(error instanceof JmapApiError)
|
|
398
|
+
if (!(error instanceof JmapApiError)) return false;
|
|
399
|
+
if (error.statusCode === 401 || error.statusCode === 403) return true;
|
|
400
|
+
if (!error.responseBody || error.statusCode === void 0 || error.statusCode < 400 || error.statusCode > 599) return false;
|
|
394
401
|
try {
|
|
395
402
|
const body = JSON.parse(error.responseBody);
|
|
396
403
|
if (!isRecord(body) || body.status !== void 0 && body.status !== error.statusCode) return false;
|
|
@@ -488,7 +495,7 @@ async function deliverRawMessage(config, session, accountId, draftsMailboxId, id
|
|
|
488
495
|
attempts: 1
|
|
489
496
|
});
|
|
490
497
|
const definite = isRequestRejection(error);
|
|
491
|
-
return failure(message, stage, stage !== "submission" && !definite, stage === "submission" && !definite);
|
|
498
|
+
return failure(message, stage, stage !== "submission" && !definite, stage === "submission" && !definite, error instanceof JmapApiError ? error : void 0);
|
|
492
499
|
}
|
|
493
500
|
}
|
|
494
501
|
/** Validates raw discovery responses before accepting delivery identifiers. @internal */
|
package/dist/index.js
CHANGED
|
@@ -296,15 +296,15 @@ async function uploadRawMessage(config, uploadUrl, accountId, plan, signal) {
|
|
|
296
296
|
body,
|
|
297
297
|
duplex: "half",
|
|
298
298
|
redirect: "error",
|
|
299
|
-
signal:
|
|
299
|
+
signal: outerSignal
|
|
300
300
|
};
|
|
301
301
|
try {
|
|
302
302
|
const response = await fetch(uploadUrl.replace("{accountId}", encodeURIComponent(accountId)), request);
|
|
303
|
-
|
|
303
|
+
outerSignal.throwIfAborted();
|
|
304
|
+
if (!response.ok) throw new JmapApiError(`Raw upload failed: ${response.status}`, response.status, await response.text(), void 0, parseRetryAfter(response.headers.get("Retry-After")));
|
|
304
305
|
if (!eof) throw new JmapApiError("Raw upload responded before validated EOF.");
|
|
305
|
-
if (!response.ok) throw new JmapApiError(`Raw upload failed: ${response.status}`, response.status, await response.text());
|
|
306
306
|
const result = await response.json();
|
|
307
|
-
|
|
307
|
+
outerSignal.throwIfAborted();
|
|
308
308
|
if (!isRecord(result) || result.accountId !== accountId || typeof result.blobId !== "string" || !result.blobId || result.size !== size) throw new JmapApiError("Invalid raw upload response.");
|
|
309
309
|
return {
|
|
310
310
|
accountId,
|
|
@@ -315,7 +315,6 @@ async function uploadRawMessage(config, uploadUrl, accountId, plan, signal) {
|
|
|
315
315
|
} catch (error) {
|
|
316
316
|
outerSignal.throwIfAborted();
|
|
317
317
|
if (hasSourceError) throw sourceError;
|
|
318
|
-
owned.throwIfAborted();
|
|
319
318
|
throw error;
|
|
320
319
|
} finally {
|
|
321
320
|
owned.removeEventListener("abort", abort);
|
|
@@ -332,11 +331,17 @@ const using = [
|
|
|
332
331
|
"urn:ietf:params:jmap:mail",
|
|
333
332
|
"urn:ietf:params:jmap:submission"
|
|
334
333
|
];
|
|
335
|
-
function failure(message, stage, retryable, unknown = false) {
|
|
334
|
+
function failure(message, stage, retryable, unknown = false, error) {
|
|
336
335
|
return createFailedReceipt(message, {
|
|
337
336
|
provider: "jmap",
|
|
338
337
|
code: `jmap.raw_${stage}_${unknown ? "unknown" : "failed"}`,
|
|
339
|
-
category: unknown ? "unknown" : retryable ? void 0 : "rejected",
|
|
338
|
+
category: unknown ? "unknown" : error?.statusCode !== void 0 || retryable ? void 0 : "rejected",
|
|
339
|
+
statusCode: error?.statusCode,
|
|
340
|
+
retryAfterMilliseconds: error?.retryAfterMilliseconds,
|
|
341
|
+
providerDetails: error ? {
|
|
342
|
+
responseBody: error.responseBody,
|
|
343
|
+
jmapErrorType: error.jmapErrorType
|
|
344
|
+
} : void 0,
|
|
340
345
|
retryable,
|
|
341
346
|
attempts: 1
|
|
342
347
|
});
|
|
@@ -367,7 +372,9 @@ function errorDescription(error) {
|
|
|
367
372
|
return `Raw JMAP operation rejected: ${String(error.type)}${typeof error.description === "string" ? `: ${error.description}` : ""}`;
|
|
368
373
|
}
|
|
369
374
|
function isRequestRejection(error) {
|
|
370
|
-
if (!(error instanceof JmapApiError)
|
|
375
|
+
if (!(error instanceof JmapApiError)) return false;
|
|
376
|
+
if (error.statusCode === 401 || error.statusCode === 403) return true;
|
|
377
|
+
if (!error.responseBody || error.statusCode === void 0 || error.statusCode < 400 || error.statusCode > 599) return false;
|
|
371
378
|
try {
|
|
372
379
|
const body = JSON.parse(error.responseBody);
|
|
373
380
|
if (!isRecord(body) || body.status !== void 0 && body.status !== error.statusCode) return false;
|
|
@@ -465,7 +472,7 @@ async function deliverRawMessage(config, session, accountId, draftsMailboxId, id
|
|
|
465
472
|
attempts: 1
|
|
466
473
|
});
|
|
467
474
|
const definite = isRequestRejection(error);
|
|
468
|
-
return failure(message, stage, stage !== "submission" && !definite, stage === "submission" && !definite);
|
|
475
|
+
return failure(message, stage, stage !== "submission" && !definite, stage === "submission" && !definite, error instanceof JmapApiError ? error : void 0);
|
|
469
476
|
}
|
|
470
477
|
}
|
|
471
478
|
/** Validates raw discovery responses before accepting delivery identifiers. @internal */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upyo/jmap",
|
|
3
|
-
"version": "0.6.0-dev.
|
|
3
|
+
"version": "0.6.0-dev.354",
|
|
4
4
|
"description": "JMAP transport for Upyo email library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"email",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"sideEffects": false,
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@upyo/core": "0.6.0-dev.
|
|
56
|
+
"@upyo/core": "0.6.0-dev.354+3493c572"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"jmap-rfc-types": "^0.1.2",
|