imapkit 4.0.3 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -19
- package/bin/imapkit.js +12 -16
- package/dist/cjs/addressparser.d.ts +21 -0
- package/dist/cjs/addressparser.js +271 -0
- package/dist/cjs/arguments.d.ts +31 -0
- package/{lib → dist/cjs}/arguments.js +9 -21
- package/dist/cjs/bodystructure.d.ts +25 -0
- package/dist/cjs/bodystructure.js +150 -0
- package/dist/cjs/cert.d.ts +2 -0
- package/dist/cjs/cert.js +7 -0
- package/dist/cjs/command-states.d.ts +36 -0
- package/dist/cjs/command-states.js +102 -0
- package/dist/cjs/commands/append.d.ts +88 -0
- package/dist/cjs/commands/append.js +299 -0
- package/dist/cjs/commands/capability.d.ts +2 -0
- package/dist/cjs/commands/capability.js +44 -0
- package/dist/cjs/commands/check.d.ts +2 -0
- package/dist/cjs/commands/check.js +28 -0
- package/dist/cjs/commands/close.d.ts +2 -0
- package/dist/cjs/commands/close.js +35 -0
- package/dist/cjs/commands/copy.d.ts +30 -0
- package/dist/cjs/commands/copy.js +107 -0
- package/dist/cjs/commands/create.d.ts +2 -0
- package/dist/cjs/commands/create.js +53 -0
- package/dist/cjs/commands/delete.d.ts +2 -0
- package/dist/cjs/commands/delete.js +63 -0
- package/dist/cjs/commands/examine.d.ts +2 -0
- package/dist/cjs/commands/examine.js +19 -0
- package/dist/cjs/commands/expunge.d.ts +2 -0
- package/dist/cjs/commands/expunge.js +32 -0
- package/dist/cjs/commands/fetch.d.ts +23 -0
- package/dist/cjs/commands/fetch.js +208 -0
- package/dist/cjs/commands/handlers/fetch.d.ts +12 -0
- package/dist/cjs/commands/handlers/fetch.js +195 -0
- package/dist/cjs/commands/handlers/flags.d.ts +17 -0
- package/dist/cjs/commands/handlers/flags.js +39 -0
- package/dist/cjs/commands/handlers/search.d.ts +85 -0
- package/dist/cjs/commands/handlers/search.js +504 -0
- package/dist/cjs/commands/handlers/status.d.ts +34 -0
- package/dist/cjs/commands/handlers/status.js +81 -0
- package/dist/cjs/commands/handlers/store.d.ts +3 -0
- package/dist/cjs/commands/handlers/store.js +117 -0
- package/dist/cjs/commands/index.d.ts +2 -0
- package/dist/cjs/commands/index.js +61 -0
- package/dist/cjs/commands/list.d.ts +2 -0
- package/dist/cjs/commands/list.js +86 -0
- package/dist/cjs/commands/login.d.ts +2 -0
- package/dist/cjs/commands/login.js +62 -0
- package/dist/cjs/commands/logout.d.ts +2 -0
- package/dist/cjs/commands/logout.js +40 -0
- package/dist/cjs/commands/lsub.d.ts +2 -0
- package/dist/cjs/commands/lsub.js +79 -0
- package/dist/cjs/commands/noop.d.ts +2 -0
- package/dist/cjs/commands/noop.js +28 -0
- package/dist/cjs/commands/rename.d.ts +2 -0
- package/dist/cjs/commands/rename.js +98 -0
- package/dist/cjs/commands/search.d.ts +10 -0
- package/dist/cjs/commands/search.js +71 -0
- package/dist/cjs/commands/select.d.ts +19 -0
- package/dist/cjs/commands/select.js +230 -0
- package/dist/cjs/commands/status.d.ts +2 -0
- package/dist/cjs/commands/status.js +57 -0
- package/dist/cjs/commands/store.d.ts +10 -0
- package/dist/cjs/commands/store.js +134 -0
- package/dist/cjs/commands/subscribe.d.ts +2 -0
- package/dist/cjs/commands/subscribe.js +51 -0
- package/dist/cjs/commands/uid-copy.d.ts +2 -0
- package/dist/cjs/commands/uid-copy.js +19 -0
- package/dist/cjs/commands/uid-fetch.d.ts +3 -0
- package/dist/cjs/commands/uid-fetch.js +17 -0
- package/dist/cjs/commands/uid-search.d.ts +3 -0
- package/dist/cjs/commands/uid-search.js +17 -0
- package/dist/cjs/commands/uid-store.d.ts +3 -0
- package/dist/cjs/commands/uid-store.js +17 -0
- package/dist/cjs/commands/unsubscribe.d.ts +2 -0
- package/dist/cjs/commands/unsubscribe.js +50 -0
- package/dist/cjs/dates.d.ts +64 -0
- package/dist/cjs/dates.js +124 -0
- package/dist/cjs/deflate-layer.d.ts +83 -0
- package/dist/cjs/deflate-layer.js +232 -0
- package/dist/cjs/encoded-words.d.ts +15 -0
- package/dist/cjs/encoded-words.js +85 -0
- package/dist/cjs/envelope.d.ts +33 -0
- package/dist/cjs/envelope.js +86 -0
- package/dist/cjs/esearch.d.ts +96 -0
- package/dist/cjs/esearch.js +190 -0
- package/dist/cjs/framing.d.ts +66 -0
- package/{lib → dist/cjs}/framing.js +9 -26
- package/dist/cjs/index.d.ts +9 -0
- package/dist/cjs/index.js +56 -0
- package/dist/cjs/list-extensions.d.ts +50 -0
- package/dist/cjs/list-extensions.js +35 -0
- package/dist/cjs/load-plugins.d.ts +21 -0
- package/dist/cjs/load-plugins.js +89 -0
- package/dist/cjs/mailbox-name.d.ts +26 -0
- package/dist/cjs/mailbox-name.js +127 -0
- package/dist/cjs/mimeparser.d.ts +137 -0
- package/dist/cjs/mimeparser.js +727 -0
- package/dist/cjs/mock-client.d.ts +39 -0
- package/dist/cjs/mock-client.js +236 -0
- package/dist/cjs/numbers.d.ts +28 -0
- package/dist/cjs/numbers.js +52 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/plugins/acl.d.ts +2 -0
- package/dist/cjs/plugins/acl.js +888 -0
- package/dist/cjs/plugins/appendlimit.d.ts +16 -0
- package/dist/cjs/plugins/appendlimit.js +87 -0
- package/dist/cjs/plugins/auth-plain.d.ts +2 -0
- package/dist/cjs/plugins/auth-plain.js +89 -0
- package/dist/cjs/plugins/binary.d.ts +30 -0
- package/dist/cjs/plugins/binary.js +247 -0
- package/dist/cjs/plugins/catenate.d.ts +14 -0
- package/dist/cjs/plugins/catenate.js +250 -0
- package/dist/cjs/plugins/compress.d.ts +7 -0
- package/dist/cjs/plugins/compress.js +79 -0
- package/dist/cjs/plugins/condstore.d.ts +5 -0
- package/dist/cjs/plugins/condstore.js +492 -0
- package/dist/cjs/plugins/context-search.d.ts +8 -0
- package/dist/cjs/plugins/context-search.js +304 -0
- package/dist/cjs/plugins/context-sort.d.ts +6 -0
- package/dist/cjs/plugins/context-sort.js +32 -0
- package/dist/cjs/plugins/create-special-use.d.ts +7 -0
- package/dist/cjs/plugins/create-special-use.js +101 -0
- package/dist/cjs/plugins/enable.d.ts +23 -0
- package/dist/cjs/plugins/enable.js +127 -0
- package/dist/cjs/plugins/esearch.d.ts +6 -0
- package/dist/cjs/plugins/esearch.js +142 -0
- package/dist/cjs/plugins/esort.d.ts +6 -0
- package/dist/cjs/plugins/esort.js +60 -0
- package/dist/cjs/plugins/id.d.ts +5 -0
- package/dist/cjs/plugins/id.js +123 -0
- package/dist/cjs/plugins/idle.d.ts +5 -0
- package/dist/cjs/plugins/idle.js +85 -0
- package/dist/cjs/plugins/imap4rev2.d.ts +6 -0
- package/dist/cjs/plugins/imap4rev2.js +184 -0
- package/dist/cjs/plugins/index.d.ts +2 -0
- package/dist/cjs/plugins/index.js +119 -0
- package/dist/cjs/plugins/list-extended.d.ts +2 -0
- package/dist/cjs/plugins/list-extended.js +235 -0
- package/dist/cjs/plugins/list-status.d.ts +6 -0
- package/dist/cjs/plugins/list-status.js +42 -0
- package/dist/cjs/plugins/literalminus.d.ts +8 -0
- package/dist/cjs/plugins/literalminus.js +32 -0
- package/dist/cjs/plugins/literalplus.d.ts +6 -0
- package/dist/cjs/plugins/literalplus.js +30 -0
- package/dist/cjs/plugins/logindisabled.d.ts +5 -0
- package/dist/cjs/plugins/logindisabled.js +54 -0
- package/dist/cjs/plugins/messagelimit.d.ts +19 -0
- package/dist/cjs/plugins/messagelimit.js +227 -0
- package/dist/cjs/plugins/metadata-server.d.ts +7 -0
- package/dist/cjs/plugins/metadata-server.js +24 -0
- package/dist/cjs/plugins/metadata.d.ts +11 -0
- package/dist/cjs/plugins/metadata.js +436 -0
- package/dist/cjs/plugins/move.d.ts +11 -0
- package/dist/cjs/plugins/move.js +96 -0
- package/dist/cjs/plugins/multiappend.d.ts +12 -0
- package/dist/cjs/plugins/multiappend.js +38 -0
- package/dist/cjs/plugins/multisearch.d.ts +6 -0
- package/dist/cjs/plugins/multisearch.js +263 -0
- package/dist/cjs/plugins/namespace.d.ts +5 -0
- package/dist/cjs/plugins/namespace.js +57 -0
- package/dist/cjs/plugins/notify.d.ts +2 -0
- package/dist/cjs/plugins/notify.js +628 -0
- package/dist/cjs/plugins/oauthbearer.d.ts +32 -0
- package/dist/cjs/plugins/oauthbearer.js +202 -0
- package/dist/cjs/plugins/objectid.d.ts +23 -0
- package/dist/cjs/plugins/objectid.js +221 -0
- package/dist/cjs/plugins/partial.d.ts +6 -0
- package/dist/cjs/plugins/partial.js +78 -0
- package/dist/cjs/plugins/preview.d.ts +31 -0
- package/dist/cjs/plugins/preview.js +378 -0
- package/dist/cjs/plugins/qresync.d.ts +11 -0
- package/dist/cjs/plugins/qresync.js +473 -0
- package/dist/cjs/plugins/quota.d.ts +18 -0
- package/dist/cjs/plugins/quota.js +254 -0
- package/dist/cjs/plugins/replace.d.ts +14 -0
- package/dist/cjs/plugins/replace.js +130 -0
- package/dist/cjs/plugins/sasl-ir.d.ts +5 -0
- package/dist/cjs/plugins/sasl-ir.js +24 -0
- package/dist/cjs/plugins/savedate.d.ts +17 -0
- package/dist/cjs/plugins/savedate.js +64 -0
- package/dist/cjs/plugins/savelimit.d.ts +10 -0
- package/dist/cjs/plugins/savelimit.js +30 -0
- package/dist/cjs/plugins/searchres.d.ts +6 -0
- package/dist/cjs/plugins/searchres.js +91 -0
- package/dist/cjs/plugins/sort-display.d.ts +11 -0
- package/dist/cjs/plugins/sort-display.js +37 -0
- package/dist/cjs/plugins/sort.d.ts +11 -0
- package/dist/cjs/plugins/sort.js +125 -0
- package/dist/cjs/plugins/special-use.d.ts +10 -0
- package/dist/cjs/plugins/special-use.js +95 -0
- package/dist/cjs/plugins/starttls.d.ts +5 -0
- package/dist/cjs/plugins/starttls.js +55 -0
- package/dist/cjs/plugins/status-size.d.ts +7 -0
- package/dist/cjs/plugins/status-size.js +30 -0
- package/dist/cjs/plugins/thread-orderedsubject.d.ts +11 -0
- package/dist/cjs/plugins/thread-orderedsubject.js +28 -0
- package/dist/cjs/plugins/thread-references.d.ts +11 -0
- package/dist/cjs/plugins/thread-references.js +28 -0
- package/dist/cjs/plugins/uidonly.d.ts +15 -0
- package/dist/cjs/plugins/uidonly.js +126 -0
- package/dist/cjs/plugins/uidplus.d.ts +15 -0
- package/dist/cjs/plugins/uidplus.js +119 -0
- package/dist/cjs/plugins/unauthenticate.d.ts +7 -0
- package/dist/cjs/plugins/unauthenticate.js +32 -0
- package/dist/cjs/plugins/unselect.d.ts +5 -0
- package/dist/cjs/plugins/unselect.js +36 -0
- package/dist/cjs/plugins/utf8-accept.d.ts +6 -0
- package/dist/cjs/plugins/utf8-accept.js +72 -0
- package/dist/cjs/plugins/x-gm-ext-1.d.ts +26 -0
- package/dist/cjs/plugins/x-gm-ext-1.js +422 -0
- package/dist/cjs/plugins/xoauth2.d.ts +2 -0
- package/dist/cjs/plugins/xoauth2.js +155 -0
- package/dist/cjs/plugins/xtoybird.d.ts +2 -0
- package/dist/cjs/plugins/xtoybird.js +236 -0
- package/dist/cjs/server.d.ts +876 -0
- package/dist/cjs/server.js +2597 -0
- package/dist/cjs/smtp-listener.d.ts +13 -0
- package/dist/cjs/smtp-listener.js +47 -0
- package/dist/cjs/sorting.d.ts +77 -0
- package/dist/cjs/sorting.js +290 -0
- package/dist/cjs/threading.d.ts +30 -0
- package/dist/cjs/threading.js +318 -0
- package/dist/cjs/types.d.ts +327 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/utf8-session.d.ts +17 -0
- package/dist/cjs/utf8-session.js +148 -0
- package/dist/cjs/vanished.d.ts +21 -0
- package/dist/cjs/vanished.js +55 -0
- package/dist/esm/addressparser.d.ts +21 -0
- package/{lib → dist/esm}/addressparser.js +106 -133
- package/dist/esm/arguments.d.ts +31 -0
- package/dist/esm/arguments.js +96 -0
- package/dist/esm/bodystructure.d.ts +25 -0
- package/{lib → dist/esm}/bodystructure.js +17 -33
- package/dist/esm/cert.d.ts +2 -0
- package/dist/esm/cert.js +4 -0
- package/dist/esm/command-states.d.ts +36 -0
- package/{lib → dist/esm}/command-states.js +4 -16
- package/dist/esm/commands/append.d.ts +88 -0
- package/{lib → dist/esm}/commands/append.js +47 -85
- package/dist/esm/commands/capability.d.ts +2 -0
- package/dist/esm/commands/capability.js +29 -0
- package/dist/esm/commands/check.d.ts +2 -0
- package/dist/esm/commands/check.js +13 -0
- package/dist/esm/commands/close.d.ts +2 -0
- package/dist/esm/commands/close.js +20 -0
- package/dist/esm/commands/copy.d.ts +30 -0
- package/{lib → dist/esm}/commands/copy.js +31 -55
- package/dist/esm/commands/create.d.ts +2 -0
- package/{lib → dist/esm}/commands/create.js +25 -39
- package/dist/esm/commands/delete.d.ts +2 -0
- package/{lib → dist/esm}/commands/delete.js +25 -41
- package/dist/esm/commands/examine.d.ts +2 -0
- package/dist/esm/commands/examine.js +4 -0
- package/dist/esm/commands/expunge.d.ts +2 -0
- package/dist/esm/commands/expunge.js +17 -0
- package/dist/esm/commands/fetch.d.ts +23 -0
- package/{lib → dist/esm}/commands/fetch.js +33 -74
- package/dist/esm/commands/handlers/fetch.d.ts +12 -0
- package/{lib → dist/esm}/commands/handlers/fetch.js +11 -42
- package/dist/esm/commands/handlers/flags.d.ts +17 -0
- package/{lib → dist/esm}/commands/handlers/flags.js +3 -11
- package/dist/esm/commands/handlers/search.d.ts +85 -0
- package/{lib → dist/esm}/commands/handlers/search.js +33 -71
- package/dist/esm/commands/handlers/status.d.ts +34 -0
- package/{lib → dist/esm}/commands/handlers/status.js +1 -9
- package/dist/esm/commands/handlers/store.d.ts +3 -0
- package/{lib → dist/esm}/commands/handlers/store.js +20 -44
- package/dist/esm/commands/index.d.ts +2 -0
- package/dist/esm/commands/index.js +55 -0
- package/dist/esm/commands/list.d.ts +2 -0
- package/dist/esm/commands/list.js +71 -0
- package/dist/esm/commands/login.d.ts +2 -0
- package/{lib → dist/esm}/commands/login.js +24 -44
- package/dist/esm/commands/logout.d.ts +2 -0
- package/dist/esm/commands/logout.js +25 -0
- package/dist/esm/commands/lsub.d.ts +2 -0
- package/dist/esm/commands/lsub.js +64 -0
- package/dist/esm/commands/noop.d.ts +2 -0
- package/dist/esm/commands/noop.js +13 -0
- package/dist/esm/commands/rename.d.ts +2 -0
- package/{lib → dist/esm}/commands/rename.js +32 -51
- package/dist/esm/commands/search.d.ts +10 -0
- package/dist/esm/commands/search.js +54 -0
- package/dist/esm/commands/select.d.ts +19 -0
- package/dist/esm/commands/select.js +214 -0
- package/dist/esm/commands/status.d.ts +2 -0
- package/{lib → dist/esm}/commands/status.js +18 -39
- package/dist/esm/commands/store.d.ts +10 -0
- package/{lib → dist/esm}/commands/store.js +39 -73
- package/dist/esm/commands/subscribe.d.ts +2 -0
- package/{lib → dist/esm}/commands/subscribe.js +22 -39
- package/dist/esm/commands/uid-copy.d.ts +2 -0
- package/dist/esm/commands/uid-copy.js +4 -0
- package/dist/esm/commands/uid-fetch.d.ts +3 -0
- package/dist/esm/commands/uid-fetch.js +3 -0
- package/dist/esm/commands/uid-search.d.ts +3 -0
- package/dist/esm/commands/uid-search.js +3 -0
- package/dist/esm/commands/uid-store.d.ts +3 -0
- package/dist/esm/commands/uid-store.js +3 -0
- package/dist/esm/commands/unsubscribe.d.ts +2 -0
- package/{lib → dist/esm}/commands/unsubscribe.js +22 -37
- package/dist/esm/dates.d.ts +64 -0
- package/{lib → dist/esm}/dates.js +6 -14
- package/dist/esm/deflate-layer.d.ts +83 -0
- package/{lib → dist/esm}/deflate-layer.js +9 -26
- package/dist/esm/encoded-words.d.ts +15 -0
- package/{lib → dist/esm}/encoded-words.js +9 -25
- package/dist/esm/envelope.d.ts +33 -0
- package/{lib → dist/esm}/envelope.js +8 -19
- package/dist/esm/esearch.d.ts +96 -0
- package/{lib → dist/esm}/esearch.js +12 -39
- package/dist/esm/framing.d.ts +66 -0
- package/dist/esm/framing.js +82 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/list-extensions.d.ts +50 -0
- package/{lib → dist/esm}/list-extensions.js +1 -4
- package/dist/esm/load-plugins.d.ts +21 -0
- package/{lib → dist/esm}/load-plugins.js +9 -43
- package/dist/esm/mailbox-name.d.ts +26 -0
- package/{lib → dist/esm}/mailbox-name.js +5 -26
- package/dist/esm/mimeparser.d.ts +137 -0
- package/{lib → dist/esm}/mimeparser.js +74 -152
- package/dist/esm/mock-client.d.ts +39 -0
- package/{lib → dist/esm}/mock-client.js +26 -40
- package/dist/esm/numbers.d.ts +28 -0
- package/{lib → dist/esm}/numbers.js +1 -8
- package/dist/esm/package.json +3 -0
- package/dist/esm/plugins/acl.d.ts +2 -0
- package/{lib → dist/esm}/plugins/acl.js +146 -240
- package/dist/esm/plugins/appendlimit.d.ts +16 -0
- package/{lib → dist/esm}/plugins/appendlimit.js +5 -16
- package/dist/esm/plugins/auth-plain.d.ts +2 -0
- package/{lib → dist/esm}/plugins/auth-plain.js +11 -31
- package/dist/esm/plugins/binary.d.ts +30 -0
- package/{lib → dist/esm}/plugins/binary.js +17 -43
- package/dist/esm/plugins/catenate.d.ts +14 -0
- package/{lib → dist/esm}/plugins/catenate.js +19 -40
- package/dist/esm/plugins/compress.d.ts +7 -0
- package/dist/esm/plugins/compress.js +61 -0
- package/dist/esm/plugins/condstore.d.ts +5 -0
- package/{lib → dist/esm}/plugins/condstore.js +66 -152
- package/dist/esm/plugins/context-search.d.ts +8 -0
- package/{lib → dist/esm}/plugins/context-search.js +53 -88
- package/dist/esm/plugins/context-sort.d.ts +6 -0
- package/{lib → dist/esm}/plugins/context-sort.js +4 -9
- package/dist/esm/plugins/create-special-use.d.ts +7 -0
- package/{lib → dist/esm}/plugins/create-special-use.js +33 -55
- package/dist/esm/plugins/enable.d.ts +23 -0
- package/dist/esm/plugins/enable.js +111 -0
- package/dist/esm/plugins/esearch.d.ts +6 -0
- package/{lib → dist/esm}/plugins/esearch.js +13 -42
- package/dist/esm/plugins/esort.d.ts +6 -0
- package/{lib → dist/esm}/plugins/esort.js +7 -25
- package/dist/esm/plugins/id.d.ts +5 -0
- package/dist/esm/plugins/id.js +108 -0
- package/dist/esm/plugins/idle.d.ts +5 -0
- package/dist/esm/plugins/idle.js +70 -0
- package/dist/esm/plugins/imap4rev2.d.ts +6 -0
- package/{lib → dist/esm}/plugins/imap4rev2.js +24 -60
- package/dist/esm/plugins/index.d.ts +2 -0
- package/dist/esm/plugins/index.js +113 -0
- package/dist/esm/plugins/list-extended.d.ts +2 -0
- package/{lib → dist/esm}/plugins/list-extended.js +28 -66
- package/dist/esm/plugins/list-status.d.ts +6 -0
- package/{lib → dist/esm}/plugins/list-status.js +5 -12
- package/dist/esm/plugins/literalminus.d.ts +8 -0
- package/{lib → dist/esm}/plugins/literalminus.js +2 -5
- package/dist/esm/plugins/literalplus.d.ts +6 -0
- package/{lib → dist/esm}/plugins/literalplus.js +2 -5
- package/dist/esm/plugins/logindisabled.d.ts +5 -0
- package/dist/esm/plugins/logindisabled.js +39 -0
- package/dist/esm/plugins/messagelimit.d.ts +19 -0
- package/{lib → dist/esm}/plugins/messagelimit.js +18 -41
- package/dist/esm/plugins/metadata-server.d.ts +7 -0
- package/{lib → dist/esm}/plugins/metadata-server.js +3 -7
- package/dist/esm/plugins/metadata.d.ts +11 -0
- package/dist/esm/plugins/metadata.js +421 -0
- package/dist/esm/plugins/move.d.ts +11 -0
- package/{lib → dist/esm}/plugins/move.js +37 -66
- package/dist/esm/plugins/multiappend.d.ts +12 -0
- package/{lib → dist/esm}/plugins/multiappend.js +2 -5
- package/dist/esm/plugins/multisearch.d.ts +6 -0
- package/{lib → dist/esm}/plugins/multisearch.js +24 -48
- package/dist/esm/plugins/namespace.d.ts +5 -0
- package/dist/esm/plugins/namespace.js +42 -0
- package/dist/esm/plugins/notify.d.ts +2 -0
- package/{lib → dist/esm}/plugins/notify.js +90 -134
- package/dist/esm/plugins/oauthbearer.d.ts +32 -0
- package/{lib → dist/esm}/plugins/oauthbearer.js +18 -48
- package/dist/esm/plugins/objectid.d.ts +23 -0
- package/{lib → dist/esm}/plugins/objectid.js +21 -58
- package/dist/esm/plugins/partial.d.ts +6 -0
- package/{lib → dist/esm}/plugins/partial.js +7 -15
- package/dist/esm/plugins/preview.d.ts +31 -0
- package/{lib → dist/esm}/plugins/preview.js +28 -66
- package/dist/esm/plugins/qresync.d.ts +11 -0
- package/{lib → dist/esm}/plugins/qresync.js +64 -134
- package/dist/esm/plugins/quota.d.ts +18 -0
- package/{lib → dist/esm}/plugins/quota.js +89 -135
- package/dist/esm/plugins/replace.d.ts +14 -0
- package/{lib → dist/esm}/plugins/replace.js +21 -51
- package/dist/esm/plugins/sasl-ir.d.ts +5 -0
- package/{lib → dist/esm}/plugins/sasl-ir.js +3 -6
- package/dist/esm/plugins/savedate.d.ts +17 -0
- package/{lib → dist/esm}/plugins/savedate.js +5 -15
- package/dist/esm/plugins/savelimit.d.ts +10 -0
- package/{lib → dist/esm}/plugins/savelimit.js +3 -6
- package/dist/esm/plugins/searchres.d.ts +6 -0
- package/{lib → dist/esm}/plugins/searchres.js +13 -22
- package/dist/esm/plugins/sort-display.d.ts +11 -0
- package/{lib → dist/esm}/plugins/sort-display.js +6 -10
- package/dist/esm/plugins/sort.d.ts +11 -0
- package/{lib → dist/esm}/plugins/sort.js +24 -46
- package/dist/esm/plugins/special-use.d.ts +10 -0
- package/{lib → dist/esm}/plugins/special-use.js +9 -24
- package/dist/esm/plugins/starttls.d.ts +5 -0
- package/{lib → dist/esm}/plugins/starttls.js +20 -37
- package/dist/esm/plugins/status-size.d.ts +7 -0
- package/{lib → dist/esm}/plugins/status-size.js +4 -11
- package/dist/esm/plugins/thread-orderedsubject.d.ts +11 -0
- package/{lib → dist/esm}/plugins/thread-orderedsubject.js +3 -6
- package/dist/esm/plugins/thread-references.d.ts +11 -0
- package/{lib → dist/esm}/plugins/thread-references.js +3 -6
- package/dist/esm/plugins/uidonly.d.ts +15 -0
- package/{lib → dist/esm}/plugins/uidonly.js +11 -35
- package/dist/esm/plugins/uidplus.d.ts +15 -0
- package/{lib → dist/esm}/plugins/uidplus.js +25 -45
- package/dist/esm/plugins/unauthenticate.d.ts +7 -0
- package/dist/esm/plugins/unauthenticate.js +17 -0
- package/dist/esm/plugins/unselect.d.ts +5 -0
- package/dist/esm/plugins/unselect.js +21 -0
- package/dist/esm/plugins/utf8-accept.d.ts +6 -0
- package/{lib → dist/esm}/plugins/utf8-accept.js +10 -21
- package/dist/esm/plugins/x-gm-ext-1.d.ts +26 -0
- package/{lib → dist/esm}/plugins/x-gm-ext-1.js +48 -100
- package/dist/esm/plugins/xoauth2.d.ts +2 -0
- package/dist/esm/plugins/xoauth2.js +140 -0
- package/dist/esm/plugins/xtoybird.d.ts +2 -0
- package/dist/esm/plugins/xtoybird.js +218 -0
- package/dist/esm/server.d.ts +876 -0
- package/dist/esm/server.js +2543 -0
- package/dist/esm/smtp-listener.d.ts +13 -0
- package/{lib → dist/esm}/smtp-listener.js +5 -12
- package/dist/esm/sorting.d.ts +77 -0
- package/{lib → dist/esm}/sorting.js +40 -53
- package/dist/esm/threading.d.ts +30 -0
- package/{lib → dist/esm}/threading.js +29 -70
- package/dist/esm/types.d.ts +327 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/utf8-session.d.ts +17 -0
- package/{lib → dist/esm}/utf8-session.js +15 -25
- package/dist/esm/vanished.d.ts +21 -0
- package/{lib → dist/esm}/vanished.js +16 -21
- package/dist/plugin-help.json +298 -0
- package/package.json +55 -12
- package/lib/commands/capability.js +0 -47
- package/lib/commands/check.js +0 -21
- package/lib/commands/close.js +0 -30
- package/lib/commands/examine.js +0 -7
- package/lib/commands/expunge.js +0 -27
- package/lib/commands/list.js +0 -100
- package/lib/commands/logout.js +0 -41
- package/lib/commands/lsub.js +0 -87
- package/lib/commands/noop.js +0 -21
- package/lib/commands/search.js +0 -76
- package/lib/commands/select.js +0 -289
- package/lib/commands/uid copy.js +0 -7
- package/lib/commands/uid fetch.js +0 -5
- package/lib/commands/uid search.js +0 -5
- package/lib/commands/uid store.js +0 -5
- package/lib/plugins/compress.js +0 -76
- package/lib/plugins/enable.js +0 -155
- package/lib/plugins/id.js +0 -138
- package/lib/plugins/idle.js +0 -105
- package/lib/plugins/logindisabled.js +0 -50
- package/lib/plugins/metadata.js +0 -475
- package/lib/plugins/namespace.js +0 -67
- package/lib/plugins/unauthenticate.js +0 -28
- package/lib/plugins/unselect.js +0 -36
- package/lib/plugins/xoauth2.js +0 -188
- package/lib/plugins/xtoybird.js +0 -282
- package/lib/server.js +0 -2880
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Parses a message into a MIME tree. Ported from WildDuck (imap-core/lib/indexer/parse-mime-tree.js and
|
|
3
|
+
// tree-walker.js), adapted to ImapKit, where message sources are binary strings (one char per octet).
|
|
4
|
+
//
|
|
5
|
+
// The tree describes the message exactly, so every section a client can FETCH is rendered from it:
|
|
6
|
+
//
|
|
7
|
+
// entity = header-lines [ CRLF body ] ; "CRLF body" present unless hasBody is false
|
|
8
|
+
// body = bytes | preamble *( delimiter entity CRLF ) close-delimiter epilogue
|
|
9
|
+
// delimiter = "--" boundary pad CRLF
|
|
10
|
+
//
|
|
11
|
+
// The CRLF after an entity belongs to the delimiter that follows it (RFC 2046 5.1.1), a part body never
|
|
12
|
+
// includes it.
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.IDENTITY_ENCODINGS = void 0;
|
|
18
|
+
exports.default = mimeparser;
|
|
19
|
+
exports.parseTree = parseTree;
|
|
20
|
+
exports.getMessageData = getMessageData;
|
|
21
|
+
exports.normalizeLineBreaks = normalizeLineBreaks;
|
|
22
|
+
exports.partsOf = partsOf;
|
|
23
|
+
exports.resolveNode = resolveNode;
|
|
24
|
+
exports.embeddedMessage = embeddedMessage;
|
|
25
|
+
exports.headerSection = headerSection;
|
|
26
|
+
exports.render = render;
|
|
27
|
+
const addressparser_js_1 = __importDefault(require("./addressparser.js"));
|
|
28
|
+
// header field and parameter names that are kept in the parsed header, anything else is only available
|
|
29
|
+
// through the raw header lines
|
|
30
|
+
const FIELD_NAME = /^[a-zA-Z0-9\-*]{1,99}$/;
|
|
31
|
+
// content transfer encodings that leave the data as it is (RFC 2045 section 6.2)
|
|
32
|
+
const IDENTITY_ENCODINGS = ['7bit', '8bit', 'binary'];
|
|
33
|
+
exports.IDENTITY_ENCODINGS = IDENTITY_ENCODINGS;
|
|
34
|
+
// message/rfc822 parts nested deeper than this are not parsed, they are described as plain parts
|
|
35
|
+
const MAX_MESSAGE_DEPTH = 32;
|
|
36
|
+
/**
|
|
37
|
+
* Converts every line break of a message to CRLF. IMAP serves messages with CRLF line breaks, so sizes and
|
|
38
|
+
* contents are computed from this form
|
|
39
|
+
*
|
|
40
|
+
* @param {String} raw Message source as a binary string
|
|
41
|
+
* @return {String} Message source with CRLF line breaks
|
|
42
|
+
*/
|
|
43
|
+
function normalizeLineBreaks(raw) {
|
|
44
|
+
const str = Buffer.isBuffer(raw) ? raw.toString('binary') : raw || '';
|
|
45
|
+
// most messages already use CRLF, so only replace if there is a bare LF
|
|
46
|
+
return /(?:^|[^\r])\n/.test(str) ? str.replace(/\r?\n/g, '\r\n') : str;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Splits a structured header value (RFC 2045 5.1 Content-Type and friends) at a separator character,
|
|
50
|
+
* leaving quoted strings intact and dropping RFC 822 comments outside of them. With no separator the
|
|
51
|
+
* whole value comes back as one part with its comments removed.
|
|
52
|
+
*
|
|
53
|
+
* @param {String} value Header value
|
|
54
|
+
* @param {String} [separator] Character to split at, outside quotes and comments
|
|
55
|
+
* @returns {Array} Parts
|
|
56
|
+
*/
|
|
57
|
+
function splitStructuredValue(value, separator) {
|
|
58
|
+
const parts = [];
|
|
59
|
+
let current = '';
|
|
60
|
+
let quoted = false;
|
|
61
|
+
let depth = 0;
|
|
62
|
+
for (let i = 0; i < value.length; i++) {
|
|
63
|
+
const chr = value.charAt(i);
|
|
64
|
+
if (quoted) {
|
|
65
|
+
current += chr;
|
|
66
|
+
if (chr === '\\' && i + 1 < value.length) {
|
|
67
|
+
// quoted-pair, keep the escaped character for the value parser
|
|
68
|
+
current += value.charAt(++i);
|
|
69
|
+
}
|
|
70
|
+
else if (chr === '"') {
|
|
71
|
+
quoted = false;
|
|
72
|
+
}
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (depth) {
|
|
76
|
+
// inside a comment, which may nest and may hold quoted-pairs
|
|
77
|
+
if (chr === '\\') {
|
|
78
|
+
i++;
|
|
79
|
+
}
|
|
80
|
+
else if (chr === '(') {
|
|
81
|
+
depth++;
|
|
82
|
+
}
|
|
83
|
+
else if (chr === ')') {
|
|
84
|
+
depth--;
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (chr === '"') {
|
|
89
|
+
quoted = true;
|
|
90
|
+
current += chr;
|
|
91
|
+
}
|
|
92
|
+
else if (chr === '(') {
|
|
93
|
+
depth = 1;
|
|
94
|
+
}
|
|
95
|
+
else if (separator && chr === separator) {
|
|
96
|
+
parts.push(current);
|
|
97
|
+
current = '';
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
current += chr;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
parts.push(current);
|
|
104
|
+
return parts;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Decodes an RFC 2231 extended parameter value (percent encoded octets in a charset). UTF-8 and US-ASCII
|
|
108
|
+
* values become the UTF-8 octets, ISO-8859-1 values are converted to UTF-8, other charsets are kept as
|
|
109
|
+
* an RFC 2047 encoded word
|
|
110
|
+
*
|
|
111
|
+
* @param {String} charset Charset name from the first segment
|
|
112
|
+
* @param {String} value Percent encoded octets
|
|
113
|
+
* @return {String} Decoded value as a binary string
|
|
114
|
+
*/
|
|
115
|
+
function decodeExtendedValue(charset, value) {
|
|
116
|
+
const octets = value.replace(/%([0-9a-fA-F]{2})/g, (match, hex) => String.fromCharCode(parseInt(hex, 16)));
|
|
117
|
+
switch ((charset || '').trim().toLowerCase()) {
|
|
118
|
+
case '':
|
|
119
|
+
case 'utf-8':
|
|
120
|
+
case 'utf8':
|
|
121
|
+
case 'us-ascii':
|
|
122
|
+
case 'ascii':
|
|
123
|
+
return octets;
|
|
124
|
+
case 'iso-8859-1':
|
|
125
|
+
case 'latin1':
|
|
126
|
+
// every char of the binary string is an ISO-8859-1 character
|
|
127
|
+
return Buffer.from(octets, 'utf-8').toString('binary');
|
|
128
|
+
default:
|
|
129
|
+
return '=?' + charset.toUpperCase() + '?Q?' + value.replace(/%/g, '=') + '?=';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
class MIMEParser {
|
|
133
|
+
/**
|
|
134
|
+
* @param {String} rfc822 Message source as a binary string with CRLF line breaks
|
|
135
|
+
* @param {Number} [depth] How many message/rfc822 levels this message is nested in
|
|
136
|
+
*/
|
|
137
|
+
constructor(rfc822, depth) {
|
|
138
|
+
this.rfc822 = rfc822 || '';
|
|
139
|
+
this.depth = depth || 0;
|
|
140
|
+
// the line break that ended the last line read, false once the input is used up
|
|
141
|
+
this._br = '';
|
|
142
|
+
this._pos = 0;
|
|
143
|
+
this.tree = {
|
|
144
|
+
childNodes: []
|
|
145
|
+
};
|
|
146
|
+
this._node = this.createNode(this.tree);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Parses the message, line by line
|
|
150
|
+
*/
|
|
151
|
+
parse() {
|
|
152
|
+
let line;
|
|
153
|
+
let prevBr = '';
|
|
154
|
+
// keep parsing until the last linebreak is not a string (no linebreaks anymore)
|
|
155
|
+
while (typeof this._br === 'string') {
|
|
156
|
+
line = this.readLine();
|
|
157
|
+
const delimiter = this.matchDelimiter(line);
|
|
158
|
+
if (delimiter) {
|
|
159
|
+
this.endPart(delimiter, prevBr);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
switch (this._node.state) {
|
|
163
|
+
case 'header':
|
|
164
|
+
if (!line) {
|
|
165
|
+
// the blank line that separates the header from the body
|
|
166
|
+
this.endHeader();
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
this._node.header.push(line);
|
|
170
|
+
}
|
|
171
|
+
break;
|
|
172
|
+
case 'body':
|
|
173
|
+
// push the line with previous linebreak value, joined together the lines
|
|
174
|
+
// give the original body
|
|
175
|
+
this._node.body.push((this._node.body.length ? prevBr : '') + line);
|
|
176
|
+
break;
|
|
177
|
+
case 'epilogue':
|
|
178
|
+
// RFC 2046 5.1.1: everything after the close delimiter up to the next delimiter
|
|
179
|
+
// of the enclosing multipart (or the end of the message) is the epilogue. Every
|
|
180
|
+
// epilogue line keeps the line break that precedes it, the first one being the
|
|
181
|
+
// line break that ends the close delimiter line
|
|
182
|
+
if (!this._node.epilogue) {
|
|
183
|
+
this._node.epilogue = [];
|
|
184
|
+
}
|
|
185
|
+
this._node.epilogue.push(prevBr + line);
|
|
186
|
+
break;
|
|
187
|
+
default:
|
|
188
|
+
// never should be reached
|
|
189
|
+
throw new Error('Unexpected state');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// store the linebreak for later usage
|
|
193
|
+
prevBr = this._br;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Reads a line from the message
|
|
198
|
+
*
|
|
199
|
+
* @return {String} The line, without its line break
|
|
200
|
+
*/
|
|
201
|
+
readLine() {
|
|
202
|
+
const end = this.rfc822.indexOf('\n', this._pos);
|
|
203
|
+
if (end < 0) {
|
|
204
|
+
// the remainder, which is empty when the input ended with a line break
|
|
205
|
+
const line = this.rfc822.slice(this._pos);
|
|
206
|
+
this._pos = this.rfc822.length;
|
|
207
|
+
this._br = false;
|
|
208
|
+
return line;
|
|
209
|
+
}
|
|
210
|
+
let lineEnd = end;
|
|
211
|
+
if (lineEnd > this._pos && this.rfc822.charCodeAt(lineEnd - 1) === 0x0d) {
|
|
212
|
+
lineEnd--;
|
|
213
|
+
}
|
|
214
|
+
const line = this.rfc822.slice(this._pos, lineEnd);
|
|
215
|
+
this._br = this.rfc822.slice(lineEnd, end + 1);
|
|
216
|
+
this._pos = end + 1;
|
|
217
|
+
return line;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Ends the header of the current node: its blank line was read, or a delimiter took its place
|
|
221
|
+
*/
|
|
222
|
+
endHeader() {
|
|
223
|
+
this.processNodeHeader();
|
|
224
|
+
this.processContentType();
|
|
225
|
+
this._node.state = 'body';
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Checks whether a line is a delimiter of an open multipart: the current node while it collects its
|
|
229
|
+
* preamble or epilogue, the multipart the current node belongs to, or any multipart above that (a
|
|
230
|
+
* lost close delimiter leaves the inner multipart open, the enclosing delimiter still ends it).
|
|
231
|
+
* RFC 2046 5.1.1: `--boundary` or `--boundary--`, optionally followed by transport padding (spaces
|
|
232
|
+
* and tabs) that receivers must accept. After the close delimiter, lines that look like the own
|
|
233
|
+
* delimiter are epilogue text.
|
|
234
|
+
*
|
|
235
|
+
* @param {String} line Line of the message
|
|
236
|
+
* @return {Object|Boolean} `{ multipart, close, pad }`, or false when the line is not a delimiter
|
|
237
|
+
*/
|
|
238
|
+
matchDelimiter(line) {
|
|
239
|
+
if (!line.startsWith('--')) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
const node = this._node;
|
|
243
|
+
// a boundary is only known once the header has ended
|
|
244
|
+
const innermost = node.boundary ? node : node.parentNode;
|
|
245
|
+
for (let multipart = innermost; multipart.boundary; multipart = multipart.parentNode) {
|
|
246
|
+
const delimiter = '--' + multipart.boundary;
|
|
247
|
+
if (!line.startsWith(delimiter)) {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
let rest = line.slice(delimiter.length);
|
|
251
|
+
const close = rest.startsWith('--');
|
|
252
|
+
if (close) {
|
|
253
|
+
rest = rest.slice(2);
|
|
254
|
+
}
|
|
255
|
+
if (/[^ \t]/.test(rest)) {
|
|
256
|
+
// something other than padding after the boundary, so a different boundary or text
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (multipart.state === 'epilogue') {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
return { multipart, close, pad: rest };
|
|
263
|
+
}
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Ends whatever the current node was collecting at a delimiter line and moves on to the next
|
|
268
|
+
* part of that multipart, or to its epilogue
|
|
269
|
+
*
|
|
270
|
+
* @param {Object} delimiter Result of matchDelimiter()
|
|
271
|
+
* @param {String} prevBr The line break that ended the line before the delimiter
|
|
272
|
+
*/
|
|
273
|
+
endPart(delimiter, prevBr) {
|
|
274
|
+
const node = this._node;
|
|
275
|
+
const multipart = delimiter.multipart;
|
|
276
|
+
if (node !== multipart) {
|
|
277
|
+
// a part ends here
|
|
278
|
+
if (node.state === 'header') {
|
|
279
|
+
// a delimiter right after the header lines, with no blank line and no line break of
|
|
280
|
+
// its own (RFC 2046 5.1.1 wants one before every delimiter): the line break that ended
|
|
281
|
+
// the last header line, or the previous delimiter line, is the only one there is
|
|
282
|
+
this.endHeader();
|
|
283
|
+
// the multiparts a lost close delimiter leaves open between this part and the one the
|
|
284
|
+
// delimiter belongs to end with this part, so they end bare too
|
|
285
|
+
for (let open = node; open !== multipart; open = open.parentNode) {
|
|
286
|
+
open.bare = true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
else if (node.body.length) {
|
|
291
|
+
// the preamble ends here. The line break between the preamble and the delimiter belongs to
|
|
292
|
+
// the delimiter, but the preamble lines end with their own
|
|
293
|
+
node.body[node.body.length - 1] += prevBr;
|
|
294
|
+
}
|
|
295
|
+
if (!delimiter.close) {
|
|
296
|
+
const next = this.createNode(multipart);
|
|
297
|
+
if (delimiter.pad) {
|
|
298
|
+
next.pad = delimiter.pad;
|
|
299
|
+
}
|
|
300
|
+
this._node = next;
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
if (delimiter.pad) {
|
|
304
|
+
multipart.closePad = delimiter.pad;
|
|
305
|
+
}
|
|
306
|
+
delete multipart.unterminated;
|
|
307
|
+
multipart.state = 'epilogue';
|
|
308
|
+
this._node = multipart;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Parses the body of a message/rfc822 node into `node.message`. RFC 2046 5.2.1 only allows the
|
|
313
|
+
* identity encodings for such a body, RFC 2045 5.1 and 6.1 make the type and encoding names case
|
|
314
|
+
* insensitive. A message/global body (RFC 6532 section 3.5) goes to `node.globalMessage`, as only
|
|
315
|
+
* IMAP4rev2 treats it like message/rfc822 (RFC 9051 section 7.5.2), see embeddedMessage()
|
|
316
|
+
*/
|
|
317
|
+
parseEmbeddedMessage(node) {
|
|
318
|
+
const contentType = node.parsedHeader['content-type'];
|
|
319
|
+
const type = ((contentType && contentType.value) || '').toLowerCase();
|
|
320
|
+
if ((type !== 'message/rfc822' && type !== 'message/global') || this.depth >= MAX_MESSAGE_DEPTH) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const encoding = (node.parsedHeader['content-transfer-encoding'] || '').toString().trim().toLowerCase();
|
|
324
|
+
if (encoding && !IDENTITY_ENCODINGS.includes(encoding)) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
node[type === 'message/rfc822' ? 'message' : 'globalMessage'] = parseTree(node.body, this.depth + 1);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Joins body arrays into strings. Removes unnecessary fields from the tree
|
|
331
|
+
*/
|
|
332
|
+
finalizeTree() {
|
|
333
|
+
if (this._node.state === 'header') {
|
|
334
|
+
this.endHeader();
|
|
335
|
+
if (this._node.header.length && !this.rfc822.endsWith('\n')) {
|
|
336
|
+
// the input ended within the last header line, there is no line break to render
|
|
337
|
+
this._node.headerUnterminated = true;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// iterative, so that deeply nested multiparts do not exhaust the stack
|
|
341
|
+
const stack = [...this.tree.childNodes];
|
|
342
|
+
while (stack.length) {
|
|
343
|
+
const parsing = stack.pop();
|
|
344
|
+
// the same object, from here on with its lines joined
|
|
345
|
+
const node = parsing;
|
|
346
|
+
const lines = parsing.body;
|
|
347
|
+
// a body section holds lines, parts, or at least a close delimiter. A blank line followed by
|
|
348
|
+
// the end of the input leaves the trailing empty line in the body, one followed directly by
|
|
349
|
+
// a delimiter leaves nothing
|
|
350
|
+
const closed = node.boundary && !node.unterminated;
|
|
351
|
+
if (!(lines.length || parsing.childNodes.length || closed)) {
|
|
352
|
+
node.hasBody = false;
|
|
353
|
+
}
|
|
354
|
+
// RFC 3501 7.4.2 body-fld-lines, counted like Dovecot does: the line breaks in the body
|
|
355
|
+
node.lineCount = lines.length ? lines.length - 1 : 0;
|
|
356
|
+
node.body = lines.join('');
|
|
357
|
+
node.size = node.body.length;
|
|
358
|
+
// a message/rfc822 entity carries its parsed message
|
|
359
|
+
this.parseEmbeddedMessage(node);
|
|
360
|
+
if (parsing.epilogue) {
|
|
361
|
+
node.epilogue = parsing.epilogue.join('');
|
|
362
|
+
}
|
|
363
|
+
parsing.childNodes.forEach(child => stack.push(child));
|
|
364
|
+
// remove unneeded properties
|
|
365
|
+
delete parsing.parentNode;
|
|
366
|
+
delete parsing.state;
|
|
367
|
+
if (!node.childNodes.length) {
|
|
368
|
+
delete node.childNodes;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Creates a new node with default values for the parse tree
|
|
374
|
+
*/
|
|
375
|
+
createNode(parentNode) {
|
|
376
|
+
const node = {
|
|
377
|
+
state: 'header',
|
|
378
|
+
childNodes: [],
|
|
379
|
+
header: [],
|
|
380
|
+
parsedHeader: Object.create(null),
|
|
381
|
+
body: [],
|
|
382
|
+
multipart: false,
|
|
383
|
+
boundary: false,
|
|
384
|
+
parentNode
|
|
385
|
+
};
|
|
386
|
+
parentNode.childNodes.push(node);
|
|
387
|
+
return node;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Processes header lines. Splits lines to key-value pairs
|
|
391
|
+
* and processes special values
|
|
392
|
+
*/
|
|
393
|
+
processNodeHeader() {
|
|
394
|
+
const node = this._node;
|
|
395
|
+
// the fields hold raw values until they are parsed below
|
|
396
|
+
const fields = node.parsedHeader;
|
|
397
|
+
// RFC 5322 2.2.3: a line that starts with whitespace continues the previous header field
|
|
398
|
+
const header = [];
|
|
399
|
+
for (const line of node.header) {
|
|
400
|
+
if (header.length && /^\s/.test(line)) {
|
|
401
|
+
header[header.length - 1] += '\r\n' + line;
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
header.push(line);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
node.header = header;
|
|
408
|
+
for (const line of header) {
|
|
409
|
+
const parts = line.split(':');
|
|
410
|
+
const key = (parts.shift() || '').trim().toLowerCase();
|
|
411
|
+
const value = parts.join(':').trim();
|
|
412
|
+
// Do not touch headers that have strange looking keys, keep these
|
|
413
|
+
// only in the unparsed array
|
|
414
|
+
if (!FIELD_NAME.test(key)) {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
if (key in fields) {
|
|
418
|
+
if (Array.isArray(fields[key])) {
|
|
419
|
+
fields[key].push(value);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
fields[key] = [fields[key], value];
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
fields[key] = value.replace(/\s*\r?\n\s*/g, ' ');
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// always ensure the presence of Content-Type. RFC 2046 5.1.5: inside a digest the default
|
|
430
|
+
// is message/rfc822 instead of text/plain
|
|
431
|
+
if (!fields['content-type']) {
|
|
432
|
+
const parentSubtype = ((node.parentNode && node.parentNode.multipart) || '').toString().toLowerCase();
|
|
433
|
+
fields['content-type'] = parentSubtype === 'digest' ? 'message/rfc822' : 'text/plain';
|
|
434
|
+
}
|
|
435
|
+
// parse additional params for Content-Type and Content-Disposition, the last header wins
|
|
436
|
+
['content-type', 'content-disposition'].forEach(key => {
|
|
437
|
+
if (fields[key]) {
|
|
438
|
+
fields[key] = this.parseValueParams([].concat(fields[key]).pop());
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
// ensure single value for selected fields, the last header wins
|
|
442
|
+
[
|
|
443
|
+
'subject',
|
|
444
|
+
'date',
|
|
445
|
+
'in-reply-to',
|
|
446
|
+
'message-id',
|
|
447
|
+
'content-transfer-encoding',
|
|
448
|
+
'content-id',
|
|
449
|
+
'content-description',
|
|
450
|
+
'content-language',
|
|
451
|
+
'content-md5',
|
|
452
|
+
'content-location'
|
|
453
|
+
].forEach(key => {
|
|
454
|
+
if (Array.isArray(fields[key])) {
|
|
455
|
+
fields[key] = fields[key].pop().replace(/\s*\r?\n\s*/g, ' ');
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
if (fields['content-transfer-encoding']) {
|
|
459
|
+
// RFC 2045 6.1: the mechanism token may be followed by a comment, which is not part of it
|
|
460
|
+
fields['content-transfer-encoding'] = splitStructuredValue(fields['content-transfer-encoding'])[0].trim();
|
|
461
|
+
}
|
|
462
|
+
// Parse address fields (join several fields with same key)
|
|
463
|
+
['from', 'sender', 'reply-to', 'to', 'cc', 'bcc'].forEach(key => {
|
|
464
|
+
if (fields[key]) {
|
|
465
|
+
fields[key] = [].concat(fields[key]).flatMap(value => (value && (0, addressparser_js_1.default)(value.replace(/\s*\r?\n\s*/g, ' '))) || []);
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Splits a value to an object.
|
|
471
|
+
* eg. 'text/plain; charset=utf-8' -> {value: 'text/plain', params:{charset: 'utf-8'}}
|
|
472
|
+
*
|
|
473
|
+
* @param {String} headerValue A string value for a header key
|
|
474
|
+
* @return {Object} Parsed value
|
|
475
|
+
*/
|
|
476
|
+
parseValueParams(headerValue) {
|
|
477
|
+
const data = {
|
|
478
|
+
value: '',
|
|
479
|
+
type: '',
|
|
480
|
+
subtype: '',
|
|
481
|
+
params: Object.create(null)
|
|
482
|
+
};
|
|
483
|
+
// RFC 2231 continuations and extended values, by parameter name
|
|
484
|
+
const continuations = Object.create(null);
|
|
485
|
+
splitStructuredValue(headerValue || '', ';').forEach((part, i) => {
|
|
486
|
+
if (!i) {
|
|
487
|
+
data.value = part.trim();
|
|
488
|
+
const subtype = data.value.split('/');
|
|
489
|
+
data.type = (subtype.shift() || '').toLowerCase();
|
|
490
|
+
data.subtype = subtype.join('/');
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
const parts = part.split('=');
|
|
494
|
+
const key = (parts.shift() || '').trim().toLowerCase();
|
|
495
|
+
let value = parts.join('=').trim();
|
|
496
|
+
if (value.length >= 2 && value.startsWith('"') && value.endsWith('"')) {
|
|
497
|
+
// RFC 2045 5.1 quoted-string: the quotes are not part of the value and a backslash
|
|
498
|
+
// quotes the character after it (RFC 822 3.3)
|
|
499
|
+
value = value.slice(1, -1).replace(/\\([\s\S])/g, '$1');
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
value = value.replace(/^['"\s]*|['"\s]*$/g, '');
|
|
503
|
+
}
|
|
504
|
+
// Do not touch parameters that have strange looking keys
|
|
505
|
+
if (!FIELD_NAME.test(key)) {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
// RFC 2231 3 and 4: `name*N` is segment N of a continued value, a trailing asterisk marks
|
|
509
|
+
// a segment as extended (percent encoded, the first one prefixed with charset'language')
|
|
510
|
+
const match = key.match(/^([^*]+)(?:\*(\d{1,3}))?(\*)?$/);
|
|
511
|
+
if (match && (match[2] !== undefined || match[3])) {
|
|
512
|
+
const name = match[1];
|
|
513
|
+
if (!continuations[name]) {
|
|
514
|
+
continuations[name] = [];
|
|
515
|
+
}
|
|
516
|
+
continuations[name][Number(match[2]) || 0] = { value, extended: !!match[3] };
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
data.params[key] = value;
|
|
520
|
+
}
|
|
521
|
+
data.hasParams = true;
|
|
522
|
+
});
|
|
523
|
+
Object.keys(continuations).forEach(key => {
|
|
524
|
+
let charset = '';
|
|
525
|
+
let encoded = '';
|
|
526
|
+
let extended = false;
|
|
527
|
+
continuations[key].forEach((segment, i) => {
|
|
528
|
+
if (!segment) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
let value = segment.value;
|
|
532
|
+
if (segment.extended && !i) {
|
|
533
|
+
const parts = value.split("'");
|
|
534
|
+
if (parts.length >= 3) {
|
|
535
|
+
charset = parts.shift();
|
|
536
|
+
parts.shift(); // language, ignored
|
|
537
|
+
value = parts.join("'");
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if (segment.extended) {
|
|
541
|
+
extended = true;
|
|
542
|
+
encoded += value;
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
// a segment that is not extended is plain text, encode it like the rest
|
|
546
|
+
encoded += value.replace(/[^\x21-\x24\x26-\x7e]/g, chr => '%' + ('0' + chr.charCodeAt(0).toString(16)).substr(-2));
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
data.params[key] = extended ? decodeExtendedValue(charset, encoded) : decodeExtendedValue('', encoded);
|
|
550
|
+
});
|
|
551
|
+
return data;
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Checks Content-Type value for the current tree node.
|
|
555
|
+
*/
|
|
556
|
+
processContentType() {
|
|
557
|
+
const node = this._node;
|
|
558
|
+
// processNodeHeader() always sets a Content-Type
|
|
559
|
+
const contentType = node.parsedHeader['content-type'];
|
|
560
|
+
if (contentType.type === 'multipart' && contentType.params.boundary) {
|
|
561
|
+
node.multipart = contentType.subtype;
|
|
562
|
+
node.boundary = contentType.params.boundary;
|
|
563
|
+
// until the close delimiter is seen
|
|
564
|
+
node.unterminated = true;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Parses a message into a MIME tree
|
|
570
|
+
*
|
|
571
|
+
* @param {String} rfc822 Message source as a binary string with CRLF line breaks
|
|
572
|
+
* @param {Number} [depth] Nesting level of message/rfc822 parts
|
|
573
|
+
* @return {Object} Root node of the tree
|
|
574
|
+
*/
|
|
575
|
+
function parseTree(rfc822, depth) {
|
|
576
|
+
const parser = new MIMEParser(rfc822, depth);
|
|
577
|
+
parser.parse();
|
|
578
|
+
parser.finalizeTree();
|
|
579
|
+
// finalizeTree() turned the nodes into MimeNodes
|
|
580
|
+
return parser.tree.childNodes[0];
|
|
581
|
+
}
|
|
582
|
+
// RFC 3501 9: body-type-mpart = 1*body SP media-subtype. A multipart whose boundary never appeared has
|
|
583
|
+
// no parts, so this empty text part stands in for them
|
|
584
|
+
const PLACEHOLDER_PART = parseTree('Content-Type: text/plain\r\n\r\n');
|
|
585
|
+
/**
|
|
586
|
+
* The parts of a node as IMAP numbers them: the parts of a multipart (the placeholder when it has none),
|
|
587
|
+
* undefined for anything else
|
|
588
|
+
*
|
|
589
|
+
* @param {Object} node A tree node
|
|
590
|
+
* @returns {Array|undefined} Part nodes
|
|
591
|
+
*/
|
|
592
|
+
function partsOf(node) {
|
|
593
|
+
if (node.childNodes) {
|
|
594
|
+
return node.childNodes;
|
|
595
|
+
}
|
|
596
|
+
return node.boundary ? [PLACEHOLDER_PART] : undefined;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* The message encapsulated in a node: the message of a message/rfc822 part, and with `global` also of a
|
|
600
|
+
* message/global part (RFC 9051 sections 6.4.5.1 and 7.5.2, IMAP4rev1 treats message/global as a basic part)
|
|
601
|
+
*
|
|
602
|
+
* @param {Object} node A tree node
|
|
603
|
+
* @param {Boolean} [global] Treat message/global like message/rfc822
|
|
604
|
+
* @returns {Object|undefined} Root node of the encapsulated message
|
|
605
|
+
*/
|
|
606
|
+
function embeddedMessage(node, global) {
|
|
607
|
+
return node.message || (global ? node.globalMessage : undefined);
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Resolves a numeric part path to a node. RFC 3501 6.4.5: the parts of a multipart are numbered from 1,
|
|
611
|
+
* a non-multipart message has one part which is the message itself, and the parts of a message/rfc822
|
|
612
|
+
* part are numbered under it
|
|
613
|
+
*
|
|
614
|
+
* @param {Object} tree Root node
|
|
615
|
+
* @param {String} path Dot-separated numeric path
|
|
616
|
+
* @param {Boolean} [global] Number the parts of message/global parts too, like IMAP4rev2 does
|
|
617
|
+
* @return {Object|Boolean} Node, or false when there is no such part
|
|
618
|
+
*/
|
|
619
|
+
function resolveNode(tree, path, global) {
|
|
620
|
+
// the message whose parts the next number counts
|
|
621
|
+
let scope = tree;
|
|
622
|
+
let node = tree;
|
|
623
|
+
for (const number of (path || '').toString().split('.')) {
|
|
624
|
+
const index = Number(number) - 1;
|
|
625
|
+
if (!scope || !(index >= 0)) {
|
|
626
|
+
return false;
|
|
627
|
+
}
|
|
628
|
+
const parts = partsOf(scope);
|
|
629
|
+
node = parts ? parts[index] : index === 0 ? scope : undefined;
|
|
630
|
+
if (!node) {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
scope = embeddedMessage(node, global) || (partsOf(node) ? node : false);
|
|
634
|
+
}
|
|
635
|
+
return node;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* The header of a node as the HEADER and MIME sections return it, with the blank line that ends it
|
|
639
|
+
*
|
|
640
|
+
* @param {Object} node Tree node
|
|
641
|
+
* @return {String} Header section
|
|
642
|
+
*/
|
|
643
|
+
function headerSection(node) {
|
|
644
|
+
const header = node.header || [];
|
|
645
|
+
if (node.hasBody === false) {
|
|
646
|
+
// RFC 3501 7.4.2: the blank line is part of the header, except for a message with no body and no blank line
|
|
647
|
+
return header.length ? header.join('\r\n') + (node.headerUnterminated ? '' : '\r\n') : '';
|
|
648
|
+
}
|
|
649
|
+
return header.length ? header.join('\r\n') + '\r\n\r\n' : '\r\n';
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Renders a node of the tree back to the octets it was parsed from
|
|
653
|
+
*
|
|
654
|
+
* @param {Object} node Tree node
|
|
655
|
+
* @param {Boolean} [textOnly] Leave out the header of the node (BODY[TEXT], BODY[n])
|
|
656
|
+
* @return {String} Binary string
|
|
657
|
+
*/
|
|
658
|
+
function render(node, textOnly) {
|
|
659
|
+
const output = [];
|
|
660
|
+
const walk = (node, withHeader) => {
|
|
661
|
+
if (withHeader) {
|
|
662
|
+
const header = node.header || [];
|
|
663
|
+
if (header.length) {
|
|
664
|
+
output.push(header.join('\r\n') + (node.headerUnterminated ? '' : '\r\n'));
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
if (node.hasBody === false) {
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
if (withHeader) {
|
|
671
|
+
// the blank line between header and body
|
|
672
|
+
output.push('\r\n');
|
|
673
|
+
}
|
|
674
|
+
output.push(node.body || '');
|
|
675
|
+
if (!node.boundary) {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
const children = node.childNodes || [];
|
|
679
|
+
for (let i = 0; i < children.length; i++) {
|
|
680
|
+
const child = children[i];
|
|
681
|
+
output.push('--' + node.boundary + (child.pad || '') + '\r\n');
|
|
682
|
+
walk(child, true);
|
|
683
|
+
if ((!node.unterminated || i < children.length - 1) && !child.bare) {
|
|
684
|
+
// the line break that belongs to the next delimiter
|
|
685
|
+
output.push('\r\n');
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
if (!node.unterminated) {
|
|
689
|
+
output.push('--' + node.boundary + '--' + (node.closePad || ''));
|
|
690
|
+
output.push(node.epilogue || '');
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
walk(node, !textOnly);
|
|
694
|
+
return output.join('');
|
|
695
|
+
}
|
|
696
|
+
// Parsed data of messages, so a message is parsed only once and not again until its source changes
|
|
697
|
+
const cache = new WeakMap();
|
|
698
|
+
/**
|
|
699
|
+
* Returns the source with CRLF line breaks and the MIME tree of a message
|
|
700
|
+
*
|
|
701
|
+
* @param {Object} message Message object with a `raw` property
|
|
702
|
+
* @return {Object} `{ raw, tree }`
|
|
703
|
+
*/
|
|
704
|
+
function getMessageData(message) {
|
|
705
|
+
let cached = cache.get(message);
|
|
706
|
+
if (!cached || cached.source !== message.raw) {
|
|
707
|
+
const raw = normalizeLineBreaks(message.raw);
|
|
708
|
+
cached = { source: message.raw, raw, tree: parseTree(raw) };
|
|
709
|
+
cache.set(message, cached);
|
|
710
|
+
}
|
|
711
|
+
return cached;
|
|
712
|
+
}
|
|
713
|
+
function mimeparser(rfc822) {
|
|
714
|
+
return parseTree(normalizeLineBreaks(rfc822));
|
|
715
|
+
}
|
|
716
|
+
{
|
|
717
|
+
const defaultExport = exports.default;
|
|
718
|
+
if (defaultExport && (typeof defaultExport === 'function' || typeof defaultExport === 'object')) {
|
|
719
|
+
for (const key of Object.keys(exports)) {
|
|
720
|
+
if (key !== 'default' && !(key in defaultExport)) {
|
|
721
|
+
defaultExport[key] = exports[key];
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
Object.defineProperty(defaultExport, 'default', { value: defaultExport, enumerable: false, writable: true, configurable: true });
|
|
725
|
+
module.exports = defaultExport;
|
|
726
|
+
}
|
|
727
|
+
}
|