primcli 1.74.1 → 1.75.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/README.md +49 -9
- package/dist/{api-command-fKP3NYa7.js → api-command-rlS3eTlZ.js} +77 -43
- package/dist/{cli-config-C0Y_Ppol.js → cli-config-B80p0pLk.js} +7 -12
- package/dist/{client.gen-CaaMP86o.js → client.gen-6rZvmHfx.js} +7 -14
- package/dist/{json-output-Ce10AsSb.js → json-output-BzSBR-KX.js} +1 -2
- package/dist/{listen-background-cD6n8VYO.js → listen-background-C0F9gNDD.js} +2 -3
- package/dist/{machine-session-B6V5-grn.js → machine-session-Cq_nD5eF.js} +144 -92
- package/dist/{notify-session-DJAb9SGm.js → notify-session-CbY4FYUt.js} +10 -30
- package/dist/oclif/auto-signal-worker.js +5 -6
- package/dist/oclif/auto-signals.js +3 -4
- package/dist/oclif/help.js +127 -0
- package/dist/oclif/index.js +414 -344
- package/dist/oclif/listen-supervisor.js +1 -1
- package/dist/oclif/proxy-auto-detect.js +2 -3
- package/dist/oclif/receiver-heal.js +6 -6
- package/dist/oclif/root-signup-hint.js +2 -3
- package/dist/{repeats-BL7ZC-_6-B_ESsWTH.js → repeats-Dj_o6c-X-LyCkKYjp.js} +552 -213
- package/dist/{scoped-chat-DAiOb622.js → scoped-chat-B0thCwME.js} +3 -5
- package/dist/{shared-mail-files-CZfm7E2k.js → shared-mail-files-BAQSGxxz.js} +2 -4
- package/dist/{shared-mail-watch-DyQB0MK0.js → shared-mail-watch-BAPMsFNv.js} +2 -3
- package/dist/{signal-command-Cte4mAL3.js → signal-command-DCPsJBdz.js} +14 -23
- package/dist/skills/primitive-connect/references/connect.md +3 -1
- package/dist/skills/primitive-connect/references/contacts.md +9 -4
- package/dist/skills/primitive-connect.json +4 -4
- package/man/primitive.1 +10 -3
- package/package.json +14 -9
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as createConfig, t as createClient } from "./client.gen-
|
|
2
|
-
|
|
1
|
+
import { n as createConfig, t as createClient } from "./client.gen-6rZvmHfx.js";
|
|
2
|
+
// \0rolldown/runtime.js
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -30,11 +30,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
value: mod,
|
|
31
31
|
enumerable: true
|
|
32
32
|
}) : target, mod));
|
|
33
|
-
|
|
34
|
-
//#region ../packages/api-core/src/api/client.gen.ts
|
|
33
|
+
// ../packages/api-core/src/api/client.gen.ts
|
|
35
34
|
const client = createClient(createConfig({ baseUrl: "https://api.primitive.dev/v1" }));
|
|
36
|
-
|
|
37
|
-
//#region ../packages/api-core/src/api/sdk.gen.ts
|
|
35
|
+
// ../packages/api-core/src/api/sdk.gen.ts
|
|
38
36
|
var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
39
37
|
addDefaultNetworkMember: () => addDefaultNetworkMember,
|
|
40
38
|
addDomain: () => addDomain,
|
|
@@ -3464,8 +3462,7 @@ const provisionMemberAddress = (options) => (options.client ?? client).put({
|
|
|
3464
3462
|
...options.headers
|
|
3465
3463
|
}
|
|
3466
3464
|
});
|
|
3467
|
-
|
|
3468
|
-
//#region src/oclif/automated-filter.ts
|
|
3465
|
+
// src/oclif/automated-filter.ts
|
|
3469
3466
|
/**
|
|
3470
3467
|
* The server-side `automated` verdict on inbound email: `automated`
|
|
3471
3468
|
* (boolean) and `automated_reasons` (why, in rule order), decided by
|
|
@@ -3611,8 +3608,98 @@ function ensureSearchReportsAutomated(apiClient) {
|
|
|
3611
3608
|
}
|
|
3612
3609
|
return probe;
|
|
3613
3610
|
}
|
|
3614
|
-
|
|
3615
|
-
|
|
3611
|
+
// ../node_modules/.pnpm/nodemailer@10.3.1/node_modules/nodemailer/dist/esm/addressparser/index.js
|
|
3612
|
+
/** The token is an operator, a text run otherwise */
|
|
3613
|
+
const TOKEN_OPERATOR = 1;
|
|
3614
|
+
/** The next character continues the same run without whitespace in between */
|
|
3615
|
+
const TOKEN_NO_BREAK = 2;
|
|
3616
|
+
/** The text run holds characters its value leaves out or changes, so it is no plain slice */
|
|
3617
|
+
const TOKEN_DIRTY = 4;
|
|
3618
|
+
/** A backslash escapes the next character in the text run, inside a quoted string or a comment */
|
|
3619
|
+
const TOKEN_ESCAPES = 8;
|
|
3620
|
+
/** The text run opens on a character an escaping backslash in front of it has escaped */
|
|
3621
|
+
const TOKEN_STARTS_ESCAPED = 16;
|
|
3622
|
+
/**
|
|
3623
|
+
* The tokens of an address field, kept as offsets into it.
|
|
3624
|
+
*
|
|
3625
|
+
* Every token used to be an object of its own, an operator for every ',' and a value string
|
|
3626
|
+
* for every run of text, and a list of one letter names, 'a,a,a,...', took some 65 times its
|
|
3627
|
+
* size in tokens before any address was read. A token is now three numbers in one typed
|
|
3628
|
+
* array, its kind and the range of the field it covers, and its value is sliced off the field
|
|
3629
|
+
* when it is read. The few text runs whose value differs from their slice, as they hold an
|
|
3630
|
+
* escaping backslash, a line break or a control character, are rebuilt once and kept aside.
|
|
3631
|
+
*/
|
|
3632
|
+
var TokenList = class {
|
|
3633
|
+
constructor(str) {
|
|
3634
|
+
this.str = str;
|
|
3635
|
+
this.slots = /* @__PURE__ */ new Int32Array(48);
|
|
3636
|
+
this.length = 0;
|
|
3637
|
+
this.cleaned = /* @__PURE__ */ new Map();
|
|
3638
|
+
}
|
|
3639
|
+
/**
|
|
3640
|
+
* Appends a token
|
|
3641
|
+
*
|
|
3642
|
+
* @param kind Kind and flags of the token
|
|
3643
|
+
* @param start Offset of its first character
|
|
3644
|
+
* @param end Offset just past its last character
|
|
3645
|
+
* @return Index of the token
|
|
3646
|
+
*/
|
|
3647
|
+
push(kind, start, end) {
|
|
3648
|
+
if ((this.length + 1) * 3 > this.slots.length) {
|
|
3649
|
+
const grown = new Int32Array(this.slots.length * 2);
|
|
3650
|
+
grown.set(this.slots);
|
|
3651
|
+
this.slots = grown;
|
|
3652
|
+
}
|
|
3653
|
+
const at = this.length * 3;
|
|
3654
|
+
this.slots[at] = kind;
|
|
3655
|
+
this.slots[at + 1] = start;
|
|
3656
|
+
this.slots[at + 2] = end;
|
|
3657
|
+
return this.length++;
|
|
3658
|
+
}
|
|
3659
|
+
/**
|
|
3660
|
+
* The character of an operator token, an empty string for a text run
|
|
3661
|
+
*/
|
|
3662
|
+
operatorAt(index) {
|
|
3663
|
+
const at = index * 3;
|
|
3664
|
+
return this.slots[at] & TOKEN_OPERATOR ? this.str.charAt(this.slots[at + 1]) : "";
|
|
3665
|
+
}
|
|
3666
|
+
/**
|
|
3667
|
+
* Whether a token is an operator
|
|
3668
|
+
*/
|
|
3669
|
+
isOperator(index) {
|
|
3670
|
+
return (this.slots[index * 3] & TOKEN_OPERATOR) !== 0;
|
|
3671
|
+
}
|
|
3672
|
+
/**
|
|
3673
|
+
* Whether the next character continues the run of a token without whitespace in between
|
|
3674
|
+
*/
|
|
3675
|
+
noBreak(index) {
|
|
3676
|
+
return (this.slots[index * 3] & TOKEN_NO_BREAK) !== 0;
|
|
3677
|
+
}
|
|
3678
|
+
/**
|
|
3679
|
+
* Value of a token
|
|
3680
|
+
*/
|
|
3681
|
+
value(index) {
|
|
3682
|
+
const cleaned = this.cleaned.get(index);
|
|
3683
|
+
if (cleaned !== void 0) return cleaned;
|
|
3684
|
+
return this.str.slice(this.slots[index * 3 + 1], this.slots[index * 3 + 2]);
|
|
3685
|
+
}
|
|
3686
|
+
};
|
|
3687
|
+
/**
|
|
3688
|
+
* A domain literal that ends an address. dtext includes '@' (RFC 5322 3.4.1), so the '@'
|
|
3689
|
+
* in front of the literal is the one that splits the domain off, not the last one: reading
|
|
3690
|
+
* 'a@[x@evil.com]' at its last '@' made it an address at evil.com.
|
|
3691
|
+
*/
|
|
3692
|
+
const DOMAIN_LITERAL_TAIL = /@(\[[^[\]\\]*\])$/;
|
|
3693
|
+
/**
|
|
3694
|
+
* Offset of the '@' that splits the domain off an address, or -1 when there is none
|
|
3695
|
+
*
|
|
3696
|
+
* @param address Address to split
|
|
3697
|
+
* @return Offset of the '@'
|
|
3698
|
+
*/
|
|
3699
|
+
function _domainAt(address) {
|
|
3700
|
+
const literal = address.charAt(address.length - 1) === "]" ? DOMAIN_LITERAL_TAIL.exec(address) : null;
|
|
3701
|
+
return literal ? address.length - literal[1].length - 1 : address.lastIndexOf("@");
|
|
3702
|
+
}
|
|
3616
3703
|
/**
|
|
3617
3704
|
* Restores the quoting of a local part that was read out of a quoted string.
|
|
3618
3705
|
*
|
|
@@ -3631,7 +3718,7 @@ function ensureSearchReportsAutomated(apiClient) {
|
|
|
3631
3718
|
* @return Address with the local part as a quoted-string
|
|
3632
3719
|
*/
|
|
3633
3720
|
function _quoteLocalPart(address) {
|
|
3634
|
-
const lastAt = address
|
|
3721
|
+
const lastAt = _domainAt(address);
|
|
3635
3722
|
if (lastAt < 0) return address;
|
|
3636
3723
|
const user = address.substr(0, lastAt);
|
|
3637
3724
|
if (/^[^\s"(),:;<>@[\\\]]+$/.test(user) || /^"(?:[^"\\]|\\[\s\S])*"$/.test(user)) return address;
|
|
@@ -3651,6 +3738,23 @@ const QUOTED_LOCAL_ADDR = /^("(?:[^"\\]|\\[\s\S])*"@\S+)(?:\s+([\s\S]+))?$/;
|
|
|
3651
3738
|
*/
|
|
3652
3739
|
const ADDR_SPEC = /^[^@\s]+@[^@\s]+$/;
|
|
3653
3740
|
/**
|
|
3741
|
+
* The same with a domain literal for the domain, which may hold an '@' of its own.
|
|
3742
|
+
*/
|
|
3743
|
+
const LITERAL_ADDR_SPEC = /^[^@\s]+@\[[^[\]\\\s]*\]$/;
|
|
3744
|
+
/**
|
|
3745
|
+
* The '@' and domain that follow a quoted local part in the same run.
|
|
3746
|
+
*/
|
|
3747
|
+
const QUOTED_LOCAL_DOMAIN = /^@(?:[^@\s"]+|\[[^[\]\\\s]*\])$/;
|
|
3748
|
+
/**
|
|
3749
|
+
* Whether a whitespace free run reads as an addr-spec under the strict grammar
|
|
3750
|
+
*
|
|
3751
|
+
* @param value Run to check
|
|
3752
|
+
* @return true when it does
|
|
3753
|
+
*/
|
|
3754
|
+
function _isAddrSpec(value) {
|
|
3755
|
+
return ADDR_SPEC.test(value) || LITERAL_ADDR_SPEC.test(value);
|
|
3756
|
+
}
|
|
3757
|
+
/**
|
|
3654
3758
|
* The looser reading applied once the strict one finds nothing, which tolerates the
|
|
3655
3759
|
* further '@' that a domain should not have but malformed headers carry anyway.
|
|
3656
3760
|
*/
|
|
@@ -3703,6 +3807,50 @@ function _indexOfAt(text, from, to) {
|
|
|
3703
3807
|
return -1;
|
|
3704
3808
|
}
|
|
3705
3809
|
/**
|
|
3810
|
+
* A quoted-string a value opens with.
|
|
3811
|
+
*/
|
|
3812
|
+
const LEADING_QUOTED_STRING = /^"(?:[^"\\]|\\[\s\S])*"/;
|
|
3813
|
+
/**
|
|
3814
|
+
* Drops the whitespace on either side of the '@' at an offset.
|
|
3815
|
+
*
|
|
3816
|
+
* obs-local-part and obs-domain allow CFWS around the '@' (RFC 5322 4.4), so 'user @ good.com'
|
|
3817
|
+
* names user@good.com. Kept, the whitespace went into the envelope as '"user "@ good.com'.
|
|
3818
|
+
* The scan is by index, a pattern such as /\s+@/ backtracks over a long whitespace run that
|
|
3819
|
+
* no '@' follows.
|
|
3820
|
+
*
|
|
3821
|
+
* @param value Value holding the '@'
|
|
3822
|
+
* @param at Offset of the '@', or -1
|
|
3823
|
+
* @return The value with the whitespace beside that '@' removed
|
|
3824
|
+
*/
|
|
3825
|
+
function _joinAtSpacing(value, at) {
|
|
3826
|
+
if (at < 0) return value;
|
|
3827
|
+
let start = at;
|
|
3828
|
+
while (start > 0 && _isSpaceCode(value.charCodeAt(start - 1))) start--;
|
|
3829
|
+
let end = at + 1;
|
|
3830
|
+
while (end < value.length && _isSpaceCode(value.charCodeAt(end))) end++;
|
|
3831
|
+
return start === at && end === at + 1 ? value : value.slice(0, start) + "@" + value.slice(end);
|
|
3832
|
+
}
|
|
3833
|
+
/**
|
|
3834
|
+
* Drops the whitespace beside the '@' that splits the domain off a value. That is the '@'
|
|
3835
|
+
* right after a quoted local part the value opens with, or else the only '@' it holds outside
|
|
3836
|
+
* any quoted string. With several it is not clear which one the whitespace belongs to, and
|
|
3837
|
+
* '<x@evil.com @good.com>' is left to the addr-spec recovery to read as it always has.
|
|
3838
|
+
*
|
|
3839
|
+
* @param value Value to clean up
|
|
3840
|
+
* @return The value with the whitespace beside that '@' removed
|
|
3841
|
+
*/
|
|
3842
|
+
function _collapseAtSpacing(value) {
|
|
3843
|
+
const quoted = LEADING_QUOTED_STRING.exec(value);
|
|
3844
|
+
if (quoted) {
|
|
3845
|
+
let at = quoted[0].length;
|
|
3846
|
+
while (at < value.length && _isSpaceCode(value.charCodeAt(at))) at++;
|
|
3847
|
+
if (value.charAt(at) === "@" && value.indexOf("@", at + 1) < 0) return _joinAtSpacing(value, at);
|
|
3848
|
+
}
|
|
3849
|
+
const at = value.indexOf("@");
|
|
3850
|
+
if (at < 0 || value.indexOf("@", at + 1) >= 0 || value.lastIndexOf("\"") > at) return value;
|
|
3851
|
+
return _joinAtSpacing(value, at);
|
|
3852
|
+
}
|
|
3853
|
+
/**
|
|
3706
3854
|
* Finds the offset LOOSE_TEXT_ADDR matches at, or -1 when it does not match at all.
|
|
3707
3855
|
*
|
|
3708
3856
|
* Letting the pattern search for itself is quadratic: '[^@\s]+' is retried from every
|
|
@@ -3773,6 +3921,7 @@ function _looseAddressStart(text) {
|
|
|
3773
3921
|
* @param data Collected address parts, mutated in place
|
|
3774
3922
|
*/
|
|
3775
3923
|
function _recoverAddrSpec(data) {
|
|
3924
|
+
data.address = _collapseAtSpacing(data.address);
|
|
3776
3925
|
if (!HAS_WHITESPACE.test(data.address)) return;
|
|
3777
3926
|
let address;
|
|
3778
3927
|
let rest;
|
|
@@ -3784,7 +3933,7 @@ function _recoverAddrSpec(data) {
|
|
|
3784
3933
|
} else {
|
|
3785
3934
|
if (data.address.indexOf("\"") >= 0) return;
|
|
3786
3935
|
const parts = data.address.split(/\s+/);
|
|
3787
|
-
let addrIndex = parts.findIndex(
|
|
3936
|
+
let addrIndex = parts.findIndex(_isAddrSpec);
|
|
3788
3937
|
if (addrIndex < 0) addrIndex = parts.findIndex((part) => LOOSE_ADDR_SPEC.test(part));
|
|
3789
3938
|
if (addrIndex < 0) return;
|
|
3790
3939
|
address = parts.splice(addrIndex, 1)[0];
|
|
@@ -3803,6 +3952,15 @@ function _recoverAddrSpec(data) {
|
|
|
3803
3952
|
* A comment is folding whitespace, so it is read as a space that splits two atoms and as
|
|
3804
3953
|
* nothing next to an '@', the same rule the token walk applies outside the brackets. Quoted
|
|
3805
3954
|
* strings and domain literals are copied through untouched, a '(' in there is not a comment.
|
|
3955
|
+
* An unexpected '<' outside them drops everything in front of it, comments included.
|
|
3956
|
+
*
|
|
3957
|
+
* RFC 822 also let an angle-addr name the relays to go through in front of the mailbox,
|
|
3958
|
+
* '<@relay1,@relay2:user@example.com>', which RFC 5322 still parses as obs-route. The route
|
|
3959
|
+
* is not part of the mailbox, and folded into the local part it made
|
|
3960
|
+
* '"@relay1,@relay2:user"@example.com' a recipient that does not exist. A local part can not
|
|
3961
|
+
* start with '@', so contents that do, up to the first ':' outside a domain literal and in
|
|
3962
|
+
* front of any quoted string, are a route and are dropped, as long as a mailbox with an '@'
|
|
3963
|
+
* of its own follows.
|
|
3806
3964
|
*
|
|
3807
3965
|
* @param address Contents of the angle brackets
|
|
3808
3966
|
* @return The address with the comments removed, and the text of the comments
|
|
@@ -3814,6 +3972,10 @@ function _stripAddressComments(address) {
|
|
|
3814
3972
|
let depth = 0;
|
|
3815
3973
|
let closer = "";
|
|
3816
3974
|
let lastChar = "";
|
|
3975
|
+
let pendingSpace = false;
|
|
3976
|
+
let firstChar = "";
|
|
3977
|
+
let quoteSeen = false;
|
|
3978
|
+
let routeEnd = -1;
|
|
3817
3979
|
for (let i = 0, len = address.length; i < len; i++) {
|
|
3818
3980
|
const chr = address.charAt(i);
|
|
3819
3981
|
if (depth) {
|
|
@@ -3824,13 +3986,17 @@ function _stripAddressComments(address) {
|
|
|
3824
3986
|
} else if (chr === ")" && !--depth) {
|
|
3825
3987
|
comments.push(comment.trim());
|
|
3826
3988
|
comment = "";
|
|
3827
|
-
|
|
3828
|
-
result += " ";
|
|
3829
|
-
lastChar = " ";
|
|
3830
|
-
}
|
|
3989
|
+
pendingSpace = lastChar !== "@";
|
|
3831
3990
|
} else comment += chr;
|
|
3832
3991
|
continue;
|
|
3833
3992
|
}
|
|
3993
|
+
if (pendingSpace && chr !== "(") {
|
|
3994
|
+
pendingSpace = false;
|
|
3995
|
+
if (chr !== "@" && chr !== "<" && !_isSpaceCode(address.charCodeAt(i))) {
|
|
3996
|
+
result += " ";
|
|
3997
|
+
lastChar = " ";
|
|
3998
|
+
}
|
|
3999
|
+
}
|
|
3834
4000
|
if (closer) {
|
|
3835
4001
|
if (chr === "\\" && closer === "\"" && i < len - 1) {
|
|
3836
4002
|
result += chr + address.charAt(++i);
|
|
@@ -3838,15 +4004,28 @@ function _stripAddressComments(address) {
|
|
|
3838
4004
|
continue;
|
|
3839
4005
|
}
|
|
3840
4006
|
if (chr === closer) closer = "";
|
|
3841
|
-
} else if (chr === "\"")
|
|
4007
|
+
} else if (chr === "\"") {
|
|
4008
|
+
closer = "\"";
|
|
4009
|
+
quoteSeen = true;
|
|
4010
|
+
} else if (chr === ":" && routeEnd < 0 && firstChar === "@" && !quoteSeen) routeEnd = result.length + 1;
|
|
3842
4011
|
else if (chr === "[") closer = "]";
|
|
3843
4012
|
else if (chr === "(") {
|
|
3844
4013
|
depth = 1;
|
|
3845
4014
|
continue;
|
|
4015
|
+
} else if (chr === "<") {
|
|
4016
|
+
result = "";
|
|
4017
|
+
lastChar = "";
|
|
4018
|
+
comments.length = 0;
|
|
4019
|
+
firstChar = "";
|
|
4020
|
+
quoteSeen = false;
|
|
4021
|
+
routeEnd = -1;
|
|
4022
|
+
continue;
|
|
3846
4023
|
}
|
|
3847
4024
|
result += chr;
|
|
3848
4025
|
lastChar = chr;
|
|
4026
|
+
if (!firstChar && !_isSpaceCode(address.charCodeAt(i))) firstChar = chr;
|
|
3849
4027
|
}
|
|
4028
|
+
if (routeEnd >= 0 && result.indexOf("@", routeEnd) >= 0) result = result.slice(routeEnd);
|
|
3850
4029
|
if (depth) comments.push(comment.trim());
|
|
3851
4030
|
return {
|
|
3852
4031
|
address: result.trim(),
|
|
@@ -3854,34 +4033,35 @@ function _stripAddressComments(address) {
|
|
|
3854
4033
|
};
|
|
3855
4034
|
}
|
|
3856
4035
|
/**
|
|
3857
|
-
*
|
|
4036
|
+
* Walks the tokens of one entry of an address list and sorts them into the runs of display
|
|
4037
|
+
* text, angle-addr and comment they belong to
|
|
3858
4038
|
*
|
|
3859
|
-
* @param tokens Tokens
|
|
3860
|
-
* @param
|
|
3861
|
-
* @
|
|
4039
|
+
* @param tokens Tokens of the whole address list
|
|
4040
|
+
* @param from Index of the first token of the entry
|
|
4041
|
+
* @param to Index just past the last token of the entry
|
|
4042
|
+
* @return The collected runs, and whether the display text came out of a comment
|
|
3862
4043
|
*/
|
|
3863
|
-
function
|
|
3864
|
-
let isGroup = false;
|
|
4044
|
+
function _collectAddressParts(tokens, from, to) {
|
|
3865
4045
|
let state = "text";
|
|
3866
|
-
const addresses = [];
|
|
3867
4046
|
const data = {
|
|
3868
4047
|
address: [],
|
|
3869
4048
|
comment: [],
|
|
3870
|
-
group: [],
|
|
3871
4049
|
text: [],
|
|
3872
|
-
textWasQuoted: []
|
|
4050
|
+
textWasQuoted: [],
|
|
4051
|
+
quotedLocalAt: []
|
|
3873
4052
|
};
|
|
3874
4053
|
let insideQuotes = false;
|
|
4054
|
+
let lastTextPureQuoted = false;
|
|
3875
4055
|
const lastChars = {
|
|
3876
4056
|
address: "",
|
|
3877
4057
|
comment: "",
|
|
3878
|
-
group: "",
|
|
3879
4058
|
text: ""
|
|
3880
4059
|
};
|
|
3881
|
-
for (let i =
|
|
3882
|
-
const
|
|
3883
|
-
const
|
|
3884
|
-
|
|
4060
|
+
for (let i = from; i < to; i++) {
|
|
4061
|
+
const value = tokens.value(i);
|
|
4062
|
+
const prevOperator = i > from ? tokens.operatorAt(i - 1) : "";
|
|
4063
|
+
const prevNoBreak = i > from && tokens.noBreak(i - 1);
|
|
4064
|
+
if (tokens.isOperator(i)) switch (value) {
|
|
3885
4065
|
case "<":
|
|
3886
4066
|
state = "address";
|
|
3887
4067
|
insideQuotes = false;
|
|
@@ -3890,11 +4070,6 @@ function _handleAddress(tokens, depth) {
|
|
|
3890
4070
|
state = "comment";
|
|
3891
4071
|
insideQuotes = false;
|
|
3892
4072
|
break;
|
|
3893
|
-
case ":":
|
|
3894
|
-
state = "group";
|
|
3895
|
-
isGroup = true;
|
|
3896
|
-
insideQuotes = false;
|
|
3897
|
-
break;
|
|
3898
4073
|
case "\"":
|
|
3899
4074
|
insideQuotes = !insideQuotes;
|
|
3900
4075
|
state = "text";
|
|
@@ -3903,101 +4078,131 @@ function _handleAddress(tokens, depth) {
|
|
|
3903
4078
|
state = "text";
|
|
3904
4079
|
insideQuotes = false;
|
|
3905
4080
|
}
|
|
3906
|
-
else
|
|
3907
|
-
const
|
|
3908
|
-
const opensAfterEmptyQuotedString = prevToken?.type === "operator" && prevToken.value === "\"" && !!prevToken.noBreak && prevPrevToken?.type === "operator" && prevPrevToken.value === "\"";
|
|
3909
|
-
if (state === "address") token.value = token.value.replace(/^[^<]*<\s*/, "");
|
|
4081
|
+
else {
|
|
4082
|
+
const opensAfterEmptyQuotedString = prevOperator === "\"" && prevNoBreak && i > from + 1 && tokens.operatorAt(i - 2) === "\"";
|
|
3910
4083
|
const parts = data[state];
|
|
3911
|
-
if (
|
|
3912
|
-
data[state]
|
|
3913
|
-
if (
|
|
3914
|
-
|
|
4084
|
+
if (prevNoBreak && parts.length && (prevOperator !== ")" || lastChars[state] === "@" || value.charAt(0) === "@")) {
|
|
4085
|
+
const last = data[state].length - 1;
|
|
4086
|
+
if (state === "text" && !insideQuotes) {
|
|
4087
|
+
if (lastTextPureQuoted && value.charAt(0) === "@") data.quotedLocalAt[last] = data.text[last].length;
|
|
4088
|
+
lastTextPureQuoted = false;
|
|
4089
|
+
}
|
|
4090
|
+
data[state][last] += value;
|
|
4091
|
+
lastChars[state] = value.charAt(value.length - 1);
|
|
4092
|
+
if (state === "text" && insideQuotes) data.textWasQuoted[last] = true;
|
|
3915
4093
|
} else {
|
|
3916
|
-
data[state].push(
|
|
3917
|
-
lastChars[state] =
|
|
3918
|
-
if (state === "text")
|
|
4094
|
+
data[state].push(value);
|
|
4095
|
+
lastChars[state] = value.charAt(value.length - 1);
|
|
4096
|
+
if (state === "text") {
|
|
4097
|
+
data.textWasQuoted.push(insideQuotes || opensAfterEmptyQuotedString);
|
|
4098
|
+
data.quotedLocalAt.push(opensAfterEmptyQuotedString && value.charAt(0) === "@" ? 0 : -1);
|
|
4099
|
+
lastTextPureQuoted = insideQuotes;
|
|
4100
|
+
}
|
|
3919
4101
|
}
|
|
3920
4102
|
}
|
|
3921
4103
|
}
|
|
4104
|
+
let textFromComment = false;
|
|
3922
4105
|
if (!data.text.length && data.comment.length) {
|
|
3923
4106
|
data.text = data.comment;
|
|
3924
4107
|
data.comment = [];
|
|
4108
|
+
textFromComment = true;
|
|
3925
4109
|
}
|
|
3926
|
-
|
|
3927
|
-
data
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
4110
|
+
return {
|
|
4111
|
+
data,
|
|
4112
|
+
textFromComment
|
|
4113
|
+
};
|
|
4114
|
+
}
|
|
4115
|
+
/**
|
|
4116
|
+
* Name of a group, from the tokens in front of its ':'. A comment names it when no text does,
|
|
4117
|
+
* as it names a mailbox.
|
|
4118
|
+
*
|
|
4119
|
+
* @param tokens Tokens of the whole address list
|
|
4120
|
+
* @param from Index of the first token in front of the ':'
|
|
4121
|
+
* @param to Index of the ':'
|
|
4122
|
+
* @return Name of the group
|
|
4123
|
+
*/
|
|
4124
|
+
function _groupName(tokens, from, to) {
|
|
4125
|
+
return _collectAddressParts(tokens, from, to).data.text.join(" ");
|
|
4126
|
+
}
|
|
4127
|
+
/**
|
|
4128
|
+
* Converts tokens for a single address into an address object
|
|
4129
|
+
*
|
|
4130
|
+
* @param tokens Tokens of the whole address list
|
|
4131
|
+
* @param from Index of the first token of this address
|
|
4132
|
+
* @param to Index just past the last token of this address
|
|
4133
|
+
* @return Address object
|
|
4134
|
+
*/
|
|
4135
|
+
function _handleAddress(tokens, from, to) {
|
|
4136
|
+
const collected = _collectAddressParts(tokens, from, to);
|
|
4137
|
+
const data = collected.data;
|
|
4138
|
+
let textFromComment = collected.textFromComment;
|
|
4139
|
+
const addressComments = [];
|
|
4140
|
+
const addressParts = [];
|
|
4141
|
+
for (const part of data.address) {
|
|
4142
|
+
const stripped = _stripAddressComments(part);
|
|
4143
|
+
for (const comment of stripped.comments) addressComments.push(comment);
|
|
4144
|
+
if (stripped.address) addressParts.push(stripped.address);
|
|
4145
|
+
}
|
|
4146
|
+
data.address = addressParts;
|
|
4147
|
+
if (!data.address.length && data.text.length && !textFromComment) {
|
|
4148
|
+
const candidates = data.text.map((part) => _collapseAtSpacing(part));
|
|
4149
|
+
for (let i = 0; i < data.text.length; i++) {
|
|
4150
|
+
const local = data.quotedLocalAt[i];
|
|
4151
|
+
const quotedLocal = data.textWasQuoted[i] && local >= 0 && QUOTED_LOCAL_DOMAIN.test(data.text[i].slice(local)) ? _quoteLocalPart(data.text[i]) : "";
|
|
4152
|
+
if (quotedLocal || !data.textWasQuoted[i] && _isAddrSpec(candidates[i])) {
|
|
4153
|
+
data.address = [quotedLocal || candidates[i]];
|
|
4154
|
+
data.text.splice(i, 1);
|
|
3953
4155
|
data.textWasQuoted.splice(i, 1);
|
|
4156
|
+
data.quotedLocalAt.splice(i, 1);
|
|
3954
4157
|
break;
|
|
3955
4158
|
}
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
4159
|
+
}
|
|
4160
|
+
if (!data.address.length) {
|
|
4161
|
+
let extracted = false;
|
|
4162
|
+
for (let i = 0; i < data.text.length; i++) if (!data.textWasQuoted[i]) {
|
|
4163
|
+
const part = candidates[i];
|
|
4164
|
+
let remainder = data.text[i];
|
|
4165
|
+
const at = _looseAddressStart(part);
|
|
4166
|
+
if (at >= 0) {
|
|
4167
|
+
LOOSE_TEXT_ADDR.lastIndex = at;
|
|
4168
|
+
const match = LOOSE_TEXT_ADDR.exec(part);
|
|
4169
|
+
if (match) {
|
|
4170
|
+
data.address = [match[0].trim()];
|
|
4171
|
+
extracted = true;
|
|
4172
|
+
remainder = part.slice(0, at) + " " + part.slice(at + match[0].length);
|
|
3970
4173
|
}
|
|
3971
|
-
data.text[i] = remainder.trim();
|
|
3972
|
-
if (extracted) break;
|
|
3973
4174
|
}
|
|
4175
|
+
data.text[i] = remainder.trim();
|
|
4176
|
+
if (extracted) break;
|
|
3974
4177
|
}
|
|
3975
4178
|
}
|
|
3976
|
-
if (!data.text.length && data.comment.length) {
|
|
3977
|
-
data.text = data.comment;
|
|
3978
|
-
data.comment = [];
|
|
3979
|
-
}
|
|
3980
|
-
if (data.address.length > 1) data.text = data.text.concat(data.address.splice(1));
|
|
3981
|
-
const addressFromQuotedText = !data.address.length && data.textWasQuoted.some((wasQuoted) => wasQuoted);
|
|
3982
|
-
data.text = data.text.join(" ");
|
|
3983
|
-
data.address = data.address.join(" ");
|
|
3984
|
-
if (addressFromQuotedText && data.text.indexOf("@") >= 0) {
|
|
3985
|
-
data.address = _quoteLocalPart(data.text);
|
|
3986
|
-
data.text = "";
|
|
3987
|
-
}
|
|
3988
|
-
_recoverAddrSpec(data);
|
|
3989
|
-
if (!data.text && addressComments.length) data.text = addressComments.join(" ");
|
|
3990
|
-
const address = {
|
|
3991
|
-
address: data.address || data.text || "",
|
|
3992
|
-
name: data.text || data.address || ""
|
|
3993
|
-
};
|
|
3994
|
-
if (address.address === address.name) {
|
|
3995
|
-
if (/@/.test(address.address || "")) address.name = "";
|
|
3996
|
-
else address.address = "";
|
|
3997
|
-
}
|
|
3998
|
-
addresses.push(address);
|
|
3999
4179
|
}
|
|
4000
|
-
|
|
4180
|
+
if (!data.text.length && data.comment.length) {
|
|
4181
|
+
data.text = data.comment;
|
|
4182
|
+
data.comment = [];
|
|
4183
|
+
}
|
|
4184
|
+
if (data.address.length > 1) data.text = data.text.concat(data.address.splice(1));
|
|
4185
|
+
const addressFromQuotedText = !data.address.length && data.textWasQuoted.some((wasQuoted) => wasQuoted);
|
|
4186
|
+
data.text = data.text.join(" ");
|
|
4187
|
+
data.address = data.address.join(" ");
|
|
4188
|
+
if (addressFromQuotedText && data.text.indexOf("@") >= 0) {
|
|
4189
|
+
data.address = _quoteLocalPart(_joinAtSpacing(data.text, _domainAt(data.text)));
|
|
4190
|
+
data.text = "";
|
|
4191
|
+
}
|
|
4192
|
+
_recoverAddrSpec(data);
|
|
4193
|
+
if (!data.text && addressComments.length) {
|
|
4194
|
+
data.text = addressComments.join(" ");
|
|
4195
|
+
textFromComment = true;
|
|
4196
|
+
}
|
|
4197
|
+
const address = {
|
|
4198
|
+
address: data.address || (textFromComment ? "" : data.text) || "",
|
|
4199
|
+
name: data.text || data.address || ""
|
|
4200
|
+
};
|
|
4201
|
+
if (address.address === address.name) {
|
|
4202
|
+
if (/@/.test(address.address || "")) address.name = "";
|
|
4203
|
+
else address.address = "";
|
|
4204
|
+
}
|
|
4205
|
+
return address;
|
|
4001
4206
|
}
|
|
4002
4207
|
/**
|
|
4003
4208
|
* Creates a Tokenizer object for tokenizing address field strings
|
|
@@ -4010,11 +4215,16 @@ var Tokenizer = class {
|
|
|
4010
4215
|
this.str = (str || "").toString();
|
|
4011
4216
|
this.operatorCurrent = "";
|
|
4012
4217
|
this.operatorExpecting = "";
|
|
4013
|
-
this.node =
|
|
4218
|
+
this.node = -1;
|
|
4014
4219
|
this.escaped = false;
|
|
4015
4220
|
this.inDomainLiteral = false;
|
|
4016
4221
|
this.afterAt = false;
|
|
4017
|
-
this.
|
|
4222
|
+
this.inGroup = false;
|
|
4223
|
+
this.innerQuoted = false;
|
|
4224
|
+
this.innerComment = 0;
|
|
4225
|
+
this.innerLiteral = false;
|
|
4226
|
+
this.innerEscaped = false;
|
|
4227
|
+
this.list = new TokenList(this.str);
|
|
4018
4228
|
/**
|
|
4019
4229
|
* Operator tokens and which tokens are expected to end the sequence
|
|
4020
4230
|
*/
|
|
@@ -4023,7 +4233,7 @@ var Tokenizer = class {
|
|
|
4023
4233
|
"(": ")",
|
|
4024
4234
|
"<": ">",
|
|
4025
4235
|
",": "",
|
|
4026
|
-
":": "
|
|
4236
|
+
":": "",
|
|
4027
4237
|
";": ""
|
|
4028
4238
|
};
|
|
4029
4239
|
}
|
|
@@ -4033,58 +4243,123 @@ var Tokenizer = class {
|
|
|
4033
4243
|
* @return An array of operator|text tokens
|
|
4034
4244
|
*/
|
|
4035
4245
|
tokenize() {
|
|
4036
|
-
const
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4246
|
+
const str = this.str;
|
|
4247
|
+
const len = str.length;
|
|
4248
|
+
for (let i = 0; i < len; i++) this.checkChar(str.charAt(i), i);
|
|
4249
|
+
this._closeText(len);
|
|
4250
|
+
const list = this.list;
|
|
4251
|
+
const slots = list.slots;
|
|
4252
|
+
let kept = 0;
|
|
4253
|
+
for (let i = 0, count = list.length; i < count; i++) {
|
|
4254
|
+
const kind = slots[i * 3];
|
|
4255
|
+
let start = slots[i * 3 + 1];
|
|
4256
|
+
let end = slots[i * 3 + 2];
|
|
4257
|
+
if (kind & TOKEN_DIRTY) {
|
|
4258
|
+
const value = this._cleanValue(start, end, kind).trim();
|
|
4259
|
+
if (!value) continue;
|
|
4260
|
+
list.cleaned.set(kept, value);
|
|
4261
|
+
} else if (!(kind & TOKEN_OPERATOR)) {
|
|
4262
|
+
while (start < end && _isSpaceCode(str.charCodeAt(start))) start++;
|
|
4263
|
+
while (end > start && _isSpaceCode(str.charCodeAt(end - 1))) end--;
|
|
4264
|
+
if (start === end) continue;
|
|
4265
|
+
}
|
|
4266
|
+
slots[kept * 3] = kind;
|
|
4267
|
+
slots[kept * 3 + 1] = start;
|
|
4268
|
+
slots[kept * 3 + 2] = end;
|
|
4269
|
+
kept++;
|
|
4270
|
+
}
|
|
4271
|
+
list.length = kept;
|
|
4046
4272
|
return list;
|
|
4047
4273
|
}
|
|
4048
4274
|
/**
|
|
4275
|
+
* Ends the text run being collected, if there is one
|
|
4276
|
+
*
|
|
4277
|
+
* @param end Offset just past its last character
|
|
4278
|
+
*/
|
|
4279
|
+
_closeText(end) {
|
|
4280
|
+
if (this.node >= 0) {
|
|
4281
|
+
this.list.slots[this.node * 3 + 2] = end;
|
|
4282
|
+
this.node = -1;
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
/**
|
|
4286
|
+
* Rebuilds the value of a text run that is no plain slice of the field, applying the
|
|
4287
|
+
* rules checkChar collects characters by: an escaping backslash is dropped, a line break
|
|
4288
|
+
* reads as a space and any other control character is left out
|
|
4289
|
+
*
|
|
4290
|
+
* @param start Offset of the first character of the run
|
|
4291
|
+
* @param end Offset just past its last character
|
|
4292
|
+
* @param kind Kind and flags of the run
|
|
4293
|
+
* @return Value of the run
|
|
4294
|
+
*/
|
|
4295
|
+
_cleanValue(start, end, kind) {
|
|
4296
|
+
const str = this.str;
|
|
4297
|
+
const escapes = (kind & TOKEN_ESCAPES) !== 0;
|
|
4298
|
+
let escaped = (kind & TOKEN_STARTS_ESCAPED) !== 0;
|
|
4299
|
+
let value = "";
|
|
4300
|
+
for (let i = start; i < end; i++) {
|
|
4301
|
+
const chr = str.charAt(i);
|
|
4302
|
+
if (escapes && !escaped && chr === "\\") {
|
|
4303
|
+
escaped = true;
|
|
4304
|
+
continue;
|
|
4305
|
+
}
|
|
4306
|
+
escaped = false;
|
|
4307
|
+
if (chr === "\n") value += " ";
|
|
4308
|
+
else if (chr.charCodeAt(0) >= 33 || chr === " " || chr === " ") value += chr;
|
|
4309
|
+
}
|
|
4310
|
+
return value;
|
|
4311
|
+
}
|
|
4312
|
+
/**
|
|
4049
4313
|
* Checks if a character is an operator or text and acts accordingly
|
|
4050
4314
|
*
|
|
4051
4315
|
* @param chr Character from the address field
|
|
4052
|
-
* @param
|
|
4316
|
+
* @param i Offset of the character in the field
|
|
4053
4317
|
*/
|
|
4054
|
-
checkChar(chr,
|
|
4318
|
+
checkChar(chr, i) {
|
|
4055
4319
|
if (!this.escaped && !this.operatorExpecting) {
|
|
4056
4320
|
if (!this.inDomainLiteral && chr === "[" && this.afterAt) this.inDomainLiteral = true;
|
|
4057
4321
|
else if (this.inDomainLiteral && (chr === "]" || chr === "," || chr === ";")) this.inDomainLiteral = false;
|
|
4058
4322
|
}
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4323
|
+
let nested = false;
|
|
4324
|
+
if (this.operatorExpecting === ">") {
|
|
4325
|
+
nested = this._trackInner(chr);
|
|
4326
|
+
if (!nested && chr === ";" && this.inGroup) {
|
|
4327
|
+
this._closeText(i);
|
|
4328
|
+
this.operatorExpecting = "";
|
|
4329
|
+
this._resetInner();
|
|
4330
|
+
}
|
|
4331
|
+
} else if (this.operatorExpecting === ")" && !this.escaped) {
|
|
4332
|
+
if (chr === "(") this.innerComment++;
|
|
4333
|
+
else if (chr === ")" && this.innerComment) {
|
|
4334
|
+
this.innerComment--;
|
|
4335
|
+
nested = true;
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4338
|
+
if (this.escaped) {} else if (chr === this.operatorExpecting && !nested) {
|
|
4339
|
+
const nextChr = this.str.charAt(i + 1);
|
|
4340
|
+
this._closeText(i);
|
|
4341
|
+
this.list.push(nextChr && ![
|
|
4065
4342
|
" ",
|
|
4066
4343
|
" ",
|
|
4067
4344
|
"\r",
|
|
4068
4345
|
"\n",
|
|
4069
4346
|
",",
|
|
4070
4347
|
";"
|
|
4071
|
-
].includes(nextChr)
|
|
4072
|
-
this.list.push(this.node);
|
|
4073
|
-
this.node = null;
|
|
4348
|
+
].includes(nextChr) ? 3 : TOKEN_OPERATOR, i, i + 1);
|
|
4074
4349
|
if (chr !== ")") this.afterAt = false;
|
|
4075
4350
|
this.operatorExpecting = "";
|
|
4076
4351
|
this.escaped = false;
|
|
4352
|
+
this._resetInner();
|
|
4077
4353
|
return;
|
|
4078
4354
|
} else if (!this.operatorExpecting && !(this.inDomainLiteral && chr === ":") && chr in this.operators) {
|
|
4079
|
-
this.
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
this.list.push(this.node);
|
|
4084
|
-
this.node = null;
|
|
4355
|
+
this._closeText(i);
|
|
4356
|
+
this.list.push(TOKEN_OPERATOR, i, i + 1);
|
|
4357
|
+
if (chr === ":") this.inGroup = true;
|
|
4358
|
+
else if (chr === ";") this.inGroup = false;
|
|
4085
4359
|
if (chr !== "(") this.afterAt = false;
|
|
4086
4360
|
this.operatorExpecting = this.operators[chr];
|
|
4087
4361
|
this.escaped = false;
|
|
4362
|
+
this._resetInner();
|
|
4088
4363
|
return;
|
|
4089
4364
|
} else if ([
|
|
4090
4365
|
"\"",
|
|
@@ -4092,70 +4367,147 @@ var Tokenizer = class {
|
|
|
4092
4367
|
")"
|
|
4093
4368
|
].includes(this.operatorExpecting) && chr === "\\") {
|
|
4094
4369
|
this.escaped = true;
|
|
4370
|
+
if (this.node >= 0) this.list.slots[this.node * 3] |= TOKEN_DIRTY;
|
|
4095
4371
|
return;
|
|
4096
4372
|
}
|
|
4097
|
-
if (
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
};
|
|
4102
|
-
this.list.push(this.node);
|
|
4373
|
+
if (this.node < 0) this.node = this.list.push((this.operatorExpecting === "\"" || this.operatorExpecting === ")" ? TOKEN_ESCAPES : 0) | (this.escaped ? TOKEN_STARTS_ESCAPED : 0), i, i);
|
|
4374
|
+
if (chr === "\n") {
|
|
4375
|
+
chr = " ";
|
|
4376
|
+
this.list.slots[this.node * 3] |= TOKEN_DIRTY;
|
|
4103
4377
|
}
|
|
4104
|
-
if (chr === "
|
|
4105
|
-
if (chr.charCodeAt(0) >= 33 || [" ", " "].includes(chr)) {
|
|
4106
|
-
this.node.value += chr;
|
|
4378
|
+
if (chr.charCodeAt(0) >= 33 || chr === " " || chr === " ") {
|
|
4107
4379
|
if (!this.operatorExpecting && chr !== " " && chr !== " ") this.afterAt = chr === "@";
|
|
4108
|
-
}
|
|
4380
|
+
} else this.list.slots[this.node * 3] |= TOKEN_DIRTY;
|
|
4109
4381
|
this.escaped = false;
|
|
4110
4382
|
}
|
|
4383
|
+
/**
|
|
4384
|
+
* Tracks the quoted strings, comments and domain literals inside an angle-addr, which its
|
|
4385
|
+
* closer must not be read from. A backslash escapes the next character inside a quoted
|
|
4386
|
+
* string and a comment. A domain literal opens right after an "@" and ends at the "]".
|
|
4387
|
+
* dtext holds the list separators as well, and inside the brackets they never split the
|
|
4388
|
+
* list anyway.
|
|
4389
|
+
*
|
|
4390
|
+
* @param chr Character from the address field
|
|
4391
|
+
* @return true while the character sits inside one of them, the one that closes it included
|
|
4392
|
+
*/
|
|
4393
|
+
_trackInner(chr) {
|
|
4394
|
+
if (this.innerEscaped) {
|
|
4395
|
+
this.innerEscaped = false;
|
|
4396
|
+
return true;
|
|
4397
|
+
}
|
|
4398
|
+
if (this.innerQuoted) {
|
|
4399
|
+
if (chr === "\\") this.innerEscaped = true;
|
|
4400
|
+
else if (chr === "\"") this.innerQuoted = false;
|
|
4401
|
+
return true;
|
|
4402
|
+
}
|
|
4403
|
+
if (this.innerComment) {
|
|
4404
|
+
if (chr === "\\") this.innerEscaped = true;
|
|
4405
|
+
else if (chr === "(") this.innerComment++;
|
|
4406
|
+
else if (chr === ")") this.innerComment--;
|
|
4407
|
+
return true;
|
|
4408
|
+
}
|
|
4409
|
+
if (this.innerLiteral) {
|
|
4410
|
+
if (chr === "]") this.innerLiteral = false;
|
|
4411
|
+
return true;
|
|
4412
|
+
}
|
|
4413
|
+
if (chr === "\"") {
|
|
4414
|
+
this.innerQuoted = true;
|
|
4415
|
+
return true;
|
|
4416
|
+
}
|
|
4417
|
+
if (chr === "(") {
|
|
4418
|
+
this.innerComment = 1;
|
|
4419
|
+
return true;
|
|
4420
|
+
}
|
|
4421
|
+
if (chr === "[" && this.afterAt) {
|
|
4422
|
+
this.innerLiteral = true;
|
|
4423
|
+
return true;
|
|
4424
|
+
}
|
|
4425
|
+
if (!_isSpaceCode(chr.charCodeAt(0))) this.afterAt = chr === "@";
|
|
4426
|
+
return false;
|
|
4427
|
+
}
|
|
4428
|
+
/**
|
|
4429
|
+
* Forgets the nesting collected for the operator that just opened or ended
|
|
4430
|
+
*/
|
|
4431
|
+
_resetInner() {
|
|
4432
|
+
this.innerQuoted = false;
|
|
4433
|
+
this.innerComment = 0;
|
|
4434
|
+
this.innerLiteral = false;
|
|
4435
|
+
this.innerEscaped = false;
|
|
4436
|
+
}
|
|
4111
4437
|
};
|
|
4112
4438
|
/**
|
|
4113
|
-
*
|
|
4114
|
-
*
|
|
4115
|
-
*
|
|
4439
|
+
* Folds the fragments an unquoted display name holding a comma is split into back together.
|
|
4440
|
+
*
|
|
4441
|
+
* "Joe Foo, PhD <joe@example.com>" is split on the comma into
|
|
4442
|
+
* [{name:"Joe Foo", address:""}, {name:"PhD", address:"joe@example.com"}]. A name-only entry
|
|
4443
|
+
* followed by an entry with both name and address is recombined. Walked back to front so
|
|
4444
|
+
* that a run of fragments folds into one entry in a single pass. Splicing each fragment out
|
|
4445
|
+
* of the list instead would cost O(n^2).
|
|
4446
|
+
*
|
|
4447
|
+
* @param list Parsed entries, in order
|
|
4448
|
+
* @return The entries with the fragments folded in
|
|
4116
4449
|
*/
|
|
4117
|
-
|
|
4450
|
+
function _mergeNameFragments(list) {
|
|
4451
|
+
const merged = [];
|
|
4452
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
4453
|
+
const current = list[i];
|
|
4454
|
+
const next = merged.length ? merged[merged.length - 1] : null;
|
|
4455
|
+
if (next && current.address === "" && current.name && !current.group && next.address && next.name) next.name = current.name + ", " + next.name;
|
|
4456
|
+
else merged.push(current);
|
|
4457
|
+
}
|
|
4458
|
+
return merged.reverse();
|
|
4459
|
+
}
|
|
4118
4460
|
/**
|
|
4119
|
-
* Parses an address list,
|
|
4461
|
+
* Parses an address list, groups included, in a single pass over its tokens.
|
|
4120
4462
|
*
|
|
4121
|
-
*
|
|
4122
|
-
*
|
|
4123
|
-
*
|
|
4124
|
-
*
|
|
4463
|
+
* A group used to be cut out of the field at the ';' that ends it and parsed again as an
|
|
4464
|
+
* address list of its own, recursively, so every level of nesting parsed what was left of
|
|
4465
|
+
* the field once more and the depth had to be capped. RFC 5322 does not nest groups at all,
|
|
4466
|
+
* and the nested ones were flattened anyway. The tokens are now walked once: a ':' opens a
|
|
4467
|
+
* group, its members are read as they come, a ';' closes it. A ':' inside an open group
|
|
4468
|
+
* stands for a group nested in it, whose name is dropped and whose members belong to the
|
|
4469
|
+
* outer one, which is how they were flattened before. The first ';' ends the group, nested
|
|
4470
|
+
* or not, as it did.
|
|
4125
4471
|
*
|
|
4126
4472
|
* @param str Address field
|
|
4127
|
-
* @param depth Current recursion depth for nested group protection
|
|
4128
4473
|
* @return An array of address objects
|
|
4129
4474
|
*/
|
|
4130
|
-
function _parseAddressList(str
|
|
4131
|
-
if (depth > MAX_NESTED_GROUP_DEPTH) return [];
|
|
4475
|
+
function _parseAddressList(str) {
|
|
4132
4476
|
const tokens = new Tokenizer(str).tokenize();
|
|
4133
|
-
const addresses = [];
|
|
4134
|
-
let address = [];
|
|
4135
4477
|
const parsedAddresses = [];
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4478
|
+
let group = null;
|
|
4479
|
+
let members = [];
|
|
4480
|
+
let from = 0;
|
|
4481
|
+
for (let i = 0, len = tokens.length; i <= len; i++) {
|
|
4482
|
+
const operator = i < len ? tokens.operatorAt(i) : "";
|
|
4483
|
+
if (i < len && operator !== "," && operator !== ";" && operator !== ":") continue;
|
|
4484
|
+
if (operator === ":") {
|
|
4485
|
+
if (!group) {
|
|
4486
|
+
group = {
|
|
4487
|
+
name: _groupName(tokens, from, i),
|
|
4488
|
+
group: []
|
|
4489
|
+
};
|
|
4490
|
+
members = [];
|
|
4491
|
+
}
|
|
4492
|
+
from = i + 1;
|
|
4493
|
+
continue;
|
|
4494
|
+
}
|
|
4495
|
+
if (i > from) {
|
|
4496
|
+
const address = _handleAddress(tokens, from, i);
|
|
4497
|
+
if (group) members.push(address);
|
|
4498
|
+
else parsedAddresses.push(address);
|
|
4499
|
+
}
|
|
4500
|
+
from = i + 1;
|
|
4501
|
+
if (group && (operator === ";" || i === len)) {
|
|
4502
|
+
group.group = _mergeNameFragments(members);
|
|
4503
|
+
parsedAddresses.push(group);
|
|
4504
|
+
group = null;
|
|
4505
|
+
}
|
|
4153
4506
|
}
|
|
4154
|
-
|
|
4155
|
-
return mergedAddresses;
|
|
4507
|
+
return _mergeNameFragments(parsedAddresses);
|
|
4156
4508
|
}
|
|
4157
4509
|
function addressparser(str, options) {
|
|
4158
|
-
const parsedAddresses = _parseAddressList(str
|
|
4510
|
+
const parsedAddresses = _parseAddressList(str);
|
|
4159
4511
|
if (options?.flatten) {
|
|
4160
4512
|
const flatAddresses = [];
|
|
4161
4513
|
const walkAddressList = (list) => {
|
|
@@ -4169,8 +4521,7 @@ function addressparser(str, options) {
|
|
|
4169
4521
|
}
|
|
4170
4522
|
return parsedAddresses;
|
|
4171
4523
|
}
|
|
4172
|
-
|
|
4173
|
-
//#region ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/util/assertString.js
|
|
4524
|
+
// ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/util/assertString.js
|
|
4174
4525
|
var require_assertString = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4175
4526
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4176
4527
|
exports.default = assertString;
|
|
@@ -4181,8 +4532,7 @@ var require_assertString = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4181
4532
|
module.exports = exports.default;
|
|
4182
4533
|
module.exports.default = exports.default;
|
|
4183
4534
|
}));
|
|
4184
|
-
|
|
4185
|
-
//#region ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/util/checkHost.js
|
|
4535
|
+
// ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/util/checkHost.js
|
|
4186
4536
|
var require_checkHost = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4187
4537
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4188
4538
|
exports.default = checkHost;
|
|
@@ -4199,8 +4549,7 @@ var require_checkHost = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4199
4549
|
module.exports = exports.default;
|
|
4200
4550
|
module.exports.default = exports.default;
|
|
4201
4551
|
}));
|
|
4202
|
-
|
|
4203
|
-
//#region ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/isByteLength.js
|
|
4552
|
+
// ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/isByteLength.js
|
|
4204
4553
|
var require_isByteLength = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4205
4554
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4206
4555
|
exports.default = isByteLength;
|
|
@@ -4233,8 +4582,7 @@ var require_isByteLength = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4233
4582
|
module.exports = exports.default;
|
|
4234
4583
|
module.exports.default = exports.default;
|
|
4235
4584
|
}));
|
|
4236
|
-
|
|
4237
|
-
//#region ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/util/merge.js
|
|
4585
|
+
// ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/util/merge.js
|
|
4238
4586
|
var require_merge = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4239
4587
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4240
4588
|
exports.default = merge;
|
|
@@ -4256,8 +4604,7 @@ var require_merge = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4256
4604
|
module.exports = exports.default;
|
|
4257
4605
|
module.exports.default = exports.default;
|
|
4258
4606
|
}));
|
|
4259
|
-
|
|
4260
|
-
//#region ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/isFQDN.js
|
|
4607
|
+
// ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/isFQDN.js
|
|
4261
4608
|
var require_isFQDN = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4262
4609
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4263
4610
|
exports.default = isFQDN;
|
|
@@ -4299,8 +4646,7 @@ var require_isFQDN = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4299
4646
|
module.exports = exports.default;
|
|
4300
4647
|
module.exports.default = exports.default;
|
|
4301
4648
|
}));
|
|
4302
|
-
|
|
4303
|
-
//#region ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/isIP.js
|
|
4649
|
+
// ../node_modules/.pnpm/validator@13.15.35/node_modules/validator/lib/isIP.js
|
|
4304
4650
|
var require_isIP = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4305
4651
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4306
4652
|
exports.default = isIP;
|
|
@@ -4362,8 +4708,7 @@ var require_isIP = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
4362
4708
|
module.exports = exports.default;
|
|
4363
4709
|
module.exports.default = exports.default;
|
|
4364
4710
|
}));
|
|
4365
|
-
|
|
4366
|
-
//#region ../sdk-node/dist/address-parser-9Qyfhuo9.js
|
|
4711
|
+
// ../sdk-node/dist/address-parser-B3oyKBvX.js
|
|
4367
4712
|
var import_isEmail = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4368
4713
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4369
4714
|
exports.default = isEmail;
|
|
@@ -4537,8 +4882,7 @@ function parseFromHeader(header) {
|
|
|
4537
4882
|
value: { address: address.toLowerCase() }
|
|
4538
4883
|
};
|
|
4539
4884
|
}
|
|
4540
|
-
|
|
4541
|
-
//#region ../sdk-node/dist/trust-CmCl198c.js
|
|
4885
|
+
// ../sdk-node/dist/trust-uBk1pAV-.js
|
|
4542
4886
|
/**
|
|
4543
4887
|
* AUTO-GENERATED - DO NOT EDIT
|
|
4544
4888
|
* Run `pnpm generate:validator` to regenerate.
|
|
@@ -21202,8 +21546,7 @@ function normalizeOptions(options) {
|
|
|
21202
21546
|
sender
|
|
21203
21547
|
};
|
|
21204
21548
|
}
|
|
21205
|
-
|
|
21206
|
-
//#region src/oclif/reply-state.ts
|
|
21549
|
+
// src/oclif/reply-state.ts
|
|
21207
21550
|
const AWAITING_VALUES = ["you", "them"];
|
|
21208
21551
|
const AWAITING_FLAG_DESCRIPTION = "Only emails whose reply state is this value: `you` = waiting on your reply (the thread's latest message is inbound), `them` = you replied last. Queued and scheduled replies count as replied. Delivered mail only: rejected mail is never returned. Fails if the server does not report reply state yet.";
|
|
21209
21552
|
const REPLY_STATE_UNSUPPORTED_CODE = "reply_state_unsupported";
|
|
@@ -21347,8 +21690,7 @@ function ensureSearchReportsReplyState(apiClient) {
|
|
|
21347
21690
|
}
|
|
21348
21691
|
return probe;
|
|
21349
21692
|
}
|
|
21350
|
-
|
|
21351
|
-
//#region src/oclif/commands/emails-poll.ts
|
|
21693
|
+
// src/oclif/commands/emails-poll.ts
|
|
21352
21694
|
function quoteDslValue(value) {
|
|
21353
21695
|
if (/^[^\s"]+$/.test(value)) return value;
|
|
21354
21696
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
@@ -21474,8 +21816,7 @@ async function fetchEmailSearchPage(params) {
|
|
|
21474
21816
|
function sleep(ms) {
|
|
21475
21817
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
21476
21818
|
}
|
|
21477
|
-
|
|
21478
|
-
//#region src/oclif/transient-retry.ts
|
|
21819
|
+
// src/oclif/transient-retry.ts
|
|
21479
21820
|
/**
|
|
21480
21821
|
* Transient API failures inside waits.
|
|
21481
21822
|
*
|
|
@@ -21624,8 +21965,7 @@ function describeApiFailure(result) {
|
|
|
21624
21965
|
const label = code ?? (status === void 0 ? "api_error" : `HTTP ${status}`);
|
|
21625
21966
|
return message ? `${label} (${message})` : label;
|
|
21626
21967
|
}
|
|
21627
|
-
|
|
21628
|
-
//#region ../sdk-node/dist/repeats-BL7ZC-_6.js
|
|
21968
|
+
// ../sdk-node/dist/repeats-Dj_o6c-X.js
|
|
21629
21969
|
const UUID$3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
21630
21970
|
const ATOM = "[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+";
|
|
21631
21971
|
const MAILBOX$1 = new RegExp(`^${ATOM}(?:\\.${ATOM})*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$`);
|
|
@@ -22406,5 +22746,4 @@ function repeatStopCommand(emailId) {
|
|
|
22406
22746
|
if (!UUID.test(emailId)) throw new TypeError("emailId must be an email UUID");
|
|
22407
22747
|
return `primitive repeat stop --id ${emailId.toLowerCase()}`;
|
|
22408
22748
|
}
|
|
22409
|
-
//#endregion
|
|
22410
22749
|
export { AutomatedFilterUnsupportedError as $, listDomains as $t, sleep as A, setMemory as An, getAgentContactPolicy as At, hasReplyState as B, updateRepeatingSend as Bn, getMemory as Bt, collectNewAcceptedEmails as C, sdk_gen_exports as Cn, deleteWakeSchedule as Ct, filtersFromFlags as D, sendEmail as Dn, downloadSentAttachmentArchiveMember as Dt, fetchEmailSearchPage as E, semanticSearch as En, downloadEmailAttachmentPart as Et, assertAwaitingFilterRows as F, stopRepeatFromEmail as Fn, getEmail as Ft, WEBHOOK_EVENT_TYPES as G, verifyAgentSignup as Gn, getWakeSchedule as Gt, queryUsesAwaiting as H, updateWakeAuthorization as Hn, getRepeatingSend as Ht, awaitingRejectedError as I, testFunction as In, getFunction as It, parseWebhookEvent as J, listAgentContacts as Jt, isEmailReceivedEvent as K, __exportAll as Kn, inviteAgentConnection as Kt, ensureSearchReportsReplyState as L, unsetFunctionRoute as Ln, getFunctionRouting as Lt, AWAITING_VALUES as M, startAgentClaim as Mn, getConversation as Mt, REPLY_STATE_UNSUPPORTED_CODE as N, startAgentSignup as Nn, getCreditBalance as Nt, quoteDslValue as O, setFunctionRoute as On, downloadSentAttachmentByFilename as Ot, ReplyStateUnsupportedError as P, startCliLogin as Pn, getDefaultNetworkAgent as Pt, AUTOMATED_VALUES as Q, listDefaultNetworkMembers as Qt, formatAwaitingCell as R, updateDefaultNetworkMember as Rn, getFunctionTestRunTrace as Rt, transientFailure as S, runWakeSchedule as Sn, deleteWakeAuthorization as St, encodeReceivedAtSearchCursor as T, searchMemories as Tn, downloadEmailAttachmentByFilename as Tt, replyStateSurfaceForOperation as U, updateWakeSchedule as Un, getSentEmail as Ut, isAwaitingRejectedError as V, updateRoute as Vn, getOrgRoutingTopology as Vt, SENT_EMAIL_EVENT_TYPES as W, verifyAgentClaim as Wn, getThread as Wt, AUTOMATED_FILTER_UNSUPPORTED_CODE as X, listContacts as Xt, parseFromHeader as Y, listAgentNetworks as Yt, AUTOMATED_FLAG_DESCRIPTION as Z, listDefaultNetworkAgents as Zt, describeApiFailure as _, redeemCreditCode as _n, createWakeSchedule as _t, REPEAT_IDLE_MAX_MINUTES as a, listRepeatingSends as an, hasAutomatedVerdict as at, retryTransient as b, replyToEmail as bn, deleteMemory as bt, classifySignalContent as c, listSentEmails as cn, cancelSentEmail as ct, parseRepeatTick as d, listWakeSchedules as dn, cliLogout as dt, listEmailAttachmentArchiveMembers as en, assertAutomatedVerdict as et, preparePresenceAliveEmail as f, pollCliLogin as fn, completeWebhookEvent as ft, WaitDeadlineReached as g, putContact as gn, createWakeAuthorization as gt, sendPreparedSignal as h, putAgentContactPolicy as hn, createRoute as ht, REPEAT_EVERY_MAX_MINUTES as i, listFunctions as in, expectedAutomatedVerdicts as it, AWAITING_FLAG_DESCRIPTION as j, simulateRoute as jn, getContact as jt, sinceFromFlags as k, setFunctionSecret as kn, getAccount as kt, parseInteractionEnvelope as l, listWakeAuthorizations as ln, cancelSentEmailByIdempotencyKey as lt, repeatStopCommand as m, putAgentContact as mn, createFunction as mt, MAX_PRESENCE_ENVELOPE_BYTES as n, listEndpoints as nn, automatedSurfaceForOperation as nt, REPEAT_MAX_SENDS_MAX as o, listRoutes as on, isAutomatedRejectedError as ot, prepareSignalEmail as p, pullWebhookEvent as pn, createEndpoint as pt, isTrustedSender as q, listAgentConnections as qt, PRESENCE_PROBE_TEXT as r, listFunctionLogs as rn, ensureSearchReportsAutomated as rt, buildRepeatStopBody as s, listSentAttachmentArchiveMembers as sn, addDefaultNetworkMember as st, MAX_INTERACTION_BYTES as t, listEmails as tn, automatedRejectedError as tt, parsePresenceEnvelope as u, listWakeDispatches as un, checkDefaultNetworkContactAdmission as ut, parseRetryAfter as v, removeDefaultNetworkMember as vn, deleteAgentContact as vt, cursorFromAcceptedRows as w, searchEmails as wn, downloadEmailAttachmentArchiveMember as wt, retryingOperation as x, resendAgentSignupVerification as xn, deleteRoute as xt, pauseForTransientFailure as y, reorderRoutes as yn, deleteContact as yt, formatRepliesCell as z, updateFunction as zn, getInboxStatus as zt };
|