imapkit 4.0.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -19
- package/bin/imapkit.js +12 -16
- package/dist/cjs/addressparser.d.ts +21 -0
- package/dist/cjs/addressparser.js +277 -0
- package/dist/cjs/arguments.d.ts +31 -0
- package/{lib → dist/cjs}/arguments.js +9 -21
- package/dist/cjs/bodystructure.d.ts +25 -0
- package/dist/cjs/bodystructure.js +150 -0
- package/dist/cjs/cert.d.ts +2 -0
- package/dist/cjs/cert.js +7 -0
- package/dist/cjs/command-states.d.ts +36 -0
- package/dist/cjs/command-states.js +102 -0
- package/dist/cjs/commands/append.d.ts +88 -0
- package/dist/cjs/commands/append.js +299 -0
- package/dist/cjs/commands/capability.d.ts +2 -0
- package/dist/cjs/commands/capability.js +44 -0
- package/dist/cjs/commands/check.d.ts +2 -0
- package/dist/cjs/commands/check.js +28 -0
- package/dist/cjs/commands/close.d.ts +2 -0
- package/dist/cjs/commands/close.js +35 -0
- package/dist/cjs/commands/copy.d.ts +30 -0
- package/dist/cjs/commands/copy.js +107 -0
- package/dist/cjs/commands/create.d.ts +2 -0
- package/dist/cjs/commands/create.js +53 -0
- package/dist/cjs/commands/delete.d.ts +2 -0
- package/dist/cjs/commands/delete.js +63 -0
- package/dist/cjs/commands/examine.d.ts +2 -0
- package/dist/cjs/commands/examine.js +19 -0
- package/dist/cjs/commands/expunge.d.ts +2 -0
- package/dist/cjs/commands/expunge.js +32 -0
- package/dist/cjs/commands/fetch.d.ts +23 -0
- package/dist/cjs/commands/fetch.js +208 -0
- package/dist/cjs/commands/handlers/fetch.d.ts +12 -0
- package/dist/cjs/commands/handlers/fetch.js +195 -0
- package/dist/cjs/commands/handlers/flags.d.ts +17 -0
- package/dist/cjs/commands/handlers/flags.js +39 -0
- package/dist/cjs/commands/handlers/search.d.ts +85 -0
- package/dist/cjs/commands/handlers/search.js +504 -0
- package/dist/cjs/commands/handlers/status.d.ts +34 -0
- package/dist/cjs/commands/handlers/status.js +81 -0
- package/dist/cjs/commands/handlers/store.d.ts +3 -0
- package/dist/cjs/commands/handlers/store.js +117 -0
- package/dist/cjs/commands/index.d.ts +2 -0
- package/dist/cjs/commands/index.js +61 -0
- package/dist/cjs/commands/list.d.ts +2 -0
- package/dist/cjs/commands/list.js +86 -0
- package/dist/cjs/commands/login.d.ts +2 -0
- package/dist/cjs/commands/login.js +62 -0
- package/dist/cjs/commands/logout.d.ts +2 -0
- package/dist/cjs/commands/logout.js +40 -0
- package/dist/cjs/commands/lsub.d.ts +2 -0
- package/dist/cjs/commands/lsub.js +79 -0
- package/dist/cjs/commands/noop.d.ts +2 -0
- package/dist/cjs/commands/noop.js +28 -0
- package/dist/cjs/commands/rename.d.ts +2 -0
- package/dist/cjs/commands/rename.js +98 -0
- package/dist/cjs/commands/search.d.ts +10 -0
- package/dist/cjs/commands/search.js +71 -0
- package/dist/cjs/commands/select.d.ts +19 -0
- package/dist/cjs/commands/select.js +230 -0
- package/dist/cjs/commands/status.d.ts +2 -0
- package/dist/cjs/commands/status.js +57 -0
- package/dist/cjs/commands/store.d.ts +10 -0
- package/dist/cjs/commands/store.js +134 -0
- package/dist/cjs/commands/subscribe.d.ts +2 -0
- package/dist/cjs/commands/subscribe.js +51 -0
- package/dist/cjs/commands/uid-copy.d.ts +2 -0
- package/dist/cjs/commands/uid-copy.js +19 -0
- package/dist/cjs/commands/uid-fetch.d.ts +3 -0
- package/dist/cjs/commands/uid-fetch.js +17 -0
- package/dist/cjs/commands/uid-search.d.ts +3 -0
- package/dist/cjs/commands/uid-search.js +17 -0
- package/dist/cjs/commands/uid-store.d.ts +3 -0
- package/dist/cjs/commands/uid-store.js +17 -0
- package/dist/cjs/commands/unsubscribe.d.ts +2 -0
- package/dist/cjs/commands/unsubscribe.js +50 -0
- package/dist/cjs/dates.d.ts +64 -0
- package/dist/cjs/dates.js +124 -0
- package/dist/cjs/deflate-layer.d.ts +83 -0
- package/dist/cjs/deflate-layer.js +232 -0
- package/dist/cjs/encoded-words.d.ts +15 -0
- package/dist/cjs/encoded-words.js +85 -0
- package/dist/cjs/envelope.d.ts +33 -0
- package/dist/cjs/envelope.js +86 -0
- package/dist/cjs/esearch.d.ts +96 -0
- package/dist/cjs/esearch.js +190 -0
- package/dist/cjs/framing.d.ts +66 -0
- package/{lib → dist/cjs}/framing.js +9 -26
- package/dist/cjs/index.d.ts +9 -0
- package/dist/cjs/index.js +56 -0
- package/dist/cjs/list-extensions.d.ts +50 -0
- package/dist/cjs/list-extensions.js +35 -0
- package/dist/cjs/load-plugins.d.ts +21 -0
- package/dist/cjs/load-plugins.js +89 -0
- package/dist/cjs/mailbox-name.d.ts +26 -0
- package/dist/cjs/mailbox-name.js +127 -0
- package/dist/cjs/mimeparser.d.ts +137 -0
- package/dist/cjs/mimeparser.js +727 -0
- package/dist/cjs/mock-client.d.ts +39 -0
- package/dist/cjs/mock-client.js +236 -0
- package/dist/cjs/numbers.d.ts +28 -0
- package/dist/cjs/numbers.js +52 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/plugins/acl.d.ts +2 -0
- package/dist/cjs/plugins/acl.js +888 -0
- package/dist/cjs/plugins/appendlimit.d.ts +16 -0
- package/dist/cjs/plugins/appendlimit.js +87 -0
- package/dist/cjs/plugins/auth-plain.d.ts +2 -0
- package/dist/cjs/plugins/auth-plain.js +89 -0
- package/dist/cjs/plugins/binary.d.ts +30 -0
- package/dist/cjs/plugins/binary.js +247 -0
- package/dist/cjs/plugins/catenate.d.ts +14 -0
- package/dist/cjs/plugins/catenate.js +250 -0
- package/dist/cjs/plugins/compress.d.ts +7 -0
- package/dist/cjs/plugins/compress.js +79 -0
- package/dist/cjs/plugins/condstore.d.ts +5 -0
- package/dist/cjs/plugins/condstore.js +492 -0
- package/dist/cjs/plugins/context-search.d.ts +8 -0
- package/dist/cjs/plugins/context-search.js +304 -0
- package/dist/cjs/plugins/context-sort.d.ts +6 -0
- package/dist/cjs/plugins/context-sort.js +32 -0
- package/dist/cjs/plugins/create-special-use.d.ts +7 -0
- package/dist/cjs/plugins/create-special-use.js +101 -0
- package/dist/cjs/plugins/enable.d.ts +23 -0
- package/dist/cjs/plugins/enable.js +127 -0
- package/dist/cjs/plugins/esearch.d.ts +6 -0
- package/dist/cjs/plugins/esearch.js +142 -0
- package/dist/cjs/plugins/esort.d.ts +6 -0
- package/dist/cjs/plugins/esort.js +60 -0
- package/dist/cjs/plugins/id.d.ts +5 -0
- package/dist/cjs/plugins/id.js +123 -0
- package/dist/cjs/plugins/idle.d.ts +5 -0
- package/dist/cjs/plugins/idle.js +85 -0
- package/dist/cjs/plugins/imap4rev2.d.ts +6 -0
- package/dist/cjs/plugins/imap4rev2.js +184 -0
- package/dist/cjs/plugins/index.d.ts +2 -0
- package/dist/cjs/plugins/index.js +119 -0
- package/dist/cjs/plugins/list-extended.d.ts +2 -0
- package/dist/cjs/plugins/list-extended.js +235 -0
- package/dist/cjs/plugins/list-status.d.ts +6 -0
- package/dist/cjs/plugins/list-status.js +42 -0
- package/dist/cjs/plugins/literalminus.d.ts +8 -0
- package/dist/cjs/plugins/literalminus.js +32 -0
- package/dist/cjs/plugins/literalplus.d.ts +6 -0
- package/dist/cjs/plugins/literalplus.js +30 -0
- package/dist/cjs/plugins/logindisabled.d.ts +5 -0
- package/dist/cjs/plugins/logindisabled.js +54 -0
- package/dist/cjs/plugins/messagelimit.d.ts +19 -0
- package/dist/cjs/plugins/messagelimit.js +227 -0
- package/dist/cjs/plugins/metadata-server.d.ts +7 -0
- package/dist/cjs/plugins/metadata-server.js +24 -0
- package/dist/cjs/plugins/metadata.d.ts +11 -0
- package/dist/cjs/plugins/metadata.js +436 -0
- package/dist/cjs/plugins/move.d.ts +11 -0
- package/dist/cjs/plugins/move.js +96 -0
- package/dist/cjs/plugins/multiappend.d.ts +12 -0
- package/dist/cjs/plugins/multiappend.js +38 -0
- package/dist/cjs/plugins/multisearch.d.ts +6 -0
- package/dist/cjs/plugins/multisearch.js +263 -0
- package/dist/cjs/plugins/namespace.d.ts +5 -0
- package/dist/cjs/plugins/namespace.js +57 -0
- package/dist/cjs/plugins/notify.d.ts +2 -0
- package/dist/cjs/plugins/notify.js +628 -0
- package/dist/cjs/plugins/oauthbearer.d.ts +32 -0
- package/dist/cjs/plugins/oauthbearer.js +202 -0
- package/dist/cjs/plugins/objectid.d.ts +23 -0
- package/dist/cjs/plugins/objectid.js +221 -0
- package/dist/cjs/plugins/partial.d.ts +6 -0
- package/dist/cjs/plugins/partial.js +78 -0
- package/dist/cjs/plugins/preview.d.ts +31 -0
- package/dist/cjs/plugins/preview.js +378 -0
- package/dist/cjs/plugins/qresync.d.ts +11 -0
- package/dist/cjs/plugins/qresync.js +473 -0
- package/dist/cjs/plugins/quota.d.ts +18 -0
- package/dist/cjs/plugins/quota.js +254 -0
- package/dist/cjs/plugins/replace.d.ts +14 -0
- package/dist/cjs/plugins/replace.js +130 -0
- package/dist/cjs/plugins/sasl-ir.d.ts +5 -0
- package/dist/cjs/plugins/sasl-ir.js +24 -0
- package/dist/cjs/plugins/savedate.d.ts +17 -0
- package/dist/cjs/plugins/savedate.js +64 -0
- package/dist/cjs/plugins/savelimit.d.ts +10 -0
- package/dist/cjs/plugins/savelimit.js +30 -0
- package/dist/cjs/plugins/searchres.d.ts +6 -0
- package/dist/cjs/plugins/searchres.js +91 -0
- package/dist/cjs/plugins/sort-display.d.ts +11 -0
- package/dist/cjs/plugins/sort-display.js +37 -0
- package/dist/cjs/plugins/sort.d.ts +11 -0
- package/dist/cjs/plugins/sort.js +125 -0
- package/dist/cjs/plugins/special-use.d.ts +10 -0
- package/dist/cjs/plugins/special-use.js +95 -0
- package/dist/cjs/plugins/starttls.d.ts +5 -0
- package/dist/cjs/plugins/starttls.js +55 -0
- package/dist/cjs/plugins/status-size.d.ts +7 -0
- package/dist/cjs/plugins/status-size.js +30 -0
- package/dist/cjs/plugins/thread-orderedsubject.d.ts +11 -0
- package/dist/cjs/plugins/thread-orderedsubject.js +28 -0
- package/dist/cjs/plugins/thread-references.d.ts +11 -0
- package/dist/cjs/plugins/thread-references.js +28 -0
- package/dist/cjs/plugins/uidonly.d.ts +15 -0
- package/dist/cjs/plugins/uidonly.js +126 -0
- package/dist/cjs/plugins/uidplus.d.ts +15 -0
- package/dist/cjs/plugins/uidplus.js +119 -0
- package/dist/cjs/plugins/unauthenticate.d.ts +7 -0
- package/dist/cjs/plugins/unauthenticate.js +32 -0
- package/dist/cjs/plugins/unselect.d.ts +5 -0
- package/dist/cjs/plugins/unselect.js +36 -0
- package/dist/cjs/plugins/utf8-accept.d.ts +6 -0
- package/dist/cjs/plugins/utf8-accept.js +72 -0
- package/dist/cjs/plugins/x-gm-ext-1.d.ts +26 -0
- package/dist/cjs/plugins/x-gm-ext-1.js +422 -0
- package/dist/cjs/plugins/xoauth2.d.ts +2 -0
- package/dist/cjs/plugins/xoauth2.js +155 -0
- package/dist/cjs/plugins/xtoybird.d.ts +2 -0
- package/dist/cjs/plugins/xtoybird.js +236 -0
- package/dist/cjs/server.d.ts +876 -0
- package/dist/cjs/server.js +2597 -0
- package/dist/cjs/smtp-listener.d.ts +13 -0
- package/dist/cjs/smtp-listener.js +47 -0
- package/dist/cjs/sorting.d.ts +77 -0
- package/dist/cjs/sorting.js +290 -0
- package/dist/cjs/threading.d.ts +30 -0
- package/dist/cjs/threading.js +318 -0
- package/dist/cjs/types.d.ts +327 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/utf8-session.d.ts +17 -0
- package/dist/cjs/utf8-session.js +148 -0
- package/dist/cjs/vanished.d.ts +21 -0
- package/dist/cjs/vanished.js +55 -0
- package/dist/esm/addressparser.d.ts +21 -0
- package/{lib → dist/esm}/addressparser.js +102 -123
- package/dist/esm/arguments.d.ts +31 -0
- package/dist/esm/arguments.js +96 -0
- package/dist/esm/bodystructure.d.ts +25 -0
- package/{lib → dist/esm}/bodystructure.js +17 -33
- package/dist/esm/cert.d.ts +2 -0
- package/dist/esm/cert.js +4 -0
- package/dist/esm/command-states.d.ts +36 -0
- package/{lib → dist/esm}/command-states.js +4 -16
- package/dist/esm/commands/append.d.ts +88 -0
- package/{lib → dist/esm}/commands/append.js +47 -85
- package/dist/esm/commands/capability.d.ts +2 -0
- package/dist/esm/commands/capability.js +29 -0
- package/dist/esm/commands/check.d.ts +2 -0
- package/dist/esm/commands/check.js +13 -0
- package/dist/esm/commands/close.d.ts +2 -0
- package/dist/esm/commands/close.js +20 -0
- package/dist/esm/commands/copy.d.ts +30 -0
- package/{lib → dist/esm}/commands/copy.js +31 -55
- package/dist/esm/commands/create.d.ts +2 -0
- package/{lib → dist/esm}/commands/create.js +25 -39
- package/dist/esm/commands/delete.d.ts +2 -0
- package/{lib → dist/esm}/commands/delete.js +25 -41
- package/dist/esm/commands/examine.d.ts +2 -0
- package/dist/esm/commands/examine.js +4 -0
- package/dist/esm/commands/expunge.d.ts +2 -0
- package/dist/esm/commands/expunge.js +17 -0
- package/dist/esm/commands/fetch.d.ts +23 -0
- package/{lib → dist/esm}/commands/fetch.js +34 -75
- package/dist/esm/commands/handlers/fetch.d.ts +12 -0
- package/{lib → dist/esm}/commands/handlers/fetch.js +11 -42
- package/dist/esm/commands/handlers/flags.d.ts +17 -0
- package/{lib → dist/esm}/commands/handlers/flags.js +3 -11
- package/dist/esm/commands/handlers/search.d.ts +85 -0
- package/{lib → dist/esm}/commands/handlers/search.js +33 -71
- package/dist/esm/commands/handlers/status.d.ts +34 -0
- package/{lib → dist/esm}/commands/handlers/status.js +1 -9
- package/dist/esm/commands/handlers/store.d.ts +3 -0
- package/{lib → dist/esm}/commands/handlers/store.js +20 -44
- package/dist/esm/commands/index.d.ts +2 -0
- package/dist/esm/commands/index.js +55 -0
- package/dist/esm/commands/list.d.ts +2 -0
- package/dist/esm/commands/list.js +71 -0
- package/dist/esm/commands/login.d.ts +2 -0
- package/{lib → dist/esm}/commands/login.js +24 -44
- package/dist/esm/commands/logout.d.ts +2 -0
- package/dist/esm/commands/logout.js +25 -0
- package/dist/esm/commands/lsub.d.ts +2 -0
- package/dist/esm/commands/lsub.js +64 -0
- package/dist/esm/commands/noop.d.ts +2 -0
- package/dist/esm/commands/noop.js +13 -0
- package/dist/esm/commands/rename.d.ts +2 -0
- package/{lib → dist/esm}/commands/rename.js +32 -51
- package/dist/esm/commands/search.d.ts +10 -0
- package/dist/esm/commands/search.js +54 -0
- package/dist/esm/commands/select.d.ts +19 -0
- package/dist/esm/commands/select.js +214 -0
- package/dist/esm/commands/status.d.ts +2 -0
- package/{lib → dist/esm}/commands/status.js +18 -39
- package/dist/esm/commands/store.d.ts +10 -0
- package/{lib → dist/esm}/commands/store.js +39 -73
- package/dist/esm/commands/subscribe.d.ts +2 -0
- package/{lib → dist/esm}/commands/subscribe.js +22 -39
- package/dist/esm/commands/uid-copy.d.ts +2 -0
- package/dist/esm/commands/uid-copy.js +4 -0
- package/dist/esm/commands/uid-fetch.d.ts +3 -0
- package/dist/esm/commands/uid-fetch.js +3 -0
- package/dist/esm/commands/uid-search.d.ts +3 -0
- package/dist/esm/commands/uid-search.js +3 -0
- package/dist/esm/commands/uid-store.d.ts +3 -0
- package/dist/esm/commands/uid-store.js +3 -0
- package/dist/esm/commands/unsubscribe.d.ts +2 -0
- package/{lib → dist/esm}/commands/unsubscribe.js +22 -37
- package/dist/esm/dates.d.ts +64 -0
- package/{lib → dist/esm}/dates.js +6 -14
- package/dist/esm/deflate-layer.d.ts +83 -0
- package/{lib → dist/esm}/deflate-layer.js +9 -26
- package/dist/esm/encoded-words.d.ts +15 -0
- package/{lib → dist/esm}/encoded-words.js +9 -25
- package/dist/esm/envelope.d.ts +33 -0
- package/{lib → dist/esm}/envelope.js +8 -19
- package/dist/esm/esearch.d.ts +96 -0
- package/{lib → dist/esm}/esearch.js +12 -39
- package/dist/esm/framing.d.ts +66 -0
- package/dist/esm/framing.js +82 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/list-extensions.d.ts +50 -0
- package/{lib → dist/esm}/list-extensions.js +1 -4
- package/dist/esm/load-plugins.d.ts +21 -0
- package/{lib → dist/esm}/load-plugins.js +9 -43
- package/dist/esm/mailbox-name.d.ts +26 -0
- package/{lib → dist/esm}/mailbox-name.js +5 -26
- package/dist/esm/mimeparser.d.ts +137 -0
- package/{lib → dist/esm}/mimeparser.js +74 -152
- package/dist/esm/mock-client.d.ts +39 -0
- package/{lib → dist/esm}/mock-client.js +26 -40
- package/dist/esm/numbers.d.ts +28 -0
- package/{lib → dist/esm}/numbers.js +1 -8
- package/dist/esm/package.json +3 -0
- package/dist/esm/plugins/acl.d.ts +2 -0
- package/{lib → dist/esm}/plugins/acl.js +146 -240
- package/dist/esm/plugins/appendlimit.d.ts +16 -0
- package/{lib → dist/esm}/plugins/appendlimit.js +5 -16
- package/dist/esm/plugins/auth-plain.d.ts +2 -0
- package/{lib → dist/esm}/plugins/auth-plain.js +11 -31
- package/dist/esm/plugins/binary.d.ts +30 -0
- package/{lib → dist/esm}/plugins/binary.js +17 -43
- package/dist/esm/plugins/catenate.d.ts +14 -0
- package/{lib → dist/esm}/plugins/catenate.js +19 -40
- package/dist/esm/plugins/compress.d.ts +7 -0
- package/dist/esm/plugins/compress.js +61 -0
- package/dist/esm/plugins/condstore.d.ts +5 -0
- package/{lib → dist/esm}/plugins/condstore.js +66 -152
- package/dist/esm/plugins/context-search.d.ts +8 -0
- package/{lib → dist/esm}/plugins/context-search.js +53 -88
- package/dist/esm/plugins/context-sort.d.ts +6 -0
- package/{lib → dist/esm}/plugins/context-sort.js +4 -9
- package/dist/esm/plugins/create-special-use.d.ts +7 -0
- package/{lib → dist/esm}/plugins/create-special-use.js +33 -55
- package/dist/esm/plugins/enable.d.ts +23 -0
- package/dist/esm/plugins/enable.js +111 -0
- package/dist/esm/plugins/esearch.d.ts +6 -0
- package/{lib → dist/esm}/plugins/esearch.js +13 -42
- package/dist/esm/plugins/esort.d.ts +6 -0
- package/{lib → dist/esm}/plugins/esort.js +7 -25
- package/dist/esm/plugins/id.d.ts +5 -0
- package/dist/esm/plugins/id.js +108 -0
- package/dist/esm/plugins/idle.d.ts +5 -0
- package/dist/esm/plugins/idle.js +70 -0
- package/dist/esm/plugins/imap4rev2.d.ts +6 -0
- package/{lib → dist/esm}/plugins/imap4rev2.js +24 -60
- package/dist/esm/plugins/index.d.ts +2 -0
- package/dist/esm/plugins/index.js +113 -0
- package/dist/esm/plugins/list-extended.d.ts +2 -0
- package/{lib → dist/esm}/plugins/list-extended.js +28 -66
- package/dist/esm/plugins/list-status.d.ts +6 -0
- package/{lib → dist/esm}/plugins/list-status.js +5 -12
- package/dist/esm/plugins/literalminus.d.ts +8 -0
- package/{lib → dist/esm}/plugins/literalminus.js +2 -5
- package/dist/esm/plugins/literalplus.d.ts +6 -0
- package/{lib → dist/esm}/plugins/literalplus.js +2 -5
- package/dist/esm/plugins/logindisabled.d.ts +5 -0
- package/dist/esm/plugins/logindisabled.js +39 -0
- package/dist/esm/plugins/messagelimit.d.ts +19 -0
- package/{lib → dist/esm}/plugins/messagelimit.js +18 -41
- package/dist/esm/plugins/metadata-server.d.ts +7 -0
- package/{lib → dist/esm}/plugins/metadata-server.js +3 -7
- package/dist/esm/plugins/metadata.d.ts +11 -0
- package/dist/esm/plugins/metadata.js +421 -0
- package/dist/esm/plugins/move.d.ts +11 -0
- package/{lib → dist/esm}/plugins/move.js +37 -66
- package/dist/esm/plugins/multiappend.d.ts +12 -0
- package/{lib → dist/esm}/plugins/multiappend.js +2 -5
- package/dist/esm/plugins/multisearch.d.ts +6 -0
- package/{lib → dist/esm}/plugins/multisearch.js +24 -48
- package/dist/esm/plugins/namespace.d.ts +5 -0
- package/dist/esm/plugins/namespace.js +42 -0
- package/dist/esm/plugins/notify.d.ts +2 -0
- package/{lib → dist/esm}/plugins/notify.js +90 -134
- package/dist/esm/plugins/oauthbearer.d.ts +32 -0
- package/{lib → dist/esm}/plugins/oauthbearer.js +18 -48
- package/dist/esm/plugins/objectid.d.ts +23 -0
- package/{lib → dist/esm}/plugins/objectid.js +21 -58
- package/dist/esm/plugins/partial.d.ts +6 -0
- package/{lib → dist/esm}/plugins/partial.js +7 -15
- package/dist/esm/plugins/preview.d.ts +31 -0
- package/{lib → dist/esm}/plugins/preview.js +28 -66
- package/dist/esm/plugins/qresync.d.ts +11 -0
- package/{lib → dist/esm}/plugins/qresync.js +64 -134
- package/dist/esm/plugins/quota.d.ts +18 -0
- package/{lib → dist/esm}/plugins/quota.js +89 -135
- package/dist/esm/plugins/replace.d.ts +14 -0
- package/{lib → dist/esm}/plugins/replace.js +21 -51
- package/dist/esm/plugins/sasl-ir.d.ts +5 -0
- package/{lib → dist/esm}/plugins/sasl-ir.js +3 -6
- package/dist/esm/plugins/savedate.d.ts +17 -0
- package/{lib → dist/esm}/plugins/savedate.js +5 -15
- package/dist/esm/plugins/savelimit.d.ts +10 -0
- package/{lib → dist/esm}/plugins/savelimit.js +3 -6
- package/dist/esm/plugins/searchres.d.ts +6 -0
- package/{lib → dist/esm}/plugins/searchres.js +13 -22
- package/dist/esm/plugins/sort-display.d.ts +11 -0
- package/{lib → dist/esm}/plugins/sort-display.js +6 -10
- package/dist/esm/plugins/sort.d.ts +11 -0
- package/{lib → dist/esm}/plugins/sort.js +24 -46
- package/dist/esm/plugins/special-use.d.ts +10 -0
- package/{lib → dist/esm}/plugins/special-use.js +9 -24
- package/dist/esm/plugins/starttls.d.ts +5 -0
- package/{lib → dist/esm}/plugins/starttls.js +20 -37
- package/dist/esm/plugins/status-size.d.ts +7 -0
- package/{lib → dist/esm}/plugins/status-size.js +4 -11
- package/dist/esm/plugins/thread-orderedsubject.d.ts +11 -0
- package/{lib → dist/esm}/plugins/thread-orderedsubject.js +3 -6
- package/dist/esm/plugins/thread-references.d.ts +11 -0
- package/{lib → dist/esm}/plugins/thread-references.js +3 -6
- package/dist/esm/plugins/uidonly.d.ts +15 -0
- package/{lib → dist/esm}/plugins/uidonly.js +11 -35
- package/dist/esm/plugins/uidplus.d.ts +15 -0
- package/{lib → dist/esm}/plugins/uidplus.js +25 -45
- package/dist/esm/plugins/unauthenticate.d.ts +7 -0
- package/dist/esm/plugins/unauthenticate.js +17 -0
- package/dist/esm/plugins/unselect.d.ts +5 -0
- package/dist/esm/plugins/unselect.js +21 -0
- package/dist/esm/plugins/utf8-accept.d.ts +6 -0
- package/{lib → dist/esm}/plugins/utf8-accept.js +10 -21
- package/dist/esm/plugins/x-gm-ext-1.d.ts +26 -0
- package/{lib → dist/esm}/plugins/x-gm-ext-1.js +48 -100
- package/dist/esm/plugins/xoauth2.d.ts +2 -0
- package/dist/esm/plugins/xoauth2.js +140 -0
- package/dist/esm/plugins/xtoybird.d.ts +2 -0
- package/dist/esm/plugins/xtoybird.js +218 -0
- package/dist/esm/server.d.ts +876 -0
- package/dist/esm/server.js +2543 -0
- package/dist/esm/smtp-listener.d.ts +13 -0
- package/{lib → dist/esm}/smtp-listener.js +5 -12
- package/dist/esm/sorting.d.ts +77 -0
- package/{lib → dist/esm}/sorting.js +40 -53
- package/dist/esm/threading.d.ts +30 -0
- package/{lib → dist/esm}/threading.js +29 -70
- package/dist/esm/types.d.ts +327 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/utf8-session.d.ts +17 -0
- package/{lib → dist/esm}/utf8-session.js +15 -25
- package/dist/esm/vanished.d.ts +21 -0
- package/{lib → dist/esm}/vanished.js +16 -21
- package/dist/plugin-help.json +298 -0
- package/package.json +54 -11
- package/lib/commands/capability.js +0 -47
- package/lib/commands/check.js +0 -21
- package/lib/commands/close.js +0 -30
- package/lib/commands/examine.js +0 -7
- package/lib/commands/expunge.js +0 -27
- package/lib/commands/list.js +0 -100
- package/lib/commands/logout.js +0 -41
- package/lib/commands/lsub.js +0 -87
- package/lib/commands/noop.js +0 -21
- package/lib/commands/search.js +0 -76
- package/lib/commands/select.js +0 -289
- package/lib/commands/uid copy.js +0 -7
- package/lib/commands/uid fetch.js +0 -5
- package/lib/commands/uid search.js +0 -5
- package/lib/commands/uid store.js +0 -5
- package/lib/plugins/compress.js +0 -76
- package/lib/plugins/enable.js +0 -155
- package/lib/plugins/id.js +0 -138
- package/lib/plugins/idle.js +0 -105
- package/lib/plugins/logindisabled.js +0 -50
- package/lib/plugins/metadata.js +0 -475
- package/lib/plugins/namespace.js +0 -67
- package/lib/plugins/unauthenticate.js +0 -28
- package/lib/plugins/unselect.js +0 -36
- package/lib/plugins/xoauth2.js +0 -188
- package/lib/plugins/xtoybird.js +0 -282
- package/lib/server.js +0 -2880
|
@@ -1,38 +1,29 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @help Adds ESEARCH [RFC4731] capability
|
|
5
3
|
* @help SEARCH and UID SEARCH take the RETURN (MIN MAX ALL COUNT) result options and answer with ESEARCH
|
|
6
4
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const { badError } = require('../commands/handlers/search');
|
|
10
|
-
|
|
5
|
+
import { buildEsearchResponse, selectReturned } from '../esearch.js';
|
|
6
|
+
import { badError } from '../commands/handlers/search.js';
|
|
11
7
|
// RFC 4466 section 2.6.1: search = "SEARCH" [SP "RETURN" SP "(" [search-return-opt *(SP search-return-opt)] ")"] SP search-program
|
|
12
|
-
const hasReturnOptions = attributes => {
|
|
8
|
+
const hasReturnOptions = (attributes) => {
|
|
13
9
|
const first = attributes && attributes[0];
|
|
14
10
|
return !!first && first.type === 'ATOM' && String(first.value).toUpperCase() === 'RETURN';
|
|
15
11
|
};
|
|
16
|
-
|
|
17
|
-
module.exports = function (server) {
|
|
12
|
+
export default function esearchPlugin(server) {
|
|
18
13
|
// SEARCHRES loads ESEARCH as well, so the plugin may be called twice
|
|
19
14
|
if (server.searchReturnOptions) {
|
|
20
15
|
return;
|
|
21
16
|
}
|
|
22
|
-
|
|
23
17
|
server.registerCapability('ESEARCH');
|
|
24
|
-
|
|
25
18
|
// RFC 4731 section 3.1 result options. Other plugins add their own: `data: false` for an option that
|
|
26
19
|
// does not add data to the ESEARCH response (SAVE of SEARCHRES), `response: true` if the ESEARCH
|
|
27
20
|
// response is sent even then (UPDATE of CONTEXT=SEARCH), `hint: true` for an option that is accepted
|
|
28
21
|
// and ignored (CONTEXT), `parse(item)` for an option with an argument and `once: true` if the option
|
|
29
22
|
// must not be repeated
|
|
30
23
|
server.searchReturnOptions = new Map(['MIN', 'MAX', 'ALL', 'COUNT'].map(name => [name, { data: true }]));
|
|
31
|
-
|
|
32
24
|
// Checks of the whole list of result options, `(options, connection, parsed, names)` returns an error message
|
|
33
25
|
// for an invalid combination. `names` also holds the hint options
|
|
34
26
|
server.searchReturnChecks = [];
|
|
35
|
-
|
|
36
27
|
/**
|
|
37
28
|
* Parses a list of result options (RFC 4466 section 2.6.1: search-return-opts)
|
|
38
29
|
*
|
|
@@ -46,7 +37,6 @@ module.exports = function (server) {
|
|
|
46
37
|
if (!Array.isArray(list)) {
|
|
47
38
|
throw badError('RETURN expects a parenthesized list of result options');
|
|
48
39
|
}
|
|
49
|
-
|
|
50
40
|
const options = new Map();
|
|
51
41
|
// every option name, also the hints that are left out of `options`
|
|
52
42
|
const names = new Set();
|
|
@@ -67,7 +57,6 @@ module.exports = function (server) {
|
|
|
67
57
|
options.set(name, value);
|
|
68
58
|
}
|
|
69
59
|
}
|
|
70
|
-
|
|
71
60
|
for (const check of server.searchReturnChecks) {
|
|
72
61
|
const error = check(options, connection, parsed, names);
|
|
73
62
|
if (error) {
|
|
@@ -76,44 +65,37 @@ module.exports = function (server) {
|
|
|
76
65
|
}
|
|
77
66
|
return options;
|
|
78
67
|
};
|
|
79
|
-
|
|
80
68
|
// only result options without return data, like SAVE (RFC 5182 section 1), suppress the ESEARCH response
|
|
81
|
-
server.isSilentReturn = options =>
|
|
82
|
-
options.size > 0 &&
|
|
69
|
+
server.isSilentReturn = (options) => options.size > 0 &&
|
|
83
70
|
![...options.keys()].some(name => {
|
|
84
71
|
const spec = server.searchReturnOptions.get(name);
|
|
85
72
|
return spec.data || spec.response;
|
|
86
73
|
});
|
|
87
|
-
|
|
88
74
|
// The result options are taken off the arguments, so the SEARCH handler only sees the search program
|
|
89
75
|
const searchWrapper = (prevHandler, connection, parsed, data, callback) => {
|
|
90
76
|
if (!hasReturnOptions(parsed.attributes)) {
|
|
91
77
|
return prevHandler(connection, parsed, data, callback);
|
|
92
78
|
}
|
|
93
|
-
|
|
94
79
|
try {
|
|
95
80
|
parsed.searchReturn = server.parseSearchReturn(parsed.attributes[1], connection, parsed);
|
|
96
|
-
}
|
|
81
|
+
}
|
|
82
|
+
catch (E) {
|
|
97
83
|
connection.sendStatus(parsed, data, 'BAD', E.message, false, (parsed.command || '').toUpperCase() + ' FAILED');
|
|
98
84
|
return callback();
|
|
99
85
|
}
|
|
100
|
-
|
|
101
86
|
parsed.attributes = parsed.attributes.slice(2);
|
|
102
87
|
prevHandler(connection, parsed, data, callback);
|
|
103
88
|
};
|
|
104
|
-
|
|
105
89
|
// Lets a command take result options before its other arguments, parsed into `parsed.searchReturn`.
|
|
106
90
|
// ESORT uses it for SORT and UID SORT (RFC 5267 section 3)
|
|
107
|
-
server.acceptSearchReturn = command => {
|
|
91
|
+
server.acceptSearchReturn = (command) => {
|
|
108
92
|
const prevHandler = server.getCommandHandler(command);
|
|
109
93
|
server.setCommandHandler(command, (connection, parsed, data, callback) => searchWrapper(prevHandler, connection, parsed, data, callback));
|
|
110
94
|
};
|
|
111
|
-
|
|
112
95
|
server.acceptSearchReturn('SEARCH');
|
|
113
96
|
server.acceptSearchReturn('UID SEARCH');
|
|
114
|
-
|
|
115
97
|
// RFC 3501 section 5.5: only the search program can hold sequence numbers, the result options do not
|
|
116
|
-
server.connectionHandlers.push(connection => {
|
|
98
|
+
server.connectionHandlers.push((connection) => {
|
|
117
99
|
const usesSequenceNumbers = connection.usesSequenceNumbers;
|
|
118
100
|
connection.usesSequenceNumbers = function (parsed) {
|
|
119
101
|
if (hasReturnOptions(parsed.attributes)) {
|
|
@@ -122,35 +104,24 @@ module.exports = function (server) {
|
|
|
122
104
|
return usesSequenceNumbers.call(this, parsed);
|
|
123
105
|
};
|
|
124
106
|
});
|
|
125
|
-
|
|
126
107
|
// Replaces the SEARCH response of an extended SEARCH with a single ESEARCH response (RFC 4731 section 3.1)
|
|
127
108
|
server.outputHandlers.push((connection, response, description, parsed, data, extra) => {
|
|
128
|
-
if (
|
|
129
|
-
!parsed ||
|
|
109
|
+
if (!parsed ||
|
|
130
110
|
!parsed.searchReturn ||
|
|
131
111
|
response.tag !== '*' ||
|
|
132
112
|
response.command !== 'SEARCH' ||
|
|
133
113
|
(description !== 'SEARCH' && description !== 'UID SEARCH') ||
|
|
134
114
|
!extra ||
|
|
135
|
-
!Array.isArray(extra.list)
|
|
136
|
-
) {
|
|
115
|
+
!Array.isArray(extra.list)) {
|
|
137
116
|
return;
|
|
138
117
|
}
|
|
139
118
|
response.skipResponse = true;
|
|
140
|
-
|
|
141
119
|
const options = parsed.searchReturn;
|
|
142
120
|
if (server.isSilentReturn(options)) {
|
|
143
121
|
return;
|
|
144
122
|
}
|
|
145
|
-
|
|
146
123
|
// like for SEARCH, the extra data is the search result, but `list` only holds the messages that the
|
|
147
124
|
// result options return (RFC 4731 section 3.2), for the MODSEQ of CONDSTORE
|
|
148
|
-
connection.send(
|
|
149
|
-
buildEsearchResponse(parsed.tag, description === 'UID SEARCH', extra, options),
|
|
150
|
-
'ESEARCH',
|
|
151
|
-
parsed,
|
|
152
|
-
data,
|
|
153
|
-
Object.assign({}, extra, { list: selectReturned(extra.list, options) })
|
|
154
|
-
);
|
|
125
|
+
connection.send(buildEsearchResponse(parsed.tag, description === 'UID SEARCH', extra, options), 'ESEARCH', parsed, data, Object.assign({}, extra, { list: selectReturned(extra.list, options) }));
|
|
155
126
|
});
|
|
156
|
-
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @help Adds ESORT [RFC5267] capability, loads SORT and ESEARCH as well
|
|
3
|
+
* @help SORT and UID SORT take the RETURN (MIN MAX ALL COUNT) result options and answer with ESEARCH, results are in sort order
|
|
4
|
+
*/
|
|
5
|
+
import type { IMAPServer } from '../types.js';
|
|
6
|
+
export default function esortPlugin(server: IMAPServer): void;
|
|
@@ -1,31 +1,22 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @help Adds ESORT [RFC5267] capability, loads SORT and ESEARCH as well
|
|
5
3
|
* @help SORT and UID SORT take the RETURN (MIN MAX ALL COUNT) result options and answer with ESEARCH, results are in sort order
|
|
6
4
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const isSort = command => command === 'SORT' || command === 'UID SORT';
|
|
13
|
-
|
|
14
|
-
module.exports = function (server) {
|
|
5
|
+
import sort from './sort.js';
|
|
6
|
+
import esearch from './esearch.js';
|
|
7
|
+
import { buildEsearchResponse, selectReturned } from '../esearch.js';
|
|
8
|
+
const isSort = (command) => command === 'SORT' || command === 'UID SORT';
|
|
9
|
+
export default function esortPlugin(server) {
|
|
15
10
|
if (server.esortLoaded) {
|
|
16
11
|
return;
|
|
17
12
|
}
|
|
18
13
|
server.esortLoaded = true;
|
|
19
|
-
|
|
20
14
|
sort(server);
|
|
21
15
|
esearch(server);
|
|
22
|
-
|
|
23
16
|
server.registerCapability('ESORT');
|
|
24
|
-
|
|
25
17
|
// RFC 5267 section 3: extended-sort = ["UID" SP] "SORT" search-return-opts SP sort-criteria SP search-criteria
|
|
26
18
|
server.acceptSearchReturn('SORT');
|
|
27
19
|
server.acceptSearchReturn('UID SORT');
|
|
28
|
-
|
|
29
20
|
// RFC 5267 section 4.1: the CONTEXT, UPDATE and PARTIAL result options of SORT come with CONTEXT=SORT. PARTIAL
|
|
30
21
|
// is also defined for the PARTIAL capability (RFC 9394 section 3.1)
|
|
31
22
|
server.searchReturnChecks.push((options, connection, parsed, names) => {
|
|
@@ -35,26 +26,17 @@ module.exports = function (server) {
|
|
|
35
26
|
const name = ['CONTEXT', 'UPDATE', 'PARTIAL'].find(key => names.has(key) && (key !== 'PARTIAL' || !server.partialRangeLast));
|
|
36
27
|
return !!name && name + ' is not supported for SORT';
|
|
37
28
|
});
|
|
38
|
-
|
|
39
29
|
// Replaces the SORT response of an extended SORT with an ESEARCH response (RFC 5267 section 3)
|
|
40
30
|
server.outputHandlers.push((connection, response, description, parsed, data, extra) => {
|
|
41
31
|
if (!parsed || !parsed.searchReturn || response.tag !== '*' || response.command !== 'SORT' || !isSort(description) || !extra || !extra.sorted) {
|
|
42
32
|
return;
|
|
43
33
|
}
|
|
44
34
|
response.skipResponse = true;
|
|
45
|
-
|
|
46
35
|
const options = parsed.searchReturn;
|
|
47
36
|
if (server.isSilentReturn(options)) {
|
|
48
37
|
return;
|
|
49
38
|
}
|
|
50
|
-
|
|
51
39
|
// the extra data lists the returned messages, for the MODSEQ of CONDSTORE (RFC 7162 section 3.1.10)
|
|
52
|
-
connection.send(
|
|
53
|
-
buildEsearchResponse(parsed.tag, description === 'UID SORT', extra, options, null, extra.sorted),
|
|
54
|
-
'ESEARCH',
|
|
55
|
-
parsed,
|
|
56
|
-
data,
|
|
57
|
-
Object.assign({}, extra, { list: selectReturned(extra.sorted, options) })
|
|
58
|
-
);
|
|
40
|
+
connection.send(buildEsearchResponse(parsed.tag, description === 'UID SORT', extra, options, null, extra.sorted), 'ESEARCH', parsed, data, Object.assign({}, extra, { list: selectReturned(extra.sorted, options) }));
|
|
59
41
|
});
|
|
60
|
-
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { states } from '../command-states.js';
|
|
2
|
+
/**
|
|
3
|
+
* @help Adds ID [RFC2971] capability
|
|
4
|
+
*/
|
|
5
|
+
export default function idPlugin(server) {
|
|
6
|
+
// Register capability, always usable
|
|
7
|
+
server.registerCapability('ID');
|
|
8
|
+
// Add ID command
|
|
9
|
+
server.setCommandHandler('ID', (connection, parsed, data, callback) => {
|
|
10
|
+
// keys are client supplied, so the object has no prototype
|
|
11
|
+
const clientList = Object.create(null);
|
|
12
|
+
let serverList = null;
|
|
13
|
+
let i;
|
|
14
|
+
let len;
|
|
15
|
+
let key = '';
|
|
16
|
+
// Require exactly 1 attribute (NIL or parameter list)
|
|
17
|
+
if (!parsed.attributes || parsed.attributes.length !== 1) {
|
|
18
|
+
return sendError('ID expects 1 attribute', connection, parsed, data, callback);
|
|
19
|
+
}
|
|
20
|
+
const list = parsed.attributes[0];
|
|
21
|
+
if ((list && !Array.isArray(list)) || (list && list.length % 2)) {
|
|
22
|
+
return sendError('ID expects valid parameter list', connection, parsed, data, callback);
|
|
23
|
+
}
|
|
24
|
+
// RFC 2971 section 3.3: at most 30 field-value pairs
|
|
25
|
+
if (list && list.length > 60) {
|
|
26
|
+
return sendError('ID allows at most 30 field-value pairs', connection, parsed, data, callback);
|
|
27
|
+
}
|
|
28
|
+
// Build client ID object and check validity of the values
|
|
29
|
+
if (list && list.length) {
|
|
30
|
+
for (i = 0, len = list.length; i < len; i++) {
|
|
31
|
+
if (i % 2 === 0) {
|
|
32
|
+
// Handle keys (always strings)
|
|
33
|
+
if (list[i] && ['STRING', 'LITERAL'].indexOf(list[i].type) >= 0) {
|
|
34
|
+
key = list[i].value;
|
|
35
|
+
// RFC 2971 section 3.3: field names are at most 30 octets, case-insensitive and unique
|
|
36
|
+
if (key.length > 30) {
|
|
37
|
+
return sendError('ID field names can be at most 30 octets', connection, parsed, data, callback);
|
|
38
|
+
}
|
|
39
|
+
if (Object.keys(clientList).some(existing => existing.toLowerCase() === key.toLowerCase())) {
|
|
40
|
+
return sendError('ID field names must not repeat', connection, parsed, data, callback);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return sendError('ID expects valid parameter list', connection, parsed, data, callback);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// Handle values (string or NIL)
|
|
49
|
+
if (!list[i] || ['STRING', 'LITERAL'].indexOf(list[i].type) >= 0) {
|
|
50
|
+
if (list[i] && list[i].value.length > 1024) {
|
|
51
|
+
return sendError('ID values can be at most 1024 octets', connection, parsed, data, callback);
|
|
52
|
+
}
|
|
53
|
+
clientList[key] = (list[i] && list[i].value) || null;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return sendError('ID expects valid parameter list', connection, parsed, data, callback);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Build response object from server options
|
|
62
|
+
if (server.options.id) {
|
|
63
|
+
const ids = [];
|
|
64
|
+
serverList = ids;
|
|
65
|
+
Object.keys(server.options.id).forEach(key => {
|
|
66
|
+
ids.push({
|
|
67
|
+
type: 'STRING',
|
|
68
|
+
value: key
|
|
69
|
+
});
|
|
70
|
+
ids.push({
|
|
71
|
+
type: 'STRING',
|
|
72
|
+
value: (server.options.id[key] || '').toString()
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
// Send untagged ID response
|
|
77
|
+
connection.send({
|
|
78
|
+
tag: '*',
|
|
79
|
+
command: 'ID',
|
|
80
|
+
attributes: [serverList]
|
|
81
|
+
}, 'ID', parsed, data, clientList);
|
|
82
|
+
// Send tagged response
|
|
83
|
+
connection.send({
|
|
84
|
+
tag: parsed.tag,
|
|
85
|
+
command: 'OK',
|
|
86
|
+
attributes: [
|
|
87
|
+
{
|
|
88
|
+
type: 'TEXT',
|
|
89
|
+
value: 'ID command completed'
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}, 'ID', parsed, data, clientList);
|
|
93
|
+
callback();
|
|
94
|
+
}, { states: states.ANY });
|
|
95
|
+
}
|
|
96
|
+
function sendError(message, connection, parsed, data, callback) {
|
|
97
|
+
connection.send({
|
|
98
|
+
tag: parsed.tag,
|
|
99
|
+
command: 'BAD',
|
|
100
|
+
attributes: [
|
|
101
|
+
{
|
|
102
|
+
type: 'TEXT',
|
|
103
|
+
value: message
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}, 'INVALID COMMAND', parsed, data);
|
|
107
|
+
return callback();
|
|
108
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { states } from '../command-states.js';
|
|
2
|
+
/**
|
|
3
|
+
* @help Adds IDLE [RFC2177] capability
|
|
4
|
+
*/
|
|
5
|
+
export default function idlePlugin(server) {
|
|
6
|
+
server.registerCapability('IDLE');
|
|
7
|
+
server.setCommandHandler('IDLE', (connection, parsed, data, callback) => {
|
|
8
|
+
const idleTimer = setTimeout(() => {
|
|
9
|
+
if (connection.socket && !connection.socket.destroyed) {
|
|
10
|
+
connection.send({
|
|
11
|
+
tag: '*',
|
|
12
|
+
command: 'BYE',
|
|
13
|
+
attributes: [
|
|
14
|
+
{
|
|
15
|
+
type: 'TEXT',
|
|
16
|
+
value: 'IDLE terminated'
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}, 'IDLE EXPIRED', parsed, data);
|
|
20
|
+
connection.end();
|
|
21
|
+
}
|
|
22
|
+
}, 30 * 60 * 1000);
|
|
23
|
+
// An idling client should not keep the process alive
|
|
24
|
+
idleTimer.unref();
|
|
25
|
+
const clearIdleTimer = () => clearTimeout(idleTimer);
|
|
26
|
+
const socket = connection.socket;
|
|
27
|
+
if (socket) {
|
|
28
|
+
socket.once('close', clearIdleTimer);
|
|
29
|
+
}
|
|
30
|
+
connection.directNotifications = true;
|
|
31
|
+
// Temporarily redirect client input to this function
|
|
32
|
+
connection.inputHandler = function (str) {
|
|
33
|
+
clearIdleTimer();
|
|
34
|
+
if (socket) {
|
|
35
|
+
socket.removeListener('close', clearIdleTimer);
|
|
36
|
+
}
|
|
37
|
+
// Stop listening to any other user input
|
|
38
|
+
connection.inputHandler = false;
|
|
39
|
+
// Notifications are sent again only while a command is in progress
|
|
40
|
+
connection.directNotifications = false;
|
|
41
|
+
if (str.toUpperCase() === 'DONE') {
|
|
42
|
+
connection.send({
|
|
43
|
+
tag: parsed.tag,
|
|
44
|
+
command: 'OK',
|
|
45
|
+
attributes: [
|
|
46
|
+
{
|
|
47
|
+
type: 'TEXT',
|
|
48
|
+
value: 'IDLE terminated'
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}, 'IDLE', parsed, data);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
connection.send({
|
|
55
|
+
tag: parsed.tag,
|
|
56
|
+
command: 'BAD',
|
|
57
|
+
attributes: [
|
|
58
|
+
{
|
|
59
|
+
type: 'TEXT',
|
|
60
|
+
value: 'Invalid Idle continuation'
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}, 'INVALID IDLE', parsed, data);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
connection.write('+ idling\r\n');
|
|
67
|
+
connection.processNotifications();
|
|
68
|
+
return callback();
|
|
69
|
+
}, { states: states.AUTHENTICATED, noArguments: true });
|
|
70
|
+
}
|
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const literalMinus = require('./literalminus');
|
|
5
|
-
const { registerEnable, isEnabled } = require('./enable');
|
|
6
|
-
|
|
1
|
+
import { updateSession } from '../utf8-session.js';
|
|
2
|
+
import literalMinus from './literalminus.js';
|
|
3
|
+
import { registerEnable, isEnabled } from './enable.js';
|
|
7
4
|
/**
|
|
8
5
|
* @help Adds IMAP4rev2 [RFC9051] capability next to IMAP4rev1 and loads
|
|
9
6
|
* @help the extensions folded into IMAP4rev2 (RFC 9051 Appendix E).
|
|
10
7
|
* @help A session follows RFC 9051 after ENABLE IMAP4rev2, others RFC 3501
|
|
11
8
|
*/
|
|
12
|
-
|
|
13
9
|
// RFC 9051 Appendix A: a client that wants IMAP4rev2 when both revisions are advertised MUST issue "ENABLE IMAP4rev2".
|
|
14
10
|
// The ENABLE plugin lists enabled extensions in this spelling
|
|
15
11
|
const REV2 = 'IMAP4rev2';
|
|
16
|
-
|
|
17
12
|
// RFC 9051 section 9 leaves these IMAP4rev1 items out of the search-key, status-att and fetch-att rules (Appendix E
|
|
18
13
|
// items 12 and 18), so an IMAP4rev2 session gets BAD for them
|
|
19
14
|
const REMOVED_SEARCH_KEYS = new Set(['NEW', 'OLD', 'RECENT', 'UNRECENT']);
|
|
@@ -21,38 +16,30 @@ const REMOVED_STATUS_ITEMS = new Set(['RECENT']);
|
|
|
21
16
|
// RFC 9051 section 6.3.11 and Appendix E item 3: STATUS DELETED is new in IMAP4rev2 (STATUS SIZE comes with STATUS=SIZE)
|
|
22
17
|
const ADDED_STATUS_ITEMS = new Set(['DELETED']);
|
|
23
18
|
const REMOVED_FETCH_ITEMS = new Set(['RFC822', 'RFC822.HEADER', 'RFC822.TEXT']);
|
|
24
|
-
|
|
25
19
|
// RFC 9051 section 2.3.2: keywords that SHOULD be allowed in SEARCH and preserved in APPEND, COPY and MOVE
|
|
26
20
|
const KEYWORDS = ['$Forwarded', '$MDNSent', '$Junk', '$NotJunk', '$Phishing'];
|
|
27
|
-
|
|
28
21
|
// set by setMode() below
|
|
29
|
-
const isRev2 = connection => !!connection.imap4rev2;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
module.exports = function (server) {
|
|
34
|
-
// RFC 9051 Appendix A: advertised together with IMAP4rev1 (capability.js always lists it), so every session
|
|
22
|
+
const isRev2 = (connection) => !!connection.imap4rev2;
|
|
23
|
+
const atomName = (attr) => (attr && attr.type === 'ATOM' ? String(attr.value).toUpperCase() : '');
|
|
24
|
+
export default function imap4rev2Plugin(server) {
|
|
25
|
+
// RFC 9051 Appendix A: advertised together with IMAP4rev1 (capability.ts always lists it), so every session
|
|
35
26
|
// starts as IMAP4rev1 (section 7.2.2) and ENABLE switches it (section 6.3.1)
|
|
36
27
|
server.registerCapability('IMAP4rev2');
|
|
37
|
-
|
|
38
28
|
registerEnable(server, REV2);
|
|
39
|
-
|
|
40
29
|
// RFC 9051 section 4.3 and Appendix E item 2: non-synchronizing literals up to 4096 octets (LITERAL-). LITERAL+
|
|
41
30
|
// allows more, so it is kept if it is loaded already, and it can replace this LITERAL- when it is loaded later
|
|
42
31
|
if (!server.capabilities['LITERAL+'] && !server.capabilities['LITERAL-']) {
|
|
43
32
|
literalMinus(server);
|
|
44
33
|
server.impliedLiteralMinus = true;
|
|
45
34
|
}
|
|
46
|
-
|
|
47
35
|
// RFC 9051 section 2.3.2: a mailbox that does not allow new keywords (no "\*" in PERMANENTFLAGS) still keeps these
|
|
48
36
|
server.mailboxHandlers.push((server, mailbox) => {
|
|
49
37
|
if (!mailbox.allowPermanentFlags) {
|
|
50
38
|
KEYWORDS.forEach(keyword => server.ensureFlag(mailbox.permanentFlags, keyword));
|
|
51
39
|
}
|
|
52
40
|
});
|
|
53
|
-
|
|
54
41
|
// The session follows RFC 9051 once IMAP4rev2 is enabled
|
|
55
|
-
const setMode = connection => {
|
|
42
|
+
const setMode = (connection) => {
|
|
56
43
|
const rev2 = (connection.imap4rev2 = isEnabled(connection, REV2));
|
|
57
44
|
// UTF-8 in quoted strings and mailbox names (sections 4.3 and 5.1), SEARCH assumes UTF-8 (section 6.4.4)
|
|
58
45
|
updateSession(connection);
|
|
@@ -66,8 +53,9 @@ module.exports = function (server) {
|
|
|
66
53
|
connection.addedStatusItems = rev2 ? ADDED_STATUS_ITEMS : null;
|
|
67
54
|
if (rev2) {
|
|
68
55
|
// \Recent is deprecated (section 2.3.2, Appendix E item 12), an IMAP4rev2 session does not see it
|
|
69
|
-
connection.getFlags = message => message.flags;
|
|
70
|
-
}
|
|
56
|
+
connection.getFlags = (message) => message.flags;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
71
59
|
// back to IMAPConnection#getFlags
|
|
72
60
|
delete connection.getFlags;
|
|
73
61
|
}
|
|
@@ -75,18 +63,15 @@ module.exports = function (server) {
|
|
|
75
63
|
server.connectionHandlers.push(setMode);
|
|
76
64
|
// RFC 8437 section 4.1: UNAUTHENTICATE turns ENABLEd extensions off
|
|
77
65
|
server.resetHandlers.push(setMode);
|
|
78
|
-
|
|
79
66
|
const sendBad = (connection, parsed, data, callback, text) => {
|
|
80
67
|
connection.sendStatus(parsed, data, 'BAD', text);
|
|
81
68
|
return callback();
|
|
82
69
|
};
|
|
83
|
-
|
|
84
70
|
// Wraps the handler of a command, `wrapper(prevHandler, connection, parsed, data, callback)` runs instead
|
|
85
71
|
const wrap = (command, wrapper) => {
|
|
86
72
|
const prevHandler = server.getCommandHandler(command);
|
|
87
73
|
server.setCommandHandler(command, (connection, parsed, data, callback) => wrapper(prevHandler, connection, parsed, data, callback));
|
|
88
74
|
};
|
|
89
|
-
|
|
90
75
|
// Appendix E item 17: CHECK was removed, NOOP does the same. Item 19: LSUB was deprecated and left out of the
|
|
91
76
|
// section 9 grammar, LIST (SUBSCRIBED) replaces it
|
|
92
77
|
Object.entries({ CHECK: 'NOOP', LSUB: 'LIST (SUBSCRIBED)' }).forEach(([command, replacement]) => {
|
|
@@ -97,25 +82,17 @@ module.exports = function (server) {
|
|
|
97
82
|
prevHandler(connection, parsed, data, callback);
|
|
98
83
|
});
|
|
99
84
|
});
|
|
100
|
-
|
|
101
85
|
// Appendix E item 18: RFC822, RFC822.HEADER and RFC822.TEXT are not fetch-att items any more, BODY[], BODY.PEEK[HEADER]
|
|
102
86
|
// and BODY[TEXT] replace them. RFC822.SIZE stays
|
|
103
87
|
const fetchWrapper = (prevHandler, connection, parsed, data, callback) => {
|
|
104
88
|
const items = (parsed.attributes || [])[1];
|
|
105
89
|
if (isRev2(connection) && [].concat(items || []).some(item => REMOVED_FETCH_ITEMS.has(atomName(item)))) {
|
|
106
|
-
return sendBad(
|
|
107
|
-
connection,
|
|
108
|
-
parsed,
|
|
109
|
-
data,
|
|
110
|
-
callback,
|
|
111
|
-
'RFC822, RFC822.HEADER and RFC822.TEXT are not part of IMAP4rev2, use BODY[] (RFC 9051 Appendix E)'
|
|
112
|
-
);
|
|
90
|
+
return sendBad(connection, parsed, data, callback, 'RFC822, RFC822.HEADER and RFC822.TEXT are not part of IMAP4rev2, use BODY[] (RFC 9051 Appendix E)');
|
|
113
91
|
}
|
|
114
92
|
prevHandler(connection, parsed, data, callback);
|
|
115
93
|
};
|
|
116
94
|
wrap('FETCH', fetchWrapper);
|
|
117
95
|
wrap('UID FETCH', fetchWrapper);
|
|
118
|
-
|
|
119
96
|
// Appendix E item 4 and section 6.4.4: SEARCH answers with ESEARCH, without result options it is RETURN (ALL).
|
|
120
97
|
// The ESEARCH plugin replaces the SEARCH response once `parsed.searchReturn` is set
|
|
121
98
|
const searchWrapper = (prevHandler, connection, parsed, data, callback) => {
|
|
@@ -126,33 +103,24 @@ module.exports = function (server) {
|
|
|
126
103
|
};
|
|
127
104
|
wrap('SEARCH', searchWrapper);
|
|
128
105
|
wrap('UID SEARCH', searchWrapper);
|
|
129
|
-
|
|
130
106
|
// Appendix E item 9 and section 6.3.2: SELECT and EXAMINE report CLOSED when they close the selected mailbox
|
|
131
107
|
server.closedChecks.push(isRev2);
|
|
132
|
-
|
|
133
108
|
// Untagged LIST response for the selected mailbox (section 6.3.2, Appendix E item 10), with accurate attributes.
|
|
134
109
|
// Not a "LIST ITEM" response, that ACL would hide for a mailbox the user may read but not list
|
|
135
110
|
const sendMailboxList = (connection, mailbox, parsed, data) => {
|
|
136
111
|
// the special-use attributes of SPECIAL-USE are mailbox attributes in IMAP4rev2 (section 7.3.1)
|
|
137
112
|
const attributes = mailbox.flags.concat(mailbox['special-use'] || []);
|
|
138
|
-
connection.send(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
attributes:
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
},
|
|
149
|
-
'SELECT LIST',
|
|
150
|
-
parsed,
|
|
151
|
-
data,
|
|
152
|
-
mailbox
|
|
153
|
-
);
|
|
113
|
+
connection.send({
|
|
114
|
+
tag: '*',
|
|
115
|
+
command: 'LIST',
|
|
116
|
+
attributes: [
|
|
117
|
+
attributes.map(flag => ({ type: 'ATOM', value: flag })),
|
|
118
|
+
server.getSeparator(mailbox),
|
|
119
|
+
// the canonical name, converted for the session in IMAPConnection#send
|
|
120
|
+
{ type: 'MAILBOX', value: mailbox.path }
|
|
121
|
+
]
|
|
122
|
+
}, 'SELECT LIST', parsed, data, mailbox);
|
|
154
123
|
};
|
|
155
|
-
|
|
156
124
|
server.outputHandlers.push((connection, response, description, parsed, data) => {
|
|
157
125
|
if (!parsed || !response || !isRev2(connection)) {
|
|
158
126
|
return;
|
|
@@ -161,29 +129,25 @@ module.exports = function (server) {
|
|
|
161
129
|
if (command !== 'SELECT' && command !== 'EXAMINE') {
|
|
162
130
|
return;
|
|
163
131
|
}
|
|
164
|
-
|
|
165
132
|
// Appendix E items 11 and 12: the RECENT response and the UNSEEN response code are deprecated
|
|
166
133
|
if (description === command + ' RECENT' || description === command + ' UNSEEN') {
|
|
167
134
|
response.skipResponse = true;
|
|
168
135
|
return;
|
|
169
136
|
}
|
|
170
|
-
|
|
171
137
|
if (description === command && response.tag === parsed.tag && response.command === 'OK' && connection.selectedMailbox) {
|
|
172
138
|
sendMailboxList(connection, connection.selectedMailbox, parsed, data);
|
|
173
139
|
}
|
|
174
140
|
});
|
|
175
|
-
|
|
176
141
|
server.outputHandlers.push((connection, response, description, parsed, data, extra) => {
|
|
177
142
|
if (description === 'ENABLED' && Array.isArray(extra) && extra.indexOf(REV2) >= 0) {
|
|
178
143
|
setMode(connection);
|
|
179
144
|
}
|
|
180
145
|
});
|
|
181
|
-
}
|
|
182
|
-
|
|
146
|
+
}
|
|
183
147
|
// RFC 9051 Appendix E item 2 lists the extensions that IMAP4rev2 folds in. With them the plugins advertise their own
|
|
184
148
|
// capabilities, which RFC 9051 Appendix A suggests for a server that supports both revisions. AUTH=PLAIN is a MUST
|
|
185
149
|
// (section 6.1.1). LITERAL- is loaded by the plugin itself, unless LITERAL+ is loaded
|
|
186
|
-
|
|
150
|
+
imap4rev2Plugin.requires = [
|
|
187
151
|
'ENABLE',
|
|
188
152
|
'NAMESPACE',
|
|
189
153
|
'UNSELECT',
|