imapkit 4.0.3 → 4.1.1
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 +271 -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 +106 -133
- 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 +55 -12
- 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
|
@@ -1,37 +1,28 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @help Adds QRESYNC [RFC7162] capability, loads CONDSTORE and ENABLE as well
|
|
5
3
|
* @help After ENABLE QRESYNC: SELECT/EXAMINE (QRESYNC (...)), UID FETCH (CHANGEDSINCE n VANISHED),
|
|
6
4
|
* @help and VANISHED responses instead of EXPUNGE
|
|
7
5
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const { registerEnable, isEnabled } = require('./enable');
|
|
14
|
-
|
|
6
|
+
import fetchHandlers from '../commands/handlers/fetch.js';
|
|
7
|
+
import { isExpungeNotification, toVanished } from '../vanished.js';
|
|
8
|
+
import { MAX_NUMBER64, isNumber, isNzNumber, isSequenceSet } from '../numbers.js';
|
|
9
|
+
import { isAtom } from '../arguments.js';
|
|
10
|
+
import { registerEnable, isEnabled } from './enable.js';
|
|
15
11
|
// commands that report expunged messages, their tagged OK carries the new HIGHESTMODSEQ (RFC 7162 sections 3.2.7
|
|
16
12
|
// and 3.2.9, RFC 6851 section 4.4). CLOSE MUST NOT (RFC 7162 section 3.2.8)
|
|
17
13
|
// REPLACE removes the replaced message as if with UID EXPUNGE (RFC 8508 section 4.5)
|
|
18
14
|
const EXPUNGING_COMMANDS = new Set(['EXPUNGE', 'UID EXPUNGE', 'MOVE', 'UID MOVE', 'REPLACE', 'UID REPLACE']);
|
|
19
|
-
|
|
20
|
-
module.exports = function (server) {
|
|
15
|
+
export default function qresyncPlugin(server) {
|
|
21
16
|
server.registerCapability('QRESYNC');
|
|
22
17
|
registerEnable(server, 'QRESYNC');
|
|
23
|
-
|
|
24
18
|
// RFC 8437 section 4.1: UNAUTHENTICATE ends what ENABLE QRESYNC enabled (the ENABLE plugin clears the list)
|
|
25
|
-
server.resetHandlers.push(connection => {
|
|
19
|
+
server.resetHandlers.push((connection) => {
|
|
26
20
|
connection.qresyncExpunged = false;
|
|
27
21
|
});
|
|
28
|
-
|
|
29
22
|
// mod-sequence each expunged message was removed with
|
|
30
23
|
const expungeModseq = new WeakMap();
|
|
31
|
-
|
|
32
|
-
const isQresync = connection => isEnabled(connection, 'QRESYNC');
|
|
24
|
+
const isQresync = (connection) => isEnabled(connection, 'QRESYNC');
|
|
33
25
|
const { isEnabled: isCondstore, getHighestModseq } = server.condstore;
|
|
34
|
-
|
|
35
26
|
// Expunged UID ranges with their mod-sequences, oldest first (RFC 7162 section 5.3), and the mod-sequence after which
|
|
36
27
|
// all expunges are remembered. Messages missing from the initial storage were expunged at an unknown time
|
|
37
28
|
// before. The record belongs to one UIDVALIDITY, as nothing needs to be kept once it changes
|
|
@@ -41,27 +32,26 @@ module.exports = function (server) {
|
|
|
41
32
|
}
|
|
42
33
|
return mailbox.qresyncExpunged;
|
|
43
34
|
};
|
|
44
|
-
|
|
45
35
|
// start remembering expunges for the mailboxes of the storage once their messages have mod-sequences
|
|
46
36
|
const indexFolders = server.indexFolders;
|
|
47
|
-
server.indexFolders = function () {
|
|
48
|
-
const result = indexFolders.apply(this,
|
|
37
|
+
server.indexFolders = function (...args) {
|
|
38
|
+
const result = indexFolders.apply(this, args);
|
|
49
39
|
Object.keys(this.folderCache).forEach(path => getExpunged(this.folderCache[path]));
|
|
50
40
|
return result;
|
|
51
41
|
};
|
|
52
|
-
|
|
53
42
|
// CONDSTORE has already incremented HIGHESTMODSEQ for this removal, the expunged UIDs get that value
|
|
54
43
|
// (RFC 7162 section 3.2)
|
|
55
44
|
server.on('expunge', (mailbox, messages, connection) => {
|
|
56
45
|
const modseq = getHighestModseq(mailbox);
|
|
57
46
|
const list = getExpunged(mailbox, modseq - 1).list;
|
|
58
|
-
messages.forEach(message => {
|
|
47
|
+
messages.forEach((message) => {
|
|
59
48
|
// consecutive UIDs expunged together are kept as one range, so the history stays small even in long test
|
|
60
49
|
// runs. It is never trimmed: the server keeps everything since it started (RFC 7162 section 5.3)
|
|
61
50
|
const last = list[list.length - 1];
|
|
62
51
|
if (last && last.modseq === modseq && last.to + 1 === message.uid) {
|
|
63
52
|
last.to = message.uid;
|
|
64
|
-
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
65
55
|
list.push({ from: message.uid, to: message.uid, modseq });
|
|
66
56
|
}
|
|
67
57
|
expungeModseq.set(message, modseq);
|
|
@@ -70,7 +60,6 @@ module.exports = function (server) {
|
|
|
70
60
|
connection.qresyncExpunged = true;
|
|
71
61
|
}
|
|
72
62
|
});
|
|
73
|
-
|
|
74
63
|
/**
|
|
75
64
|
* Lists the UIDs of a set that were expunged after a mod-sequence (RFC 7162 sections 3.2.5.1 and 3.2.6)
|
|
76
65
|
*
|
|
@@ -83,31 +72,28 @@ module.exports = function (server) {
|
|
|
83
72
|
*/
|
|
84
73
|
const getVanished = (mailbox, messages, ranges, modseq, knownUpTo) => {
|
|
85
74
|
const { since, list } = getExpunged(mailbox);
|
|
86
|
-
|
|
87
75
|
let candidates;
|
|
88
76
|
if (modseq >= since) {
|
|
89
77
|
// all expunges after the client's mod-sequence are remembered. Message sequence match data only helps
|
|
90
78
|
// when they are not, so it is not used here (RFC 7162 section 5.3)
|
|
91
|
-
candidates = intersectRanges(mergeRanges(list.filter(entry => entry.modseq > modseq).map(entry => [entry.from, entry.to])), ranges);
|
|
92
|
-
}
|
|
79
|
+
candidates = intersectRanges(mergeRanges(list.filter(entry => entry.modseq > modseq).map((entry) => [entry.from, entry.to])), ranges);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
93
82
|
// RFC 7162 section 3.2.6: for a mod-sequence older than the remembered expunges, the server MUST behave as
|
|
94
83
|
// if asked to report all expunged messages of the set: every UID below UIDNEXT that is not in the mailbox,
|
|
95
84
|
// except what the sequence match data shows the client knows
|
|
96
85
|
candidates = intersectRanges(ranges, [[(knownUpTo || 0) + 1, mailbox.uidnext - 1]]);
|
|
97
86
|
}
|
|
98
|
-
|
|
99
87
|
// messages the session still sees are left out, an expunge that the session has not been told about yet is
|
|
100
88
|
// reported with VANISHED without EARLIER
|
|
101
89
|
return subtractUids(candidates, messages)
|
|
102
90
|
.map(range => (range[0] === range[1] ? String(range[0]) : range[0] + ':' + range[1]))
|
|
103
91
|
.join(',');
|
|
104
92
|
};
|
|
105
|
-
|
|
106
93
|
const sendBad = (connection, parsed, data, callback, message) => {
|
|
107
94
|
connection.sendStatus(parsed, data, 'BAD', message, false, 'QRESYNC FAILED');
|
|
108
95
|
return callback();
|
|
109
96
|
};
|
|
110
|
-
|
|
111
97
|
// Wraps an existing command handler. Commands that are not available are left alone
|
|
112
98
|
const wrapHandler = (command, wrapper) => {
|
|
113
99
|
const prevHandler = server.getCommandHandler(command);
|
|
@@ -116,51 +102,44 @@ module.exports = function (server) {
|
|
|
116
102
|
}
|
|
117
103
|
server.setCommandHandler(command, (connection, parsed, data, callback) => wrapper(prevHandler, connection, parsed, data, callback));
|
|
118
104
|
};
|
|
119
|
-
|
|
120
105
|
// RFC 7162 section 3.2.5: SELECT/EXAMINE mailbox (QRESYNC (uidvalidity mod-sequence-value [known-uids] [seq-match-data]))
|
|
121
106
|
const selectWrapper = (prevHandler, connection, parsed, data, callback) => {
|
|
122
107
|
const params = parsed.attributes && parsed.attributes[1];
|
|
123
|
-
const isQresyncParam = param => isAtom(param, 'QRESYNC');
|
|
108
|
+
const isQresyncParam = (param) => isAtom(param, 'QRESYNC');
|
|
124
109
|
const position = Array.isArray(params) ? params.findIndex(isQresyncParam) : -1;
|
|
125
110
|
if (position < 0) {
|
|
126
111
|
return prevHandler(connection, parsed, data, callback);
|
|
127
112
|
}
|
|
128
|
-
|
|
129
113
|
if (!isQresync(connection)) {
|
|
130
114
|
return sendBad(connection, parsed, data, callback, 'QRESYNC parameter requires ENABLE QRESYNC');
|
|
131
115
|
}
|
|
132
116
|
if (params.findLastIndex(isQresyncParam) !== position) {
|
|
133
117
|
return sendBad(connection, parsed, data, callback, 'QRESYNC parameter can be used only once');
|
|
134
118
|
}
|
|
135
|
-
|
|
136
119
|
let qresync;
|
|
137
120
|
try {
|
|
138
121
|
qresync = parseQresyncParam(params[position + 1]);
|
|
139
|
-
}
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
140
124
|
return sendBad(connection, parsed, data, callback, err.message);
|
|
141
125
|
}
|
|
142
|
-
|
|
143
126
|
params.splice(position, 2);
|
|
144
127
|
if (!params.length) {
|
|
145
128
|
parsed.attributes.splice(1, 1);
|
|
146
129
|
}
|
|
147
130
|
parsed.qresync = qresync;
|
|
148
|
-
|
|
149
131
|
prevHandler(connection, parsed, data, callback);
|
|
150
132
|
};
|
|
151
|
-
|
|
152
133
|
wrapHandler('SELECT', selectWrapper);
|
|
153
134
|
wrapHandler('EXAMINE', selectWrapper);
|
|
154
|
-
|
|
155
135
|
// RFC 7162 section 3.2.6: the VANISHED UID FETCH modifier
|
|
156
136
|
const fetchWrapper = (isUid, prevHandler, connection, parsed, data, callback) => {
|
|
157
137
|
const modifiers = parsed.attributes && parsed.attributes[2];
|
|
158
|
-
const isVanished = modifier => isAtom(modifier, 'VANISHED');
|
|
138
|
+
const isVanished = (modifier) => isAtom(modifier, 'VANISHED');
|
|
159
139
|
const position = Array.isArray(modifiers) ? modifiers.findIndex(isVanished) : -1;
|
|
160
140
|
if (position < 0) {
|
|
161
141
|
return prevHandler(connection, parsed, data, callback);
|
|
162
142
|
}
|
|
163
|
-
|
|
164
143
|
if (!isUid) {
|
|
165
144
|
return sendBad(connection, parsed, data, callback, 'VANISHED is only allowed with UID FETCH');
|
|
166
145
|
}
|
|
@@ -170,58 +149,46 @@ module.exports = function (server) {
|
|
|
170
149
|
if (modifiers.findLastIndex(isVanished) !== position) {
|
|
171
150
|
return sendBad(connection, parsed, data, callback, 'VANISHED can be used only once');
|
|
172
151
|
}
|
|
173
|
-
if (!modifiers.some(modifier => isAtom(modifier, 'CHANGEDSINCE'))) {
|
|
152
|
+
if (!modifiers.some((modifier) => isAtom(modifier, 'CHANGEDSINCE'))) {
|
|
174
153
|
return sendBad(connection, parsed, data, callback, 'VANISHED requires CHANGEDSINCE');
|
|
175
154
|
}
|
|
176
|
-
|
|
177
155
|
modifiers.splice(position, 1);
|
|
178
156
|
parsed.qresyncVanished = true;
|
|
179
|
-
|
|
180
157
|
prevHandler(connection, parsed, data, callback);
|
|
181
158
|
};
|
|
182
|
-
|
|
183
159
|
wrapHandler('FETCH', fetchWrapper.bind(null, false));
|
|
184
160
|
wrapHandler('UID FETCH', fetchWrapper.bind(null, true));
|
|
185
|
-
|
|
186
161
|
// RFC 7162 section 3.2.10: after ENABLE QRESYNC, expunges are reported with VANISHED instead of EXPUNGE.
|
|
187
162
|
// Consecutive EXPUNGE notifications become one VANISHED response
|
|
188
|
-
server.connectionHandlers.push(connection => {
|
|
163
|
+
server.connectionHandlers.push((connection) => {
|
|
189
164
|
const prepareNotifications = connection.prepareNotifications;
|
|
190
165
|
connection.prepareNotifications = function (queue) {
|
|
191
166
|
queue = prepareNotifications.call(this, queue);
|
|
192
167
|
return isQresync(this) ? toVanished(queue) : queue;
|
|
193
168
|
};
|
|
194
169
|
});
|
|
195
|
-
|
|
196
170
|
// Sends a VANISHED (EARLIER) response, if there is anything to report
|
|
197
171
|
const sendVanishedEarlier = (connection, uids, parsed, data) => {
|
|
198
172
|
if (!uids) {
|
|
199
173
|
return;
|
|
200
174
|
}
|
|
201
|
-
connection.send(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
},
|
|
207
|
-
'VANISHED EARLIER',
|
|
208
|
-
parsed,
|
|
209
|
-
data
|
|
210
|
-
);
|
|
175
|
+
connection.send({
|
|
176
|
+
tag: '*',
|
|
177
|
+
command: 'VANISHED',
|
|
178
|
+
attributes: [[{ type: 'ATOM', value: 'EARLIER' }], { type: 'SEQUENCE', value: uids }]
|
|
179
|
+
}, 'VANISHED EARLIER', parsed, data);
|
|
211
180
|
};
|
|
212
|
-
|
|
213
181
|
// RFC 7162 section 3.2.5.1: after SELECT/EXAMINE (QRESYNC), expunges and flag changes since the given mod-sequence
|
|
214
182
|
const sendQresyncChanges = (connection, parsed, data) => {
|
|
183
|
+
// only called with a mailbox selected
|
|
215
184
|
const mailbox = connection.selectedMailbox;
|
|
216
185
|
const qresync = parsed.qresync;
|
|
217
186
|
if (qresync.uidvalidity !== mailbox.uidvalidity) {
|
|
218
187
|
// RFC 7162 section 3.2.5: ignore the remaining parameters if UIDVALIDITY does not match
|
|
219
188
|
return;
|
|
220
189
|
}
|
|
221
|
-
|
|
222
190
|
// without known UIDs, the client is treated as if it sent 1:<UIDNEXT - 1>, nothing for an unused mailbox
|
|
223
191
|
const ranges = qresync.knownUids || (mailbox.uidnext > 1 ? [[1, mailbox.uidnext - 1]] : []);
|
|
224
|
-
|
|
225
192
|
// RFC 7162 section 3.2.5.2: the last pair of sequence number and UID that still match tells up to which
|
|
226
193
|
// UID the client knows about all expunges, the first pair that does not match ends the comparison
|
|
227
194
|
let knownUpTo = 0;
|
|
@@ -236,51 +203,41 @@ module.exports = function (server) {
|
|
|
236
203
|
knownUpTo = uid;
|
|
237
204
|
}
|
|
238
205
|
}
|
|
239
|
-
|
|
240
206
|
// VANISHED (EARLIER) MUST come before the FETCH responses (RFC 7162 section 3.2.6)
|
|
241
207
|
sendVanishedEarlier(connection, getVanished(mailbox, mailbox.messages, ranges, qresync.modseq, knownUpTo), parsed, data);
|
|
242
|
-
|
|
243
208
|
const getFlags = server.fetchHandlers.FLAGS || fetchHandlers.FLAGS;
|
|
244
209
|
mailbox.messages.forEach((message, i) => {
|
|
245
210
|
if (message.MODSEQ <= qresync.modseq || !inRanges(ranges, message.uid)) {
|
|
246
211
|
return;
|
|
247
212
|
}
|
|
248
213
|
// flag changes MUST include the UID (RFC 7162 section 3.2.5.1)
|
|
249
|
-
connection.send(
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
[message.MODSEQ]
|
|
262
|
-
]
|
|
214
|
+
connection.send({
|
|
215
|
+
tag: '*',
|
|
216
|
+
attributes: [
|
|
217
|
+
i + 1,
|
|
218
|
+
{ type: 'ATOM', value: 'FETCH' },
|
|
219
|
+
[
|
|
220
|
+
{ type: 'ATOM', value: 'UID' },
|
|
221
|
+
message.uid,
|
|
222
|
+
{ type: 'ATOM', value: 'FLAGS' },
|
|
223
|
+
getFlags(connection, message, { type: 'ATOM', value: 'FLAGS' }),
|
|
224
|
+
{ type: 'ATOM', value: 'MODSEQ' },
|
|
225
|
+
[message.MODSEQ]
|
|
263
226
|
]
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
parsed,
|
|
267
|
-
data,
|
|
268
|
-
message
|
|
269
|
-
);
|
|
227
|
+
]
|
|
228
|
+
}, 'QRESYNC FETCH', parsed, data, message);
|
|
270
229
|
});
|
|
271
230
|
};
|
|
272
|
-
|
|
273
|
-
const highestModseqCode = modseq => ({ type: 'SECTION', section: [{ type: 'ATOM', value: 'HIGHESTMODSEQ' }, modseq] });
|
|
274
|
-
|
|
231
|
+
const highestModseqCode = (modseq) => ({ type: 'SECTION', section: [{ type: 'ATOM', value: 'HIGHESTMODSEQ' }, modseq] });
|
|
275
232
|
server.outputHandlers.push((connection, response, description, parsed, data) => {
|
|
276
233
|
if (!parsed || !response || response.tag === '+') {
|
|
277
234
|
return;
|
|
278
235
|
}
|
|
279
236
|
const isTagged = response.tag !== '*' && response.tag === parsed.tag;
|
|
280
|
-
|
|
281
237
|
// UID FETCH (VANISHED): VANISHED (EARLIER) comes before the first FETCH response, or before the tagged OK
|
|
282
238
|
if (parsed.qresyncVanished && ((response.tag === '*' && description === 'UID FETCH') || (isTagged && response.command === 'OK'))) {
|
|
283
239
|
parsed.qresyncVanished = false;
|
|
240
|
+
// UID FETCH runs in the Selected state
|
|
284
241
|
const mailbox = connection.selectedMailbox;
|
|
285
242
|
const ranges = parseUidSet(parsed.attributes[0].value, mailbox.uidnext - 1);
|
|
286
243
|
if (ranges) {
|
|
@@ -288,61 +245,48 @@ module.exports = function (server) {
|
|
|
288
245
|
}
|
|
289
246
|
return;
|
|
290
247
|
}
|
|
291
|
-
|
|
292
248
|
if (!isTagged) {
|
|
293
249
|
return;
|
|
294
250
|
}
|
|
295
|
-
|
|
296
251
|
if (parsed.qresync && response.command === 'OK' && (description === 'SELECT' || description === 'EXAMINE') && connection.selectedMailbox) {
|
|
297
252
|
sendQresyncChanges(connection, parsed, data);
|
|
298
253
|
return;
|
|
299
254
|
}
|
|
300
|
-
|
|
301
255
|
const expunged = connection.qresyncExpunged;
|
|
302
256
|
connection.qresyncExpunged = false;
|
|
303
|
-
|
|
304
257
|
// HIGHESTMODSEQ in the tagged OK once messages were expunged, RFC 7162 sections 3.2.7 and 3.2.9 require it
|
|
305
258
|
// with QRESYNC enabled, RFC 6851 section 4.4 for MOVE
|
|
306
|
-
if (
|
|
307
|
-
expunged &&
|
|
259
|
+
if (expunged &&
|
|
308
260
|
response.command === 'OK' &&
|
|
309
261
|
EXPUNGING_COMMANDS.has(String(parsed.command).toUpperCase()) &&
|
|
310
262
|
connection.selectedMailbox &&
|
|
311
|
-
isCondstore(connection)
|
|
312
|
-
) {
|
|
263
|
+
isCondstore(connection)) {
|
|
313
264
|
const hasCode = response.attributes && response.attributes[0] && response.attributes[0].type === 'SECTION';
|
|
314
265
|
if (!hasCode) {
|
|
315
266
|
response.attributes = [highestModseqCode(getHighestModseq(connection.selectedMailbox))].concat(response.attributes || []);
|
|
316
267
|
}
|
|
317
268
|
return;
|
|
318
269
|
}
|
|
319
|
-
|
|
320
270
|
// RFC 7162 section 3.2: while expunges are held back (FETCH, STORE, SEARCH), the client must not take a
|
|
321
271
|
// MODSEQ it got as the new HIGHESTMODSEQ, so tell it a value below the mod-sequence of the pending expunges
|
|
322
272
|
if (isCondstore(connection)) {
|
|
323
273
|
let lowest = 0;
|
|
324
|
-
connection.notificationQueue.forEach(notification => {
|
|
325
|
-
const modseq = isExpungeNotification(notification) && expungeModseq.get(notification.message);
|
|
274
|
+
connection.notificationQueue.forEach((notification) => {
|
|
275
|
+
const modseq = isExpungeNotification(notification) && notification.message && expungeModseq.get(notification.message);
|
|
326
276
|
if (modseq && (!lowest || modseq < lowest)) {
|
|
327
277
|
lowest = modseq;
|
|
328
278
|
}
|
|
329
279
|
});
|
|
330
280
|
if (lowest > 1) {
|
|
331
|
-
connection.send(
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
},
|
|
337
|
-
'QRESYNC HIGHESTMODSEQ',
|
|
338
|
-
parsed,
|
|
339
|
-
data
|
|
340
|
-
);
|
|
281
|
+
connection.send({
|
|
282
|
+
tag: '*',
|
|
283
|
+
command: 'OK',
|
|
284
|
+
attributes: [highestModseqCode(lowest - 1), { type: 'TEXT', value: 'Expunges not reported yet' }]
|
|
285
|
+
}, 'QRESYNC HIGHESTMODSEQ', parsed, data);
|
|
341
286
|
}
|
|
342
287
|
}
|
|
343
288
|
});
|
|
344
|
-
}
|
|
345
|
-
|
|
289
|
+
}
|
|
346
290
|
/**
|
|
347
291
|
* Parses a sequence set without "*" into [from, to] ranges as written
|
|
348
292
|
*
|
|
@@ -354,12 +298,11 @@ function parseSequenceSet(value, name) {
|
|
|
354
298
|
if (!value || Array.isArray(value) || ['ATOM', 'SEQUENCE'].indexOf(value.type) < 0 || !isSequenceSet(value.value, true)) {
|
|
355
299
|
throw new Error('Invalid QRESYNC ' + name + ', a sequence set without "*" expected');
|
|
356
300
|
}
|
|
357
|
-
return value.value.split(',').map(part => {
|
|
301
|
+
return value.value.split(',').map((part) => {
|
|
358
302
|
const range = part.split(':').map(Number);
|
|
359
303
|
return [range[0], range.length > 1 ? range[1] : range[0]];
|
|
360
304
|
});
|
|
361
305
|
}
|
|
362
|
-
|
|
363
306
|
/**
|
|
364
307
|
* Parses the UID set of UID FETCH, "*" stands for the highest UID the mailbox may have used
|
|
365
308
|
*
|
|
@@ -371,13 +314,10 @@ function parseUidSet(value, star) {
|
|
|
371
314
|
if (!/^[\d*:,]+$/.test(String(value))) {
|
|
372
315
|
return false;
|
|
373
316
|
}
|
|
374
|
-
return mergeRanges(
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
.map(part => part.split(':').map(number => (number === '*' ? star : Number(number))))
|
|
378
|
-
);
|
|
317
|
+
return mergeRanges(String(value)
|
|
318
|
+
.split(',')
|
|
319
|
+
.map(part => part.split(':').map(number => (number === '*' ? star : Number(number)))));
|
|
379
320
|
}
|
|
380
|
-
|
|
381
321
|
// Intersection of two lists of ascending, non-overlapping ranges
|
|
382
322
|
function intersectRanges(a, b) {
|
|
383
323
|
const result = [];
|
|
@@ -391,13 +331,13 @@ function intersectRanges(a, b) {
|
|
|
391
331
|
}
|
|
392
332
|
if (a[i][1] < b[j][1]) {
|
|
393
333
|
i++;
|
|
394
|
-
}
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
395
336
|
j++;
|
|
396
337
|
}
|
|
397
338
|
}
|
|
398
339
|
return result;
|
|
399
340
|
}
|
|
400
|
-
|
|
401
341
|
// Removes the UIDs of messages (ordered by UID) from ascending ranges, walking both lists once
|
|
402
342
|
function subtractUids(ranges, messages) {
|
|
403
343
|
const result = [];
|
|
@@ -419,7 +359,6 @@ function subtractUids(ranges, messages) {
|
|
|
419
359
|
});
|
|
420
360
|
return result;
|
|
421
361
|
}
|
|
422
|
-
|
|
423
362
|
/**
|
|
424
363
|
* Orders the ends of every range and merges overlapping or adjacent ranges, so that a UID is listed once
|
|
425
364
|
*
|
|
@@ -427,19 +366,19 @@ function subtractUids(ranges, messages) {
|
|
|
427
366
|
* @return {Array} ascending [low, high] ranges
|
|
428
367
|
*/
|
|
429
368
|
function mergeRanges(ranges) {
|
|
430
|
-
const sorted = ranges.map(range => [Math.min(...range), Math.max(...range)]).sort((a, b) => a[0] - b[0]);
|
|
369
|
+
const sorted = ranges.map((range) => [Math.min(...range), Math.max(...range)]).sort((a, b) => a[0] - b[0]);
|
|
431
370
|
const result = [];
|
|
432
371
|
sorted.forEach(range => {
|
|
433
372
|
const last = result[result.length - 1];
|
|
434
373
|
if (last && range[0] <= last[1] + 1) {
|
|
435
374
|
last[1] = Math.max(last[1], range[1]);
|
|
436
|
-
}
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
437
377
|
result.push(range);
|
|
438
378
|
}
|
|
439
379
|
});
|
|
440
380
|
return result;
|
|
441
381
|
}
|
|
442
|
-
|
|
443
382
|
// Lists the numbers of ascending ranges one by one
|
|
444
383
|
function* iterateRanges(ranges) {
|
|
445
384
|
for (const [from, to] of ranges) {
|
|
@@ -448,7 +387,6 @@ function* iterateRanges(ranges) {
|
|
|
448
387
|
}
|
|
449
388
|
}
|
|
450
389
|
}
|
|
451
|
-
|
|
452
390
|
/**
|
|
453
391
|
* Checks that a sequence set lists its numbers in ascending order and counts them
|
|
454
392
|
*/
|
|
@@ -464,7 +402,6 @@ function countAscending(ranges, name) {
|
|
|
464
402
|
});
|
|
465
403
|
return count;
|
|
466
404
|
}
|
|
467
|
-
|
|
468
405
|
/**
|
|
469
406
|
* Validates the value of the QRESYNC SELECT/EXAMINE parameter (RFC 7162 section 7):
|
|
470
407
|
* "(" uidvalidity SP mod-sequence-value [SP known-uids] [SP seq-match-data] ")"
|
|
@@ -476,7 +413,6 @@ function parseQresyncParam(value) {
|
|
|
476
413
|
if (!Array.isArray(value) || value.length < 2 || value.length > 4) {
|
|
477
414
|
throw new Error('QRESYNC expects (uidvalidity modseq [known-uids] [(known-sequence-set known-uid-set)])');
|
|
478
415
|
}
|
|
479
|
-
|
|
480
416
|
const [uidvalidity, modseq] = value;
|
|
481
417
|
// uidvalidity = nz-number
|
|
482
418
|
if (!isAtom(uidvalidity) || !isNzNumber(uidvalidity.value)) {
|
|
@@ -486,19 +422,16 @@ function parseQresyncParam(value) {
|
|
|
486
422
|
if (!isAtom(modseq) || !isNumber(modseq.value, MAX_NUMBER64) || BigInt(modseq.value) < 1n) {
|
|
487
423
|
throw new Error('Invalid QRESYNC mod-sequence, a positive number expected');
|
|
488
424
|
}
|
|
489
|
-
|
|
490
425
|
const result = {
|
|
491
426
|
uidvalidity: Number(uidvalidity.value),
|
|
492
427
|
modseq: Number(modseq.value),
|
|
493
428
|
knownUids: false,
|
|
494
429
|
seqMatch: false
|
|
495
430
|
};
|
|
496
|
-
|
|
497
431
|
const rest = value.slice(2);
|
|
498
432
|
if (rest.length && !Array.isArray(rest[0])) {
|
|
499
433
|
result.knownUids = mergeRanges(parseSequenceSet(rest.shift(), 'known-uids'));
|
|
500
434
|
}
|
|
501
|
-
|
|
502
435
|
if (rest.length) {
|
|
503
436
|
const seqMatch = rest.shift();
|
|
504
437
|
if (!Array.isArray(seqMatch) || seqMatch.length !== 2 || rest.length) {
|
|
@@ -513,13 +446,10 @@ function parseQresyncParam(value) {
|
|
|
513
446
|
}
|
|
514
447
|
result.seqMatch = { sequences, uids };
|
|
515
448
|
}
|
|
516
|
-
|
|
517
449
|
return result;
|
|
518
450
|
}
|
|
519
|
-
|
|
520
451
|
function inRanges(ranges, uid) {
|
|
521
452
|
return ranges.some(range => uid >= range[0] && uid <= range[1]);
|
|
522
453
|
}
|
|
523
|
-
|
|
524
454
|
// RFC 7162 section 3.2.3: a QRESYNC server implements CONDSTORE and ENABLE, these are loaded first
|
|
525
|
-
|
|
455
|
+
qresyncPlugin.requires = ['ENABLE', 'CONDSTORE'];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IMAPServer } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* @help Adds QUOTA [RFC9208] capability with the STORAGE, MESSAGE and MAILBOX
|
|
4
|
+
* @help resources and SETQUOTA. All personal mailboxes share one quota root, set
|
|
5
|
+
* @help with the "quota" server option, eg. {"root": "User quota",
|
|
6
|
+
* @help "STORAGE": 10240, "MESSAGE": 1000, "MAILBOX": 100, "soft": false}.
|
|
7
|
+
* @help STORAGE is in units of 1024 octets. Hard limits make APPEND, COPY, MOVE
|
|
8
|
+
* @help and CREATE fail with NO [OVERQUOTA], soft limits only send a warning
|
|
9
|
+
*
|
|
10
|
+
* QUOTA: https://www.rfc-editor.org/rfc/rfc9208.txt
|
|
11
|
+
*
|
|
12
|
+
* Additional commands:
|
|
13
|
+
* - GETQUOTA, GETQUOTAROOT, SETQUOTA
|
|
14
|
+
*
|
|
15
|
+
* Additional STATUS items:
|
|
16
|
+
* - DELETED, DELETED-STORAGE
|
|
17
|
+
*/
|
|
18
|
+
export default function quotaPlugin(server: IMAPServer): void;
|