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,85 @@
|
|
|
1
|
+
import type { Attribute, IMAPConnection, IMAPError, IMAPServer, Message, MessageRange, ParsedCommand } from '../../types.js';
|
|
2
|
+
/** The type of a search key argument: a type name, or a function that parses the value and throws for an invalid one */
|
|
3
|
+
export type SearchArgumentType = string | ((value: string) => any);
|
|
4
|
+
/** The argument types of a search key, or a function that decides them from the criteria that follow the key */
|
|
5
|
+
export type SearchKeyTypes = SearchArgumentType[] | ((list: Attribute[]) => SearchArgumentType[]);
|
|
6
|
+
/** A node of the query tree that the search builds from the criteria */
|
|
7
|
+
export interface SearchNode {
|
|
8
|
+
key: string;
|
|
9
|
+
args: any[];
|
|
10
|
+
/** the messages of a sequence set (`_SEQ`) or a UID set */
|
|
11
|
+
set?: Set<Message> | undefined;
|
|
12
|
+
/** the lower cased string to look for */
|
|
13
|
+
needle?: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
/** Resolves a sequence set of the criteria */
|
|
16
|
+
export type RangeResolver = (range: string, isUid: boolean) => MessageRange;
|
|
17
|
+
/** The result of a search */
|
|
18
|
+
export interface SearchResult {
|
|
19
|
+
/** the matching messages */
|
|
20
|
+
list: Message[];
|
|
21
|
+
/** sequence numbers by UID */
|
|
22
|
+
numbers: Record<number, number>;
|
|
23
|
+
/** the search keys used in the criteria, other than sequence sets */
|
|
24
|
+
keys: Set<string>;
|
|
25
|
+
/** checks a message against the same criteria later */
|
|
26
|
+
matches: (message: Message, index: number) => boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates an error that is reported to the client as BAD
|
|
30
|
+
*/
|
|
31
|
+
declare function badError(message: string): IMAPError;
|
|
32
|
+
/**
|
|
33
|
+
* Date of a date-time value, disregarding time and timezone, as a comparable YYYY-MM-DD string,
|
|
34
|
+
* or false when it can not be parsed
|
|
35
|
+
*
|
|
36
|
+
* @param {String} dateTime Date-time value, e.g. "14-Sep-2013 21:22:28 -0300"
|
|
37
|
+
* @return {String|Boolean} date or false
|
|
38
|
+
*/
|
|
39
|
+
declare function getDateKey(dateTime: string): string | false;
|
|
40
|
+
/**
|
|
41
|
+
* Converts the parsed search criteria of a command to the values the search takes, parenthesized lists stay nested
|
|
42
|
+
*
|
|
43
|
+
* @param {Array} attributes Parsed arguments
|
|
44
|
+
* @return {Array} values
|
|
45
|
+
* @throws {Error} BAD error for an argument that can not be a search key or its value
|
|
46
|
+
*/
|
|
47
|
+
declare function criteriaValues(attributes: Attribute[]): any[];
|
|
48
|
+
/**
|
|
49
|
+
* Answers a failed search with NO, or BAD for `err.imapResponse` "BAD": the BADCHARSET response code with the
|
|
50
|
+
* supported charsets (RFC 3501 section 7.1, RFC 5256 section 3), or the response code a search limit set
|
|
51
|
+
* (`err.responseCode`), and the text
|
|
52
|
+
*
|
|
53
|
+
* @param {Object} connection IMAP connection
|
|
54
|
+
* @param {Object} parsed Parsed command
|
|
55
|
+
* @param {String} data Raw command
|
|
56
|
+
* @param {Error} err Search error
|
|
57
|
+
* @param {String} description Description for output handlers
|
|
58
|
+
*/
|
|
59
|
+
declare function sendSearchError(connection: IMAPConnection, parsed: ParsedCommand, data: string, err: IMAPError, description: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Checks if SEARCH criteria refer to messages by sequence number (RFC 3501 section 5.5), that is,
|
|
62
|
+
* if a sequence set is used as a search key. Arguments of search keys, like the UID set of UID
|
|
63
|
+
* or a string that looks like a number, are not search keys.
|
|
64
|
+
*
|
|
65
|
+
* @param {Object} server IMAP server
|
|
66
|
+
* @param {Array} attributes Parsed SEARCH arguments, nested lists are arrays
|
|
67
|
+
* @return {Boolean} true if a sequence set key occurs
|
|
68
|
+
*/
|
|
69
|
+
declare function hasSequenceSetKey(server: IMAPServer, attributes: Attribute[]): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Searches messages. Errors thrown for the client are answered with BAD when `imapResponse` is "BAD",
|
|
72
|
+
* otherwise NO. SORT and THREAD send `responseCode` (a list of atoms) as the response code
|
|
73
|
+
*
|
|
74
|
+
* @param {Object} connection IMAP connection
|
|
75
|
+
* @param {Array} messageSource Messages of the selected mailbox, as the session sees them
|
|
76
|
+
* @param {Array} params Search criteria: strings, and arrays for parenthesized lists
|
|
77
|
+
* @param {Function} [getMessageRange] Resolves the sequence sets of the criteria, `(range, isUid)`, defaults to
|
|
78
|
+
* the selected mailbox of the connection. Used to search a mailbox that is not selected
|
|
79
|
+
* @return {Object} `{ list, numbers, keys, matches }`, the matching messages, the sequence numbers by UID,
|
|
80
|
+
* the set of search keys used in the criteria and a `matches(message, index)` function that checks
|
|
81
|
+
* a message against the same criteria later. Sequence sets in the criteria stay as they were resolved
|
|
82
|
+
* now, they are not evaluated again
|
|
83
|
+
*/
|
|
84
|
+
export default function searchHandlers(connection: IMAPConnection, messageSource: Message[], params: any, getMessageRange?: RangeResolver | null): SearchResult;
|
|
85
|
+
export { hasSequenceSetKey, getDateKey, badError, criteriaValues, sendSearchError };
|
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = searchHandlers;
|
|
4
|
+
exports.hasSequenceSetKey = hasSequenceSetKey;
|
|
5
|
+
exports.getDateKey = getDateKey;
|
|
6
|
+
exports.badError = badError;
|
|
7
|
+
exports.criteriaValues = criteriaValues;
|
|
8
|
+
exports.sendSearchError = sendSearchError;
|
|
9
|
+
const node_buffer_1 = require("node:buffer");
|
|
10
|
+
const mimeparser_js_1 = require("../../mimeparser.js");
|
|
11
|
+
const dates_js_1 = require("../../dates.js");
|
|
12
|
+
const numbers_js_1 = require("../../numbers.js");
|
|
13
|
+
const encoded_words_js_1 = require("../../encoded-words.js");
|
|
14
|
+
// RFC 3501 6.4.4 search keys and their arguments
|
|
15
|
+
const searchKeys = {
|
|
16
|
+
ALL: [],
|
|
17
|
+
ANSWERED: [],
|
|
18
|
+
BCC: ['string'],
|
|
19
|
+
BEFORE: ['date'],
|
|
20
|
+
BODY: ['string'],
|
|
21
|
+
CC: ['string'],
|
|
22
|
+
DELETED: [],
|
|
23
|
+
DRAFT: [],
|
|
24
|
+
FLAGGED: [],
|
|
25
|
+
FROM: ['string'],
|
|
26
|
+
HEADER: ['string', 'string'],
|
|
27
|
+
KEYWORD: ['string'],
|
|
28
|
+
LARGER: ['number64'],
|
|
29
|
+
NEW: [],
|
|
30
|
+
NOT: ['key'],
|
|
31
|
+
OLD: [],
|
|
32
|
+
ON: ['date'],
|
|
33
|
+
OR: ['key', 'key'],
|
|
34
|
+
RECENT: [],
|
|
35
|
+
SEEN: [],
|
|
36
|
+
SENTBEFORE: ['date'],
|
|
37
|
+
SENTON: ['date'],
|
|
38
|
+
SENTSINCE: ['date'],
|
|
39
|
+
SINCE: ['date'],
|
|
40
|
+
SMALLER: ['number64'],
|
|
41
|
+
SUBJECT: ['string'],
|
|
42
|
+
TEXT: ['string'],
|
|
43
|
+
TO: ['string'],
|
|
44
|
+
UID: ['sequence'],
|
|
45
|
+
UNANSWERED: [],
|
|
46
|
+
UNDELETED: [],
|
|
47
|
+
UNDRAFT: [],
|
|
48
|
+
UNFLAGGED: [],
|
|
49
|
+
UNKEYWORD: ['string'],
|
|
50
|
+
UNSEEN: []
|
|
51
|
+
};
|
|
52
|
+
// Charsets accepted for the CHARSET argument (RFC 3501 6.4.4: US-ASCII must be supported)
|
|
53
|
+
const charsets = ['US-ASCII', 'UTF-8'];
|
|
54
|
+
/**
|
|
55
|
+
* Creates an error that is reported to the client as BAD
|
|
56
|
+
*/
|
|
57
|
+
function badError(message) {
|
|
58
|
+
const err = new Error(message);
|
|
59
|
+
err.imapResponse = 'BAD';
|
|
60
|
+
return err;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Parses an RFC 3501 date argument (date-day "-" date-month "-" date-year) to a comparable YYYY-MM-DD string
|
|
64
|
+
*/
|
|
65
|
+
function parseQueryDate(value) {
|
|
66
|
+
const match = (value || '').toString().match(/^(\d{1,2})-([A-Za-z]{3})-(\d{4})$/);
|
|
67
|
+
const date = match && (0, dates_js_1.dateKey)(Number(match[1]), (0, dates_js_1.monthIndex)(match[2]), Number(match[3]));
|
|
68
|
+
if (!date) {
|
|
69
|
+
throw badError('Invalid date argument ' + value);
|
|
70
|
+
}
|
|
71
|
+
return date;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Date of a date-time value, disregarding time and timezone, as a comparable YYYY-MM-DD string,
|
|
75
|
+
* or false when it can not be parsed
|
|
76
|
+
*
|
|
77
|
+
* @param {String} dateTime Date-time value, e.g. "14-Sep-2013 21:22:28 -0300"
|
|
78
|
+
* @return {String|Boolean} date or false
|
|
79
|
+
*/
|
|
80
|
+
function getDateKey(dateTime) {
|
|
81
|
+
const date = (0, dates_js_1.parseDateTime)(dateTime);
|
|
82
|
+
return date ? (0, dates_js_1.dateKey)(date.day, date.month, date.year) : false;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Date of the internal date of a message, disregarding time and timezone, or false when it can not be parsed
|
|
86
|
+
*/
|
|
87
|
+
function getInternalDate(message) {
|
|
88
|
+
return getDateKey(message.internaldate);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Date of the Date header of a message, disregarding time and timezone (RFC 3501 section 6.4.4, unlike the
|
|
92
|
+
* sent date of SORT it is not adjusted to UTC). Falls back to the internal date
|
|
93
|
+
*/
|
|
94
|
+
function getSentDate(message) {
|
|
95
|
+
const date = (0, dates_js_1.parseHeaderDate)((0, mimeparser_js_1.getMessageData)(message).tree.parsedHeader.date);
|
|
96
|
+
return date ? (0, dates_js_1.dateKey)(date.day, date.month, date.year) : getInternalDate(message);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Converts the parsed search criteria of a command to the values the search takes, parenthesized lists stay nested
|
|
100
|
+
*
|
|
101
|
+
* @param {Array} attributes Parsed arguments
|
|
102
|
+
* @return {Array} values
|
|
103
|
+
* @throws {Error} BAD error for an argument that can not be a search key or its value
|
|
104
|
+
*/
|
|
105
|
+
function criteriaValues(attributes) {
|
|
106
|
+
const convert = (argument, i) => {
|
|
107
|
+
if (Array.isArray(argument)) {
|
|
108
|
+
return argument.map(convert);
|
|
109
|
+
}
|
|
110
|
+
if (!argument || ['STRING', 'ATOM', 'LITERAL', 'SEQUENCE'].indexOf(argument.type) < 0) {
|
|
111
|
+
throw badError('Invalid search criteria argument #' + (i + 1));
|
|
112
|
+
}
|
|
113
|
+
return argument.value;
|
|
114
|
+
};
|
|
115
|
+
return attributes.map(convert);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Answers a failed search with NO, or BAD for `err.imapResponse` "BAD": the BADCHARSET response code with the
|
|
119
|
+
* supported charsets (RFC 3501 section 7.1, RFC 5256 section 3), or the response code a search limit set
|
|
120
|
+
* (`err.responseCode`), and the text
|
|
121
|
+
*
|
|
122
|
+
* @param {Object} connection IMAP connection
|
|
123
|
+
* @param {Object} parsed Parsed command
|
|
124
|
+
* @param {String} data Raw command
|
|
125
|
+
* @param {Error} err Search error
|
|
126
|
+
* @param {String} description Description for output handlers
|
|
127
|
+
*/
|
|
128
|
+
function sendSearchError(connection, parsed, data, err, description) {
|
|
129
|
+
const attributes = [];
|
|
130
|
+
if (err.code === 'BADCHARSET') {
|
|
131
|
+
attributes.push({
|
|
132
|
+
type: 'SECTION',
|
|
133
|
+
section: [{ type: 'ATOM', value: 'BADCHARSET' }, err.charsets.map((value) => ({ type: 'ATOM', value }))]
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else if (err.responseCode) {
|
|
137
|
+
attributes.push({ type: 'SECTION', section: err.responseCode.map((value) => ({ type: 'ATOM', value: String(value) })) });
|
|
138
|
+
}
|
|
139
|
+
attributes.push({ type: 'TEXT', value: err.message });
|
|
140
|
+
connection.send({ tag: parsed.tag, command: err.imapResponse === 'BAD' ? 'BAD' : 'NO', attributes }, description, parsed, data);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Lower cases ASCII letters only, so that 8-bit octets in binary strings stay intact. RFC 9051
|
|
144
|
+
* section 6.4.4 asks for case insensitive matching only within the ASCII range
|
|
145
|
+
*/
|
|
146
|
+
function asciiLowerCase(str) {
|
|
147
|
+
return str.replace(/[A-Z]+/g, chars => chars.toLowerCase());
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Checks if a string contains another one, ignoring ASCII case
|
|
151
|
+
*
|
|
152
|
+
* @param {String} haystack String to search in
|
|
153
|
+
* @param {String} needle String to look for, already lower cased with asciiLowerCase
|
|
154
|
+
*/
|
|
155
|
+
function contains(haystack, needle) {
|
|
156
|
+
return asciiLowerCase(haystack).indexOf(needle) >= 0;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Returns the search keys with the types of their arguments, including the keys that plugins
|
|
160
|
+
* define in `server.searchHandlers`. If a plugin handler takes more than 3 params
|
|
161
|
+
* (connection, message, index), the remaining ones are its arguments. A plugin handler can
|
|
162
|
+
* describe its arguments instead with an `argumentTypes(list)` method, that gets the criteria
|
|
163
|
+
* following the key and returns the list of types. A type can also be a function that gets the
|
|
164
|
+
* argument value and returns the parsed value, or throws for an invalid one.
|
|
165
|
+
*
|
|
166
|
+
* @param {Object} server IMAP server
|
|
167
|
+
* @return {Object} search key to list of argument types, or to a function that returns the list
|
|
168
|
+
*/
|
|
169
|
+
function getSearchKeys(server) {
|
|
170
|
+
const keys = Object.assign({}, searchKeys);
|
|
171
|
+
const pluginHandlers = server.searchHandlers;
|
|
172
|
+
Object.keys(pluginHandlers).forEach(key => {
|
|
173
|
+
if (!(key in keys)) {
|
|
174
|
+
const handler = pluginHandlers[key];
|
|
175
|
+
keys[key] = typeof handler.argumentTypes === 'function' ? handler.argumentTypes : new Array(Math.max(handler.length - 3, 0)).fill('string');
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
return keys;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Checks if SEARCH criteria refer to messages by sequence number (RFC 3501 section 5.5), that is,
|
|
182
|
+
* if a sequence set is used as a search key. Arguments of search keys, like the UID set of UID
|
|
183
|
+
* or a string that looks like a number, are not search keys.
|
|
184
|
+
*
|
|
185
|
+
* @param {Object} server IMAP server
|
|
186
|
+
* @param {Array} attributes Parsed SEARCH arguments, nested lists are arrays
|
|
187
|
+
* @return {Boolean} true if a sequence set key occurs
|
|
188
|
+
*/
|
|
189
|
+
function hasSequenceSetKey(server, attributes) {
|
|
190
|
+
const keys = getSearchKeys(server);
|
|
191
|
+
const walk = (list) => {
|
|
192
|
+
// arguments of the previous key that are values, not keys
|
|
193
|
+
let skip = 0;
|
|
194
|
+
return list.some((item, i) => {
|
|
195
|
+
if (Array.isArray(item)) {
|
|
196
|
+
return walk(item);
|
|
197
|
+
}
|
|
198
|
+
if (skip) {
|
|
199
|
+
skip--;
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
const value = ((item && item.value) || '').toString();
|
|
203
|
+
const key = value.toUpperCase();
|
|
204
|
+
if (key === 'CHARSET' && i === 0) {
|
|
205
|
+
skip = 1;
|
|
206
|
+
}
|
|
207
|
+
else if (Object.hasOwn(keys, key)) {
|
|
208
|
+
// NOT and OR take keys as arguments, these are checked as keys
|
|
209
|
+
let types = keys[key];
|
|
210
|
+
if (typeof types === 'function') {
|
|
211
|
+
types = types(list.slice(i + 1).map(next => (Array.isArray(next) ? next : ((next && next.value) || '').toString())));
|
|
212
|
+
}
|
|
213
|
+
skip = types.filter((type) => type !== 'key').length;
|
|
214
|
+
}
|
|
215
|
+
else if (/^[\d*][\d*,:]*$/.test(value)) {
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
return walk([].concat(attributes || []));
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Searches messages. Errors thrown for the client are answered with BAD when `imapResponse` is "BAD",
|
|
225
|
+
* otherwise NO. SORT and THREAD send `responseCode` (a list of atoms) as the response code
|
|
226
|
+
*
|
|
227
|
+
* @param {Object} connection IMAP connection
|
|
228
|
+
* @param {Array} messageSource Messages of the selected mailbox, as the session sees them
|
|
229
|
+
* @param {Array} params Search criteria: strings, and arrays for parenthesized lists
|
|
230
|
+
* @param {Function} [getMessageRange] Resolves the sequence sets of the criteria, `(range, isUid)`, defaults to
|
|
231
|
+
* the selected mailbox of the connection. Used to search a mailbox that is not selected
|
|
232
|
+
* @return {Object} `{ list, numbers, keys, matches }`, the matching messages, the sequence numbers by UID,
|
|
233
|
+
* the set of search keys used in the criteria and a `matches(message, index)` function that checks
|
|
234
|
+
* a message against the same criteria later. Sequence sets in the criteria stay as they were resolved
|
|
235
|
+
* now, they are not evaluated again
|
|
236
|
+
*/
|
|
237
|
+
function searchHandlers(connection, messageSource, params, getMessageRange) {
|
|
238
|
+
const resolveRange = getMessageRange || ((range, isUid) => connection.getMessageRange(range, isUid));
|
|
239
|
+
const numbers = {};
|
|
240
|
+
// search keys used in the criteria, other than sequence sets
|
|
241
|
+
const usedKeys = new Set();
|
|
242
|
+
const keys = getSearchKeys(connection.server);
|
|
243
|
+
const pluginHandlers = connection.server.searchHandlers;
|
|
244
|
+
params = [].concat(params || []);
|
|
245
|
+
// IMAP4rev1 search strings are US-ASCII unless a CHARSET is given (RFC 3501 6.4.4). A plugin can
|
|
246
|
+
// fix the charset of a session with connection.searchCharset, e.g. UTF-8 after ENABLE UTF8=ACCEPT,
|
|
247
|
+
// or change the default with connection.defaultSearchCharset (IMAP4rev2 assumes UTF-8, RFC 9051 6.4.4)
|
|
248
|
+
let searchCharset = connection.searchCharset || connection.defaultSearchCharset || 'US-ASCII';
|
|
249
|
+
if (typeof params[0] === 'string' && params[0].toUpperCase() === 'CHARSET') {
|
|
250
|
+
if (connection.searchCharset) {
|
|
251
|
+
// RFC 9755 section 3: a CHARSET conflicts with the charset of the session
|
|
252
|
+
throw badError('CHARSET is not allowed, search strings are always ' + connection.searchCharset + ' in this session');
|
|
253
|
+
}
|
|
254
|
+
params.shift();
|
|
255
|
+
const charset = params.shift();
|
|
256
|
+
if (typeof charset !== 'string') {
|
|
257
|
+
throw badError('CHARSET expects a charset name');
|
|
258
|
+
}
|
|
259
|
+
if (charsets.indexOf(charset.toUpperCase()) < 0) {
|
|
260
|
+
const err = new Error('Unsupported charset ' + charset);
|
|
261
|
+
err.imapResponse = 'NO';
|
|
262
|
+
err.code = 'BADCHARSET';
|
|
263
|
+
err.charsets = charsets;
|
|
264
|
+
throw err;
|
|
265
|
+
}
|
|
266
|
+
searchCharset = charset.toUpperCase();
|
|
267
|
+
}
|
|
268
|
+
// strings must be valid in the declared charset, a client must not send 8-bit text as US-ASCII
|
|
269
|
+
const checkString = (key, value) => {
|
|
270
|
+
if (searchCharset === 'US-ASCII' && /[\u0080-\u00ff]/.test(value)) {
|
|
271
|
+
throw badError(key + ' argument has 8-bit characters, use CHARSET UTF-8');
|
|
272
|
+
}
|
|
273
|
+
if (searchCharset === 'UTF-8' && !(0, node_buffer_1.isUtf8)(Buffer.from(value, 'binary'))) {
|
|
274
|
+
throw badError(key + ' argument is not valid UTF-8');
|
|
275
|
+
}
|
|
276
|
+
return value;
|
|
277
|
+
};
|
|
278
|
+
if (!params.length) {
|
|
279
|
+
throw badError('SEARCH expects search criteria, empty query given');
|
|
280
|
+
}
|
|
281
|
+
// Parses one search key and its arguments from a list of criteria into a node of the query tree
|
|
282
|
+
const parseKey = (list) => {
|
|
283
|
+
if (!list.length) {
|
|
284
|
+
throw badError('Unexpected end of search criteria');
|
|
285
|
+
}
|
|
286
|
+
const param = list.shift();
|
|
287
|
+
if (Array.isArray(param)) {
|
|
288
|
+
// a parenthesized list of keys that all must match
|
|
289
|
+
return { key: 'AND', args: parseList([].concat(param)) };
|
|
290
|
+
}
|
|
291
|
+
const key = param.toUpperCase();
|
|
292
|
+
// a plugin can remove keys from a session, e.g. NEW, OLD and RECENT are not in the IMAP4rev2 grammar
|
|
293
|
+
if (!Object.prototype.hasOwnProperty.call(keys, key) || (connection.disabledSearchKeys && connection.disabledSearchKeys.has(key))) {
|
|
294
|
+
// a sequence set, plugins may support other forms of it than numbers
|
|
295
|
+
let range;
|
|
296
|
+
try {
|
|
297
|
+
range = resolveRange(param, false);
|
|
298
|
+
}
|
|
299
|
+
catch (E) {
|
|
300
|
+
throw /^[\d,:*]+$/.test(param) ? E : badError('Invalid search key ' + param);
|
|
301
|
+
}
|
|
302
|
+
return { key: '_SEQ', args: [range] };
|
|
303
|
+
}
|
|
304
|
+
usedKeys.add(key);
|
|
305
|
+
const keyTypes = keys[key];
|
|
306
|
+
const types = typeof keyTypes === 'function' ? keyTypes(list) : keyTypes;
|
|
307
|
+
const args = types.map((type) => {
|
|
308
|
+
if (type === 'key') {
|
|
309
|
+
return parseKey(list);
|
|
310
|
+
}
|
|
311
|
+
if (!list.length || typeof list[0] !== 'string') {
|
|
312
|
+
throw badError(key + ' expects ' + types.length + ' argument' + (types.length > 1 ? 's' : ''));
|
|
313
|
+
}
|
|
314
|
+
const value = list.shift();
|
|
315
|
+
if (typeof type === 'function') {
|
|
316
|
+
return type(value);
|
|
317
|
+
}
|
|
318
|
+
switch (type) {
|
|
319
|
+
case 'date':
|
|
320
|
+
return parseQueryDate(value);
|
|
321
|
+
case 'number':
|
|
322
|
+
case 'number64': {
|
|
323
|
+
// RFC 3501 section 9: number is 32-bit. LARGER and SMALLER take a number64 in IMAP4rev2 (RFC 9051
|
|
324
|
+
// section 9), so in a session with connection.number64 set
|
|
325
|
+
const number64 = type === 'number64' && connection.number64;
|
|
326
|
+
if (!(0, numbers_js_1.isNumber)(value, number64 ? numbers_js_1.MAX_NUMBER64 : numbers_js_1.MAX_NUMBER)) {
|
|
327
|
+
throw badError(key + ' expects a number' + (number64 ? '64' : ''));
|
|
328
|
+
}
|
|
329
|
+
return Number(value);
|
|
330
|
+
}
|
|
331
|
+
case 'sequence':
|
|
332
|
+
return resolveRange(value, true);
|
|
333
|
+
default:
|
|
334
|
+
return checkString(key, value);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
return { key, args };
|
|
338
|
+
};
|
|
339
|
+
const parseList = (list) => {
|
|
340
|
+
if (!list.length) {
|
|
341
|
+
throw badError('Empty search criteria list');
|
|
342
|
+
}
|
|
343
|
+
const nodes = [];
|
|
344
|
+
while (list.length) {
|
|
345
|
+
nodes.push(parseKey(list));
|
|
346
|
+
}
|
|
347
|
+
return nodes;
|
|
348
|
+
};
|
|
349
|
+
const query = { key: 'AND', args: parseList(params) };
|
|
350
|
+
// a sequence set argument resolves to [number, message] pairs, turn these into a lookup set
|
|
351
|
+
const toMessageSet = (range) => new Set(range.map(item => item[1]));
|
|
352
|
+
const prepare = (node) => {
|
|
353
|
+
if (node.key === '_SEQ' || node.key === 'UID') {
|
|
354
|
+
node.set = toMessageSet(node.args[0]);
|
|
355
|
+
}
|
|
356
|
+
// lower case the string to look for once, not for every message. Header values are compared
|
|
357
|
+
// as Unicode text after decoding their encoded words, so the UTF-8 octets of the string are
|
|
358
|
+
// decoded too (RFC 9051 section 6.4.4)
|
|
359
|
+
if (['BODY', 'TEXT'].indexOf(node.key) >= 0) {
|
|
360
|
+
node.needle = asciiLowerCase(node.args[0]);
|
|
361
|
+
}
|
|
362
|
+
else if (['BCC', 'CC', 'FROM', 'HEADER', 'SUBJECT', 'TO'].indexOf(node.key) >= 0) {
|
|
363
|
+
node.needle = asciiLowerCase((0, encoded_words_js_1.decodeUtf8)(node.args[node.key === 'HEADER' ? 1 : 0]));
|
|
364
|
+
}
|
|
365
|
+
node.args.forEach((arg) => {
|
|
366
|
+
if (arg && typeof arg === 'object' && arg.key) {
|
|
367
|
+
prepare(arg);
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
};
|
|
371
|
+
prepare(query);
|
|
372
|
+
const hasFlag = (message, flag) => message.flags.indexOf(flag) >= 0;
|
|
373
|
+
// compares the unfolded values of the header lines with that name, after decoding their encoded
|
|
374
|
+
// words. RFC 3501 and RFC 9051 section 6.4.4: [MIME-HDRS] strings in headers MUST be decoded before comparing text
|
|
375
|
+
const matchHeader = (message, name, needle) => {
|
|
376
|
+
name = name.toLowerCase();
|
|
377
|
+
return ((0, mimeparser_js_1.getMessageData)(message).tree.header || []).some((line) => {
|
|
378
|
+
const colon = line.indexOf(':');
|
|
379
|
+
const lineName = (colon < 0 ? line : line.substr(0, colon)).trim().toLowerCase();
|
|
380
|
+
const value = colon < 0 ? '' : line.substr(colon + 1).replace(/\r?\n(?=[ \t])/g, '');
|
|
381
|
+
return lineName === name && contains((0, encoded_words_js_1.decodeHeader)(value), needle);
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
const matches = (node, message, index) => {
|
|
385
|
+
const args = node.args;
|
|
386
|
+
if (Object.prototype.hasOwnProperty.call(pluginHandlers, node.key)) {
|
|
387
|
+
// plugin defined search key, which may also override a built-in one
|
|
388
|
+
return !!pluginHandlers[node.key](connection, message, index, ...args);
|
|
389
|
+
}
|
|
390
|
+
switch (node.key) {
|
|
391
|
+
case 'AND':
|
|
392
|
+
return args.every((arg) => matches(arg, message, index));
|
|
393
|
+
case '_SEQ':
|
|
394
|
+
case 'UID':
|
|
395
|
+
return node.set.has(message);
|
|
396
|
+
case 'ALL':
|
|
397
|
+
return true;
|
|
398
|
+
case 'ANSWERED':
|
|
399
|
+
return hasFlag(message, '\\Answered');
|
|
400
|
+
case 'BCC':
|
|
401
|
+
case 'CC':
|
|
402
|
+
case 'FROM':
|
|
403
|
+
case 'SUBJECT':
|
|
404
|
+
case 'TO':
|
|
405
|
+
return matchHeader(message, node.key, node.needle);
|
|
406
|
+
case 'HEADER':
|
|
407
|
+
return matchHeader(message, args[0], node.needle);
|
|
408
|
+
case 'BEFORE': {
|
|
409
|
+
const date = getInternalDate(message);
|
|
410
|
+
return !!date && date < args[0];
|
|
411
|
+
}
|
|
412
|
+
case 'ON':
|
|
413
|
+
return getInternalDate(message) === args[0];
|
|
414
|
+
case 'SINCE': {
|
|
415
|
+
const date = getInternalDate(message);
|
|
416
|
+
return !!date && date >= args[0];
|
|
417
|
+
}
|
|
418
|
+
case 'SENTBEFORE': {
|
|
419
|
+
const date = getSentDate(message);
|
|
420
|
+
return !!date && date < args[0];
|
|
421
|
+
}
|
|
422
|
+
case 'SENTON':
|
|
423
|
+
return getSentDate(message) === args[0];
|
|
424
|
+
case 'SENTSINCE': {
|
|
425
|
+
const date = getSentDate(message);
|
|
426
|
+
return !!date && date >= args[0];
|
|
427
|
+
}
|
|
428
|
+
case 'BODY':
|
|
429
|
+
return contains((0, mimeparser_js_1.render)((0, mimeparser_js_1.getMessageData)(message).tree, true), node.needle);
|
|
430
|
+
case 'TEXT':
|
|
431
|
+
return contains((0, mimeparser_js_1.getMessageData)(message).raw, node.needle);
|
|
432
|
+
case 'DELETED':
|
|
433
|
+
return hasFlag(message, '\\Deleted');
|
|
434
|
+
case 'DRAFT':
|
|
435
|
+
return hasFlag(message, '\\Draft');
|
|
436
|
+
case 'FLAGGED':
|
|
437
|
+
return hasFlag(message, '\\Flagged');
|
|
438
|
+
case 'KEYWORD':
|
|
439
|
+
return hasFlag(message, args[0]);
|
|
440
|
+
case 'LARGER':
|
|
441
|
+
return (0, mimeparser_js_1.getMessageData)(message).raw.length > args[0];
|
|
442
|
+
case 'SMALLER':
|
|
443
|
+
return (0, mimeparser_js_1.getMessageData)(message).raw.length < args[0];
|
|
444
|
+
// \Recent is a session flag, see IMAPConnection#isRecent
|
|
445
|
+
case 'NEW':
|
|
446
|
+
return connection.isRecent(message) && !hasFlag(message, '\\Seen');
|
|
447
|
+
case 'OLD':
|
|
448
|
+
return !connection.isRecent(message);
|
|
449
|
+
case 'RECENT':
|
|
450
|
+
return connection.isRecent(message);
|
|
451
|
+
case 'SEEN':
|
|
452
|
+
return hasFlag(message, '\\Seen');
|
|
453
|
+
case 'NOT':
|
|
454
|
+
return !matches(args[0], message, index);
|
|
455
|
+
case 'OR':
|
|
456
|
+
return matches(args[0], message, index) || matches(args[1], message, index);
|
|
457
|
+
case 'UNANSWERED':
|
|
458
|
+
return !hasFlag(message, '\\Answered');
|
|
459
|
+
case 'UNDELETED':
|
|
460
|
+
return !hasFlag(message, '\\Deleted');
|
|
461
|
+
case 'UNDRAFT':
|
|
462
|
+
return !hasFlag(message, '\\Draft');
|
|
463
|
+
case 'UNFLAGGED':
|
|
464
|
+
return !hasFlag(message, '\\Flagged');
|
|
465
|
+
case 'UNKEYWORD':
|
|
466
|
+
return !hasFlag(message, args[0]);
|
|
467
|
+
case 'UNSEEN':
|
|
468
|
+
return !hasFlag(message, '\\Seen');
|
|
469
|
+
default:
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
// plugins can narrow down the messages that are looked at (server.searchLimits), sequence numbers stay as they are
|
|
474
|
+
const searched = connection.server.searchLimits.reduce((messages, limit) => limit(connection, messages, query) || messages, messageSource);
|
|
475
|
+
const searchedSet = searched !== messageSource && new Set(searched);
|
|
476
|
+
const list = [];
|
|
477
|
+
messageSource.forEach((message, i) => {
|
|
478
|
+
if (searchedSet && !searchedSet.has(message)) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
if (matches(query, message, i + 1)) {
|
|
482
|
+
numbers[message.uid] = i + 1;
|
|
483
|
+
list.push(message);
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
return {
|
|
487
|
+
list,
|
|
488
|
+
numbers,
|
|
489
|
+
keys: usedKeys,
|
|
490
|
+
matches: (message, index) => matches(query, message, index)
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
{
|
|
494
|
+
const defaultExport = exports.default;
|
|
495
|
+
if (defaultExport && (typeof defaultExport === 'function' || typeof defaultExport === 'object')) {
|
|
496
|
+
for (const key of Object.keys(exports)) {
|
|
497
|
+
if (key !== 'default' && !(key in defaultExport)) {
|
|
498
|
+
defaultExport[key] = exports[key];
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
Object.defineProperty(defaultExport, 'default', { value: defaultExport, enumerable: false, writable: true, configurable: true });
|
|
502
|
+
module.exports = defaultExport;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Attribute, IMAPConnection, IMAPResponse, IMAPServer, Mailbox, ParsedCommand } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validates a list of STATUS data item names (RFC 3501 section 9, "(" status-att *(SP status-att) ")")
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} server IMAPServer instance
|
|
6
|
+
* @param {Array} list Parsed list of status items
|
|
7
|
+
* @param {Object} [connection] IMAP connection, its `disabledStatusItems` set lists items the session can not use,
|
|
8
|
+
* `addedStatusItems` the items only this session can use (DELETED after ENABLE IMAP4rev2)
|
|
9
|
+
* @return {Array} upper case item names
|
|
10
|
+
* @throws {Error} if the list is empty or has an invalid item, the message is for the BAD response
|
|
11
|
+
*/
|
|
12
|
+
declare function parseStatusItems(server: IMAPServer, list: Attribute, connection?: IMAPConnection | null): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Sends an untagged STATUS response
|
|
15
|
+
*
|
|
16
|
+
* @param {Object} connection IMAPConnection instance
|
|
17
|
+
* @param {String} path Storage name of the mailbox
|
|
18
|
+
* @param {Object} mailbox Mailbox object
|
|
19
|
+
* @param {Array} items Upper case item names from parseStatusItems
|
|
20
|
+
* @param {Object} parsed Parsed command
|
|
21
|
+
* @param {Object} data Command data
|
|
22
|
+
*/
|
|
23
|
+
declare function sendStatus(connection: IMAPConnection, path: string, mailbox: Mailbox, items: string[], parsed: ParsedCommand, data: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* Builds an untagged STATUS response
|
|
26
|
+
*
|
|
27
|
+
* @param {Object} connection IMAPConnection instance
|
|
28
|
+
* @param {String} path Storage name of the mailbox
|
|
29
|
+
* @param {Object} mailbox Mailbox object
|
|
30
|
+
* @param {Array} items Upper case item names
|
|
31
|
+
* @return {Object} STATUS response
|
|
32
|
+
*/
|
|
33
|
+
declare function statusResponse(connection: IMAPConnection, path: string, mailbox: Mailbox, items: string[]): IMAPResponse;
|
|
34
|
+
export { parseStatusItems, sendStatus, statusResponse };
|