git subrepo clone https://github.com/mailcow/mailcow-dockerized.git mailcow/src/mailcow-dockerized

subrepo: subdir:   "mailcow/src/mailcow-dockerized"
  merged:   "a832becb"
upstream: origin:   "https://github.com/mailcow/mailcow-dockerized.git"
  branch:   "master"
  commit:   "a832becb"
git-subrepo: version:  "0.4.3"
  origin:   "???"
  commit:   "???"
Change-Id: If5be2d621a211e164c9b6577adaa7884449f16b5
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/CHANGELOG.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/CHANGELOG.md
new file mode 100644
index 0000000..62fffab
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/CHANGELOG.md
@@ -0,0 +1,637 @@
+# Changelog
+
+## [1.10.0](https://github.com/ddeboer/imap/tree/1.10.0) (2020-01-24)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.9.0...1.10.0)
+
+**Implemented enhancements:**
+
+- Handle comments \(CFWS\) in Date header + not-valid formats [\#439](https://github.com/ddeboer/imap/pull/439) ([pupaxxo](https://github.com/pupaxxo))
+- Support PHP 7.4, require PHP 7.2 [\#433](https://github.com/ddeboer/imap/pull/433) ([Slamdunk](https://github.com/Slamdunk))
+
+**Closed issues:**
+
+- Invalid Date header when trying to fetching date on not RFC compliant emails [\#438](https://github.com/ddeboer/imap/issues/438)
+
+**Merged pull requests:**
+
+- Clear the last used mailbox cache when closing a connection [\#447](https://github.com/ddeboer/imap/pull/447) ([dhzavann](https://github.com/dhzavann))
+- README: update PHP version to match composer.json [\#441](https://github.com/ddeboer/imap/pull/441) ([Slamdunk](https://github.com/Slamdunk))
+- Typo [\#440](https://github.com/ddeboer/imap/pull/440) ([OskarStark](https://github.com/OskarStark))
+
+## [1.9.0](https://github.com/ddeboer/imap/tree/1.9.0) (2019-11-25)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.8.0...1.9.0)
+
+**Implemented enhancements:**
+
+- Quota: let's also test the numbers [\#431](https://github.com/ddeboer/imap/pull/431) ([Slamdunk](https://github.com/Slamdunk))
+- Add getQuota method using imap\_get\_quotaroot to Connection class [\#430](https://github.com/ddeboer/imap/pull/430) ([arkadiusjonczek](https://github.com/arkadiusjonczek))
+
+**Closed issues:**
+
+- markAsSeen\(\)  not work [\#415](https://github.com/ddeboer/imap/issues/415)
+
+**Merged pull requests:**
+
+- CS Fix: strip redundant php docs [\#428](https://github.com/ddeboer/imap/pull/428) ([Slamdunk](https://github.com/Slamdunk))
+- Fix: Variable name [\#412](https://github.com/ddeboer/imap/pull/412) ([localheinz](https://github.com/localheinz))
+
+## [1.8.0](https://github.com/ddeboer/imap/tree/1.8.0) (2019-04-15)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.2...1.8.0)
+
+**Implemented enhancements:**
+
+- Add phpstan-strict-rules, expose PartiInterface::getDescription\(\) [\#409](https://github.com/ddeboer/imap/pull/409) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.7.2](https://github.com/ddeboer/imap/tree/1.7.2) (2019-04-12)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.1...1.7.2)
+
+**Fixed bugs:**
+
+- Handle message/rfc822 when content-disposition is missing [\#410](https://github.com/ddeboer/imap/pull/410) ([Daredzik](https://github.com/Daredzik))
+
+## [1.7.1](https://github.com/ddeboer/imap/tree/1.7.1) (2019-03-18)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.7.0...1.7.1)
+
+**Fixed bugs:**
+
+- Encoding problem with 1.7 [\#405](https://github.com/ddeboer/imap/issues/405)
+- imap\_search/imap\_sort: default params must not be passed if unspecified [\#406](https://github.com/ddeboer/imap/pull/406) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.7.0](https://github.com/ddeboer/imap/tree/1.7.0) (2019-03-04)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.6.0...1.7.0)
+
+**Implemented enhancements:**
+
+- Docker and Travis differs in handling new message eols [\#404](https://github.com/ddeboer/imap/pull/404) ([Slamdunk](https://github.com/Slamdunk))
+- Update PHP-CS-Fixer rules [\#403](https://github.com/ddeboer/imap/pull/403) ([Slamdunk](https://github.com/Slamdunk))
+- Add charset for imap\_search or imap\_sort [\#402](https://github.com/ddeboer/imap/pull/402) ([Slamdunk](https://github.com/Slamdunk))
+- PHPStan clean ups [\#400](https://github.com/ddeboer/imap/pull/400) ([Slamdunk](https://github.com/Slamdunk))
+- Adding an undelete\(\) message method [\#386](https://github.com/ddeboer/imap/pull/386) ([C-Duv](https://github.com/C-Duv))
+
+**Closed issues:**
+
+- Convert from GBK \(X-GBK\) to UTF-8 Issue [\#395](https://github.com/ddeboer/imap/issues/395)
+
+**Merged pull requests:**
+
+- Add new ResourceCheckFailureException to handle imap\_check\(\) false [\#399](https://github.com/ddeboer/imap/pull/399) ([pyatnitsev](https://github.com/pyatnitsev))
+- Remove GBK -\> X-GBK Alias and add X-GBK -\> GBK [\#396](https://github.com/ddeboer/imap/pull/396) ([pyatnitsev](https://github.com/pyatnitsev))
+- Add Feature Requests to README.md [\#394](https://github.com/ddeboer/imap/pull/394) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.6.0](https://github.com/ddeboer/imap/tree/1.6.0) (2018-12-04)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.5...1.6.0)
+
+**Implemented enhancements:**
+
+- Require PHP ^7.1 [\#257](https://github.com/ddeboer/imap/issues/257)
+- Require PHP ^7.1 [\#383](https://github.com/ddeboer/imap/pull/383) ([Slamdunk](https://github.com/Slamdunk))
+- Add ability to pass options and retries to imap\_open [\#382](https://github.com/ddeboer/imap/pull/382) ([Slamdunk](https://github.com/Slamdunk))
+- Docker setup for running tests [\#374](https://github.com/ddeboer/imap/pull/374) ([LeadTechVisas](https://github.com/LeadTechVisas))
+- Get messages by UID sequence [\#373](https://github.com/ddeboer/imap/pull/373) ([LeadTechVisas](https://github.com/LeadTechVisas))
+
+**Fixed bugs:**
+
+- Undeliverable mail: attachment parsing error [\#334](https://github.com/ddeboer/imap/issues/334)
+- imap\_getmailboxes returns false; [\#134](https://github.com/ddeboer/imap/issues/134)
+- Fix mailbox name as only numbers [\#381](https://github.com/ddeboer/imap/pull/381) ([Slamdunk](https://github.com/Slamdunk))
+- Gracefully handle possible non-array return value of imap\_getmailboxes [\#372](https://github.com/ddeboer/imap/pull/372) ([Slamdunk](https://github.com/Slamdunk))
+
+**Closed issues:**
+
+- \[AUTHENTICATIONFAILED\] Authentication failed - Too many login failures [\#368](https://github.com/ddeboer/imap/issues/368)
+- last folder in list [\#353](https://github.com/ddeboer/imap/issues/353)
+- Caching IMAP server connections [\#88](https://github.com/ddeboer/imap/issues/88)
+
+## [1.5.5](https://github.com/ddeboer/imap/tree/1.5.5) (2018-08-21)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.4...1.5.5)
+
+**Fixed bugs:**
+
+- Plain text attachments are not identified as Attachment parts [\#341](https://github.com/ddeboer/imap/issues/341)
+- Handle plain/text attachments without Content-Type header [\#367](https://github.com/ddeboer/imap/pull/367) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.5.4](https://github.com/ddeboer/imap/tree/1.5.4) (2018-08-19)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.3...1.5.4)
+
+**Fixed bugs:**
+
+- Very long filename, result of getFilename\(\) = NULL? [\#365](https://github.com/ddeboer/imap/issues/365)
+- Support RFC2231 attachment filenames [\#366](https://github.com/ddeboer/imap/pull/366) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.5.3](https://github.com/ddeboer/imap/tree/1.5.3) (2018-07-20)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.2...1.5.3)
+
+**Fixed bugs:**
+
+- Dates: handle UT timezone [\#361](https://github.com/ddeboer/imap/pull/361) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.5.2](https://github.com/ddeboer/imap/tree/1.5.2) (2018-07-10)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.1...1.5.2)
+
+**Fixed bugs:**
+
+- Fails to load Message Headers [\#358](https://github.com/ddeboer/imap/issues/358)
+- Handle invalid headers [\#359](https://github.com/ddeboer/imap/pull/359) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.5.1](https://github.com/ddeboer/imap/tree/1.5.1) (2018-05-04)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.5.0...1.5.1)
+
+**Fixed bugs:**
+
+- getContent\(\) method returns wrong content part [\#342](https://github.com/ddeboer/imap/issues/342)
+- Fix handle of attachment messages with attachments [\#343](https://github.com/ddeboer/imap/pull/343) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.5.0](https://github.com/ddeboer/imap/tree/1.5.0) (2018-03-26)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.4.1...1.5.0)
+
+**Implemented enhancements:**
+
+- ImapResource: cache last opened mailbox [\#328](https://github.com/ddeboer/imap/pull/328) ([Slamdunk](https://github.com/Slamdunk))
+
+**Fixed bugs:**
+
+- AbstractPart::isAttachment\(\) handle unknown part type [\#302](https://github.com/ddeboer/imap/pull/302) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.4.1](https://github.com/ddeboer/imap/tree/1.4.1) (2018-03-22)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.4.0...1.4.1)
+
+**Fixed bugs:**
+
+- Return value of Ddeboer\\Imap\\Message\\AbstractPart::getDecodedContent\(\) must be of the type string, boolean returned [\#284](https://github.com/ddeboer/imap/issues/284)
+- base64\_decode may return false in PHP \< 7.1 [\#324](https://github.com/ddeboer/imap/pull/324) ([Slamdunk](https://github.com/Slamdunk))
+
+**Merged pull requests:**
+
+- Add entry in README about Mailbox::addMessage [\#325](https://github.com/ddeboer/imap/pull/325) ([soywod](https://github.com/soywod))
+
+## [1.4.0](https://github.com/ddeboer/imap/tree/1.4.0) (2018-03-19)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.3.1...1.4.0)
+
+**Implemented enhancements:**
+
+- Lazy load Message [\#320](https://github.com/ddeboer/imap/pull/320) ([Slamdunk](https://github.com/Slamdunk))
+
+**Fixed bugs:**
+
+- Invalid argument supplied for foreach\(\) in Parameters.php line 52 [\#317](https://github.com/ddeboer/imap/issues/317)
+- Message "11964" does not exist: imap\_fetchstructure\(\): Bad message number [\#310](https://github.com/ddeboer/imap/issues/310)
+- imap\_mime\_header\_decode may return false [\#322](https://github.com/ddeboer/imap/pull/322) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.3.1](https://github.com/ddeboer/imap/tree/1.3.1) (2018-03-09)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.3.0...1.3.1)
+
+**Implemented enhancements:**
+
+- Allow empty port [\#312](https://github.com/ddeboer/imap/pull/312) ([Slamdunk](https://github.com/Slamdunk))
+
+**Closed issues:**
+
+- getServerString\(\) with no port [\#311](https://github.com/ddeboer/imap/issues/311)
+
+## [1.3.0](https://github.com/ddeboer/imap/tree/1.3.0) (2018-02-28)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.3...1.3.0)
+
+**Implemented enhancements:**
+
+- Implement bulk-move [\#306](https://github.com/ddeboer/imap/pull/306) ([particleflux](https://github.com/particleflux))
+
+**Closed issues:**
+
+- feature: Bulk move [\#305](https://github.com/ddeboer/imap/issues/305)
+
+**Merged pull requests:**
+
+- README.md: add `Unknown search criterion: OR` note [\#304](https://github.com/ddeboer/imap/pull/304) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.2.3](https://github.com/ddeboer/imap/tree/1.2.3) (2018-02-09)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.2...1.2.3)
+
+**Fixed bugs:**
+
+- $part-\>type can be 9 [\#301](https://github.com/ddeboer/imap/issues/301)
+
+**Merged pull requests:**
+
+- README.md: code-coverage has higher priority than Scrutinizer [\#300](https://github.com/ddeboer/imap/pull/300) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.2.2](https://github.com/ddeboer/imap/tree/1.2.2) (2018-02-05)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.1...1.2.2)
+
+**Implemented enhancements:**
+
+- Allow PHPUnit ^7.0 [\#296](https://github.com/ddeboer/imap/pull/296) ([Slamdunk](https://github.com/Slamdunk))
+
+**Fixed bugs:**
+
+- Attachment-\>getFilename return null [\#297](https://github.com/ddeboer/imap/issues/297)
+- Don't handle multiplart as an attachment [\#298](https://github.com/ddeboer/imap/pull/298) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.2.1](https://github.com/ddeboer/imap/tree/1.2.1) (2018-01-29)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.2.0...1.2.1)
+
+**Implemented enhancements:**
+
+- Introduce strict comparison [\#289](https://github.com/ddeboer/imap/pull/289) ([Slamdunk](https://github.com/Slamdunk))
+
+**Fixed bugs:**
+
+- Invalid Date header found: "Thur, 04 Jan 2018 06:44:23 +0400" [\#293](https://github.com/ddeboer/imap/issues/293)
+- MessageIterator::current\(\) fails when there are no messages [\#288](https://github.com/ddeboer/imap/issues/288)
+- Remove weekday while parsing date header [\#294](https://github.com/ddeboer/imap/pull/294) ([Slamdunk](https://github.com/Slamdunk))
+- MessageIterator: forbid raw calls [\#290](https://github.com/ddeboer/imap/pull/290) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.2.0](https://github.com/ddeboer/imap/tree/1.2.0) (2018-01-15)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.2...1.2.0)
+
+**Implemented enhancements:**
+
+- Make imap\_append\(\) optional arguments reachable [\#280](https://github.com/ddeboer/imap/pull/280) ([Slamdunk](https://github.com/Slamdunk))
+- PHPStan: introduce static analysis [\#276](https://github.com/ddeboer/imap/pull/276) ([Slamdunk](https://github.com/Slamdunk))
+
+**Fixed bugs:**
+
+- getAttachments\(\) problem when mixin inline and attachment [\#281](https://github.com/ddeboer/imap/issues/281)
+- UnexpectedEncodingException: Cannot decode "5" [\#278](https://github.com/ddeboer/imap/issues/278)
+- Handle correctly multiple nested attachments [\#283](https://github.com/ddeboer/imap/pull/283) ([Slamdunk](https://github.com/Slamdunk))
+- Manageable UnexpectedEncodingException [\#282](https://github.com/ddeboer/imap/pull/282) ([Slamdunk](https://github.com/Slamdunk))
+
+**Closed issues:**
+
+- Appending mail with options [\#279](https://github.com/ddeboer/imap/issues/279)
+
+## [1.1.2](https://github.com/ddeboer/imap/tree/1.1.2) (2017-12-12)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.1...1.1.2)
+
+**Fixed bugs:**
+
+- Unsupported charset "134": mb\_convert\_encoding\(\): Illegal character encoding specified [\#270](https://github.com/ddeboer/imap/issues/270)
+- Support Microsoft charset values [\#271](https://github.com/ddeboer/imap/pull/271) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.1.1](https://github.com/ddeboer/imap/tree/1.1.1) (2017-11-10)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.1.0...1.1.1)
+
+**Implemented enhancements:**
+
+- Transcoder: expand charset aliases list [\#267](https://github.com/ddeboer/imap/pull/267) ([Slamdunk](https://github.com/Slamdunk))
+
+**Fixed bugs:**
+
+- Charset aliases: fix to lowercase search [\#266](https://github.com/ddeboer/imap/pull/266) ([Slamdunk](https://github.com/Slamdunk))
+
+**Merged pull requests:**
+
+- README.md: add timeout note [\#263](https://github.com/ddeboer/imap/pull/263) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.1.0](https://github.com/ddeboer/imap/tree/1.1.0) (2017-11-06)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.8...1.1.0)
+
+**Implemented enhancements:**
+
+- Deprecate MessageInterface::maskAsSeen\(\) in favour of MessageInterface::markAsSeen\(\) [\#255](https://github.com/ddeboer/imap/pull/255) ([Slamdunk](https://github.com/Slamdunk))
+- Lazy load structured Headers [\#250](https://github.com/ddeboer/imap/pull/250) ([Slamdunk](https://github.com/Slamdunk))
+- Implement imap\_thread [\#249](https://github.com/ddeboer/imap/pull/249) ([Slamdunk](https://github.com/Slamdunk))
+- Require ext-iconv [\#248](https://github.com/ddeboer/imap/pull/248) ([Slamdunk](https://github.com/Slamdunk))
+- Message Part: expose $partNumber [\#244](https://github.com/ddeboer/imap/pull/244) ([wujku](https://github.com/wujku))
+- Add Mockability helpers and documentation [\#236](https://github.com/ddeboer/imap/pull/236) ([Slamdunk](https://github.com/Slamdunk))
+- Add missing interface change for \#225 [\#233](https://github.com/ddeboer/imap/pull/233) ([Slamdunk](https://github.com/Slamdunk))
+- Connection: check if the connection is still active with `imap\_ping` [\#232](https://github.com/ddeboer/imap/pull/232) ([wujku](https://github.com/wujku))
+- Message: add `References` and `In-Reply-To` headers shortcuts [\#230](https://github.com/ddeboer/imap/pull/230) ([wujku](https://github.com/wujku))
+- Added bulk set / clear flags functionality for mailbox messages [\#225](https://github.com/ddeboer/imap/pull/225) ([wujku](https://github.com/wujku))
+
+**Merged pull requests:**
+
+- make docs more obvious [\#252](https://github.com/ddeboer/imap/pull/252) ([lgg](https://github.com/lgg))
+- README.md: add Table of Contents with Travis checker [\#234](https://github.com/ddeboer/imap/pull/234) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.0.8](https://github.com/ddeboer/imap/tree/1.0.8) (2017-10-27)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.7...1.0.8)
+
+**Implemented enhancements:**
+
+- Headers: no catchable exception [\#246](https://github.com/ddeboer/imap/issues/246)
+- imap\_thread [\#113](https://github.com/ddeboer/imap/issues/113)
+
+**Fixed bugs:**
+
+- \[TypeError\] Return value of Ddeboer\Imap\Message\AbstractMessage::getId\(\) must be of the type string, null returned [\#253](https://github.com/ddeboer/imap/issues/253)
+- BasicMessageInterface::getId\(\) can be null [\#254](https://github.com/ddeboer/imap/pull/254) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.0.7](https://github.com/ddeboer/imap/tree/1.0.7) (2017-10-16)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.6...1.0.7)
+
+**Fixed bugs:**
+
+- Problem with a IMAP resource stream [\#245](https://github.com/ddeboer/imap/issues/245)
+- IMAP resource must be checked at every call for mailbox context [\#247](https://github.com/ddeboer/imap/pull/247) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.0.6](https://github.com/ddeboer/imap/tree/1.0.6) (2017-10-12)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.5...1.0.6)
+
+**Fixed bugs:**
+
+- \[TypeError\] Return value of AbstractMessage::getFrom\(\) must be an instance of EmailAddress, null returned [\#241](https://github.com/ddeboer/imap/issues/241)
+- Message: Date header can be absent [\#243](https://github.com/ddeboer/imap/pull/243) ([Slamdunk](https://github.com/Slamdunk))
+- Message: From header can be absent [\#242](https://github.com/ddeboer/imap/pull/242) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.0.5](https://github.com/ddeboer/imap/tree/1.0.5) (2017-10-12)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.4...1.0.5)
+
+**Fixed bugs:**
+
+- Use set\_error\_handler with late exception [\#240](https://github.com/ddeboer/imap/pull/240) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.0.4](https://github.com/ddeboer/imap/tree/1.0.4) (2017-10-11)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.3...1.0.4)
+
+**Implemented enhancements:**
+
+- Avoid \(set|restor\)\_error\_handler [\#239](https://github.com/ddeboer/imap/pull/239) ([Slamdunk](https://github.com/Slamdunk))
+
+**Fixed bugs:**
+
+- Current Transcoder class does not support all charsets.  [\#237](https://github.com/ddeboer/imap/issues/237)
+- Relay also iconv during decoding [\#238](https://github.com/ddeboer/imap/pull/238) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.0.3](https://github.com/ddeboer/imap/tree/1.0.3) (2017-10-11)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.2...1.0.3)
+
+**Fixed bugs:**
+
+- Attachment::getFilename\(\) may be null on inline-att, widen return type [\#235](https://github.com/ddeboer/imap/pull/235) ([wujku](https://github.com/wujku))
+
+## [1.0.2](https://github.com/ddeboer/imap/tree/1.0.2) (2017-10-06)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.1...1.0.2)
+
+**Fixed bugs:**
+
+- Issue with saving XML attachments [\#228](https://github.com/ddeboer/imap/issues/228)
+- Do not charset-decode attachments [\#231](https://github.com/ddeboer/imap/pull/231) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.0.1](https://github.com/ddeboer/imap/tree/1.0.1) (2017-10-05)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/1.0.0...1.0.1)
+
+**Fixed bugs:**
+
+- Error with attachment charset [\#226](https://github.com/ddeboer/imap/issues/226)
+- If charset is not specified defaults to "us-ascii" [\#227](https://github.com/ddeboer/imap/pull/227) ([Slamdunk](https://github.com/Slamdunk))
+
+## [1.0.0](https://github.com/ddeboer/imap/tree/1.0.0) (2017-10-04)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.2...1.0.0)
+
+**Implemented enhancements:**
+
+- Need getAll for headers [\#200](https://github.com/ddeboer/imap/issues/200)
+- Tests: implement @covers to avoid false positive on code-coverage [\#188](https://github.com/ddeboer/imap/issues/188)
+- Remove commented code [\#174](https://github.com/ddeboer/imap/issues/174)
+- Regex in SearchExpressions [\#157](https://github.com/ddeboer/imap/issues/157)
+- How do I get unread messages count? [\#98](https://github.com/ddeboer/imap/issues/98)
+- Add mocking ability through Interfaces [\#221](https://github.com/ddeboer/imap/pull/221) ([Slamdunk](https://github.com/Slamdunk))
+- Wrap imap resource to periodically check its status [\#220](https://github.com/ddeboer/imap/pull/220) ([Slamdunk](https://github.com/Slamdunk))
+- Add more coding-standard rules [\#218](https://github.com/ddeboer/imap/pull/218) ([Slamdunk](https://github.com/Slamdunk))
+- Always keep unseen: remove keepUnseen, add markAsSeen [\#217](https://github.com/ddeboer/imap/pull/217) ([Slamdunk](https://github.com/Slamdunk))
+- Embedded messages: refactor \#106 [\#216](https://github.com/ddeboer/imap/pull/216) ([Slamdunk](https://github.com/Slamdunk))
+- Headers now extends \ArrayIterator [\#215](https://github.com/ddeboer/imap/pull/215) ([Slamdunk](https://github.com/Slamdunk))
+- Implement imap\_mail\_copy [\#214](https://github.com/ddeboer/imap/pull/214) ([Slamdunk](https://github.com/Slamdunk))
+- Imap sort [\#213](https://github.com/ddeboer/imap/pull/213) ([Slamdunk](https://github.com/Slamdunk))
+- Increased code-coverage [\#211](https://github.com/ddeboer/imap/pull/211) ([Slamdunk](https://github.com/Slamdunk))
+- Update to PHPUnit ^6.2 [\#209](https://github.com/ddeboer/imap/pull/209) ([Slamdunk](https://github.com/Slamdunk))
+- Use specific exceptions to ease user catches [\#208](https://github.com/ddeboer/imap/pull/208) ([Slamdunk](https://github.com/Slamdunk))
+- Wrap Exception on invalid Date header [\#205](https://github.com/ddeboer/imap/pull/205) ([Slamdunk](https://github.com/Slamdunk))
+- Add tests for \#144 set flags functionalities [\#203](https://github.com/ddeboer/imap/pull/203) ([Slamdunk](https://github.com/Slamdunk))
+- Add imap\_fetchheader\(\) functionality to get raw headers [\#202](https://github.com/ddeboer/imap/pull/202) ([Slamdunk](https://github.com/Slamdunk))
+- Parse all email type headers [\#199](https://github.com/ddeboer/imap/pull/199) ([Slamdunk](https://github.com/Slamdunk))
+- Test search conditions [\#198](https://github.com/ddeboer/imap/pull/198) ([Slamdunk](https://github.com/Slamdunk))
+- Mailbox: get status [\#192](https://github.com/ddeboer/imap/pull/192) ([Slamdunk](https://github.com/Slamdunk))
+- SearchExpression is a Search\ConditionInterface [\#191](https://github.com/ddeboer/imap/pull/191) ([Slamdunk](https://github.com/Slamdunk))
+- SearchCondition: \_\_toString\(\) -\> toString\(\) [\#187](https://github.com/ddeboer/imap/pull/187) ([Slamdunk](https://github.com/Slamdunk))
+- Retain imap\_getmailboxes\(\) results [\#184](https://github.com/ddeboer/imap/pull/184) ([Slamdunk](https://github.com/Slamdunk))
+- Add type hints and return types [\#183](https://github.com/ddeboer/imap/pull/183) ([Slamdunk](https://github.com/Slamdunk))
+- Exception: increase verbosity with imap\_alerts\(\) and imap\_errors\(\) [\#182](https://github.com/ddeboer/imap/pull/182) ([Slamdunk](https://github.com/Slamdunk))
+- Add coding-standards [\#181](https://github.com/ddeboer/imap/pull/181) ([Slamdunk](https://github.com/Slamdunk))
+- Travis: re-enable code-coverage on scrutinizer [\#177](https://github.com/ddeboer/imap/pull/177) ([Slamdunk](https://github.com/Slamdunk))
+- Add .gitattributes to remove from releases unneded files [\#173](https://github.com/ddeboer/imap/pull/173) ([Slamdunk](https://github.com/Slamdunk))
+- Travis: use local Dovecot installation [\#170](https://github.com/ddeboer/imap/pull/170) ([Slamdunk](https://github.com/Slamdunk))
+- Need all Headers in string format [\#149](https://github.com/ddeboer/imap/pull/149) ([FlashWS](https://github.com/FlashWS))
+- Get raw mail [\#146](https://github.com/ddeboer/imap/pull/146) ([styxit](https://github.com/styxit))
+- add getBcc\(\), Set, Clear Flag\(\Seen, \Answered, \Flagged, \Deleted, and \Draft\), getHeadersRaw\(\) [\#144](https://github.com/ddeboer/imap/pull/144) ([trungpv93](https://github.com/trungpv93))
+
+**Fixed bugs:**
+
+- Search\Condition needs charset escaping/indication [\#190](https://github.com/ddeboer/imap/issues/190)
+- imap\_utf7\_\(encode|decode\) -\> mb\_convert\_encoding [\#185](https://github.com/ddeboer/imap/issues/185)
+- España [\#176](https://github.com/ddeboer/imap/issues/176)
+- getHeaders\(\) decode broke information [\#171](https://github.com/ddeboer/imap/issues/171)
+- Date format for date search condition [\#168](https://github.com/ddeboer/imap/issues/168)
+- Error when trying fetch messages from container [\#167](https://github.com/ddeboer/imap/issues/167)
+- Attachment encoding error [\#158](https://github.com/ddeboer/imap/issues/158)
+- getFilename\(\) is empty and no attachment, even when there is an attachment. [\#142](https://github.com/ddeboer/imap/issues/142)
+- Encoding issues [\#136](https://github.com/ddeboer/imap/issues/136)
+- URGENT: The timezone could not be found in the database [\#135](https://github.com/ddeboer/imap/issues/135)
+- Incorrect transcoding of text attachments [\#132](https://github.com/ddeboer/imap/issues/132)
+- Undefined offset  [\#123](https://github.com/ddeboer/imap/issues/123)
+- ICS file not supported as attachment [\#120](https://github.com/ddeboer/imap/issues/120)
+- Should iconv be a requirement? [\#115](https://github.com/ddeboer/imap/issues/115)
+- KeepUnseen doen't work [\#92](https://github.com/ddeboer/imap/issues/92)
+- PHP Fatal error Failed to parse time string in ddeboer/imap/src/Message.php [\#89](https://github.com/ddeboer/imap/issues/89)
+- encoding issue [\#85](https://github.com/ddeboer/imap/issues/85)
+- keepUnseen not working correctly with Hotmail [\#84](https://github.com/ddeboer/imap/issues/84)
+- Iconv Exception [\#78](https://github.com/ddeboer/imap/issues/78)
+- $message-\>getAttachments\(\) doesn't recognize some attachments [\#74](https://github.com/ddeboer/imap/issues/74)
+- Message::move\(\) doesn't work. [\#73](https://github.com/ddeboer/imap/issues/73)
+- Message\Part: part number must distinguish original message [\#223](https://github.com/ddeboer/imap/pull/223) ([Slamdunk](https://github.com/Slamdunk))
+- Recursive Embedded email body bug [\#222](https://github.com/ddeboer/imap/pull/222) ([Slamdunk](https://github.com/Slamdunk))
+- Exclude HTML from allowed attachment subtype [\#212](https://github.com/ddeboer/imap/pull/212) ([Slamdunk](https://github.com/Slamdunk))
+- Fix imap\_mail\_move behaviour and test it [\#207](https://github.com/ddeboer/imap/pull/207) ([Slamdunk](https://github.com/Slamdunk))
+- Undefined encoding: throw exception [\#197](https://github.com/ddeboer/imap/pull/197) ([Slamdunk](https://github.com/Slamdunk))
+- Message charset: mb\_convert\_encoding + aliases [\#196](https://github.com/ddeboer/imap/pull/196) ([Slamdunk](https://github.com/Slamdunk))
+- Mailbox: only UTF-8 names [\#193](https://github.com/ddeboer/imap/pull/193) ([Slamdunk](https://github.com/Slamdunk))
+- Search\Date\AbstractDate: fix format to RFC-3501 [\#189](https://github.com/ddeboer/imap/pull/189) ([Slamdunk](https://github.com/Slamdunk))
+- Travis: fix failing tests [\#172](https://github.com/ddeboer/imap/pull/172) ([Slamdunk](https://github.com/Slamdunk))
+- Return body of single-part HTML message as HTML, not text [\#101](https://github.com/ddeboer/imap/pull/101) ([joker806](https://github.com/joker806))
+- Implement "undisclosed recipients" addresses [\#86](https://github.com/ddeboer/imap/pull/86) ([darit](https://github.com/darit))
+
+**Closed issues:**
+
+- Potential memory issue with attachments [\#195](https://github.com/ddeboer/imap/issues/195)
+- Explain Message::delete [\#175](https://github.com/ddeboer/imap/issues/175)
+- Get raw message [\#161](https://github.com/ddeboer/imap/issues/161)
+- Composer install problem [\#160](https://github.com/ddeboer/imap/issues/160)
+- Transcoder not exist [\#154](https://github.com/ddeboer/imap/issues/154)
+- The library doesn't support using sort by [\#151](https://github.com/ddeboer/imap/issues/151)
+- Office 365 - Array to string conversion error [\#131](https://github.com/ddeboer/imap/issues/131)
+- Is there a method to turn a seen message into an "unseen" one ? [\#130](https://github.com/ddeboer/imap/issues/130)
+- Create mailbox [\#126](https://github.com/ddeboer/imap/issues/126)
+- Move and Delete Message not working [\#112](https://github.com/ddeboer/imap/issues/112)
+- Problem on production server [\#111](https://github.com/ddeboer/imap/issues/111)
+- Authentication failed for a Gmail account [\#109](https://github.com/ddeboer/imap/issues/109)
+- A method to run IMAP commands? [\#83](https://github.com/ddeboer/imap/issues/83)
+
+**Merged pull requests:**
+
+- Update README.md to latest develop changes [\#224](https://github.com/ddeboer/imap/pull/224) ([Slamdunk](https://github.com/Slamdunk))
+- Add Filippo Tessarotto as an author of the package [\#219](https://github.com/ddeboer/imap/pull/219) ([Slamdunk](https://github.com/Slamdunk))
+- README.md: call Connection::expunge after move and delete [\#210](https://github.com/ddeboer/imap/pull/210) ([Slamdunk](https://github.com/Slamdunk))
+- Remove misleading Mailbox::expunge\(\) [\#206](https://github.com/ddeboer/imap/pull/206) ([Slamdunk](https://github.com/Slamdunk))
+- Add CHANGELOG.md [\#194](https://github.com/ddeboer/imap/pull/194) ([Slamdunk](https://github.com/Slamdunk))
+- README.md updates [\#178](https://github.com/ddeboer/imap/pull/178) ([Slamdunk](https://github.com/Slamdunk))
+
+## [0.5.2](https://github.com/ddeboer/imap/tree/0.5.2) (2015-12-03)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.1...0.5.2)
+
+**Closed issues:**
+
+- $message-\>getAttachments\(\) returns null if message has no attachments [\#80](https://github.com/ddeboer/imap/issues/80)
+- Email objects visibility [\#76](https://github.com/ddeboer/imap/issues/76)
+
+**Merged pull requests:**
+
+- Fixed the keepUnseen method [\#95](https://github.com/ddeboer/imap/pull/95) ([aeyoll](https://github.com/aeyoll))
+- Mark Mailbox as countable, fix doc comments [\#91](https://github.com/ddeboer/imap/pull/91) ([krzysiekpiasecki](https://github.com/krzysiekpiasecki))
+- Message::getAttachments confirm to signature [\#82](https://github.com/ddeboer/imap/pull/82) ([boekkooi](https://github.com/boekkooi))
+- Added hasMailbox to Connection [\#81](https://github.com/ddeboer/imap/pull/81) ([boekkooi](https://github.com/boekkooi))
+- Make sure imap connection are reopened [\#79](https://github.com/ddeboer/imap/pull/79) ([joserobleda](https://github.com/joserobleda))
+
+## [0.5.1](https://github.com/ddeboer/imap/tree/0.5.1) (2015-02-01)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/0.5.0...0.5.1)
+
+**Closed issues:**
+
+- imap\_open error  [\#72](https://github.com/ddeboer/imap/issues/72)
+- $message-\>getAttachments\(\) does not return anything, even though a message has at least one attachment [\#71](https://github.com/ddeboer/imap/issues/71)
+- Prepare docs for 1.0 [\#69](https://github.com/ddeboer/imap/issues/69)
+- "date" header is not reliable [\#63](https://github.com/ddeboer/imap/issues/63)
+- File Attachments don't show up [\#55](https://github.com/ddeboer/imap/issues/55)
+
+**Merged pull requests:**
+
+- Add support for attachments without content disposition [\#70](https://github.com/ddeboer/imap/pull/70) ([ddeboer](https://github.com/ddeboer))
+
+## [0.5.0](https://github.com/ddeboer/imap/tree/0.5.0) (2015-01-24)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/0.4.0...0.5.0)
+
+**Closed issues:**
+
+- Use utf8\_encode\(\) function to encode content [\#66](https://github.com/ddeboer/imap/issues/66)
+- Please add function order by date [\#59](https://github.com/ddeboer/imap/issues/59)
+- mb\_convert\_encoding breaks code [\#57](https://github.com/ddeboer/imap/issues/57)
+- How get I getMessages but newest first ... [\#11](https://github.com/ddeboer/imap/issues/11)
+
+## [0.4.0](https://github.com/ddeboer/imap/tree/0.4.0) (2015-01-04)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/0.3.1...0.4.0)
+
+**Closed issues:**
+
+- Please add 6th parameter to imap\_open call [\#62](https://github.com/ddeboer/imap/issues/62)
+- Should Message::delete\(\) use the Message UID? [\#46](https://github.com/ddeboer/imap/issues/46)
+- mb\_convert\_encoding\(\): Illegal character encoding specified [\#35](https://github.com/ddeboer/imap/issues/35)
+- Deleting a message isn't working [\#30](https://github.com/ddeboer/imap/issues/30)
+- imap\_header doesn't work with message uid [\#26](https://github.com/ddeboer/imap/issues/26)
+
+**Merged pull requests:**
+
+- Added basic requirement [\#61](https://github.com/ddeboer/imap/pull/61) ([nikoskip](https://github.com/nikoskip))
+- FIX: PHP error: "Cannot declare class Ddeboer\Imap\Search\Text\Text ..." [\#58](https://github.com/ddeboer/imap/pull/58) ([racztiborzoltan](https://github.com/racztiborzoltan))
+- Message::delete sets the FT\_UID flag.  Fixes \#30 Fixes \#46 [\#54](https://github.com/ddeboer/imap/pull/54) ([ctalbot](https://github.com/ctalbot))
+- Allow binary-encoded part content [\#48](https://github.com/ddeboer/imap/pull/48) ([joker806](https://github.com/joker806))
+- Fix CS [\#47](https://github.com/ddeboer/imap/pull/47) ([xelan](https://github.com/xelan))
+- fixed typo [\#45](https://github.com/ddeboer/imap/pull/45) ([xelan](https://github.com/xelan))
+
+## [0.3.1](https://github.com/ddeboer/imap/tree/0.3.1) (2014-08-11)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/0.3.0...0.3.1)
+
+**Merged pull requests:**
+
+- \imap\_header dosen't work with UID [\#44](https://github.com/ddeboer/imap/pull/44) ([ysramirez](https://github.com/ysramirez))
+
+## [0.3.0](https://github.com/ddeboer/imap/tree/0.3.0) (2014-08-10)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/0.2...0.3.0)
+
+**Closed issues:**
+
+- please remove useless wiki [\#42](https://github.com/ddeboer/imap/issues/42)
+- Travis tests allways fail? [\#40](https://github.com/ddeboer/imap/issues/40)
+- Garbled e-mail body encoding [\#27](https://github.com/ddeboer/imap/issues/27)
+- Improve docs [\#25](https://github.com/ddeboer/imap/issues/25)
+- "undisclosed-recipients" throws error [\#23](https://github.com/ddeboer/imap/issues/23)
+
+**Merged pull requests:**
+
+- correct minor typo [\#43](https://github.com/ddeboer/imap/pull/43) ([cordoval](https://github.com/cordoval))
+- Utf-8 encode body content. [\#39](https://github.com/ddeboer/imap/pull/39) ([cmoralesweb](https://github.com/cmoralesweb))
+- Fix regex parsing the date header \(allowing multiple brackets\) [\#38](https://github.com/ddeboer/imap/pull/38) ([joker806](https://github.com/joker806))
+- Allow empty connection flags [\#34](https://github.com/ddeboer/imap/pull/34) ([joker806](https://github.com/joker806))
+- Fixed typo [\#32](https://github.com/ddeboer/imap/pull/32) ([abhinavkumar940](https://github.com/abhinavkumar940))
+
+## [0.2](https://github.com/ddeboer/imap/tree/0.2) (2013-11-24)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/0.1...0.2)
+
+## [0.1](https://github.com/ddeboer/imap/tree/0.1) (2013-11-22)
+
+[Full Changelog](https://github.com/ddeboer/imap/compare/c02d49cdb9246901bb00d211a0f2aba208f6fab6...0.1)
+
+**Closed issues:**
+
+- Prevent setting SEEN flag [\#20](https://github.com/ddeboer/imap/issues/20)
+- Add tests [\#18](https://github.com/ddeboer/imap/issues/18)
+- delete messages [\#9](https://github.com/ddeboer/imap/issues/9)
+- README is missing basic usage [\#7](https://github.com/ddeboer/imap/issues/7)
+- Subject and other texts are decoded incorrectly  [\#3](https://github.com/ddeboer/imap/issues/3)
+
+**Merged pull requests:**
+
+- also fetch inline attachments [\#24](https://github.com/ddeboer/imap/pull/24) ([kaiserlos](https://github.com/kaiserlos))
+- since leading slash is always needed [\#22](https://github.com/ddeboer/imap/pull/22) ([huglester](https://github.com/huglester))
+- Added missed createMailbox\($name\) function [\#19](https://github.com/ddeboer/imap/pull/19) ([burci](https://github.com/burci))
+- Added move and delete function to message + expunge function [\#17](https://github.com/ddeboer/imap/pull/17) ([burci](https://github.com/burci))
+- Clean up some unused variable [\#16](https://github.com/ddeboer/imap/pull/16) ([burci](https://github.com/burci))
+- Fixed mailbox encoding [\#15](https://github.com/ddeboer/imap/pull/15) ([burci](https://github.com/burci))
+- Create new mailbox [\#14](https://github.com/ddeboer/imap/pull/14) ([burci](https://github.com/burci))
+- Fixed bug in getDecodedContent with 'format=flowed' email [\#13](https://github.com/ddeboer/imap/pull/13) ([burci](https://github.com/burci))
+- Fixed date parsing for some imap servers [\#12](https://github.com/ddeboer/imap/pull/12) ([thelfensdrfer](https://github.com/thelfensdrfer))
+- Add support for more complex search expressions. [\#10](https://github.com/ddeboer/imap/pull/10) ([jamesiarmes](https://github.com/jamesiarmes))
+- Allow user to change server connection flags [\#6](https://github.com/ddeboer/imap/pull/6) ([mvar](https://github.com/mvar))
+- Improvements in EmailAddress class [\#4](https://github.com/ddeboer/imap/pull/4) ([mvar](https://github.com/mvar))
+
+
+
+\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/LICENSE
new file mode 100644
index 0000000..2c679e3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2013 David de Boer <david@ddeboer.nl>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/README.md
new file mode 100644
index 0000000..59dc532
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/README.md
@@ -0,0 +1,361 @@
+# IMAP library
+
+[![Build Status](https://travis-ci.org/ddeboer/imap.svg?branch=master)](https://travis-ci.org/ddeboer/imap)
+[![Code Coverage](https://scrutinizer-ci.com/g/ddeboer/imap/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/ddeboer/imap/?branch=master)
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/ddeboer/imap/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/ddeboer/imap/?branch=master)
+[![Latest Stable Version](https://poser.pugx.org/ddeboer/imap/v/stable.svg)](https://packagist.org/packages/ddeboer/imap)
+[![Total Downloads](https://poser.pugx.org/ddeboer/imap/downloads.png)](https://packagist.org/packages/ddeboer/imap)
+
+A PHP 7.2+ library to read and process e-mails over IMAP.
+
+This library requires [IMAP](https://secure.php.net/manual/en/book.imap.php),
+[iconv](https://secure.php.net/manual/en/book.iconv.php) and
+[Multibyte String](https://secure.php.net/manual/en/book.mbstring.php) extensions installed.
+
+## Table of Contents
+
+1. [Feature Requests](#feature-requests)
+1. [Installation](#installation)
+1. [Usage](#usage)
+    1. [Connect and Authenticate](#connect-and-authenticate)
+    1. [Mailboxes](#mailboxes)
+    1. [Messages](#messages)
+        1. [Searching for Messages](#searching-for-messages)
+        1. [Unknown search criterion: OR](#unknown-search-criterion-or)
+        1. [Message Properties and Operations](#message-properties-and-operations)
+    1. [Message Attachments](#message-attachments)
+    1. [Embedded Messages](#embedded-messages)
+    1. [Timeouts](#timeouts)
+1. [Mock the library](#mock-the-library)
+1. [Running the Tests](#running-the-tests)
+    1. [Running Tests using Docker](#running-tests-using-docker)
+
+## Feature Requests
+
+[![Feature Requests](https://feathub.com/ddeboer/imap?format=svg)](https://feathub.com/ddeboer/imap)
+
+## Installation
+
+The recommended way to install the IMAP library is through [Composer](https://getcomposer.org):
+
+```bash
+$ composer require ddeboer/imap
+```
+
+This command requires you to have Composer installed globally, as explained
+in the [installation chapter](https://getcomposer.org/doc/00-intro.md)
+of the Composer documentation.
+
+## Usage
+
+### Connect and Authenticate
+
+```php
+use Ddeboer\Imap\Server;
+
+$server = new Server('imap.gmail.com');
+
+// $connection is instance of \Ddeboer\Imap\Connection
+$connection = $server->authenticate('my_username', 'my_password');
+```
+
+You can specify port, [flags and parameters](https://secure.php.net/manual/en/function.imap-open.php)
+to the server:
+
+```php
+$server = new Server(
+    $hostname, // required
+    $port,     // defaults to '993'
+    $flags,    // defaults to '/imap/ssl/validate-cert'
+    $parameters
+);
+```
+
+### Mailboxes
+
+Retrieve mailboxes (also known as mail folders) from the mail server and iterate
+over them:
+
+```php
+$mailboxes = $connection->getMailboxes();
+
+foreach ($mailboxes as $mailbox) {
+    // Skip container-only mailboxes
+    // @see https://secure.php.net/manual/en/function.imap-getmailboxes.php
+    if ($mailbox->getAttributes() & \LATT_NOSELECT) {
+        continue;
+    }
+
+    // $mailbox is instance of \Ddeboer\Imap\Mailbox
+    printf('Mailbox "%s" has %s messages', $mailbox->getName(), $mailbox->count());
+}
+```
+
+Or retrieve a specific mailbox:
+
+```php
+$mailbox = $connection->getMailbox('INBOX');
+```
+
+Delete a mailbox:
+
+```php
+$connection->deleteMailbox($mailbox);
+```
+
+You can bulk set, or clear, any [flag](https://secure.php.net/manual/en/function.imap-setflag-full.php) of mailbox messages (by UIDs):
+
+```php
+$mailbox->setFlag('\\Seen \\Flagged', ['1:5', '7', '9']);
+$mailbox->setFlag('\\Seen', '1,3,5,6:8');
+
+$mailbox->clearFlag('\\Flagged', '1,3');
+```
+
+**WARNING** You must retrieve new Message instances in case of bulk modify flags to refresh the single Messages flags.
+
+### Messages
+
+Retrieve messages (e-mails) from a mailbox and iterate over them:
+
+```php
+$messages = $mailbox->getMessages();
+
+foreach ($messages as $message) {
+    // $message is instance of \Ddeboer\Imap\Message
+}
+```
+
+To insert a new message (that just has been sent) into the Sent mailbox and flag it as seen:
+
+```php
+$mailbox = $connection->getMailbox('Sent');
+$mailbox->addMessage($messageMIME, '\\Seen');
+```
+
+Note that the message should be a string at MIME format (as described in the [RFC2045](https://tools.ietf.org/html/rfc2045)).
+
+#### Searching for Messages
+
+```php
+use Ddeboer\Imap\SearchExpression;
+use Ddeboer\Imap\Search\Email\To;
+use Ddeboer\Imap\Search\Text\Body;
+
+$search = new SearchExpression();
+$search->addCondition(new To('me@here.com'));
+$search->addCondition(new Body('contents'));
+
+$messages = $mailbox->getMessages($search);
+```
+
+**WARNING** We are currently unable to have both spaces _and_ double-quotes
+escaped together. Only spaces are currently escaped correctly.
+You can use `Ddeboer\Imap\Search\RawExpression` to write the complete search
+condition by yourself.
+
+Messages can also be retrieved sorted as per [imap_sort](https://secure.php.net/manual/en/function.imap-sort.php)
+function:
+
+```php
+$today = new DateTimeImmutable();
+$thirtyDaysAgo = $today->sub(new DateInterval('P30D'));
+
+$messages = $mailbox->getMessages(
+    new Ddeboer\Imap\Search\Date\Since($thirtyDaysAgo),
+    \SORTDATE, // Sort criteria
+    true // Descending order
+);
+```
+
+#### Unknown search criterion: OR
+
+Note that PHP imap library relies on the `c-client` library available at https://www.washington.edu/imap/
+which doesn't fully support some IMAP4 search criteria like `OR`. If you want those unsupported criteria,
+you need to manually patch the latest version (`imap-2007f` of 23-Jul-2011 at the time of this commit)
+and recompile PHP onto your patched `c-client` library.
+
+By the way most of the common search criteria are available and functioning, browse them in `./src/Search`.
+
+References:
+
+1. https://stackoverflow.com/questions/36356715/imap-search-unknown-search-criterion-or
+1. imap-2007f.tar.gz: `./src/c-client/mail.c` and `./docs/internal.txt`
+
+#### Message Properties and Operations
+
+Get message number and unique [message id](https://en.wikipedia.org/wiki/Message-ID)
+in the form <...>:
+
+```php
+$message->getNumber();
+$message->getId();
+```
+
+Get other message properties:
+
+```php
+$message->getSubject();
+$message->getFrom();    // Message\EmailAddress
+$message->getTo();      // array of Message\EmailAddress
+$message->getDate();    // DateTimeImmutable
+$message->isAnswered();
+$message->isDeleted();
+$message->isDraft();
+$message->isSeen();
+```
+
+Get message headers as a [\Ddeboer\Imap\Message\Headers](/src/Ddeboer/Imap/Message/Headers.php) object:
+
+```php
+$message->getHeaders();
+```
+
+Get message body as HTML or plain text:
+
+```php
+$message->getBodyHtml();    // Content of text/html part, if present
+$message->getBodyText();    // Content of text/plain part, if present
+```
+
+Reading the message body keeps the message as unseen.
+If you want to mark the message as seen:
+
+```php
+$message->markAsSeen();
+```
+
+Or you can set, or clear, any [flag](https://secure.php.net/manual/en/function.imap-setflag-full.php):
+
+```php
+$message->setFlag('\\Seen \\Flagged');
+$message->clearFlag('\\Flagged');
+```
+
+Move a message to another mailbox:
+
+```php
+$mailbox = $connection->getMailbox('another-mailbox');
+$message->move($mailbox);
+$connection->expunge();
+```
+
+Deleting messages:
+
+```php
+$mailbox->getMessage(1)->delete();
+$mailbox->getMessage(2)->delete();
+$connection->expunge();
+```
+
+### Message Attachments
+
+Get message attachments (both inline and attached) and iterate over them:
+
+```php
+$attachments = $message->getAttachments();
+
+foreach ($attachments as $attachment) {
+    // $attachment is instance of \Ddeboer\Imap\Message\Attachment
+}
+```
+
+Download a message attachment to a local file:
+
+```php
+// getDecodedContent() decodes the attachment’s contents automatically:
+file_put_contents(
+    '/my/local/dir/' . $attachment->getFilename(),
+    $attachment->getDecodedContent()
+);
+```
+
+### Embedded Messages
+
+Check if attachment is embedded message and get it:
+
+```php
+$attachments = $message->getAttachments();
+
+foreach ($attachments as $attachment) {
+    if ($attachment->isEmbeddedMessage()) {
+        $embeddedMessage = $attachment->getEmbeddedMessage();
+        // $embeddedMessage is instance of \Ddeboer\Imap\Message\EmbeddedMessage
+    }
+}
+```
+
+An EmbeddedMessage has the same API as a normal Message, apart from flags
+and operations like copy, move or delete.
+
+### Timeouts
+
+The IMAP extension provides the [imap_timeout](https://secure.php.net/manual/en/function.imap-timeout.php)
+function to adjust the timeout seconds for various operations.
+
+However the extension's implementation doesn't link the functionality to a
+specific context or connection, instead they are global. So in order to not
+affect functionalities outside this library, we had to choose whether wrap
+every `imap_*` call around an optional user-provided timeout or leave this
+task to the user.
+
+Because of the heterogeneous world of IMAP servers and the high complexity
+burden cost for such a little gain of the former, we chose the latter.
+
+## Mock the library
+
+Mockability is granted by interfaces present for each API.
+Dig into [MockabilityTest](tests/MockabilityTest.php) for an example of a
+mocked workflow.
+
+## Running the Tests
+
+This library is functionally tested on [Travis CI](https://travis-ci.org/ddeboer/imap)
+against a local Dovecot server.
+
+If you have your own IMAP (test) account, you can run the tests locally by
+providing your IMAP credentials:
+
+```bash
+$ composer install
+$ IMAP_SERVER_NAME="my.imap.server.com" IMAP_SERVER_PORT="60993" IMAP_USERNAME="johndoe" IMAP_PASSWORD="p4ssword" vendor/bin/phpunit
+```
+
+You can also copy `phpunit.xml.dist` file to a custom `phpunit.xml` and put
+these environment variables in it:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit
+    bootstrap="./vendor/autoload.php"
+    colors="true"
+    verbose="true"
+>
+    <testsuites>
+        <testsuite name="ddeboer/imap">
+            <directory>./tests/</directory>
+        </testsuite>
+    </testsuites>
+    <filter>
+        <whitelist>
+            <directory suffix=".php">./src</directory>
+        </whitelist>
+    </filter>
+    <php>
+        <env name="IMAP_SERVER_NAME" value="my.imap.server.com" />
+        <env name="IMAP_SERVER_PORT" value="60993" />
+        <env name="IMAP_USERNAME" value="johndoe" />
+        <env name="IMAP_PASSWORD" value="p4ssword" />
+    </php>
+</phpunit>
+```
+
+**WARNING** Tests create new mailboxes without removing them.
+
+### Running Tests using Docker
+
+If you have Docker installed you can run the tests locally with the following command:
+
+```
+$ docker-compose run tests
+```
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/composer.json
new file mode 100644
index 0000000..d48ac0d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/composer.json
@@ -0,0 +1,48 @@
+{
+    "name": "ddeboer/imap",
+    "description": "Object-oriented IMAP for PHP",
+    "keywords": [
+        "email",
+        "mail",
+        "imap"
+    ],
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "David de Boer",
+            "email": "david@ddeboer.nl"
+        },
+        {
+            "name": "Filippo Tessarotto",
+            "email": "zoeslam@gmail.com"
+        },
+        {
+            "name": "Community contributors",
+            "homepage": "https://github.com/ddeboer/imap/graphs/contributors"
+        }
+    ],
+    "require": {
+        "php": "^7.2",
+        "ext-iconv": "*",
+        "ext-imap": "*",
+        "ext-mbstring": "*"
+    },
+    "require-dev": {
+        "friendsofphp/php-cs-fixer": "^2.16",
+        "phpstan/phpstan": "^0.12",
+        "phpstan/phpstan-phpunit": "^0.12",
+        "phpstan/phpstan-strict-rules": "^0.12",
+        "phpunit/phpunit": "^8.5",
+        "zendframework/zend-mail": "^2.10"
+    },
+    "autoload": {
+        "psr-4": {
+            "Ddeboer\\Imap\\": "src/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Ddeboer\\Imap\\Tests\\": "tests/"
+        }
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php
new file mode 100644
index 0000000..902c7ce
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Connection.php
@@ -0,0 +1,234 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+use Ddeboer\Imap\Exception\CreateMailboxException;
+use Ddeboer\Imap\Exception\DeleteMailboxException;
+use Ddeboer\Imap\Exception\ImapGetmailboxesException;
+use Ddeboer\Imap\Exception\ImapNumMsgException;
+use Ddeboer\Imap\Exception\ImapQuotaException;
+use Ddeboer\Imap\Exception\InvalidResourceException;
+use Ddeboer\Imap\Exception\MailboxDoesNotExistException;
+
+/**
+ * A connection to an IMAP server that is authenticated for a user.
+ */
+final class Connection implements ConnectionInterface
+{
+    /**
+     * @var ImapResourceInterface
+     */
+    private $resource;
+
+    /**
+     * @var string
+     */
+    private $server;
+
+    /**
+     * @var null|array
+     */
+    private $mailboxes;
+
+    /**
+     * @var null|array
+     */
+    private $mailboxNames;
+
+    /**
+     * Constructor.
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function __construct(ImapResourceInterface $resource, string $server)
+    {
+        $this->resource = $resource;
+        $this->server   = $server;
+    }
+
+    /**
+     * Get IMAP resource.
+     */
+    public function getResource(): ImapResourceInterface
+    {
+        return $this->resource;
+    }
+
+    /**
+     * Delete all messages marked for deletion.
+     */
+    public function expunge(): bool
+    {
+        return \imap_expunge($this->resource->getStream());
+    }
+
+    /**
+     * Close connection.
+     */
+    public function close(int $flag = 0): bool
+    {
+        $this->resource->clearLastMailboxUsedCache();
+
+        return \imap_close($this->resource->getStream(), $flag);
+    }
+
+    /**
+     * Get Mailbox quota.
+     */
+    public function getQuota(string $root = 'INBOX'): array
+    {
+        $errorMessage = null;
+        $errorNumber  = 0;
+        \set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber): bool {
+            $errorMessage = $message;
+            $errorNumber = $nr;
+
+            return true;
+        });
+
+        $return = \imap_get_quotaroot($this->resource->getStream(), $root);
+
+        \restore_error_handler();
+
+        if (false === $return || null !== $errorMessage) {
+            throw new ImapQuotaException(
+                \sprintf(
+                    'IMAP Quota request failed for "%s"%s',
+                    $root,
+                    null !== $errorMessage ? ': ' . $errorMessage : ''
+                ),
+                $errorNumber
+            );
+        }
+
+        return $return;
+    }
+
+    /**
+     * Get a list of mailboxes (also known as folders).
+     *
+     * @return MailboxInterface[]
+     */
+    public function getMailboxes(): array
+    {
+        $this->initMailboxNames();
+
+        if (null === $this->mailboxes) {
+            $this->mailboxes = [];
+            foreach ($this->mailboxNames as $mailboxName => $mailboxInfo) {
+                $this->mailboxes[(string) $mailboxName] = $this->getMailbox((string) $mailboxName);
+            }
+        }
+
+        return $this->mailboxes;
+    }
+
+    /**
+     * Check that a mailbox with the given name exists.
+     *
+     * @param string $name Mailbox name
+     */
+    public function hasMailbox(string $name): bool
+    {
+        $this->initMailboxNames();
+
+        return isset($this->mailboxNames[$name]);
+    }
+
+    /**
+     * Get a mailbox by its name.
+     *
+     * @param string $name Mailbox name
+     *
+     * @throws MailboxDoesNotExistException If mailbox does not exist
+     */
+    public function getMailbox(string $name): MailboxInterface
+    {
+        if (false === $this->hasMailbox($name)) {
+            throw new MailboxDoesNotExistException(\sprintf('Mailbox name "%s" does not exist', $name));
+        }
+
+        return new Mailbox($this->resource, $name, $this->mailboxNames[$name]);
+    }
+
+    /**
+     * Count number of messages not in any mailbox.
+     *
+     * @return int
+     */
+    public function count()
+    {
+        $return = \imap_num_msg($this->resource->getStream());
+
+        if (false === $return) {
+            throw new ImapNumMsgException('imap_num_msg failed');
+        }
+
+        return $return;
+    }
+
+    /**
+     * Check if the connection is still active.
+     *
+     * @throws InvalidResourceException If connection was closed
+     */
+    public function ping(): bool
+    {
+        return \imap_ping($this->resource->getStream());
+    }
+
+    /**
+     * Create mailbox.
+     *
+     * @throws CreateMailboxException
+     */
+    public function createMailbox(string $name): MailboxInterface
+    {
+        if (false === \imap_createmailbox($this->resource->getStream(), $this->server . \mb_convert_encoding($name, 'UTF7-IMAP', 'UTF-8'))) {
+            throw new CreateMailboxException(\sprintf('Can not create "%s" mailbox at "%s"', $name, $this->server));
+        }
+
+        $this->mailboxNames = $this->mailboxes = null;
+        $this->resource->clearLastMailboxUsedCache();
+
+        return $this->getMailbox($name);
+    }
+
+    /**
+     * Create mailbox.
+     *
+     * @throws DeleteMailboxException
+     */
+    public function deleteMailbox(MailboxInterface $mailbox): void
+    {
+        if (false === \imap_deletemailbox($this->resource->getStream(), $mailbox->getFullEncodedName())) {
+            throw new DeleteMailboxException(\sprintf('Mailbox "%s" could not be deleted', $mailbox->getName()));
+        }
+
+        $this->mailboxes = $this->mailboxNames = null;
+        $this->resource->clearLastMailboxUsedCache();
+    }
+
+    /**
+     * Get mailbox names.
+     */
+    private function initMailboxNames(): void
+    {
+        if (null !== $this->mailboxNames) {
+            return;
+        }
+
+        $this->mailboxNames = [];
+        $mailboxesInfo      = \imap_getmailboxes($this->resource->getStream(), $this->server, '*');
+        if (!\is_array($mailboxesInfo)) {
+            throw new ImapGetmailboxesException('imap_getmailboxes failed');
+        }
+
+        foreach ($mailboxesInfo as $mailboxInfo) {
+            $name                      = \mb_convert_encoding(\str_replace($this->server, '', $mailboxInfo->name), 'UTF-8', 'UTF7-IMAP');
+            $this->mailboxNames[$name] = $mailboxInfo;
+        }
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php
new file mode 100644
index 0000000..e76077f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ConnectionInterface.php
@@ -0,0 +1,67 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+/**
+ * A connection to an IMAP server that is authenticated for a user.
+ */
+interface ConnectionInterface extends \Countable
+{
+    /**
+     * Get IMAP resource.
+     */
+    public function getResource(): ImapResourceInterface;
+
+    /**
+     * Delete all messages marked for deletion.
+     */
+    public function expunge(): bool;
+
+    /**
+     * Close connection.
+     */
+    public function close(int $flag = 0): bool;
+
+    /**
+     * Check if the connection is still active.
+     */
+    public function ping(): bool;
+
+    /**
+     * Get Mailbox quota.
+     */
+    public function getQuota(string $root = 'INBOX'): array;
+
+    /**
+     * Get a list of mailboxes (also known as folders).
+     *
+     * @return MailboxInterface[]
+     */
+    public function getMailboxes(): array;
+
+    /**
+     * Check that a mailbox with the given name exists.
+     *
+     * @param string $name Mailbox name
+     */
+    public function hasMailbox(string $name): bool;
+
+    /**
+     * Get a mailbox by its name.
+     *
+     * @param string $name Mailbox name
+     */
+    public function getMailbox(string $name): MailboxInterface;
+
+    /**
+     * Create mailbox.
+     */
+    public function createMailbox(string $name): MailboxInterface;
+
+    /**
+     * Delete mailbox.
+     */
+    public function deleteMailbox(MailboxInterface $mailbox): void;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AbstractException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AbstractException.php
new file mode 100644
index 0000000..26c1e58
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AbstractException.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+abstract class AbstractException extends \RuntimeException
+{
+    /**
+     * @var array
+     */
+    private static $errorLabels = [
+        \E_ERROR                => 'E_ERROR',
+        \E_WARNING              => 'E_WARNING',
+        \E_PARSE                => 'E_PARSE',
+        \E_NOTICE               => 'E_NOTICE',
+        \E_CORE_ERROR           => 'E_CORE_ERROR',
+        \E_CORE_WARNING         => 'E_CORE_WARNING',
+        \E_COMPILE_ERROR        => 'E_COMPILE_ERROR',
+        \E_COMPILE_WARNING      => 'E_COMPILE_WARNING',
+        \E_USER_ERROR           => 'E_USER_ERROR',
+        \E_USER_WARNING         => 'E_USER_WARNING',
+        \E_USER_NOTICE          => 'E_USER_NOTICE',
+        \E_STRICT               => 'E_STRICT',
+        \E_RECOVERABLE_ERROR    => 'E_RECOVERABLE_ERROR',
+        \E_DEPRECATED           => 'E_DEPRECATED',
+        \E_USER_DEPRECATED      => 'E_USER_DEPRECATED',
+    ];
+
+    /**
+     * @param string     $message  The exception message
+     * @param int        $code     The exception code
+     * @param \Throwable $previous The previous exception
+     */
+    final public function __construct(string $message, int $code = 0, \Throwable $previous = null)
+    {
+        $errorType = '';
+        if (isset(self::$errorLabels[$code])) {
+            $errorType = \sprintf('[%s] ', self::$errorLabels[$code]);
+        }
+
+        $joinString      = "\n- ";
+        $alerts          = \imap_alerts();
+        $errors          = \imap_errors();
+        $completeMessage = \sprintf(
+            "%s%s\nimap_alerts (%s):%s\nimap_errors (%s):%s",
+            $errorType,
+            $message,
+            false !== $alerts ? \count($alerts) : 0,
+            false !== $alerts ? $joinString . \implode($joinString, $alerts) : '',
+            false !== $errors ? \count($errors) : 0,
+            false !== $errors ? $joinString . \implode($joinString, $errors) : ''
+        );
+
+        parent::__construct($completeMessage, $code, $previous);
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AuthenticationFailedException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AuthenticationFailedException.php
new file mode 100644
index 0000000..c0e93d0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/AuthenticationFailedException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class AuthenticationFailedException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/CreateMailboxException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/CreateMailboxException.php
new file mode 100644
index 0000000..55bb3a9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/CreateMailboxException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class CreateMailboxException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/DeleteMailboxException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/DeleteMailboxException.php
new file mode 100644
index 0000000..694c3a6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/DeleteMailboxException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class DeleteMailboxException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapFetchbodyException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapFetchbodyException.php
new file mode 100644
index 0000000..0e2f30f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapFetchbodyException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class ImapFetchbodyException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapFetchheaderException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapFetchheaderException.php
new file mode 100644
index 0000000..8a8387f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapFetchheaderException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class ImapFetchheaderException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapGetmailboxesException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapGetmailboxesException.php
new file mode 100644
index 0000000..7e68326
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapGetmailboxesException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class ImapGetmailboxesException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapMsgnoException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapMsgnoException.php
new file mode 100644
index 0000000..c9de4e4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapMsgnoException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class ImapMsgnoException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapNumMsgException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapNumMsgException.php
new file mode 100644
index 0000000..37a55ee
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapNumMsgException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class ImapNumMsgException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapQuotaException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapQuotaException.php
new file mode 100644
index 0000000..5a73e67
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapQuotaException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class ImapQuotaException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapStatusException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapStatusException.php
new file mode 100644
index 0000000..ca808cd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ImapStatusException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class ImapStatusException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidDateHeaderException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidDateHeaderException.php
new file mode 100644
index 0000000..05401e2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidDateHeaderException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class InvalidDateHeaderException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidHeadersException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidHeadersException.php
new file mode 100644
index 0000000..9554527
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidHeadersException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class InvalidHeadersException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidResourceException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidResourceException.php
new file mode 100644
index 0000000..f3cbf5b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidResourceException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class InvalidResourceException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidSearchCriteriaException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidSearchCriteriaException.php
new file mode 100644
index 0000000..783c6ba
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/InvalidSearchCriteriaException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class InvalidSearchCriteriaException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MailboxDoesNotExistException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MailboxDoesNotExistException.php
new file mode 100644
index 0000000..0cdf28a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MailboxDoesNotExistException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class MailboxDoesNotExistException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageCopyException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageCopyException.php
new file mode 100644
index 0000000..aa1ab68
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageCopyException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class MessageCopyException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageDeleteException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageDeleteException.php
new file mode 100644
index 0000000..38d88ff
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageDeleteException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class MessageDeleteException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageDoesNotExistException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageDoesNotExistException.php
new file mode 100644
index 0000000..1485a63
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageDoesNotExistException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class MessageDoesNotExistException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageMoveException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageMoveException.php
new file mode 100644
index 0000000..2f0cd0c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageMoveException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class MessageMoveException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageStructureException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageStructureException.php
new file mode 100644
index 0000000..a0dd436
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageStructureException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class MessageStructureException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageUndeleteException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageUndeleteException.php
new file mode 100644
index 0000000..a25f45c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/MessageUndeleteException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class MessageUndeleteException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/NotEmbeddedMessageException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/NotEmbeddedMessageException.php
new file mode 100644
index 0000000..12afdec
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/NotEmbeddedMessageException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class NotEmbeddedMessageException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/OutOfBoundsException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/OutOfBoundsException.php
new file mode 100644
index 0000000..55528c1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/OutOfBoundsException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class OutOfBoundsException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ReopenMailboxException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ReopenMailboxException.php
new file mode 100644
index 0000000..945c654
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ReopenMailboxException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class ReopenMailboxException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ResourceCheckFailureException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ResourceCheckFailureException.php
new file mode 100644
index 0000000..2751c71
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/ResourceCheckFailureException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class ResourceCheckFailureException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/UnexpectedEncodingException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/UnexpectedEncodingException.php
new file mode 100644
index 0000000..7ec3943
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/UnexpectedEncodingException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class UnexpectedEncodingException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/UnsupportedCharsetException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/UnsupportedCharsetException.php
new file mode 100644
index 0000000..5743679
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Exception/UnsupportedCharsetException.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Exception;
+
+final class UnsupportedCharsetException extends AbstractException
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResource.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResource.php
new file mode 100644
index 0000000..60c1617
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResource.php
@@ -0,0 +1,107 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+use Ddeboer\Imap\Exception\InvalidResourceException;
+use Ddeboer\Imap\Exception\ReopenMailboxException;
+
+/**
+ * An imap resource stream.
+ */
+final class ImapResource implements ImapResourceInterface
+{
+    /**
+     * @var mixed
+     */
+    private $resource;
+
+    /**
+     * @var null|MailboxInterface
+     */
+    private $mailbox;
+
+    /**
+     * @var null|string
+     */
+    private static $lastMailboxUsedCache;
+
+    /**
+     * Constructor.
+     *
+     * @param resource $resource
+     */
+    public function __construct($resource, MailboxInterface $mailbox = null)
+    {
+        $this->resource = $resource;
+        $this->mailbox  = $mailbox;
+    }
+
+    /**
+     * Get IMAP resource stream.
+     *
+     * @throws InvalidResourceException
+     *
+     * @return resource
+     */
+    public function getStream()
+    {
+        if (false === \is_resource($this->resource) || 'imap' !== \get_resource_type($this->resource)) {
+            throw new InvalidResourceException('Supplied resource is not a valid imap resource');
+        }
+
+        $this->initMailbox();
+
+        return $this->resource;
+    }
+
+    /**
+     * Clear last mailbox used cache.
+     */
+    public function clearLastMailboxUsedCache(): void
+    {
+        self::$lastMailboxUsedCache = null;
+    }
+
+    /**
+     * If connection is not currently in this mailbox, switch it to this mailbox.
+     */
+    private function initMailbox(): void
+    {
+        if (null === $this->mailbox || self::isMailboxOpen($this->mailbox, $this->resource)) {
+            return;
+        }
+
+        \imap_reopen($this->resource, $this->mailbox->getFullEncodedName());
+
+        if (self::isMailboxOpen($this->mailbox, $this->resource)) {
+            return;
+        }
+
+        throw new ReopenMailboxException(\sprintf('Cannot reopen mailbox "%s"', $this->mailbox->getName()));
+    }
+
+    /**
+     * Check whether the current mailbox is open.
+     *
+     * @param mixed $resource
+     */
+    private static function isMailboxOpen(MailboxInterface $mailbox, $resource): bool
+    {
+        $currentMailboxName = $mailbox->getFullEncodedName();
+        if ($currentMailboxName === self::$lastMailboxUsedCache) {
+            return true;
+        }
+
+        self::$lastMailboxUsedCache = null;
+        $check                      = \imap_check($resource);
+        $return                     = false !== $check && $check->Mailbox === $currentMailboxName;
+
+        if (true === $return) {
+            self::$lastMailboxUsedCache = $currentMailboxName;
+        }
+
+        return $return;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php
new file mode 100644
index 0000000..03c16f7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ImapResourceInterface.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+interface ImapResourceInterface
+{
+    /**
+     * Get IMAP resource stream.
+     *
+     * @return resource
+     */
+    public function getStream();
+
+    /**
+     * Clear last mailbox used cache.
+     */
+    public function clearLastMailboxUsedCache(): void;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Mailbox.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Mailbox.php
new file mode 100644
index 0000000..d4e1bf4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Mailbox.php
@@ -0,0 +1,321 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+use DateTimeInterface;
+use Ddeboer\Imap\Exception\ImapNumMsgException;
+use Ddeboer\Imap\Exception\ImapStatusException;
+use Ddeboer\Imap\Exception\InvalidSearchCriteriaException;
+use Ddeboer\Imap\Exception\MessageCopyException;
+use Ddeboer\Imap\Exception\MessageMoveException;
+use Ddeboer\Imap\Search\ConditionInterface;
+use Ddeboer\Imap\Search\LogicalOperator\All;
+
+/**
+ * An IMAP mailbox (commonly referred to as a 'folder').
+ */
+final class Mailbox implements MailboxInterface
+{
+    /**
+     * @var ImapResourceInterface
+     */
+    private $resource;
+
+    /**
+     * @var string
+     */
+    private $name;
+
+    /**
+     * @var \stdClass
+     */
+    private $info;
+
+    /**
+     * Constructor.
+     *
+     * @param ImapResourceInterface $resource IMAP resource
+     * @param string                $name     Mailbox decoded name
+     * @param \stdClass             $info     Mailbox info
+     */
+    public function __construct(ImapResourceInterface $resource, string $name, \stdClass $info)
+    {
+        $this->resource = new ImapResource($resource->getStream(), $this);
+        $this->name     = $name;
+        $this->info     = $info;
+    }
+
+    /**
+     * Get mailbox decoded name.
+     */
+    public function getName(): string
+    {
+        return $this->name;
+    }
+
+    /**
+     * Get mailbox encoded path.
+     */
+    public function getEncodedName(): string
+    {
+        /** @var string $name */
+        $name = $this->info->name;
+
+        return (string) \preg_replace('/^{.+}/', '', $name);
+    }
+
+    /**
+     * Get mailbox encoded full name.
+     */
+    public function getFullEncodedName(): string
+    {
+        return $this->info->name;
+    }
+
+    /**
+     * Get mailbox attributes.
+     */
+    public function getAttributes(): int
+    {
+        return $this->info->attributes;
+    }
+
+    /**
+     * Get mailbox delimiter.
+     */
+    public function getDelimiter(): string
+    {
+        return $this->info->delimiter;
+    }
+
+    /**
+     * Get number of messages in this mailbox.
+     *
+     * @return int
+     */
+    public function count()
+    {
+        $return = \imap_num_msg($this->resource->getStream());
+
+        if (false === $return) {
+            throw new ImapNumMsgException('imap_num_msg failed');
+        }
+
+        return $return;
+    }
+
+    /**
+     * Get Mailbox status.
+     */
+    public function getStatus(int $flags = null): \stdClass
+    {
+        $return = \imap_status($this->resource->getStream(), $this->getFullEncodedName(), $flags ?? \SA_ALL);
+
+        if (false === $return) {
+            throw new ImapStatusException('imap_status failed');
+        }
+
+        return $return;
+    }
+
+    /**
+     * Bulk Set Flag for Messages.
+     *
+     * @param string                       $flag    \Seen, \Answered, \Flagged, \Deleted, and \Draft
+     * @param array|MessageIterator|string $numbers Message numbers
+     */
+    public function setFlag(string $flag, $numbers): bool
+    {
+        return \imap_setflag_full($this->resource->getStream(), $this->prepareMessageIds($numbers), $flag, \ST_UID);
+    }
+
+    /**
+     * Bulk Clear Flag for Messages.
+     *
+     * @param string                       $flag    \Seen, \Answered, \Flagged, \Deleted, and \Draft
+     * @param array|MessageIterator|string $numbers Message numbers
+     */
+    public function clearFlag(string $flag, $numbers): bool
+    {
+        return \imap_clearflag_full($this->resource->getStream(), $this->prepareMessageIds($numbers), $flag, \ST_UID);
+    }
+
+    /**
+     * Get message ids.
+     *
+     * @param ConditionInterface $search Search expression (optional)
+     */
+    public function getMessages(ConditionInterface $search = null, int $sortCriteria = null, bool $descending = false, string $charset = null): MessageIteratorInterface
+    {
+        if (null === $search) {
+            $search = new All();
+        }
+        $query = $search->toString();
+
+        // We need to clear the stack to know whether imap_last_error()
+        // is related to this imap_search
+        \imap_errors();
+
+        if (null !== $sortCriteria) {
+            $params = [
+                $this->resource->getStream(),
+                $sortCriteria,
+                $descending ? 1 : 0,
+                \SE_UID,
+                $query,
+            ];
+            if (null !== $charset) {
+                $params[] = $charset;
+            }
+            $messageNumbers = \imap_sort(...$params);
+        } else {
+            $params = [
+                $this->resource->getStream(),
+                $query,
+                \SE_UID,
+            ];
+            if (null !== $charset) {
+                $params[] = $charset;
+            }
+            $messageNumbers = \imap_search(...$params);
+        }
+        if (false === $messageNumbers) {
+            if (false !== \imap_last_error()) {
+                throw new InvalidSearchCriteriaException(\sprintf('Invalid search criteria [%s]', $query));
+            }
+
+            // imap_search can also return false
+            $messageNumbers = [];
+        }
+
+        return new MessageIterator($this->resource, $messageNumbers);
+    }
+
+    /**
+     * Get message iterator for a sequence.
+     *
+     * @param string $sequence Message numbers
+     */
+    public function getMessageSequence(string $sequence): MessageIteratorInterface
+    {
+        \imap_errors();
+
+        $overview = \imap_fetch_overview($this->resource->getStream(), $sequence, \FT_UID);
+        if (\is_array($overview) && [] !== $overview) {
+            $messageNumbers = \array_column($overview, 'uid');
+        } else {
+            if (false !== \imap_last_error()) {
+                throw new InvalidSearchCriteriaException(\sprintf('Invalid sequence [%s]', $sequence));
+            }
+
+            $messageNumbers = [];
+        }
+
+        return new MessageIterator($this->resource, $messageNumbers);
+    }
+
+    /**
+     * Get a message by message number.
+     *
+     * @param int $number Message number
+     */
+    public function getMessage(int $number): MessageInterface
+    {
+        return new Message($this->resource, $number);
+    }
+
+    /**
+     * Get messages in this mailbox.
+     */
+    public function getIterator(): MessageIteratorInterface
+    {
+        return $this->getMessages();
+    }
+
+    /**
+     * Add a message to the mailbox.
+     */
+    public function addMessage(string $message, string $options = null, DateTimeInterface $internalDate = null): bool
+    {
+        $arguments = [
+            $this->resource->getStream(),
+            $this->getFullEncodedName(),
+            $message,
+        ];
+        if (null !== $options) {
+            $arguments[] = $options;
+            if (null !== $internalDate) {
+                $arguments[] = $internalDate->format('d-M-Y H:i:s O');
+            }
+        }
+
+        return \imap_append(...$arguments);
+    }
+
+    /**
+     * Returns a tree of threaded message for the current Mailbox.
+     */
+    public function getThread(): array
+    {
+        \set_error_handler(static function (): bool {
+            return true;
+        });
+
+        /** @var array|false $tree */
+        $tree = \imap_thread($this->resource->getStream());
+
+        \restore_error_handler();
+
+        return false !== $tree ? $tree : [];
+    }
+
+    /**
+     * Bulk move messages.
+     *
+     * @param array|MessageIterator|string $numbers Message numbers
+     * @param MailboxInterface             $mailbox Destination Mailbox to move the messages to
+     *
+     * @throws \Ddeboer\Imap\Exception\MessageMoveException
+     */
+    public function move($numbers, MailboxInterface $mailbox): void
+    {
+        if (!\imap_mail_move($this->resource->getStream(), $this->prepareMessageIds($numbers), $mailbox->getEncodedName(), \CP_UID)) {
+            throw new MessageMoveException(\sprintf('Messages cannot be moved to "%s"', $mailbox->getName()));
+        }
+    }
+
+    /**
+     * Bulk copy messages.
+     *
+     * @param array|MessageIterator|string $numbers Message numbers
+     * @param MailboxInterface             $mailbox Destination Mailbox to copy the messages to
+     *
+     * @throws \Ddeboer\Imap\Exception\MessageCopyException
+     */
+    public function copy($numbers, MailboxInterface $mailbox): void
+    {
+        if (!\imap_mail_copy($this->resource->getStream(), $this->prepareMessageIds($numbers), $mailbox->getEncodedName(), \CP_UID)) {
+            throw new MessageCopyException(\sprintf('Messages cannot be copied to "%s"', $mailbox->getName()));
+        }
+    }
+
+    /**
+     * Prepare message ids for the use with bulk functions.
+     *
+     * @param array|MessageIterator|string $messageIds Message numbers
+     */
+    private function prepareMessageIds($messageIds): string
+    {
+        if ($messageIds instanceof MessageIterator) {
+            $messageIds = $messageIds->getArrayCopy();
+        }
+
+        if (\is_array($messageIds)) {
+            $messageIds = \implode(',', $messageIds);
+        }
+
+        return $messageIds;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php
new file mode 100644
index 0000000..efe432d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MailboxInterface.php
@@ -0,0 +1,116 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+use DateTimeInterface;
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * An IMAP mailbox (commonly referred to as a 'folder').
+ */
+interface MailboxInterface extends \Countable, \IteratorAggregate
+{
+    /**
+     * Get mailbox decoded name.
+     */
+    public function getName(): string;
+
+    /**
+     * Get mailbox encoded path.
+     */
+    public function getEncodedName(): string;
+
+    /**
+     * Get mailbox encoded full name.
+     */
+    public function getFullEncodedName(): string;
+
+    /**
+     * Get mailbox attributes.
+     */
+    public function getAttributes(): int;
+
+    /**
+     * Get mailbox delimiter.
+     */
+    public function getDelimiter(): string;
+
+    /**
+     * Get Mailbox status.
+     */
+    public function getStatus(int $flags = null): \stdClass;
+
+    /**
+     * Bulk Set Flag for Messages.
+     *
+     * @param string                       $flag    \Seen, \Answered, \Flagged, \Deleted, and \Draft
+     * @param array|MessageIterator|string $numbers Message numbers
+     */
+    public function setFlag(string $flag, $numbers): bool;
+
+    /**
+     * Bulk Clear Flag for Messages.
+     *
+     * @param string                       $flag    \Seen, \Answered, \Flagged, \Deleted, and \Draft
+     * @param array|MessageIterator|string $numbers Message numbers
+     */
+    public function clearFlag(string $flag, $numbers): bool;
+
+    /**
+     * Get message ids.
+     *
+     * @param ConditionInterface $search Search expression (optional)
+     */
+    public function getMessages(ConditionInterface $search = null, int $sortCriteria = null, bool $descending = false, string $charset = null): MessageIteratorInterface;
+
+    /**
+     * Get message iterator for a sequence.
+     *
+     * @param string $sequence Message numbers
+     */
+    public function getMessageSequence(string $sequence): MessageIteratorInterface;
+
+    /**
+     * Get a message by message number.
+     *
+     * @param int $number Message number
+     */
+    public function getMessage(int $number): MessageInterface;
+
+    /**
+     * Get messages in this mailbox.
+     */
+    public function getIterator(): MessageIteratorInterface;
+
+    /**
+     * Add a message to the mailbox.
+     */
+    public function addMessage(string $message, string $options = null, DateTimeInterface $internalDate = null): bool;
+
+    /**
+     * Returns a tree of threaded message for the current Mailbox.
+     */
+    public function getThread(): array;
+
+    /**
+     * Bulk move messages.
+     *
+     * @param array|MessageIterator|string $numbers Message numbers
+     * @param MailboxInterface             $mailbox Destination Mailbox to move the messages to
+     *
+     * @throws \Ddeboer\Imap\Exception\MessageMoveException
+     */
+    public function move($numbers, self $mailbox): void;
+
+    /**
+     * Bulk copy messages.
+     *
+     * @param array|MessageIterator|string $numbers Message numbers
+     * @param MailboxInterface             $mailbox Destination Mailbox to copy the messages to
+     *
+     * @throws \Ddeboer\Imap\Exception\MessageCopyException
+     */
+    public function copy($numbers, self $mailbox): void;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php
new file mode 100644
index 0000000..7b50777
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message.php
@@ -0,0 +1,355 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+use Ddeboer\Imap\Exception\ImapFetchheaderException;
+use Ddeboer\Imap\Exception\InvalidHeadersException;
+use Ddeboer\Imap\Exception\MessageCopyException;
+use Ddeboer\Imap\Exception\MessageDeleteException;
+use Ddeboer\Imap\Exception\MessageDoesNotExistException;
+use Ddeboer\Imap\Exception\MessageMoveException;
+use Ddeboer\Imap\Exception\MessageStructureException;
+use Ddeboer\Imap\Exception\MessageUndeleteException;
+
+/**
+ * An IMAP message (e-mail).
+ */
+final class Message extends Message\AbstractMessage implements MessageInterface
+{
+    /**
+     * @var bool
+     */
+    private $messageNumberVerified = false;
+
+    /**
+     * @var int
+     */
+    private $imapMsgNo = 0;
+
+    /**
+     * @var bool
+     */
+    private $structureLoaded = false;
+
+    /**
+     * @var null|Message\Headers
+     */
+    private $headers;
+
+    /**
+     * @var null|string
+     */
+    private $rawHeaders;
+
+    /**
+     * @var null|string
+     */
+    private $rawMessage;
+
+    /**
+     * Constructor.
+     *
+     * @param ImapResourceInterface $resource      IMAP resource
+     * @param int                   $messageNumber Message number
+     */
+    public function __construct(ImapResourceInterface $resource, int $messageNumber)
+    {
+        parent::__construct($resource, $messageNumber, '1', new \stdClass());
+    }
+
+    /**
+     * Lazy load structure.
+     */
+    protected function lazyLoadStructure(): void
+    {
+        if (true === $this->structureLoaded) {
+            return;
+        }
+        $this->structureLoaded = true;
+
+        $messageNumber = $this->getNumber();
+
+        $errorMessage = null;
+        $errorNumber  = 0;
+        \set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber): bool {
+            $errorMessage = $message;
+            $errorNumber = $nr;
+
+            return true;
+        });
+
+        $structure = \imap_fetchstructure(
+            $this->resource->getStream(),
+            $messageNumber,
+            \FT_UID
+        );
+
+        \restore_error_handler();
+
+        if (!$structure instanceof \stdClass) {
+            throw new MessageStructureException(\sprintf(
+                'Message "%s" structure is empty: %s',
+                $messageNumber,
+                $errorMessage
+            ), $errorNumber);
+        }
+
+        $this->setStructure($structure);
+    }
+
+    /**
+     * Ensure message exists.
+     */
+    protected function assertMessageExists(int $messageNumber): void
+    {
+        if (true === $this->messageNumberVerified) {
+            return;
+        }
+        $this->messageNumberVerified = true;
+
+        $msgno = \imap_msgno($this->resource->getStream(), $messageNumber);
+        if (\is_numeric($msgno) && $msgno > 0) {
+            $this->imapMsgNo = $msgno;
+
+            return;
+        }
+
+        throw new MessageDoesNotExistException(\sprintf(
+            'Message "%s" does not exist',
+            $messageNumber
+        ));
+    }
+
+    private function getMsgNo(): int
+    {
+        // Triggers assertMessageExists()
+        $this->getNumber();
+
+        return $this->imapMsgNo;
+    }
+
+    /**
+     * Get raw message headers.
+     */
+    public function getRawHeaders(): string
+    {
+        if (null === $this->rawHeaders) {
+            $rawHeaders = \imap_fetchheader($this->resource->getStream(), $this->getNumber(), \FT_UID);
+
+            if (false === $rawHeaders) {
+                throw new ImapFetchheaderException('imap_fetchheader failed');
+            }
+
+            $this->rawHeaders = $rawHeaders;
+        }
+
+        return $this->rawHeaders;
+    }
+
+    /**
+     * Get the raw message, including all headers, parts, etc. unencoded and unparsed.
+     *
+     * @return string the raw message
+     */
+    public function getRawMessage(): string
+    {
+        if (null === $this->rawMessage) {
+            $this->rawMessage = $this->doGetContent('');
+        }
+
+        return $this->rawMessage;
+    }
+
+    /**
+     * Get message headers.
+     */
+    public function getHeaders(): Message\Headers
+    {
+        if (null === $this->headers) {
+            // imap_headerinfo is much faster than imap_fetchheader
+            // imap_headerinfo returns only a subset of all mail headers,
+            // but it does include the message flags.
+            $headers = \imap_headerinfo($this->resource->getStream(), $this->getMsgNo());
+            if (false === $headers) {
+                // @see https://github.com/ddeboer/imap/issues/358
+                throw new InvalidHeadersException(\sprintf('Message "%s" has invalid headers', $this->getNumber()));
+            }
+            $this->headers = new Message\Headers($headers);
+        }
+
+        return $this->headers;
+    }
+
+    /**
+     * Clearmessage headers.
+     */
+    private function clearHeaders(): void
+    {
+        $this->headers = null;
+    }
+
+    /**
+     * Get message recent flag value (from headers).
+     */
+    public function isRecent(): ?string
+    {
+        return $this->getHeaders()->get('recent');
+    }
+
+    /**
+     * Get message unseen flag value (from headers).
+     */
+    public function isUnseen(): bool
+    {
+        return 'U' === $this->getHeaders()->get('unseen');
+    }
+
+    /**
+     * Get message flagged flag value (from headers).
+     */
+    public function isFlagged(): bool
+    {
+        return 'F' === $this->getHeaders()->get('flagged');
+    }
+
+    /**
+     * Get message answered flag value (from headers).
+     */
+    public function isAnswered(): bool
+    {
+        return 'A' === $this->getHeaders()->get('answered');
+    }
+
+    /**
+     * Get message deleted flag value (from headers).
+     */
+    public function isDeleted(): bool
+    {
+        return 'D' === $this->getHeaders()->get('deleted');
+    }
+
+    /**
+     * Get message draft flag value (from headers).
+     */
+    public function isDraft(): bool
+    {
+        return 'X' === $this->getHeaders()->get('draft');
+    }
+
+    /**
+     * Has the message been marked as read?
+     */
+    public function isSeen(): bool
+    {
+        return 'N' !== $this->getHeaders()->get('recent') && 'U' !== $this->getHeaders()->get('unseen');
+    }
+
+    /**
+     * Mark message as seen.
+     *
+     * @deprecated since version 1.1, to be removed in 2.0
+     */
+    public function maskAsSeen(): bool
+    {
+        \trigger_error(\sprintf('%s is deprecated and will be removed in 2.0. Use %s::markAsSeen instead.', __METHOD__, __CLASS__), \E_USER_DEPRECATED);
+
+        return $this->markAsSeen();
+    }
+
+    /**
+     * Mark message as seen.
+     */
+    public function markAsSeen(): bool
+    {
+        return $this->setFlag('\\Seen');
+    }
+
+    /**
+     * Move message to another mailbox.
+     *
+     * @throws MessageCopyException
+     */
+    public function copy(MailboxInterface $mailbox): void
+    {
+        // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header
+        $this->clearHeaders();
+
+        if (!\imap_mail_copy($this->resource->getStream(), (string) $this->getNumber(), $mailbox->getEncodedName(), \CP_UID)) {
+            throw new MessageCopyException(\sprintf('Message "%s" cannot be copied to "%s"', $this->getNumber(), $mailbox->getName()));
+        }
+    }
+
+    /**
+     * Move message to another mailbox.
+     *
+     * @throws MessageMoveException
+     */
+    public function move(MailboxInterface $mailbox): void
+    {
+        // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header
+        $this->clearHeaders();
+
+        if (!\imap_mail_move($this->resource->getStream(), (string) $this->getNumber(), $mailbox->getEncodedName(), \CP_UID)) {
+            throw new MessageMoveException(\sprintf('Message "%s" cannot be moved to "%s"', $this->getNumber(), $mailbox->getName()));
+        }
+    }
+
+    /**
+     * Delete message.
+     *
+     * @throws MessageDeleteException
+     */
+    public function delete(): void
+    {
+        // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header
+        $this->clearHeaders();
+
+        if (!\imap_delete($this->resource->getStream(), $this->getNumber(), \FT_UID)) {
+            throw new MessageDeleteException(\sprintf('Message "%s" cannot be deleted', $this->getNumber()));
+        }
+    }
+
+    /**
+     * Undelete message.
+     *
+     * @throws MessageUndeleteException
+     */
+    public function undelete(): void
+    {
+        // 'deleted' header changed, force to reload headers, would be better to set deleted flag to false on header
+        $this->clearHeaders();
+        if (!\imap_undelete($this->resource->getStream(), $this->getNumber(), \FT_UID)) {
+            throw new MessageUndeleteException(\sprintf('Message "%s" cannot be undeleted', $this->getNumber()));
+        }
+    }
+
+    /**
+     * Set Flag Message.
+     *
+     * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
+     */
+    public function setFlag(string $flag): bool
+    {
+        $result = \imap_setflag_full($this->resource->getStream(), (string) $this->getNumber(), $flag, \ST_UID);
+
+        $this->clearHeaders();
+
+        return $result;
+    }
+
+    /**
+     * Clear Flag Message.
+     *
+     * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
+     */
+    public function clearFlag(string $flag): bool
+    {
+        $result = \imap_clearflag_full($this->resource->getStream(), (string) $this->getNumber(), $flag, \ST_UID);
+
+        $this->clearHeaders();
+
+        return $result;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php
new file mode 100644
index 0000000..9187c38
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractMessage.php
@@ -0,0 +1,266 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+use Ddeboer\Imap\Exception\InvalidDateHeaderException;
+
+abstract class AbstractMessage extends AbstractPart
+{
+    /**
+     * @var null|array
+     */
+    private $attachments;
+
+    /**
+     * Get message headers.
+     */
+    abstract public function getHeaders(): Headers;
+
+    /**
+     * Get message id.
+     *
+     * A unique message id in the form <...>
+     */
+    final public function getId(): ?string
+    {
+        return $this->getHeaders()->get('message_id');
+    }
+
+    /**
+     * Get message sender (from headers).
+     */
+    final public function getFrom(): ?EmailAddress
+    {
+        $from = $this->getHeaders()->get('from');
+
+        return null !== $from ? $this->decodeEmailAddress($from[0]) : null;
+    }
+
+    /**
+     * Get To recipients.
+     *
+     * @return EmailAddress[] Empty array in case message has no To: recipients
+     */
+    final public function getTo(): array
+    {
+        return $this->decodeEmailAddresses($this->getHeaders()->get('to') ?: []);
+    }
+
+    /**
+     * Get Cc recipients.
+     *
+     * @return EmailAddress[] Empty array in case message has no CC: recipients
+     */
+    final public function getCc(): array
+    {
+        return $this->decodeEmailAddresses($this->getHeaders()->get('cc') ?: []);
+    }
+
+    /**
+     * Get Bcc recipients.
+     *
+     * @return EmailAddress[] Empty array in case message has no BCC: recipients
+     */
+    final public function getBcc(): array
+    {
+        return $this->decodeEmailAddresses($this->getHeaders()->get('bcc') ?: []);
+    }
+
+    /**
+     * Get Reply-To recipients.
+     *
+     * @return EmailAddress[] Empty array in case message has no Reply-To: recipients
+     */
+    final public function getReplyTo(): array
+    {
+        return $this->decodeEmailAddresses($this->getHeaders()->get('reply_to') ?: []);
+    }
+
+    /**
+     * Get Sender.
+     *
+     * @return EmailAddress[] Empty array in case message has no Sender: recipients
+     */
+    final public function getSender(): array
+    {
+        return $this->decodeEmailAddresses($this->getHeaders()->get('sender') ?: []);
+    }
+
+    /**
+     * Get Return-Path.
+     *
+     * @return EmailAddress[] Empty array in case message has no Return-Path: recipients
+     */
+    final public function getReturnPath(): array
+    {
+        return $this->decodeEmailAddresses($this->getHeaders()->get('return_path') ?: []);
+    }
+
+    /**
+     * Get date (from headers).
+     */
+    final public function getDate(): ?\DateTimeImmutable
+    {
+        /** @var null|string $dateHeader */
+        $dateHeader = $this->getHeaders()->get('date');
+        if (null === $dateHeader) {
+            return null;
+        }
+
+        $alteredValue = $dateHeader;
+        $alteredValue = \str_replace(',', '', $alteredValue);
+        $alteredValue = (string) \preg_replace('/^[a-zA-Z]+ ?/', '', $alteredValue);
+        $alteredValue = (string) \preg_replace('/\(.*\)/', '', $alteredValue);
+        $alteredValue = (string) \preg_replace('/\bUT\b/', 'UTC', $alteredValue);
+        if (0 === \preg_match('/\d\d:\d\d:\d\d.* [\+\-]\d\d:?\d\d/', $alteredValue)) {
+            $alteredValue .= ' +0000';
+        }
+        // Handle numeric months
+        $alteredValue = (string) \preg_replace('/^(\d\d) (\d\d) (\d\d(?:\d\d)?) /', '$3-$2-$1 ', $alteredValue);
+
+        try {
+            $date = new \DateTimeImmutable($alteredValue);
+        } catch (\Throwable $ex) {
+            throw new InvalidDateHeaderException(\sprintf('Invalid Date header found: "%s"', $dateHeader), 0, $ex);
+        }
+
+        return $date;
+    }
+
+    /**
+     * Get message size (from headers).
+     *
+     * @return null|int|string
+     */
+    final public function getSize()
+    {
+        return $this->getHeaders()->get('size');
+    }
+
+    /**
+     * Get message subject (from headers).
+     */
+    final public function getSubject(): ?string
+    {
+        return $this->getHeaders()->get('subject');
+    }
+
+    /**
+     * Get message In-Reply-To (from headers).
+     */
+    final public function getInReplyTo(): array
+    {
+        $inReplyTo = $this->getHeaders()->get('in_reply_to');
+
+        return null !== $inReplyTo ? \explode(' ', $inReplyTo) : [];
+    }
+
+    /**
+     * Get message References (from headers).
+     */
+    final public function getReferences(): array
+    {
+        $references = $this->getHeaders()->get('references');
+
+        return null !== $references ? \explode(' ', $references) : [];
+    }
+
+    /**
+     * Get body HTML.
+     */
+    final public function getBodyHtml(): ?string
+    {
+        $iterator = new \RecursiveIteratorIterator($this, \RecursiveIteratorIterator::SELF_FIRST);
+        foreach ($iterator as $part) {
+            if (self::SUBTYPE_HTML === $part->getSubtype()) {
+                return $part->getDecodedContent();
+            }
+        }
+
+        // If message has no parts and is HTML, return content of message itself.
+        if (self::SUBTYPE_HTML === $this->getSubtype()) {
+            return $this->getDecodedContent();
+        }
+
+        return null;
+    }
+
+    /**
+     * Get body text.
+     */
+    final public function getBodyText(): ?string
+    {
+        $iterator = new \RecursiveIteratorIterator($this, \RecursiveIteratorIterator::SELF_FIRST);
+        foreach ($iterator as $part) {
+            if (self::SUBTYPE_PLAIN === $part->getSubtype()) {
+                return $part->getDecodedContent();
+            }
+        }
+
+        // If message has no parts, return content of message itself.
+        if (self::SUBTYPE_PLAIN === $this->getSubtype()) {
+            return $this->getDecodedContent();
+        }
+
+        return null;
+    }
+
+    /**
+     * Get attachments (if any) linked to this e-mail.
+     *
+     * @return AttachmentInterface[]
+     */
+    final public function getAttachments(): array
+    {
+        if (null === $this->attachments) {
+            $this->attachments = self::gatherAttachments($this);
+        }
+
+        return $this->attachments;
+    }
+
+    private static function gatherAttachments(PartInterface $part): array
+    {
+        $attachments = [];
+        foreach ($part->getParts() as $childPart) {
+            if ($childPart instanceof Attachment) {
+                $attachments[] = $childPart;
+            }
+            if ($childPart->hasChildren()) {
+                $attachments = \array_merge($attachments, self::gatherAttachments($childPart));
+            }
+        }
+
+        return $attachments;
+    }
+
+    /**
+     * Does this message have attachments?
+     */
+    final public function hasAttachments(): bool
+    {
+        return \count($this->getAttachments()) > 0;
+    }
+
+    /**
+     * @param \stdClass[] $addresses
+     */
+    private function decodeEmailAddresses(array $addresses): array
+    {
+        $return = [];
+        foreach ($addresses as $address) {
+            if (isset($address->mailbox)) {
+                $return[] = $this->decodeEmailAddress($address);
+            }
+        }
+
+        return $return;
+    }
+
+    private function decodeEmailAddress(\stdClass $value): EmailAddress
+    {
+        return new EmailAddress($value->mailbox, $value->host, $value->personal);
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php
new file mode 100644
index 0000000..923f300
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AbstractPart.php
@@ -0,0 +1,572 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+use Ddeboer\Imap\Exception\ImapFetchbodyException;
+use Ddeboer\Imap\Exception\UnexpectedEncodingException;
+use Ddeboer\Imap\ImapResourceInterface;
+use Ddeboer\Imap\Message;
+
+/**
+ * A message part.
+ */
+abstract class AbstractPart implements PartInterface
+{
+    /**
+     * @var ImapResourceInterface
+     */
+    protected $resource;
+
+    /**
+     * @var bool
+     */
+    private $structureParsed = false;
+
+    /**
+     * @var array
+     */
+    private $parts = [];
+
+    /**
+     * @var string
+     */
+    private $partNumber;
+
+    /**
+     * @var int
+     */
+    private $messageNumber;
+
+    /**
+     * @var \stdClass
+     */
+    private $structure;
+
+    /**
+     * @var Parameters
+     */
+    private $parameters;
+
+    /**
+     * @var null|string
+     */
+    private $type;
+
+    /**
+     * @var null|string
+     */
+    private $subtype;
+
+    /**
+     * @var null|string
+     */
+    private $encoding;
+
+    /**
+     * @var null|string
+     */
+    private $disposition;
+
+    /**
+     * @var null|string
+     */
+    private $description;
+
+    /**
+     * @var null|string
+     */
+    private $bytes;
+
+    /**
+     * @var null|string
+     */
+    private $lines;
+
+    /**
+     * @var null|string
+     */
+    private $content;
+
+    /**
+     * @var null|string
+     */
+    private $decodedContent;
+
+    /**
+     * @var int
+     */
+    private $key = 0;
+
+    /**
+     * @var array
+     */
+    private static $typesMap = [
+        \TYPETEXT        => self::TYPE_TEXT,
+        \TYPEMULTIPART   => self::TYPE_MULTIPART,
+        \TYPEMESSAGE     => self::TYPE_MESSAGE,
+        \TYPEAPPLICATION => self::TYPE_APPLICATION,
+        \TYPEAUDIO       => self::TYPE_AUDIO,
+        \TYPEIMAGE       => self::TYPE_IMAGE,
+        \TYPEVIDEO       => self::TYPE_VIDEO,
+        \TYPEMODEL       => self::TYPE_MODEL,
+        \TYPEOTHER       => self::TYPE_OTHER,
+    ];
+
+    /**
+     * @var array
+     */
+    private static $encodingsMap = [
+        \ENC7BIT            => self::ENCODING_7BIT,
+        \ENC8BIT            => self::ENCODING_8BIT,
+        \ENCBINARY          => self::ENCODING_BINARY,
+        \ENCBASE64          => self::ENCODING_BASE64,
+        \ENCQUOTEDPRINTABLE => self::ENCODING_QUOTED_PRINTABLE,
+    ];
+
+    /**
+     * @var array
+     */
+    private static $attachmentKeys = [
+        'name'      => true,
+        'filename'  => true,
+        'name*'     => true,
+        'filename*' => true,
+    ];
+
+    /**
+     * Constructor.
+     *
+     * @param ImapResourceInterface $resource      IMAP resource
+     * @param int                   $messageNumber Message number
+     * @param string                $partNumber    Part number
+     * @param \stdClass             $structure     Part structure
+     */
+    public function __construct(
+        ImapResourceInterface $resource,
+        int $messageNumber,
+        string $partNumber,
+        \stdClass $structure
+    ) {
+        $this->resource      = $resource;
+        $this->messageNumber = $messageNumber;
+        $this->partNumber    = $partNumber;
+        $this->setStructure($structure);
+    }
+
+    /**
+     * Get message number (from headers).
+     */
+    final public function getNumber(): int
+    {
+        $this->assertMessageExists($this->messageNumber);
+
+        return $this->messageNumber;
+    }
+
+    /**
+     * Ensure message exists.
+     */
+    protected function assertMessageExists(int $messageNumber): void
+    {
+    }
+
+    /**
+     * @param \stdClass $structure Part structure
+     */
+    final protected function setStructure(\stdClass $structure): void
+    {
+        $this->structure = $structure;
+    }
+
+    /**
+     * Part structure.
+     */
+    final public function getStructure(): \stdClass
+    {
+        $this->lazyLoadStructure();
+
+        return $this->structure;
+    }
+
+    /**
+     * Lazy load structure.
+     */
+    protected function lazyLoadStructure(): void
+    {
+    }
+
+    /**
+     * Part parameters.
+     */
+    final public function getParameters(): Parameters
+    {
+        $this->lazyParseStructure();
+
+        return $this->parameters;
+    }
+
+    /**
+     * Part charset.
+     */
+    final public function getCharset(): ?string
+    {
+        $this->lazyParseStructure();
+
+        return $this->parameters->get('charset') ?: null;
+    }
+
+    /**
+     * Part type.
+     */
+    final public function getType(): ?string
+    {
+        $this->lazyParseStructure();
+
+        return $this->type;
+    }
+
+    /**
+     * Part subtype.
+     */
+    final public function getSubtype(): ?string
+    {
+        $this->lazyParseStructure();
+
+        return $this->subtype;
+    }
+
+    /**
+     * Part encoding.
+     */
+    final public function getEncoding(): ?string
+    {
+        $this->lazyParseStructure();
+
+        return $this->encoding;
+    }
+
+    /**
+     * Part disposition.
+     */
+    final public function getDisposition(): ?string
+    {
+        $this->lazyParseStructure();
+
+        return $this->disposition;
+    }
+
+    /**
+     * Part description.
+     */
+    final public function getDescription(): ?string
+    {
+        $this->lazyParseStructure();
+
+        return $this->description;
+    }
+
+    /**
+     * Part bytes.
+     *
+     * @return null|int|string
+     */
+    final public function getBytes()
+    {
+        $this->lazyParseStructure();
+
+        return $this->bytes;
+    }
+
+    /**
+     * Part lines.
+     */
+    final public function getLines(): ?string
+    {
+        $this->lazyParseStructure();
+
+        return $this->lines;
+    }
+
+    /**
+     * Get raw part content.
+     */
+    final public function getContent(): string
+    {
+        if (null === $this->content) {
+            $this->content = $this->doGetContent($this->getContentPartNumber());
+        }
+
+        return $this->content;
+    }
+
+    /**
+     * Get content part number.
+     */
+    protected function getContentPartNumber(): string
+    {
+        return $this->partNumber;
+    }
+
+    /**
+     * Get part number.
+     */
+    final public function getPartNumber(): string
+    {
+        return $this->partNumber;
+    }
+
+    /**
+     * Get decoded part content.
+     */
+    final public function getDecodedContent(): string
+    {
+        if (null === $this->decodedContent) {
+            if (self::ENCODING_UNKNOWN === $this->getEncoding()) {
+                throw new UnexpectedEncodingException('Cannot decode a content with an uknown encoding');
+            }
+
+            $content = $this->getContent();
+            if (self::ENCODING_BASE64 === $this->getEncoding()) {
+                $content = \base64_decode($content, false);
+            } elseif (self::ENCODING_QUOTED_PRINTABLE === $this->getEncoding()) {
+                $content = \quoted_printable_decode($content);
+            }
+
+            if (false === $content) {
+                throw new UnexpectedEncodingException('Cannot decode content');
+            }
+
+            // If this part is a text part, convert its charset to UTF-8.
+            // We don't want to decode an attachment's charset.
+            if (!$this instanceof Attachment && null !== $this->getCharset() && self::TYPE_TEXT === $this->getType()) {
+                $content = Transcoder::decode($content, $this->getCharset());
+            }
+
+            $this->decodedContent = $content;
+        }
+
+        return $this->decodedContent;
+    }
+
+    /**
+     * Get raw message content.
+     */
+    final protected function doGetContent(string $partNumber): string
+    {
+        $return = \imap_fetchbody(
+            $this->resource->getStream(),
+            $this->getNumber(),
+            $partNumber,
+            \FT_UID | \FT_PEEK
+        );
+
+        if (false === $return) {
+            throw new ImapFetchbodyException('imap_fetchbody failed');
+        }
+
+        return $return;
+    }
+
+    /**
+     * Get an array of all parts for this message.
+     *
+     * @return PartInterface[]
+     */
+    final public function getParts(): array
+    {
+        $this->lazyParseStructure();
+
+        return $this->parts;
+    }
+
+    /**
+     * Get current child part.
+     *
+     * @return mixed
+     */
+    final public function current()
+    {
+        $this->lazyParseStructure();
+
+        return $this->parts[$this->key];
+    }
+
+    /**
+     * Get current child part.
+     *
+     * @return \RecursiveIterator
+     */
+    final public function getChildren()
+    {
+        return $this->current();
+    }
+
+    /**
+     * Get current child part.
+     *
+     * @return bool
+     */
+    final public function hasChildren()
+    {
+        $this->lazyParseStructure();
+
+        return \count($this->parts) > 0;
+    }
+
+    /**
+     * Get current part key.
+     *
+     * @return int
+     */
+    final public function key()
+    {
+        return $this->key;
+    }
+
+    /**
+     * Move to next part.
+     *
+     * @return void
+     */
+    final public function next()
+    {
+        ++$this->key;
+    }
+
+    /**
+     * Reset part key.
+     *
+     * @return void
+     */
+    final public function rewind()
+    {
+        $this->key = 0;
+    }
+
+    /**
+     * Check if current part is a valid one.
+     *
+     * @return bool
+     */
+    final public function valid()
+    {
+        $this->lazyParseStructure();
+
+        return isset($this->parts[$this->key]);
+    }
+
+    /**
+     * Parse part structure.
+     */
+    private function lazyParseStructure(): void
+    {
+        if (true === $this->structureParsed) {
+            return;
+        }
+        $this->structureParsed = true;
+
+        $this->lazyLoadStructure();
+
+        $this->type = self::$typesMap[$this->structure->type] ?? self::TYPE_UNKNOWN;
+
+        // In our context, \ENCOTHER is as useful as an uknown encoding
+        $this->encoding = self::$encodingsMap[$this->structure->encoding] ?? self::ENCODING_UNKNOWN;
+        $this->subtype  = $this->structure->subtype;
+
+        if (isset($this->structure->bytes)) {
+            $this->bytes = $this->structure->bytes;
+        }
+        if ($this->structure->ifdisposition) {
+            $this->disposition = $this->structure->disposition;
+        }
+        if ($this->structure->ifdescription) {
+            $this->description = $this->structure->description;
+        }
+
+        $this->parameters = new Parameters();
+        if ($this->structure->ifparameters) {
+            $this->parameters->add($this->structure->parameters);
+        }
+
+        if ($this->structure->ifdparameters) {
+            $this->parameters->add($this->structure->dparameters);
+        }
+
+        // When the message is not multipart and the body is the attachment content
+        // Prevents infinite recursion
+        if (self::isAttachment($this->structure) && !$this instanceof Attachment) {
+            $this->parts[] = new Attachment($this->resource, $this->getNumber(), '1', $this->structure);
+        }
+
+        if (isset($this->structure->parts)) {
+            $parts = $this->structure->parts;
+            // https://secure.php.net/manual/en/function.imap-fetchbody.php#89002
+            if ($this instanceof Attachment && $this->isEmbeddedMessage() && 1 === \count($parts) && \TYPEMULTIPART === $parts[0]->type) {
+                $parts = $parts[0]->parts;
+            }
+            foreach ($parts as $key => $partStructure) {
+                $partNumber = (!$this instanceof Message) ? $this->partNumber . '.' : '';
+                $partNumber .= (string) ($key + 1);
+
+                $newPartClass = self::isAttachment($partStructure)
+                    ? Attachment::class
+                    : SimplePart::class
+                ;
+
+                $this->parts[] = new $newPartClass($this->resource, $this->getNumber(), $partNumber, $partStructure);
+            }
+        }
+    }
+
+    /**
+     * Check if the given part is an attachment.
+     */
+    private static function isAttachment(\stdClass $part): bool
+    {
+        if (isset(self::$typesMap[$part->type]) && self::TYPE_MULTIPART === self::$typesMap[$part->type]) {
+            return false;
+        }
+
+        // Attachment with correct Content-Disposition header
+        if ($part->ifdisposition) {
+            if ('attachment' === \strtolower($part->disposition)) {
+                return true;
+            }
+
+            if (
+                    'inline' === \strtolower($part->disposition)
+                && self::SUBTYPE_PLAIN !== \strtoupper($part->subtype)
+                && self::SUBTYPE_HTML !== \strtoupper($part->subtype)
+            ) {
+                return true;
+            }
+        }
+
+        // Attachment without Content-Disposition header
+        if ($part->ifparameters) {
+            foreach ($part->parameters as $parameter) {
+                if (isset(self::$attachmentKeys[\strtolower($parameter->attribute)])) {
+                    return true;
+                }
+            }
+        }
+
+        /*
+        if ($part->ifdparameters) {
+            foreach ($part->dparameters as $parameter) {
+                if (isset(self::$attachmentKeys[\strtolower($parameter->attribute)])) {
+                    return true;
+                }
+            }
+        }
+         */
+
+        if (self::SUBTYPE_RFC822 === \strtoupper($part->subtype)) {
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php
new file mode 100644
index 0000000..bd76769
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Attachment.php
@@ -0,0 +1,63 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+use Ddeboer\Imap\Exception\NotEmbeddedMessageException;
+
+/**
+ * An e-mail attachment.
+ */
+final class Attachment extends AbstractPart implements AttachmentInterface
+{
+    /**
+     * Get attachment filename.
+     */
+    public function getFilename(): ?string
+    {
+        return $this->getParameters()->get('filename')
+            ?: $this->getParameters()->get('name');
+    }
+
+    /**
+     * Get attachment file size.
+     *
+     * @return null|int Number of bytes
+     */
+    public function getSize()
+    {
+        $size = $this->getParameters()->get('size');
+        if (\is_numeric($size)) {
+            $size = (int) $size;
+        }
+
+        return $size;
+    }
+
+    /**
+     * Is this attachment also an Embedded Message?
+     */
+    public function isEmbeddedMessage(): bool
+    {
+        return self::TYPE_MESSAGE === $this->getType();
+    }
+
+    /**
+     * Return embedded message.
+     *
+     * @throws NotEmbeddedMessageException
+     */
+    public function getEmbeddedMessage(): EmbeddedMessageInterface
+    {
+        if (!$this->isEmbeddedMessage()) {
+            throw new NotEmbeddedMessageException(\sprintf(
+                'Attachment "%s" in message "%s" is not embedded message',
+                $this->getPartNumber(),
+                $this->getNumber()
+            ));
+        }
+
+        return new EmbeddedMessage($this->resource, $this->getNumber(), $this->getPartNumber(), $this->getStructure()->parts[0]);
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php
new file mode 100644
index 0000000..0d20f44
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/AttachmentInterface.php
@@ -0,0 +1,33 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+/**
+ * An e-mail attachment.
+ */
+interface AttachmentInterface extends PartInterface
+{
+    /**
+     * Get attachment filename.
+     */
+    public function getFilename(): ?string;
+
+    /**
+     * Get attachment file size.
+     *
+     * @return null|int Number of bytes
+     */
+    public function getSize();
+
+    /**
+     * Is this attachment also an Embedded Message?
+     */
+    public function isEmbeddedMessage(): bool;
+
+    /**
+     * Return embedded message.
+     */
+    public function getEmbeddedMessage(): EmbeddedMessageInterface;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/BasicMessageInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/BasicMessageInterface.php
new file mode 100644
index 0000000..20e6b1a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/BasicMessageInterface.php
@@ -0,0 +1,130 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+interface BasicMessageInterface extends PartInterface
+{
+    /**
+     * Get raw message headers.
+     */
+    public function getRawHeaders(): string;
+
+    /**
+     * Get the raw message, including all headers, parts, etc. unencoded and unparsed.
+     *
+     * @return string the raw message
+     */
+    public function getRawMessage(): string;
+
+    /**
+     * Get message headers.
+     */
+    public function getHeaders(): Headers;
+
+    /**
+     * Get message id.
+     *
+     * A unique message id in the form <...>
+     */
+    public function getId(): ?string;
+
+    /**
+     * Get message sender (from headers).
+     */
+    public function getFrom(): ?EmailAddress;
+
+    /**
+     * Get To recipients.
+     *
+     * @return EmailAddress[] Empty array in case message has no To: recipients
+     */
+    public function getTo(): array;
+
+    /**
+     * Get Cc recipients.
+     *
+     * @return EmailAddress[] Empty array in case message has no CC: recipients
+     */
+    public function getCc(): array;
+
+    /**
+     * Get Bcc recipients.
+     *
+     * @return EmailAddress[] Empty array in case message has no BCC: recipients
+     */
+    public function getBcc(): array;
+
+    /**
+     * Get Reply-To recipients.
+     *
+     * @return EmailAddress[] Empty array in case message has no Reply-To: recipients
+     */
+    public function getReplyTo(): array;
+
+    /**
+     * Get Sender.
+     *
+     * @return EmailAddress[] Empty array in case message has no Sender: recipients
+     */
+    public function getSender(): array;
+
+    /**
+     * Get Return-Path.
+     *
+     * @return EmailAddress[] Empty array in case message has no Return-Path: recipients
+     */
+    public function getReturnPath(): array;
+
+    /**
+     * Get date (from headers).
+     */
+    public function getDate(): ?\DateTimeImmutable;
+
+    /**
+     * Get message size (from headers).
+     *
+     * @return null|int|string
+     */
+    public function getSize();
+
+    /**
+     * Get message subject (from headers).
+     */
+    public function getSubject(): ?string;
+
+    /**
+     * Get message In-Reply-To (from headers).
+     */
+    public function getInReplyTo(): array;
+
+    /**
+     * Get message References (from headers).
+     */
+    public function getReferences(): array;
+
+    /**
+     * Get body HTML.
+     *
+     * @return null|string Null if message has no HTML message part
+     */
+    public function getBodyHtml(): ?string;
+
+    /**
+     * Get body text.
+     */
+    public function getBodyText(): ?string;
+
+    /**
+     * Get attachments (if any) linked to this e-mail.
+     *
+     * @return AttachmentInterface[]
+     */
+    public function getAttachments(): array;
+
+    /**
+     * Does this message have attachments?
+     */
+    public function hasAttachments(): bool;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php
new file mode 100644
index 0000000..b88e0f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmailAddress.php
@@ -0,0 +1,84 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+/**
+ * An e-mail address.
+ */
+final class EmailAddress
+{
+    /**
+     * @var string
+     */
+    private $mailbox;
+
+    /**
+     * @var null|string
+     */
+    private $hostname;
+
+    /**
+     * @var null|string
+     */
+    private $name;
+
+    /**
+     * @var null|string
+     */
+    private $address;
+
+    public function __construct(string $mailbox, string $hostname = null, string $name = null)
+    {
+        $this->mailbox  = $mailbox;
+        $this->hostname = $hostname;
+        $this->name     = $name;
+
+        if (null !== $hostname) {
+            $this->address = $mailbox . '@' . $hostname;
+        }
+    }
+
+    /**
+     * @return null|string
+     */
+    public function getAddress()
+    {
+        return $this->address;
+    }
+
+    /**
+     * Returns address with person name.
+     */
+    public function getFullAddress(): string
+    {
+        $address = \sprintf('%s@%s', $this->mailbox, $this->hostname);
+        if (null !== $this->name) {
+            $address = \sprintf('"%s" <%s>', \addcslashes($this->name, '"'), $address);
+        }
+
+        return $address;
+    }
+
+    public function getMailbox(): string
+    {
+        return $this->mailbox;
+    }
+
+    /**
+     * @return null|string
+     */
+    public function getHostname()
+    {
+        return $this->hostname;
+    }
+
+    /**
+     * @return null|string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php
new file mode 100644
index 0000000..243cff6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessage.php
@@ -0,0 +1,75 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+final class EmbeddedMessage extends AbstractMessage implements EmbeddedMessageInterface
+{
+    /**
+     * @var null|Headers
+     */
+    private $headers;
+
+    /**
+     * @var null|string
+     */
+    private $rawHeaders;
+
+    /**
+     * @var null|string
+     */
+    private $rawMessage;
+
+    /**
+     * Get message headers.
+     */
+    public function getHeaders(): Headers
+    {
+        if (null === $this->headers) {
+            $this->headers = new Headers(\imap_rfc822_parse_headers($this->getRawHeaders()));
+        }
+
+        return $this->headers;
+    }
+
+    /**
+     * Get raw message headers.
+     */
+    public function getRawHeaders(): string
+    {
+        if (null === $this->rawHeaders) {
+            $rawHeaders       = \explode("\r\n\r\n", $this->getRawMessage(), 2);
+            $this->rawHeaders = \current($rawHeaders);
+        }
+
+        return $this->rawHeaders;
+    }
+
+    /**
+     * Get the raw message, including all headers, parts, etc. unencoded and unparsed.
+     *
+     * @return string the raw message
+     */
+    public function getRawMessage(): string
+    {
+        if (null === $this->rawMessage) {
+            $this->rawMessage = $this->doGetContent($this->getPartNumber());
+        }
+
+        return $this->rawMessage;
+    }
+
+    /**
+     * Get content part number.
+     */
+    protected function getContentPartNumber(): string
+    {
+        $partNumber = $this->getPartNumber();
+        if (0 === \count($this->getParts())) {
+            $partNumber .= '.1';
+        }
+
+        return $partNumber;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessageInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessageInterface.php
new file mode 100644
index 0000000..c685edf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/EmbeddedMessageInterface.php
@@ -0,0 +1,9 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+interface EmbeddedMessageInterface extends BasicMessageInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Headers.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Headers.php
new file mode 100644
index 0000000..f76fec3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Headers.php
@@ -0,0 +1,72 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+/**
+ * Collection of message headers.
+ */
+final class Headers extends Parameters
+{
+    /**
+     * Constructor.
+     */
+    public function __construct(\stdClass $headers)
+    {
+        parent::__construct();
+
+        // Store all headers as lowercase
+        $headers = \array_change_key_case((array) $headers);
+
+        foreach ($headers as $key => $value) {
+            $this[$key] = $this->parseHeader($key, $value);
+        }
+    }
+
+    /**
+     * Get header.
+     *
+     * @return mixed
+     */
+    public function get(string $key)
+    {
+        return parent::get(\strtolower($key));
+    }
+
+    /**
+     * Parse header.
+     *
+     * @param mixed $value
+     *
+     * @return mixed
+     */
+    private function parseHeader(string $key, $value)
+    {
+        switch ($key) {
+            case 'msgno':
+                return (int) $value;
+            case 'from':
+            case 'to':
+            case 'cc':
+            case 'bcc':
+            case 'reply_to':
+            case 'sender':
+            case 'return_path':
+                /** @var \stdClass $address */
+                foreach ($value as $address) {
+                    if (isset($address->mailbox)) {
+                        $address->host     = $address->host ?? null;
+                        $address->personal = isset($address->personal) ? $this->decode($address->personal) : null;
+                    }
+                }
+
+                return $value;
+            case 'date':
+            case 'subject':
+                return $this->decode($value);
+        }
+
+        return $value;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php
new file mode 100644
index 0000000..2f7d8a1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Parameters.php
@@ -0,0 +1,74 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+class Parameters extends \ArrayIterator
+{
+    /**
+     * @var array
+     */
+    private static $attachmentCustomKeys = [
+        'name*'     => 'name',
+        'filename*' => 'filename',
+    ];
+
+    public function __construct(array $parameters = [])
+    {
+        parent::__construct();
+
+        $this->add($parameters);
+    }
+
+    public function add(array $parameters = []): void
+    {
+        foreach ($parameters as $parameter) {
+            $key = \strtolower($parameter->attribute);
+            if (isset(self::$attachmentCustomKeys[$key])) {
+                $key = self::$attachmentCustomKeys[$key];
+            }
+            $value      = $this->decode($parameter->value);
+            $this[$key] = $value;
+        }
+    }
+
+    /**
+     * @return mixed
+     */
+    public function get(string $key)
+    {
+        return $this[$key] ?? null;
+    }
+
+    /**
+     * Decode value.
+     */
+    final protected function decode(string $value): string
+    {
+        $parts = \imap_mime_header_decode($value);
+        if (!\is_array($parts)) {
+            return $value;
+        }
+
+        $decoded = '';
+        foreach ($parts as $part) {
+            $text = $part->text;
+            if ('default' !== $part->charset) {
+                $text = Transcoder::decode($text, $part->charset);
+            }
+            // RFC2231
+            if (1 === \preg_match('/^(?<encoding>[^\']+)\'[^\']*?\'(?<urltext>.+)$/', $text, $matches)) {
+                $hasInvalidChars = 1 === \preg_match('#[^%a-zA-Z0-9\-_\.\+]#', $matches['urltext']);
+                $hasEscapedChars = 1 === \preg_match('#%[a-zA-Z0-9]{2}#', $matches['urltext']);
+                if (!$hasInvalidChars && $hasEscapedChars) {
+                    $text = Transcoder::decode(\urldecode($matches['urltext']), $matches['encoding']);
+                }
+            }
+
+            $decoded .= $text;
+        }
+
+        return $decoded;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/PartInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/PartInterface.php
new file mode 100644
index 0000000..70a83f2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/PartInterface.php
@@ -0,0 +1,112 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+/**
+ * A message part.
+ */
+interface PartInterface extends \RecursiveIterator
+{
+    public const TYPE_TEXT          = 'text';
+    public const TYPE_MULTIPART     = 'multipart';
+    public const TYPE_MESSAGE       = 'message';
+    public const TYPE_APPLICATION   = 'application';
+    public const TYPE_AUDIO         = 'audio';
+    public const TYPE_IMAGE         = 'image';
+    public const TYPE_VIDEO         = 'video';
+    public const TYPE_MODEL         = 'model';
+    public const TYPE_OTHER         = 'other';
+    public const TYPE_UNKNOWN       = 'unknown';
+
+    public const ENCODING_7BIT              = '7bit';
+    public const ENCODING_8BIT              = '8bit';
+    public const ENCODING_BINARY            = 'binary';
+    public const ENCODING_BASE64            = 'base64';
+    public const ENCODING_QUOTED_PRINTABLE  = 'quoted-printable';
+    public const ENCODING_UNKNOWN           = 'unknown';
+
+    public const SUBTYPE_PLAIN  = 'PLAIN';
+    public const SUBTYPE_HTML   = 'HTML';
+    public const SUBTYPE_RFC822 = 'RFC822';
+
+    /**
+     * Get message number (from headers).
+     */
+    public function getNumber(): int;
+
+    /**
+     * Part charset.
+     */
+    public function getCharset(): ?string;
+
+    /**
+     * Part type.
+     */
+    public function getType(): ?string;
+
+    /**
+     * Part subtype.
+     */
+    public function getSubtype(): ?string;
+
+    /**
+     * Part encoding.
+     */
+    public function getEncoding(): ?string;
+
+    /**
+     * Part disposition.
+     */
+    public function getDisposition(): ?string;
+
+    /**
+     * Part description.
+     */
+    public function getDescription(): ?string;
+
+    /**
+     * Part bytes.
+     *
+     * @return null|int|string
+     */
+    public function getBytes();
+
+    /**
+     * Part lines.
+     */
+    public function getLines(): ?string;
+
+    /**
+     * Part parameters.
+     */
+    public function getParameters(): Parameters;
+
+    /**
+     * Get raw part content.
+     */
+    public function getContent(): string;
+
+    /**
+     * Get decoded part content.
+     */
+    public function getDecodedContent(): string;
+
+    /**
+     * Part structure.
+     */
+    public function getStructure(): \stdClass;
+
+    /**
+     * Get part number.
+     */
+    public function getPartNumber(): string;
+
+    /**
+     * Get an array of all parts for this message.
+     *
+     * @return PartInterface[]
+     */
+    public function getParts(): array;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/SimplePart.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/SimplePart.php
new file mode 100644
index 0000000..3c6188d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/SimplePart.php
@@ -0,0 +1,12 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+/**
+ * A message part.
+ */
+final class SimplePart extends AbstractPart
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Transcoder.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Transcoder.php
new file mode 100644
index 0000000..15dfb87
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Message/Transcoder.php
@@ -0,0 +1,328 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Message;
+
+use Ddeboer\Imap\Exception\UnsupportedCharsetException;
+
+final class Transcoder
+{
+    /**
+     * @var array
+     *
+     * @see https://encoding.spec.whatwg.org/#encodings
+     * @see https://dxr.mozilla.org/mozilla-central/source/dom/encoding/labelsencodings.properties
+     * @see https://dxr.mozilla.org/mozilla1.9.1/source/intl/uconv/src/charsetalias.properties
+     * @see https://msdn.microsoft.com/en-us/library/cc194829.aspx
+     */
+    private static $charsetAliases = [
+        '128'                       => 'Shift_JIS',
+        '129'                       => 'EUC-KR',
+        '134'                       => 'GB2312',
+        '136'                       => 'Big5',
+        '161'                       => 'windows-1253',
+        '162'                       => 'windows-1254',
+        '177'                       => 'windows-1255',
+        '178'                       => 'windows-1256',
+        '186'                       => 'windows-1257',
+        '204'                       => 'windows-1251',
+        '222'                       => 'windows-874',
+        '238'                       => 'windows-1250',
+        '5601'                      => 'EUC-KR',
+        '646'                       => 'us-ascii',
+        '850'                       => 'IBM850',
+        '852'                       => 'IBM852',
+        '855'                       => 'IBM855',
+        '857'                       => 'IBM857',
+        '862'                       => 'IBM862',
+        '864'                       => 'IBM864',
+        '864i'                      => 'IBM864i',
+        '866'                       => 'IBM866',
+        'ansi-1251'                 => 'windows-1251',
+        'ansi_x3.4-1968'            => 'us-ascii',
+        'arabic'                    => 'ISO-8859-6',
+        'ascii'                     => 'us-ascii',
+        'asmo-708'                  => 'ISO-8859-6',
+        'big5-hkscs'                => 'Big5',
+        'chinese'                   => 'GB2312',
+        'cn-big5'                   => 'Big5',
+        'cns11643'                  => 'x-euc-tw',
+        'cp-866'                    => 'IBM866',
+        'cp1250'                    => 'windows-1250',
+        'cp1251'                    => 'windows-1251',
+        'cp1252'                    => 'windows-1252',
+        'cp1253'                    => 'windows-1253',
+        'cp1254'                    => 'windows-1254',
+        'cp1255'                    => 'windows-1255',
+        'cp1256'                    => 'windows-1256',
+        'cp1257'                    => 'windows-1257',
+        'cp1258'                    => 'windows-1258',
+        'cp819'                     => 'ISO-8859-1',
+        'cp850'                     => 'IBM850',
+        'cp852'                     => 'IBM852',
+        'cp855'                     => 'IBM855',
+        'cp857'                     => 'IBM857',
+        'cp862'                     => 'IBM862',
+        'cp864'                     => 'IBM864',
+        'cp864i'                    => 'IBM864i',
+        'cp866'                     => 'IBM866',
+        'cp932'                     => 'Shift_JIS',
+        'csbig5'                    => 'Big5',
+        'cseucjpkdfmtjapanese'      => 'EUC-JP',
+        'cseuckr'                   => 'EUC-KR',
+        'cseucpkdfmtjapanese'       => 'EUC-JP',
+        'csgb2312'                  => 'GB2312',
+        'csibm850'                  => 'IBM850',
+        'csibm852'                  => 'IBM852',
+        'csibm855'                  => 'IBM855',
+        'csibm857'                  => 'IBM857',
+        'csibm862'                  => 'IBM862',
+        'csibm864'                  => 'IBM864',
+        'csibm864i'                 => 'IBM864i',
+        'csibm866'                  => 'IBM866',
+        'csiso103t618bit'           => 'T.61-8bit',
+        'csiso111ecmacyrillic'      => 'ISO-IR-111',
+        'csiso2022jp'               => 'ISO-2022-JP',
+        'csiso2022jp2'              => 'ISO-2022-JP',
+        'csiso2022kr'               => 'ISO-2022-KR',
+        'csiso58gb231280'           => 'GB2312',
+        'csiso88596e'               => 'ISO-8859-6-E',
+        'csiso88596i'               => 'ISO-8859-6-I',
+        'csiso88598e'               => 'ISO-8859-8-E',
+        'csiso88598i'               => 'ISO-8859-8-I',
+        'csisolatin1'               => 'ISO-8859-1',
+        'csisolatin2'               => 'ISO-8859-2',
+        'csisolatin3'               => 'ISO-8859-3',
+        'csisolatin4'               => 'ISO-8859-4',
+        'csisolatin5'               => 'ISO-8859-9',
+        'csisolatin6'               => 'ISO-8859-10',
+        'csisolatin9'               => 'ISO-8859-15',
+        'csisolatinarabic'          => 'ISO-8859-6',
+        'csisolatincyrillic'        => 'ISO-8859-5',
+        'csisolatingreek'           => 'ISO-8859-7',
+        'csisolatinhebrew'          => 'ISO-8859-8',
+        'cskoi8r'                   => 'KOI8-R',
+        'csksc56011987'             => 'EUC-KR',
+        'csmacintosh'               => 'x-mac-roman',
+        'csshiftjis'                => 'Shift_JIS',
+        'csueckr'                   => 'EUC-KR',
+        'csunicode'                 => 'UTF-16BE',
+        'csunicode11'               => 'UTF-16BE',
+        'csunicode11utf7'           => 'UTF-7',
+        'csunicodeascii'            => 'UTF-16BE',
+        'csunicodelatin1'           => 'UTF-16BE',
+        'csviqr'                    => 'VIQR',
+        'csviscii'                  => 'VISCII',
+        'cyrillic'                  => 'ISO-8859-5',
+        'dos-874'                   => 'windows-874',
+        'ecma-114'                  => 'ISO-8859-6',
+        'ecma-118'                  => 'ISO-8859-7',
+        'ecma-cyrillic'             => 'ISO-IR-111',
+        'elot_928'                  => 'ISO-8859-7',
+        'gb_2312'                   => 'GB2312',
+        'gb_2312-80'                => 'GB2312',
+        'greek'                     => 'ISO-8859-7',
+        'greek8'                    => 'ISO-8859-7',
+        'hebrew'                    => 'ISO-8859-8',
+        'ibm-864'                   => 'IBM864',
+        'ibm-864i'                  => 'IBM864i',
+        'ibm819'                    => 'ISO-8859-1',
+        'ibm874'                    => 'windows-874',
+        'iso-10646'                 => 'UTF-16BE',
+        'iso-10646-j-1'             => 'UTF-16BE',
+        'iso-10646-ucs-2'           => 'UTF-16BE',
+        'iso-10646-ucs-4'           => 'UTF-32BE',
+        'iso-10646-ucs-basic'       => 'UTF-16BE',
+        'iso-10646-unicode-latin1'  => 'UTF-16BE',
+        'iso-2022-cn-ext'           => 'ISO-2022-CN',
+        'iso-2022-jp-2'             => 'ISO-2022-JP',
+        'iso-8859-8i'               => 'ISO-8859-8-I',
+        'iso-ir-100'                => 'ISO-8859-1',
+        'iso-ir-101'                => 'ISO-8859-2',
+        'iso-ir-103'                => 'T.61-8bit',
+        'iso-ir-109'                => 'ISO-8859-3',
+        'iso-ir-110'                => 'ISO-8859-4',
+        'iso-ir-126'                => 'ISO-8859-7',
+        'iso-ir-127'                => 'ISO-8859-6',
+        'iso-ir-138'                => 'ISO-8859-8',
+        'iso-ir-144'                => 'ISO-8859-5',
+        'iso-ir-148'                => 'ISO-8859-9',
+        'iso-ir-149'                => 'EUC-KR',
+        'iso-ir-157'                => 'ISO-8859-10',
+        'iso-ir-58'                 => 'GB2312',
+        'iso8859-1'                 => 'ISO-8859-1',
+        'iso8859-10'                => 'ISO-8859-10',
+        'iso8859-11'                => 'ISO-8859-11',
+        'iso8859-13'                => 'ISO-8859-13',
+        'iso8859-14'                => 'ISO-8859-14',
+        'iso8859-15'                => 'ISO-8859-15',
+        'iso8859-2'                 => 'ISO-8859-2',
+        'iso8859-3'                 => 'ISO-8859-3',
+        'iso8859-4'                 => 'ISO-8859-4',
+        'iso8859-5'                 => 'ISO-8859-5',
+        'iso8859-6'                 => 'ISO-8859-6',
+        'iso8859-7'                 => 'ISO-8859-7',
+        'iso8859-8'                 => 'ISO-8859-8',
+        'iso8859-9'                 => 'ISO-8859-9',
+        'iso88591'                  => 'ISO-8859-1',
+        'iso885910'                 => 'ISO-8859-10',
+        'iso885911'                 => 'ISO-8859-11',
+        'iso885912'                 => 'ISO-8859-12',
+        'iso885913'                 => 'ISO-8859-13',
+        'iso885914'                 => 'ISO-8859-14',
+        'iso885915'                 => 'ISO-8859-15',
+        'iso88592'                  => 'ISO-8859-2',
+        'iso88593'                  => 'ISO-8859-3',
+        'iso88594'                  => 'ISO-8859-4',
+        'iso88595'                  => 'ISO-8859-5',
+        'iso88596'                  => 'ISO-8859-6',
+        'iso88597'                  => 'ISO-8859-7',
+        'iso88598'                  => 'ISO-8859-8',
+        'iso88599'                  => 'ISO-8859-9',
+        'iso_8859-1'                => 'ISO-8859-1',
+        'iso_8859-15'               => 'ISO-8859-15',
+        'iso_8859-1:1987'           => 'ISO-8859-1',
+        'iso_8859-2'                => 'ISO-8859-2',
+        'iso_8859-2:1987'           => 'ISO-8859-2',
+        'iso_8859-3'                => 'ISO-8859-3',
+        'iso_8859-3:1988'           => 'ISO-8859-3',
+        'iso_8859-4'                => 'ISO-8859-4',
+        'iso_8859-4:1988'           => 'ISO-8859-4',
+        'iso_8859-5'                => 'ISO-8859-5',
+        'iso_8859-5:1988'           => 'ISO-8859-5',
+        'iso_8859-6'                => 'ISO-8859-6',
+        'iso_8859-6:1987'           => 'ISO-8859-6',
+        'iso_8859-7'                => 'ISO-8859-7',
+        'iso_8859-7:1987'           => 'ISO-8859-7',
+        'iso_8859-8'                => 'ISO-8859-8',
+        'iso_8859-8:1988'           => 'ISO-8859-8',
+        'iso_8859-9'                => 'ISO-8859-9',
+        'iso_8859-9:1989'           => 'ISO-8859-9',
+        'koi'                       => 'KOI8-R',
+        'koi8'                      => 'KOI8-R',
+        'koi8-ru'                   => 'KOI8-U',
+        'koi8_r'                    => 'KOI8-R',
+        'korean'                    => 'EUC-KR',
+        'ks_c_5601-1987'            => 'EUC-KR',
+        'ks_c_5601-1989'            => 'EUC-KR',
+        'ksc5601'                   => 'EUC-KR',
+        'ksc_5601'                  => 'EUC-KR',
+        'l1'                        => 'ISO-8859-1',
+        'l2'                        => 'ISO-8859-2',
+        'l3'                        => 'ISO-8859-3',
+        'l4'                        => 'ISO-8859-4',
+        'l5'                        => 'ISO-8859-9',
+        'l6'                        => 'ISO-8859-10',
+        'l9'                        => 'ISO-8859-15',
+        'latin1'                    => 'ISO-8859-1',
+        'latin2'                    => 'ISO-8859-2',
+        'latin3'                    => 'ISO-8859-3',
+        'latin4'                    => 'ISO-8859-4',
+        'latin5'                    => 'ISO-8859-9',
+        'latin6'                    => 'ISO-8859-10',
+        'logical'                   => 'ISO-8859-8-I',
+        'mac'                       => 'x-mac-roman',
+        'macintosh'                 => 'x-mac-roman',
+        'ms932'                     => 'Shift_JIS',
+        'ms_kanji'                  => 'Shift_JIS',
+        'shift-jis'                 => 'Shift_JIS',
+        'sjis'                      => 'Shift_JIS',
+        'sun_eu_greek'              => 'ISO-8859-7',
+        't.61'                      => 'T.61-8bit',
+        'tis620'                    => 'TIS-620',
+        'unicode-1-1-utf-7'         => 'UTF-7',
+        'unicode-1-1-utf-8'         => 'UTF-8',
+        'unicode-2-0-utf-7'         => 'UTF-7',
+        'visual'                    => 'ISO-8859-8',
+        'windows-31j'               => 'Shift_JIS',
+        'windows-949'               => 'EUC-KR',
+        'x-cp1250'                  => 'windows-1250',
+        'x-cp1251'                  => 'windows-1251',
+        'x-cp1252'                  => 'windows-1252',
+        'x-cp1253'                  => 'windows-1253',
+        'x-cp1254'                  => 'windows-1254',
+        'x-cp1255'                  => 'windows-1255',
+        'x-cp1256'                  => 'windows-1256',
+        'x-cp1257'                  => 'windows-1257',
+        'x-cp1258'                  => 'windows-1258',
+        'x-euc-jp'                  => 'EUC-JP',
+        'x-gbk'                     => 'gbk',
+        'x-iso-10646-ucs-2-be'      => 'UTF-16BE',
+        'x-iso-10646-ucs-2-le'      => 'UTF-16LE',
+        'x-iso-10646-ucs-4-be'      => 'UTF-32BE',
+        'x-iso-10646-ucs-4-le'      => 'UTF-32LE',
+        'x-sjis'                    => 'Shift_JIS',
+        'x-unicode-2-0-utf-7'       => 'UTF-7',
+        'x-x-big5'                  => 'Big5',
+        'zh_cn.euc'                 => 'GB2312',
+        'zh_tw-big5'                => 'Big5',
+        'zh_tw-euc'                 => 'x-euc-tw',
+    ];
+
+    /**
+     * Decode text to UTF-8.
+     *
+     * @param string $text        Text to decode
+     * @param string $fromCharset Original charset
+     */
+    public static function decode(string $text, string $fromCharset): string
+    {
+        static $utf8Aliases = [
+            'unicode-1-1-utf-8' => true,
+            'utf8'              => true,
+            'utf-8'             => true,
+            'UTF8'              => true,
+            'UTF-8'             => true,
+        ];
+
+        if (isset($utf8Aliases[$fromCharset])) {
+            return $text;
+        }
+
+        $originalFromCharset  = $fromCharset;
+        $lowercaseFromCharset = \strtolower($fromCharset);
+        if (isset(self::$charsetAliases[$lowercaseFromCharset])) {
+            $fromCharset = self::$charsetAliases[$lowercaseFromCharset];
+        }
+
+        \set_error_handler(static function (): bool {
+            return true;
+        });
+
+        $iconvDecodedText = \iconv($fromCharset, 'UTF-8', $text);
+        if (false === $iconvDecodedText) {
+            $iconvDecodedText = \iconv($originalFromCharset, 'UTF-8', $text);
+        }
+
+        \restore_error_handler();
+
+        if (false !== $iconvDecodedText) {
+            return $iconvDecodedText;
+        }
+
+        $errorMessage = null;
+        $errorNumber  = 0;
+        \set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber): bool {
+            $errorMessage = $message;
+            $errorNumber = $nr;
+
+            return true;
+        });
+
+        $decodedText = \mb_convert_encoding($text, 'UTF-8', $fromCharset);
+
+        \restore_error_handler();
+
+        if (null !== $errorMessage) {
+            throw new UnsupportedCharsetException(\sprintf(
+                'Unsupported charset "%s"%s: %s',
+                $originalFromCharset,
+                ($fromCharset !== $originalFromCharset) ? \sprintf(' (alias found: "%s")', $fromCharset) : '',
+                $errorMessage
+            ), $errorNumber);
+        }
+
+        return $decodedText;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php
new file mode 100644
index 0000000..eda8ab6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageInterface.php
@@ -0,0 +1,97 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+/**
+ * An IMAP message (e-mail).
+ */
+interface MessageInterface extends Message\BasicMessageInterface
+{
+    /**
+     * Get raw part content.
+     */
+    public function getContent(): string;
+
+    /**
+     * Get message recent flag value (from headers).
+     */
+    public function isRecent(): ?string;
+
+    /**
+     * Get message unseen flag value (from headers).
+     */
+    public function isUnseen(): bool;
+
+    /**
+     * Get message flagged flag value (from headers).
+     */
+    public function isFlagged(): bool;
+
+    /**
+     * Get message answered flag value (from headers).
+     */
+    public function isAnswered(): bool;
+
+    /**
+     * Get message deleted flag value (from headers).
+     */
+    public function isDeleted(): bool;
+
+    /**
+     * Get message draft flag value (from headers).
+     */
+    public function isDraft(): bool;
+
+    /**
+     * Has the message been marked as read?
+     */
+    public function isSeen(): bool;
+
+    /**
+     * Mark message as seen.
+     *
+     * @deprecated since version 1.1, to be removed in 2.0
+     */
+    public function maskAsSeen(): bool;
+
+    /**
+     * Mark message as seen.
+     */
+    public function markAsSeen(): bool;
+
+    /**
+     * Move message to another mailbox.
+     */
+    public function copy(MailboxInterface $mailbox): void;
+
+    /**
+     * Move message to another mailbox.
+     */
+    public function move(MailboxInterface $mailbox): void;
+
+    /**
+     * Delete message.
+     */
+    public function delete(): void;
+
+    /**
+     * Undelete message.
+     */
+    public function undelete(): void;
+
+    /**
+     * Set Flag Message.
+     *
+     * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
+     */
+    public function setFlag(string $flag): bool;
+
+    /**
+     * Clear Flag Message.
+     *
+     * @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
+     */
+    public function clearFlag(string $flag): bool;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIterator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIterator.php
new file mode 100644
index 0000000..c617478
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIterator.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+final class MessageIterator extends \ArrayIterator implements MessageIteratorInterface
+{
+    /**
+     * @var ImapResourceInterface
+     */
+    private $resource;
+
+    /**
+     * Constructor.
+     *
+     * @param ImapResourceInterface $resource       IMAP resource
+     * @param array                 $messageNumbers Array of message numbers
+     */
+    public function __construct(ImapResourceInterface $resource, array $messageNumbers)
+    {
+        $this->resource = $resource;
+
+        parent::__construct($messageNumbers);
+    }
+
+    /**
+     * Get current message.
+     */
+    public function current(): MessageInterface
+    {
+        $current = parent::current();
+        if (!\is_int($current)) {
+            throw new Exception\OutOfBoundsException(\sprintf(
+                'The current value "%s" isn\'t an integer and doesn\'t represent a message;'
+                . ' try to cycle this "%s" with a native php function like foreach or with the method getArrayCopy(),'
+                . ' or check it by calling the methods valid().',
+                \is_object($current) ? \get_class($current) : \gettype($current),
+                static::class
+            ));
+        }
+
+        return new Message($this->resource, $current);
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php
new file mode 100644
index 0000000..a9d7988
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/MessageIteratorInterface.php
@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+interface MessageIteratorInterface extends \Iterator
+{
+    /**
+     * Get current message.
+     */
+    public function current(): MessageInterface;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractDate.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractDate.php
new file mode 100644
index 0000000..cdd7312
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractDate.php
@@ -0,0 +1,51 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search;
+
+use DateTimeInterface;
+
+/**
+ * Represents a date condition.
+ */
+abstract class AbstractDate implements ConditionInterface
+{
+    /**
+     * Format for dates to be sent to the IMAP server.
+     *
+     * @var string
+     */
+    private $dateFormat;
+
+    /**
+     * The date to be used for the condition.
+     *
+     * @var DateTimeInterface
+     */
+    private $date;
+
+    /**
+     * Constructor.
+     *
+     * @param DateTimeInterface $date optional date for the condition
+     */
+    public function __construct(DateTimeInterface $date, string $dateFormat = 'j-M-Y')
+    {
+        $this->date       = $date;
+        $this->dateFormat = $dateFormat;
+    }
+
+    /**
+     * Converts the condition to a string that can be sent to the IMAP server.
+     */
+    final public function toString(): string
+    {
+        return \sprintf('%s "%s"', $this->getKeyword(), $this->date->format($this->dateFormat));
+    }
+
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    abstract protected function getKeyword(): string;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php
new file mode 100644
index 0000000..69b2516
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/AbstractText.php
@@ -0,0 +1,42 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search;
+
+/**
+ * Represents a text based condition. Text based conditions use a contains
+ * restriction.
+ */
+abstract class AbstractText implements ConditionInterface
+{
+    /**
+     * Text to be used for the condition.
+     *
+     * @var string
+     */
+    private $text;
+
+    /**
+     * Constructor.
+     *
+     * @param string $text optional text for the condition
+     */
+    public function __construct(string $text)
+    {
+        $this->text = $text;
+    }
+
+    /**
+     * Converts the condition to a string that can be sent to the IMAP server.
+     */
+    final public function toString(): string
+    {
+        return \sprintf('%s "%s"', $this->getKeyword(), $this->text);
+    }
+
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    abstract protected function getKeyword(): string;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/ConditionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/ConditionInterface.php
new file mode 100644
index 0000000..3aed28c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/ConditionInterface.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search;
+
+/**
+ * Represents a condition that can be used in a search expression.
+ */
+interface ConditionInterface
+{
+    /**
+     * Converts the condition to a string that can be sent to the IMAP server.
+     */
+    public function toString(): string;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Date/Before.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Date/Before.php
new file mode 100644
index 0000000..561f3f2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Date/Before.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Date;
+
+use Ddeboer\Imap\Search\AbstractDate;
+
+/**
+ * Represents a date before condition. Messages must have a date before the
+ * specified date in order to match the condition.
+ */
+final class Before extends AbstractDate
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'BEFORE';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Date/On.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Date/On.php
new file mode 100644
index 0000000..2f00dde
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Date/On.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Date;
+
+use Ddeboer\Imap\Search\AbstractDate;
+
+/**
+ * Represents a date on condition. Messages must have a date matching the
+ * specified date in order to match the condition.
+ */
+final class On extends AbstractDate
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'ON';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Date/Since.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Date/Since.php
new file mode 100644
index 0000000..31825f6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Date/Since.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Date;
+
+use Ddeboer\Imap\Search\AbstractDate;
+
+/**
+ * Represents a date after condition. Messages must have a date after the
+ * specified date in order to match the condition.
+ */
+final class Since extends AbstractDate
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'SINCE';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/Bcc.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/Bcc.php
new file mode 100644
index 0000000..d450973
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/Bcc.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Email;
+
+use Ddeboer\Imap\Search\AbstractText;
+
+/**
+ * Represents a "Bcc" email address condition. Messages must have been addressed
+ * to the specified recipient (along with any others) in order to match the
+ * condition.
+ */
+final class Bcc extends AbstractText
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'BCC';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/Cc.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/Cc.php
new file mode 100644
index 0000000..72d0642
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/Cc.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Email;
+
+use Ddeboer\Imap\Search\AbstractText;
+
+/**
+ * Represents a "Cc" email address condition. Messages must have been addressed
+ * to the specified recipient (along with any others) in order to match the
+ * condition.
+ */
+final class Cc extends AbstractText
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'CC';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/From.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/From.php
new file mode 100644
index 0000000..f690121
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/From.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Email;
+
+use Ddeboer\Imap\Search\AbstractText;
+
+/**
+ * Represents a "From" email address condition. Messages must have been sent
+ * from the specified email address in order to match the condition.
+ */
+final class From extends AbstractText
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'FROM';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/To.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/To.php
new file mode 100644
index 0000000..5ff5c09
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Email/To.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Email;
+
+use Ddeboer\Imap\Search\AbstractText;
+
+/**
+ * Represents a "To" email address condition. Messages must have been addressed
+ * to the specified recipient (along with any others) in order to match the
+ * condition.
+ */
+final class To extends AbstractText
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'TO';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Answered.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Answered.php
new file mode 100644
index 0000000..fc671a3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Answered.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Flag;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents an ANSWERED flag condition. Messages must have the \\ANSWERED flag
+ * set in order to match the condition.
+ */
+final class Answered implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'ANSWERED';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Flagged.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Flagged.php
new file mode 100644
index 0000000..b1161cc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Flagged.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Flag;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents a FLAGGED flag condition. Messages must have the \\FLAGGED flag
+ * (i.e. urgent or important) set in order to match the condition.
+ */
+final class Flagged implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'FLAGGED';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Recent.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Recent.php
new file mode 100644
index 0000000..ba0ba73
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Recent.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Flag;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents an RECENT flag condition. Messages must have the \\RECENT flag
+ * set in order to match the condition.
+ */
+final class Recent implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'RECENT';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Seen.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Seen.php
new file mode 100644
index 0000000..2a52a9d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Seen.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Flag;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents an SEEN flag condition. Messages must have the \\SEEN flag
+ * set in order to match the condition.
+ */
+final class Seen implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'SEEN';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Unanswered.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Unanswered.php
new file mode 100644
index 0000000..e2c5717
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Unanswered.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Flag;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents an UNANSWERED flag condition. Messages must not have the
+ * \\ANSWERED flag set in order to match the condition.
+ */
+final class Unanswered implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'UNANSWERED';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Unflagged.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Unflagged.php
new file mode 100644
index 0000000..ca53c6d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Unflagged.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Flag;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents a UNFLAGGED flag condition. Messages must no have the \\FLAGGED
+ * flag (i.e. urgent or important) set in order to match the condition.
+ */
+final class Unflagged implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'UNFLAGGED';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Unseen.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Unseen.php
new file mode 100644
index 0000000..27db7d2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Flag/Unseen.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Flag;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents an UNSEEN flag condition. Messages must not have the \\SEEN flag
+ * set in order to match the condition.
+ */
+final class Unseen implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'UNSEEN';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/All.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/All.php
new file mode 100644
index 0000000..c867ec7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/All.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\LogicalOperator;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents an ALL operator. Messages must match all conditions following this
+ * operator in order to match the expression.
+ */
+final class All implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'ALL';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/OrConditions.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/OrConditions.php
new file mode 100644
index 0000000..bfebddd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/LogicalOperator/OrConditions.php
@@ -0,0 +1,50 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\LogicalOperator;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents an OR operator. Messages only need to match one of the conditions
+ * after this operator to match the expression.
+ */
+final class OrConditions implements ConditionInterface
+{
+    /**
+     * The conditions that together represent the expression.
+     *
+     * @var array
+     */
+    private $conditions = [];
+
+    public function __construct(array $conditions)
+    {
+        foreach ($conditions as $condition) {
+            $this->addCondition($condition);
+        }
+    }
+
+    /**
+     * Adds a new condition to the expression.
+     *
+     * @param ConditionInterface $condition the condition to be added
+     */
+    private function addCondition(ConditionInterface $condition)
+    {
+        $this->conditions[] = $condition;
+    }
+
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        $conditions = \array_map(static function (ConditionInterface $condition): string {
+            return $condition->toString();
+        }, $this->conditions);
+
+        return \sprintf('( %s )', \implode(' OR ', $conditions));
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php
new file mode 100644
index 0000000..cc6a465
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/RawExpression.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search;
+
+/**
+ * Represents a raw expression.
+ */
+final class RawExpression implements ConditionInterface
+{
+    /**
+     * Text to be used for the condition.
+     *
+     * @var string
+     */
+    private $expression;
+
+    /**
+     * @param string $expression text for the condition
+     */
+    public function __construct(string $expression)
+    {
+        $this->expression = $expression;
+    }
+
+    public function toString(): string
+    {
+        return $this->expression;
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Deleted.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Deleted.php
new file mode 100644
index 0000000..b74581e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Deleted.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\State;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents a DELETED condition. Messages must have been marked for deletion
+ * but not yet expunged in order to match the condition.
+ */
+final class Deleted implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'DELETED';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/NewMessage.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/NewMessage.php
new file mode 100644
index 0000000..98df4fb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/NewMessage.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\State;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents a NEW condition. Only new messages will match this condition.
+ */
+final class NewMessage implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'NEW';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Old.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Old.php
new file mode 100644
index 0000000..396673f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Old.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\State;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents an OLD condition. Only old messages will match this condition.
+ */
+final class Old implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'OLD';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Undeleted.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Undeleted.php
new file mode 100644
index 0000000..d6d2d36
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/State/Undeleted.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\State;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Represents a UNDELETED condition. Messages must not have been marked for
+ * deletion in order to match the condition.
+ */
+final class Undeleted implements ConditionInterface
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    public function toString(): string
+    {
+        return 'UNDELETED';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Body.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Body.php
new file mode 100644
index 0000000..6b6d531
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Body.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Text;
+
+use Ddeboer\Imap\Search\AbstractText;
+
+/**
+ * Represents a body text contains condition. Messages must have a body
+ * containing the specified text in order to match the condition.
+ */
+final class Body extends AbstractText
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'BODY';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Keyword.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Keyword.php
new file mode 100644
index 0000000..6bf1e11
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Keyword.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Text;
+
+use Ddeboer\Imap\Search\AbstractText;
+
+/**
+ * Represents a keyword text contains condition. Messages must have a keyword
+ * matching the specified text in order to match the condition.
+ */
+final class Keyword extends AbstractText
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'KEYWORD';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Subject.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Subject.php
new file mode 100644
index 0000000..6f5198f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Subject.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Text;
+
+use Ddeboer\Imap\Search\AbstractText;
+
+/**
+ * Represents a subject contains condition. Messages must have a subject
+ * containing the specified text in order to match the condition.
+ */
+final class Subject extends AbstractText
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'SUBJECT';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Text.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Text.php
new file mode 100644
index 0000000..09c3017
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Text.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Text;
+
+use Ddeboer\Imap\Search\AbstractText;
+
+/**
+ * Represents a message text contains condition. Messages must contain the
+ * specified text in order to match the condition.
+ */
+final class Text extends AbstractText
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'TEXT';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Unkeyword.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Unkeyword.php
new file mode 100644
index 0000000..64a706d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Search/Text/Unkeyword.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Search\Text;
+
+use Ddeboer\Imap\Search\AbstractText;
+
+/**
+ * Represents a keyword text does not contain condition. Messages must not have
+ * a keyword matching the specified text in order to match the condition.
+ */
+final class Unkeyword extends AbstractText
+{
+    /**
+     * Returns the keyword that the condition represents.
+     */
+    protected function getKeyword(): string
+    {
+        return 'UNKEYWORD';
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/SearchExpression.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/SearchExpression.php
new file mode 100644
index 0000000..e89d49e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/SearchExpression.php
@@ -0,0 +1,44 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+use Ddeboer\Imap\Search\ConditionInterface;
+
+/**
+ * Defines a search expression that can be used to look up email messages.
+ */
+final class SearchExpression implements ConditionInterface
+{
+    /**
+     * The conditions that together represent the expression.
+     *
+     * @var array
+     */
+    private $conditions = [];
+
+    /**
+     * Adds a new condition to the expression.
+     *
+     * @param ConditionInterface $condition the condition to be added
+     */
+    public function addCondition(ConditionInterface $condition): self
+    {
+        $this->conditions[] = $condition;
+
+        return $this;
+    }
+
+    /**
+     * Converts the expression to a string that can be sent to the IMAP server.
+     */
+    public function toString(): string
+    {
+        $conditions = \array_map(static function (ConditionInterface $condition): string {
+            return $condition->toString();
+        }, $this->conditions);
+
+        return \implode(' ', $conditions);
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php
new file mode 100644
index 0000000..7412f00
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Server.php
@@ -0,0 +1,146 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+use Ddeboer\Imap\Exception\AuthenticationFailedException;
+use Ddeboer\Imap\Exception\ResourceCheckFailureException;
+
+/**
+ * An IMAP server.
+ */
+final class Server implements ServerInterface
+{
+    /**
+     * @var string Internet domain name or bracketed IP address of server
+     */
+    private $hostname;
+
+    /**
+     * @var string TCP port number
+     */
+    private $port;
+
+    /**
+     * @var string Optional flags
+     */
+    private $flags;
+
+    /**
+     * @var array
+     */
+    private $parameters;
+
+    /**
+     * @var int Connection options
+     */
+    private $options;
+
+    /**
+     * @var int Retries number
+     */
+    private $retries;
+
+    /**
+     * Constructor.
+     *
+     * @param string $hostname   Internet domain name or bracketed IP address
+     *                           of server
+     * @param string $port       TCP port number
+     * @param string $flags      Optional flags
+     * @param array  $parameters Connection parameters
+     * @param int    $options    Connection options
+     * @param int    $retries    Retries number
+     */
+    public function __construct(
+        string $hostname,
+        string $port = '993',
+        string $flags = '/imap/ssl/validate-cert',
+        array $parameters = [],
+        int $options = 0,
+        int $retries = 1
+    ) {
+        if (!\function_exists('imap_open')) {
+            throw new \RuntimeException('IMAP extension must be enabled');
+        }
+
+        $this->hostname   = $hostname;
+        $this->port       = $port;
+        $this->flags      = '' !== $flags ? '/' . \ltrim($flags, '/') : '';
+        $this->parameters = $parameters;
+        $this->options    = $options;
+        $this->retries    = $retries;
+    }
+
+    /**
+     * Authenticate connection.
+     *
+     * @param string $username Username
+     * @param string $password Password
+     *
+     * @throws AuthenticationFailedException
+     */
+    public function authenticate(string $username, string $password): ConnectionInterface
+    {
+        $errorMessage = null;
+        $errorNumber  = 0;
+        \set_error_handler(static function ($nr, $message) use (&$errorMessage, &$errorNumber): bool {
+            $errorMessage = $message;
+            $errorNumber = $nr;
+
+            return true;
+        });
+
+        $resource = \imap_open(
+            $this->getServerString(),
+            $username,
+            $password,
+            $this->options,
+            $this->retries,
+            $this->parameters
+        );
+
+        \restore_error_handler();
+
+        if (false === $resource || null !== $errorMessage) {
+            throw new AuthenticationFailedException(\sprintf(
+                'Authentication failed for user "%s"%s',
+                $username,
+                null !== $errorMessage ? ': ' . $errorMessage : ''
+            ), $errorNumber);
+        }
+
+        $check = \imap_check($resource);
+
+        if (false === $check) {
+            throw new ResourceCheckFailureException('Resource check failure');
+        }
+
+        $mailbox       = $check->Mailbox;
+        $connection    = $mailbox;
+        $curlyPosition = \strpos($mailbox, '}');
+        if (false !== $curlyPosition) {
+            $connection = \substr($mailbox, 0, $curlyPosition + 1);
+        }
+
+        // These are necessary to get rid of PHP throwing IMAP errors
+        \imap_errors();
+        \imap_alerts();
+
+        return new Connection(new ImapResource($resource), $connection);
+    }
+
+    /**
+     * Glues hostname, port and flags and returns result.
+     */
+    private function getServerString(): string
+    {
+        return \sprintf(
+            '{%s%s%s}',
+            $this->hostname,
+            '' !== $this->port ? ':' . $this->port : '',
+            $this->flags
+        );
+    }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ServerInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ServerInterface.php
new file mode 100644
index 0000000..f7e95f9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/ServerInterface.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap;
+
+/**
+ * An IMAP server.
+ */
+interface ServerInterface
+{
+    /**
+     * Authenticate connection.
+     *
+     * @param string $username Username
+     * @param string $password Password
+     */
+    public function authenticate(string $username, string $password): ConnectionInterface;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Test/RawMessageIterator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Test/RawMessageIterator.php
new file mode 100644
index 0000000..08500b6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/ddeboer/imap/src/Test/RawMessageIterator.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Ddeboer\Imap\Test;
+
+use Ddeboer\Imap\MessageInterface;
+use Ddeboer\Imap\MessageIteratorInterface;
+
+/**
+ * A MessageIterator to be used in a mocked environment.
+ */
+final class RawMessageIterator extends \ArrayIterator implements MessageIteratorInterface
+{
+    public function current(): MessageInterface
+    {
+        return parent::current();
+    }
+}