imapkit 4.0.3 → 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 +33 -74
- 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,61 @@
|
|
|
1
|
+
import { states } from '../command-states.js';
|
|
2
|
+
import DeflateLayer from '../deflate-layer.js';
|
|
3
|
+
/**
|
|
4
|
+
* @help Adds COMPRESS=DEFLATE [RFC4978] capability
|
|
5
|
+
* @help Raw DEFLATE in both directions after the tagged OK,
|
|
6
|
+
* @help every burst of responses ends with a sync flush
|
|
7
|
+
*/
|
|
8
|
+
export default function compressPlugin(server) {
|
|
9
|
+
server.registerCapability('COMPRESS=DEFLATE');
|
|
10
|
+
const isActive = (connection) => connection.transport instanceof DeflateLayer && connection.transport.active;
|
|
11
|
+
// RFC 8437 section 4.1: after UNAUTHENTICATE the server ends its compression after the CRLF of
|
|
12
|
+
// the OK, and the client after the CRLF of the command, so anything it compressed later is dropped
|
|
13
|
+
server.resetHandlers.push((connection) => {
|
|
14
|
+
if (isActive(connection)) {
|
|
15
|
+
connection.discardInput();
|
|
16
|
+
connection.transport.endInput();
|
|
17
|
+
connection.transport.end();
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
server.setCommandHandler('COMPRESS', (connection, parsed, data, callback) => {
|
|
21
|
+
const args = parsed.attributes || [];
|
|
22
|
+
// RFC 4978 section 5: compress = "COMPRESS" SP algorithm, algorithm = "DEFLATE"
|
|
23
|
+
if (args.length !== 1 || !args[0] || args[0].type !== 'ATOM') {
|
|
24
|
+
connection.sendStatus(parsed, data, 'BAD', 'COMPRESS expects a compression mechanism');
|
|
25
|
+
return callback();
|
|
26
|
+
}
|
|
27
|
+
if (args[0].value.toUpperCase() !== 'DEFLATE') {
|
|
28
|
+
connection.sendStatus(parsed, data, 'BAD', 'Unknown compression mechanism');
|
|
29
|
+
return callback();
|
|
30
|
+
}
|
|
31
|
+
// RFC 4978 section 3: BAD if COMPRESS is already active, NO is for compression by another
|
|
32
|
+
// layer, such as TLS, which ImapKit never negotiates. Dovecot answers NO here
|
|
33
|
+
if (isActive(connection)) {
|
|
34
|
+
connection.sendStatus(parsed, data, 'BAD', 'DEFLATE active via COMPRESS', 'COMPRESSIONACTIVE');
|
|
35
|
+
return callback();
|
|
36
|
+
}
|
|
37
|
+
connection.sendStatus(parsed, data, 'OK', 'DEFLATE active');
|
|
38
|
+
if (connection.transport) {
|
|
39
|
+
// the layer of an earlier session, it passes data on as is since UNAUTHENTICATE
|
|
40
|
+
connection.transport.destroy();
|
|
41
|
+
}
|
|
42
|
+
// compression starts right after the CRLF of the tagged OK
|
|
43
|
+
connection.transport = new DeflateLayer({
|
|
44
|
+
// the layer writes only Buffers to the server, strings come from the clients that share it
|
|
45
|
+
writeRaw: (chunk) => connection.writeRaw(chunk),
|
|
46
|
+
onData: (chunk) => connection.onData(chunk),
|
|
47
|
+
onError: (err) => {
|
|
48
|
+
// the input can not be decompressed, so there is nothing left to talk about
|
|
49
|
+
if (connection.options.debug) {
|
|
50
|
+
console.log('COMPRESS error: %s', err.message);
|
|
51
|
+
}
|
|
52
|
+
connection.sendStatus({ tag: '*' }, null, 'BYE', 'Invalid compressed data', false, 'COMPRESS ERROR');
|
|
53
|
+
connection.end();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return callback();
|
|
57
|
+
},
|
|
58
|
+
// RFC 4978 section 3: the client MUST NOT send further commands until it has seen the result of COMPRESS.
|
|
59
|
+
// Those commands would be uncompressed, and after an OK the server expects compressed input
|
|
60
|
+
{ states: states.AUTHENTICATED, noPipelining: true });
|
|
61
|
+
}
|
|
@@ -1,68 +1,51 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @help Adds CONDSTORE [RFC7162] capability
|
|
5
3
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
module.exports = function (server) {
|
|
4
|
+
import { macros as FETCH_MACROS } from '../commands/fetch.js';
|
|
5
|
+
import { badError } from '../commands/handlers/search.js';
|
|
6
|
+
import { INVALID_KEYWORD_CHAR } from '../commands/handlers/flags.js';
|
|
7
|
+
import { MAX_NUMBER64, isNumber } from '../numbers.js';
|
|
8
|
+
import { registerEnable, isEnabled as isExtensionEnabled } from './enable.js';
|
|
9
|
+
export default function condstorePlugin(server) {
|
|
14
10
|
// Register capability, always usable
|
|
15
11
|
server.registerCapability('CONDSTORE');
|
|
16
|
-
|
|
17
12
|
registerEnable(server, 'CONDSTORE');
|
|
18
|
-
|
|
19
13
|
// HIGHESTMODSEQ must be a positive number, even for an empty mailbox
|
|
20
|
-
const getHighestModseq = mailbox => Math.max(Number(mailbox.HIGHESTMODSEQ) || 0, 1);
|
|
21
|
-
|
|
22
|
-
const bumpModseq = mailbox => {
|
|
14
|
+
const getHighestModseq = (mailbox) => Math.max(Number(mailbox.HIGHESTMODSEQ) || 0, 1);
|
|
15
|
+
const bumpModseq = (mailbox) => {
|
|
23
16
|
mailbox.HIGHESTMODSEQ = getHighestModseq(mailbox) + 1;
|
|
24
17
|
return mailbox.HIGHESTMODSEQ;
|
|
25
18
|
};
|
|
26
|
-
|
|
27
19
|
// RFC 8437 section 4.1: after UNAUTHENTICATE the session behaves as if no CONDSTORE enabling command was issued
|
|
28
|
-
server.resetHandlers.push(connection => {
|
|
20
|
+
server.resetHandlers.push((connection) => {
|
|
29
21
|
connection.condstoreEnabled = false;
|
|
30
22
|
});
|
|
31
|
-
|
|
32
23
|
// ENABLE QRESYNC is a CONDSTORE enabling command as well (RFC 7162 section 3.2.3)
|
|
33
|
-
const isEnabled = connection => !!connection.condstoreEnabled || isExtensionEnabled(connection, 'CONDSTORE') || isExtensionEnabled(connection, 'QRESYNC');
|
|
34
|
-
|
|
24
|
+
const isEnabled = (connection) => !!connection.condstoreEnabled || isExtensionEnabled(connection, 'CONDSTORE') || isExtensionEnabled(connection, 'QRESYNC');
|
|
35
25
|
// shared with QRESYNC, which builds on CONDSTORE
|
|
36
26
|
server.condstore = { isEnabled, getHighestModseq };
|
|
37
|
-
|
|
38
27
|
const sendHighestModseq = (connection, mailbox, parsed, data) => {
|
|
39
|
-
connection.send(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
},
|
|
60
|
-
'CONDSTORE INFO',
|
|
61
|
-
parsed,
|
|
62
|
-
data
|
|
63
|
-
);
|
|
28
|
+
connection.send({
|
|
29
|
+
tag: '*',
|
|
30
|
+
command: 'OK',
|
|
31
|
+
attributes: [
|
|
32
|
+
{
|
|
33
|
+
type: 'SECTION',
|
|
34
|
+
section: [
|
|
35
|
+
{
|
|
36
|
+
type: 'ATOM',
|
|
37
|
+
value: 'HIGHESTMODSEQ'
|
|
38
|
+
},
|
|
39
|
+
getHighestModseq(mailbox)
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'TEXT',
|
|
44
|
+
value: 'Highest'
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}, 'CONDSTORE INFO', parsed, data);
|
|
64
48
|
};
|
|
65
|
-
|
|
66
49
|
// Marks the session as CONDSTORE aware. The first CONDSTORE enabling command
|
|
67
50
|
// issued with a mailbox selected reports HIGHESTMODSEQ for that mailbox
|
|
68
51
|
const enableCondstore = (connection, parsed, data) => {
|
|
@@ -75,7 +58,6 @@ module.exports = function (server) {
|
|
|
75
58
|
sendHighestModseq(connection, connection.selectedMailbox, parsed, data);
|
|
76
59
|
}
|
|
77
60
|
};
|
|
78
|
-
|
|
79
61
|
// Set modseq values when a message is created or initialized
|
|
80
62
|
server.messageHandlers.push((server, message, mailbox) => {
|
|
81
63
|
const modseq = Number(message.MODSEQ);
|
|
@@ -83,24 +65,21 @@ module.exports = function (server) {
|
|
|
83
65
|
// keep the value from storage
|
|
84
66
|
message.MODSEQ = modseq;
|
|
85
67
|
mailbox.HIGHESTMODSEQ = Math.max(getHighestModseq(mailbox), modseq);
|
|
86
|
-
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
87
70
|
message.MODSEQ = bumpModseq(mailbox);
|
|
88
71
|
}
|
|
89
72
|
});
|
|
90
|
-
|
|
91
73
|
// Expunging messages (EXPUNGE, UID EXPUNGE, CLOSE, MOVE) changes the mailbox, all messages removed
|
|
92
74
|
// at once share the incremented mod-sequence (RFC 7162 section 3.2)
|
|
93
75
|
server.on('expunge', mailbox => {
|
|
94
76
|
bumpModseq(mailbox);
|
|
95
77
|
});
|
|
96
|
-
|
|
97
78
|
// RFC 7162 section 3.2.11: SELECT or EXAMINE closes the selected mailbox, a CONDSTORE server marks
|
|
98
79
|
// where the responses for the new mailbox start
|
|
99
80
|
server.closedChecks.push(() => true);
|
|
100
|
-
|
|
101
81
|
server.allowedStatus.push('HIGHESTMODSEQ');
|
|
102
82
|
server.statusHandlers.HIGHESTMODSEQ = (connection, mailbox) => getHighestModseq(mailbox);
|
|
103
|
-
|
|
104
83
|
// Wraps an existing command handler. Commands that are not available are left alone
|
|
105
84
|
const wrapHandler = (command, wrapper) => {
|
|
106
85
|
const prevHandler = server.getCommandHandler(command);
|
|
@@ -109,17 +88,13 @@ module.exports = function (server) {
|
|
|
109
88
|
}
|
|
110
89
|
server.setCommandHandler(command, (connection, parsed, data, callback) => wrapper(prevHandler, connection, parsed, data, callback));
|
|
111
90
|
};
|
|
112
|
-
|
|
113
91
|
const sendBad = (connection, parsed, data, callback, message) => {
|
|
114
92
|
connection.sendStatus(parsed, data, 'BAD', message, false, 'CONDSTORE FAILED');
|
|
115
93
|
return callback();
|
|
116
94
|
};
|
|
117
|
-
|
|
118
95
|
// RFC 7162 section 7: chgsince-fetch-mod = "CHANGEDSINCE" SP mod-sequence-value (1 or more), store-modifier =/
|
|
119
96
|
// "UNCHANGEDSINCE" SP mod-sequence-valzer (0 or more). Both are 1*DIGIT, so not a quoted string, up to 63 bits
|
|
120
|
-
const isValidModseq = (value, allowZero) =>
|
|
121
|
-
!!value && value.type === 'ATOM' && isNumber(value.value, MAX_NUMBER64) && (allowZero || BigInt(value.value) > 0n);
|
|
122
|
-
|
|
97
|
+
const isValidModseq = (value, allowZero) => !!value && value.type === 'ATOM' && isNumber(value.value, MAX_NUMBER64) && (allowZero || BigInt(value.value) > 0n);
|
|
123
98
|
const selectWrapper = (prevHandler, connection, parsed, data, callback) => {
|
|
124
99
|
if (hasCondstoreOption(parsed.attributes && parsed.attributes[1], parsed.attributes, 1)) {
|
|
125
100
|
// SELECT and EXAMINE always report HIGHESTMODSEQ, so no need to send it here
|
|
@@ -128,10 +103,8 @@ module.exports = function (server) {
|
|
|
128
103
|
}
|
|
129
104
|
prevHandler(connection, parsed, data, callback);
|
|
130
105
|
};
|
|
131
|
-
|
|
132
106
|
wrapHandler('SELECT', selectWrapper);
|
|
133
107
|
wrapHandler('EXAMINE', selectWrapper);
|
|
134
|
-
|
|
135
108
|
wrapHandler('STATUS', (prevHandler, connection, parsed, data, callback) => {
|
|
136
109
|
const items = parsed.attributes && parsed.attributes[1];
|
|
137
110
|
if (Array.isArray(items) && items.some(item => item && item.type === 'ATOM' && String(item.value).toUpperCase() === 'HIGHESTMODSEQ')) {
|
|
@@ -139,13 +112,11 @@ module.exports = function (server) {
|
|
|
139
112
|
}
|
|
140
113
|
prevHandler(connection, parsed, data, callback);
|
|
141
114
|
});
|
|
142
|
-
|
|
143
115
|
const fetchWrapper = (prevHandler, connection, parsed, data, callback) => {
|
|
144
116
|
// RFC 4466 2.4: fetch-modifiers are the last argument, a single fetch-att may take arguments of its own
|
|
145
117
|
const attributes = parsed.attributes || [];
|
|
146
118
|
const index = Math.max(attributes.length - 1, 2);
|
|
147
119
|
const changedsince = getCondstoreValue(attributes[index], 'CHANGEDSINCE', attributes, index);
|
|
148
|
-
|
|
149
120
|
if (changedsince) {
|
|
150
121
|
if (!isValidModseq(changedsince)) {
|
|
151
122
|
return sendBad(connection, parsed, data, callback, 'Invalid syntax for CHANGEDSINCE, number expected');
|
|
@@ -154,20 +125,15 @@ module.exports = function (server) {
|
|
|
154
125
|
// CHANGEDSINCE implicitly adds the MODSEQ data item
|
|
155
126
|
addModseqItem(parsed);
|
|
156
127
|
}
|
|
157
|
-
|
|
158
128
|
if (changedsince || hasModseqItem(parsed)) {
|
|
159
129
|
enableCondstore(connection, parsed, data);
|
|
160
130
|
}
|
|
161
|
-
|
|
162
131
|
prevHandler(connection, parsed, data, callback);
|
|
163
132
|
};
|
|
164
|
-
|
|
165
133
|
wrapHandler('FETCH', fetchWrapper);
|
|
166
134
|
wrapHandler('UID FETCH', fetchWrapper);
|
|
167
|
-
|
|
168
135
|
const storeWrapper = (prevHandler, connection, parsed, data, callback) => {
|
|
169
136
|
const unchangedsince = getCondstoreValue(parsed.attributes && parsed.attributes[1], 'UNCHANGEDSINCE', parsed.attributes, 1);
|
|
170
|
-
|
|
171
137
|
if (unchangedsince) {
|
|
172
138
|
if (!isValidModseq(unchangedsince, true)) {
|
|
173
139
|
return sendBad(connection, parsed, data, callback, 'Invalid syntax for UNCHANGEDSINCE, number expected');
|
|
@@ -175,7 +141,6 @@ module.exports = function (server) {
|
|
|
175
141
|
parsed.unchangedsince = Number(unchangedsince.value);
|
|
176
142
|
enableCondstore(connection, parsed, data);
|
|
177
143
|
}
|
|
178
|
-
|
|
179
144
|
// Per command state for tracking changed messages
|
|
180
145
|
parsed.condstoreStore = {
|
|
181
146
|
isUid: (parsed.command || '').toUpperCase() === 'UID STORE',
|
|
@@ -183,32 +148,24 @@ module.exports = function (server) {
|
|
|
183
148
|
modified: [],
|
|
184
149
|
done: false
|
|
185
150
|
};
|
|
186
|
-
|
|
187
151
|
prevHandler(connection, parsed, data, callback);
|
|
188
152
|
};
|
|
189
|
-
|
|
190
153
|
wrapHandler('STORE', storeWrapper);
|
|
191
154
|
wrapHandler('UID STORE', storeWrapper);
|
|
192
|
-
|
|
193
155
|
// RFC 7162 section 3.1.5: MODSEQ [<entry-name> <entry-type-req>] <mod-sequence-valzer>. Mod-sequences
|
|
194
156
|
// are not stored per flag, so the entry name and type are checked but otherwise ignored
|
|
195
157
|
const searchModseq = (connection, message, index, ...args) => message.MODSEQ >= args[args.length - 1];
|
|
196
|
-
searchModseq.argumentTypes = list =>
|
|
197
|
-
typeof list[0] === 'string' && /^\d+$/.test(list[0]) ? [parseModseqValzer] : [parseEntryName, parseEntryType, parseModseqValzer];
|
|
158
|
+
searchModseq.argumentTypes = (list) => typeof list[0] === 'string' && /^\d+$/.test(list[0]) ? [parseModseqValzer] : [parseEntryName, parseEntryType, parseModseqValzer];
|
|
198
159
|
server.searchHandlers.MODSEQ = searchModseq;
|
|
199
|
-
|
|
200
160
|
// highest mod-sequence of a list of messages
|
|
201
|
-
const highestModseq = messages => messages.reduce((highest, message) => Math.max(highest, message.MODSEQ), 0);
|
|
202
|
-
|
|
161
|
+
const highestModseq = (messages) => messages.reduce((highest, message) => Math.max(highest, message.MODSEQ), 0);
|
|
203
162
|
server.fetchHandlers.MODSEQ = function (connection, message) {
|
|
204
163
|
return [message.MODSEQ]; // Must be a list
|
|
205
164
|
};
|
|
206
|
-
|
|
207
165
|
server.fetchFilters.push((connection, message, parsed, index) => {
|
|
208
166
|
if ('changedsince' in parsed && !(parsed.changedsince < message.MODSEQ)) {
|
|
209
167
|
return false;
|
|
210
168
|
}
|
|
211
|
-
|
|
212
169
|
// remember \Seen state, FETCH might set it implicitly
|
|
213
170
|
if (!parsed.condstoreFetch) {
|
|
214
171
|
parsed.condstoreFetch = new Map();
|
|
@@ -217,51 +174,43 @@ module.exports = function (server) {
|
|
|
217
174
|
message,
|
|
218
175
|
seen: message.flags.indexOf('\\Seen') >= 0
|
|
219
176
|
});
|
|
220
|
-
|
|
221
177
|
return true;
|
|
222
178
|
});
|
|
223
|
-
|
|
224
179
|
server.storeFilters.push((connection, message, parsed, index) => {
|
|
225
180
|
const state = parsed.condstoreStore;
|
|
226
181
|
if (!state) {
|
|
227
182
|
return true;
|
|
228
183
|
}
|
|
229
|
-
|
|
230
184
|
if ('unchangedsince' in parsed && message.MODSEQ > parsed.unchangedsince) {
|
|
231
185
|
// failed the UNCHANGEDSINCE test, reported with the MODIFIED response code
|
|
232
186
|
state.modified.push(state.isUid ? message.uid : index);
|
|
233
187
|
return false;
|
|
234
188
|
}
|
|
235
|
-
|
|
236
189
|
state.messages.set(message, {
|
|
237
190
|
index,
|
|
238
191
|
before: snapshot(message),
|
|
239
192
|
bumped: false,
|
|
240
193
|
reported: false
|
|
241
194
|
});
|
|
242
|
-
|
|
243
195
|
return true;
|
|
244
196
|
});
|
|
245
|
-
|
|
246
197
|
// Bumps MODSEQ if the message metadata was changed by the current STORE
|
|
247
198
|
const checkStored = (connection, message, entry) => {
|
|
248
199
|
if (!entry.bumped && snapshot(message) !== entry.before) {
|
|
249
200
|
entry.bumped = true;
|
|
201
|
+
// STORE runs in the Selected state
|
|
250
202
|
message.MODSEQ = bumpModseq(connection.selectedMailbox);
|
|
251
203
|
}
|
|
252
204
|
};
|
|
253
|
-
|
|
254
205
|
server.outputHandlers.push((connection, response, description, parsed, data, extra) => {
|
|
255
206
|
// Flag changes made by another session (RFC 7162 section 3.1), these are not responses to a command
|
|
256
207
|
if (description === 'FLAG NOTIFICATION' && response && extra && isEnabled(connection)) {
|
|
257
208
|
setModseqValue(response.attributes[2], extra.MODSEQ);
|
|
258
209
|
return;
|
|
259
210
|
}
|
|
260
|
-
|
|
261
211
|
if (!parsed || !response) {
|
|
262
212
|
return;
|
|
263
213
|
}
|
|
264
|
-
|
|
265
214
|
// Untagged FETCH responses caused by STORE
|
|
266
215
|
if (description === 'FLAG UPDATE' && parsed.condstoreStore && extra && parsed.condstoreStore.messages.has(extra)) {
|
|
267
216
|
const entry = parsed.condstoreStore.messages.get(extra);
|
|
@@ -273,10 +222,10 @@ module.exports = function (server) {
|
|
|
273
222
|
}
|
|
274
223
|
return;
|
|
275
224
|
}
|
|
276
|
-
|
|
277
225
|
// SEARCH, ESEARCH, SORT or THREAD with the MODSEQ search key, a CONDSTORE enabling command (RFC 7162 section 3.1).
|
|
278
226
|
// `extra.list` holds the messages the response is about
|
|
279
|
-
const isSearch = ['SEARCH', 'SORT', 'THREAD'].includes(response.command) &&
|
|
227
|
+
const isSearch = ['SEARCH', 'SORT', 'THREAD'].includes(response.command) &&
|
|
228
|
+
[response.command, 'UID ' + response.command].includes(description);
|
|
280
229
|
if ((isSearch || description === 'ESEARCH') && response.tag === '*' && extra && extra.keys && extra.keys.has('MODSEQ')) {
|
|
281
230
|
enableCondstore(connection, parsed, data);
|
|
282
231
|
// RFC 7162 section 3.1.9: THREAD responses are unchanged
|
|
@@ -288,16 +237,13 @@ module.exports = function (server) {
|
|
|
288
237
|
}
|
|
289
238
|
return;
|
|
290
239
|
}
|
|
291
|
-
|
|
292
240
|
// Untagged FETCH responses of FETCH, check for implicitly set \Seen
|
|
293
|
-
if (
|
|
294
|
-
response.tag === '*' &&
|
|
241
|
+
if (response.tag === '*' &&
|
|
295
242
|
parsed.condstoreFetch &&
|
|
296
243
|
response.attributes &&
|
|
297
244
|
response.attributes[1] &&
|
|
298
245
|
response.attributes[1].value === 'FETCH' &&
|
|
299
|
-
parsed.condstoreFetch.has(response.attributes[0])
|
|
300
|
-
) {
|
|
246
|
+
parsed.condstoreFetch.has(response.attributes[0])) {
|
|
301
247
|
const entry = parsed.condstoreFetch.get(response.attributes[0]);
|
|
302
248
|
const message = entry.message;
|
|
303
249
|
let changed = false;
|
|
@@ -316,12 +262,10 @@ module.exports = function (server) {
|
|
|
316
262
|
}
|
|
317
263
|
return;
|
|
318
264
|
}
|
|
319
|
-
|
|
320
265
|
// Tagged response of STORE
|
|
321
266
|
if (response.tag === parsed.tag && parsed.condstoreStore && !parsed.condstoreStore.done) {
|
|
322
267
|
const state = parsed.condstoreStore;
|
|
323
268
|
state.done = true;
|
|
324
|
-
|
|
325
269
|
state.messages.forEach((entry, message) => {
|
|
326
270
|
checkStored(connection, message, entry);
|
|
327
271
|
// .SILENT stores send no FETCH responses, CONDSTORE aware clients still need the new MODSEQ values
|
|
@@ -335,26 +279,19 @@ module.exports = function (server) {
|
|
|
335
279
|
];
|
|
336
280
|
// RFC 7162 section 3.1: UID and MODSEQ in every untagged FETCH caused by STORE
|
|
337
281
|
attributes.unshift({ type: 'ATOM', value: 'UID' }, message.uid);
|
|
338
|
-
connection.send(
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
},
|
|
350
|
-
'CONDSTORE MODSEQ UPDATE',
|
|
351
|
-
parsed,
|
|
352
|
-
data,
|
|
353
|
-
message
|
|
354
|
-
);
|
|
282
|
+
connection.send({
|
|
283
|
+
tag: '*',
|
|
284
|
+
attributes: [
|
|
285
|
+
entry.index,
|
|
286
|
+
{
|
|
287
|
+
type: 'ATOM',
|
|
288
|
+
value: 'FETCH'
|
|
289
|
+
},
|
|
290
|
+
attributes
|
|
291
|
+
]
|
|
292
|
+
}, 'CONDSTORE MODSEQ UPDATE', parsed, data, message);
|
|
355
293
|
}
|
|
356
294
|
});
|
|
357
|
-
|
|
358
295
|
// RFC 7162 section 3.1.3 example 11: MODIFIED can also go with the tagged NO of a STORE on expunged messages
|
|
359
296
|
// (RFC 2180 section 4.2.3), it replaces EXPUNGEISSUED there since a response has only one response code
|
|
360
297
|
if ((response.command === 'OK' || response.command === 'NO') && state.modified.length) {
|
|
@@ -372,11 +309,10 @@ module.exports = function (server) {
|
|
|
372
309
|
}
|
|
373
310
|
]
|
|
374
311
|
}
|
|
375
|
-
].concat((response.attributes || []).filter(attr => response.command === 'OK' || !attr || attr.type !== 'SECTION'));
|
|
312
|
+
].concat((response.attributes || []).filter((attr) => response.command === 'OK' || !attr || attr.type !== 'SECTION'));
|
|
376
313
|
}
|
|
377
314
|
return;
|
|
378
315
|
}
|
|
379
|
-
|
|
380
316
|
if (description === 'ENABLED' && Array.isArray(extra) && extra.indexOf('CONDSTORE') >= 0) {
|
|
381
317
|
// ENABLE CONDSTORE was issued
|
|
382
318
|
if (!connection.condstoreEnabled) {
|
|
@@ -387,13 +323,11 @@ module.exports = function (server) {
|
|
|
387
323
|
}
|
|
388
324
|
return;
|
|
389
325
|
}
|
|
390
|
-
|
|
391
326
|
if (description === 'ENABLE' && parsed.condstoreReportHighest && connection.selectedMailbox) {
|
|
392
327
|
parsed.condstoreReportHighest = false;
|
|
393
328
|
sendHighestModseq(connection, connection.selectedMailbox, parsed, data);
|
|
394
329
|
return;
|
|
395
330
|
}
|
|
396
|
-
|
|
397
331
|
// Add CONDSTORE info to SELECT and EXAMINE
|
|
398
332
|
if ((description === 'EXAMINE' || description === 'SELECT') && response.tag === parsed.tag && connection.selectedMailbox) {
|
|
399
333
|
// (CONDSTORE) option was used, show notice
|
|
@@ -404,17 +338,16 @@ module.exports = function (server) {
|
|
|
404
338
|
type: 'TEXT',
|
|
405
339
|
value: 'CONDSTORE is now enabled'
|
|
406
340
|
});
|
|
407
|
-
}
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
408
343
|
last.value += ', CONDSTORE is now enabled';
|
|
409
344
|
}
|
|
410
345
|
}
|
|
411
|
-
|
|
412
346
|
// Send untagged info about highest modseq
|
|
413
347
|
sendHighestModseq(connection, connection.selectedMailbox, parsed, data);
|
|
414
348
|
}
|
|
415
349
|
});
|
|
416
|
-
}
|
|
417
|
-
|
|
350
|
+
}
|
|
418
351
|
// RFC 7162 section 7: mod-sequence-valzer = "0" / mod-sequence-value. Dovecot also accepts values above 63 bits
|
|
419
352
|
function parseModseqValzer(value) {
|
|
420
353
|
if (!isNumber(value, MAX_NUMBER64)) {
|
|
@@ -422,7 +355,6 @@ function parseModseqValzer(value) {
|
|
|
422
355
|
}
|
|
423
356
|
return Number(value);
|
|
424
357
|
}
|
|
425
|
-
|
|
426
358
|
// RFC 7162 section 7: entry-flag-name = DQUOTE "/flags/" attr-flag DQUOTE, attr-flag is a flag without "\Recent"
|
|
427
359
|
function parseEntryName(value) {
|
|
428
360
|
const match = value.match(/^\/flags\/(\\?)(.+)$/i);
|
|
@@ -431,7 +363,6 @@ function parseEntryName(value) {
|
|
|
431
363
|
}
|
|
432
364
|
return value;
|
|
433
365
|
}
|
|
434
|
-
|
|
435
366
|
// RFC 7162 section 7: entry-type-req = "priv" / "shared" / "all"
|
|
436
367
|
function parseEntryType(value) {
|
|
437
368
|
if (!['PRIV', 'SHARED', 'ALL'].includes(value.toUpperCase())) {
|
|
@@ -439,12 +370,10 @@ function parseEntryType(value) {
|
|
|
439
370
|
}
|
|
440
371
|
return value;
|
|
441
372
|
}
|
|
442
|
-
|
|
443
373
|
// Serialized message metadata, used to detect changes
|
|
444
374
|
function snapshot(message) {
|
|
445
375
|
return JSON.stringify([message.flags || [], message['X-GM-LABELS'] || []]);
|
|
446
376
|
}
|
|
447
|
-
|
|
448
377
|
function findItem(list, name) {
|
|
449
378
|
if (!Array.isArray(list)) {
|
|
450
379
|
return -1;
|
|
@@ -456,7 +385,6 @@ function findItem(list, name) {
|
|
|
456
385
|
}
|
|
457
386
|
return -1;
|
|
458
387
|
}
|
|
459
|
-
|
|
460
388
|
// Sets or adds the MODSEQ value in a FETCH response attribute list
|
|
461
389
|
function setModseqValue(list, modseq) {
|
|
462
390
|
if (!Array.isArray(list)) {
|
|
@@ -465,39 +393,30 @@ function setModseqValue(list, modseq) {
|
|
|
465
393
|
const pos = findItem(list, 'MODSEQ');
|
|
466
394
|
if (pos >= 0) {
|
|
467
395
|
list[pos + 1] = [modseq];
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
[modseq]
|
|
475
|
-
);
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
list.push({
|
|
399
|
+
type: 'ATOM',
|
|
400
|
+
value: 'MODSEQ'
|
|
401
|
+
}, [modseq]);
|
|
476
402
|
}
|
|
477
403
|
}
|
|
478
|
-
|
|
479
404
|
// Adds the UID to a FETCH response attribute list unless it is there already
|
|
480
405
|
function setUidValue(list, uid) {
|
|
481
406
|
if (Array.isArray(list) && findItem(list, 'UID') < 0) {
|
|
482
|
-
list.push(
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
},
|
|
487
|
-
uid
|
|
488
|
-
);
|
|
407
|
+
list.push({
|
|
408
|
+
type: 'ATOM',
|
|
409
|
+
value: 'UID'
|
|
410
|
+
}, uid);
|
|
489
411
|
}
|
|
490
412
|
}
|
|
491
|
-
|
|
492
413
|
function isModseqAtom(item) {
|
|
493
414
|
return !!item && item.type === 'ATOM' && String(item.value).toUpperCase() === 'MODSEQ';
|
|
494
415
|
}
|
|
495
|
-
|
|
496
416
|
function hasModseqItem(parsed) {
|
|
497
417
|
const items = parsed.attributes && parsed.attributes[1];
|
|
498
418
|
return Array.isArray(items) ? items.some(isModseqAtom) : isModseqAtom(items);
|
|
499
419
|
}
|
|
500
|
-
|
|
501
420
|
// Adds MODSEQ to the list of FETCH data items, unless it is already there
|
|
502
421
|
function addModseqItem(parsed) {
|
|
503
422
|
if (!parsed.attributes || !parsed.attributes[1] || hasModseqItem(parsed)) {
|
|
@@ -508,14 +427,13 @@ function addModseqItem(parsed) {
|
|
|
508
427
|
const name = String(items.value).toUpperCase();
|
|
509
428
|
const macro = items.type === 'ATOM' && Object.hasOwn(FETCH_MACROS, name) && FETCH_MACROS[name];
|
|
510
429
|
// a single fetch-att keeps the arguments that follow it, eg. RFC 8970 PREVIEW (LAZY)
|
|
511
|
-
items = macro ? macro.map(value => ({ type: 'ATOM', value })) : [items].concat(parsed.attributes.splice(2));
|
|
430
|
+
items = macro ? macro.map((value) => ({ type: 'ATOM', value })) : [items].concat(parsed.attributes.splice(2));
|
|
512
431
|
}
|
|
513
432
|
parsed.attributes[1] = items.concat({
|
|
514
433
|
type: 'ATOM',
|
|
515
434
|
value: 'MODSEQ'
|
|
516
435
|
});
|
|
517
436
|
}
|
|
518
|
-
|
|
519
437
|
function hasCondstoreOption(attributes, parent, index) {
|
|
520
438
|
if (!attributes) {
|
|
521
439
|
return false;
|
|
@@ -529,7 +447,6 @@ function hasCondstoreOption(attributes, parent, index) {
|
|
|
529
447
|
break;
|
|
530
448
|
}
|
|
531
449
|
}
|
|
532
|
-
|
|
533
450
|
// remove parameter if no other memebers were left
|
|
534
451
|
if (!attributes.length) {
|
|
535
452
|
parent.splice(index, 1);
|
|
@@ -537,7 +454,6 @@ function hasCondstoreOption(attributes, parent, index) {
|
|
|
537
454
|
}
|
|
538
455
|
return !!condstoreOption;
|
|
539
456
|
}
|
|
540
|
-
|
|
541
457
|
function getCondstoreValue(attributes, name, parent, index) {
|
|
542
458
|
if (!attributes) {
|
|
543
459
|
return false;
|
|
@@ -552,12 +468,10 @@ function getCondstoreValue(attributes, name, parent, index) {
|
|
|
552
468
|
break;
|
|
553
469
|
}
|
|
554
470
|
}
|
|
555
|
-
|
|
556
471
|
// remove parameter if no other memebers were left
|
|
557
472
|
if (!attributes.length) {
|
|
558
473
|
parent.splice(index, 1);
|
|
559
474
|
}
|
|
560
475
|
}
|
|
561
|
-
|
|
562
476
|
return condstoreValue;
|
|
563
477
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @help Adds CONTEXT=SEARCH [RFC5267] capability, loads ESEARCH as well
|
|
3
|
+
* @help SEARCH RETURN (UPDATE) sends ADDTO and REMOVEFROM updates as the result changes, until CANCELUPDATE or the mailbox is closed
|
|
4
|
+
* @help SEARCH RETURN (PARTIAL 1:100) returns a window of the results, the CONTEXT hint is accepted and ignored
|
|
5
|
+
* @help Server option "maxSearchContexts" (default 10) limits the updating contexts of a session, above it NOUPDATE is sent
|
|
6
|
+
*/
|
|
7
|
+
import type { IMAPServer } from '../types.js';
|
|
8
|
+
export default function contextSearchPlugin(server: IMAPServer): void;
|