imapkit 4.0.3 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -19
- package/bin/imapkit.js +12 -16
- package/dist/cjs/addressparser.d.ts +21 -0
- package/dist/cjs/addressparser.js +277 -0
- package/dist/cjs/arguments.d.ts +31 -0
- package/{lib → dist/cjs}/arguments.js +9 -21
- package/dist/cjs/bodystructure.d.ts +25 -0
- package/dist/cjs/bodystructure.js +150 -0
- package/dist/cjs/cert.d.ts +2 -0
- package/dist/cjs/cert.js +7 -0
- package/dist/cjs/command-states.d.ts +36 -0
- package/dist/cjs/command-states.js +102 -0
- package/dist/cjs/commands/append.d.ts +88 -0
- package/dist/cjs/commands/append.js +299 -0
- package/dist/cjs/commands/capability.d.ts +2 -0
- package/dist/cjs/commands/capability.js +44 -0
- package/dist/cjs/commands/check.d.ts +2 -0
- package/dist/cjs/commands/check.js +28 -0
- package/dist/cjs/commands/close.d.ts +2 -0
- package/dist/cjs/commands/close.js +35 -0
- package/dist/cjs/commands/copy.d.ts +30 -0
- package/dist/cjs/commands/copy.js +107 -0
- package/dist/cjs/commands/create.d.ts +2 -0
- package/dist/cjs/commands/create.js +53 -0
- package/dist/cjs/commands/delete.d.ts +2 -0
- package/dist/cjs/commands/delete.js +63 -0
- package/dist/cjs/commands/examine.d.ts +2 -0
- package/dist/cjs/commands/examine.js +19 -0
- package/dist/cjs/commands/expunge.d.ts +2 -0
- package/dist/cjs/commands/expunge.js +32 -0
- package/dist/cjs/commands/fetch.d.ts +23 -0
- package/dist/cjs/commands/fetch.js +208 -0
- package/dist/cjs/commands/handlers/fetch.d.ts +12 -0
- package/dist/cjs/commands/handlers/fetch.js +195 -0
- package/dist/cjs/commands/handlers/flags.d.ts +17 -0
- package/dist/cjs/commands/handlers/flags.js +39 -0
- package/dist/cjs/commands/handlers/search.d.ts +85 -0
- package/dist/cjs/commands/handlers/search.js +504 -0
- package/dist/cjs/commands/handlers/status.d.ts +34 -0
- package/dist/cjs/commands/handlers/status.js +81 -0
- package/dist/cjs/commands/handlers/store.d.ts +3 -0
- package/dist/cjs/commands/handlers/store.js +117 -0
- package/dist/cjs/commands/index.d.ts +2 -0
- package/dist/cjs/commands/index.js +61 -0
- package/dist/cjs/commands/list.d.ts +2 -0
- package/dist/cjs/commands/list.js +86 -0
- package/dist/cjs/commands/login.d.ts +2 -0
- package/dist/cjs/commands/login.js +62 -0
- package/dist/cjs/commands/logout.d.ts +2 -0
- package/dist/cjs/commands/logout.js +40 -0
- package/dist/cjs/commands/lsub.d.ts +2 -0
- package/dist/cjs/commands/lsub.js +79 -0
- package/dist/cjs/commands/noop.d.ts +2 -0
- package/dist/cjs/commands/noop.js +28 -0
- package/dist/cjs/commands/rename.d.ts +2 -0
- package/dist/cjs/commands/rename.js +98 -0
- package/dist/cjs/commands/search.d.ts +10 -0
- package/dist/cjs/commands/search.js +71 -0
- package/dist/cjs/commands/select.d.ts +19 -0
- package/dist/cjs/commands/select.js +230 -0
- package/dist/cjs/commands/status.d.ts +2 -0
- package/dist/cjs/commands/status.js +57 -0
- package/dist/cjs/commands/store.d.ts +10 -0
- package/dist/cjs/commands/store.js +134 -0
- package/dist/cjs/commands/subscribe.d.ts +2 -0
- package/dist/cjs/commands/subscribe.js +51 -0
- package/dist/cjs/commands/uid-copy.d.ts +2 -0
- package/dist/cjs/commands/uid-copy.js +19 -0
- package/dist/cjs/commands/uid-fetch.d.ts +3 -0
- package/dist/cjs/commands/uid-fetch.js +17 -0
- package/dist/cjs/commands/uid-search.d.ts +3 -0
- package/dist/cjs/commands/uid-search.js +17 -0
- package/dist/cjs/commands/uid-store.d.ts +3 -0
- package/dist/cjs/commands/uid-store.js +17 -0
- package/dist/cjs/commands/unsubscribe.d.ts +2 -0
- package/dist/cjs/commands/unsubscribe.js +50 -0
- package/dist/cjs/dates.d.ts +64 -0
- package/dist/cjs/dates.js +124 -0
- package/dist/cjs/deflate-layer.d.ts +83 -0
- package/dist/cjs/deflate-layer.js +232 -0
- package/dist/cjs/encoded-words.d.ts +15 -0
- package/dist/cjs/encoded-words.js +85 -0
- package/dist/cjs/envelope.d.ts +33 -0
- package/dist/cjs/envelope.js +86 -0
- package/dist/cjs/esearch.d.ts +96 -0
- package/dist/cjs/esearch.js +190 -0
- package/dist/cjs/framing.d.ts +66 -0
- package/{lib → dist/cjs}/framing.js +9 -26
- package/dist/cjs/index.d.ts +9 -0
- package/dist/cjs/index.js +56 -0
- package/dist/cjs/list-extensions.d.ts +50 -0
- package/dist/cjs/list-extensions.js +35 -0
- package/dist/cjs/load-plugins.d.ts +21 -0
- package/dist/cjs/load-plugins.js +89 -0
- package/dist/cjs/mailbox-name.d.ts +26 -0
- package/dist/cjs/mailbox-name.js +127 -0
- package/dist/cjs/mimeparser.d.ts +137 -0
- package/dist/cjs/mimeparser.js +727 -0
- package/dist/cjs/mock-client.d.ts +39 -0
- package/dist/cjs/mock-client.js +236 -0
- package/dist/cjs/numbers.d.ts +28 -0
- package/dist/cjs/numbers.js +52 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/plugins/acl.d.ts +2 -0
- package/dist/cjs/plugins/acl.js +888 -0
- package/dist/cjs/plugins/appendlimit.d.ts +16 -0
- package/dist/cjs/plugins/appendlimit.js +87 -0
- package/dist/cjs/plugins/auth-plain.d.ts +2 -0
- package/dist/cjs/plugins/auth-plain.js +89 -0
- package/dist/cjs/plugins/binary.d.ts +30 -0
- package/dist/cjs/plugins/binary.js +247 -0
- package/dist/cjs/plugins/catenate.d.ts +14 -0
- package/dist/cjs/plugins/catenate.js +250 -0
- package/dist/cjs/plugins/compress.d.ts +7 -0
- package/dist/cjs/plugins/compress.js +79 -0
- package/dist/cjs/plugins/condstore.d.ts +5 -0
- package/dist/cjs/plugins/condstore.js +492 -0
- package/dist/cjs/plugins/context-search.d.ts +8 -0
- package/dist/cjs/plugins/context-search.js +304 -0
- package/dist/cjs/plugins/context-sort.d.ts +6 -0
- package/dist/cjs/plugins/context-sort.js +32 -0
- package/dist/cjs/plugins/create-special-use.d.ts +7 -0
- package/dist/cjs/plugins/create-special-use.js +101 -0
- package/dist/cjs/plugins/enable.d.ts +23 -0
- package/dist/cjs/plugins/enable.js +127 -0
- package/dist/cjs/plugins/esearch.d.ts +6 -0
- package/dist/cjs/plugins/esearch.js +142 -0
- package/dist/cjs/plugins/esort.d.ts +6 -0
- package/dist/cjs/plugins/esort.js +60 -0
- package/dist/cjs/plugins/id.d.ts +5 -0
- package/dist/cjs/plugins/id.js +123 -0
- package/dist/cjs/plugins/idle.d.ts +5 -0
- package/dist/cjs/plugins/idle.js +85 -0
- package/dist/cjs/plugins/imap4rev2.d.ts +6 -0
- package/dist/cjs/plugins/imap4rev2.js +184 -0
- package/dist/cjs/plugins/index.d.ts +2 -0
- package/dist/cjs/plugins/index.js +119 -0
- package/dist/cjs/plugins/list-extended.d.ts +2 -0
- package/dist/cjs/plugins/list-extended.js +235 -0
- package/dist/cjs/plugins/list-status.d.ts +6 -0
- package/dist/cjs/plugins/list-status.js +42 -0
- package/dist/cjs/plugins/literalminus.d.ts +8 -0
- package/dist/cjs/plugins/literalminus.js +32 -0
- package/dist/cjs/plugins/literalplus.d.ts +6 -0
- package/dist/cjs/plugins/literalplus.js +30 -0
- package/dist/cjs/plugins/logindisabled.d.ts +5 -0
- package/dist/cjs/plugins/logindisabled.js +54 -0
- package/dist/cjs/plugins/messagelimit.d.ts +19 -0
- package/dist/cjs/plugins/messagelimit.js +227 -0
- package/dist/cjs/plugins/metadata-server.d.ts +7 -0
- package/dist/cjs/plugins/metadata-server.js +24 -0
- package/dist/cjs/plugins/metadata.d.ts +11 -0
- package/dist/cjs/plugins/metadata.js +436 -0
- package/dist/cjs/plugins/move.d.ts +11 -0
- package/dist/cjs/plugins/move.js +96 -0
- package/dist/cjs/plugins/multiappend.d.ts +12 -0
- package/dist/cjs/plugins/multiappend.js +38 -0
- package/dist/cjs/plugins/multisearch.d.ts +6 -0
- package/dist/cjs/plugins/multisearch.js +263 -0
- package/dist/cjs/plugins/namespace.d.ts +5 -0
- package/dist/cjs/plugins/namespace.js +57 -0
- package/dist/cjs/plugins/notify.d.ts +2 -0
- package/dist/cjs/plugins/notify.js +628 -0
- package/dist/cjs/plugins/oauthbearer.d.ts +32 -0
- package/dist/cjs/plugins/oauthbearer.js +202 -0
- package/dist/cjs/plugins/objectid.d.ts +23 -0
- package/dist/cjs/plugins/objectid.js +221 -0
- package/dist/cjs/plugins/partial.d.ts +6 -0
- package/dist/cjs/plugins/partial.js +78 -0
- package/dist/cjs/plugins/preview.d.ts +31 -0
- package/dist/cjs/plugins/preview.js +378 -0
- package/dist/cjs/plugins/qresync.d.ts +11 -0
- package/dist/cjs/plugins/qresync.js +473 -0
- package/dist/cjs/plugins/quota.d.ts +18 -0
- package/dist/cjs/plugins/quota.js +254 -0
- package/dist/cjs/plugins/replace.d.ts +14 -0
- package/dist/cjs/plugins/replace.js +130 -0
- package/dist/cjs/plugins/sasl-ir.d.ts +5 -0
- package/dist/cjs/plugins/sasl-ir.js +24 -0
- package/dist/cjs/plugins/savedate.d.ts +17 -0
- package/dist/cjs/plugins/savedate.js +64 -0
- package/dist/cjs/plugins/savelimit.d.ts +10 -0
- package/dist/cjs/plugins/savelimit.js +30 -0
- package/dist/cjs/plugins/searchres.d.ts +6 -0
- package/dist/cjs/plugins/searchres.js +91 -0
- package/dist/cjs/plugins/sort-display.d.ts +11 -0
- package/dist/cjs/plugins/sort-display.js +37 -0
- package/dist/cjs/plugins/sort.d.ts +11 -0
- package/dist/cjs/plugins/sort.js +125 -0
- package/dist/cjs/plugins/special-use.d.ts +10 -0
- package/dist/cjs/plugins/special-use.js +95 -0
- package/dist/cjs/plugins/starttls.d.ts +5 -0
- package/dist/cjs/plugins/starttls.js +55 -0
- package/dist/cjs/plugins/status-size.d.ts +7 -0
- package/dist/cjs/plugins/status-size.js +30 -0
- package/dist/cjs/plugins/thread-orderedsubject.d.ts +11 -0
- package/dist/cjs/plugins/thread-orderedsubject.js +28 -0
- package/dist/cjs/plugins/thread-references.d.ts +11 -0
- package/dist/cjs/plugins/thread-references.js +28 -0
- package/dist/cjs/plugins/uidonly.d.ts +15 -0
- package/dist/cjs/plugins/uidonly.js +126 -0
- package/dist/cjs/plugins/uidplus.d.ts +15 -0
- package/dist/cjs/plugins/uidplus.js +119 -0
- package/dist/cjs/plugins/unauthenticate.d.ts +7 -0
- package/dist/cjs/plugins/unauthenticate.js +32 -0
- package/dist/cjs/plugins/unselect.d.ts +5 -0
- package/dist/cjs/plugins/unselect.js +36 -0
- package/dist/cjs/plugins/utf8-accept.d.ts +6 -0
- package/dist/cjs/plugins/utf8-accept.js +72 -0
- package/dist/cjs/plugins/x-gm-ext-1.d.ts +26 -0
- package/dist/cjs/plugins/x-gm-ext-1.js +422 -0
- package/dist/cjs/plugins/xoauth2.d.ts +2 -0
- package/dist/cjs/plugins/xoauth2.js +155 -0
- package/dist/cjs/plugins/xtoybird.d.ts +2 -0
- package/dist/cjs/plugins/xtoybird.js +236 -0
- package/dist/cjs/server.d.ts +876 -0
- package/dist/cjs/server.js +2597 -0
- package/dist/cjs/smtp-listener.d.ts +13 -0
- package/dist/cjs/smtp-listener.js +47 -0
- package/dist/cjs/sorting.d.ts +77 -0
- package/dist/cjs/sorting.js +290 -0
- package/dist/cjs/threading.d.ts +30 -0
- package/dist/cjs/threading.js +318 -0
- package/dist/cjs/types.d.ts +327 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/utf8-session.d.ts +17 -0
- package/dist/cjs/utf8-session.js +148 -0
- package/dist/cjs/vanished.d.ts +21 -0
- package/dist/cjs/vanished.js +55 -0
- package/dist/esm/addressparser.d.ts +21 -0
- package/{lib → dist/esm}/addressparser.js +102 -123
- package/dist/esm/arguments.d.ts +31 -0
- package/dist/esm/arguments.js +96 -0
- package/dist/esm/bodystructure.d.ts +25 -0
- package/{lib → dist/esm}/bodystructure.js +17 -33
- package/dist/esm/cert.d.ts +2 -0
- package/dist/esm/cert.js +4 -0
- package/dist/esm/command-states.d.ts +36 -0
- package/{lib → dist/esm}/command-states.js +4 -16
- package/dist/esm/commands/append.d.ts +88 -0
- package/{lib → dist/esm}/commands/append.js +47 -85
- package/dist/esm/commands/capability.d.ts +2 -0
- package/dist/esm/commands/capability.js +29 -0
- package/dist/esm/commands/check.d.ts +2 -0
- package/dist/esm/commands/check.js +13 -0
- package/dist/esm/commands/close.d.ts +2 -0
- package/dist/esm/commands/close.js +20 -0
- package/dist/esm/commands/copy.d.ts +30 -0
- package/{lib → dist/esm}/commands/copy.js +31 -55
- package/dist/esm/commands/create.d.ts +2 -0
- package/{lib → dist/esm}/commands/create.js +25 -39
- package/dist/esm/commands/delete.d.ts +2 -0
- package/{lib → dist/esm}/commands/delete.js +25 -41
- package/dist/esm/commands/examine.d.ts +2 -0
- package/dist/esm/commands/examine.js +4 -0
- package/dist/esm/commands/expunge.d.ts +2 -0
- package/dist/esm/commands/expunge.js +17 -0
- package/dist/esm/commands/fetch.d.ts +23 -0
- package/{lib → dist/esm}/commands/fetch.js +33 -74
- package/dist/esm/commands/handlers/fetch.d.ts +12 -0
- package/{lib → dist/esm}/commands/handlers/fetch.js +11 -42
- package/dist/esm/commands/handlers/flags.d.ts +17 -0
- package/{lib → dist/esm}/commands/handlers/flags.js +3 -11
- package/dist/esm/commands/handlers/search.d.ts +85 -0
- package/{lib → dist/esm}/commands/handlers/search.js +33 -71
- package/dist/esm/commands/handlers/status.d.ts +34 -0
- package/{lib → dist/esm}/commands/handlers/status.js +1 -9
- package/dist/esm/commands/handlers/store.d.ts +3 -0
- package/{lib → dist/esm}/commands/handlers/store.js +20 -44
- package/dist/esm/commands/index.d.ts +2 -0
- package/dist/esm/commands/index.js +55 -0
- package/dist/esm/commands/list.d.ts +2 -0
- package/dist/esm/commands/list.js +71 -0
- package/dist/esm/commands/login.d.ts +2 -0
- package/{lib → dist/esm}/commands/login.js +24 -44
- package/dist/esm/commands/logout.d.ts +2 -0
- package/dist/esm/commands/logout.js +25 -0
- package/dist/esm/commands/lsub.d.ts +2 -0
- package/dist/esm/commands/lsub.js +64 -0
- package/dist/esm/commands/noop.d.ts +2 -0
- package/dist/esm/commands/noop.js +13 -0
- package/dist/esm/commands/rename.d.ts +2 -0
- package/{lib → dist/esm}/commands/rename.js +32 -51
- package/dist/esm/commands/search.d.ts +10 -0
- package/dist/esm/commands/search.js +54 -0
- package/dist/esm/commands/select.d.ts +19 -0
- package/dist/esm/commands/select.js +214 -0
- package/dist/esm/commands/status.d.ts +2 -0
- package/{lib → dist/esm}/commands/status.js +18 -39
- package/dist/esm/commands/store.d.ts +10 -0
- package/{lib → dist/esm}/commands/store.js +39 -73
- package/dist/esm/commands/subscribe.d.ts +2 -0
- package/{lib → dist/esm}/commands/subscribe.js +22 -39
- package/dist/esm/commands/uid-copy.d.ts +2 -0
- package/dist/esm/commands/uid-copy.js +4 -0
- package/dist/esm/commands/uid-fetch.d.ts +3 -0
- package/dist/esm/commands/uid-fetch.js +3 -0
- package/dist/esm/commands/uid-search.d.ts +3 -0
- package/dist/esm/commands/uid-search.js +3 -0
- package/dist/esm/commands/uid-store.d.ts +3 -0
- package/dist/esm/commands/uid-store.js +3 -0
- package/dist/esm/commands/unsubscribe.d.ts +2 -0
- package/{lib → dist/esm}/commands/unsubscribe.js +22 -37
- package/dist/esm/dates.d.ts +64 -0
- package/{lib → dist/esm}/dates.js +6 -14
- package/dist/esm/deflate-layer.d.ts +83 -0
- package/{lib → dist/esm}/deflate-layer.js +9 -26
- package/dist/esm/encoded-words.d.ts +15 -0
- package/{lib → dist/esm}/encoded-words.js +9 -25
- package/dist/esm/envelope.d.ts +33 -0
- package/{lib → dist/esm}/envelope.js +8 -19
- package/dist/esm/esearch.d.ts +96 -0
- package/{lib → dist/esm}/esearch.js +12 -39
- package/dist/esm/framing.d.ts +66 -0
- package/dist/esm/framing.js +82 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/list-extensions.d.ts +50 -0
- package/{lib → dist/esm}/list-extensions.js +1 -4
- package/dist/esm/load-plugins.d.ts +21 -0
- package/{lib → dist/esm}/load-plugins.js +9 -43
- package/dist/esm/mailbox-name.d.ts +26 -0
- package/{lib → dist/esm}/mailbox-name.js +5 -26
- package/dist/esm/mimeparser.d.ts +137 -0
- package/{lib → dist/esm}/mimeparser.js +74 -152
- package/dist/esm/mock-client.d.ts +39 -0
- package/{lib → dist/esm}/mock-client.js +26 -40
- package/dist/esm/numbers.d.ts +28 -0
- package/{lib → dist/esm}/numbers.js +1 -8
- package/dist/esm/package.json +3 -0
- package/dist/esm/plugins/acl.d.ts +2 -0
- package/{lib → dist/esm}/plugins/acl.js +146 -240
- package/dist/esm/plugins/appendlimit.d.ts +16 -0
- package/{lib → dist/esm}/plugins/appendlimit.js +5 -16
- package/dist/esm/plugins/auth-plain.d.ts +2 -0
- package/{lib → dist/esm}/plugins/auth-plain.js +11 -31
- package/dist/esm/plugins/binary.d.ts +30 -0
- package/{lib → dist/esm}/plugins/binary.js +17 -43
- package/dist/esm/plugins/catenate.d.ts +14 -0
- package/{lib → dist/esm}/plugins/catenate.js +19 -40
- package/dist/esm/plugins/compress.d.ts +7 -0
- package/dist/esm/plugins/compress.js +61 -0
- package/dist/esm/plugins/condstore.d.ts +5 -0
- package/{lib → dist/esm}/plugins/condstore.js +66 -152
- package/dist/esm/plugins/context-search.d.ts +8 -0
- package/{lib → dist/esm}/plugins/context-search.js +53 -88
- package/dist/esm/plugins/context-sort.d.ts +6 -0
- package/{lib → dist/esm}/plugins/context-sort.js +4 -9
- package/dist/esm/plugins/create-special-use.d.ts +7 -0
- package/{lib → dist/esm}/plugins/create-special-use.js +33 -55
- package/dist/esm/plugins/enable.d.ts +23 -0
- package/dist/esm/plugins/enable.js +111 -0
- package/dist/esm/plugins/esearch.d.ts +6 -0
- package/{lib → dist/esm}/plugins/esearch.js +13 -42
- package/dist/esm/plugins/esort.d.ts +6 -0
- package/{lib → dist/esm}/plugins/esort.js +7 -25
- package/dist/esm/plugins/id.d.ts +5 -0
- package/dist/esm/plugins/id.js +108 -0
- package/dist/esm/plugins/idle.d.ts +5 -0
- package/dist/esm/plugins/idle.js +70 -0
- package/dist/esm/plugins/imap4rev2.d.ts +6 -0
- package/{lib → dist/esm}/plugins/imap4rev2.js +24 -60
- package/dist/esm/plugins/index.d.ts +2 -0
- package/dist/esm/plugins/index.js +113 -0
- package/dist/esm/plugins/list-extended.d.ts +2 -0
- package/{lib → dist/esm}/plugins/list-extended.js +28 -66
- package/dist/esm/plugins/list-status.d.ts +6 -0
- package/{lib → dist/esm}/plugins/list-status.js +5 -12
- package/dist/esm/plugins/literalminus.d.ts +8 -0
- package/{lib → dist/esm}/plugins/literalminus.js +2 -5
- package/dist/esm/plugins/literalplus.d.ts +6 -0
- package/{lib → dist/esm}/plugins/literalplus.js +2 -5
- package/dist/esm/plugins/logindisabled.d.ts +5 -0
- package/dist/esm/plugins/logindisabled.js +39 -0
- package/dist/esm/plugins/messagelimit.d.ts +19 -0
- package/{lib → dist/esm}/plugins/messagelimit.js +18 -41
- package/dist/esm/plugins/metadata-server.d.ts +7 -0
- package/{lib → dist/esm}/plugins/metadata-server.js +3 -7
- package/dist/esm/plugins/metadata.d.ts +11 -0
- package/dist/esm/plugins/metadata.js +421 -0
- package/dist/esm/plugins/move.d.ts +11 -0
- package/{lib → dist/esm}/plugins/move.js +37 -66
- package/dist/esm/plugins/multiappend.d.ts +12 -0
- package/{lib → dist/esm}/plugins/multiappend.js +2 -5
- package/dist/esm/plugins/multisearch.d.ts +6 -0
- package/{lib → dist/esm}/plugins/multisearch.js +24 -48
- package/dist/esm/plugins/namespace.d.ts +5 -0
- package/dist/esm/plugins/namespace.js +42 -0
- package/dist/esm/plugins/notify.d.ts +2 -0
- package/{lib → dist/esm}/plugins/notify.js +90 -134
- package/dist/esm/plugins/oauthbearer.d.ts +32 -0
- package/{lib → dist/esm}/plugins/oauthbearer.js +18 -48
- package/dist/esm/plugins/objectid.d.ts +23 -0
- package/{lib → dist/esm}/plugins/objectid.js +21 -58
- package/dist/esm/plugins/partial.d.ts +6 -0
- package/{lib → dist/esm}/plugins/partial.js +7 -15
- package/dist/esm/plugins/preview.d.ts +31 -0
- package/{lib → dist/esm}/plugins/preview.js +28 -66
- package/dist/esm/plugins/qresync.d.ts +11 -0
- package/{lib → dist/esm}/plugins/qresync.js +64 -134
- package/dist/esm/plugins/quota.d.ts +18 -0
- package/{lib → dist/esm}/plugins/quota.js +89 -135
- package/dist/esm/plugins/replace.d.ts +14 -0
- package/{lib → dist/esm}/plugins/replace.js +21 -51
- package/dist/esm/plugins/sasl-ir.d.ts +5 -0
- package/{lib → dist/esm}/plugins/sasl-ir.js +3 -6
- package/dist/esm/plugins/savedate.d.ts +17 -0
- package/{lib → dist/esm}/plugins/savedate.js +5 -15
- package/dist/esm/plugins/savelimit.d.ts +10 -0
- package/{lib → dist/esm}/plugins/savelimit.js +3 -6
- package/dist/esm/plugins/searchres.d.ts +6 -0
- package/{lib → dist/esm}/plugins/searchres.js +13 -22
- package/dist/esm/plugins/sort-display.d.ts +11 -0
- package/{lib → dist/esm}/plugins/sort-display.js +6 -10
- package/dist/esm/plugins/sort.d.ts +11 -0
- package/{lib → dist/esm}/plugins/sort.js +24 -46
- package/dist/esm/plugins/special-use.d.ts +10 -0
- package/{lib → dist/esm}/plugins/special-use.js +9 -24
- package/dist/esm/plugins/starttls.d.ts +5 -0
- package/{lib → dist/esm}/plugins/starttls.js +20 -37
- package/dist/esm/plugins/status-size.d.ts +7 -0
- package/{lib → dist/esm}/plugins/status-size.js +4 -11
- package/dist/esm/plugins/thread-orderedsubject.d.ts +11 -0
- package/{lib → dist/esm}/plugins/thread-orderedsubject.js +3 -6
- package/dist/esm/plugins/thread-references.d.ts +11 -0
- package/{lib → dist/esm}/plugins/thread-references.js +3 -6
- package/dist/esm/plugins/uidonly.d.ts +15 -0
- package/{lib → dist/esm}/plugins/uidonly.js +11 -35
- package/dist/esm/plugins/uidplus.d.ts +15 -0
- package/{lib → dist/esm}/plugins/uidplus.js +25 -45
- package/dist/esm/plugins/unauthenticate.d.ts +7 -0
- package/dist/esm/plugins/unauthenticate.js +17 -0
- package/dist/esm/plugins/unselect.d.ts +5 -0
- package/dist/esm/plugins/unselect.js +21 -0
- package/dist/esm/plugins/utf8-accept.d.ts +6 -0
- package/{lib → dist/esm}/plugins/utf8-accept.js +10 -21
- package/dist/esm/plugins/x-gm-ext-1.d.ts +26 -0
- package/{lib → dist/esm}/plugins/x-gm-ext-1.js +48 -100
- package/dist/esm/plugins/xoauth2.d.ts +2 -0
- package/dist/esm/plugins/xoauth2.js +140 -0
- package/dist/esm/plugins/xtoybird.d.ts +2 -0
- package/dist/esm/plugins/xtoybird.js +218 -0
- package/dist/esm/server.d.ts +876 -0
- package/dist/esm/server.js +2543 -0
- package/dist/esm/smtp-listener.d.ts +13 -0
- package/{lib → dist/esm}/smtp-listener.js +5 -12
- package/dist/esm/sorting.d.ts +77 -0
- package/{lib → dist/esm}/sorting.js +40 -53
- package/dist/esm/threading.d.ts +30 -0
- package/{lib → dist/esm}/threading.js +29 -70
- package/dist/esm/types.d.ts +327 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/utf8-session.d.ts +17 -0
- package/{lib → dist/esm}/utf8-session.js +15 -25
- package/dist/esm/vanished.d.ts +21 -0
- package/{lib → dist/esm}/vanished.js +16 -21
- package/dist/plugin-help.json +298 -0
- package/package.json +54 -11
- package/lib/commands/capability.js +0 -47
- package/lib/commands/check.js +0 -21
- package/lib/commands/close.js +0 -30
- package/lib/commands/examine.js +0 -7
- package/lib/commands/expunge.js +0 -27
- package/lib/commands/list.js +0 -100
- package/lib/commands/logout.js +0 -41
- package/lib/commands/lsub.js +0 -87
- package/lib/commands/noop.js +0 -21
- package/lib/commands/search.js +0 -76
- package/lib/commands/select.js +0 -289
- package/lib/commands/uid copy.js +0 -7
- package/lib/commands/uid fetch.js +0 -5
- package/lib/commands/uid search.js +0 -5
- package/lib/commands/uid store.js +0 -5
- package/lib/plugins/compress.js +0 -76
- package/lib/plugins/enable.js +0 -155
- package/lib/plugins/id.js +0 -138
- package/lib/plugins/idle.js +0 -105
- package/lib/plugins/logindisabled.js +0 -50
- package/lib/plugins/metadata.js +0 -475
- package/lib/plugins/namespace.js +0 -67
- package/lib/plugins/unauthenticate.js +0 -28
- package/lib/plugins/unselect.js +0 -36
- package/lib/plugins/xoauth2.js +0 -188
- package/lib/plugins/xtoybird.js +0 -282
- package/lib/server.js +0 -2880
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IMAPServer } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* @help Adds APPENDLIMIT [RFC7889] capability
|
|
4
|
+
* @help Server option "appendLimit" sets the limit in octets for all
|
|
5
|
+
* @help mailboxes, a mailbox in storage can set its own "appendLimit"
|
|
6
|
+
* @help (null for no limit)
|
|
7
|
+
*
|
|
8
|
+
* APPENDLIMIT: https://www.rfc-editor.org/rfc/rfc7889
|
|
9
|
+
*
|
|
10
|
+
* The server option "appendLimit" (octets) sets a limit for all mailboxes, advertised as
|
|
11
|
+
* APPENDLIMIT=<n>. A mailbox in the storage can set its own "appendLimit" (a number, or null
|
|
12
|
+
* for no limit), then the capability is a plain APPENDLIMIT and clients read the limits with
|
|
13
|
+
* STATUS (APPENDLIMIT). A larger APPEND or REPLACE fails with NO [TOOBIG], a synchronizing
|
|
14
|
+
* literal is refused before it is sent.
|
|
15
|
+
*/
|
|
16
|
+
export default function appendlimitPlugin(server: IMAPServer): void;
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { getPendingTarget } = require('../commands/append');
|
|
4
|
-
|
|
1
|
+
import { getPendingTarget } from '../commands/append.js';
|
|
5
2
|
/**
|
|
6
3
|
* @help Adds APPENDLIMIT [RFC7889] capability
|
|
7
4
|
* @help Server option "appendLimit" sets the limit in octets for all
|
|
@@ -16,39 +13,34 @@ const { getPendingTarget } = require('../commands/append');
|
|
|
16
13
|
* STATUS (APPENDLIMIT). A larger APPEND or REPLACE fails with NO [TOOBIG], a synchronizing
|
|
17
14
|
* literal is refused before it is sent.
|
|
18
15
|
*/
|
|
19
|
-
|
|
16
|
+
export default function appendlimitPlugin(server) {
|
|
20
17
|
const serverLimit = 'appendLimit' in server.options ? server.options.appendLimit : null;
|
|
21
18
|
if (serverLimit !== null && !isValidLimit(serverLimit)) {
|
|
22
19
|
throw new TypeError('Invalid appendLimit option, expecting a non-negative integer');
|
|
23
20
|
}
|
|
24
|
-
|
|
25
|
-
const hasOwnLimit = mailbox => Object.hasOwn(mailbox, 'appendLimit');
|
|
21
|
+
const hasOwnLimit = (mailbox) => Object.hasOwn(mailbox, 'appendLimit');
|
|
26
22
|
const hasMailboxLimits = () => Object.values(server.folderCache).some(hasOwnLimit);
|
|
27
|
-
|
|
28
23
|
/**
|
|
29
24
|
* @param {Object} mailbox Mailbox object
|
|
30
25
|
* @return {Number|null} limit in octets, null if there is no limit
|
|
31
26
|
*/
|
|
32
|
-
const getLimit = mailbox => {
|
|
27
|
+
const getLimit = (mailbox) => {
|
|
33
28
|
if (!hasOwnLimit(mailbox)) {
|
|
34
29
|
return serverLimit;
|
|
35
30
|
}
|
|
36
31
|
return isValidLimit(mailbox.appendLimit) ? mailbox.appendLimit : null;
|
|
37
32
|
};
|
|
38
|
-
|
|
39
33
|
// RFC 7889 section 5: an APPENDLIMIT of 0 means that nothing can be appended
|
|
40
34
|
const isTooBig = (mailbox, size) => {
|
|
41
35
|
const limit = getLimit(mailbox);
|
|
42
36
|
return limit !== null && (size > limit || limit === 0);
|
|
43
37
|
};
|
|
44
|
-
|
|
45
38
|
// RFC 7889 section 2: APPENDLIMIT=<n> for the same limit in every mailbox, otherwise a plain
|
|
46
39
|
// APPENDLIMIT and the limits come from STATUS
|
|
47
40
|
if (serverLimit !== null) {
|
|
48
41
|
server.registerCapability('APPENDLIMIT=' + serverLimit, () => !hasMailboxLimits());
|
|
49
42
|
}
|
|
50
43
|
server.registerCapability('APPENDLIMIT', () => serverLimit === null || hasMailboxLimits());
|
|
51
|
-
|
|
52
44
|
// RFC 7889 section 4: a message over the limit is refused with TOOBIG
|
|
53
45
|
server.appendChecks.push((connection, mailbox, messages, options) => {
|
|
54
46
|
// COPY and MOVE are not uploads (RFC 7889 section 1)
|
|
@@ -60,7 +52,6 @@ module.exports = function (server) {
|
|
|
60
52
|
}
|
|
61
53
|
return false;
|
|
62
54
|
});
|
|
63
|
-
|
|
64
55
|
// Refuse the literal of a message that is too large before the client sends it, by not
|
|
65
56
|
// sending a continuation request (RFC 3502 section 6.3.11 example A005)
|
|
66
57
|
server.literalFilters.push((connection, command, line, literalSize) => {
|
|
@@ -71,13 +62,11 @@ module.exports = function (server) {
|
|
|
71
62
|
}
|
|
72
63
|
return false;
|
|
73
64
|
});
|
|
74
|
-
|
|
75
65
|
// RFC 7889 section 3.1: status-att-val =/ "APPENDLIMIT" SP (number / nil)
|
|
76
66
|
server.allowedStatus.push('APPENDLIMIT');
|
|
77
67
|
// also used by the STATUS return option of LIST-STATUS (RFC 7889 section 3.2)
|
|
78
68
|
server.statusHandlers.APPENDLIMIT = (connection, mailbox) => getLimit(mailbox);
|
|
79
|
-
}
|
|
80
|
-
|
|
69
|
+
}
|
|
81
70
|
function isValidLimit(value) {
|
|
82
71
|
return Number.isSafeInteger(value) && value >= 0;
|
|
83
72
|
}
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @help Adds AUTH=PLAIN capability
|
|
5
3
|
* @help Supports SASL-IR [RFC4959] as well
|
|
6
4
|
*/
|
|
7
|
-
|
|
8
5
|
const utf8 = new TextDecoder('utf-8', { fatal: true });
|
|
9
|
-
|
|
10
|
-
module.exports = function (server) {
|
|
6
|
+
export default function authPlainPlugin(server) {
|
|
11
7
|
// Register AUTH=PLAIN capability for non authenticated state
|
|
12
|
-
server.registerCapability('AUTH=PLAIN', connection => {
|
|
8
|
+
server.registerCapability('AUTH=PLAIN', (connection) => {
|
|
13
9
|
return connection.state === 'Not Authenticated';
|
|
14
10
|
});
|
|
15
|
-
|
|
16
11
|
// Validates a base64 encoded "authzid NUL authcid NUL passwd" message (RFC 4616) and logs the user in
|
|
17
12
|
const authenticate = (connection, parsed, data, input) => {
|
|
18
13
|
const decoded = connection.decodeSaslResponse(input);
|
|
@@ -23,7 +18,8 @@ module.exports = function (server) {
|
|
|
23
18
|
let message;
|
|
24
19
|
try {
|
|
25
20
|
message = utf8.decode(decoded);
|
|
26
|
-
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
27
23
|
return connection.sendStatus(parsed, data, 'BAD', 'Invalid UTF-8 in SASL PLAIN message', false, 'AUTHENTICATE PLAIN FAILED');
|
|
28
24
|
}
|
|
29
25
|
const parts = message.split('\x00');
|
|
@@ -31,23 +27,19 @@ module.exports = function (server) {
|
|
|
31
27
|
const username = parts[1] || '';
|
|
32
28
|
const password = parts[2] || '';
|
|
33
29
|
const user = connection.server.getUser(username);
|
|
34
|
-
|
|
35
30
|
if (parts.length !== 3 || !user || user.password !== password) {
|
|
36
31
|
// RFC 5530 section 3: unknown user or bad password
|
|
37
32
|
return connection.sendStatus(parsed, data, 'NO', 'Login failed: authentication failure', 'AUTHENTICATIONFAILED', 'AUTHENTICATE PLAIN FAILED');
|
|
38
33
|
}
|
|
39
|
-
|
|
40
34
|
if (authzid && authzid !== username) {
|
|
41
35
|
// Acting as another user is not supported, authzid must be empty or the same as authcid. The credentials
|
|
42
36
|
// were fine, so this is AUTHORIZATIONFAILED (RFC 5530 section 3, RFC 9051 section 7.1)
|
|
43
37
|
return connection.sendStatus(parsed, data, 'NO', 'Can not act as ' + authzid, 'AUTHORIZATIONFAILED', 'AUTHENTICATE PLAIN FAILED');
|
|
44
38
|
}
|
|
45
|
-
|
|
46
39
|
connection.state = 'Authenticated';
|
|
47
40
|
connection.username = username;
|
|
48
41
|
connection.sendStatus(parsed, data, 'OK', 'User logged in', false, 'AUTHENTICATE PLAIN SUCCESS');
|
|
49
42
|
};
|
|
50
|
-
|
|
51
43
|
server.setCommandHandler('AUTHENTICATE PLAIN', (connection, parsed, data, callback) => {
|
|
52
44
|
// If this is the old style api, send + and wait for password
|
|
53
45
|
if (!parsed.attributes) {
|
|
@@ -55,40 +47,28 @@ module.exports = function (server) {
|
|
|
55
47
|
connection.inputHandler = function (str) {
|
|
56
48
|
// Stop listening to any other user input
|
|
57
49
|
connection.inputHandler = false;
|
|
58
|
-
|
|
59
50
|
if (str === '*') {
|
|
60
51
|
// Client cancelled the exchange (RFC 3501 section 6.2.2)
|
|
61
52
|
return connection.sendStatus(parsed, data, 'BAD', 'Authentication cancelled', false, 'AUTHENTICATE PLAIN FAILED');
|
|
62
53
|
}
|
|
63
|
-
|
|
64
54
|
authenticate(connection, parsed, data, str);
|
|
65
55
|
};
|
|
66
|
-
|
|
67
56
|
// Send an empty continuation request to the client
|
|
68
57
|
connection.write('+ \r\n');
|
|
69
|
-
}
|
|
70
|
-
|
|
58
|
+
}
|
|
59
|
+
else if (parsed.attributes.length === 1 &&
|
|
71
60
|
// second argument must be Base64 string as ATOM
|
|
72
|
-
parsed.attributes[0].type === 'ATOM'
|
|
73
|
-
) {
|
|
61
|
+
parsed.attributes[0].type === 'ATOM') {
|
|
74
62
|
if (!server.capabilities['SASL-IR'] || !server.capabilities['SASL-IR'](connection)) {
|
|
75
|
-
connection.sendStatus(
|
|
76
|
-
parsed,
|
|
77
|
-
data,
|
|
78
|
-
'BAD',
|
|
79
|
-
'SASL-IR must be enabled to send Initial Response with the request',
|
|
80
|
-
false,
|
|
81
|
-
'AUTHENTICATE PLAIN FAILED'
|
|
82
|
-
);
|
|
63
|
+
connection.sendStatus(parsed, data, 'BAD', 'SASL-IR must be enabled to send Initial Response with the request', false, 'AUTHENTICATE PLAIN FAILED');
|
|
83
64
|
return callback();
|
|
84
65
|
}
|
|
85
|
-
|
|
86
66
|
authenticate(connection, parsed, data, parsed.attributes[0].value);
|
|
87
|
-
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
88
69
|
// Not correct AUTH=PLAIN
|
|
89
70
|
connection.sendStatus(parsed, data, 'BAD', 'Invalid attributes for AUTHENTICATE PLAIN', false, 'AUTHENTICATE PLAIN FAILED');
|
|
90
71
|
}
|
|
91
|
-
|
|
92
72
|
return callback();
|
|
93
73
|
});
|
|
94
|
-
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { IMAPServer } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Decodes base64 data. RFC 2045 section 6.8: characters outside the base64 alphabet are ignored, and
|
|
4
|
+
* "=" marks the end of the data
|
|
5
|
+
*
|
|
6
|
+
* @param {String} str Encoded data
|
|
7
|
+
* @return {String} Decoded octets as a binary string
|
|
8
|
+
*/
|
|
9
|
+
declare function decodeBase64(str: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Decodes quoted-printable data (RFC 2045 section 6.7). Trailing white space of a line is removed
|
|
12
|
+
* (rule 3), a line that ends with "=" continues on the next line (rule 5), and an "=" that is not
|
|
13
|
+
* followed by two hex digits is kept as it is, as the RFC suggests for robust implementations
|
|
14
|
+
*
|
|
15
|
+
* @param {String} str Encoded data with CRLF line breaks
|
|
16
|
+
* @return {String} Decoded octets as a binary string
|
|
17
|
+
*/
|
|
18
|
+
declare function decodeQuotedPrintable(str: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Base64 encodes the binary parts of a message that was appended as a literal8, as the IMAP4rev1
|
|
21
|
+
* part of the protocol can not carry them (RFC 3516 sections 4.4 and 6): parts with the binary
|
|
22
|
+
* encoding, and parts with an identity encoding that contain NUL octets anyway. Any other NUL octet
|
|
23
|
+
* (in a header, or in a part with another encoding) can not be stored.
|
|
24
|
+
*
|
|
25
|
+
* @param {String} raw Message as a binary string
|
|
26
|
+
* @return {String} Message to store
|
|
27
|
+
*/
|
|
28
|
+
declare function storeBinaryMessage(raw: string): string;
|
|
29
|
+
export default function binaryPlugin(server: IMAPServer): void;
|
|
30
|
+
export { decodeBase64, decodeQuotedPrintable, storeBinaryMessage };
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const { applyPartial } = require('../commands/handlers/fetch');
|
|
5
|
-
const { appendError } = require('../commands/append');
|
|
6
|
-
|
|
1
|
+
import { getMessageData, resolveNode, embeddedMessage, render, parseTree, normalizeLineBreaks, IDENTITY_ENCODINGS } from '../mimeparser.js';
|
|
2
|
+
import { applyPartial } from '../commands/handlers/fetch.js';
|
|
3
|
+
import { appendError } from '../commands/append.js';
|
|
7
4
|
/**
|
|
8
5
|
* @help Adds BINARY [RFC3516] capability
|
|
9
6
|
*
|
|
@@ -14,13 +11,10 @@ const { appendError } = require('../commands/append');
|
|
|
14
11
|
*
|
|
15
12
|
* APPEND (and REPLACE) accept messages as a literal8 (~{n}), binary parts are stored base64 encoded
|
|
16
13
|
*/
|
|
17
|
-
|
|
18
14
|
// RFC 3516 section 7: section-binary = "[" [section-part] "]", section-part = nz-number *("." nz-number)
|
|
19
15
|
const SECTION_PART = /^[1-9]\d*(?:\.[1-9]\d*)*$/;
|
|
20
|
-
|
|
21
16
|
// decoded leaf parts, the tree of a message is replaced when its source changes
|
|
22
17
|
const decodedCache = new WeakMap();
|
|
23
|
-
|
|
24
18
|
/**
|
|
25
19
|
* Creates an error that fails a command with NO [UNKNOWN-CTE] (RFC 3516 sections 4.3 and 4.4)
|
|
26
20
|
*
|
|
@@ -33,7 +27,6 @@ function unknownCte(message) {
|
|
|
33
27
|
err.code = 'UNKNOWN-CTE';
|
|
34
28
|
return err;
|
|
35
29
|
}
|
|
36
|
-
|
|
37
30
|
/**
|
|
38
31
|
* Returns the media type of a tree node, e.g. "text/plain"
|
|
39
32
|
*/
|
|
@@ -41,14 +34,12 @@ function mediaType(node) {
|
|
|
41
34
|
const contentType = node.parsedHeader['content-type'];
|
|
42
35
|
return ((contentType && contentType.value) || '').toLowerCase();
|
|
43
36
|
}
|
|
44
|
-
|
|
45
37
|
/**
|
|
46
38
|
* Returns the lower case content transfer encoding of a node, 7bit if not set (RFC 2045 section 6.1)
|
|
47
39
|
*/
|
|
48
40
|
function transferEncoding(node) {
|
|
49
41
|
return (node.parsedHeader['content-transfer-encoding'] || '7bit').toString().trim().toLowerCase();
|
|
50
42
|
}
|
|
51
|
-
|
|
52
43
|
/**
|
|
53
44
|
* RFC 9051 section 6.4.5: BINARY applies to leaf body parts only, not to multipart/*, message/rfc822
|
|
54
45
|
* or message/global parts. IMAP4rev1 describes message/global as a basic part (RFC 3501 body-type-basic)
|
|
@@ -60,7 +51,6 @@ function isLeaf(node, global) {
|
|
|
60
51
|
const type = mediaType(node);
|
|
61
52
|
return !node.boundary && !/^multipart\//.test(type) && type !== 'message/rfc822' && (!global || type !== 'message/global');
|
|
62
53
|
}
|
|
63
|
-
|
|
64
54
|
/**
|
|
65
55
|
* Decodes base64 data. RFC 2045 section 6.8: characters outside the base64 alphabet are ignored, and
|
|
66
56
|
* "=" marks the end of the data
|
|
@@ -76,7 +66,6 @@ function decodeBase64(str) {
|
|
|
76
66
|
}
|
|
77
67
|
return Buffer.from(data, 'base64').toString('binary');
|
|
78
68
|
}
|
|
79
|
-
|
|
80
69
|
/**
|
|
81
70
|
* Decodes quoted-printable data (RFC 2045 section 6.7). Trailing white space of a line is removed
|
|
82
71
|
* (rule 3), a line that ends with "=" continues on the next line (rule 5), and an "=" that is not
|
|
@@ -91,7 +80,6 @@ function decodeQuotedPrintable(str) {
|
|
|
91
80
|
.replace(/=(?:\r\n|$)/g, '')
|
|
92
81
|
.replace(/=([0-9A-Fa-f]{2})/g, (match, hex) => String.fromCharCode(parseInt(hex, 16)));
|
|
93
82
|
}
|
|
94
|
-
|
|
95
83
|
/**
|
|
96
84
|
* Returns the content of a BINARY section with the content transfer encoding removed
|
|
97
85
|
*
|
|
@@ -103,7 +91,6 @@ function decodeQuotedPrintable(str) {
|
|
|
103
91
|
function getDecodedSection(connection, message, query) {
|
|
104
92
|
const key = query.value.toUpperCase();
|
|
105
93
|
const section = query.section;
|
|
106
|
-
|
|
107
94
|
if (!section) {
|
|
108
95
|
throw new Error(key + ' requires a section');
|
|
109
96
|
}
|
|
@@ -114,7 +101,6 @@ function getDecodedSection(connection, message, query) {
|
|
|
114
101
|
if (section.length !== 1 || section[0].type !== 'ATOM' || !SECTION_PART.test(section[0].value)) {
|
|
115
102
|
throw new Error('Invalid ' + key + ' section, expecting a part number (RFC 3516 section 7)');
|
|
116
103
|
}
|
|
117
|
-
|
|
118
104
|
const node = resolveNode(getMessageData(message).tree, section[0].value, connection.messageGlobal);
|
|
119
105
|
if (!node) {
|
|
120
106
|
// like BODY[<section>], a part that does not exist is empty
|
|
@@ -123,13 +109,11 @@ function getDecodedSection(connection, message, query) {
|
|
|
123
109
|
if (!isLeaf(node, connection.messageGlobal)) {
|
|
124
110
|
throw new Error(key + '[' + section[0].value + '] is not a leaf body part (RFC 9051 section 6.4.5)');
|
|
125
111
|
}
|
|
126
|
-
|
|
127
112
|
if (!decodedCache.has(node)) {
|
|
128
113
|
decodedCache.set(node, decodeNode(node));
|
|
129
114
|
}
|
|
130
115
|
return decodedCache.get(node);
|
|
131
116
|
}
|
|
132
|
-
|
|
133
117
|
/**
|
|
134
118
|
* Removes the content transfer encoding of a leaf part
|
|
135
119
|
*
|
|
@@ -142,25 +126,25 @@ function decodeNode(node) {
|
|
|
142
126
|
let decoded;
|
|
143
127
|
if (IDENTITY_ENCODINGS.includes(encoding)) {
|
|
144
128
|
decoded = body;
|
|
145
|
-
}
|
|
129
|
+
}
|
|
130
|
+
else if (encoding === 'base64') {
|
|
146
131
|
decoded = decodeBase64(body);
|
|
147
|
-
}
|
|
132
|
+
}
|
|
133
|
+
else if (encoding === 'quoted-printable') {
|
|
148
134
|
decoded = decodeQuotedPrintable(body);
|
|
149
|
-
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
150
137
|
throw unknownCte('Unknown Content-Transfer-Encoding ' + JSON.stringify(encoding).replace(/[^\x20-\x7e]/g, '?'));
|
|
151
138
|
}
|
|
152
|
-
|
|
153
139
|
// RFC 3516 section 6: textual sections are sent with CRLF line breaks
|
|
154
140
|
return /^text\//.test(mediaType(node)) ? normalizeLineBreaks(decoded) : decoded;
|
|
155
141
|
}
|
|
156
|
-
|
|
157
142
|
/**
|
|
158
143
|
* BINARY[<section>]<<partial>> (RFC 3516 section 4.2)
|
|
159
144
|
*/
|
|
160
145
|
function fetchBinary(connection, message, query) {
|
|
161
146
|
// RFC 3516 section 4.2: the range applies to the decoded data
|
|
162
147
|
const value = applyPartial(getDecodedSection(connection, message, query), query.partial);
|
|
163
|
-
|
|
164
148
|
// RFC 3516 section 4.3: data without NUL is sent as a string, a literal8 only when it is needed
|
|
165
149
|
return {
|
|
166
150
|
type: value.indexOf('\x00') >= 0 ? 'LITERAL8' : 'LITERAL',
|
|
@@ -169,7 +153,6 @@ function fetchBinary(connection, message, query) {
|
|
|
169
153
|
}
|
|
170
154
|
// BINARY sets \Seen like BODY[<section>] does
|
|
171
155
|
fetchBinary.setsSeen = true;
|
|
172
|
-
|
|
173
156
|
/**
|
|
174
157
|
* BINARY.SIZE[<section>] (RFC 3516 section 4.2), the size of the decoded section
|
|
175
158
|
*/
|
|
@@ -180,7 +163,6 @@ function fetchBinarySize(connection, message, query) {
|
|
|
180
163
|
}
|
|
181
164
|
return getDecodedSection(connection, message, query).length;
|
|
182
165
|
}
|
|
183
|
-
|
|
184
166
|
/**
|
|
185
167
|
* Base64 encodes the binary parts of a message that was appended as a literal8, as the IMAP4rev1
|
|
186
168
|
* part of the protocol can not carry them (RFC 3516 sections 4.4 and 6): parts with the binary
|
|
@@ -192,9 +174,8 @@ function fetchBinarySize(connection, message, query) {
|
|
|
192
174
|
*/
|
|
193
175
|
function storeBinaryMessage(raw) {
|
|
194
176
|
const tree = parseTree(raw);
|
|
195
|
-
|
|
196
177
|
// returns true if the node or anything in it was converted
|
|
197
|
-
const convert = node => {
|
|
178
|
+
const convert = (node) => {
|
|
198
179
|
if (node.childNodes) {
|
|
199
180
|
// every part is converted, so no short circuit
|
|
200
181
|
return node.childNodes.map(convert).includes(true);
|
|
@@ -217,40 +198,33 @@ function storeBinaryMessage(raw) {
|
|
|
217
198
|
.toString('base64')
|
|
218
199
|
.match(/.{1,76}/g)
|
|
219
200
|
.join('\r\n');
|
|
220
|
-
node.header = node.header.filter(line => !/^content-transfer-encoding\s*:/i.test(line)).concat('Content-Transfer-Encoding: base64');
|
|
201
|
+
node.header = node.header.filter((line) => !/^content-transfer-encoding\s*:/i.test(line)).concat('Content-Transfer-Encoding: base64');
|
|
221
202
|
return true;
|
|
222
203
|
};
|
|
223
|
-
|
|
224
204
|
const result = convert(tree) ? render(tree) : raw;
|
|
225
205
|
if (result.indexOf('\x00') >= 0) {
|
|
226
206
|
throw unknownCte('NUL octets are only allowed in the body of a part with the binary, 7bit or 8bit encoding');
|
|
227
207
|
}
|
|
228
208
|
return result;
|
|
229
209
|
}
|
|
230
|
-
|
|
231
|
-
module.exports = function (server) {
|
|
210
|
+
export default function binaryPlugin(server) {
|
|
232
211
|
server.registerCapability('BINARY');
|
|
233
|
-
|
|
234
212
|
// RFC 3516 section 7: literal8 and the BINARY fetch items with a section and a partial range
|
|
235
213
|
server.parserOptions.literal8 = true;
|
|
236
214
|
server.parserOptions.allowSection.push('BINARY', 'BINARY.PEEK', 'BINARY.SIZE');
|
|
237
|
-
|
|
238
215
|
server.fetchHandlers.BINARY = fetchBinary;
|
|
239
216
|
// the same without setting \Seen
|
|
240
217
|
server.fetchHandlers['BINARY.PEEK'] = (connection, message, query) => fetchBinary(connection, message, query);
|
|
241
218
|
server.fetchHandlers['BINARY.SIZE'] = fetchBinarySize;
|
|
242
|
-
|
|
243
219
|
// RFC 3516 section 4.4: APPEND (and REPLACE, MULTIAPPEND) take a message as a literal8, the commands
|
|
244
220
|
// allow it with the literal8: 'BINARY' option
|
|
245
|
-
server.appendLiteral8 = raw => {
|
|
221
|
+
server.appendLiteral8 = (raw) => {
|
|
246
222
|
try {
|
|
247
223
|
return storeBinaryMessage(raw);
|
|
248
|
-
}
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
249
226
|
throw appendError(err.message, err.code);
|
|
250
227
|
}
|
|
251
228
|
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
module.exports.decodeBase64 = decodeBase64;
|
|
255
|
-
module.exports.decodeQuotedPrintable = decodeQuotedPrintable;
|
|
256
|
-
module.exports.storeBinaryMessage = storeBinaryMessage;
|
|
229
|
+
}
|
|
230
|
+
export { decodeBase64, decodeQuotedPrintable, storeBinaryMessage };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IMAPServer } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* @help Adds CATENATE [RFC4469] and URL-PARTIAL [RFC5550] capabilities
|
|
4
|
+
* @help Only absolute-path URLs are accepted, eg. "/INBOX/;UID=1/;SECTION=1"
|
|
5
|
+
*
|
|
6
|
+
* CATENATE: https://www.rfc-editor.org/rfc/rfc4469
|
|
7
|
+
*
|
|
8
|
+
* APPEND (and REPLACE) can build a message from literals and IMAP URLs of messages or
|
|
9
|
+
* message parts on this server. Only absolute-path URLs are accepted, for example
|
|
10
|
+
* "/INBOX;UIDVALIDITY=1/;UID=2/;SECTION=1.MIME/;PARTIAL=0.100" (RFC 5092). Other URLs,
|
|
11
|
+
* and URLs that do not resolve, fail with NO [BADURL]. A message larger than the
|
|
12
|
+
* literal size limit fails with NO [TOOBIG].
|
|
13
|
+
*/
|
|
14
|
+
export default function catenatePlugin(server: IMAPServer): void;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const { encodeMailboxName } = require('../mailbox-name');
|
|
8
|
-
const { isNumber, isNzNumber } = require('../numbers');
|
|
9
|
-
|
|
1
|
+
import imapHandler from 'imap-handler';
|
|
2
|
+
import { appendError, badArgument } from '../commands/append.js';
|
|
3
|
+
import fetchHandlers from '../commands/handlers/fetch.js';
|
|
4
|
+
import { getMessageData, resolveNode } from '../mimeparser.js';
|
|
5
|
+
import { encodeMailboxName } from '../mailbox-name.js';
|
|
6
|
+
import { isNumber, isNzNumber } from '../numbers.js';
|
|
10
7
|
/**
|
|
11
8
|
* @help Adds CATENATE [RFC4469] and URL-PARTIAL [RFC5550] capabilities
|
|
12
9
|
* @help Only absolute-path URLs are accepted, eg. "/INBOX/;UID=1/;SECTION=1"
|
|
@@ -19,31 +16,30 @@ const { isNumber, isNzNumber } = require('../numbers');
|
|
|
19
16
|
* and URLs that do not resolve, fail with NO [BADURL]. A message larger than the
|
|
20
17
|
* literal size limit fails with NO [TOOBIG].
|
|
21
18
|
*/
|
|
22
|
-
|
|
19
|
+
export default function catenatePlugin(server) {
|
|
23
20
|
server.registerCapability('CATENATE');
|
|
24
21
|
// RFC 5550 section 5.7.1: ;PARTIAL= is supported in the URLs of CATENATE
|
|
25
22
|
server.registerCapability('URL-PARTIAL');
|
|
26
|
-
|
|
27
23
|
// RFC 4469 section 5: append-data =/ "CATENATE" SP "(" cat-part *(SP cat-part) ")"
|
|
28
24
|
// cat-part = text-literal / url, text-literal = "TEXT" SP literal, url = "URL" SP astring
|
|
29
25
|
server.appendDataHandlers.CATENATE = (connection, list) => {
|
|
30
26
|
if (!Array.isArray(list) || !list.length || list.length % 2) {
|
|
31
27
|
throw badArgument('CATENATE expects a list of TEXT literals and URLs');
|
|
32
28
|
}
|
|
33
|
-
|
|
34
29
|
const parts = [];
|
|
35
30
|
for (let i = 0; i < list.length; i += 2) {
|
|
36
31
|
const label = list[i] && list[i].type === 'ATOM' ? String(list[i].value).toUpperCase() : '';
|
|
37
32
|
const value = list[i + 1];
|
|
38
33
|
if (label === 'TEXT' && value && value.type === 'LITERAL') {
|
|
39
34
|
parts.push({ text: value.value });
|
|
40
|
-
}
|
|
35
|
+
}
|
|
36
|
+
else if (label === 'URL' && value && ['ATOM', 'STRING', 'LITERAL'].indexOf(value.type) >= 0) {
|
|
41
37
|
parts.push({ url: value.value });
|
|
42
|
-
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
43
40
|
throw badArgument('Invalid CATENATE part ' + (i / 2 + 1));
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
|
-
|
|
47
43
|
// the message is built once the target mailbox is known to exist
|
|
48
44
|
return () => {
|
|
49
45
|
const maxSize = connection.getMaxLiteralSize();
|
|
@@ -58,15 +54,12 @@ module.exports = function (server) {
|
|
|
58
54
|
return raw;
|
|
59
55
|
};
|
|
60
56
|
};
|
|
61
|
-
}
|
|
62
|
-
|
|
57
|
+
}
|
|
63
58
|
// RFC 5092 section 11: bchar (achar / ":" / "@" / "/"), and ";" that starts the URL parameters
|
|
64
59
|
const URL_CHARS = /^[A-Za-z0-9\-._~!$'()*+,&=:@/;%]*$/;
|
|
65
|
-
|
|
66
60
|
// RFC 5092 section 11: iabsolute-path = "/" imessagepart, where
|
|
67
61
|
// imessagepart = enc-mailbox [uidvalidity] iuid [isection] [ipartial] (URLAUTH is not supported)
|
|
68
62
|
const MESSAGE_PART = /^\/([^;]+?)(?:;UIDVALIDITY=([^/;]*))?\/;UID=([^/;]*)(?:\/;SECTION=([^/;]*))?(?:\/;PARTIAL=([^/;]*))?$/i;
|
|
69
|
-
|
|
70
63
|
/**
|
|
71
64
|
* Creates a BADURL error (RFC 4469 section 4.1). url-resp-text is any TEXT-CHAR except "]", so other
|
|
72
65
|
* octets of an invalid URL are percent-encoded
|
|
@@ -83,7 +76,6 @@ function badUrl(url, text) {
|
|
|
83
76
|
const value = url.replace(/[^\x20-\x5c\x5e-\x7e]/g, chr => '%' + chr.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0'));
|
|
84
77
|
return appendError(text, 'BADURL', [{ type: 'TEXT', value }]);
|
|
85
78
|
}
|
|
86
|
-
|
|
87
79
|
/**
|
|
88
80
|
* Removes "." and ".." segments from a path (RFC 3986 section 5.2.4), as relative IMAP URLs are
|
|
89
81
|
* resolved by the generic URI rules (RFC 5092 section 7)
|
|
@@ -109,7 +101,6 @@ function removeDotSegments(path) {
|
|
|
109
101
|
});
|
|
110
102
|
return '/' + output.join('/');
|
|
111
103
|
}
|
|
112
|
-
|
|
113
104
|
/**
|
|
114
105
|
* Decodes percent-encoded octets
|
|
115
106
|
*
|
|
@@ -119,7 +110,6 @@ function removeDotSegments(path) {
|
|
|
119
110
|
function percentDecode(value) {
|
|
120
111
|
return value.replace(/%([0-9a-f]{2})/gi, (match, hex) => String.fromCharCode(parseInt(hex, 16)));
|
|
121
112
|
}
|
|
122
|
-
|
|
123
113
|
/**
|
|
124
114
|
* Returns the octets of a message part as BODY.PEEK[<section>] would, or false if the section is
|
|
125
115
|
* invalid or the part does not exist
|
|
@@ -133,19 +123,18 @@ function getSection(connection, message, section) {
|
|
|
133
123
|
if (!section || !/^[\x20-\x7e]+$/.test(section)) {
|
|
134
124
|
return false;
|
|
135
125
|
}
|
|
136
|
-
|
|
137
126
|
// reuse the FETCH grammar for section-spec
|
|
138
127
|
let query;
|
|
139
128
|
try {
|
|
140
129
|
const parsed = imapHandler.parser('X FETCH 1 BODY.PEEK[' + section + ']');
|
|
141
130
|
query = parsed.attributes.length === 2 && !parsed.attributes[1].partial && parsed.attributes[1];
|
|
142
|
-
}
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
143
133
|
return false;
|
|
144
134
|
}
|
|
145
135
|
if (!query || !query.section || !query.section.length || query.section[0].type !== 'ATOM') {
|
|
146
136
|
return false;
|
|
147
137
|
}
|
|
148
|
-
|
|
149
138
|
// FETCH returns an empty string for a part that does not exist, a URL for it is invalid (RFC 4469 section 4.1)
|
|
150
139
|
const sectionId = String(query.section[0].value).toUpperCase();
|
|
151
140
|
const path = (sectionId.match(/^[1-9]\d*(?:\.[1-9]\d*)*/) || [''])[0];
|
|
@@ -157,14 +146,13 @@ function getSection(connection, message, section) {
|
|
|
157
146
|
return false;
|
|
158
147
|
}
|
|
159
148
|
}
|
|
160
|
-
|
|
161
149
|
try {
|
|
162
150
|
return fetchHandlers.BODY(connection, message, { section: query.section }).value;
|
|
163
|
-
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
164
153
|
return false;
|
|
165
154
|
}
|
|
166
155
|
}
|
|
167
|
-
|
|
168
156
|
/**
|
|
169
157
|
* Returns the octets an IMAP URL refers to. RFC 4469 section 3: only URLs of messages or message
|
|
170
158
|
* parts in the current session are supported, relative to "imap://user@server/". RFC 5092 section 7.2
|
|
@@ -187,31 +175,27 @@ function resolveUrl(connection, url) {
|
|
|
187
175
|
if (!URL_CHARS.test(url) || /%(?![0-9a-f]{2})/i.test(url)) {
|
|
188
176
|
throw badUrl(url, 'Invalid characters in URL');
|
|
189
177
|
}
|
|
190
|
-
|
|
191
178
|
const match = removeDotSegments(url).match(MESSAGE_PART);
|
|
192
179
|
if (!match) {
|
|
193
180
|
throw badUrl(url, 'URL does not refer to a message or a message part');
|
|
194
181
|
}
|
|
195
182
|
const [, encMailbox, uidvalidity, uid, encSection, partial] = match;
|
|
196
|
-
|
|
197
183
|
// RFC 5092 section 11: uidvalidity and iuid-only are nz-number values (32-bit, RFC 3501 section 9)
|
|
198
184
|
if ((uidvalidity !== undefined && !isNzNumber(uidvalidity)) || !isNzNumber(uid)) {
|
|
199
185
|
throw badUrl(url, 'Invalid UIDVALIDITY or UID in URL');
|
|
200
186
|
}
|
|
201
|
-
|
|
202
187
|
// RFC 5092 section 8: mailbox names are percent-encoded UTF-8
|
|
203
188
|
let name;
|
|
204
189
|
try {
|
|
205
190
|
name = new TextDecoder('utf-8', { fatal: true }).decode(Buffer.from(percentDecode(encMailbox), 'binary'));
|
|
206
|
-
}
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
207
193
|
throw badUrl(url, 'Mailbox name in URL is not valid UTF-8');
|
|
208
194
|
}
|
|
209
|
-
|
|
210
195
|
const mailbox = connection.server.getMailbox(encodeMailboxName(name));
|
|
211
196
|
if (!mailbox || mailbox.flags.indexOf('\\Noselect') >= 0) {
|
|
212
197
|
throw badUrl(url, 'Mailbox does not exist');
|
|
213
198
|
}
|
|
214
|
-
|
|
215
199
|
// plugins can refuse to read the mailbox, e.g. ACL without the "r" right
|
|
216
200
|
for (const check of connection.server.urlAccessChecks) {
|
|
217
201
|
const refusal = check(connection, mailbox, url);
|
|
@@ -219,17 +203,14 @@ function resolveUrl(connection, url) {
|
|
|
219
203
|
throw badUrl(url, refusal.text || 'Permission denied');
|
|
220
204
|
}
|
|
221
205
|
}
|
|
222
|
-
|
|
223
206
|
// RFC 5092 section 5: a stale URL behaves as if the mailbox does not exist
|
|
224
207
|
if (uidvalidity !== undefined && Number(uidvalidity) !== mailbox.uidvalidity) {
|
|
225
208
|
throw badUrl(url, 'UIDVALIDITY does not match');
|
|
226
209
|
}
|
|
227
|
-
|
|
228
|
-
const message = mailbox.messages.find(item => item.uid === Number(uid));
|
|
210
|
+
const message = mailbox.messages.find((item) => item.uid === Number(uid));
|
|
229
211
|
if (!message) {
|
|
230
212
|
throw badUrl(url, 'Message does not exist');
|
|
231
213
|
}
|
|
232
|
-
|
|
233
214
|
// RFC 5092 section 6: no section is the whole message, BODY.PEEK[], so \Seen is not set
|
|
234
215
|
let value = message.raw;
|
|
235
216
|
if (encSection !== undefined) {
|
|
@@ -238,7 +219,6 @@ function resolveUrl(connection, url) {
|
|
|
238
219
|
throw badUrl(url, 'Invalid section or the message part does not exist');
|
|
239
220
|
}
|
|
240
221
|
}
|
|
241
|
-
|
|
242
222
|
if (partial !== undefined) {
|
|
243
223
|
// RFC 5092 section 11: partial-range = number ["." nz-number], offset and length in octets, both 32-bit
|
|
244
224
|
// (RFC 3501 section 9)
|
|
@@ -248,6 +228,5 @@ function resolveUrl(connection, url) {
|
|
|
248
228
|
}
|
|
249
229
|
value = value.substr(Number(range[1]), range[2] ? Number(range[2]) : undefined);
|
|
250
230
|
}
|
|
251
|
-
|
|
252
231
|
return value;
|
|
253
232
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IMAPServer } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* @help Adds COMPRESS=DEFLATE [RFC4978] capability
|
|
4
|
+
* @help Raw DEFLATE in both directions after the tagged OK,
|
|
5
|
+
* @help every burst of responses ends with a sync flush
|
|
6
|
+
*/
|
|
7
|
+
export default function compressPlugin(server: IMAPServer): void;
|