imapkit 4.0.2 → 4.1.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 +32 -19
- package/bin/imapkit.js +12 -16
- package/dist/cjs/addressparser.d.ts +21 -0
- package/dist/cjs/addressparser.js +277 -0
- package/dist/cjs/arguments.d.ts +31 -0
- package/{lib → dist/cjs}/arguments.js +9 -21
- package/dist/cjs/bodystructure.d.ts +25 -0
- package/dist/cjs/bodystructure.js +150 -0
- package/dist/cjs/cert.d.ts +2 -0
- package/dist/cjs/cert.js +7 -0
- package/dist/cjs/command-states.d.ts +36 -0
- package/dist/cjs/command-states.js +102 -0
- package/dist/cjs/commands/append.d.ts +88 -0
- package/dist/cjs/commands/append.js +299 -0
- package/dist/cjs/commands/capability.d.ts +2 -0
- package/dist/cjs/commands/capability.js +44 -0
- package/dist/cjs/commands/check.d.ts +2 -0
- package/dist/cjs/commands/check.js +28 -0
- package/dist/cjs/commands/close.d.ts +2 -0
- package/dist/cjs/commands/close.js +35 -0
- package/dist/cjs/commands/copy.d.ts +30 -0
- package/dist/cjs/commands/copy.js +107 -0
- package/dist/cjs/commands/create.d.ts +2 -0
- package/dist/cjs/commands/create.js +53 -0
- package/dist/cjs/commands/delete.d.ts +2 -0
- package/dist/cjs/commands/delete.js +63 -0
- package/dist/cjs/commands/examine.d.ts +2 -0
- package/dist/cjs/commands/examine.js +19 -0
- package/dist/cjs/commands/expunge.d.ts +2 -0
- package/dist/cjs/commands/expunge.js +32 -0
- package/dist/cjs/commands/fetch.d.ts +23 -0
- package/dist/cjs/commands/fetch.js +208 -0
- package/dist/cjs/commands/handlers/fetch.d.ts +12 -0
- package/dist/cjs/commands/handlers/fetch.js +195 -0
- package/dist/cjs/commands/handlers/flags.d.ts +17 -0
- package/dist/cjs/commands/handlers/flags.js +39 -0
- package/dist/cjs/commands/handlers/search.d.ts +85 -0
- package/dist/cjs/commands/handlers/search.js +504 -0
- package/dist/cjs/commands/handlers/status.d.ts +34 -0
- package/dist/cjs/commands/handlers/status.js +81 -0
- package/dist/cjs/commands/handlers/store.d.ts +3 -0
- package/dist/cjs/commands/handlers/store.js +117 -0
- package/dist/cjs/commands/index.d.ts +2 -0
- package/dist/cjs/commands/index.js +61 -0
- package/dist/cjs/commands/list.d.ts +2 -0
- package/dist/cjs/commands/list.js +86 -0
- package/dist/cjs/commands/login.d.ts +2 -0
- package/dist/cjs/commands/login.js +62 -0
- package/dist/cjs/commands/logout.d.ts +2 -0
- package/dist/cjs/commands/logout.js +40 -0
- package/dist/cjs/commands/lsub.d.ts +2 -0
- package/dist/cjs/commands/lsub.js +79 -0
- package/dist/cjs/commands/noop.d.ts +2 -0
- package/dist/cjs/commands/noop.js +28 -0
- package/dist/cjs/commands/rename.d.ts +2 -0
- package/dist/cjs/commands/rename.js +98 -0
- package/dist/cjs/commands/search.d.ts +10 -0
- package/dist/cjs/commands/search.js +71 -0
- package/dist/cjs/commands/select.d.ts +19 -0
- package/dist/cjs/commands/select.js +230 -0
- package/dist/cjs/commands/status.d.ts +2 -0
- package/dist/cjs/commands/status.js +57 -0
- package/dist/cjs/commands/store.d.ts +10 -0
- package/dist/cjs/commands/store.js +134 -0
- package/dist/cjs/commands/subscribe.d.ts +2 -0
- package/dist/cjs/commands/subscribe.js +51 -0
- package/dist/cjs/commands/uid-copy.d.ts +2 -0
- package/dist/cjs/commands/uid-copy.js +19 -0
- package/dist/cjs/commands/uid-fetch.d.ts +3 -0
- package/dist/cjs/commands/uid-fetch.js +17 -0
- package/dist/cjs/commands/uid-search.d.ts +3 -0
- package/dist/cjs/commands/uid-search.js +17 -0
- package/dist/cjs/commands/uid-store.d.ts +3 -0
- package/dist/cjs/commands/uid-store.js +17 -0
- package/dist/cjs/commands/unsubscribe.d.ts +2 -0
- package/dist/cjs/commands/unsubscribe.js +50 -0
- package/dist/cjs/dates.d.ts +64 -0
- package/dist/cjs/dates.js +124 -0
- package/dist/cjs/deflate-layer.d.ts +83 -0
- package/dist/cjs/deflate-layer.js +232 -0
- package/dist/cjs/encoded-words.d.ts +15 -0
- package/dist/cjs/encoded-words.js +85 -0
- package/dist/cjs/envelope.d.ts +33 -0
- package/dist/cjs/envelope.js +86 -0
- package/dist/cjs/esearch.d.ts +96 -0
- package/dist/cjs/esearch.js +190 -0
- package/dist/cjs/framing.d.ts +66 -0
- package/{lib → dist/cjs}/framing.js +9 -26
- package/dist/cjs/index.d.ts +9 -0
- package/dist/cjs/index.js +56 -0
- package/dist/cjs/list-extensions.d.ts +50 -0
- package/dist/cjs/list-extensions.js +35 -0
- package/dist/cjs/load-plugins.d.ts +21 -0
- package/dist/cjs/load-plugins.js +89 -0
- package/dist/cjs/mailbox-name.d.ts +26 -0
- package/dist/cjs/mailbox-name.js +127 -0
- package/dist/cjs/mimeparser.d.ts +137 -0
- package/dist/cjs/mimeparser.js +727 -0
- package/dist/cjs/mock-client.d.ts +39 -0
- package/dist/cjs/mock-client.js +236 -0
- package/dist/cjs/numbers.d.ts +28 -0
- package/dist/cjs/numbers.js +52 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/plugins/acl.d.ts +2 -0
- package/dist/cjs/plugins/acl.js +888 -0
- package/dist/cjs/plugins/appendlimit.d.ts +16 -0
- package/dist/cjs/plugins/appendlimit.js +87 -0
- package/dist/cjs/plugins/auth-plain.d.ts +2 -0
- package/dist/cjs/plugins/auth-plain.js +89 -0
- package/dist/cjs/plugins/binary.d.ts +30 -0
- package/dist/cjs/plugins/binary.js +247 -0
- package/dist/cjs/plugins/catenate.d.ts +14 -0
- package/dist/cjs/plugins/catenate.js +250 -0
- package/dist/cjs/plugins/compress.d.ts +7 -0
- package/dist/cjs/plugins/compress.js +79 -0
- package/dist/cjs/plugins/condstore.d.ts +5 -0
- package/dist/cjs/plugins/condstore.js +492 -0
- package/dist/cjs/plugins/context-search.d.ts +8 -0
- package/dist/cjs/plugins/context-search.js +304 -0
- package/dist/cjs/plugins/context-sort.d.ts +6 -0
- package/dist/cjs/plugins/context-sort.js +32 -0
- package/dist/cjs/plugins/create-special-use.d.ts +7 -0
- package/dist/cjs/plugins/create-special-use.js +101 -0
- package/dist/cjs/plugins/enable.d.ts +23 -0
- package/dist/cjs/plugins/enable.js +127 -0
- package/dist/cjs/plugins/esearch.d.ts +6 -0
- package/dist/cjs/plugins/esearch.js +142 -0
- package/dist/cjs/plugins/esort.d.ts +6 -0
- package/dist/cjs/plugins/esort.js +60 -0
- package/dist/cjs/plugins/id.d.ts +5 -0
- package/dist/cjs/plugins/id.js +123 -0
- package/dist/cjs/plugins/idle.d.ts +5 -0
- package/dist/cjs/plugins/idle.js +85 -0
- package/dist/cjs/plugins/imap4rev2.d.ts +6 -0
- package/dist/cjs/plugins/imap4rev2.js +184 -0
- package/dist/cjs/plugins/index.d.ts +2 -0
- package/dist/cjs/plugins/index.js +119 -0
- package/dist/cjs/plugins/list-extended.d.ts +2 -0
- package/dist/cjs/plugins/list-extended.js +235 -0
- package/dist/cjs/plugins/list-status.d.ts +6 -0
- package/dist/cjs/plugins/list-status.js +42 -0
- package/dist/cjs/plugins/literalminus.d.ts +8 -0
- package/dist/cjs/plugins/literalminus.js +32 -0
- package/dist/cjs/plugins/literalplus.d.ts +6 -0
- package/dist/cjs/plugins/literalplus.js +30 -0
- package/dist/cjs/plugins/logindisabled.d.ts +5 -0
- package/dist/cjs/plugins/logindisabled.js +54 -0
- package/dist/cjs/plugins/messagelimit.d.ts +19 -0
- package/dist/cjs/plugins/messagelimit.js +227 -0
- package/dist/cjs/plugins/metadata-server.d.ts +7 -0
- package/dist/cjs/plugins/metadata-server.js +24 -0
- package/dist/cjs/plugins/metadata.d.ts +11 -0
- package/dist/cjs/plugins/metadata.js +436 -0
- package/dist/cjs/plugins/move.d.ts +11 -0
- package/dist/cjs/plugins/move.js +96 -0
- package/dist/cjs/plugins/multiappend.d.ts +12 -0
- package/dist/cjs/plugins/multiappend.js +38 -0
- package/dist/cjs/plugins/multisearch.d.ts +6 -0
- package/dist/cjs/plugins/multisearch.js +263 -0
- package/dist/cjs/plugins/namespace.d.ts +5 -0
- package/dist/cjs/plugins/namespace.js +57 -0
- package/dist/cjs/plugins/notify.d.ts +2 -0
- package/dist/cjs/plugins/notify.js +628 -0
- package/dist/cjs/plugins/oauthbearer.d.ts +32 -0
- package/dist/cjs/plugins/oauthbearer.js +202 -0
- package/dist/cjs/plugins/objectid.d.ts +23 -0
- package/dist/cjs/plugins/objectid.js +221 -0
- package/dist/cjs/plugins/partial.d.ts +6 -0
- package/dist/cjs/plugins/partial.js +78 -0
- package/dist/cjs/plugins/preview.d.ts +31 -0
- package/dist/cjs/plugins/preview.js +378 -0
- package/dist/cjs/plugins/qresync.d.ts +11 -0
- package/dist/cjs/plugins/qresync.js +473 -0
- package/dist/cjs/plugins/quota.d.ts +18 -0
- package/dist/cjs/plugins/quota.js +254 -0
- package/dist/cjs/plugins/replace.d.ts +14 -0
- package/dist/cjs/plugins/replace.js +130 -0
- package/dist/cjs/plugins/sasl-ir.d.ts +5 -0
- package/dist/cjs/plugins/sasl-ir.js +24 -0
- package/dist/cjs/plugins/savedate.d.ts +17 -0
- package/dist/cjs/plugins/savedate.js +64 -0
- package/dist/cjs/plugins/savelimit.d.ts +10 -0
- package/dist/cjs/plugins/savelimit.js +30 -0
- package/dist/cjs/plugins/searchres.d.ts +6 -0
- package/dist/cjs/plugins/searchres.js +91 -0
- package/dist/cjs/plugins/sort-display.d.ts +11 -0
- package/dist/cjs/plugins/sort-display.js +37 -0
- package/dist/cjs/plugins/sort.d.ts +11 -0
- package/dist/cjs/plugins/sort.js +125 -0
- package/dist/cjs/plugins/special-use.d.ts +10 -0
- package/dist/cjs/plugins/special-use.js +95 -0
- package/dist/cjs/plugins/starttls.d.ts +5 -0
- package/dist/cjs/plugins/starttls.js +55 -0
- package/dist/cjs/plugins/status-size.d.ts +7 -0
- package/dist/cjs/plugins/status-size.js +30 -0
- package/dist/cjs/plugins/thread-orderedsubject.d.ts +11 -0
- package/dist/cjs/plugins/thread-orderedsubject.js +28 -0
- package/dist/cjs/plugins/thread-references.d.ts +11 -0
- package/dist/cjs/plugins/thread-references.js +28 -0
- package/dist/cjs/plugins/uidonly.d.ts +15 -0
- package/dist/cjs/plugins/uidonly.js +126 -0
- package/dist/cjs/plugins/uidplus.d.ts +15 -0
- package/dist/cjs/plugins/uidplus.js +119 -0
- package/dist/cjs/plugins/unauthenticate.d.ts +7 -0
- package/dist/cjs/plugins/unauthenticate.js +32 -0
- package/dist/cjs/plugins/unselect.d.ts +5 -0
- package/dist/cjs/plugins/unselect.js +36 -0
- package/dist/cjs/plugins/utf8-accept.d.ts +6 -0
- package/dist/cjs/plugins/utf8-accept.js +72 -0
- package/dist/cjs/plugins/x-gm-ext-1.d.ts +26 -0
- package/dist/cjs/plugins/x-gm-ext-1.js +422 -0
- package/dist/cjs/plugins/xoauth2.d.ts +2 -0
- package/dist/cjs/plugins/xoauth2.js +155 -0
- package/dist/cjs/plugins/xtoybird.d.ts +2 -0
- package/dist/cjs/plugins/xtoybird.js +236 -0
- package/dist/cjs/server.d.ts +876 -0
- package/dist/cjs/server.js +2597 -0
- package/dist/cjs/smtp-listener.d.ts +13 -0
- package/dist/cjs/smtp-listener.js +47 -0
- package/dist/cjs/sorting.d.ts +77 -0
- package/dist/cjs/sorting.js +290 -0
- package/dist/cjs/threading.d.ts +30 -0
- package/dist/cjs/threading.js +318 -0
- package/dist/cjs/types.d.ts +327 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/utf8-session.d.ts +17 -0
- package/dist/cjs/utf8-session.js +148 -0
- package/dist/cjs/vanished.d.ts +21 -0
- package/dist/cjs/vanished.js +55 -0
- package/dist/esm/addressparser.d.ts +21 -0
- package/{lib → dist/esm}/addressparser.js +102 -123
- package/dist/esm/arguments.d.ts +31 -0
- package/dist/esm/arguments.js +96 -0
- package/dist/esm/bodystructure.d.ts +25 -0
- package/{lib → dist/esm}/bodystructure.js +17 -33
- package/dist/esm/cert.d.ts +2 -0
- package/dist/esm/cert.js +4 -0
- package/dist/esm/command-states.d.ts +36 -0
- package/{lib → dist/esm}/command-states.js +4 -16
- package/dist/esm/commands/append.d.ts +88 -0
- package/{lib → dist/esm}/commands/append.js +47 -85
- package/dist/esm/commands/capability.d.ts +2 -0
- package/dist/esm/commands/capability.js +29 -0
- package/dist/esm/commands/check.d.ts +2 -0
- package/dist/esm/commands/check.js +13 -0
- package/dist/esm/commands/close.d.ts +2 -0
- package/dist/esm/commands/close.js +20 -0
- package/dist/esm/commands/copy.d.ts +30 -0
- package/{lib → dist/esm}/commands/copy.js +31 -55
- package/dist/esm/commands/create.d.ts +2 -0
- package/{lib → dist/esm}/commands/create.js +25 -39
- package/dist/esm/commands/delete.d.ts +2 -0
- package/{lib → dist/esm}/commands/delete.js +25 -41
- package/dist/esm/commands/examine.d.ts +2 -0
- package/dist/esm/commands/examine.js +4 -0
- package/dist/esm/commands/expunge.d.ts +2 -0
- package/dist/esm/commands/expunge.js +17 -0
- package/dist/esm/commands/fetch.d.ts +23 -0
- package/{lib → dist/esm}/commands/fetch.js +34 -75
- package/dist/esm/commands/handlers/fetch.d.ts +12 -0
- package/{lib → dist/esm}/commands/handlers/fetch.js +11 -42
- package/dist/esm/commands/handlers/flags.d.ts +17 -0
- package/{lib → dist/esm}/commands/handlers/flags.js +3 -11
- package/dist/esm/commands/handlers/search.d.ts +85 -0
- package/{lib → dist/esm}/commands/handlers/search.js +33 -71
- package/dist/esm/commands/handlers/status.d.ts +34 -0
- package/{lib → dist/esm}/commands/handlers/status.js +1 -9
- package/dist/esm/commands/handlers/store.d.ts +3 -0
- package/{lib → dist/esm}/commands/handlers/store.js +20 -44
- package/dist/esm/commands/index.d.ts +2 -0
- package/dist/esm/commands/index.js +55 -0
- package/dist/esm/commands/list.d.ts +2 -0
- package/dist/esm/commands/list.js +71 -0
- package/dist/esm/commands/login.d.ts +2 -0
- package/{lib → dist/esm}/commands/login.js +24 -44
- package/dist/esm/commands/logout.d.ts +2 -0
- package/dist/esm/commands/logout.js +25 -0
- package/dist/esm/commands/lsub.d.ts +2 -0
- package/dist/esm/commands/lsub.js +64 -0
- package/dist/esm/commands/noop.d.ts +2 -0
- package/dist/esm/commands/noop.js +13 -0
- package/dist/esm/commands/rename.d.ts +2 -0
- package/{lib → dist/esm}/commands/rename.js +32 -51
- package/dist/esm/commands/search.d.ts +10 -0
- package/dist/esm/commands/search.js +54 -0
- package/dist/esm/commands/select.d.ts +19 -0
- package/dist/esm/commands/select.js +214 -0
- package/dist/esm/commands/status.d.ts +2 -0
- package/{lib → dist/esm}/commands/status.js +18 -39
- package/dist/esm/commands/store.d.ts +10 -0
- package/{lib → dist/esm}/commands/store.js +39 -73
- package/dist/esm/commands/subscribe.d.ts +2 -0
- package/{lib → dist/esm}/commands/subscribe.js +22 -39
- package/dist/esm/commands/uid-copy.d.ts +2 -0
- package/dist/esm/commands/uid-copy.js +4 -0
- package/dist/esm/commands/uid-fetch.d.ts +3 -0
- package/dist/esm/commands/uid-fetch.js +3 -0
- package/dist/esm/commands/uid-search.d.ts +3 -0
- package/dist/esm/commands/uid-search.js +3 -0
- package/dist/esm/commands/uid-store.d.ts +3 -0
- package/dist/esm/commands/uid-store.js +3 -0
- package/dist/esm/commands/unsubscribe.d.ts +2 -0
- package/{lib → dist/esm}/commands/unsubscribe.js +22 -37
- package/dist/esm/dates.d.ts +64 -0
- package/{lib → dist/esm}/dates.js +6 -14
- package/dist/esm/deflate-layer.d.ts +83 -0
- package/{lib → dist/esm}/deflate-layer.js +9 -26
- package/dist/esm/encoded-words.d.ts +15 -0
- package/{lib → dist/esm}/encoded-words.js +9 -25
- package/dist/esm/envelope.d.ts +33 -0
- package/{lib → dist/esm}/envelope.js +8 -19
- package/dist/esm/esearch.d.ts +96 -0
- package/{lib → dist/esm}/esearch.js +12 -39
- package/dist/esm/framing.d.ts +66 -0
- package/dist/esm/framing.js +82 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/list-extensions.d.ts +50 -0
- package/{lib → dist/esm}/list-extensions.js +1 -4
- package/dist/esm/load-plugins.d.ts +21 -0
- package/{lib → dist/esm}/load-plugins.js +9 -43
- package/dist/esm/mailbox-name.d.ts +26 -0
- package/{lib → dist/esm}/mailbox-name.js +5 -26
- package/dist/esm/mimeparser.d.ts +137 -0
- package/{lib → dist/esm}/mimeparser.js +74 -152
- package/dist/esm/mock-client.d.ts +39 -0
- package/{lib → dist/esm}/mock-client.js +26 -40
- package/dist/esm/numbers.d.ts +28 -0
- package/{lib → dist/esm}/numbers.js +1 -8
- package/dist/esm/package.json +3 -0
- package/dist/esm/plugins/acl.d.ts +2 -0
- package/{lib → dist/esm}/plugins/acl.js +146 -240
- package/dist/esm/plugins/appendlimit.d.ts +16 -0
- package/{lib → dist/esm}/plugins/appendlimit.js +5 -16
- package/dist/esm/plugins/auth-plain.d.ts +2 -0
- package/{lib → dist/esm}/plugins/auth-plain.js +11 -31
- package/dist/esm/plugins/binary.d.ts +30 -0
- package/{lib → dist/esm}/plugins/binary.js +17 -43
- package/dist/esm/plugins/catenate.d.ts +14 -0
- package/{lib → dist/esm}/plugins/catenate.js +19 -40
- package/dist/esm/plugins/compress.d.ts +7 -0
- package/dist/esm/plugins/compress.js +61 -0
- package/dist/esm/plugins/condstore.d.ts +5 -0
- package/{lib → dist/esm}/plugins/condstore.js +66 -152
- package/dist/esm/plugins/context-search.d.ts +8 -0
- package/{lib → dist/esm}/plugins/context-search.js +53 -88
- package/dist/esm/plugins/context-sort.d.ts +6 -0
- package/{lib → dist/esm}/plugins/context-sort.js +4 -9
- package/dist/esm/plugins/create-special-use.d.ts +7 -0
- package/{lib → dist/esm}/plugins/create-special-use.js +33 -55
- package/dist/esm/plugins/enable.d.ts +23 -0
- package/dist/esm/plugins/enable.js +111 -0
- package/dist/esm/plugins/esearch.d.ts +6 -0
- package/{lib → dist/esm}/plugins/esearch.js +13 -42
- package/dist/esm/plugins/esort.d.ts +6 -0
- package/{lib → dist/esm}/plugins/esort.js +7 -25
- package/dist/esm/plugins/id.d.ts +5 -0
- package/dist/esm/plugins/id.js +108 -0
- package/dist/esm/plugins/idle.d.ts +5 -0
- package/dist/esm/plugins/idle.js +70 -0
- package/dist/esm/plugins/imap4rev2.d.ts +6 -0
- package/{lib → dist/esm}/plugins/imap4rev2.js +24 -60
- package/dist/esm/plugins/index.d.ts +2 -0
- package/dist/esm/plugins/index.js +113 -0
- package/dist/esm/plugins/list-extended.d.ts +2 -0
- package/{lib → dist/esm}/plugins/list-extended.js +28 -66
- package/dist/esm/plugins/list-status.d.ts +6 -0
- package/{lib → dist/esm}/plugins/list-status.js +5 -12
- package/dist/esm/plugins/literalminus.d.ts +8 -0
- package/{lib → dist/esm}/plugins/literalminus.js +2 -5
- package/dist/esm/plugins/literalplus.d.ts +6 -0
- package/{lib → dist/esm}/plugins/literalplus.js +2 -5
- package/dist/esm/plugins/logindisabled.d.ts +5 -0
- package/dist/esm/plugins/logindisabled.js +39 -0
- package/dist/esm/plugins/messagelimit.d.ts +19 -0
- package/{lib → dist/esm}/plugins/messagelimit.js +18 -41
- package/dist/esm/plugins/metadata-server.d.ts +7 -0
- package/{lib → dist/esm}/plugins/metadata-server.js +3 -7
- package/dist/esm/plugins/metadata.d.ts +11 -0
- package/dist/esm/plugins/metadata.js +421 -0
- package/dist/esm/plugins/move.d.ts +11 -0
- package/{lib → dist/esm}/plugins/move.js +37 -66
- package/dist/esm/plugins/multiappend.d.ts +12 -0
- package/{lib → dist/esm}/plugins/multiappend.js +2 -5
- package/dist/esm/plugins/multisearch.d.ts +6 -0
- package/{lib → dist/esm}/plugins/multisearch.js +24 -48
- package/dist/esm/plugins/namespace.d.ts +5 -0
- package/dist/esm/plugins/namespace.js +42 -0
- package/dist/esm/plugins/notify.d.ts +2 -0
- package/{lib → dist/esm}/plugins/notify.js +90 -134
- package/dist/esm/plugins/oauthbearer.d.ts +32 -0
- package/{lib → dist/esm}/plugins/oauthbearer.js +18 -48
- package/dist/esm/plugins/objectid.d.ts +23 -0
- package/{lib → dist/esm}/plugins/objectid.js +21 -58
- package/dist/esm/plugins/partial.d.ts +6 -0
- package/{lib → dist/esm}/plugins/partial.js +7 -15
- package/dist/esm/plugins/preview.d.ts +31 -0
- package/{lib → dist/esm}/plugins/preview.js +28 -66
- package/dist/esm/plugins/qresync.d.ts +11 -0
- package/{lib → dist/esm}/plugins/qresync.js +64 -134
- package/dist/esm/plugins/quota.d.ts +18 -0
- package/{lib → dist/esm}/plugins/quota.js +89 -135
- package/dist/esm/plugins/replace.d.ts +14 -0
- package/{lib → dist/esm}/plugins/replace.js +21 -51
- package/dist/esm/plugins/sasl-ir.d.ts +5 -0
- package/{lib → dist/esm}/plugins/sasl-ir.js +3 -6
- package/dist/esm/plugins/savedate.d.ts +17 -0
- package/{lib → dist/esm}/plugins/savedate.js +5 -15
- package/dist/esm/plugins/savelimit.d.ts +10 -0
- package/{lib → dist/esm}/plugins/savelimit.js +3 -6
- package/dist/esm/plugins/searchres.d.ts +6 -0
- package/{lib → dist/esm}/plugins/searchres.js +13 -22
- package/dist/esm/plugins/sort-display.d.ts +11 -0
- package/{lib → dist/esm}/plugins/sort-display.js +6 -10
- package/dist/esm/plugins/sort.d.ts +11 -0
- package/{lib → dist/esm}/plugins/sort.js +24 -46
- package/dist/esm/plugins/special-use.d.ts +10 -0
- package/{lib → dist/esm}/plugins/special-use.js +9 -24
- package/dist/esm/plugins/starttls.d.ts +5 -0
- package/{lib → dist/esm}/plugins/starttls.js +20 -37
- package/dist/esm/plugins/status-size.d.ts +7 -0
- package/{lib → dist/esm}/plugins/status-size.js +4 -11
- package/dist/esm/plugins/thread-orderedsubject.d.ts +11 -0
- package/{lib → dist/esm}/plugins/thread-orderedsubject.js +3 -6
- package/dist/esm/plugins/thread-references.d.ts +11 -0
- package/{lib → dist/esm}/plugins/thread-references.js +3 -6
- package/dist/esm/plugins/uidonly.d.ts +15 -0
- package/{lib → dist/esm}/plugins/uidonly.js +11 -35
- package/dist/esm/plugins/uidplus.d.ts +15 -0
- package/{lib → dist/esm}/plugins/uidplus.js +25 -45
- package/dist/esm/plugins/unauthenticate.d.ts +7 -0
- package/dist/esm/plugins/unauthenticate.js +17 -0
- package/dist/esm/plugins/unselect.d.ts +5 -0
- package/dist/esm/plugins/unselect.js +21 -0
- package/dist/esm/plugins/utf8-accept.d.ts +6 -0
- package/{lib → dist/esm}/plugins/utf8-accept.js +10 -21
- package/dist/esm/plugins/x-gm-ext-1.d.ts +26 -0
- package/{lib → dist/esm}/plugins/x-gm-ext-1.js +48 -100
- package/dist/esm/plugins/xoauth2.d.ts +2 -0
- package/dist/esm/plugins/xoauth2.js +140 -0
- package/dist/esm/plugins/xtoybird.d.ts +2 -0
- package/dist/esm/plugins/xtoybird.js +218 -0
- package/dist/esm/server.d.ts +876 -0
- package/dist/esm/server.js +2543 -0
- package/dist/esm/smtp-listener.d.ts +13 -0
- package/{lib → dist/esm}/smtp-listener.js +5 -12
- package/dist/esm/sorting.d.ts +77 -0
- package/{lib → dist/esm}/sorting.js +40 -53
- package/dist/esm/threading.d.ts +30 -0
- package/{lib → dist/esm}/threading.js +29 -70
- package/dist/esm/types.d.ts +327 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/utf8-session.d.ts +17 -0
- package/{lib → dist/esm}/utf8-session.js +15 -25
- package/dist/esm/vanished.d.ts +21 -0
- package/{lib → dist/esm}/vanished.js +16 -21
- package/dist/plugin-help.json +298 -0
- package/package.json +54 -11
- package/lib/commands/capability.js +0 -47
- package/lib/commands/check.js +0 -21
- package/lib/commands/close.js +0 -30
- package/lib/commands/examine.js +0 -7
- package/lib/commands/expunge.js +0 -27
- package/lib/commands/list.js +0 -100
- package/lib/commands/logout.js +0 -41
- package/lib/commands/lsub.js +0 -87
- package/lib/commands/noop.js +0 -21
- package/lib/commands/search.js +0 -76
- package/lib/commands/select.js +0 -289
- package/lib/commands/uid copy.js +0 -7
- package/lib/commands/uid fetch.js +0 -5
- package/lib/commands/uid search.js +0 -5
- package/lib/commands/uid store.js +0 -5
- package/lib/plugins/compress.js +0 -76
- package/lib/plugins/enable.js +0 -155
- package/lib/plugins/id.js +0 -138
- package/lib/plugins/idle.js +0 -105
- package/lib/plugins/logindisabled.js +0 -50
- package/lib/plugins/metadata.js +0 -475
- package/lib/plugins/namespace.js +0 -67
- package/lib/plugins/unauthenticate.js +0 -28
- package/lib/plugins/unselect.js +0 -36
- package/lib/plugins/xoauth2.js +0 -188
- package/lib/plugins/xtoybird.js +0 -282
- package/lib/server.js +0 -2880
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = xGmExt1Plugin;
|
|
7
|
+
const search_js_1 = __importDefault(require("../commands/handlers/search.js"));
|
|
8
|
+
const search_js_2 = require("../commands/handlers/search.js");
|
|
9
|
+
const dates_js_1 = require("../dates.js");
|
|
10
|
+
// X-GM-MSGID is a 64 bit unsigned number, so it is tracked as a BigInt
|
|
11
|
+
// Sample value from Gmail IMAP extensions API page
|
|
12
|
+
// https://developers.google.com/workspace/gmail/imap/imap-extensions
|
|
13
|
+
// Used as default, if server.options["HIGHESTX-GM-MSGID"]
|
|
14
|
+
// is missing
|
|
15
|
+
const SEED = '1278455344230334865';
|
|
16
|
+
const MAX_UINT64 = 2n ** 64n - 1n;
|
|
17
|
+
// X-GM-RAW mailbox shortcuts of in: and is: (Gmail search operators), as ImapKit criteria
|
|
18
|
+
const RAW_SHORTCUTS = {
|
|
19
|
+
'in:inbox': ['X-GM-LABELS', '\\Inbox'],
|
|
20
|
+
'in:sent': ['X-GM-LABELS', '\\Sent'],
|
|
21
|
+
'in:drafts': ['X-GM-LABELS', '\\Drafts'],
|
|
22
|
+
'in:trash': ['X-GM-LABELS', '\\Trash'],
|
|
23
|
+
'in:spam': ['X-GM-LABELS', '\\Junk'],
|
|
24
|
+
'in:anywhere': ['ALL'],
|
|
25
|
+
'is:unread': ['UNSEEN'],
|
|
26
|
+
'is:read': ['SEEN'],
|
|
27
|
+
'is:starred': ['FLAGGED'],
|
|
28
|
+
'is:important': ['X-GM-LABELS', '\\Important']
|
|
29
|
+
};
|
|
30
|
+
// X-GM-RAW operators that take a value, as the search key the value is given to
|
|
31
|
+
const RAW_OPERATORS = {
|
|
32
|
+
from: 'FROM',
|
|
33
|
+
to: 'TO',
|
|
34
|
+
cc: 'CC',
|
|
35
|
+
bcc: 'BCC',
|
|
36
|
+
subject: 'SUBJECT',
|
|
37
|
+
label: 'X-GM-LABELS',
|
|
38
|
+
larger: 'LARGER',
|
|
39
|
+
smaller: 'SMALLER',
|
|
40
|
+
after: 'SINCE',
|
|
41
|
+
before: 'BEFORE',
|
|
42
|
+
rfc822msgid: 'HEADER'
|
|
43
|
+
};
|
|
44
|
+
// Gmail operators that ImapKit does not implement, answered with NO instead of a wrong result
|
|
45
|
+
const RAW_UNSUPPORTED = ['is', 'has', 'list', 'filename', 'around', 'size', 'older', 'newer', 'older_than', 'newer_than', 'deliveredto', 'category'];
|
|
46
|
+
/**
|
|
47
|
+
* @help Adds Gmail specific X-GM-EXT-1 capability
|
|
48
|
+
* @help (https://developers.google.com/workspace/gmail/imap/imap-extensions)
|
|
49
|
+
* @help X-GM-MSGID and X-GM-THRID: FETCH and SEARCH. X-GM-THRID is the
|
|
50
|
+
* @help X-GM-MSGID of the message unless storage sets an X-GM-THRID
|
|
51
|
+
* @help value, so every message is its own thread unless the
|
|
52
|
+
* @help fixture groups messages. With OBJECTID, the messages of a
|
|
53
|
+
* @help THREADID share the X-GM-THRID of its first message
|
|
54
|
+
* @help X-GM-LABELS: FETCH, STORE (+/-, .SILENT) and SEARCH. System
|
|
55
|
+
* @help labels are atoms that start with "\" (\Inbox for INBOX, the
|
|
56
|
+
* @help special-use attribute for special-use mailboxes), other labels
|
|
57
|
+
* @help are mailbox names, sent like mailbox names (modified UTF-7, or
|
|
58
|
+
* @help UTF-8 after ENABLE UTF8=ACCEPT, quoted when not atoms). Labels
|
|
59
|
+
* @help have no side effects: the message is not copied to or removed
|
|
60
|
+
* @help from other mailboxes. In SEARCH a label that starts with "\"
|
|
61
|
+
* @help is a system label
|
|
62
|
+
* @help X-GM-RAW: a subset of the Gmail search syntax. Words and "quoted
|
|
63
|
+
* @help phrases" (TEXT), -term, OR, (groups), {any of}, from: to: cc:
|
|
64
|
+
* @help bcc: subject: label: in: (inbox sent drafts trash spam
|
|
65
|
+
* @help anywhere, or a label) is: (read unread starred important)
|
|
66
|
+
* @help larger: smaller: (k and m suffixes) after: before:
|
|
67
|
+
* @help (YYYY/MM/DD) and rfc822msgid:. Other Gmail operators are
|
|
68
|
+
* @help answered with NO
|
|
69
|
+
*/
|
|
70
|
+
function xGmExt1Plugin(server) {
|
|
71
|
+
server.registerCapability('X-GM-EXT-1');
|
|
72
|
+
server['HIGHESTX-GM-MSGID'] = BigInt(server.options['HIGHESTX-GM-MSGID'] || SEED);
|
|
73
|
+
// set X-GM-MSGID values when message is created / initialized
|
|
74
|
+
server.messageHandlers.push((server, message, mailbox) => {
|
|
75
|
+
let labels;
|
|
76
|
+
if (!message['X-GM-MSGID']) {
|
|
77
|
+
server['HIGHESTX-GM-MSGID'] += 1n;
|
|
78
|
+
message['X-GM-MSGID'] = server['HIGHESTX-GM-MSGID'].toString();
|
|
79
|
+
}
|
|
80
|
+
else if (/^\d+$/.test(message['X-GM-MSGID']) && BigInt(message['X-GM-MSGID']) > server['HIGHESTX-GM-MSGID']) {
|
|
81
|
+
// Storage might be shared with another server instance, do not reuse existing values
|
|
82
|
+
server['HIGHESTX-GM-MSGID'] = BigInt(message['X-GM-MSGID']);
|
|
83
|
+
}
|
|
84
|
+
// Ensure message has an array of labels
|
|
85
|
+
message['X-GM-LABELS'] = [].concat(message['X-GM-LABELS'] || []);
|
|
86
|
+
if (mailbox.path.toUpperCase() === 'INBOX') {
|
|
87
|
+
labels = ['\\Inbox'];
|
|
88
|
+
}
|
|
89
|
+
else if (mailbox['special-use'] && mailbox['special-use'].length) {
|
|
90
|
+
labels = [].concat(mailbox['special-use']);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
labels = [userLabel(mailbox.path)];
|
|
94
|
+
}
|
|
95
|
+
labels.forEach(label => {
|
|
96
|
+
server.ensureFlag(message['X-GM-LABELS'], label);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
// A message starts its own thread unless storage puts it into one. With OBJECTID loaded, the messages of a THREADID
|
|
100
|
+
// (RFC 8474 section 5.2) share an X-GM-THRID: the one of the first message of that thread, like Gmail uses the
|
|
101
|
+
// X-GM-MSGID of the first message. This runs after every other message handler, so OBJECTID set the THREADID
|
|
102
|
+
// already, whatever the load order is
|
|
103
|
+
const gmThreads = new Map();
|
|
104
|
+
server.once('pluginsLoaded', () => {
|
|
105
|
+
server.messageHandlers.push((server, message) => {
|
|
106
|
+
const known = message.THREADID && gmThreads.get(message.THREADID);
|
|
107
|
+
if (!message['X-GM-THRID']) {
|
|
108
|
+
message['X-GM-THRID'] = known || message['X-GM-MSGID'];
|
|
109
|
+
}
|
|
110
|
+
if (message.THREADID && !known) {
|
|
111
|
+
gmThreads.set(message.THREADID, message['X-GM-THRID']);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
// Retrieve X-GM-MSGID values with FETCH
|
|
116
|
+
server.fetchHandlers['X-GM-MSGID'] = function (connection, message) {
|
|
117
|
+
return {
|
|
118
|
+
type: 'ATOM',
|
|
119
|
+
value: message['X-GM-MSGID']
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
// Retrieve X-GM-LABELS values with FETCH
|
|
123
|
+
server.fetchHandlers['X-GM-LABELS'] = function (connection, message) {
|
|
124
|
+
return formatLabels(message);
|
|
125
|
+
};
|
|
126
|
+
// X-GM-MSGID and X-GM-THRID are 64 bit unsigned numbers
|
|
127
|
+
const idArgument = () => [
|
|
128
|
+
(value) => {
|
|
129
|
+
if (!/^\d{1,20}$/.test(value) || BigInt(value) > MAX_UINT64) {
|
|
130
|
+
throw (0, search_js_2.badError)('Expected a 64 bit unsigned number');
|
|
131
|
+
}
|
|
132
|
+
return BigInt(value).toString();
|
|
133
|
+
}
|
|
134
|
+
];
|
|
135
|
+
server.searchHandlers['X-GM-MSGID'] = function (connection, message, sequence, xGmMsgid) {
|
|
136
|
+
return message['X-GM-MSGID'] === xGmMsgid;
|
|
137
|
+
};
|
|
138
|
+
server.searchHandlers['X-GM-MSGID'].argumentTypes = idArgument;
|
|
139
|
+
// Retrieve X-GM-THRID values with FETCH
|
|
140
|
+
server.fetchHandlers['X-GM-THRID'] = function (connection, message) {
|
|
141
|
+
return {
|
|
142
|
+
type: 'ATOM',
|
|
143
|
+
value: message['X-GM-THRID']
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
server.searchHandlers['X-GM-THRID'] = function (connection, message, sequence, xGmThrid) {
|
|
147
|
+
return message['X-GM-THRID'] === xGmThrid;
|
|
148
|
+
};
|
|
149
|
+
server.searchHandlers['X-GM-THRID'].argumentTypes = idArgument;
|
|
150
|
+
// SEARCH X-GM-LABELS label, the label is given in the form the session uses for mailbox names
|
|
151
|
+
server.searchHandlers['X-GM-LABELS'] = function (connection, message, sequence, label) {
|
|
152
|
+
return message['X-GM-LABELS'].some((stored) => {
|
|
153
|
+
if (isSystemLabel(stored)) {
|
|
154
|
+
// system labels are matched without case, like flags
|
|
155
|
+
return stored.toLowerCase() === label.toLowerCase();
|
|
156
|
+
}
|
|
157
|
+
return connection.exportMailboxName(labelName(stored)) === label;
|
|
158
|
+
});
|
|
159
|
+
};
|
|
160
|
+
// SEARCH X-GM-RAW query, a subset of the Gmail search syntax
|
|
161
|
+
// the translated criteria are compiled once per SEARCH, they are the same array for every message
|
|
162
|
+
const rawMatchers = new WeakMap();
|
|
163
|
+
server.searchHandlers['X-GM-RAW'] = function (connection, message, sequence, criteria) {
|
|
164
|
+
if (!rawMatchers.has(criteria)) {
|
|
165
|
+
// without UTF8=ACCEPT the translated criteria take a CHARSET, Gmail queries are UTF-8
|
|
166
|
+
const params = connection.searchCharset ? criteria : ['CHARSET', 'UTF-8'].concat(criteria);
|
|
167
|
+
rawMatchers.set(criteria, (0, search_js_1.default)(connection, [], params, () => []).matches);
|
|
168
|
+
}
|
|
169
|
+
return rawMatchers.get(criteria)(message, sequence);
|
|
170
|
+
};
|
|
171
|
+
server.searchHandlers['X-GM-RAW'].argumentTypes = () => [parseRawQuery];
|
|
172
|
+
const setLabels = (message, labels) => {
|
|
173
|
+
message['X-GM-LABELS'] = [];
|
|
174
|
+
addLabels(message, labels);
|
|
175
|
+
};
|
|
176
|
+
const addLabels = (message, labels) => {
|
|
177
|
+
labels.forEach((label) => server.ensureFlag(message['X-GM-LABELS'], label));
|
|
178
|
+
};
|
|
179
|
+
const removeLabels = (message, labels) => {
|
|
180
|
+
labels.forEach((label) => server.removeFlag(message['X-GM-LABELS'], label));
|
|
181
|
+
};
|
|
182
|
+
[
|
|
183
|
+
['X-GM-LABELS', setLabels],
|
|
184
|
+
['+X-GM-LABELS', addLabels],
|
|
185
|
+
['-X-GM-LABELS', removeLabels]
|
|
186
|
+
].forEach(([name, update]) => {
|
|
187
|
+
// all labels are parsed before the message changes, an invalid one fails the STORE
|
|
188
|
+
const apply = (connection, message, flags) => update(message, flags.map(flag => parseLabel(connection, flag)));
|
|
189
|
+
server.storeHandlers[name] = function (connection, message, flags, index, parsed, data) {
|
|
190
|
+
apply(connection, message, flags);
|
|
191
|
+
sendLabelUpdate(connection, parsed, data, index, message);
|
|
192
|
+
};
|
|
193
|
+
server.storeHandlers[name + '.SILENT'] = apply;
|
|
194
|
+
// labels are astrings (Gmail IMAP extensions): literals are accepted, NIL is a label name
|
|
195
|
+
server.storeHandlers[name].astringValues = server.storeHandlers[name + '.SILENT'].astringValues = true;
|
|
196
|
+
});
|
|
197
|
+
// Gmail keeps the same X-GM-MSGID for a message in every mailbox, so copies get the value of the source message
|
|
198
|
+
server.copyHandlers.push((server, source, copy) => {
|
|
199
|
+
if (source['X-GM-MSGID']) {
|
|
200
|
+
copy['X-GM-MSGID'] = source['X-GM-MSGID'];
|
|
201
|
+
copy['X-GM-THRID'] = source['X-GM-THRID'];
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Labels are kept as strings in message["X-GM-LABELS"]. A system label like \Inbox starts with "\",
|
|
207
|
+
* any other label is a mailbox name in storage form. A mailbox name that itself starts with "\" is
|
|
208
|
+
* kept with one more "\" in front, so it can not be mistaken for a system label
|
|
209
|
+
*/
|
|
210
|
+
const isSystemLabel = (label) => label.charAt(0) === '\\' && label.charAt(1) !== '\\';
|
|
211
|
+
const userLabel = (name) => (name.charAt(0) === '\\' ? '\\' + name : name);
|
|
212
|
+
const labelName = (label) => (label.charAt(0) === '\\' ? label.substr(1) : label);
|
|
213
|
+
/**
|
|
214
|
+
* Converts a STORE X-GM-LABELS value to a stored label. An atom that starts with "\" is a system
|
|
215
|
+
* label, anything else is a label name: an astring in the form the session uses for mailbox names
|
|
216
|
+
*
|
|
217
|
+
* @param {Object} connection IMAP connection
|
|
218
|
+
* @param {Object} attr Parsed value
|
|
219
|
+
* @return {String} Stored label
|
|
220
|
+
*/
|
|
221
|
+
function parseLabel(connection, attr) {
|
|
222
|
+
const value = String((attr && attr.value) || '');
|
|
223
|
+
if (attr.type === 'ATOM' && value.charAt(0) === '\\') {
|
|
224
|
+
return value;
|
|
225
|
+
}
|
|
226
|
+
return userLabel(connection.importMailboxName(value));
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Formats the labels of a message for a FETCH response. Label names are MAILBOX attributes, so the
|
|
230
|
+
* session gets them in its own form and quoted when they are not atoms
|
|
231
|
+
*/
|
|
232
|
+
function formatLabels(message) {
|
|
233
|
+
return message['X-GM-LABELS'].map((label) => isSystemLabel(label) ? { type: 'ATOM', value: label } : { type: 'MAILBOX', value: labelName(label) });
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Translates an X-GM-RAW query (Gmail search syntax) to ImapKit search criteria. Terms are
|
|
237
|
+
* ANDed, OR binds tighter than that ("a b OR c" is a AND (b OR c)), "-" negates a term, ( ) groups
|
|
238
|
+
* terms and { } matches any of its terms.
|
|
239
|
+
*
|
|
240
|
+
* @param {String} query Query as a binary string, UTF-8
|
|
241
|
+
* @return {Array} Search criteria
|
|
242
|
+
* @throws {Error} BAD for a query that can not be parsed, NO for an unsupported operator
|
|
243
|
+
*/
|
|
244
|
+
function parseRawQuery(query) {
|
|
245
|
+
const tokens = [];
|
|
246
|
+
const re = /\s*(?:([(){}])|"([^"]*)"|([^\s(){}"]+?:)"([^"]*)"|([^\s(){}"]+))/gy;
|
|
247
|
+
let match;
|
|
248
|
+
// end of the last token, a failed sticky match resets lastIndex
|
|
249
|
+
let end = 0;
|
|
250
|
+
while (end < query.length && (match = re.exec(query))) {
|
|
251
|
+
end = re.lastIndex;
|
|
252
|
+
if (match[1]) {
|
|
253
|
+
tokens.push({ type: match[1] });
|
|
254
|
+
}
|
|
255
|
+
else if (typeof match[2] === 'string') {
|
|
256
|
+
tokens.push({ type: 'word', value: match[2] });
|
|
257
|
+
}
|
|
258
|
+
else if (match[3]) {
|
|
259
|
+
tokens.push({ type: 'word', value: match[3] + match[4], operator: match[3].slice(0, -1), operand: match[4] });
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
tokens.push({ type: 'word', value: match[5] });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (query.slice(end).trim()) {
|
|
266
|
+
throw (0, search_js_2.badError)('X-GM-RAW query has an unterminated quoted string');
|
|
267
|
+
}
|
|
268
|
+
let pos = 0;
|
|
269
|
+
const peek = () => tokens[pos];
|
|
270
|
+
// expression = 1*term, until the end or a closing bracket
|
|
271
|
+
const expression = (end) => {
|
|
272
|
+
const terms = [];
|
|
273
|
+
while (pos < tokens.length && (!peek() || peek().type !== end)) {
|
|
274
|
+
terms.push(term());
|
|
275
|
+
}
|
|
276
|
+
if (end) {
|
|
277
|
+
if (!peek() || peek().type !== end) {
|
|
278
|
+
throw (0, search_js_2.badError)('X-GM-RAW query is missing "' + end + '"');
|
|
279
|
+
}
|
|
280
|
+
pos++;
|
|
281
|
+
}
|
|
282
|
+
if (!terms.length) {
|
|
283
|
+
throw (0, search_js_2.badError)('X-GM-RAW query is empty');
|
|
284
|
+
}
|
|
285
|
+
return terms.length === 1 ? terms[0] : terms;
|
|
286
|
+
};
|
|
287
|
+
// term = unary *("OR" unary)
|
|
288
|
+
const term = () => {
|
|
289
|
+
let result = unary();
|
|
290
|
+
while (peek() && peek().type === 'word' && peek().value === 'OR' && tokens[pos + 1]) {
|
|
291
|
+
pos++;
|
|
292
|
+
result = ['OR', result, unary()];
|
|
293
|
+
}
|
|
294
|
+
return result;
|
|
295
|
+
};
|
|
296
|
+
const unary = () => {
|
|
297
|
+
const token = tokens[pos++];
|
|
298
|
+
if (!token || token.type === ')' || token.type === '}') {
|
|
299
|
+
throw (0, search_js_2.badError)('Unexpected end of X-GM-RAW query');
|
|
300
|
+
}
|
|
301
|
+
if (token.type === '(') {
|
|
302
|
+
return expression(')');
|
|
303
|
+
}
|
|
304
|
+
if (token.type === '{') {
|
|
305
|
+
const options = [];
|
|
306
|
+
while (peek() && peek().type !== '}') {
|
|
307
|
+
options.push(unary());
|
|
308
|
+
}
|
|
309
|
+
if (!peek() || !options.length) {
|
|
310
|
+
throw (0, search_js_2.badError)('X-GM-RAW query has an empty or unterminated { } group');
|
|
311
|
+
}
|
|
312
|
+
pos++;
|
|
313
|
+
return options.reduce((any, option) => ['OR', any, option]);
|
|
314
|
+
}
|
|
315
|
+
// the brackets are handled above, a word always has a value
|
|
316
|
+
const value = token.value;
|
|
317
|
+
if (value === '-' && peek() && (peek().type === '(' || peek().type === '{')) {
|
|
318
|
+
return ['NOT', unary()];
|
|
319
|
+
}
|
|
320
|
+
if (value.charAt(0) === '-' && value.length > 1) {
|
|
321
|
+
return ['NOT', rawTerm(rawWord(value.substr(1)))];
|
|
322
|
+
}
|
|
323
|
+
return rawTerm(token);
|
|
324
|
+
};
|
|
325
|
+
return [expression()];
|
|
326
|
+
}
|
|
327
|
+
// splits "name:value" into an operator and an operand
|
|
328
|
+
function rawWord(value) {
|
|
329
|
+
const match = value.match(/^([a-z_0-9]+):(.+)$/i);
|
|
330
|
+
return match ? { value, operator: match[1], operand: match[2] } : { value, operator: false, operand: false };
|
|
331
|
+
}
|
|
332
|
+
function rawTerm(token) {
|
|
333
|
+
const word = token.operator ? token : rawWord(token.value);
|
|
334
|
+
const operator = word.operator;
|
|
335
|
+
if (!operator) {
|
|
336
|
+
return ['TEXT', token.value];
|
|
337
|
+
}
|
|
338
|
+
// an operator always comes with its operand
|
|
339
|
+
const operand = word.operand;
|
|
340
|
+
const name = operator.toLowerCase();
|
|
341
|
+
// own keys only, names like "constructor:" are plain text
|
|
342
|
+
const shortcutKey = name + ':' + operand.toLowerCase();
|
|
343
|
+
const shortcut = Object.hasOwn(RAW_SHORTCUTS, shortcutKey) && RAW_SHORTCUTS[shortcutKey];
|
|
344
|
+
if (shortcut) {
|
|
345
|
+
return shortcut;
|
|
346
|
+
}
|
|
347
|
+
const key = Object.hasOwn(RAW_OPERATORS, name) && RAW_OPERATORS[name];
|
|
348
|
+
if (key) {
|
|
349
|
+
switch (key) {
|
|
350
|
+
case 'LARGER':
|
|
351
|
+
case 'SMALLER': {
|
|
352
|
+
const size = operand.match(/^(\d+)([km]?)$/i);
|
|
353
|
+
if (!size) {
|
|
354
|
+
throw (0, search_js_2.badError)('X-GM-RAW ' + name + ': expects a size');
|
|
355
|
+
}
|
|
356
|
+
return [key, String(Number(size[1]) * { '': 1, k: 1024, m: 1024 * 1024 }[size[2].toLowerCase()])];
|
|
357
|
+
}
|
|
358
|
+
case 'SINCE':
|
|
359
|
+
case 'BEFORE': {
|
|
360
|
+
const date = operand.match(/^(\d{4})[/-](\d{1,2})[/-](\d{1,2})$/);
|
|
361
|
+
if (!date || !(0, dates_js_1.isRealDate)(Number(date[3]), Number(date[2]) - 1, Number(date[1]))) {
|
|
362
|
+
throw (0, search_js_2.badError)('X-GM-RAW ' + name + ': expects a date as YYYY/MM/DD');
|
|
363
|
+
}
|
|
364
|
+
return [key, Number(date[3]) + '-' + dates_js_1.MONTHS[Number(date[2]) - 1] + '-' + date[1]];
|
|
365
|
+
}
|
|
366
|
+
case 'HEADER':
|
|
367
|
+
return [key, 'Message-ID', operand];
|
|
368
|
+
default:
|
|
369
|
+
return [key, operand];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (name === 'in') {
|
|
373
|
+
// any other mailbox is a label
|
|
374
|
+
return ['X-GM-LABELS', operand];
|
|
375
|
+
}
|
|
376
|
+
if (RAW_UNSUPPORTED.indexOf(name) >= 0) {
|
|
377
|
+
const err = new Error('X-GM-RAW operator ' + name + ':' + operand + ' is not supported by imapkit');
|
|
378
|
+
err.imapResponse = 'NO';
|
|
379
|
+
throw err;
|
|
380
|
+
}
|
|
381
|
+
// not an operator, like "http://example.com"
|
|
382
|
+
return ['TEXT', token.value];
|
|
383
|
+
}
|
|
384
|
+
function sendLabelUpdate(connection, parsed, data, index, message) {
|
|
385
|
+
const resp = [
|
|
386
|
+
{
|
|
387
|
+
type: 'ATOM',
|
|
388
|
+
value: 'X-GM-LABELS'
|
|
389
|
+
},
|
|
390
|
+
formatLabels(message)
|
|
391
|
+
];
|
|
392
|
+
if ((parsed.command || '').toUpperCase() === 'UID STORE') {
|
|
393
|
+
resp.push({
|
|
394
|
+
type: 'ATOM',
|
|
395
|
+
value: 'UID'
|
|
396
|
+
});
|
|
397
|
+
resp.push(message.uid);
|
|
398
|
+
}
|
|
399
|
+
connection.send({
|
|
400
|
+
tag: '*',
|
|
401
|
+
attributes: [
|
|
402
|
+
index,
|
|
403
|
+
{
|
|
404
|
+
type: 'ATOM',
|
|
405
|
+
value: 'FETCH'
|
|
406
|
+
},
|
|
407
|
+
resp
|
|
408
|
+
]
|
|
409
|
+
}, 'FLAG UPDATE', parsed, data, message);
|
|
410
|
+
}
|
|
411
|
+
{
|
|
412
|
+
const defaultExport = exports.default;
|
|
413
|
+
if (defaultExport && (typeof defaultExport === 'function' || typeof defaultExport === 'object')) {
|
|
414
|
+
for (const key of Object.keys(exports)) {
|
|
415
|
+
if (key !== 'default' && !(key in defaultExport)) {
|
|
416
|
+
defaultExport[key] = exports[key];
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
Object.defineProperty(defaultExport, 'default', { value: defaultExport, enumerable: false, writable: true, configurable: true });
|
|
420
|
+
module.exports = defaultExport;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = xoauth2Plugin;
|
|
4
|
+
// https://developers.google.com/gmail/xoauth2_protocol
|
|
5
|
+
/**
|
|
6
|
+
* @help Enables XOAUTH2 capability
|
|
7
|
+
* @help Implementation difference - ImapKit requires
|
|
8
|
+
* @help SASL-IR enabled and used while Gmail does not
|
|
9
|
+
* @help Valid login info:
|
|
10
|
+
* @help Username: testuser
|
|
11
|
+
* @help Access Token: testtoken
|
|
12
|
+
*/
|
|
13
|
+
const utf8 = new TextDecoder('utf-8', { fatal: true });
|
|
14
|
+
function xoauth2Plugin(server) {
|
|
15
|
+
// Register capability, usable for non authenticated users
|
|
16
|
+
server.registerCapability('AUTH=XOAUTH2', (connection) => {
|
|
17
|
+
return connection.state === 'Not Authenticated';
|
|
18
|
+
});
|
|
19
|
+
server.setCommandHandler('AUTHENTICATE XOAUTH2', (connection, parsed, data, callback) => {
|
|
20
|
+
if (!server.capabilities['SASL-IR'] || !server.capabilities['SASL-IR'](connection)) {
|
|
21
|
+
connection.send({
|
|
22
|
+
tag: parsed.tag,
|
|
23
|
+
command: 'BAD',
|
|
24
|
+
attributes: [
|
|
25
|
+
{
|
|
26
|
+
type: 'TEXT',
|
|
27
|
+
value: 'SASL-IR must be enabled to support XOAUTH2'
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}, 'AUTHENTICATE XOAUTH2 FAILED', parsed, data);
|
|
31
|
+
return callback();
|
|
32
|
+
}
|
|
33
|
+
if (!parsed.attributes || parsed.attributes.length !== 1 || !parsed.attributes[0] || ['STRING', 'ATOM'].indexOf(parsed.attributes[0].type) < 0) {
|
|
34
|
+
connection.send({
|
|
35
|
+
tag: parsed.tag,
|
|
36
|
+
command: 'NO',
|
|
37
|
+
attributes: [
|
|
38
|
+
{
|
|
39
|
+
type: 'TEXT',
|
|
40
|
+
value: 'Invalid SASL argument'
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}, 'AUTHENTICATE XOAUTH2 FAILED', parsed, data);
|
|
44
|
+
return callback();
|
|
45
|
+
}
|
|
46
|
+
const decoded = connection.decodeSaslResponse(parsed.attributes[0].value);
|
|
47
|
+
if (!decoded) {
|
|
48
|
+
connection.sendStatus(parsed, data, 'BAD', 'Invalid base64 in SASL response', false, 'AUTHENTICATE XOAUTH2 FAILED');
|
|
49
|
+
return callback();
|
|
50
|
+
}
|
|
51
|
+
let parts = [];
|
|
52
|
+
try {
|
|
53
|
+
// user names are unicode strings, like the keys of `users`
|
|
54
|
+
parts = utf8.decode(decoded).split('\x01');
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// invalid UTF-8 is a malformed payload like any other
|
|
58
|
+
}
|
|
59
|
+
const user = (parts[0] || '').substr(5);
|
|
60
|
+
const accessToken = (parts[1] || '').substr(12);
|
|
61
|
+
if (parts.length !== 4 ||
|
|
62
|
+
!parts[0].match(/^user=/) ||
|
|
63
|
+
!parts[1].match(/^auth=Bearer /) ||
|
|
64
|
+
!user || // Must be present
|
|
65
|
+
!accessToken || // Must be present
|
|
66
|
+
parts[2] || // Must be empty
|
|
67
|
+
parts[3] // Must be empty
|
|
68
|
+
) {
|
|
69
|
+
connection.send({
|
|
70
|
+
tag: parsed.tag,
|
|
71
|
+
command: 'NO',
|
|
72
|
+
attributes: [
|
|
73
|
+
{
|
|
74
|
+
type: 'TEXT',
|
|
75
|
+
value: 'Invalid SASL argument.'
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}, 'AUTHENTICATE XOAUTH2 FAILED', parsed, data);
|
|
79
|
+
return callback();
|
|
80
|
+
}
|
|
81
|
+
const userData = connection.server.getUser(user);
|
|
82
|
+
if (!userData) {
|
|
83
|
+
connection.send({
|
|
84
|
+
tag: parsed.tag,
|
|
85
|
+
command: 'NO',
|
|
86
|
+
attributes: [
|
|
87
|
+
// RFC 5530 section 3: unknown user or bad token
|
|
88
|
+
{ type: 'SECTION', section: [{ type: 'ATOM', value: 'AUTHENTICATIONFAILED' }] },
|
|
89
|
+
{
|
|
90
|
+
type: 'TEXT',
|
|
91
|
+
value: 'Invalid credentials'
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}, 'AUTHENTICATE XOAUTH2 FAILED', parsed, data);
|
|
95
|
+
return callback();
|
|
96
|
+
}
|
|
97
|
+
if (!userData.xoauth2 || userData.xoauth2.accessToken !== accessToken) {
|
|
98
|
+
connection.send({
|
|
99
|
+
tag: '+',
|
|
100
|
+
attributes: [
|
|
101
|
+
{
|
|
102
|
+
type: 'ATOM',
|
|
103
|
+
value: Buffer.from(JSON.stringify({
|
|
104
|
+
status: '400',
|
|
105
|
+
schemes: 'Bearer',
|
|
106
|
+
scope: 'https://mail.google.com/'
|
|
107
|
+
})).toString('base64')
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}, 'AUTHENTICATE XOAUTH2 FAILED', parsed, data);
|
|
111
|
+
// wait for response
|
|
112
|
+
connection.inputHandler = function () {
|
|
113
|
+
connection.inputHandler = false;
|
|
114
|
+
connection.send({
|
|
115
|
+
tag: parsed.tag,
|
|
116
|
+
command: 'NO',
|
|
117
|
+
attributes: [
|
|
118
|
+
{ type: 'SECTION', section: [{ type: 'ATOM', value: 'AUTHENTICATIONFAILED' }] },
|
|
119
|
+
{
|
|
120
|
+
type: 'TEXT',
|
|
121
|
+
value: 'SASL authentication failed'
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}, 'AUTHENTICATE XOAUTH2 FAILED', parsed, data);
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
connection.state = 'Authenticated';
|
|
129
|
+
connection.username = user;
|
|
130
|
+
connection.send({
|
|
131
|
+
tag: parsed.tag,
|
|
132
|
+
command: 'OK',
|
|
133
|
+
attributes: [
|
|
134
|
+
{
|
|
135
|
+
type: 'TEXT',
|
|
136
|
+
value: 'User logged in'
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}, 'AUTHENTICATE XOAUTH2 SUCCESS', parsed, data);
|
|
140
|
+
}
|
|
141
|
+
return callback();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
{
|
|
145
|
+
const defaultExport = exports.default;
|
|
146
|
+
if (defaultExport && (typeof defaultExport === 'function' || typeof defaultExport === 'object')) {
|
|
147
|
+
for (const key of Object.keys(exports)) {
|
|
148
|
+
if (key !== 'default' && !(key in defaultExport)) {
|
|
149
|
+
defaultExport[key] = exports[key];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
Object.defineProperty(defaultExport, 'default', { value: defaultExport, enumerable: false, writable: true, configurable: true });
|
|
153
|
+
module.exports = defaultExport;
|
|
154
|
+
}
|
|
155
|
+
}
|