├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── general-help-request.md ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── LICENSE.md ├── README.md ├── _config.yml ├── composer.json ├── examples ├── custom_attachment_mask.php ├── custom_message_mask.php ├── folder_structure.blade.php └── message_table.blade.php ├── phpunit.xml.dist └── src ├── Commands └── ImapIdleCommand.php ├── Events ├── Event.php ├── FlagDeletedEvent.php ├── FlagNewEvent.php ├── FolderDeletedEvent.php ├── FolderMovedEvent.php ├── FolderNewEvent.php ├── MessageCopiedEvent.php ├── MessageDeletedEvent.php ├── MessageMovedEvent.php ├── MessageNewEvent.php └── MessageRestoredEvent.php ├── Facades └── Client.php ├── Providers └── LaravelServiceProvider.php └── config └── imap.php /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: webklex 2 | custom: ['https://www.buymeacoffee.com/webklex'] 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop / Server (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - PHP: [e.g. 5.5.9] 26 | - Version [e.g. 22] 27 | 28 | **Additional context** 29 | Add any other context about the problem here. 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/general-help-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: General help request 3 | about: Feel free to ask about any project related stuff 4 | 5 | --- 6 | 7 | Please be aware that these issues will be closed if inactive for more then 14 days :) 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | .idea -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | os: linux 4 | dist: xenial 5 | 6 | php: 7 | - 5.6 8 | - 7.0 9 | - 7.1 10 | - 7.2 11 | - 7.3 12 | - 7.4 13 | - hhvm 14 | 15 | matrix: 16 | fast_finish: true 17 | allow_failures: 18 | - php: 7.0 19 | - php: 7.1 20 | - php: 7.3 21 | - php: 7.4 22 | - php: hhvm 23 | 24 | sudo: false 25 | 26 | before_script: 27 | - echo "memory_limit=2048M" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini 28 | - composer selfupdate 29 | - composer clearcache 30 | - composer install --no-interaction 31 | 32 | install: 33 | - COMPOSER_MEMORY_LIMIT=-1 composer install --no-interaction 34 | 35 | script: 36 | - phpunit 37 | 38 | notifications: 39 | email: 40 | on_success: always 41 | on_failure: always 42 | 43 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `webklex/laravel-imap` will be documented in this file. 4 | 5 | Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles. 6 | 7 | ## [UNRELEASED] 8 | ### Fixed 9 | - NaN 10 | 11 | ### Added 12 | - NaN 13 | 14 | ### Breaking changes 15 | - NaN 16 | 17 | ## [6.2.0] - 2025-04-25 18 | ### Fixed 19 | - When using the chunk function, some messages do not have an element with index 0 (thanks @zeddmaster) 20 | - Get folders list in hierarchical order (thanks @rskrzypczak) 21 | - Fix remaining implicit marking of parameters as nullable (PHP 8.4) (thanks @steffenweber) 22 | - Fix case sensitivity of folder attribute parsing (\NoSelect, \NoInferiors) (thanks @smajti1) 23 | - Fix error on getUid(null) with 0 results (thanks @pierement) 24 | - Fix Date parsing on non-standard format from Aqua Mail (thanks @lm-cmxkonzepte) 25 | 26 | ### Added 27 | - SSL stream context options added (thanks @llemoine) 28 | - Support copy/move Message with utf7 folder path (thanks @loc4l) 29 | - Public `Query::search()` method (Thanks @madbob) 30 | 31 | ## [6.1.0] - 2025-01-19 32 | ### Fixed 33 | - Filename sanitization is now optional (enabled via default) 34 | - Address parsing improved and extended to include more cases 35 | - Boundary parsing fixed and improved to support more formats 36 | - Decode partially encoded address names 37 | - Enforce RFC822 parsing if enabled 38 | 39 | ### Added 40 | - Security configuration options added 41 | - Spoofing detection added 42 | - RFC4315 MOVE fallback added (thanks @freescout-help-desk) 43 | - Content fetching RFC standard support added (thanks @ybizeul) 44 | - Support unescaped dates inside the search conditions 45 | - `Client::clone()` looses account configuration (thanks @netpok) 46 | 47 | ## [6.0.0] - 2025-01-17 48 | ### Fixed 49 | - Legacy protocol support fixed (object to array conversion) 50 | - Header value decoding improved 51 | - Protocol exception handling improved (bad response message added) 52 | - Prevent fetching singular rfc partials from running indefinitely 53 | - Subject with colon ";" is truncated 54 | - Catching and handling iconv decoding exception 55 | - Error token length mismatch in `ImapProtocol::readResponse` 56 | - Attachment name parsing fixed (thanks @nuernbergerA) 57 | - Additional Attachment name fallback added to prevent missing attachments 58 | - Attachment id is now static (based on the raw part content) instead of random 59 | - Always parse the attachment description if it is available 60 | - Fixed date issue if timezone is UT and a 2 digit year (thanks @ferrisbuellers) 61 | - Make the space optional after a comma separator (thanks @marc0adam) 62 | - Fix bug when multipart message getHTMLBody() method returns null (thanks @michalkortas) 63 | - Fix: Improve return type hints and return docblocks for query classes (thanks @olliescase) 64 | - Fix - Query - Chunked - Resolved infinite loop when start chunk > 1 (thanks @NeekTheNook) 65 | - Attachment with symbols in filename (thanks @nuernbergerA) 66 | - Ignore possible untagged lines after IDLE and DONE commands (thanks @gazben) 67 | - Fix Empty Child Folder Error (thanks @bierpub) 68 | - Filename sanitization improved (thanks @neolip) 69 | - `Client::getFolderPath()` return null if folder is not set (thanks @arnolem) 70 | - Fix implicit marking of parameters as nullable, deprecated in PHP8.4 (thanks @campbell-m) 71 | 72 | ### Added 73 | - Additional timestamp formats added (thanks @esk-ap) 74 | - Attachment content hash added 75 | - IMAP STATUS command support added `Folder::status()` (thanks @InterLinked1) 76 | - Add attributes and special flags (thanks @sazanof) 77 | - Better connection check for IMAP (thanks @thin-k-design) 78 | - Config handling moved into a new class `Config::class` to allow class serialization (sponsored by elb-BIT GmbH) 79 | - Support for Carbon 3 added 80 | - Custom decoder support added 81 | - Decoding filename with non-standard encoding (thanks @grnsv) 82 | 83 | ### Breaking changes 84 | - `Folder::getStatus()` no longer returns the results of `EXAMINE` but `STATUS` instead. If you want to use `EXAMINE` you can use the `Folder::examine()` method instead. 85 | - `ClientManager::class` has now longer access to all configs. Config handling has been moved to its own class `Config::class`. If you want to access the config you can use the retriever method `::getConfig()` instead. Example: `$client->getConfig()` or `$message->getConfig()`, etc. 86 | - `ClientManager::get` isn't available anymore. Use the regular config accessor instead. Example: `$cm->getConfig()` 87 | - `M̀essage::getConfig()` now returns the client configuration instead of the fetching options configuration. Please use `$message->getOptions()` instead. 88 | - `Attachment::getConfig()` now returns the client configuration instead of the fetching options configuration. Please use `$attachment->getOptions()` instead. 89 | - `Header::getConfig()` now returns the client configuration instead of the fetching options configuration. Please use `$header->getOptions()` instead. 90 | - `M̀essage::setConfig` now expects the client configuration instead of the fetching options configuration. Please use `$message->setOptions` instead. 91 | - `Attachment::setConfig` now expects the client configuration instead of the fetching options configuration. Please use `$attachment->setOptions` instead. 92 | - `Header::setConfig` now expects the client configuration instead of the fetching options configuration. Please use `$header->setOptions` instead. 93 | - All protocol constructors now require a `Config::class` instance 94 | - The `Client::class` constructors now require a `Config::class` instance 95 | - The `Part::class` constructors now require a `Config::class` instance 96 | - The `Header::class` constructors now require a `Config::class` instance 97 | - The `Message::fromFile` method now requires a `Config::class` instance 98 | - The `Message::fromString` method now requires a `Config::class` instance 99 | - The `Message::boot` method now requires a `Config::class` instance 100 | 101 | ## [5.3.0] - Security patch - 2023-06-20 102 | ### Fixed 103 | - Potential RCE through path traversal fixed [#414](https://github.com/Webklex/php-imap/pull/414) (special thanks @angelej) 104 | 105 | ### Security Impact and Mitigation 106 | Impacted are all versions below v5.3.0. 107 | If possible, update to >= v5.3.0 as soon as possible. Impacted was the `Attachment::save` 108 | method which could be used to write files to the local filesystem. The path was not 109 | properly sanitized and could be used to write files to arbitrary locations. 110 | 111 | However, the `Attachment::save` method is not used by default and has to be called 112 | manually. If you are using this method without providing a sanitized path, you are 113 | affected by this vulnerability. 114 | If you are not using this method or are providing a sanitized path, you are not affected 115 | by this vulnerability and no immediate action is required. 116 | 117 | If you have any questions, please feel welcome to join this issue: https://github.com/Webklex/php-imap/issues/416 118 | 119 | ## [5.2.0] - 2023-04-11 120 | ### Fixed 121 | - The message uid and message number will only be fetched if accessed and wasn't previously set (thanks @szymekjanaczek) 122 | - Fix undefined attachment name when headers use "filename*=" format (thanks @JulienChavee) 123 | - Fixed `ImapProtocol::logout` always throws 'not connected' Exception after upgraded to 4.1.2 124 | - Protocol interface and methods unified 125 | - Strict attribute and return types introduced where ever possible 126 | - Parallel messages during idle 127 | - Idle timeout / stale resource stream issue fixed 128 | - Syntax updated to support php 8 features 129 | - Get the attachment file extension from the filename if no mimetype detection library is available 130 | - Prevent the structure parsing from parsing an empty part 131 | - Convert all header keys to their lower case representation 132 | - Restructure the decode function (thanks @istid) 133 | - More unique ID generation to prevent multiple attachments with same ID (thanks @Guite) 134 | - Not all attachments are pushed to the collection (thanks @AdrianKuriata) 135 | - Allow search response to be empty 136 | - Unsafe usage of switch case. (thanks @shuergab) 137 | - Fix use of ST_MSGN as sequence method (thanks @gioid) 138 | - Prevent infinite loop in ImapProtocol (thanks @thin-k-design) 139 | - IMAP Quota root command fixed 140 | - Prevent line-breaks in folder path caused by special chars 141 | - Partial fix for (allow overview response to be empty) 142 | - `Message::setConfig()` config parameter type set to array 143 | - Reset the protocol uid cache if the session gets expunged 144 | - Set the "seen" flag only if the flag isn't set and the fetch option isn't `IMAP::FT_PEEK` 145 | - `Message::is()` date comparison fixed 146 | - `Message::$client` could not be set to null 147 | - `in_reply_to` and `references` parsing fixed 148 | - Prevent message body parser from injecting empty lines 149 | - Don't parse regular inline message parts without name or filename as attachment 150 | - `Message::hasTextBody()` and `Message::hasHtmlBody()` should return `false` if the body is empty 151 | - Imap-Protocol "empty response" detection extended to catch an empty response caused by a broken resource stream 152 | - `iconv_mime_decode()` is now used with `ICONV_MIME_DECODE_CONTINUE_ON_ERROR` to prevent the decoding from failing 153 | - Date decoding rules extended to support more date formats 154 | - Unset the currently active folder if it gets deleted (prevent infinite loop) 155 | - Attachment name and filename parsing fixed and improved to support more formats 156 | - Check if the next uid is available (after copying or moving a message) before fetching it 157 | - Default pagination `$total` attribute value set to 0 (thanks @hhniao) 158 | - Use attachment ID as fallback filename for saving an attachment 159 | - Address decoding error detection added 160 | - Use all available methods to detect the attachment extension instead of just one 161 | - Allow the `LIST` command response to be empty 162 | - Initialize folder children attributes on class initialization 163 | 164 | ### Added 165 | - Unit tests added (thanks @sergiy-petrov, @boekkooi-lengoo) 166 | - `Client::clone()` method added to clone a client instance 167 | - Save an entire message (including its headers) `Message::save()` 168 | - Restore a message from a local or remote file `Message::fromFile()` 169 | - Protocol resource stream accessor added `Protocol::getStream()` 170 | - Protocol resource stream meta data accessor added `Protocol::meta()` 171 | - ImapProtocol resource stream reset method added `ImapProtocol::reset()` 172 | - Protocol `Response::class` introduced to handle and unify all protocol requests 173 | - Static mask config accessor added `ClientManager::getMask()` added 174 | - An `Attribute::class` instance can be treated as array 175 | - Get the current client account configuration via `Client::getConfig()` 176 | - Delete a folder via `Client::deleteFolder()` 177 | - Extended UTF-7 support added (RFC2060) 178 | - `Protocol::sizes()` support added (fetch the message byte size via RFC822.SIZE). Accessible through `Message::getSize()` (thanks @didi1357) 179 | - `Message::hasFlag()` method added to check if a message has a specific flag 180 | - `Message::getConfig()` method added to get the current message configuration 181 | - `Folder::select()` method added to select a folder 182 | - `Message::getAvailableFlags()` method added to get all available flags 183 | - Live mailbox and fixture tests added 184 | - `Attribute::map()` method added to map all attribute values 185 | - `Header::has()` method added to check if a header attribute / value exist 186 | - All part attributes are now accessible via linked attribute 187 | - Restore a message from string `Message::fromString()` 188 | - Soft fail option added to all folder fetching methods. If soft fail is enabled, the method will return an empty collection instead of throwing an exception if the folder doesn't exist 189 | 190 | 191 | ### Breaking changes 192 | - PHP ^8.0.2 required 193 | - `nesbot/carbon` version bumped to ^2.62.1 194 | - `phpunit/phpunit` version bumped to ^9.5.10 195 | - `Header::get()` always returns an `Attribute::class` instance 196 | - `Attribute::class` accessor methods renamed to shorten their names and improve the readability 197 | - All protocol methods that used to return `array|bool` will now always return a `Response::class` instance. 198 | - `ResponseException::class` gets thrown if a response is empty or contains errors 199 | - Message client is optional and can be null (e.g. if used in combination with `Message::fromFile()`) 200 | - The message text or html body is now "" if its empty and not `null` 201 | 202 | 203 | ## [4.1.2] - 2023-01-18 204 | ### Fixed 205 | - Type casting added to several ImapProtocol return values 206 | - Remove IMAP::OP_READONLY flag from imap_reopen if POP3 or NNTP protocol is selected (thanks @xianzhe18) 207 | - Several statements optimized and redundant checks removed 208 | - Check if the Protocol supports the fetch method if extensions are present 209 | - Detect `NONEXISTENT` errors while selecting or examining a folder 210 | - Missing type cast added to `PaginatedCollection::paginate` (thanks @rogerb87) 211 | - Fix multiline header unfolding (thanks @sulgie-eitea) 212 | - Fix problem with illegal offset error (thanks @szymekjanaczek) 213 | - Typos fixed 214 | - RFC 822 3.1.1. long header fields regular expression fixed (thanks @hbraehne) 215 | - Fix assumedNextTaggedLine bug (thanks @Blear) 216 | - Fix empty response error for blank lines (thanks @bierpub) 217 | - Fix empty body (thanks @latypoff) 218 | - Fix imap_reopen folder argument (thanks @latypoff) 219 | - Fix for extension recognition (thanks @pwoszczyk) 220 | - Missing null check added (thanks @spanjeta) 221 | - Leading white-space in response causes an infinite loop (thanks @thin-k-design) 222 | - Fix error when creating folders with special chars (thanks @thin-k-design) 223 | - `Client::getFoldersWithStatus()` recursive loading fixed (thanks @szymekjanaczek) 224 | - Fix Folder name encoding error in `Folder::appendMessage()` (thanks @rskrzypczak) 225 | - Attachment ID can return an empty value 226 | - Additional message date format added (thanks @amorebietakoUdala) 227 | 228 | ### Added 229 | - Added possibility of loading a Folder status (thanks @szymekjanaczek) 230 | 231 | ## [4.0.0] - 2022-08-19 232 | ### Fixed 233 | - PHP dependency updated to support php v8.0 (thanks @freescout-helpdesk) 234 | - Method return and argument types added 235 | - Imap `DONE` method refactored 236 | - UID cache loop fixed 237 | - `HasEvent::getEvent` return value set to mixed to allow multiple event types 238 | - Protocol line reader changed to `fread` (stream_context timeout issue fixed) 239 | - Issue setting the client timeout fixed 240 | - IMAP Connection debugging improved 241 | - `Folder::idle()` method reworked and several issues fixed 242 | - Datetime conversion rules extended 243 | 244 | ### Breaking changes 245 | - No longer supports php >=5.5.9 but instead requires at least php v7.0.0. 246 | - `HasEvent::getEvent` returns a mixed result. Either an `Event` or a class string representing the event class. 247 | - The error message, if the connection fails to read the next line, is now `empty response` instead of `failed to read - connection closed?`. 248 | - The `$auto_reconnect` used with `Folder::indle()` is deprecated and doesn't serve any purpose anymore. 249 | 250 | 251 | ## [3.0.0-alpha] - 2021-11-10 252 | ### Fixed 253 | - Debug line position fixed 254 | - Handle incomplete address to string conversion 255 | - Configured message key gets overwritten by the first fetched message 256 | - Attachment::save() return error 'A facade root has not been set' 257 | - Unused dependencies removed 258 | - Fix PHP 8 error that changes null back in to an empty string. (thanks @mennovanhout) 259 | - Fix regex to be case insensitive (thanks @mennovanhout) 260 | - Attachment detection updated 261 | - Timeout handling improved 262 | - Additional utf-8 checks added to prevent decoding of unencoded values 263 | - Boundary detection simplified 264 | - Prevent potential body overwriting 265 | - CSV files are no longer regarded as plain body 266 | - Boundary detection overhauled to support "related" and "alternative" multipart messages 267 | - Attachment saving filename fixed 268 | - Unnecessary parameter removed from `Client::getTimeout()` 269 | - Missing encryption variable added - could have caused problems with unencrypted communications 270 | - Prefer attachment filename attribute over name attribute 271 | - Missing connection settings added to `Folder:idle()` auto mode 272 | - Message move / copy expect a folder path 273 | - `Client::getFolder()` updated to circumvent special edge cases 274 | - Missing connection status checks added to various methods 275 | - Unused default attribute `message_no` removed from `Message::class` 276 | - Fix setting default mask from config (thanks @shacky) 277 | - Chunked fetch fails in case of less available mails than page size 278 | - Protocol::createStream() exception information fixed 279 | - Legacy methods (headers, content, flags) fixed 280 | - Legacy connection cycle fixed (thanks @zssarkany) 281 | - Several POP3 fixes (thanks @Korko) 282 | - Fixes handling of long header lines which are seperated by `\r\n\t` (thanks @Oliver-Holz) 283 | - Fixes to line parsing with multiple addresses (thanks @Oliver-Holz) 284 | - Fixed problem with skipping last line of the response. (thanks @szymekjanaczek) 285 | - Extend date parsing error message 286 | - Fixed 'Where' method replaces the content with uppercase 287 | - Don't surround numeric search values with quotes 288 | - Context added to `InvalidWhereQueryCriteriaException` 289 | - Redundant `stream_set_timeout()` removed 290 | 291 | ### Added 292 | - Auto reconnect option added to `Folder::idle()` 293 | - Dynamic Attribute access support added (e.g `$message->from[0]`) 294 | - Message not found exception added 295 | - Chunked fetching support added `Query::chunked()`. Just in case you can't fetch all messages at once 296 | - "Soft fail" support added 297 | - Count method added to `Attribute:class` 298 | - Convert an Attribute instance into a Carbon date object 299 | - Disable rfc822 header parsing via config option 300 | - Added imap 4 handling. (thanks @szymekjanaczek) 301 | - Added laravel's conditionable methods. (thanks @szymekjanaczek) 302 | - Expose message folder path (thanks @Magiczne) 303 | - Adds mailparse_rfc822_parse_addresses integration (thanks @Oliver-Holz) 304 | - Added moveManyMessages method (thanks @Magiczne) 305 | - Added copyManyMessages method (thanks @Magiczne) 306 | - Added `UID` as available search criteria (thanks @szymekjanaczek) 307 | - Make boundary regex configurable (thanks @EthraZa) 308 | - IMAP ID support added 309 | - Enable debug mode via config 310 | - Custom UID alternative support added 311 | - Fetch additional extensions using `Folder::query(["FEATURE_NAME"])` 312 | - Optionally move a message during "deletion" instead of just "flagging" it (thanks @EthraZa) 313 | - `WhereQuery::where()` accepts now a wide range of criteria / values. 314 | 315 | ### Breaking changes 316 | - A new exception can occur if a message can't be fetched (`\Webklex\PHPIMAP\Exceptions\MessageNotFoundException::class`) 317 | - `Message::move()` and `Message::copy()` no longer accept folder names as folder path 318 | - A `Message::class` instance might no longer have a `message_no` attribute 319 | - All protocol methods which had a `boolean` `$uid` option no longer support a boolean. Use `IMAP::ST_UID` or `IMAP::NIL` instead. If you want to use an alternative to `UID` just use the string instead. 320 | - Default config option `options.sequence` changed from `IMAP::ST_MSGN` to `IMAP::ST_UID`. 321 | - `Folder::query()` no longer accepts a charset string. It has been replaced by an extension array, which provides the ability to automatically fetch additional features. 322 | 323 | 324 | ## [2.4.0] - 2021-01-09 325 | ### Fixed 326 | - Attachment::save() return error 'A facade root has not been set' 327 | - Unused dependencies removed 328 | - Fix PHP 8 error that changes null back in to an empty string. (thanks @mennovanhout) 329 | - Fix regex to be case insensitive (thanks @mennovanhout) 330 | - Debug line position fixed 331 | - Handle incomplete address to string conversion 332 | - Configured message key gets overwritten by the first fetched message 333 | - Get partial overview when `IMAP::ST_UID` is set 334 | - Unnecessary "'" removed from address names 335 | - Folder referral typo fixed 336 | - Legacy protocol fixed 337 | - Treat message collection keys always as strings 338 | - Missing RFC attributes added 339 | - Set the message sequence when idling 340 | - Missing UID commands added 341 | 342 | ### Added 343 | - Configurable supported default flags added 344 | - Message attribute class added to unify value handling 345 | - Address class added and integrated 346 | - Alias `Message::attachments()` for `Message::getAttachments()` added 347 | - Alias `Message::addFlag()` for `Message::setFlag()` added 348 | - Alias `Message::removeFlag()` for `Message::unsetFlag()` added 349 | - Alias `Message::flags()` for `Message::getFlags()` added 350 | - New Exception `MessageFlagException::class` added 351 | - New method `Message::setSequenceId($id)` added 352 | - Optional Header attributizion option added 353 | - Get a message by its message number 354 | - Get a message by its uid 355 | 356 | ### Breaking changes 357 | - Stringified message headers are now separated by ", " instead of " ". 358 | - All message header values such as subject, message_id, from, to, etc now consists of an `Àttribute::class` instance (should behave the same way as before, but might cause some problem in certain edge cases) 359 | - The formal address object "from", "to", etc now consists of an `Address::class` instance (should behave the same way as before, but might cause some problem in certain edge cases) 360 | - When fetching or manipulating message flags a `MessageFlagException::class` exception can be thrown if a runtime error occurs 361 | - Learn more about the new `Attribute` class here: [www.php-imap.com/api/attribute](https://www.php-imap.com/api/attribute) 362 | - Learn more about the new `Address` class here: [www.php-imap.com/api/address](https://www.php-imap.com/api/address) 363 | - Folder attribute "referal" is now called "referral" 364 | 365 | ## [2.3.0] - 2020-12-21 366 | ### Fixed 367 | - Missing env variable `IMAP_AUTHENTICATION` added 368 | - Header decoding problem fixed 369 | - IMAP::FT_PEEK removing "Seen" flag issue fixed 370 | - Text/Html body fetched as attachment if subtype is null 371 | - Potential header overwriting through header extensions 372 | - Prevent empty attachments 373 | - Search performance increased by fetching all headers, bodies and flags at once 374 | - Legacy protocol support updated 375 | - Fix Query pagination. (thanks [@mikemiller891](https://github.com/mikemiller891)) 376 | - Missing array decoder method added (thanks [@lutchin](https://github.com/lutchin)) 377 | - Additional checks added to prevent message from getting marked as seen 378 | - Boundary parsing improved (thanks [@AntonioDiPassio-AppSys](https://github.com/AntonioDiPassio-AppSys)) 379 | - Idle operation updated 380 | - Cert validation issue fixed 381 | - Allow boundaries ending with a space or semicolon (thanks [@smartilabs](https://github.com/smartilabs)) 382 | - Ignore IMAP DONE command response 383 | - Default `options.fetch` set to `IMAP::FT_PEEK` 384 | - Address parsing fixed 385 | - Alternative rfc822 header parsing fixed 386 | - Parse more than one header key 387 | - Fetch folder overview fixed 388 | - `Message::getTextBody()` fallback value fixed 389 | 390 | ### Added 391 | - Default folder locations added 392 | - Search for messages by message-Id 393 | - Search for messages by In-Reply-To 394 | - Message threading added `Message::thread()` 395 | - Default folder locations added 396 | - Set fetch order during query [@Max13](https://github.com/Max13) 397 | - Missing message setter methods added 398 | - `Folder::overview()` method added to fetch all headers of all messages in the current folder 399 | - Force a folder to be opened 400 | - Proxy support added 401 | - Flexible disposition support added 402 | - New `options.message_key` option `uid` added 403 | - Protocol UID support added 404 | - Flexible sequence type support added 405 | 406 | ### Breaking changes 407 | - Depending on your configuration, your certificates actually get checked. Which can cause an aborted connection if the certificate can not be validated. 408 | - Messages don't get flagged as read unless you are using your own custom config. 409 | - All `Header::class` attribute keys are now in a snake_format and no longer minus-separated. 410 | - `Message::getTextBody()` no longer returns false if no text body is present. `null` is returned instead. 411 | 412 | 413 | ## [2.2.0] - 2020-10-16 414 | ### Fixed 415 | - Prevent text bodies from being fetched as attachment 416 | - Missing variable check added to prevent exception while parsing an address #356 417 | - Missing variable check added to prevent exception while parsing a part subtype 418 | - Missing variable check added to prevent exception while parsing a part content-type #356 419 | - Mixed message header attribute `in_reply_to` "unified" to be always an array 420 | - Potential message moving / copying problem fixed 421 | - Move messages by using `Protocol::moveMessage()` instead of `Protocol::copyMessage()` and `Message::delete()` 422 | - Boundary detection problem fixed ([@DasTobbel](https://github.com/DasTobbel)) 423 | - Content-Type detection problem fixed ([@DasTobbel](https://github.com/DasTobbel)) 424 | - If content disposition is multiline, implode the array to a simple string ([@DasTobbel](https://github.com/DasTobbel)) 425 | - Potential problematic prefixed white-spaces removed from header attributes 426 | - Fix inline attachments and embedded images ([@dwalczyk](https://github.com/dwalczyk)) 427 | - Possible error during address decoding fixed ([@Slauta](https://github.com/Slauta)) 428 | - Flag event dispatching fixed 429 | - Fixed `Query::paginate()` ([@Max13](https://github.com/Max13)) 430 | - `Message::getAttributes()` hasn't returned all parameters 431 | - Wrong message content property reference fixed 432 | - Fix header extension values 433 | - Part header detection method changed 434 | - Possible decoding problem fixed 435 | - `Str::class` dependency removed from `Header::class` 436 | - Dependency problem in `Attachement::getExtension()` fixed 437 | - Quota handling fixed 438 | 439 | ### Added 440 | - `Protocol::moveMessage()` method added 441 | - Expended `Client::getFolder($name, $deleimiter = null)` to accept either a folder name or path ([@DasTobbel](https://github.com/DasTobbel)) 442 | - Special MS-Exchange header decoding support added 443 | - `ClientManager::make()` method added to support undefined accounts 444 | - Alternative attachment names support added ([@oneFoldSoftware](https://github.com/oneFoldSoftware)) 445 | - Fetch message content without leaving a "Seen" flag behind 446 | - Support multiple boundaries ([@dwalczyk](https://github.com/dwalczyk)) 447 | - Part number added to attachment 448 | - `Client::getFolderByPath()` added ([@Max13](https://github.com/Max13)) 449 | - `Client::getFolderByName()` added ([@Max13](https://github.com/Max13)) 450 | - Throws exceptions if the authentication fails ([@Max13](https://github.com/Max13)) 451 | - Default account config fallback added 452 | 453 | ### Breaking changes 454 | - Text bodies might no longer get fetched as attachment 455 | - `Message::$in_reply_to` type changed from mixed to array 456 | 457 | 458 | ## [2.1.1] - 2020-10-15 459 | ### Fixed 460 | - Missing default config parameter added #346 461 | 462 | ### Added 463 | - Imap idle command added 464 | 465 | ## [2.1.0] - 2020-10-08 466 | ### Fixed 467 | - Redundant class `ClientManager::class` removed and config handling moved to depending library "webklex/php-imap" #345 #344 468 | 469 | ### Breaking changes 470 | - `\Webklex\IMAP\ClientManager::class` no longer exists. Please use the `\Webklex\IMAP\Facades\Client::class` facade or `\Webklex\PHPIMAP\ClientManager::class` instead. 471 | 472 | ## [2.0.2] - 2020-09-23 473 | ### Fixed 474 | - Missing default config parameter added (#337) 475 | 476 | ## [2.0.1] - 2020-09-22 477 | ### Fixed 478 | - Wrong path to config directory (#336) 479 | 480 | ## [2.0.0] - 2020-09-22 481 | ### Fixed 482 | - Encoding / Decoding improved and exception fallback added 483 | - Missing pagination item records fixed (#287, #329) 484 | - Missing attachments problem solved (#284, #277) 485 | 486 | ### Added 487 | - php-imap module replaced by direct socket communication 488 | - Package core moved to `webklex/php-imap` 489 | - Legacy protocol support added 490 | - True IMAP IDLE support added (#185) 491 | - oAuth support added (#180) 492 | - Dynamic and customizable events added 493 | - Fetching all available headers (#282) 494 | 495 | ### Breaking changes 496 | - Most class namespaces have changed from `IMAP` to `PHPIMAP` 497 | - Method response structure has changed in most classes 498 | - Deprecated methods removed 499 | - New exceptions can occur 500 | 501 | ### Affected Classes 502 | - All 503 | 504 | ## [1.6.2] - 2020-09-07 505 | ### Fixed 506 | - Exception handling improved and missing child exception added (#326) 507 | - Fix 'A non well formed numeric value encountered' ErrorException (#327) 508 | 509 | ## [1.6.1] - 2020-09-04 510 | ### Fixed 511 | - Greatly increased IDLE performance 512 | - Message::fetchStructure() redundant code removed 513 | 514 | ### Added 515 | - Read an overview of the information in the headers of a given message or sequence 516 | - Folder name encoding added (#324) (@aperture-it) 517 | - Add a fallback when aliasing encodings for iconv (#325) (@Hokan22) 518 | - Method to receive the encoded folder name added 519 | 520 | ### Affected Classes 521 | - [Client::class](src/Client.php) 522 | - [Message::class](src/Message.php) 523 | - [Query::class](src/Query/Query.php) 524 | 525 | ## [1.6.0] - 2020-09-04 526 | ### Fixed 527 | - Default fetch attributes set to `null` in order to use the config default value 528 | 529 | ### Added 530 | - "BADCHARSET" exception will be used to determine the required charset (#100) 531 | 532 | ### Breaking changes 533 | - Client::getMessages() default fetch parameter changed 534 | - Folder::getMessages() default fetch parameter changed 535 | - Folder::getMessage() default fetch parameter changed 536 | 537 | ### Affected Classes 538 | - [Query::class](src/Query/Query.php) 539 | - [Client::class](src/Client.php) 540 | - [Folder::class](src/Folder.php) 541 | 542 | ## [1.5.3] - 2020-08-24 543 | ### Fixed 544 | - Event parameter handling fixed (#322) 545 | 546 | ## [1.5.2] - 2020-08-24 547 | ### Added 548 | - IDLE like support added (#185) 549 | 550 | ### Affected Classes 551 | - [Query::class](src/Query/Query.php) 552 | 553 | ## [1.5.1] - 2020-08-23 554 | ### Added 555 | - Message events added (deleted, restored, moved, new*) 556 | 557 | ### Affected Classes 558 | - [Message::class](src/Message.php) 559 | 560 | ## [1.5.0] - 2020-08-20 561 | ### Fixed 562 | - Point to root namespace if handling native functions (#279) 563 | - Use address charset from header information if set (#286) 564 | - Fix Attachment::getExtension() under Laravel 7.x (#290) (@ThanhSonITNIC) 565 | - Custom and X-Spam search criteria fixed (#296) 566 | 567 | ### Added 568 | - Prevent double where condition strings 569 | - Optional iconv_mime_decode() support added (#295) 570 | 571 | ### Breaking changes 572 | - Custom search conditions have to begin with `CUSTOM ` 573 | 574 | ### Affected Classes 575 | - [Query::class](src/Query/WhereQuery.php) 576 | - [Attachment::class](src/Attachment.php) 577 | - [Client::class](src/Client.php) 578 | - [Folder::class](src/Folder.php) 579 | - [Message::class](src/Message.php) 580 | 581 | ## [1.4.5] - 2020-01-23 582 | ### Fixed 583 | - Convert encoding of personal data struct #272 584 | - Test & implement fix for #203 #270 #235 585 | 586 | ### Added 587 | - Attachment size handling added #276 588 | - Find messages by custom search criteria #268 589 | 590 | ### Affected Classes 591 | - [Message::class](src/IMAP/Message.php) 592 | - [Attachment::class](src/IMAP/Attachment.php) 593 | 594 | ## [1.4.4] - 2019-11-29 595 | ### Fixed 596 | - Date handling in Folder::appendMessage() fixed #224 597 | - Carbon Exception Parse Data #45 598 | - Convert sender name from non-utf8 to uf8 #260 (@hwilok) #259 599 | 600 | ### Affected Classes 601 | - [Folder::class](src/IMAP/Folder.php) 602 | - [Message::class](src/IMAP/Message.php) 603 | 604 | ## [1.4.3] - 2019-09-15 605 | ### Fixed 606 | - .csv attachement is not processed #231 607 | - mail part structure property comparison changed to lowercase #241 #242 608 | - Replace helper functions for Laravel 6.0 #250 (@koenhoeijmakers) 609 | 610 | ### Added 611 | - Path prefix option added to Client::getFolder() method #234 612 | 613 | ### Affected Classes 614 | - [Client::class](src/IMAP/Client.php) 615 | - [Message::class](src/IMAP/Message.php) 616 | - [Attachment::class](src/IMAP/Attachment.php) 617 | - [Query::class](src/IMAP/Query/WhereQuery.php) 618 | - [Mask::class](src/IMAP/Support/Masks/Mask.php) 619 | 620 | ## [1.4.2] - 2019-07-02 621 | ### Fixed 622 | - Pagination count total bug #213 623 | - Changed internal message move and copy methods #210 624 | - Query::since() query returning empty response #215 625 | - Carbon Exception Parse Data #45 626 | - Reading a blank body (text / html) but only from this sender #203 627 | 628 | ### Added 629 | - Message::getFolder() method 630 | - Create a fast count method for queries #216 631 | - STARTTLS encryption alias added 632 | 633 | ### Affected Classes 634 | - [Message::class](src/IMAP/Message.php) 635 | - [Query::class](src/IMAP/Query/Query.php) 636 | - [Client::class](src/IMAP/Client.php) 637 | 638 | ## [1.4.1] - 2019-04-13 639 | ### Fixed 640 | - Problem with Message::moveToFolder() and multiple moves #31 641 | - Problem with encoding conversion #203 642 | - Message null value attribute problem fixed 643 | - Client connection path handling changed to be handled inside the calling method #31 644 | 645 | ### Added 646 | - Mailbox fetching exception added #201 647 | - Message::moveToFolder() fetches new Message::class afterwards #31 648 | 649 | ### Affected Classes 650 | - [Message::class](src/IMAP/Message.php) 651 | - [Folder::class](src/IMAP/Folder.php) 652 | - [Client::class](src/IMAP/Client.php) 653 | 654 | ### Breaking changes 655 | - Message::moveToFolder() returns either a Message::class instance or null and not a boolean 656 | 657 | ## [1.4.0] - 2019-03-18 658 | ### Fixed 659 | - iconv(): error suppressor for //IGNORE added #184 660 | - Typo Folder attribute fullName changed to full_name 661 | - Query scope error fixed #153 662 | 663 | ### Added 664 | - Message structure accessor added #182 665 | - Shadow Imap const class added #188 666 | - Connectable "NOT" queries added 667 | - Additional where methods added 668 | - Message attribute handling changed 669 | - Attachment attribute handling changed 670 | - Message flag handling updated 671 | - Message::getHTMLBody($callback) extended 672 | - Masks added (take look at the examples for more information on masks) 673 | - More examples added 674 | - Query::paginate() method added 675 | 676 | ### Affected Classes 677 | - [Folder::class](src/IMAP/Folder.php) 678 | - [Client::class](src/IMAP/Client.php) 679 | - [Message::class](src/IMAP/Message.php) 680 | - [Attachment::class](src/IMAP/Attachment.php) 681 | - [Query::class](src/IMAP/Query/Query.php) 682 | - [WhereQuery::class](src/IMAP/Query/WhereQuery.php) 683 | 684 | ### Breaking changes 685 | - Folder::fullName is now Folder::full_name 686 | - Attachment::image_src might no longer work as expected - use Attachment::getImageSrc() instead 687 | 688 | ## [1.3.1] - 2019-03-12 689 | ### Fixed 690 | - Replace embedded image with URL #151 691 | 692 | ### Added 693 | - Imap client timeout can be modified and read #186 694 | - Decoder config options added #175 695 | - Message search criteria "NOT" added #181 696 | 697 | ### Affected Classes 698 | - [Client::class](src/IMAP/Client.php) 699 | - [Message::class](src/IMAP/Message.php) 700 | - [Attachment::class](src/IMAP/Attachment.php) 701 | 702 | ## [1.3.0] - 2019-03-11 703 | ### Fixed 704 | - Fix sender name in non-latin emails sent from Gmail (#155) 705 | - Fix broken non-latin characters in body in ASCII (us-ascii) charset #156 706 | - Message::getMessageId() returns wrong value #197 707 | - Message date validation extended #45 #192 708 | 709 | ### Added 710 | - Invalid message date exception added 711 | 712 | ### Affected Classes 713 | - [Message::class](src/IMAP/Message.php) 714 | 715 | ## [1.2.9] - 2018-09-15 716 | ### Fixed 717 | - Removed "-i" from "iso-8859-8-i" in Message::parseBody #146 718 | 719 | ### Added 720 | - Blade examples 721 | 722 | ### Affected Classes 723 | - [Message::class](src/IMAP/Message.php) 724 | 725 | ## [1.2.8] - 2018-08-06 726 | ### Fixed 727 | - Folder delimiter check added #137 728 | 729 | ### Affected Classes 730 | - [Folder::class](src/IMAP/Folder.php) 731 | 732 | ## [1.2.7] - 2018-08-06 733 | ### Fixed 734 | - Broken non-latin characters in subjects and attachments #133 735 | 736 | ### Added 737 | - Required php extensions added to composer.json 738 | 739 | ### Affected Classes 740 | - [Message::class](src/IMAP/Message.php) 741 | - [Attachment::class](src/IMAP/Attachment.php) 742 | 743 | ## [1.2.6] - 2018-08-04 744 | ### Fixed 745 | - Message subjects and attachment names will now be decoded with a guessed encoding #97 #107 746 | 747 | ### Added 748 | - Expunge option added to critical imap operations 749 | 750 | ### Affected Classes 751 | - [Folder::class](src/IMAP/Folder.php) 752 | - [Client::class](src/IMAP/Client.php) 753 | - [Message::class](src/IMAP/Message.php) 754 | - [Attachment::class](src/IMAP/Attachment.php) 755 | 756 | ## [1.2.5] - 2018-07-30 757 | ### Fixed 758 | - Fixing undefined index error if associative config array isn't properly filled #131 759 | 760 | ### Affected Classes 761 | - [LaravelServiceProvider::class](src/IMAP/Providers/LaravelServiceProvider.php) 762 | 763 | ## [1.2.4] - 2018-07-26 764 | ### Fixed 765 | - fetch_flags default set to true on all methods 766 | - Missing fetch_flags attribute added 767 | 768 | ### Added 769 | - Folder::query() aliases added 770 | - Priority fetching added 771 | 772 | ### Affected Classes 773 | - [Folder::class](src/IMAP/Folder.php) 774 | - [Message::class](src/IMAP/Message.php) 775 | - [Query::class](src/IMAP/Query/Query.php) 776 | 777 | ## [1.2.3] - 2018-07-23 778 | ### Fixed 779 | - Config loading fixed and moved to a custom solution 780 | - Set Encryption type correctly #128 781 | - Moving a message takes now a uid #127 782 | 783 | ### Affected Classes 784 | - [Client::class](src/IMAP/Client.php) 785 | - [Message::class](src/IMAP/Message.php) 786 | 787 | ## [1.2.2] - 2018-07-22 788 | ### Fixed 789 | - Don't set the charset if it isn't used - prevent strange outlook mail server errors #100 790 | - Protocol option added -minor Fix #126 791 | 792 | ### Added 793 | - Query extended with markAsRead() and leaveUnread() methods 794 | 795 | ### Affected Classes 796 | - [Query::class](src/IMAP/Query/Query.php) 797 | - [Client::class](src/IMAP/Client.php) 798 | 799 | ## [1.2.1] - 2018-07-22 800 | ### Added 801 | - WhereQuery aliases for all where methods added 802 | 803 | ### Affected Classes 804 | - [WhereQuery::class](src/IMAP/Query/WhereQuery.php) 805 | 806 | ## [1.2.0] - 2018-07-22 807 | ### Fixed 808 | - Charset error fixed #109 809 | - Potential imap_close() error fixed #118 810 | - Plain text attachments have a content type of other/plain of text/plain #119 811 | - Carbon Exception Parse Data #45 812 | 813 | ### Added 814 | - Protocol option added #124 815 | - Message collection key option added 816 | - Message collection sorting option added 817 | - Search Query functionality added 818 | - Flag collection added 819 | - Search methods updated 820 | 821 | ### Affected Classes 822 | - [Folder::class](src/IMAP/Folder.php) 823 | - [Client::class](src/IMAP/Client.php) 824 | - [Message::class](src/IMAP/Message.php) 825 | - [Attachment::class](src/IMAP/Attachment.php) 826 | - [Query::class](src/IMAP/Query/Query.php) [WhereQuery::class](src/IMAP/Query/WhereQuery.php) 827 | 828 | ## [1.1.1] - 2018-05-04 829 | ### Fixed 830 | - Force to add a space between criteria in search query, otherwise no messages are fetched. Thanks to @cent89 831 | 832 | ### Added 833 | - Attachment::getMimeType() and Attachment::getExtension() added 834 | 835 | ### Affected Classes 836 | - [Folder::class](src/IMAP/Folder.php) 837 | - [Attachment::class](src/IMAP/Attachment.php) 838 | 839 | ## [1.1.0] - 2018-04-24 840 | ### Fixed 841 | - Client::createFolder($name) fixed #91 842 | - Versions will now follow basic **Semantic Versioning** guidelines (MAJOR.MINOR.PATCH) 843 | 844 | ### Added 845 | - Connection validation added 846 | - Client::renameFolder($old_name, $new_name) and Client::deleteFolder($name) methods added #91 847 | - Find the folder containing a message #92 848 | - Change all incoming encodings to iconv() supported ones #94 849 | 850 | ### Affected Classes 851 | - [Client::class](src/IMAP/Client.php) 852 | - [Message::class](src/IMAP/Message.php) 853 | 854 | ## [1.0.5.9] - 2018-04-15 855 | ### Added 856 | - Handle Carbon instances in message search criteria #82 857 | - $message->getRawBody() throws Exception #88 858 | - Request: add getReferences method to Message class #83 859 | 860 | ### Affected Classes 861 | - [Folder::class](src/IMAP/Folder.php) 862 | - [Message::class](src/IMAP/Message.php) 863 | 864 | ## [1.0.5.8] - 2018-04-08 865 | ### Added 866 | - Specify provider name when publishing the config #80 867 | - Enable package discovery #81 868 | 869 | ## [1.0.5.7] - 2018-04-04 870 | ### Fixed 871 | - Added option for optional attachment download #76 872 | - Added option for optional body download 873 | - Renamed "fetch" parameters 874 | - hasAttachment() method added 875 | 876 | ### Affected Classes 877 | - [Message::class](src/IMAP/Message.php) 878 | - [Folder::class](src/IMAP/Folder.php) 879 | - [Client::class](src/IMAP/Client.php) 880 | 881 | ## [1.0.5.6] - 2018-04-03 882 | ### Fixed 883 | - More explicit date validation statements 884 | - Resolving getMessage is not returning the body of the message #75 885 | 886 | ### Affected Classes 887 | - [Message::class](src/IMAP/Message.php) 888 | - [Folder::class](src/IMAP/Folder.php) 889 | 890 | ## [1.0.5.5] - 2018-03-28 891 | ### Fixed 892 | - New validation rule for a new invalid date format added (Exception Parse Data #45) 893 | - Default config keys are now fixed (Confusing default configuration values #66) 894 | 895 | ### Affected Classes 896 | - [Message::class](src/IMAP/Message.php) 897 | - [Client::class](src/IMAP/Client.php) 898 | 899 | ## [1.0.5.4] - 2018-03-27 900 | ### Fixed 901 | - Clear error stack before imap_close #72 902 | 903 | ### Affected Classes 904 | - [Client::class](src/IMAP/Client.php) 905 | 906 | ## [1.0.5.3] - 2018-03-18 907 | ### Added 908 | - FolderCollection::class added 909 | - Comments updated 910 | 911 | ### Affected Classes 912 | - [Client::class](src/IMAP/Client.php) 913 | - [Folder::class](src/IMAP/Folder.php) 914 | - [FolderCollection::class](src/IMAP/Support/FolderCollection.php) 915 | 916 | ## [1.0.5.2] - 2018-03-18 917 | ### Added 918 | - Attachment::save() method added 919 | - Unnecessary methods declared deprecated 920 | 921 | ### Affected Classes 922 | - [Client::class](src/IMAP/Client.php) 923 | - [Message::class](src/IMAP/Message.php) 924 | - [Folder::class](src/IMAP/Folder.php) 925 | - [Attachment::class](src/IMAP/Attachment.php) 926 | 927 | ## [1.0.5.1] - 2018-03-16 928 | ### Added 929 | - Message collection moved to Support 930 | - Attachment collection added 931 | - Attachment class added 932 | 933 | ### Affected Classes 934 | - [Message::class](src/IMAP/Message.php) 935 | - [Folder::class](src/IMAP/Folder.php) 936 | - [Attachment::class](src/IMAP/Attachment.php) 937 | - [MessageCollection::class](src/IMAP/Support/MessageCollection.php) 938 | - [AttachmentCollection::class](src/IMAP/Support/AttachmentCollection.php) 939 | 940 | ## [1.0.5.0] - 2018-03-16 941 | ### Added 942 | - Message search method added 943 | - Basic pagination added 944 | - Prevent automatic body parsing (will be default within the next major version (2.x)) 945 | - Unified MessageCollection::class added 946 | - Several small improvements and docs added 947 | - Implementation of the "get raw body" pull request [#59](https://github.com/Webklex/laravel-imap/pull/59) 948 | - Get a single message by uid 949 | 950 | ### Affected Classes 951 | - [Message::class](src/IMAP/Message.php) 952 | - [Client::class](src/IMAP/Client.php) 953 | - [Folder::class](src/IMAP/Folder.php) 954 | - [MessageCollection::class](src/IMAP/Support/MessageCollection.php) 955 | - [MessageSearchValidationException::class](src/IMAP/Exceptions/MessageSearchValidationException.php) 956 | 957 | ## [1.0.4.2] - 2018-03-15 958 | ### Added 959 | - Support message delivery status [#47](https://github.com/Webklex/laravel-imap/pull/47) 960 | 961 | ### Affected Classes 962 | - [Message::class](src/IMAP/Message.php) 963 | 964 | ## [1.0.4.1] - 2018-02-14 965 | ### Added 966 | - Enable support to get In-Reply-To property from Message header. [#56](https://github.com/Webklex/laravel-imap/pull/56) 967 | 968 | ### Affected Classes 969 | - [Message::class](src/IMAP/Message.php) 970 | 971 | ## [1.0.4.0] - 2018-01-28 972 | ### Added 973 | - Set and unset flags added `$oMessage->setFlag(['Seen', 'Spam']) or $oMessage->unsetFlag('Spam')` 974 | - Get raw header string `$oMessage->getHeader()` 975 | - Get additional header information `$oMessage->getHeaderInfo()` 976 | 977 | ### Affected Classes 978 | - [Message::class](src/IMAP/Message.php) 979 | 980 | ## [1.0.3.11] - 2018-01-01 981 | ### Added 982 | - New experimental function added [#48 How can I specify a single folder?](https://github.com/Webklex/laravel-imap/issues/48) 983 | 984 | ### Affected Classes 985 | - [Client::class](src/IMAP/Client.php) 986 | 987 | ## [1.0.3.10] - 2018-01-01 988 | ### Fixed 989 | - Ignore inconvertible chars in order to prevent sudden code exists 990 | 991 | ### Affected Classes 992 | - [Message::class](src/IMAP/Message.php) 993 | 994 | ## [1.0.3.9] - 2017-12-03 995 | ### Fixed 996 | - #45 DateTime::__construct(): Failed to parse time string (...) 997 | 998 | ### Affected Classes 999 | - [Message::class](src/IMAP/Message.php) 1000 | 1001 | ## [1.0.3.8] - 2017-11-24 1002 | ### Fixed 1003 | - #41 imap_expunge(): supplied resource is not a valid imap resource 1004 | - #40 mb_convert_encoding(): Illegal character encoding specified 1005 | 1006 | ### Affected Classes 1007 | - [Message::class](src/IMAP/Message.php) 1008 | 1009 | ## [1.0.3.7] - 2017-11-05 1010 | ### Fixed 1011 | - Fix assignment ```msgno``` to ```uid``` regardless of ```fetch_options``` is set in config 1012 | - Disposition is checked in case of malformed mail attachments 1013 | 1014 | ### Affected Classes 1015 | - [Message::class](src/IMAP/Message.php) 1016 | 1017 | ## [1.0.3.6] - 2017-10-24 1018 | ### Added 1019 | - A method to get only unread messages from email folders to [Client::class](src/IMAP/client.php) 1020 | 1021 | ## [1.0.3.5] - 2017-10-18 1022 | ### Fixed 1023 | - Messageset issue resolved [#31](https://github.com/Webklex/laravel-imap/issues/31) 1024 | 1025 | ### Affected Classes 1026 | - [Message::class](src/IMAP/Message.php) 1027 | - [Client::class](src/IMAP/Client.php) 1028 | 1029 | ## [1.0.3.4] - 2017-10-04 1030 | ### Fixed 1031 | - E-mails parsed without a content type of multipart present no body [#27](https://github.com/Webklex/laravel-imap/pull/27) 1032 | - Do not resolve uid to msgno if using FT_UID [#25](https://github.com/Webklex/laravel-imap/pull/25) 1033 | 1034 | ### Affected Classes 1035 | - [Message::class](src/IMAP/Message.php) 1036 | 1037 | 1038 | ## [1.0.3.3] - 2017-09-22 1039 | ### Fixed 1040 | - General code style and documentation 1041 | 1042 | ### Added 1043 | - several getter methods added to [Message::class](src/IMAP/Message.php) 1044 | 1045 | ### Affected Classes 1046 | - All 1047 | 1048 | ## [1.0.3.2] - 2017-09-07 1049 | ### Fixed 1050 | - Fix implode error in Client.php, beacause imap_errors() can return FALSE instead of an array 1051 | 1052 | ### Added 1053 | - FT_UID changed to $this->options which references to `imap.options.fetch` 1054 | 1055 | ### Affected Classes 1056 | - [Message::class](src/IMAP/Message.php) 1057 | - [Client::class](src/IMAP/Client.php) 1058 | 1059 | ## [1.0.3.1] - 2017-09-05 1060 | ### Added 1061 | - getConnection method added 1062 | - Using a bit more fail save uid / msgNo by calling imap_msgno() 1063 | 1064 | ### Affected Classes 1065 | - [Client::class](src/IMAP/Client.php) 1066 | - [Message::class](src/IMAP/Message.php) 1067 | 1068 | ## [1.0.3.0] - 2017-09-01 1069 | ### Changes 1070 | - Carbon dependency removed 1071 | 1072 | ## [1.0.2.12] - 2017-08-27 1073 | ### Added 1074 | - Fixing text attachment issue - overwrite mail body (thx to radicalloop) 1075 | 1076 | ### Affected Classes 1077 | - [Message::class](src/IMAP/Message.php) 1078 | 1079 | ## [1.0.2.11] - 2017-08-25 1080 | ### Added 1081 | - Attachment disposition (special thanks to radicalloop) 1082 | - Missing method added to README.md 1083 | 1084 | ### Affected Classes 1085 | - [Message::class](src/IMAP/Message.php) 1086 | 1087 | ## [1.0.2.10] - 2017-08-11 1088 | ### Added 1089 | - $fetch_option setter added 1090 | 1091 | ### Affected Classes 1092 | - [Message::class](src/IMAP/Message.php) 1093 | 1094 | ## [1.0.2.9] - 2017-07-12 1095 | ### Added 1096 | - Merged configuration 1097 | - New config parameter added 1098 | - "Known issues" added to README.md 1099 | - Typo fixed 1100 | 1101 | ### Affected Classes 1102 | - [Client::class](src/IMAP/Client.php) 1103 | - [LaravelServiceProvider::class](src/IMAP/Providers/LaravelServiceProvider.php) 1104 | 1105 | ## [1.0.2.8] - 2017-06-25 1106 | ### Added 1107 | - Message attribute is now case insensitive 1108 | - Readme file extended 1109 | - Changelog typo fixed 1110 | 1111 | ### Affected Classes 1112 | - [Message::class](src/IMAP/Message.php) 1113 | 1114 | 1115 | ## [1.0.2.7] - 2017-04-23 1116 | ### Added 1117 | - imap_fetchheader(): Bad message number - merged 1118 | - Changed the default options in imap_fetchbody function - merged 1119 | - Attachment handling fixed (Plain text files are no longer ignored) 1120 | - Optional config parameter added. 1121 | - Readme file extended 1122 | 1123 | ### Changes 1124 | - [Client::class](src/IMAP/Client.php) 1125 | - [Message::class](src/IMAP/Message.php) 1126 | - [Folder::class](src/IMAP/Folder.php) 1127 | 1128 | ## [1.0.2.3] - 2017-03-09 1129 | ### Added 1130 | - Code commented 1131 | - A whole bunch of functions and features added. To many to mention all of them ;) 1132 | - Readme file extended 1133 | 1134 | ### Changes 1135 | - [Client::class](src/IMAP/Client.php) 1136 | - [Message::class](src/IMAP/Message.php) 1137 | - [Folder::class](src/IMAP/Folder.php) 1138 | 1139 | ## 0.0.1 - 2017-03-04 1140 | ### Added 1141 | - new laravel-imap package 1142 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at github@webklex.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Webklex 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Malte Goldenbaum 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IMAP Library for Laravel 2 | 3 | [![Latest release on Packagist][ico-release]][link-packagist] 4 | [![Latest prerelease on Packagist][ico-prerelease]][link-packagist] 5 | [![Software License][ico-license]][link-license] 6 | [![Code quality][ico-quality]][link-scrutinizer] 7 | [![Total Downloads][ico-downloads]][link-downloads] 8 | [![Hits][ico-hits]][link-hits] 9 | [![Discord][ico-discord]][link-discord] 10 | [![Snyk][ico-snyk]][link-snyk] 11 | 12 | 13 | ## Description 14 | Laravel IMAP is an easy way to integrate both the native php-imap module and an extended custom imap protocol 15 | into your **Laravel** app. This enables your app to not only respond to new emails but also allows it to 16 | read and parse existing mails and much more. 17 | 18 | Official documentation: [php-imap.com/frameworks/laravel](https://www.php-imap.com/frameworks/laravel/installation) 19 | 20 | Discord: [discord.gg/jCcZWCSq][link-discord] 21 | 22 | ## Table of Contents 23 | - [Documentations](#documentations) 24 | - [Compatibility](#compatibility) 25 | - [Installation](#installation) 26 | - [Basic usage example](#basic-usage-example) 27 | - [Sponsors](#sponsors) 28 | - [Known issues](#known-issues) 29 | - [Support](#support) 30 | - [Features & pull requests](#features--pull-requests) 31 | - [Security](#security) 32 | - [Credits](#credits) 33 | - [Supporters](#supporters) 34 | - [License](#license) 35 | 36 | 37 | ## Documentations 38 | - Legacy (< v2.0.0): [legacy documentation](https://github.com/Webklex/laravel-imap/tree/1.6.2#table-of-contents) 39 | - Core documentation: [php-imap.com](https://www.php-imap.com/) 40 | - Example Laravel Integration: [Example Application](https://github.com/Webklex/laravel_imap_example#laravael-imap-example-application) 41 | 42 | 43 | ## Compatibility 44 | | Version | PHP 5.6 | PHP 7 | PHP 8 | 45 | |:--------|:-------:|:-----:|:-----:| 46 | | v5.x | / | / | X | 47 | | v4.x | / | X | X | 48 | | v3.x | / | X | / | 49 | | v2.x | X | X | / | 50 | | v1.x | X | / | / | 51 | 52 | 53 | ## Installation 54 | This library requires the `mbstring` php module. Make sure to install or enable it if it isn't available. 55 | ```bash 56 | sudo apt-get install php*-mbstring 57 | ``` 58 | Installation via composer: 59 | ```bash 60 | composer require webklex/laravel-imap 61 | ``` 62 | Additional information such as troubleshooting, legacy support and package publishing can be found here: 63 | [php-imap.com/frameworks/laravel/installation](https://www.php-imap.com/frameworks/laravel/installation) 64 | 65 | ## Basic usage example 66 | This is a basic example, which will echo out all Mails within all imap folders 67 | and will move every message into INBOX.read. Please be aware that this should not be 68 | tested in real life and is only meant to gives an impression on how things work. 69 | 70 | ```php 71 | /** @var \Webklex\PHPIMAP\Client $client */ 72 | $client = Webklex\IMAP\Facades\Client::account('default'); 73 | 74 | //Connect to the IMAP Server 75 | $client->connect(); 76 | 77 | //Get all Mailboxes 78 | /** @var \Webklex\PHPIMAP\Support\FolderCollection $folders */ 79 | $folders = $client->getFolders(); 80 | 81 | //Loop through every Mailbox 82 | /** @var \Webklex\PHPIMAP\Folder $folder */ 83 | foreach($folders as $folder){ 84 | 85 | //Get all Messages of the current Mailbox $folder 86 | /** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */ 87 | $messages = $folder->messages()->all()->get(); 88 | 89 | /** @var \Webklex\PHPIMAP\Message $message */ 90 | foreach($messages as $message){ 91 | echo $message->getSubject().'
'; 92 | echo 'Attachments: '.$message->getAttachments()->count().'
'; 93 | echo $message->getHTMLBody(); 94 | 95 | //Move the current Message to 'INBOX.read' 96 | if($message->move('INBOX.read') == true){ 97 | echo 'Message has been moved'; 98 | }else{ 99 | echo 'Message could not be moved'; 100 | } 101 | } 102 | } 103 | ``` 104 | 105 | 106 | ## Sponsors 107 | [![elb-BIT][ico-sponsor-elb-bit]][link-sponsor-elb-bit] 108 | [![Feline][ico-sponsor-feline]][link-sponsor-feline] 109 | 110 | 111 | ### Known issues 112 | | Error | Solution | 113 | |---------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| 114 | | Kerberos error: No credentials cache file found (try running kinit) (...) | Uncomment "DISABLE_AUTHENTICATOR" inside and use the `legacy-imap` protocol `config/imap.php` | 115 | 116 | 117 | ## Support 118 | If you encounter any problems or if you find a bug, please don't hesitate to create a new 119 | [issue](https://github.com/Webklex/laravel-imap/issues). 120 | However please be aware that it might take some time to get an answer. 121 | 122 | Off topic, rude or abusive issues will be deleted without any notice. 123 | 124 | If you need **immediate** or **commercial** support, feel free to send me a mail at github@webklex.com. 125 | 126 | ##### A little notice 127 | If you write source code in your issue, please consider to format it correctly. This makes it so much nicer to read 128 | and people are more likely to comment and help :) 129 | 130 | ```php 131 | 132 | echo 'your php code...'; 133 | 134 | ``` 135 | 136 | will turn into: 137 | ```php 138 | echo 'your php code...'; 139 | ``` 140 | 141 | ### Features & pull requests 142 | Everyone can contribute to this project. Every pull request will be considered but it can also happen to be declined. 143 | To prevent unnecessary work, please consider to create a 144 | [feature issue](https://github.com/Webklex/laravel-imap/issues/new?template=feature_request.md) 145 | first, if you're planning to do bigger changes. Of course you can also create a new 146 | [feature issue](https://github.com/Webklex/laravel-imap/issues/new?template=feature_request.md) 147 | if you're just wishing a feature ;) 148 | 149 | 150 | ## Change log 151 | Please see [CHANGELOG][link-changelog] for more information what has changed recently. 152 | 153 | ## Security 154 | If you discover any security related issues, please email github@webklex.com instead of using the issue tracker. 155 | 156 | ## Credits 157 | - [Webklex][link-author] 158 | - [All Contributors][link-contributors] 159 | 160 | ## License 161 | The MIT License (MIT). Please see [License File][link-license] for more information. 162 | 163 | 164 | [ico-release]: https://img.shields.io/packagist/v/webklex/laravel-imap.svg?style=flat-square&label=version 165 | [ico-prerelease]: https://img.shields.io/github/v/release/webklex/laravel-imap?include_prereleases&style=flat-square&label=pre-release 166 | [ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square 167 | [ico-travis]: https://img.shields.io/travis/Webklex/laravel-imap/master.svg?style=flat-square 168 | [ico-downloads]: https://img.shields.io/packagist/dt/Webklex/laravel-imap.svg?style=flat-square 169 | [ico-hits]: https://hits.webklex.com/svg/webklex/laravel-imap? 170 | [ico-build]: https://img.shields.io/scrutinizer/build/g/Webklex/laravel-imap/master?style=flat-square 171 | [ico-quality]: https://img.shields.io/scrutinizer/quality/g/Webklex/laravel-imap/master?style=flat-square 172 | [ico-snyk]: https://snyk-widget.herokuapp.com/badge/composer/webklex/laravel-imap/badge.svg 173 | [ico-discord]: https://img.shields.io/static/v1?label=discord&message=open&color=5865f2&style=flat-square 174 | 175 | [link-packagist]: https://packagist.org/packages/Webklex/laravel-imap 176 | [link-travis]: https://travis-ci.org/Webklex/laravel-imap 177 | [link-downloads]: https://packagist.org/packages/Webklex/laravel-imap 178 | [link-scrutinizer]: https://scrutinizer-ci.com/g/Webklex/laravel-imap/?branch=master 179 | [link-hits]: https://hits.webklex.com 180 | [link-author]: https://github.com/webklex 181 | [link-contributors]: https://github.com/Webklex/laravel-imap/graphs/contributors 182 | [link-license]: https://github.com/Webklex/laravel-imap/blob/master/LICENSE 183 | [link-changelog]: https://github.com/Webklex/laravel-imap/blob/master/CHANGELOG.md 184 | [link-snyk]: https://snyk.io/vuln/composer:webklex%2Flaravel-imap 185 | [link-discord]: https://discord.gg/vUHrbfbDr9 186 | 187 | 188 | [ico-sponsor-feline]: https://cdn.feline.dk/public/feline.png 189 | [link-sponsor-feline]: https://www.feline.dk 190 | [ico-sponsor-elb-bit]: https://www.elb-bit.de/user/themes/deliver/images/logo_small.png 191 | [link-sponsor-elb-bit]: https://www.elb-bit.de?ref=webklex/php-imap -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webklex/laravel-imap", 3 | "type": "library", 4 | "description": "Laravel IMAP client", 5 | "keywords": [ 6 | "webklex", 7 | "laravel", 8 | "imap", 9 | "pop3", 10 | "oauth", 11 | "idle", 12 | "laravel-imap", 13 | "mail" 14 | ], 15 | "homepage": "https://github.com/webklex/laravel-imap", 16 | "license": "MIT", 17 | "authors": [ 18 | { 19 | "name": "Malte Goldenbaum", 20 | "email": "github@webklex.com", 21 | "role": "Developer" 22 | } 23 | ], 24 | "require": { 25 | "php": "^8.0.2", 26 | "webklex/php-imap": "^6.2.0", 27 | "laravel/framework": ">=6.0.0" 28 | }, 29 | "autoload": { 30 | "psr-4": { 31 | "Webklex\\IMAP\\": "src" 32 | } 33 | }, 34 | "scripts": { 35 | "test": "phpunit" 36 | }, 37 | "extra": { 38 | "branch-alias": { 39 | "dev-master": "1.0-dev" 40 | }, 41 | "laravel": { 42 | "providers": [ 43 | "Webklex\\IMAP\\Providers\\LaravelServiceProvider" 44 | ], 45 | "aliases": { 46 | "Client": "Webklex\\IMAP\\Facades\\Client" 47 | } 48 | } 49 | }, 50 | "minimum-stability": "dev", 51 | "prefer-stable": true 52 | } 53 | -------------------------------------------------------------------------------- /examples/custom_attachment_mask.php: -------------------------------------------------------------------------------- 1 | id, $this->getMessage()->getUid(), $this->name]); 21 | } 22 | 23 | /** 24 | * Custom attachment saving method 25 | * @return bool 26 | */ 27 | public function custom_save() { 28 | $path = storage_path('foo'); 29 | $filename = $this->token(); 30 | 31 | $path = substr($path, -1) == DIRECTORY_SEPARATOR ? $path : $path.DIRECTORY_SEPARATOR; 32 | 33 | return \Illuminate\Support\Facades\File::put($path.$filename, $this->getContent()) !== false; 34 | } 35 | 36 | } 37 | 38 | /** @var \Webklex\PHPIMAP\Client $oClient */ 39 | $oClient = \Webklex\IMAP\Facades\Client::account('default'); 40 | $oClient->connect(); 41 | $oClient->setDefaultAttachmentMask(CustomAttachmentMask::class); 42 | 43 | /** @var \Webklex\PHPIMAP\Folder $folder */ 44 | $folder = $oClient->getFolder('INBOX'); 45 | 46 | /** @var \Webklex\PHPIMAP\Message $message */ 47 | $message = $folder->query()->limit(1)->get()->first(); 48 | 49 | /** @var \Webklex\PHPIMAP\Attachment $attachment */ 50 | $attachment = $message->getAttachments()->first(); 51 | 52 | /** @var CustomAttachmentMask $masked_attachment */ 53 | $masked_attachment = $attachment->mask(); 54 | 55 | echo 'Token for uid ['.$masked_attachment->getMessage()->getUid().']: '.$masked_attachment->token(); 56 | 57 | $masked_attachment->custom_save(); -------------------------------------------------------------------------------- /examples/custom_message_mask.php: -------------------------------------------------------------------------------- 1 | message_id, $this->uid, $this->message_no]); 21 | } 22 | 23 | /** 24 | * Get number of message attachments 25 | * @return integer 26 | */ 27 | public function getAttachmentCount() { 28 | return $this->getAttachments()->count(); 29 | } 30 | 31 | } 32 | 33 | /** @var \Webklex\PHPIMAP\Client $oClient */ 34 | $oClient = \Webklex\IMAP\Facades\Client::account('default'); 35 | $oClient->connect(); 36 | 37 | /** @var \Webklex\PHPIMAP\Folder $folder */ 38 | $folder = $oClient->getFolder('INBOX'); 39 | 40 | /** @var \Webklex\PHPIMAP\Message $message */ 41 | $message = $folder->query()->limit(1)->get()->first(); 42 | 43 | /** @var CustomMessageMask $masked_message */ 44 | $masked_message = $message->mask(CustomMessageMask::class); 45 | 46 | echo 'Token for uid ['.$masked_message->uid.']: '.$masked_message->my_token().' @atms:'.$masked_message->getAttachmentCount(); 47 | 48 | $masked_message->setFlag('seen'); 49 | 50 | -------------------------------------------------------------------------------- /examples/folder_structure.blade.php: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | @if($paginator->count() > 0) 28 | @foreach($paginator as $oFolder) 29 | 30 | 31 | 32 | 33 | @endforeach 34 | @else 35 | 36 | 37 | 38 | @endif 39 | 40 |
FolderUnread messages
{{$oFolder->name}}{{$oFolder->search()->unseen()->leaveUnread()->setFetchBody(false)->setFetchAttachment(false)->get()->count()}}
No folders found
41 | 42 | {{$paginator->links()}} -------------------------------------------------------------------------------- /examples/message_table.blade.php: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | @if($paginator->count() > 0) 30 | @foreach($paginator as $oMessage) 31 | 32 | 33 | 34 | 35 | 36 | 37 | @endforeach 38 | @else 39 | 40 | 41 | 42 | @endif 43 | 44 |
UIDSubjectFromAttachments
{{$oMessage->getUid()}}{{$oMessage->getSubject()}}{{$oMessage->getFrom()[0]->mail}}{{$oMessage->getAttachments()->count() > 0 ? 'yes' : 'no'}}
No messages found
45 | 46 | {{$paginator->links()}} -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | tests 15 | 16 | 17 | 18 | 19 | src/ 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Commands/ImapIdleCommand.php: -------------------------------------------------------------------------------- 1 | info("New message received: ".$message->subject); 58 | } 59 | 60 | /** 61 | * Execute the console command. 62 | * 63 | * @return int 64 | */ 65 | public function handle() { 66 | if (is_array($this->account)) { 67 | $client = ClientFacade::make($this->account); 68 | }else{ 69 | $client = ClientFacade::account($this->account); 70 | } 71 | 72 | try { 73 | $client->connect(); 74 | } catch (ConnectionFailedException $e) { 75 | Log::error($e->getMessage()); 76 | return 1; 77 | } 78 | 79 | /** @var Folder $folder */ 80 | try { 81 | $folder = $client->getFolder($this->folder_name); 82 | } catch (ConnectionFailedException $e) { 83 | Log::error($e->getMessage()); 84 | return 1; 85 | } catch (FolderFetchingException $e) { 86 | Log::error($e->getMessage()); 87 | return 1; 88 | } 89 | 90 | try { 91 | $folder->idle(function($message){ 92 | $this->onNewMessage($message); 93 | }); 94 | } catch (\Exception $e) { 95 | Log::error($e->getMessage()); 96 | return 1; 97 | } 98 | 99 | return 0; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Events/Event.php: -------------------------------------------------------------------------------- 1 | message = $arguments[0]; 22 | $this->flag = $arguments[1]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Events/FolderDeletedEvent.php: -------------------------------------------------------------------------------- 1 | old_folder = $folders[0]; 21 | $this->new_folder = $folders[1]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Events/FolderNewEvent.php: -------------------------------------------------------------------------------- 1 | folder = $folders[0]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Events/MessageCopiedEvent.php: -------------------------------------------------------------------------------- 1 | old_message = $messages[0]; 21 | $this->new_message = $messages[1]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Events/MessageNewEvent.php: -------------------------------------------------------------------------------- 1 | message = $messages[0]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Events/MessageRestoredEvent.php: -------------------------------------------------------------------------------- 1 | publishes([ 33 | __DIR__ . '/../config/imap.php' => config_path('imap.php'), 34 | ]); 35 | } 36 | 37 | /** 38 | * Register any package services. 39 | * 40 | * @return void 41 | */ 42 | public function register() { 43 | $this->setVendorConfig(); 44 | 45 | $this->app->singleton(ClientManager::class, function($app) { 46 | return new ClientManager($app['config']["imap"]); 47 | }); 48 | 49 | $this->app->singleton(Client::class, function($app) { 50 | return $app[ClientManager::class]->account(); 51 | }); 52 | } 53 | 54 | /** 55 | * Merge the vendor settings with the local config 56 | * 57 | * The default account identifier will be used as default for any missing account parameters. 58 | * If however the default account is missing a parameter the package default account parameter will be used. 59 | * This can be disabled by setting imap.default in your config file to 'false' 60 | */ 61 | private function setVendorConfig() { 62 | 63 | $config_key = 'imap'; 64 | $path = __DIR__ . '/../config/' . $config_key . '.php'; 65 | 66 | $vendor_config = require $path; 67 | $config = $this->app['config']->get($config_key, []); 68 | 69 | $this->app['config']->set($config_key, $this->array_merge_recursive_distinct($vendor_config, $config)); 70 | 71 | $config = $this->app['config']->get($config_key); 72 | 73 | if (is_array($config)) { 74 | if (isset($config['default'])) { 75 | if (isset($config['accounts']) && $config['default'] != false) { 76 | 77 | $default_config = $vendor_config['accounts']['default']; 78 | if (isset($config['accounts'][$config['default']])) { 79 | $default_config = array_merge($default_config, $config['accounts'][$config['default']]); 80 | } 81 | 82 | if (is_array($config['accounts'])) { 83 | foreach ($config['accounts'] as $account_key => $account) { 84 | $config['accounts'][$account_key] = array_merge($default_config, $account); 85 | } 86 | } 87 | } 88 | } 89 | } 90 | 91 | $this->app['config']->set($config_key, $config); 92 | } 93 | 94 | /** 95 | * Marge arrays recursively and distinct 96 | * 97 | * Merges any number of arrays / parameters recursively, replacing 98 | * entries with string keys with values from latter arrays. 99 | * If the entry or the next value to be assigned is an array, then it 100 | * automatically treats both arguments as an array. 101 | * Numeric entries are appended, not replaced, but only if they are 102 | * unique 103 | * 104 | * @param array $array1 Initial array to merge. 105 | * @param array ... Variable list of arrays to recursively merge. 106 | * 107 | * @return array|mixed 108 | * 109 | * @link http://www.php.net/manual/en/function.array-merge-recursive.php#96201 110 | * @author Mark Roduner 111 | */ 112 | private function array_merge_recursive_distinct() { 113 | 114 | $arrays = func_get_args(); 115 | $base = array_shift($arrays); 116 | 117 | if (!is_array($base)) $base = empty($base) ? array() : array($base); 118 | 119 | foreach ($arrays as $append) { 120 | 121 | if (!is_array($append)) $append = array($append); 122 | 123 | foreach ($append as $key => $value) { 124 | 125 | if (!array_key_exists($key, $base) and !is_numeric($key)) { 126 | $base[$key] = $append[$key]; 127 | continue; 128 | } 129 | 130 | if (is_array($value) or is_array($base[$key])) { 131 | $base[$key] = $this->array_merge_recursive_distinct($base[$key], $append[$key]); 132 | } else if (is_numeric($key)) { 133 | if (!in_array($value, $base)) $base[] = $value; 134 | } else { 135 | $base[$key] = $value; 136 | } 137 | 138 | } 139 | 140 | } 141 | 142 | return $base; 143 | } 144 | 145 | } -------------------------------------------------------------------------------- /src/config/imap.php: -------------------------------------------------------------------------------- 1 | env('IMAP_DEFAULT_ACCOUNT', 'default'), 26 | 27 | /* 28 | |-------------------------------------------------------------------------- 29 | | Default date format 30 | |-------------------------------------------------------------------------- 31 | | 32 | | The default date format is used to convert any given Carbon::class object into a valid date string. 33 | | These are currently known working formats: "d-M-Y", "d-M-y", "d M y" 34 | | 35 | */ 36 | 'date_format' => 'd-M-Y', 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Available IMAP accounts 41 | |-------------------------------------------------------------------------- 42 | | 43 | | Please list all IMAP accounts which you are planning to use within the 44 | | array below. 45 | | 46 | */ 47 | 'accounts' => [ 48 | 49 | 'default' => [// account identifier 50 | 'host' => env('IMAP_HOST', 'localhost'), 51 | 'port' => env('IMAP_PORT', 993), 52 | 'protocol' => env('IMAP_PROTOCOL', 'imap'), //might also use imap, [pop3 or nntp (untested)] 53 | 'encryption' => env('IMAP_ENCRYPTION', 'ssl'), // Supported: false, 'ssl', 'tls', 'notls', 'starttls' 54 | 'validate_cert' => env('IMAP_VALIDATE_CERT', true), 55 | 'username' => env('IMAP_USERNAME', 'root@example.com'), 56 | 'password' => env('IMAP_PASSWORD', ''), 57 | 'authentication' => env('IMAP_AUTHENTICATION', null), 58 | 'proxy' => [ 59 | 'socket' => null, 60 | 'request_fulluri' => false, 61 | 'username' => null, 62 | 'password' => null, 63 | ], 64 | "timeout" => 30, 65 | "extensions" => [] 66 | ], 67 | 68 | /* 69 | 'gmail' => [ // account identifier 70 | 'host' => 'imap.gmail.com', 71 | 'port' => 993, 72 | 'encryption' => 'ssl', 73 | 'validate_cert' => true, 74 | 'username' => 'example@gmail.com', 75 | 'password' => 'PASSWORD', 76 | 'authentication' => 'oauth', 77 | ], 78 | 79 | 'another' => [ // account identifier 80 | 'host' => '', 81 | 'port' => 993, 82 | 'encryption' => false, 83 | 'validate_cert' => true, 84 | 'username' => '', 85 | 'password' => '', 86 | 'authentication' => null, 87 | ] 88 | */ 89 | ], 90 | 91 | /* 92 | |-------------------------------------------------------------------------- 93 | | Available IMAP options 94 | |-------------------------------------------------------------------------- 95 | | 96 | | Available php imap config parameters are listed below 97 | | -Delimiter (optional): 98 | | This option is only used when calling $oClient-> 99 | | You can use any supported char such as ".", "/", (...) 100 | | -Fetch option: 101 | | IMAP::FT_UID - Message marked as read by fetching the body message 102 | | IMAP::FT_PEEK - Fetch the message without setting the "seen" flag 103 | | -Fetch sequence id: 104 | | IMAP::ST_UID - Fetch message components using the message uid 105 | | IMAP::ST_MSGN - Fetch message components using the message number 106 | | -Body download option 107 | | Default TRUE 108 | | -Flag download option 109 | | Default TRUE 110 | | -Soft fail 111 | | Default FALSE - Set to TRUE if you want to ignore certain exception while fetching bulk messages 112 | | -RFC822 113 | | Default TRUE - Set to FALSE to prevent the usage of \imap_rfc822_parse_headers(). 114 | | See https://github.com/Webklex/php-imap/issues/115 for more information. 115 | | -Debug enable to trace communication traffic 116 | | -UID cache enable the UID cache 117 | | -Fallback date is used if the given message date could not be parsed 118 | | -Boundary regex used to detect message boundaries. If you are having problems with empty messages, missing 119 | | attachments or anything like this. Be advised that it likes to break which causes new problems.. 120 | | -Message key identifier option 121 | | You can choose between the following: 122 | | 'id' - Use the MessageID as array key (default, might cause hickups with yahoo mail) 123 | | 'number' - Use the message number as array key (isn't always unique and can cause some interesting behavior) 124 | | 'list' - Use the message list number as array key (incrementing integer (does not always start at 0 or 1) 125 | | 'uid' - Use the message uid as array key (isn't always unique and can cause some interesting behavior) 126 | | -Fetch order 127 | | 'asc' - Order all messages ascending (probably results in oldest first) 128 | | 'desc' - Order all messages descending (probably results in newest first) 129 | | -Disposition types potentially considered an attachment 130 | | Default ['attachment', 'inline'] 131 | | -Common folders 132 | | Default folder locations and paths assumed if none is provided 133 | | -Open IMAP options: 134 | | DISABLE_AUTHENTICATOR - Disable authentication properties. 135 | | Use 'GSSAPI' if you encounter the following 136 | | error: "Kerberos error: No credentials cache 137 | | file found (try running kinit) (...)" 138 | | or ['GSSAPI','PLAIN'] if you are using outlook mail 139 | | 140 | */ 141 | 'options' => [ 142 | 'delimiter' => '/', 143 | 'fetch' => \Webklex\PHPIMAP\IMAP::FT_PEEK, 144 | 'sequence' => \Webklex\PHPIMAP\IMAP::ST_UID, 145 | 'fetch_body' => true, 146 | 'fetch_flags' => true, 147 | 'soft_fail' => false, 148 | 'rfc822' => true, 149 | 'debug' => false, 150 | 'uid_cache' => true, 151 | // 'fallback_date' => "01.01.1970 00:00:00", 152 | 'boundary' => '/boundary=(.*?(?=;)|(.*))/i', 153 | 'message_key' => 'list', 154 | 'fetch_order' => 'asc', 155 | 'dispositions' => ['attachment', 'inline'], 156 | 'common_folders' => [ 157 | "root" => "INBOX", 158 | "junk" => "INBOX/Junk", 159 | "draft" => "INBOX/Drafts", 160 | "sent" => "INBOX/Sent", 161 | "trash" => "INBOX/Trash", 162 | ], 163 | 'open' => [ 164 | // 'DISABLE_AUTHENTICATOR' => 'GSSAPI' 165 | ] 166 | ], 167 | 168 | /** 169 | * |-------------------------------------------------------------------------- 170 | * | Available decoding options 171 | * |-------------------------------------------------------------------------- 172 | * | 173 | * | Available php imap config parameters are listed below 174 | * | -options: Decoder options (currently only the message subject and attachment name decoder can be set) 175 | * | 'utf-8' - Uses imap_utf8($string) to decode a string 176 | * | 'mimeheader' - Uses mb_decode_mimeheader($string) to decode a string 177 | * | -decoder: Decoder to be used. Can be replaced by custom decoders if needed. 178 | * | 'header' - HeaderDecoder 179 | * | 'message' - MessageDecoder 180 | * | 'attachment' - AttachmentDecoder 181 | */ 182 | 'decoding' => [ 183 | 'options' => [ 184 | 'header' => 'utf-8', // mimeheader 185 | 'message' => 'utf-8', // mimeheader 186 | 'attachment' => 'utf-8' // mimeheader 187 | ], 188 | 'decoder' => [ 189 | 'header' => \Webklex\PHPIMAP\Decoder\HeaderDecoder::class, 190 | 'message' => \Webklex\PHPIMAP\Decoder\MessageDecoder::class, 191 | 'attachment' => \Webklex\PHPIMAP\Decoder\AttachmentDecoder::class 192 | ] 193 | ], 194 | 195 | /* 196 | |-------------------------------------------------------------------------- 197 | | Available flags 198 | |-------------------------------------------------------------------------- 199 | | 200 | | List all available / supported flags. Set to null to accept all given flags. 201 | */ 202 | 'flags' => ['recent', 'flagged', 'answered', 'deleted', 'seen', 'draft'], 203 | 204 | /* 205 | |-------------------------------------------------------------------------- 206 | | Available events 207 | |-------------------------------------------------------------------------- 208 | | 209 | */ 210 | 'events' => [ 211 | "message" => [ 212 | 'new' => \Webklex\IMAP\Events\MessageNewEvent::class, 213 | 'moved' => \Webklex\IMAP\Events\MessageMovedEvent::class, 214 | 'copied' => \Webklex\IMAP\Events\MessageCopiedEvent::class, 215 | 'deleted' => \Webklex\IMAP\Events\MessageDeletedEvent::class, 216 | 'restored' => \Webklex\IMAP\Events\MessageRestoredEvent::class, 217 | ], 218 | "folder" => [ 219 | 'new' => \Webklex\IMAP\Events\FolderNewEvent::class, 220 | 'moved' => \Webklex\IMAP\Events\FolderMovedEvent::class, 221 | 'deleted' => \Webklex\IMAP\Events\FolderDeletedEvent::class, 222 | ], 223 | "flag" => [ 224 | 'new' => \Webklex\IMAP\Events\FlagNewEvent::class, 225 | 'deleted' => \Webklex\IMAP\Events\FlagDeletedEvent::class, 226 | ], 227 | ], 228 | 229 | /* 230 | |-------------------------------------------------------------------------- 231 | | Available masking options 232 | |-------------------------------------------------------------------------- 233 | | 234 | | By using your own custom masks you can implement your own methods for 235 | | a better and faster access and less code to write. 236 | | 237 | | Checkout the two examples custom_attachment_mask and custom_message_mask 238 | | for a quick start. 239 | | 240 | | The provided masks below are used as the default masks. 241 | */ 242 | 'masks' => [ 243 | 'message' => \Webklex\PHPIMAP\Support\Masks\MessageMask::class, 244 | 'attachment' => \Webklex\PHPIMAP\Support\Masks\AttachmentMask::class 245 | ] 246 | ]; 247 | --------------------------------------------------------------------------------