├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── general-help-request.md ├── docker │ ├── Dockerfile │ └── dovecot_setup.sh └── workflows │ └── tests.yaml ├── .gitignore ├── 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 ├── Address.php ├── Attachment.php ├── Attribute.php ├── Client.php ├── ClientManager.php ├── Config.php ├── Connection │ └── Protocols │ │ ├── ImapProtocol.php │ │ ├── LegacyProtocol.php │ │ ├── Protocol.php │ │ ├── ProtocolInterface.php │ │ └── Response.php ├── Decoder │ ├── AttachmentDecoder.php │ ├── Decoder.php │ ├── DecoderInterface.php │ ├── HeaderDecoder.php │ └── MessageDecoder.php ├── EncodingAliases.php ├── Events │ ├── Event.php │ ├── FlagDeletedEvent.php │ ├── FlagNewEvent.php │ ├── FolderDeletedEvent.php │ ├── FolderMovedEvent.php │ ├── FolderNewEvent.php │ ├── MessageCopiedEvent.php │ ├── MessageDeletedEvent.php │ ├── MessageMovedEvent.php │ ├── MessageNewEvent.php │ └── MessageRestoredEvent.php ├── Exceptions │ ├── AuthFailedException.php │ ├── ConnectionFailedException.php │ ├── DecoderNotFoundException.php │ ├── EventNotFoundException.php │ ├── FolderFetchingException.php │ ├── GetMessagesFailedException.php │ ├── ImapBadRequestException.php │ ├── ImapServerErrorException.php │ ├── InvalidMessageDateException.php │ ├── InvalidWhereQueryCriteriaException.php │ ├── MaskNotFoundException.php │ ├── MessageContentFetchingException.php │ ├── MessageFlagException.php │ ├── MessageHeaderFetchingException.php │ ├── MessageNotFoundException.php │ ├── MessageSearchValidationException.php │ ├── MessageSizeFetchingException.php │ ├── MethodNotFoundException.php │ ├── MethodNotSupportedException.php │ ├── NotSupportedCapabilityException.php │ ├── ProtocolNotSupportedException.php │ ├── ResponseException.php │ ├── RuntimeException.php │ └── SpoofingAttemptDetectedException.php ├── Folder.php ├── Header.php ├── IMAP.php ├── Message.php ├── Part.php ├── Query │ ├── Query.php │ └── WhereQuery.php ├── Structure.php ├── Support │ ├── AttachmentCollection.php │ ├── FlagCollection.php │ ├── FolderCollection.php │ ├── Masks │ │ ├── AttachmentMask.php │ │ ├── Mask.php │ │ └── MessageMask.php │ ├── MessageCollection.php │ └── PaginatedCollection.php ├── Traits │ └── HasEvents.php └── config │ └── imap.php └── tests ├── AddressTest.php ├── AttachmentTest.php ├── AttributeTest.php ├── ClientManagerTest.php ├── ClientTest.php ├── HeaderTest.php ├── ImapProtocolTest.php ├── MessageTest.php ├── PartTest.php ├── StructureTest.php ├── fixtures ├── AttachmentEncodedFilenameTest.php ├── AttachmentLongFilenameTest.php ├── AttachmentNoDispositionTest.php ├── BccTest.php ├── BooleanDecodedContentTest.php ├── DateTemplateTest.php ├── EmailAddressTest.php ├── EmbeddedEmailTest.php ├── EmbeddedEmailWithoutContentDispositionEmbeddedTest.php ├── EmbeddedEmailWithoutContentDispositionTest.php ├── ExampleBounceTest.php ├── FixtureTestCase.php ├── FourNestedEmailsTest.php ├── GbkCharsetTest.php ├── HtmlOnlyTest.php ├── ImapMimeHeaderDecodeReturnsFalseTest.php ├── InlineAttachmentTest.php ├── KsC56011987HeadersTest.php ├── MailThatIsAttachmentTest.php ├── MissingDateTest.php ├── MissingFromTest.php ├── MixedFilenameTest.php ├── MultipartWithoutBodyTest.php ├── MultipleHtmlPartsAndAttachmentsTest.php ├── MultipleNestedAttachmentsTest.php ├── NestesEmbeddedWithAttachmentTest.php ├── NullContentCharsetTest.php ├── PecTest.php ├── PlainOnlyTest.php ├── PlainTextAttachmentTest.php ├── ReferencesTest.php ├── SimpleMultipartTest.php ├── StructuredWithAttachmentTest.php ├── UndefinedCharsetHeaderTest.php ├── UndisclosedRecipientsMinusTest.php ├── UndisclosedRecipientsSpaceTest.php ├── UndisclosedRecipientsTest.php ├── UnknownEncodingTest.php ├── WithoutCharsetPlainOnlyTest.php └── WithoutCharsetSimpleMultipartTest.php ├── issues ├── Issue275Test.php ├── Issue355Test.php ├── Issue379Test.php ├── Issue382Test.php ├── Issue383Test.php ├── Issue393Test.php ├── Issue401Test.php ├── Issue407Test.php ├── Issue40Test.php ├── Issue410Test.php ├── Issue412Test.php ├── Issue413Test.php ├── Issue414Test.php ├── Issue420Test.php ├── Issue462Test.php ├── Issue469Test.php ├── Issue511Test.php └── Issue544Test.php ├── live ├── ClientTest.php ├── FolderTest.php ├── LegacyTest.php ├── LiveMailboxTestCase.php ├── MessageTest.php └── QueryTest.php └── messages ├── 1366671050@github.com.eml ├── attachment_encoded_filename.eml ├── attachment_long_filename.eml ├── attachment_no_disposition.eml ├── bcc.eml ├── boolean_decoded_content.eml ├── date-template.eml ├── email_address.eml ├── embedded_email.eml ├── embedded_email_without_content_disposition-embedded.eml ├── embedded_email_without_content_disposition.eml ├── example_attachment.eml ├── example_bounce.eml ├── four_nested_emails.eml ├── gbk_charset.eml ├── html_only.eml ├── imap_mime_header_decode_returns_false.eml ├── inline_attachment.eml ├── issue-275-2.eml ├── issue-275.eml ├── issue-348.eml ├── issue-382.eml ├── issue-40.eml ├── issue-401.eml ├── issue-410.eml ├── issue-410b.eml ├── issue-410symbols.eml ├── issue-412.eml ├── issue-413.eml ├── issue-414.eml ├── issue-462.eml ├── issue-511.eml ├── issue-544.eml ├── ks_c_5601-1987_headers.eml ├── mail_that_is_attachment.eml ├── missing_date.eml ├── missing_from.eml ├── mixed_filename.eml ├── multipart_without_body.eml ├── multiple_html_parts_and_attachments.eml ├── multiple_nested_attachments.eml ├── nestes_embedded_with_attachment.eml ├── null_content_charset.eml ├── pec.eml ├── plain.eml ├── plain_only.eml ├── plain_text_attachment.eml ├── references.eml ├── simple_multipart.eml ├── structured_with_attachment.eml ├── thread_my_topic.eml ├── thread_re_my_topic.eml ├── thread_unrelated.eml ├── undefined_charset_header.eml ├── undisclosed_recipients.eml ├── undisclosed_recipients_minus.eml ├── undisclosed_recipients_space.eml ├── unknown_encoding.eml ├── without_charset_plain_only.eml └── without_charset_simple_multipart.eml /.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 | **Used config** 11 | Please provide the used config, if you are not using the package default config. 12 | 13 | **Code to Reproduce** 14 | The troubling code section which produces the reported bug. 15 | ```php 16 | echo "Bug"; 17 | ``` 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Desktop / Server (please complete the following information):** 26 | - OS: [e.g. Debian 10] 27 | - PHP: [e.g. 5.5.9] 28 | - Version [e.g. v2.3.1] 29 | - Provider [e.g. Gmail, Outlook, Dovecot] 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.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 | 9 | Also make sure to use https://github.com/Webklex/php-imap/issues/new?template=bug_report.md if you want to report a bug 10 | or https://github.com/Webklex/php-imap/issues/new?template=feature_request.md if you want to suggest a feature. 11 | 12 | Still here? Well clean this out and go ahead :) 13 | -------------------------------------------------------------------------------- /.github/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | LABEL maintainer="Webklex " 3 | 4 | RUN apt-get update 5 | RUN apt-get upgrade -y 6 | RUN apt-get install -y sudo dovecot-imapd 7 | 8 | ENV LIVE_MAILBOX=true 9 | ENV LIVE_MAILBOX_HOST=mail.example.local 10 | ENV LIVE_MAILBOX_PORT=993 11 | ENV LIVE_MAILBOX_ENCRYPTION=ssl 12 | ENV LIVE_MAILBOX_VALIDATE_CERT=true 13 | ENV LIVE_MAILBOX_USERNAME=root@example.local 14 | ENV LIVE_MAILBOX_PASSWORD=foobar 15 | ENV LIVE_MAILBOX_QUOTA_SUPPORT=true 16 | 17 | EXPOSE 993 18 | 19 | ADD dovecot_setup.sh /root/dovecot_setup.sh 20 | RUN chmod +x /root/dovecot_setup.sh 21 | 22 | CMD ["/bin/bash", "-c", "/root/dovecot_setup.sh && tail -f /dev/null"] 23 | 24 | -------------------------------------------------------------------------------- /.github/docker/dovecot_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ex 4 | 5 | sudo apt-get -q update 6 | sudo apt-get -q -y install dovecot-imapd 7 | 8 | { 9 | echo "127.0.0.1 $LIVE_MAILBOX_HOST" 10 | } | sudo tee -a /etc/hosts 11 | 12 | SSL_CERT="/etc/ssl/certs/dovecot.crt" 13 | SSL_KEY="/etc/ssl/private/dovecot.key" 14 | 15 | sudo openssl req -new -x509 -days 3 -nodes \ 16 | -out "$SSL_CERT" \ 17 | -keyout "$SSL_KEY" \ 18 | -subj "/C=EU/ST=Europe/L=Home/O=Webklex/OU=Webklex DEV/CN=""$LIVE_MAILBOX_HOST" 19 | 20 | sudo chown root:dovecot "$SSL_CERT" "$SSL_KEY" 21 | sudo chmod 0440 "$SSL_CERT" 22 | sudo chmod 0400 "$SSL_KEY" 23 | 24 | DOVECOT_CONF="/etc/dovecot/local.conf" 25 | MAIL_CONF="/etc/dovecot/conf.d/10-mail.conf" 26 | IMAP_CONF="/etc/dovecot/conf.d/20-imap.conf" 27 | QUOTA_CONF="/etc/dovecot/conf.d/90-quota.conf" 28 | sudo touch "$DOVECOT_CONF" "$MAIL_CONF" "$IMAP_CONF" "$QUOTA_CONF" 29 | sudo chown root:dovecot "$DOVECOT_CONF" "$MAIL_CONF" "$IMAP_CONF" "$QUOTA_CONF" 30 | sudo chmod 0640 "$DOVECOT_CONF" "$MAIL_CONF" "$IMAP_CONF" "$QUOTA_CONF" 31 | 32 | { 33 | echo "ssl = required" 34 | echo "disable_plaintext_auth = yes" 35 | echo "ssl_cert = <""$SSL_CERT" 36 | echo "ssl_key = <""$SSL_KEY" 37 | echo "ssl_protocols = !SSLv2 !SSLv3" 38 | echo "ssl_cipher_list = AES128+EECDH:AES128+EDH" 39 | } | sudo tee -a "$DOVECOT_CONF" 40 | 41 | { 42 | echo "mail_plugins = \$mail_plugins quota" 43 | } | sudo tee -a "$MAIL_CONF" 44 | 45 | { 46 | echo "protocol imap {" 47 | echo " mail_plugins = \$mail_plugins imap_quota" 48 | echo "}" 49 | } | sudo tee -a "$IMAP_CONF" 50 | 51 | { 52 | echo "plugin {" 53 | echo " quota = maildir:User quota" 54 | echo " quota_rule = *:storage=1G" 55 | echo "}" 56 | } | sudo tee -a "$QUOTA_CONF" 57 | 58 | sudo useradd --create-home --shell /bin/false "$LIVE_MAILBOX_USERNAME" 59 | echo "$LIVE_MAILBOX_USERNAME"":""$LIVE_MAILBOX_PASSWORD" | sudo chpasswd 60 | 61 | sudo service dovecot restart 62 | 63 | sudo doveadm auth test -x service=imap "$LIVE_MAILBOX_USERNAME" "$LIVE_MAILBOX_PASSWORD" -------------------------------------------------------------------------------- /.github/workflows/tests.yaml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '0 0 * * *' 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | phpunit: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | fail-fast: true 18 | matrix: 19 | php: ['8.0', 8.1, 8.2, 8.3, 8.4] 20 | 21 | name: PHP ${{ matrix.php }} 22 | 23 | env: 24 | LIVE_MAILBOX: true 25 | LIVE_MAILBOX_DEBUG: true 26 | LIVE_MAILBOX_HOST: mail.example.local 27 | LIVE_MAILBOX_PORT: 993 28 | LIVE_MAILBOX_USERNAME: root@example.local 29 | LIVE_MAILBOX_ENCRYPTION: ssl 30 | LIVE_MAILBOX_PASSWORD: foobar 31 | LIVE_MAILBOX_QUOTA_SUPPORT: true 32 | 33 | steps: 34 | - name: Checkout code 35 | uses: actions/checkout@v3 36 | 37 | - name: Setup PHP 38 | uses: shivammathur/setup-php@v2 39 | with: 40 | php-version: ${{ matrix.php }} 41 | extensions: openssl, json, mbstring, iconv, fileinfo, libxml, zip 42 | coverage: none 43 | 44 | - name: Install Composer dependencies 45 | run: composer install --prefer-dist --no-interaction --no-progress 46 | 47 | - run: "sh .github/docker/dovecot_setup.sh" 48 | 49 | - name: Execute tests 50 | run: vendor/bin/phpunit -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | .idea 4 | /build/ 5 | test.php 6 | .phpunit.result.cache 7 | phpunit.xml -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webklex/php-imap", 3 | "type": "library", 4 | "description": "PHP IMAP client", 5 | "keywords": [ 6 | "webklex", 7 | "imap", 8 | "pop3", 9 | "php-imap", 10 | "mail" 11 | ], 12 | "homepage": "https://github.com/webklex/php-imap", 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "Malte Goldenbaum", 17 | "email": "github@webklex.com", 18 | "role": "Developer" 19 | } 20 | ], 21 | "require": { 22 | "php": "^8.0.2", 23 | "ext-openssl": "*", 24 | "ext-json": "*", 25 | "ext-mbstring": "*", 26 | "ext-iconv": "*", 27 | "ext-libxml": "*", 28 | "ext-zip": "*", 29 | "ext-fileinfo": "*", 30 | "nesbot/carbon": "^2.62.1|^3.2.4", 31 | "symfony/http-foundation": ">=2.8.0", 32 | "illuminate/pagination": ">=5.0.0" 33 | }, 34 | "require-dev": { 35 | "phpunit/phpunit": "^9.5.10" 36 | }, 37 | "suggest": { 38 | "symfony/mime": "Recomended for better extension support", 39 | "symfony/var-dumper": "Usefull tool for debugging" 40 | }, 41 | "autoload": { 42 | "psr-4": { 43 | "Webklex\\PHPIMAP\\": "src" 44 | } 45 | }, 46 | "autoload-dev": { 47 | "psr-4": { 48 | "Tests\\": "tests" 49 | } 50 | }, 51 | "scripts": { 52 | "test": "phpunit" 53 | }, 54 | "extra": { 55 | "branch-alias": { 56 | "dev-master": "6.0-dev" 57 | } 58 | }, 59 | "minimum-stability": "dev", 60 | "prefer-stable": true 61 | } 62 | -------------------------------------------------------------------------------- /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(): bool { 28 | $path = "foo".DIRECTORY_SEPARATOR."bar".DIRECTORY_SEPARATOR; 29 | $filename = $this->token(); 30 | 31 | return file_put_contents($path.$filename, $this->getContent()) !== false; 32 | } 33 | 34 | } 35 | 36 | $cm = new \Webklex\PHPIMAP\ClientManager('path/to/config/imap.php'); 37 | 38 | /** @var \Webklex\PHPIMAP\Client $client */ 39 | $client = $cm->account('default'); 40 | $client->connect(); 41 | $client->setDefaultAttachmentMask(CustomAttachmentMask::class); 42 | 43 | /** @var \Webklex\PHPIMAP\Folder $folder */ 44 | $folder = $client->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(): int { 28 | return $this->getAttachments()->count(); 29 | } 30 | 31 | } 32 | 33 | $cm = new \Webklex\PHPIMAP\ClientManager('path/to/config/imap.php'); 34 | 35 | /** @var \Webklex\PHPIMAP\Client $client */ 36 | $client = $cm->account('default'); 37 | $client->connect(); 38 | 39 | /** @var \Webklex\PHPIMAP\Folder $folder */ 40 | $folder = $client->getFolder('INBOX'); 41 | 42 | /** @var \Webklex\PHPIMAP\Message $message */ 43 | $message = $folder->query()->limit(1)->get()->first(); 44 | 45 | /** @var CustomMessageMask $masked_message */ 46 | $masked_message = $message->mask(CustomMessageMask::class); 47 | 48 | echo 'Token for uid [' . $masked_message->uid . ']: ' . $masked_message->token() . ' @atms:' . $masked_message->getAttachmentCount(); 49 | 50 | $masked_message->setFlag('seen'); 51 | 52 | -------------------------------------------------------------------------------- /examples/folder_structure.blade.php: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | count() > 0): ?> 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
FolderUnread messages
name; ?>search()->unseen()->setFetchBody(false)->count(); ?>
No folders found
41 | 42 | links(); ?> -------------------------------------------------------------------------------- /examples/message_table.blade.php: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | count() > 0): ?> 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
UIDSubjectFromAttachments
getUid(); ?>getSubject(); ?>getFrom()[0]->mail; ?>getAttachments()->count() > 0 ? 'yes' : 'no'; ?>
No messages found
45 | 46 | links(); ?> -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | src/ 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | tests 16 | tests/fixtures 17 | tests/issues 18 | tests/live 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/Address.php: -------------------------------------------------------------------------------- 1 | personal = $object->personal ?? ''; } 42 | if (property_exists($object, "mailbox")){ $this->mailbox = $object->mailbox ?? ''; } 43 | if (property_exists($object, "host")){ $this->host = $object->host ?? ''; } 44 | if (property_exists($object, "mail")){ $this->mail = $object->mail ?? ''; } 45 | if (property_exists($object, "full")){ $this->full = $object->full ?? ''; } 46 | $this->boot(); 47 | } 48 | 49 | /** 50 | * Boot the address 51 | */ 52 | private function boot(): void { 53 | if($this->mail === "" && $this->mailbox !== "" && $this->host !== ""){ 54 | $this->mail = $this->mailbox . "@" . $this->host; 55 | }elseif($this->mail === "" && $this->mailbox !== ""){ 56 | $this->mail = $this->mailbox; 57 | } 58 | 59 | if($this->full === "" && $this->mail !== "" && $this->personal !== ""){ 60 | $this->full = $this->personal . " <" . $this->mail . ">"; 61 | }elseif($this->full === "" && $this->mail !== ""){ 62 | $this->full = $this->mail; 63 | } 64 | } 65 | 66 | 67 | /** 68 | * Return the stringified address 69 | * 70 | * @return string 71 | */ 72 | public function __toString() { 73 | return $this->full ?: ""; 74 | } 75 | 76 | /** 77 | * Return the serialized address 78 | * 79 | * @return array 80 | */ 81 | public function __serialize(){ 82 | return [ 83 | "personal" => $this->personal, 84 | "mailbox" => $this->mailbox, 85 | "host" => $this->host, 86 | "mail" => $this->mail, 87 | "full" => $this->full, 88 | ]; 89 | } 90 | 91 | /** 92 | * Convert instance to array 93 | * 94 | * @return array 95 | */ 96 | public function toArray(): array { 97 | return $this->__serialize(); 98 | } 99 | 100 | /** 101 | * Return the stringified attribute 102 | * 103 | * @return string 104 | */ 105 | public function toString(): string { 106 | return $this->__toString(); 107 | } 108 | } -------------------------------------------------------------------------------- /src/Decoder/AttachmentDecoder.php: -------------------------------------------------------------------------------- 1 | decodeHeaderArray($value); 27 | } 28 | $original_value = $value; 29 | $decoder = $this->options['header']; 30 | 31 | if ($value !== null) { 32 | if ($decoder === 'utf-8') { 33 | $decoded_values = $this->mimeHeaderDecode($value); 34 | $tempValue = ""; 35 | foreach ($decoded_values as $decoded_value) { 36 | $tempValue .= $this->convertEncoding($decoded_value->text, $decoded_value->charset); 37 | } 38 | if ($tempValue) { 39 | $value = $tempValue; 40 | } else if (extension_loaded('imap')) { 41 | $value = \imap_utf8($value); 42 | } else if (function_exists('iconv_mime_decode')) { 43 | $value = iconv_mime_decode($value, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, "UTF-8"); 44 | } else { 45 | $value = mb_decode_mimeheader($value); 46 | } 47 | } elseif ($decoder === 'iconv') { 48 | $value = iconv_mime_decode($value, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, "UTF-8"); 49 | } else if (self::isUTF8($value)) { 50 | $value = mb_decode_mimeheader($value); 51 | } 52 | 53 | if (self::notDecoded($original_value, $value)) { 54 | $value = $this->convertEncoding($original_value, $this->getEncoding($original_value)); 55 | } 56 | } 57 | 58 | return $value; 59 | } 60 | 61 | /** 62 | * Get the encoding of a given abject 63 | * @param object|string $structure 64 | * 65 | * @return string 66 | */ 67 | public function getEncoding(object|string $structure): string { 68 | if (property_exists($structure, 'parameters')) { 69 | foreach ($structure->parameters as $parameter) { 70 | if (strtolower($parameter->attribute) == "charset") { 71 | return EncodingAliases::get($parameter->value == "default" ? EncodingAliases::detectEncoding($parameter->value) : $parameter->value, $this->fallback_encoding); 72 | } 73 | } 74 | } elseif (property_exists($structure, 'charset')) { 75 | return EncodingAliases::get($structure->charset == "default" ? EncodingAliases::detectEncoding($structure->charset) : $structure->charset, $this->fallback_encoding); 76 | } elseif (is_string($structure) === true) { 77 | $result = mb_detect_encoding($structure); 78 | return $result === false ? $this->fallback_encoding : $result; 79 | } 80 | 81 | return $this->fallback_encoding; 82 | } 83 | 84 | 85 | /** 86 | * Decode a given array 87 | * @param array $values 88 | * 89 | * @return array 90 | */ 91 | private function decodeHeaderArray(array $values): array { 92 | foreach ($values as $key => $value) { 93 | $values[$key] = $this->decode($value); 94 | } 95 | return $values; 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /src/Events/Event.php: -------------------------------------------------------------------------------- 1 | message = $arguments[0]; 38 | $this->flag = $arguments[1]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Events/FolderDeletedEvent.php: -------------------------------------------------------------------------------- 1 | old_folder = $folders[0]; 38 | $this->new_folder = $folders[1]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Events/FolderNewEvent.php: -------------------------------------------------------------------------------- 1 | folder = $folders[0]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Events/MessageCopiedEvent.php: -------------------------------------------------------------------------------- 1 | old_message = $messages[0]; 38 | $this->new_message = $messages[1]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Events/MessageNewEvent.php: -------------------------------------------------------------------------------- 1 | message = $messages[0]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Events/MessageRestoredEvent.php: -------------------------------------------------------------------------------- 1 | getErrors() as $error) { 38 | $message .= "\t- $error\n"; 39 | } 40 | 41 | if(!$response->data()) { 42 | $message .= "\t- Empty response\n"; 43 | } 44 | 45 | if ($debug) { 46 | $message .= self::debug_message($response); 47 | } 48 | 49 | foreach($response->getStack() as $_response) { 50 | $exception = self::make($_response, $debug, $exception); 51 | } 52 | 53 | return new self($message."Error occurred", 0, $exception); 54 | } 55 | 56 | /** 57 | * Generate a debug message containing all commands send and responses received 58 | * @param Response $response 59 | * 60 | * @return string 61 | */ 62 | protected static function debug_message(Response $response): string { 63 | $commands = $response->getCommands(); 64 | $message = "Commands send:\n"; 65 | if ($commands) { 66 | foreach($commands as $command) { 67 | $message .= "\t".str_replace("\r\n", "\\r\\n", $command)."\n"; 68 | } 69 | }else{ 70 | $message .= "\tNo command send!\n"; 71 | } 72 | 73 | $responses = $response->getResponse(); 74 | $message .= "Responses received:\n"; 75 | if ($responses) { 76 | foreach($responses as $_response) { 77 | if (is_array($_response)) { 78 | foreach($_response as $value) { 79 | $message .= "\t".str_replace("\r\n", "\\r\\n", "$value")."\n"; 80 | } 81 | }else{ 82 | $message .= "\t".str_replace("\r\n", "\\r\\n", "$_response")."\n"; 83 | } 84 | } 85 | }else{ 86 | $message .= "\tNo responses received!\n"; 87 | } 88 | 89 | return $message; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/Exceptions/RuntimeException.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | class AttachmentCollection extends PaginatedCollection { 25 | 26 | } -------------------------------------------------------------------------------- /src/Support/FlagCollection.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | class FlagCollection extends PaginatedCollection { 24 | 25 | } -------------------------------------------------------------------------------- /src/Support/FolderCollection.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | class FolderCollection extends PaginatedCollection { 25 | 26 | } -------------------------------------------------------------------------------- /src/Support/Masks/AttachmentMask.php: -------------------------------------------------------------------------------- 1 | parent->content); 35 | } 36 | 37 | /** 38 | * Get a base64 image src string 39 | * 40 | * @return string|null 41 | */ 42 | public function getImageSrc(): ?string { 43 | return 'data:'.$this->parent->content_type.';base64,'.$this->getContentBase64Encoded(); 44 | } 45 | } -------------------------------------------------------------------------------- /src/Support/Masks/Mask.php: -------------------------------------------------------------------------------- 1 | parent = $parent; 45 | 46 | if(method_exists($this->parent, 'getAttributes')){ 47 | $this->attributes = array_merge($this->attributes, $this->parent->getAttributes()); 48 | } 49 | 50 | $this->boot(); 51 | } 52 | 53 | /** 54 | * Boot method made to be used by any custom mask 55 | */ 56 | protected function boot(): void {} 57 | 58 | /** 59 | * Call dynamic attribute setter and getter methods and inherit the parent calls 60 | * @param string $method 61 | * @param array $arguments 62 | * 63 | * @return mixed 64 | * @throws MethodNotFoundException 65 | */ 66 | public function __call(string $method, array $arguments) { 67 | if(strtolower(substr($method, 0, 3)) === 'get') { 68 | $name = Str::snake(substr($method, 3)); 69 | 70 | if(isset($this->attributes[$name])) { 71 | return $this->attributes[$name]; 72 | } 73 | 74 | }elseif (strtolower(substr($method, 0, 3)) === 'set') { 75 | $name = Str::snake(substr($method, 3)); 76 | 77 | if(isset($this->attributes[$name])) { 78 | $this->attributes[$name] = array_pop($arguments); 79 | 80 | return $this->attributes[$name]; 81 | } 82 | 83 | } 84 | 85 | if(method_exists($this->parent, $method) === true){ 86 | return call_user_func_array([$this->parent, $method], $arguments); 87 | } 88 | 89 | throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported'); 90 | } 91 | 92 | /** 93 | * Magic setter 94 | * @param $name 95 | * @param $value 96 | * 97 | * @return mixed 98 | */ 99 | public function __set($name, $value) { 100 | $this->attributes[$name] = $value; 101 | 102 | return $this->attributes[$name]; 103 | } 104 | 105 | /** 106 | * Magic getter 107 | * @param $name 108 | * 109 | * @return mixed|null 110 | */ 111 | public function __get($name) { 112 | if(isset($this->attributes[$name])) { 113 | return $this->attributes[$name]; 114 | } 115 | 116 | return null; 117 | } 118 | 119 | /** 120 | * Get the parent instance 121 | * 122 | * @return mixed 123 | */ 124 | public function getParent(): mixed { 125 | return $this->parent; 126 | } 127 | 128 | /** 129 | * Get all available attributes 130 | * 131 | * @return array 132 | */ 133 | public function getAttributes(): array { 134 | return $this->attributes; 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /src/Support/Masks/MessageMask.php: -------------------------------------------------------------------------------- 1 | parent->getBodies(); 36 | if (!isset($bodies['html'])) { 37 | return null; 38 | } 39 | 40 | if(is_object($bodies['html']) && property_exists($bodies['html'], 'content')) { 41 | return $bodies['html']->content; 42 | } 43 | return $bodies['html']; 44 | } 45 | 46 | /** 47 | * Get the Message html body filtered by an optional callback 48 | * @param callable|null $callback 49 | * 50 | * @return string|null 51 | */ 52 | public function getCustomHTMLBody(?callable $callback = null): ?string { 53 | $body = $this->getHtmlBody(); 54 | if($body === null) return null; 55 | 56 | if ($callback !== null) { 57 | $aAttachment = $this->parent->getAttachments(); 58 | $aAttachment->each(function($oAttachment) use(&$body, $callback) { 59 | /** @var Attachment $oAttachment */ 60 | if(is_callable($callback)) { 61 | $body = $callback($body, $oAttachment); 62 | }elseif(is_string($callback)) { 63 | call_user_func($callback, [$body, $oAttachment]); 64 | } 65 | }); 66 | } 67 | 68 | return $body; 69 | } 70 | 71 | /** 72 | * Get the Message html body with embedded base64 images 73 | * the resulting $body. 74 | * 75 | * @return string|null 76 | */ 77 | public function getHTMLBodyWithEmbeddedBase64Images(): ?string { 78 | return $this->getCustomHTMLBody(function($body, $oAttachment){ 79 | /** @var Attachment $oAttachment */ 80 | if ($oAttachment->id) { 81 | $body = str_replace('cid:'.$oAttachment->id, 'data:'.$oAttachment->getContentType().';base64, '.base64_encode($oAttachment->getContent()), $body); 82 | } 83 | 84 | return $body; 85 | }); 86 | } 87 | } -------------------------------------------------------------------------------- /src/Support/MessageCollection.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | class MessageCollection extends PaginatedCollection { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/Support/PaginatedCollection.php: -------------------------------------------------------------------------------- 1 | total ?: $this->count(); 46 | 47 | $results = !$prepaginated && $total ? $this->forPage($page, $per_page)->toArray() : $this->all(); 48 | 49 | return $this->paginator($results, $total, $per_page, $page, [ 50 | 'path' => Paginator::resolveCurrentPath(), 51 | 'pageName' => $page_name, 52 | ]); 53 | } 54 | 55 | /** 56 | * Create a new length-aware paginator instance. 57 | * @param array $items 58 | * @param int $total 59 | * @param int $per_page 60 | * @param int|null $current_page 61 | * @param array $options 62 | * 63 | * @return LengthAwarePaginator 64 | */ 65 | protected function paginator(array $items, int $total, int $per_page, ?int $current_page, array $options): LengthAwarePaginator { 66 | return new LengthAwarePaginator($items, $total, $per_page, $current_page, $options); 67 | } 68 | 69 | /** 70 | * Get and set the total amount 71 | * @param null $total 72 | * 73 | * @return int|null 74 | */ 75 | public function total($total = null): ?int { 76 | if($total === null) { 77 | return $this->total; 78 | } 79 | 80 | return $this->total = $total; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Traits/HasEvents.php: -------------------------------------------------------------------------------- 1 | events[$section])) { 41 | $this->events[$section][$event] = $class; 42 | } 43 | } 44 | 45 | /** 46 | * Set all events 47 | * @param array $events 48 | */ 49 | public function setEvents(array $events): void { 50 | $this->events = $events; 51 | } 52 | 53 | /** 54 | * Get a specific event callback 55 | * @param string $section 56 | * @param string $event 57 | * 58 | * @return Event|string 59 | * @throws EventNotFoundException 60 | */ 61 | public function getEvent(string $section, string $event): Event|string { 62 | if (isset($this->events[$section])) { 63 | return $this->events[$section][$event]; 64 | } 65 | throw new EventNotFoundException(); 66 | } 67 | 68 | /** 69 | * Get all events 70 | * 71 | * @return array 72 | */ 73 | public function getEvents(): array { 74 | return $this->events; 75 | } 76 | 77 | /** 78 | * Dispatch a specific event. 79 | * @throws EventNotFoundException 80 | */ 81 | public function dispatch(string $section, string $event, mixed ...$args): void { 82 | $event = $this->getEvent($section, $event); 83 | $event::dispatch(...$args); 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /tests/AddressTest.php: -------------------------------------------------------------------------------- 1 | "Username", 27 | "mailbox" => "info", 28 | "host" => "domain.tld", 29 | "mail" => "info@domain.tld", 30 | "full" => "Username ", 31 | ]; 32 | 33 | /** 34 | * Address test 35 | * 36 | * @return void 37 | */ 38 | public function testAddress(): void { 39 | $address = new Address((object)$this->data); 40 | 41 | self::assertSame("Username", $address->personal); 42 | self::assertSame("info", $address->mailbox); 43 | self::assertSame("domain.tld", $address->host); 44 | self::assertSame("info@domain.tld", $address->mail); 45 | self::assertSame("Username ", $address->full); 46 | } 47 | 48 | /** 49 | * Test Address to string conversion 50 | * 51 | * @return void 52 | */ 53 | public function testAddressToStringConversion(): void { 54 | $address = new Address((object)$this->data); 55 | 56 | self::assertSame("Username ", (string)$address); 57 | } 58 | 59 | /** 60 | * Test Address serialization 61 | * 62 | * @return void 63 | */ 64 | public function testAddressSerialization(): void { 65 | $address = new Address((object)$this->data); 66 | 67 | foreach($address as $key => $value) { 68 | self::assertSame($this->data[$key], $value); 69 | } 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /tests/AttachmentTest.php: -------------------------------------------------------------------------------- 1 | getFixture("attachment_encoded_filename.eml"); 17 | $this->attachment = $message->getAttachments()->first(); 18 | } 19 | /** 20 | * @dataProvider decodeNameDataProvider 21 | */ 22 | public function testDecodeName(string $input, string $output): void 23 | { 24 | $name = $this->attachment->decodeName($input); 25 | $this->assertEquals($output, $name); 26 | } 27 | 28 | public function decodeNameDataProvider(): array 29 | { 30 | return [ 31 | ['../../../../../../../../../../../var/www/shell.php', 'varwwwshell.php'], 32 | ['test..xml', 'test.xml'], 33 | [chr(0), ''], 34 | ['C:\\file.txt', 'Cfile.txt'], 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/AttributeTest.php: -------------------------------------------------------------------------------- 1 | toString()); 30 | self::assertSame("foo", $attribute->getName()); 31 | self::assertSame("foos", $attribute->setName("foos")->getName()); 32 | } 33 | 34 | /** 35 | * Date Attribute test 36 | * 37 | * @return void 38 | */ 39 | public function testDateAttribute(): void { 40 | $attribute = new Attribute("foo", "2022-12-26 08:07:14 GMT-0800"); 41 | 42 | self::assertInstanceOf(Carbon::class, $attribute->toDate()); 43 | self::assertSame("2022-12-26 08:07:14 GMT-0800", $attribute->toDate()->format("Y-m-d H:i:s T")); 44 | } 45 | 46 | /** 47 | * Array Attribute test 48 | * 49 | * @return void 50 | */ 51 | public function testArrayAttribute(): void { 52 | $attribute = new Attribute("foo", ["bar"]); 53 | 54 | self::assertSame("bar", $attribute->toString()); 55 | 56 | $attribute->add("bars"); 57 | self::assertSame(true, $attribute->has(1)); 58 | self::assertSame("bars", $attribute->get(1)); 59 | self::assertSame(true, $attribute->contains("bars")); 60 | self::assertSame("foo, bars", $attribute->set("foo", 0)->toString()); 61 | 62 | $attribute->remove(0); 63 | self::assertSame("bars", $attribute->toString()); 64 | 65 | self::assertSame("bars, foos", $attribute->merge(["foos", "bars"], true)->toString()); 66 | self::assertSame("bars, foos, foos, donk", $attribute->merge(["foos", "donk"], false)->toString()); 67 | 68 | self::assertSame(4, $attribute->count()); 69 | 70 | self::assertSame("donk", $attribute->last()); 71 | self::assertSame("bars", $attribute->first()); 72 | 73 | self::assertSame(["bars", "foos", "foos", "donk"], array_values($attribute->all())); 74 | } 75 | } -------------------------------------------------------------------------------- /tests/ClientManagerTest.php: -------------------------------------------------------------------------------- 1 | cm = new ClientManager(); 34 | } 35 | 36 | /** 37 | * Test if the config can be accessed 38 | * 39 | * @return void 40 | */ 41 | public function testConfigAccessorAccount(): void { 42 | $config = $this->cm->getConfig(); 43 | self::assertInstanceOf(Config::class, $config); 44 | self::assertSame("default", $config->get("default")); 45 | self::assertSame("d-M-Y", $config->get("date_format")); 46 | self::assertSame(IMAP::FT_PEEK, $config->get("options.fetch")); 47 | self::assertSame([], $config->get("options.open")); 48 | } 49 | 50 | /** 51 | * Test creating a client instance 52 | * 53 | * @throws MaskNotFoundException 54 | */ 55 | public function testMakeClient(): void { 56 | self::assertInstanceOf(Client::class, $this->cm->make([])); 57 | } 58 | 59 | /** 60 | * Test accessing accounts 61 | * 62 | * @throws MaskNotFoundException 63 | */ 64 | public function testAccountAccessor(): void { 65 | self::assertSame("default", $this->cm->getConfig()->getDefaultAccount()); 66 | self::assertNotEmpty($this->cm->account("default")); 67 | 68 | $this->cm->getConfig()->setDefaultAccount("foo"); 69 | self::assertSame("foo", $this->cm->getConfig()->getDefaultAccount()); 70 | $this->cm->getConfig()->setDefaultAccount("default"); 71 | } 72 | 73 | /** 74 | * Test setting a config 75 | * 76 | * @throws MaskNotFoundException 77 | */ 78 | public function testSetConfig(): void { 79 | $config = [ 80 | "default" => "foo", 81 | "options" => [ 82 | "fetch" => IMAP::ST_MSGN, 83 | "open" => "foo" 84 | ] 85 | ]; 86 | $cm = new ClientManager($config); 87 | 88 | self::assertSame("foo", $cm->getConfig()->getDefaultAccount()); 89 | self::assertInstanceOf(Client::class, $cm->account("foo")); 90 | self::assertSame(IMAP::ST_MSGN, $cm->getConfig()->get("options.fetch")); 91 | self::assertSame(false, is_array($cm->getConfig()->get("options.open"))); 92 | 93 | } 94 | } -------------------------------------------------------------------------------- /tests/ImapProtocolTest.php: -------------------------------------------------------------------------------- 1 | config = Config::make(); 32 | } 33 | 34 | 35 | /** 36 | * ImapProtocol test 37 | * 38 | * @return void 39 | */ 40 | public function testImapProtocol(): void { 41 | 42 | $protocol = new ImapProtocol($this->config, false); 43 | self::assertSame(false, $protocol->getCertValidation()); 44 | self::assertSame("", $protocol->getEncryption()); 45 | 46 | $protocol->setCertValidation(true); 47 | $protocol->setEncryption("ssl"); 48 | 49 | self::assertSame(true, $protocol->getCertValidation()); 50 | self::assertSame("ssl", $protocol->getEncryption()); 51 | 52 | $protocol->setSslOptions([ 53 | 'verify_peer' => true, 54 | 'cafile' => '/dummy/path/for/testing', 55 | 'peer_fingerprint' => ['md5' => 40], 56 | ]); 57 | 58 | self::assertSame([ 59 | 'verify_peer' => true, 60 | 'cafile' => '/dummy/path/for/testing', 61 | 'peer_fingerprint' => ['md5' => 40], 62 | ], $protocol->getSslOptions()); 63 | } 64 | } -------------------------------------------------------------------------------- /tests/StructureTest.php: -------------------------------------------------------------------------------- 1 | config = Config::make(); 34 | } 35 | 36 | /** 37 | * Test parsing email headers 38 | * 39 | * @throws InvalidMessageDateException 40 | * @throws MessageContentFetchingException 41 | */ 42 | public function testStructureParsing(): void { 43 | $email = file_get_contents(implode(DIRECTORY_SEPARATOR, [__DIR__, "messages", "1366671050@github.com.eml"])); 44 | if(!str_contains($email, "\r\n")){ 45 | $email = str_replace("\n", "\r\n", $email); 46 | } 47 | 48 | $raw_header = substr($email, 0, strpos($email, "\r\n\r\n")); 49 | $raw_body = substr($email, strlen($raw_header)+8); 50 | 51 | $header = new Header($raw_header, $this->config); 52 | $structure = new Structure($raw_body, $header); 53 | 54 | self::assertSame(2, count($structure->parts)); 55 | 56 | $textPart = $structure->parts[0]; 57 | 58 | self::assertSame("UTF-8", $textPart->charset); 59 | self::assertSame("text/plain", $textPart->content_type); 60 | self::assertSame(278, $textPart->bytes); 61 | 62 | $htmlPart = $structure->parts[1]; 63 | 64 | self::assertSame("UTF-8", $htmlPart->charset); 65 | self::assertSame("text/html", $htmlPart->content_type); 66 | self::assertSame(1478, $htmlPart->bytes); 67 | } 68 | } -------------------------------------------------------------------------------- /tests/fixtures/AttachmentEncodedFilenameTest.php: -------------------------------------------------------------------------------- 1 | getFixture("attachment_encoded_filename.eml"); 31 | 32 | self::assertEquals("", $message->subject); 33 | self::assertEquals("multipart/mixed", $message->content_type->last()); 34 | self::assertFalse($message->hasTextBody()); 35 | self::assertFalse($message->hasHTMLBody()); 36 | 37 | self::assertCount(1, $message->attachments()); 38 | 39 | $attachment = $message->attachments()->first(); 40 | self::assertInstanceOf(Attachment::class, $attachment); 41 | self::assertEquals("Prostřeno_2014_poslední volné termíny.xls", $attachment->filename); 42 | self::assertEquals("Prostřeno_2014_poslední volné termíny.xls", $attachment->name); 43 | self::assertEquals('xls', $attachment->getExtension()); 44 | self::assertEquals('text', $attachment->type); 45 | self::assertEquals("application/vnd.ms-excel", $attachment->content_type); 46 | self::assertEquals("a0ef7cfbc05b73dbcb298fe0bc224b41900cdaf60f9904e3fea5ba6c7670013c", hash("sha256", $attachment->content)); 47 | self::assertEquals(146, $attachment->size); 48 | self::assertEquals(0, $attachment->part_number); 49 | self::assertEquals("attachment", $attachment->disposition); 50 | self::assertNotEmpty($attachment->id); 51 | } 52 | } -------------------------------------------------------------------------------- /tests/fixtures/AttachmentNoDispositionTest.php: -------------------------------------------------------------------------------- 1 | getFixture("attachment_no_disposition.eml"); 31 | 32 | self::assertEquals("", $message->subject); 33 | self::assertEquals("multipart/mixed", $message->content_type->last()); 34 | self::assertFalse($message->hasTextBody()); 35 | self::assertFalse($message->hasHTMLBody()); 36 | 37 | self::assertCount(1, $message->attachments()); 38 | 39 | $attachment = $message->attachments()->first(); 40 | 41 | self::assertInstanceOf(Attachment::class, $attachment); 42 | self::assertEquals('26ed3dd2', $attachment->filename); 43 | self::assertEquals('26ed3dd2', $attachment->id); 44 | self::assertEquals("Prostřeno_2014_poslední volné termíny.xls", $attachment->name); 45 | self::assertEquals('text', $attachment->type); 46 | self::assertEquals('xls', $attachment->getExtension()); 47 | self::assertEquals("application/vnd.ms-excel", $attachment->content_type); 48 | self::assertEquals("a0ef7cfbc05b73dbcb298fe0bc224b41900cdaf60f9904e3fea5ba6c7670013c", hash("sha256", $attachment->content)); 49 | self::assertEquals(146, $attachment->size); 50 | self::assertEquals(0, $attachment->part_number); 51 | self::assertNull($attachment->disposition); 52 | self::assertNotEmpty($attachment->id); 53 | self::assertEmpty($attachment->content_id); 54 | } 55 | } -------------------------------------------------------------------------------- /tests/fixtures/BccTest.php: -------------------------------------------------------------------------------- 1 | getFixture("bcc.eml"); 29 | 30 | self::assertEquals("test", $message->subject); 31 | self::assertSame([ 32 | 'personal' => '', 33 | 'mailbox' => 'return-path', 34 | 'host' => 'here.com', 35 | 'mail' => 'return-path@here.com', 36 | 'full' => 'return-path@here.com', 37 | ], $message->return_path->first()->toArray()); 38 | self::assertEquals("1.0", $message->mime_version); 39 | self::assertEquals("text/plain", $message->content_type); 40 | self::assertEquals("Hi!", $message->getTextBody()); 41 | self::assertFalse($message->hasHTMLBody()); 42 | self::assertEquals("2017-09-27 10:48:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 43 | self::assertEquals("from@there.com", $message->from); 44 | self::assertEquals("to@here.com", $message->to); 45 | self::assertEquals("A_€@{è_Z ", $message->bcc); 46 | self::assertEquals("sender@here.com", $message->sender); 47 | self::assertEquals("reply-to@here.com", $message->reply_to); 48 | } 49 | } -------------------------------------------------------------------------------- /tests/fixtures/BooleanDecodedContentTest.php: -------------------------------------------------------------------------------- 1 | getFixture("boolean_decoded_content.eml"); 31 | 32 | self::assertEquals("Nuu", $message->subject); 33 | self::assertEquals("Here is the problem mail\r\n \r\nBody text", $message->getTextBody()); 34 | self::assertEquals("Here is the problem mail\r\n \r\nBody text", $message->getHTMLBody()); 35 | 36 | self::assertEquals("2017-09-13 11:05:45", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 37 | self::assertEquals("from@there.com", $message->from); 38 | self::assertEquals("to@here.com", $message->to); 39 | 40 | $attachments = $message->getAttachments(); 41 | self::assertCount(1, $attachments); 42 | 43 | $attachment = $attachments[0]; 44 | self::assertInstanceOf(Attachment::class, $attachment); 45 | self::assertEquals("Example Domain.pdf", $attachment->name); 46 | self::assertEquals('text', $attachment->type); 47 | self::assertEquals('pdf', $attachment->getExtension()); 48 | self::assertEquals("application/pdf", $attachment->content_type); 49 | self::assertEquals("1c449aaab4f509012fa5eaa180fd017eb7724ccacabdffc1c6066d3756dcde5c", hash("sha256", $attachment->content)); 50 | self::assertEquals(53, $attachment->size); 51 | self::assertEquals(2, $attachment->part_number); 52 | self::assertEquals("attachment", $attachment->disposition); 53 | self::assertNotEmpty($attachment->id); 54 | } 55 | } -------------------------------------------------------------------------------- /tests/fixtures/EmailAddressTest.php: -------------------------------------------------------------------------------- 1 | getFixture("email_address.eml"); 49 | 50 | self::assertEquals("", $message->subject); 51 | self::assertEquals("123@example.com", $message->message_id); 52 | self::assertEquals("Hi\r\nHow are you?", $message->getTextBody()); 53 | self::assertFalse($message->hasHTMLBody()); 54 | self::assertFalse($message->date->first()); 55 | self::assertEquals("no_host", (string)$message->from); 56 | self::assertEquals("", $message->to); 57 | self::assertEquals("This one: is \"right\" , No-address", (string)$message->cc); 58 | } 59 | } -------------------------------------------------------------------------------- /tests/fixtures/EmbeddedEmailTest.php: -------------------------------------------------------------------------------- 1 | getFixture("embedded_email.eml"); 31 | 32 | self::assertEquals("embedded message", $message->subject); 33 | self::assertEquals([ 34 | 'from webmail.my-office.cz (localhost [127.0.0.1]) by keira.cofis.cz ; Fri, 29 Jan 2016 14:25:40 +0100', 35 | ], $message->received->toArray()); 36 | self::assertEquals("7e5798da5747415e5b82fdce042ab2a6@cerstor.cz", $message->message_id); 37 | self::assertEquals("demo@cerstor.cz", $message->return_path); 38 | self::assertEquals("1.0", $message->mime_version); 39 | self::assertEquals("Roundcube Webmail/1.0.0", $message->user_agent); 40 | self::assertEquals("email that contains embedded message", $message->getTextBody()); 41 | self::assertFalse($message->hasHTMLBody()); 42 | 43 | self::assertEquals("2016-01-29 13:25:40", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 44 | self::assertEquals("demo@cerstor.cz", $message->from); 45 | self::assertEquals("demo@cerstor.cz", $message->x_sender); 46 | self::assertEquals("demo@cerstor.cz", $message->to); 47 | 48 | $attachments = $message->getAttachments(); 49 | self::assertCount(1, $attachments); 50 | 51 | $attachment = $attachments[0]; 52 | self::assertInstanceOf(Attachment::class, $attachment); 53 | self::assertEquals("demo.eml", $attachment->name); 54 | self::assertEquals('text', $attachment->type); 55 | self::assertEquals('eml', $attachment->getExtension()); 56 | self::assertEquals("message/rfc822", $attachment->content_type); 57 | self::assertEquals("a1f965f10a9872e902a82dde039a237e863f522d238a1cb1968fe3396dbcac65", hash("sha256", $attachment->content)); 58 | self::assertEquals(893, $attachment->size); 59 | self::assertEquals(1, $attachment->part_number); 60 | self::assertEquals("attachment", $attachment->disposition); 61 | self::assertNotEmpty($attachment->id); 62 | } 63 | } -------------------------------------------------------------------------------- /tests/fixtures/EmbeddedEmailWithoutContentDispositionEmbeddedTest.php: -------------------------------------------------------------------------------- 1 | getFixture("embedded_email_without_content_disposition-embedded.eml"); 31 | 32 | self::assertEquals("embedded_message_subject", $message->subject); 33 | self::assertEquals([ 34 | 'from webmail.my-office.cz (localhost [127.0.0.1]) by keira.cofis.cz ; Fri, 29 Jan 2016 14:25:40 +0100', 35 | ], $message->received->toArray()); 36 | self::assertEquals("AC39946EBF5C034B87BABD5343E96979012671D40E38@VM002.cerk.cc", $message->message_id); 37 | self::assertEquals("pl-PL, nl-NL", $message->accept_language); 38 | self::assertEquals("pl-PL", $message->content_language); 39 | self::assertEquals("1.0", $message->mime_version); 40 | self::assertEquals("some txt", $message->getTextBody()); 41 | self::assertEquals("\r\n

some txt

\r\n", $message->getHTMLBody()); 42 | 43 | self::assertEquals("2019-04-05 10:10:49", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 44 | self::assertEquals("demo@cerstor.cz", $message->from); 45 | self::assertEquals("demo@cerstor.cz", $message->to); 46 | 47 | $attachments = $message->getAttachments(); 48 | self::assertCount(2, $attachments); 49 | 50 | $attachment = $attachments[0]; 51 | self::assertInstanceOf(Attachment::class, $attachment); 52 | self::assertEquals("file1.xlsx", $attachment->name); 53 | self::assertEquals('text', $attachment->type); 54 | self::assertEquals('xlsx', $attachment->getExtension()); 55 | self::assertEquals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $attachment->content_type); 56 | self::assertEquals("87737d24c106b96e177f9564af6712e2c6d3e932c0632bfbab69c88b0bb934dc", hash("sha256", $attachment->content)); 57 | self::assertEquals(40, $attachment->size); 58 | self::assertEquals(2, $attachment->part_number); 59 | self::assertEquals("attachment", $attachment->disposition); 60 | self::assertNotEmpty($attachment->id); 61 | 62 | $attachment = $attachments[1]; 63 | self::assertInstanceOf(Attachment::class, $attachment); 64 | self::assertEquals("file2.xlsx", $attachment->name); 65 | self::assertEquals('xlsx', $attachment->getExtension()); 66 | self::assertEquals('text', $attachment->type); 67 | self::assertEquals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $attachment->content_type); 68 | self::assertEquals("87737d24c106b96e177f9564af6712e2c6d3e932c0632bfbab69c88b0bb934dc", hash("sha256", $attachment->content)); 69 | self::assertEquals(40, $attachment->size); 70 | self::assertEquals(3, $attachment->part_number); 71 | self::assertEquals("attachment", $attachment->disposition); 72 | self::assertNotEmpty($attachment->id); 73 | } 74 | } -------------------------------------------------------------------------------- /tests/fixtures/FixtureTestCase.php: -------------------------------------------------------------------------------- 1 | [ 54 | "debug" => $_ENV["LIVE_MAILBOX_DEBUG"] ?? false, 55 | ], 56 | 'accounts' => [ 57 | 'default' => [ 58 | 'host' => getenv("LIVE_MAILBOX_HOST"), 59 | 'port' => getenv("LIVE_MAILBOX_PORT"), 60 | 'encryption' => getenv("LIVE_MAILBOX_ENCRYPTION"), 61 | 'validate_cert' => getenv("LIVE_MAILBOX_VALIDATE_CERT"), 62 | 'username' => getenv("LIVE_MAILBOX_USERNAME"), 63 | 'password' => getenv("LIVE_MAILBOX_PASSWORD"), 64 | 'protocol' => 'imap', //might also use imap, [pop3 or nntp (untested)] 65 | ], 66 | ], 67 | ]); 68 | return self::$manager; 69 | } 70 | 71 | /** 72 | * Get a fixture message 73 | * @param string $template 74 | * 75 | * @return Message 76 | * @throws ReflectionException 77 | * @throws AuthFailedException 78 | * @throws ConnectionFailedException 79 | * @throws ImapBadRequestException 80 | * @throws ImapServerErrorException 81 | * @throws InvalidMessageDateException 82 | * @throws MaskNotFoundException 83 | * @throws MessageContentFetchingException 84 | * @throws ResponseException 85 | * @throws RuntimeException 86 | */ 87 | final public function getFixture(string $template, ?Config $config = null) : Message { 88 | $filename = implode(DIRECTORY_SEPARATOR, [__DIR__, "..", "messages", $template]); 89 | $message = Message::fromFile($filename, $config); 90 | self::assertInstanceOf(Message::class, $message); 91 | 92 | return $message; 93 | } 94 | } -------------------------------------------------------------------------------- /tests/fixtures/FourNestedEmailsTest.php: -------------------------------------------------------------------------------- 1 | getFixture("four_nested_emails.eml"); 31 | 32 | self::assertEquals("3-third-subject", $message->subject); 33 | self::assertEquals("3-third-content", $message->getTextBody()); 34 | self::assertFalse($message->hasHTMLBody()); 35 | self::assertFalse($message->date->first()); 36 | self::assertEquals("test@example.com", $message->from->first()->mail); 37 | self::assertEquals("test@example.com", $message->to->first()->mail); 38 | 39 | $attachments = $message->getAttachments(); 40 | self::assertCount(1, $attachments); 41 | 42 | $attachment = $attachments[0]; 43 | self::assertInstanceOf(Attachment::class, $attachment); 44 | self::assertEquals("2-second-email.eml", $attachment->name); 45 | self::assertEquals('text', $attachment->type); 46 | self::assertEquals('eml', $attachment->getExtension()); 47 | self::assertEquals("message/rfc822", $attachment->content_type); 48 | self::assertEquals("85012e6a26d064a0288ee62618b3192687385adb4a4e27e48a28f738a325ca46", hash("sha256", $attachment->content)); 49 | self::assertEquals(1376, $attachment->size); 50 | self::assertEquals(2, $attachment->part_number); 51 | self::assertEquals("attachment", $attachment->disposition); 52 | self::assertNotEmpty($attachment->id); 53 | 54 | } 55 | } -------------------------------------------------------------------------------- /tests/fixtures/GbkCharsetTest.php: -------------------------------------------------------------------------------- 1 | getFixture("gbk_charset.eml"); 29 | 30 | self::assertEquals("Nuu", $message->subject); 31 | self::assertEquals("Hi", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertEquals("2017-09-13 11:05:45", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from->first()->mail); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/fixtures/HtmlOnlyTest.php: -------------------------------------------------------------------------------- 1 | getFixture("html_only.eml"); 29 | 30 | self::assertEquals("Nuu", $message->subject); 31 | self::assertEquals("Hi", $message->getHTMLBody()); 32 | self::assertFalse($message->hasTextBody()); 33 | self::assertEquals("2017-09-13 11:05:45", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from->first()->mail); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/fixtures/ImapMimeHeaderDecodeReturnsFalseTest.php: -------------------------------------------------------------------------------- 1 | getFixture("imap_mime_header_decode_returns_false.eml"); 29 | 30 | self::assertEquals("=?UTF-8?B?nnDusSNdG92w6Fuw61fMjAxOF8wMy0xMzMyNTMzMTkzLnBkZg==?=", $message->subject->first()); 31 | self::assertEquals("Hi", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertEquals("2017-09-13 11:05:45", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from->first()->mail); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/fixtures/InlineAttachmentTest.php: -------------------------------------------------------------------------------- 1 | getFixture("inline_attachment.eml"); 32 | 33 | self::assertEquals("", $message->subject); 34 | self::assertFalse($message->hasTextBody()); 35 | self::assertEquals('', $message->getHTMLBody()); 36 | 37 | self::assertFalse($message->date->first()); 38 | self::assertFalse($message->from->first()); 39 | self::assertFalse($message->to->first()); 40 | 41 | 42 | $attachments = $message->attachments(); 43 | self::assertInstanceOf(AttachmentCollection::class, $attachments); 44 | self::assertCount(1, $attachments); 45 | 46 | $attachment = $attachments[0]; 47 | 48 | self::assertInstanceOf(Attachment::class, $attachment); 49 | self::assertEquals('d2913999', $attachment->name); 50 | self::assertEquals('d2913999', $attachment->filename); 51 | self::assertEquals('ii_15f0aad691bb745f', $attachment->id); 52 | self::assertEquals('text', $attachment->type); 53 | self::assertEquals('', $attachment->getExtension()); 54 | self::assertEquals("image/png", $attachment->content_type); 55 | self::assertEquals("6568c9e9c35a7fa06f236e89f704d8c9b47183a24f2c978dba6c92e2747e3a13", hash("sha256", $attachment->content)); 56 | self::assertEquals(1486, $attachment->size); 57 | self::assertEquals(1, $attachment->part_number); 58 | self::assertEquals("inline", $attachment->disposition); 59 | self::assertEquals("", $attachment->content_id); 60 | self::assertNotEmpty($attachment->id); 61 | } 62 | } -------------------------------------------------------------------------------- /tests/fixtures/KsC56011987HeadersTest.php: -------------------------------------------------------------------------------- 1 | getFixture("ks_c_5601-1987_headers.eml"); 29 | 30 | self::assertEquals("RE: 회원님께 Ersi님이 메시지를 보냈습니다.", $message->subject); 31 | self::assertEquals("=?ks_c_5601-1987?B?yLi/+LTUsrIgRXJzabTUwMwguN69w8H2uKYgurizwr3AtM+02S4=?=", $message->thread_topic); 32 | self::assertEquals("1.0", $message->mime_version); 33 | self::assertEquals("Content", $message->getTextBody()); 34 | self::assertFalse($message->hasHTMLBody()); 35 | self::assertEquals("2017-09-27 10:48:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 36 | self::assertEquals("to@here.com", $message->to->first()->mail); 37 | 38 | 39 | $from = $message->from->first(); 40 | self::assertEquals("김 현진", $from->personal); 41 | self::assertEquals("from", $from->mailbox); 42 | self::assertEquals("there.com", $from->host); 43 | self::assertEquals("from@there.com", $from->mail); 44 | self::assertEquals("김 현진 ", $from->full); 45 | } 46 | } -------------------------------------------------------------------------------- /tests/fixtures/MailThatIsAttachmentTest.php: -------------------------------------------------------------------------------- 1 | getFixture("mail_that_is_attachment.eml"); 31 | 32 | self::assertEquals("Report domain: yyy.cz Submitter: google.com Report-ID: 2244696771454641389", $message->subject); 33 | self::assertEquals("2244696771454641389@google.com", $message->message_id); 34 | self::assertEquals("1.0", $message->mime_version); 35 | self::assertFalse($message->hasTextBody()); 36 | self::assertFalse($message->hasHTMLBody()); 37 | 38 | self::assertEquals("2015-02-15 10:21:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 39 | self::assertEquals("xxx@yyy.cz", $message->to->first()->mail); 40 | self::assertEquals("xxx@yyy.cz", $message->sender->first()->mail); 41 | 42 | $from = $message->from->first(); 43 | self::assertEquals("noreply-dmarc-support via xxx", $from->personal); 44 | self::assertEquals("xxx", $from->mailbox); 45 | self::assertEquals("yyy.cz", $from->host); 46 | self::assertEquals("xxx@yyy.cz", $from->mail); 47 | self::assertEquals("noreply-dmarc-support via xxx ", $from->full); 48 | 49 | self::assertCount(1, $message->attachments()); 50 | 51 | $attachment = $message->attachments()->first(); 52 | self::assertInstanceOf(Attachment::class, $attachment); 53 | self::assertEquals("google.com!yyy.cz!1423872000!1423958399.zip", $attachment->name); 54 | self::assertEquals('zip', $attachment->getExtension()); 55 | self::assertEquals('text', $attachment->type); 56 | self::assertEquals("application/zip", $attachment->content_type); 57 | self::assertEquals("c0d4f47b6fde124cea7460c3e509440d1a062705f550b0502b8ba0cbf621c97a", hash("sha256", $attachment->content)); 58 | self::assertEquals(1062, $attachment->size); 59 | self::assertEquals(0, $attachment->part_number); 60 | self::assertEquals("attachment", $attachment->disposition); 61 | self::assertNotEmpty($attachment->id); 62 | } 63 | } -------------------------------------------------------------------------------- /tests/fixtures/MissingDateTest.php: -------------------------------------------------------------------------------- 1 | getFixture("missing_date.eml"); 29 | 30 | self::assertEquals("Nuu", $message->getSubject()); 31 | self::assertEquals("Hi", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertFalse($message->date->first()); 34 | self::assertEquals("from@here.com", $message->from->first()->mail); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/fixtures/MissingFromTest.php: -------------------------------------------------------------------------------- 1 | getFixture("missing_from.eml"); 29 | 30 | self::assertEquals("Nuu", $message->getSubject()); 31 | self::assertEquals("Hi", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertEquals("2017-09-13 11:05:45", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertFalse($message->from->first()); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/fixtures/MixedFilenameTest.php: -------------------------------------------------------------------------------- 1 | getFixture("mixed_filename.eml"); 31 | 32 | self::assertEquals("Свежий прайс-лист", $message->subject); 33 | self::assertFalse($message->hasTextBody()); 34 | self::assertFalse($message->hasHTMLBody()); 35 | 36 | self::assertEquals("2018-02-02 19:23:06", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 37 | 38 | $from = $message->from->first(); 39 | self::assertEquals("Прайсы || ПартКом", $from->personal); 40 | self::assertEquals("support", $from->mailbox); 41 | self::assertEquals("part-kom.ru", $from->host); 42 | self::assertEquals("support@part-kom.ru", $from->mail); 43 | self::assertEquals("Прайсы || ПартКом ", $from->full); 44 | 45 | self::assertEquals("foo@bar.com", $message->to->first()); 46 | 47 | self::assertCount(1, $message->attachments()); 48 | 49 | $attachment = $message->attachments()->first(); 50 | self::assertInstanceOf(Attachment::class, $attachment); 51 | self::assertEquals("Price4VladDaKar.xlsx", $attachment->name); 52 | self::assertEquals('xlsx', $attachment->getExtension()); 53 | self::assertEquals('text', $attachment->type); 54 | self::assertEquals("application/octet-stream", $attachment->content_type); 55 | self::assertEquals("b832983842b0ad65db69e4c7096444c540a2393e2d43f70c2c9b8b9fceeedbb1", hash('sha256', $attachment->content)); 56 | self::assertEquals(94, $attachment->size); 57 | self::assertEquals(2, $attachment->part_number); 58 | self::assertEquals("attachment", $attachment->disposition); 59 | self::assertNotEmpty($attachment->id); 60 | } 61 | } -------------------------------------------------------------------------------- /tests/fixtures/MultipleNestedAttachmentsTest.php: -------------------------------------------------------------------------------- 1 | getFixture("multiple_nested_attachments.eml"); 32 | 33 | self::assertEquals("", $message->subject); 34 | self::assertEquals("------------------------------------------------------------------------", $message->getTextBody()); 35 | self::assertEquals("\r\n \r\n\r\n \r\n \r\n \r\n


\r\n

\r\n
\r\n \r\n \r\n  \"\"\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n

\r\n

\r\n
\r\n
\r\n \r\n", $message->getHTMLBody()); 36 | 37 | self::assertEquals("2018-01-15 09:54:09", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 38 | self::assertFalse($message->from->first()); 39 | self::assertFalse($message->to->first()); 40 | 41 | $attachments = $message->attachments(); 42 | self::assertInstanceOf(AttachmentCollection::class, $attachments); 43 | self::assertCount(2, $attachments); 44 | 45 | $attachment = $attachments[0]; 46 | self::assertInstanceOf(Attachment::class, $attachment); 47 | self::assertEquals("mleokdgdlgkkecep.png", $attachment->name); 48 | self::assertEquals('png', $attachment->getExtension()); 49 | self::assertEquals('text', $attachment->type); 50 | self::assertEquals("image/png", $attachment->content_type); 51 | self::assertEquals("e0e99b0bd6d5ea3ced99add53cc98b6f8eea6eae8ddd773fd06f3489289385fb", hash("sha256", $attachment->content)); 52 | self::assertEquals(114, $attachment->size); 53 | self::assertEquals(3, $attachment->part_number); 54 | self::assertEquals("inline", $attachment->disposition); 55 | self::assertNotEmpty($attachment->id); 56 | 57 | $attachment = $attachments[1]; 58 | self::assertInstanceOf(Attachment::class, $attachment); 59 | self::assertEquals("FF4D00-1.png", $attachment->name); 60 | self::assertEquals('png', $attachment->getExtension()); 61 | self::assertEquals('text', $attachment->type); 62 | self::assertEquals("image/png", $attachment->content_type); 63 | self::assertEquals("e0e99b0bd6d5ea3ced99add53cc98b6f8eea6eae8ddd773fd06f3489289385fb", hash("sha256", $attachment->content)); 64 | self::assertEquals(114, $attachment->size); 65 | self::assertEquals(4, $attachment->part_number); 66 | self::assertEquals("attachment", $attachment->disposition); 67 | self::assertNotEmpty($attachment->id); 68 | } 69 | } -------------------------------------------------------------------------------- /tests/fixtures/NullContentCharsetTest.php: -------------------------------------------------------------------------------- 1 | getFixture("null_content_charset.eml"); 29 | 30 | self::assertEquals("test", $message->getSubject()); 31 | self::assertEquals("Hi!", $message->getTextBody()); 32 | self::assertEquals("1.0", $message->mime_version); 33 | self::assertFalse($message->hasHTMLBody()); 34 | 35 | self::assertEquals("2017-09-27 10:48:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 36 | self::assertEquals("from@there.com", $message->from->first()->mail); 37 | self::assertEquals("to@here.com", $message->to->first()->mail); 38 | } 39 | } -------------------------------------------------------------------------------- /tests/fixtures/PecTest.php: -------------------------------------------------------------------------------- 1 | getFixture("pec.eml"); 32 | 33 | self::assertEquals("Certified", $message->subject); 34 | self::assertEquals("Signed", $message->getTextBody()); 35 | self::assertEquals("Signed", $message->getHTMLBody()); 36 | 37 | self::assertEquals("2017-10-02 10:13:43", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 38 | self::assertEquals("test@example.com", $message->from->first()->mail); 39 | self::assertEquals("test@example.com", $message->to->first()->mail); 40 | 41 | $attachments = $message->attachments(); 42 | 43 | self::assertInstanceOf(AttachmentCollection::class, $attachments); 44 | self::assertCount(3, $attachments); 45 | 46 | $attachment = $attachments[0]; 47 | self::assertInstanceOf(Attachment::class, $attachment); 48 | self::assertEquals("data.xml", $attachment->name); 49 | self::assertEquals('xml', $attachment->getExtension()); 50 | self::assertEquals('text', $attachment->type); 51 | self::assertEquals("application/xml", $attachment->content_type); 52 | self::assertEquals("", $attachment->content); 53 | self::assertEquals(8, $attachment->size); 54 | self::assertEquals(3, $attachment->part_number); 55 | self::assertEquals("inline", $attachment->disposition); 56 | self::assertNotEmpty($attachment->id); 57 | 58 | $attachment = $attachments[1]; 59 | self::assertInstanceOf(Attachment::class, $attachment); 60 | self::assertEquals("postacert.eml", $attachment->name); 61 | self::assertEquals('eml', $attachment->getExtension()); 62 | self::assertEquals('text', $attachment->type); 63 | self::assertEquals("message/rfc822", $attachment->content_type); 64 | self::assertEquals("To: test@example.com\r\nFrom: test@example.com\r\nSubject: test-subject\r\nDate: Mon, 2 Oct 2017 12:13:50 +0200\r\nContent-Type: text/plain; charset=iso-8859-15; format=flowed\r\nContent-Transfer-Encoding: 7bit\r\n\r\ntest-content", $attachment->content); 65 | self::assertEquals(216, $attachment->size); 66 | self::assertEquals(4, $attachment->part_number); 67 | self::assertEquals("inline", $attachment->disposition); 68 | self::assertNotEmpty($attachment->id); 69 | 70 | $attachment = $attachments[2]; 71 | self::assertInstanceOf(Attachment::class, $attachment); 72 | self::assertEquals("smime.p7s", $attachment->name); 73 | self::assertEquals('p7s', $attachment->getExtension()); 74 | self::assertEquals('text', $attachment->type); 75 | self::assertEquals("application/x-pkcs7-signature", $attachment->content_type); 76 | self::assertEquals("1", $attachment->content); 77 | self::assertEquals(4, $attachment->size); 78 | self::assertEquals(5, $attachment->part_number); 79 | self::assertEquals("attachment", $attachment->disposition); 80 | self::assertNotEmpty($attachment->id); 81 | } 82 | } -------------------------------------------------------------------------------- /tests/fixtures/PlainOnlyTest.php: -------------------------------------------------------------------------------- 1 | getFixture("plain_only.eml"); 29 | 30 | self::assertEquals("Nuu", $message->getSubject()); 31 | self::assertEquals("Hi", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertEquals("2017-09-13 11:05:45", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from->first()->mail); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/fixtures/PlainTextAttachmentTest.php: -------------------------------------------------------------------------------- 1 | getFixture("plain_text_attachment.eml"); 31 | 32 | self::assertEquals("Plain text attachment", $message->subject); 33 | self::assertEquals("Test", $message->getTextBody()); 34 | self::assertFalse($message->hasHTMLBody()); 35 | 36 | self::assertEquals("2018-08-21 07:05:14", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 37 | self::assertEquals("from@there.com", $message->from->first()->mail); 38 | self::assertEquals("to@here.com", $message->to->first()->mail); 39 | 40 | self::assertCount(1, $message->attachments()); 41 | 42 | $attachment = $message->attachments()->first(); 43 | self::assertInstanceOf(Attachment::class, $attachment); 44 | self::assertEquals("a.txt", $attachment->name); 45 | self::assertEquals('txt', $attachment->getExtension()); 46 | self::assertEquals('text', $attachment->type); 47 | self::assertNull($attachment->content_type); 48 | self::assertEquals("Hi!", $attachment->content); 49 | self::assertEquals(4, $attachment->size); 50 | self::assertEquals(2, $attachment->part_number); 51 | self::assertEquals("attachment", $attachment->disposition); 52 | self::assertNotEmpty($attachment->id); 53 | } 54 | } -------------------------------------------------------------------------------- /tests/fixtures/ReferencesTest.php: -------------------------------------------------------------------------------- 1 | getFixture("references.eml"); 29 | 30 | self::assertEquals("", $message->subject); 31 | self::assertEquals("Hi\r\nHow are you?", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertFalse($message->date->first()); 34 | 35 | self::assertEquals("b9e87bd5e661a645ed6e3b832828fcc5@example.com", $message->in_reply_to); 36 | self::assertEquals("", $message->from->first()->personal); 37 | self::assertEquals("", $message->from->first()->host); 38 | self::assertEquals("no_host", $message->from->first()->mail); 39 | self::assertFalse($message->to->first()); 40 | 41 | self::assertEquals([ 42 | "231d9ac57aec7d8c1a0eacfeab8af6f3@example.com", 43 | "08F04024-A5B3-4FDE-BF2C-6710DE97D8D9@example.com" 44 | ], $message->getReferences()->all()); 45 | 46 | self::assertEquals([ 47 | 'This one: is "right" ', 48 | 'No-address' 49 | ], $message->cc->map(function($address){ 50 | /** @var \Webklex\PHPIMAP\Address $address */ 51 | return $address->full; 52 | })); 53 | } 54 | } -------------------------------------------------------------------------------- /tests/fixtures/SimpleMultipartTest.php: -------------------------------------------------------------------------------- 1 | getFixture("simple_multipart.eml"); 29 | 30 | self::assertEquals("test", $message->getSubject()); 31 | self::assertEquals("MyPlain", $message->getTextBody()); 32 | self::assertEquals("MyHtml", $message->getHTMLBody()); 33 | self::assertEquals("2017-09-27 10:48:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from->first()->mail); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/fixtures/StructuredWithAttachmentTest.php: -------------------------------------------------------------------------------- 1 | getFixture("structured_with_attachment.eml"); 32 | 33 | self::assertEquals("Test", $message->getSubject()); 34 | self::assertEquals("Test", $message->getTextBody()); 35 | self::assertFalse($message->hasHTMLBody()); 36 | 37 | self::assertEquals("2017-09-29 08:55:23", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 38 | self::assertEquals("from@there.com", $message->from->first()->mail); 39 | self::assertEquals("to@here.com", $message->to->first()->mail); 40 | 41 | self::assertCount(1, $message->attachments()); 42 | 43 | $attachment = $message->attachments()->first(); 44 | self::assertInstanceOf(Attachment::class, $attachment); 45 | self::assertEquals("MyFile.txt", $attachment->name); 46 | self::assertEquals('txt', $attachment->getExtension()); 47 | self::assertEquals('text', $attachment->type); 48 | self::assertEquals("text/plain", $attachment->content_type); 49 | self::assertEquals("MyFileContent", $attachment->content); 50 | self::assertEquals(20, $attachment->size); 51 | self::assertEquals(2, $attachment->part_number); 52 | self::assertEquals("attachment", $attachment->disposition); 53 | self::assertNotEmpty($attachment->id); 54 | } 55 | } -------------------------------------------------------------------------------- /tests/fixtures/UndefinedCharsetHeaderTest.php: -------------------------------------------------------------------------------- 1 | getFixture("undefined_charset_header.eml"); 31 | 32 | self::assertEquals("", $message->get("x-real-to")); 33 | self::assertEquals("1.0", $message->get("mime-version")); 34 | self::assertEquals("Mon, 27 Feb 2017 13:21:44 +0930", $message->get("Resent-Date")); 35 | self::assertEquals("", $message->get("Resent-From")); 36 | self::assertEquals("BlaBla", $message->get("X-Stored-In")); 37 | self::assertSame([ 38 | 'personal' => '', 39 | 'mailbox' => 'info', 40 | 'host' => 'bla.bla', 41 | 'mail' => 'info@bla.bla', 42 | 'full' => 'info@bla.bla', 43 | ], $message->get("Return-Path")->first()->toArray()); 44 | self::assertEquals([ 45 | 'from by bla.bla (CommuniGate Pro RULE 6.1.13) with RULE id 14057804; Mon, 27 Feb 2017 13:21:44 +0930', 46 | ], $message->get("Received")->all()); 47 | self::assertEquals(")", $message->getHTMLBody()); 48 | self::assertFalse($message->hasTextBody()); 49 | self::assertEquals("2017-02-27 03:51:29", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 50 | 51 | $from = $message->from->first(); 52 | self::assertInstanceOf(Address::class, $from); 53 | 54 | self::assertEquals("myGov", $from->personal); 55 | self::assertEquals("info", $from->mailbox); 56 | self::assertEquals("bla.bla", $from->host); 57 | self::assertEquals("info@bla.bla", $from->mail); 58 | self::assertEquals("myGov ", $from->full); 59 | 60 | self::assertEquals("sales@bla.bla", $message->to->first()->mail); 61 | self::assertEquals("Submit your tax refund | Australian Taxation Office.", $message->subject); 62 | self::assertEquals("201702270351.BGF77614@bla.bla", $message->message_id); 63 | } 64 | } -------------------------------------------------------------------------------- /tests/fixtures/UndisclosedRecipientsMinusTest.php: -------------------------------------------------------------------------------- 1 | getFixture("undisclosed_recipients_minus.eml"); 29 | 30 | self::assertEquals("test", $message->subject); 31 | self::assertEquals("Hi!", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertEquals("2017-09-27 10:48:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from); 35 | self::assertEquals([ 36 | "undisclosed-recipients", 37 | "" 38 | ], $message->to->map(function ($item) { 39 | return $item->mailbox; 40 | })); 41 | } 42 | } -------------------------------------------------------------------------------- /tests/fixtures/UndisclosedRecipientsSpaceTest.php: -------------------------------------------------------------------------------- 1 | getFixture("undisclosed_recipients_space.eml"); 29 | 30 | self::assertEquals("test", $message->subject); 31 | self::assertEquals("Hi!", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertEquals("2017-09-27 10:48:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from); 35 | self::assertEquals([ 36 | "Undisclosed recipients", 37 | "" 38 | ], $message->to->map(function ($item) { 39 | return $item->mailbox; 40 | })); 41 | } 42 | } -------------------------------------------------------------------------------- /tests/fixtures/UndisclosedRecipientsTest.php: -------------------------------------------------------------------------------- 1 | getFixture("undisclosed_recipients.eml"); 29 | 30 | self::assertEquals("test", $message->subject); 31 | self::assertEquals("Hi!", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertEquals("2017-09-27 10:48:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from); 35 | self::assertEquals([ 36 | "Undisclosed Recipients", 37 | "" 38 | ], $message->to->map(function ($item) { 39 | return $item->mailbox; 40 | })); 41 | } 42 | } -------------------------------------------------------------------------------- /tests/fixtures/UnknownEncodingTest.php: -------------------------------------------------------------------------------- 1 | getFixture("unknown_encoding.eml"); 29 | 30 | self::assertEquals("test", $message->getSubject()); 31 | self::assertEquals("MyPlain", $message->getTextBody()); 32 | self::assertEquals("MyHtml", $message->getHTMLBody()); 33 | self::assertEquals("2017-09-27 10:48:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from->first()->mail); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/fixtures/WithoutCharsetPlainOnlyTest.php: -------------------------------------------------------------------------------- 1 | getFixture("without_charset_plain_only.eml"); 29 | 30 | self::assertEquals("Nuu", $message->getSubject()); 31 | self::assertEquals("Hi", $message->getTextBody()); 32 | self::assertFalse($message->hasHTMLBody()); 33 | self::assertEquals("2017-09-13 11:05:45", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from->first()->mail); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/fixtures/WithoutCharsetSimpleMultipartTest.php: -------------------------------------------------------------------------------- 1 | getFixture("without_charset_simple_multipart.eml"); 29 | 30 | self::assertEquals("test", $message->getSubject()); 31 | self::assertEquals("MyPlain", $message->getTextBody()); 32 | self::assertEquals("MyHtml", $message->getHTMLBody()); 33 | self::assertEquals("2017-09-27 10:48:51", $message->date->first()->setTimezone('UTC')->format("Y-m-d H:i:s")); 34 | self::assertEquals("from@there.com", $message->from->first()->mail); 35 | self::assertEquals("to@here.com", $message->to->first()->mail); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/issues/Issue275Test.php: -------------------------------------------------------------------------------- 1 | subject); 25 | self::assertSame("Asdf testing123 this is a body", $message->getTextBody()); 26 | } 27 | 28 | public function testIssueEmail2() { 29 | $filename = implode(DIRECTORY_SEPARATOR, [__DIR__, "..", "messages", "issue-275-2.eml"]); 30 | $message = Message::fromFile($filename); 31 | 32 | $body = "Test\r\n\r\nMed venlig hilsen\r\nMartin Larsen\r\nFeline Holidays A/S\r\nTlf 78 77 04 12"; 33 | 34 | self::assertSame("Test 1017", (string)$message->subject); 35 | self::assertSame($body, $message->getTextBody()); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /tests/issues/Issue355Test.php: -------------------------------------------------------------------------------- 1 | get("subject"); 26 | 27 | $this->assertEquals("Re: Uppdaterat ärende (447899), kostnader för hjälp med stadgeändring enligt ny lagstiftning", $subject->toString()); 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /tests/issues/Issue379Test.php: -------------------------------------------------------------------------------- 1 | getFolder('INBOX'); 53 | 54 | $message = $this->appendMessageTemplate($folder, "plain.eml"); 55 | $this->assertEquals(214, $message->getSize()); 56 | 57 | // Clean up 58 | $this->assertTrue($message->delete(true)); 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /tests/issues/Issue382Test.php: -------------------------------------------------------------------------------- 1 | from->first(); 25 | 26 | self::assertSame("Mail Delivery System", $from->personal); 27 | self::assertSame("MAILER-DAEMON", $from->mailbox); 28 | self::assertSame("mta-09.someserver.com", $from->host); 29 | self::assertSame("MAILER-DAEMON@mta-09.someserver.com", $from->mail); 30 | self::assertSame("Mail Delivery System ", $from->full); 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /tests/issues/Issue383Test.php: -------------------------------------------------------------------------------- 1 | getClient(); 44 | $client->connect(); 45 | 46 | $delimiter = $this->getManager()->getConfig()->get("options.delimiter"); 47 | $folder_path = implode($delimiter, ['INBOX', 'Entwürfe+']); 48 | 49 | $folder = $client->getFolder($folder_path); 50 | $this->deleteFolder($folder); 51 | 52 | $folder = $client->createFolder($folder_path, false); 53 | self::assertInstanceOf(Folder::class, $folder); 54 | 55 | $folder = $this->getFolder($folder_path); 56 | self::assertInstanceOf(Folder::class, $folder); 57 | 58 | $this->assertEquals('Entwürfe+', $folder->name); 59 | $this->assertEquals($folder_path, $folder->full_name); 60 | 61 | $folder_path = implode($delimiter, ['INBOX', 'Entw&APw-rfe+']); 62 | $this->assertEquals($folder_path, $folder->path); 63 | 64 | // Clean up 65 | if ($this->deleteFolder($folder) === false) { 66 | $this->fail("Could not delete folder: " . $folder->path); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /tests/issues/Issue393Test.php: -------------------------------------------------------------------------------- 1 | getClient(); 44 | $client->connect(); 45 | 46 | $delimiter = $this->getManager()->getConfig()->get("options.delimiter"); 47 | $pattern = implode($delimiter, ['doesnt_exist', '%']); 48 | 49 | $folder = $client->getFolder('doesnt_exist'); 50 | $this->deleteFolder($folder); 51 | 52 | $folders = $client->getFolders(true, $pattern, true); 53 | self::assertCount(0, $folders); 54 | 55 | try { 56 | $client->getFolders(true, $pattern, false); 57 | $this->fail('Expected FolderFetchingException::class exception not thrown'); 58 | } catch (FolderFetchingException $e) { 59 | self::assertInstanceOf(FolderFetchingException::class, $e); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /tests/issues/Issue401Test.php: -------------------------------------------------------------------------------- 1 | subject); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /tests/issues/Issue407Test.php: -------------------------------------------------------------------------------- 1 | getFolder('INBOX'); 41 | self::assertInstanceOf(Folder::class, $folder); 42 | 43 | $message = $this->appendMessageTemplate($folder, "plain.eml"); 44 | self::assertInstanceOf(Message::class, $message); 45 | 46 | $message->setFlag("Seen"); 47 | 48 | $flags = $this->getClient()->getConnection()->flags($message->uid, IMAP::ST_UID)->validatedData(); 49 | 50 | self::assertIsArray($flags); 51 | self::assertSame(1, count($flags)); 52 | self::assertSame("\\Seen", $flags[$message->uid][0]); 53 | 54 | $message->delete(); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /tests/issues/Issue40Test.php: -------------------------------------------------------------------------------- 1 | getFixture("issue-40.eml"); 47 | 48 | self::assertSame("Zly from", (string)$message->subject); 49 | self::assertSame([ 50 | 'personal' => '', 51 | 'mailbox' => 'faked_sender', 52 | 'host' => 'sender_domain.pl', 53 | 'mail' => 'faked_sender@sender_domain.pl', 54 | 'full' => 'faked_sender@sender_domain.pl', 55 | ], $message->from->first()->toArray()); 56 | self::assertSame([ 57 | 'personal' => '', 58 | 'mailbox' => 'real_sender', 59 | 'host' => 'sender_domain.pl', 60 | 'mail' => 'real_sender@sender_domain.pl', 61 | 'full' => ' ', 62 | ], (array)$message->return_path->first()); 63 | self::assertSame(true, $message->spoofed->first()); 64 | 65 | $config = $message->getConfig(); 66 | self::assertSame(false, $config->get("security.detect_spoofing_exception")); 67 | $config->set("security.detect_spoofing_exception", true); 68 | self::assertSame(true, $config->get("security.detect_spoofing_exception")); 69 | 70 | $this->expectException(SpoofingAttemptDetectedException::class); 71 | $this->getFixture("issue-40.eml", $config); 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /tests/issues/Issue412Test.php: -------------------------------------------------------------------------------- 1 | subject); 26 | self::assertSame("64254d63e92a36ee02c760676351e60a", md5($message->getTextBody())); 27 | self::assertSame("2e4de288f6a1ed658548ed11fcdb1d79", md5($message->getHTMLBody())); 28 | self::assertSame(0, $message->attachments()->count()); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /tests/issues/Issue413Test.php: -------------------------------------------------------------------------------- 1 | getFolder('INBOX'); 45 | self::assertInstanceOf(Folder::class, $folder); 46 | 47 | /** @var Message $message */ 48 | $_message = $this->appendMessageTemplate($folder, 'issue-413.eml'); 49 | 50 | $message = $folder->messages()->getMessageByMsgn($_message->msgn); 51 | self::assertEquals($message->uid, $_message->uid); 52 | 53 | self::assertSame("Test Message", (string)$message->subject); 54 | self::assertSame("This is just a test, so ignore it (if you can!)\r\n\r\nTony Marston", $message->getTextBody()); 55 | 56 | $message->delete(); 57 | } 58 | 59 | /** 60 | * Static parsing test 61 | * 62 | * @return void 63 | * @throws \ReflectionException 64 | * @throws \Webklex\PHPIMAP\Exceptions\AuthFailedException 65 | * @throws \Webklex\PHPIMAP\Exceptions\ConnectionFailedException 66 | * @throws \Webklex\PHPIMAP\Exceptions\ImapBadRequestException 67 | * @throws \Webklex\PHPIMAP\Exceptions\ImapServerErrorException 68 | * @throws \Webklex\PHPIMAP\Exceptions\InvalidMessageDateException 69 | * @throws \Webklex\PHPIMAP\Exceptions\MaskNotFoundException 70 | * @throws \Webklex\PHPIMAP\Exceptions\MessageContentFetchingException 71 | * @throws \Webklex\PHPIMAP\Exceptions\ResponseException 72 | * @throws \Webklex\PHPIMAP\Exceptions\RuntimeException 73 | */ 74 | public function testIssueEmail() { 75 | $filename = implode(DIRECTORY_SEPARATOR, [__DIR__, "..", "messages", "issue-413.eml"]); 76 | $message = Message::fromFile($filename); 77 | 78 | self::assertSame("Test Message", (string)$message->subject); 79 | self::assertSame("This is just a test, so ignore it (if you can!)\r\n\r\nTony Marston", $message->getTextBody()); 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /tests/issues/Issue414Test.php: -------------------------------------------------------------------------------- 1 | subject); 25 | 26 | $attachments = $message->getAttachments(); 27 | 28 | self::assertSame(2, $attachments->count()); 29 | 30 | $attachment = $attachments->first(); 31 | self::assertEmpty($attachment->description); 32 | self::assertSame("exampleMyFile.txt", $attachment->filename); 33 | self::assertSame("exampleMyFile.txt", $attachment->name); 34 | self::assertSame("be62f7e6", $attachment->id); 35 | 36 | $attachment = $attachments->last(); 37 | self::assertEmpty($attachment->description); 38 | self::assertSame("phpfoo", $attachment->filename); 39 | self::assertSame("phpfoo", $attachment->name); 40 | self::assertSame("12e1d38b", $attachment->hash); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /tests/issues/Issue420Test.php: -------------------------------------------------------------------------------- 1 | get("subject"); 26 | 27 | // Ticket No: [��17] Mailbox Inbox - (17) Incoming failed messages 28 | $this->assertEquals('Ticket No: [??17] Mailbox Inbox - (17) Incoming failed messages', utf8_decode($subject->toString())); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /tests/issues/Issue462Test.php: -------------------------------------------------------------------------------- 1 | set('options.rfc822', false); 44 | $message = $this->getFixture("issue-462.eml", $config); 45 | self::assertSame("Undeliverable: Some subject", (string)$message->subject); 46 | self::assertSame("postmaster@ ", (string)$message->from->first()); 47 | } 48 | } -------------------------------------------------------------------------------- /tests/issues/Issue469Test.php: -------------------------------------------------------------------------------- 1 | createStub(Client::class); 16 | $folder_name = '[Gmail]'; 17 | $delimiter = '/'; 18 | 19 | $attributes = [ 20 | '\NoInferiors', 21 | '\NoSelect', 22 | ]; 23 | $folder = new Folder($client, $folder_name, $delimiter, $attributes); 24 | 25 | $attributes_lowercase = [ 26 | '\Noinferiors', 27 | '\Noselect', 28 | ]; 29 | $folder_lowercase = new Folder($client, $folder_name, $delimiter, $attributes_lowercase); 30 | 31 | self::assertSame( 32 | $folder->no_inferiors, 33 | $folder_lowercase->no_inferiors, 34 | 'The parsed "\NoInferiors" attribute does not match the parsed "\Noinferiors" attribute' 35 | ); 36 | self::assertSame( 37 | $folder->no_select, 38 | $folder_lowercase->no_select, 39 | 'The parsed "\NoSelect" attribute does not match the parsed "\Noselect" attribute' 40 | ); 41 | } 42 | } -------------------------------------------------------------------------------- /tests/issues/Issue511Test.php: -------------------------------------------------------------------------------- 1 | getFixture("issue-511.eml"); 47 | self::assertSame("RE: [EXTERNAL] Re: Lorem Ipsum /40 one", (string)$message->subject); 48 | self::assertSame("COMPANYNAME | usługi ", (string)$message->from->first()); 49 | } 50 | } -------------------------------------------------------------------------------- /tests/issues/Issue544Test.php: -------------------------------------------------------------------------------- 1 | getFixture("issue-544.eml"); 46 | 47 | self::assertSame("Test bad boundary", (string)$message->subject); 48 | 49 | $attachments = $message->getAttachments(); 50 | 51 | self::assertSame(1, $attachments->count()); 52 | 53 | /** @var Attachment $attachment */ 54 | $attachment = $attachments->first(); 55 | self::assertSame("file.pdf", $attachment->name); 56 | self::assertSame("file.pdf", $attachment->filename); 57 | self::assertStringStartsWith("%PDF-1.4", $attachment->content); 58 | self::assertStringEndsWith("%%EOF\n", $attachment->content); 59 | self::assertSame(14938, $attachment->size); 60 | } 61 | } -------------------------------------------------------------------------------- /tests/messages/attachment_encoded_filename.eml: -------------------------------------------------------------------------------- 1 | Content-Type: multipart/mixed; 2 | boundary="BOUNDARY" 3 | 4 | --BOUNDARY 5 | Content-Type: application/vnd.ms-excel; name="=?UTF-8?Q?Prost=C5=99eno=5F2014=5Fposledn=C3=AD_voln=C3=A9_term=C3=ADny.xls?="; charset="UTF-8" 6 | Content-Transfer-Encoding: base64 7 | Content-Disposition: attachment; filename="=?UTF-8?Q?Prost=C5=99eno=5F2014=5Fposledn=C3=AD_voln=C3=A9_term=C3=ADny.xls?=" 8 | 9 | 0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAACAAAAwgAAAAAA 10 | AAAAEAAA/v///wAAAAD+////AAAAAMAAAADBAAAA//////////////////////////////// 11 | -------------------------------------------------------------------------------- /tests/messages/attachment_long_filename.eml: -------------------------------------------------------------------------------- 1 | Content-Type: multipart/mixed; 2 | boundary="BOUNDARY" 3 | 4 | --BOUNDARY 5 | Content-Type: text/plain; 6 | name*0*=utf-8''Buchungsbest%C3%A4tigung-%20Rechnung-Gesch%C3%A4ftsbedingung; 7 | name*1*=en-Nr.B123-45%20-%20XXXX%20xxxxxxxxxxxxxxxxx%20XxxX%2C%20L%C3%BCd; 8 | name*2*=xxxxxxxx%20-%20VM%20Klaus%20XXXXXX%20-%20xxxxxxxx.pdf 9 | Content-Disposition: attachment; 10 | filename*0*=utf-8''Buchungsbest%C3%A4tigung-%20Rechnung-Gesch%C3%A4ftsbedin; 11 | filename*1*=gungen-Nr.B123-45%20-%20XXXXX%20xxxxxxxxxxxxxxxxx%20XxxX%2C; 12 | filename*2*=%20L%C3%BCxxxxxxxxxx%20-%20VM%20Klaus%20XXXXXX%20-%20xxxxxxxx.p; 13 | filename*3*=df 14 | Content-Transfer-Encoding: base64 15 | 16 | SGkh 17 | --BOUNDARY 18 | Content-Type: text/plain; charset=UTF-8; 19 | name="=?UTF-8?B?MDFfQeKCrMOgw6TEhdCx2YrYr0BaLTAxMjM0NTY3ODktcXdlcnR5dWlv?= 20 | =?UTF-8?Q?pasdfghjklzxcvbnmopqrstuvz-0123456789-qwertyuiopasdfghjklzx?= 21 | =?UTF-8?Q?cvbnmopqrstuvz-0123456789-qwertyuiopasdfghjklzxcvbnmopqrstu?= 22 | =?UTF-8?Q?vz.txt?=" 23 | Content-Transfer-Encoding: base64 24 | Content-Disposition: attachment; 25 | filename*0*=iso-8859-15''%30%31%5F%41%A4%E0%E4%3F%3F%3F%3F%40%5A%2D%30%31; 26 | filename*1*=%32%33%34%35%36%37%38%39%2D%71%77%65%72%74%79%75%69%6F%70%61; 27 | filename*2*=%73%64%66%67%68%6A%6B%6C%7A%78%63%76%62%6E%6D%6F%70%71%72%73; 28 | filename*3*=%74%75%76%7A%2D%30%31%32%33%34%35%36%37%38%39%2D%71%77%65%72; 29 | filename*4*=%74%79%75%69%6F%70%61%73%64%66%67%68%6A%6B%6C%7A%78%63%76%62; 30 | filename*5*=%6E%6D%6F%70%71%72%73%74%75%76%7A%2D%30%31%32%33%34%35%36%37; 31 | filename*6*=%38%39%2D%71%77%65%72%74%79%75%69%6F%70%61%73%64%66%67%68%6A; 32 | filename*7*=%6B%6C%7A%78%63%76%62%6E%6D%6F%70%71%72%73%74%75%76%7A%2E%74; 33 | filename*8*=%78%74 34 | 35 | SGkh 36 | --BOUNDARY 37 | Content-Type: text/plain; charset=UTF-8; 38 | name="=?UTF-8?B?MDJfQeKCrMOgw6TEhdCx2YrYr0BaLTAxMjM0NTY3ODktcXdlcnR5dWlv?= 39 | =?UTF-8?Q?pasdfghjklzxcvbnmopqrstuvz-0123456789-qwertyuiopasdfghjklzx?= 40 | =?UTF-8?Q?cvbnmopqrstuvz-0123456789-qwertyuiopasdfghjklzxcvbnmopqrstu?= 41 | =?UTF-8?Q?vz.txt?=" 42 | Content-Transfer-Encoding: base64 43 | Content-Disposition: attachment; 44 | filename*0*=UTF-8''%30%32%5F%41%E2%82%AC%C3%A0%C3%A4%C4%85%D0%B1%D9%8A%D8; 45 | filename*1*=%AF%40%5A%2D%30%31%32%33%34%35%36%37%38%39%2D%71%77%65%72%74; 46 | filename*2*=%79%75%69%6F%70%61%73%64%66%67%68%6A%6B%6C%7A%78%63%76%62%6E; 47 | filename*3*=%6D%6F%70%71%72%73%74%75%76%7A%2D%30%31%32%33%34%35%36%37%38; 48 | filename*4*=%39%2D%71%77%65%72%74%79%75%69%6F%70%61%73%64%66%67%68%6A%6B; 49 | filename*5*=%6C%7A%78%63%76%62%6E%6D%6F%70%71%72%73%74%75%76%7A%2D%30%31; 50 | filename*6*=%32%33%34%35%36%37%38%39%2D%71%77%65%72%74%79%75%69%6F%70%61; 51 | filename*7*=%73%64%66%67%68%6A%6B%6C%7A%78%63%76%62%6E%6D%6F%70%71%72%73; 52 | filename*8*=%74%75%76%7A%2E%74%78%74 53 | 54 | SGkh 55 | --BOUNDARY-- 56 | -------------------------------------------------------------------------------- /tests/messages/attachment_no_disposition.eml: -------------------------------------------------------------------------------- 1 | Content-Type: multipart/mixed; 2 | boundary="BOUNDARY" 3 | 4 | --BOUNDARY 5 | Content-Type: application/vnd.ms-excel; name="=?UTF-8?Q?Prost=C5=99eno=5F2014=5Fposledn=C3=AD_voln=C3=A9_term=C3=ADny.xls?="; charset="UTF-8" 6 | Content-Transfer-Encoding: base64 7 | 8 | 0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAACAAAAwgAAAAAA 9 | AAAAEAAA/v///wAAAAD+////AAAAAMAAAADBAAAA//////////////////////////////// 10 | -------------------------------------------------------------------------------- /tests/messages/bcc.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Subject: test 3 | MIME-Version: 1.0 4 | Content-Type: text/plain 5 | Date: Wed, 27 Sep 2017 12:48:51 +0200 6 | From: from@there.com 7 | To: to@here.com 8 | Bcc: =?UTF-8?B?QV/igqxAe8OoX1o=?= 9 | Reply-To: reply-to@here.com 10 | Sender: sender@here.com 11 | 12 | Hi! 13 | -------------------------------------------------------------------------------- /tests/messages/boolean_decoded_content.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: Nuu 4 | Date: Wed, 13 Sep 2017 13:05:45 +0200 5 | Content-Type: multipart/mixed; boundary="=-vyqYb0SSRwuGFKv/Trdf" 6 | 7 | --=-vyqYb0SSRwuGFKv/Trdf 8 | Content-Type: multipart/alternative; boundary="=-ewUvwipK68Y6itClYNpy" 9 | 10 | --=-ewUvwipK68Y6itClYNpy 11 | Content-Type: text/plain; charset="us-ascii" 12 | 13 | Here is the problem mail 14 | 15 | Body text 16 | --=-ewUvwipK68Y6itClYNpy 17 | Content-Type: text/html; charset="us-ascii" 18 | 19 | Here is the problem mail 20 | 21 | Body text 22 | --=-ewUvwipK68Y6itClYNpy-- 23 | 24 | --=-vyqYb0SSRwuGFKv/Trdf 25 | Content-Type: application/pdf; name="Example Domain.pdf" 26 | Content-Disposition: attachment; filename="Example Domain.pdf" 27 | Content-Transfer-Encoding: base64 28 | 29 | nnDusSNdG92w6Fuw61fMjAxOF8wMy0xMzMyNTMzMTkzLnBkZg==?= 30 | 31 | --=-vyqYb0SSRwuGFKv/Trdf-- 32 | -------------------------------------------------------------------------------- /tests/messages/date-template.eml: -------------------------------------------------------------------------------- 1 | Subject: test 2 | MIME-Version: 1.0 3 | Content-Type: text/plain 4 | Date: %date_raw_header% 5 | From: from@there.com 6 | To: to@here.com 7 | 8 | Hi! 9 | -------------------------------------------------------------------------------- /tests/messages/email_address.eml: -------------------------------------------------------------------------------- 1 | Message-ID: <123@example.com> 2 | From: no_host 3 | Cc: "This one: is \"right\"" , No-address 4 | Content-Type: text/plain; 5 | charset="us-ascii" 6 | Content-Transfer-Encoding: quoted-printable 7 | 8 | Hi 9 | How are you? 10 | -------------------------------------------------------------------------------- /tests/messages/embedded_email.eml: -------------------------------------------------------------------------------- 1 | Return-Path: demo@cerstor.cz 2 | Received: from webmail.my-office.cz (localhost [127.0.0.1]) 3 | by keira.cofis.cz 4 | ; Fri, 29 Jan 2016 14:25:40 +0100 5 | MIME-Version: 1.0 6 | Content-Type: multipart/mixed; 7 | boundary="=_5d4b2de51e6aad0435b4bfbd7a23594a" 8 | Date: Fri, 29 Jan 2016 14:25:40 +0100 9 | From: demo@cerstor.cz 10 | To: demo@cerstor.cz 11 | Subject: embedded message 12 | Message-ID: <7e5798da5747415e5b82fdce042ab2a6@cerstor.cz> 13 | X-Sender: demo@cerstor.cz 14 | User-Agent: Roundcube Webmail/1.0.0 15 | 16 | --=_5d4b2de51e6aad0435b4bfbd7a23594a 17 | Content-Transfer-Encoding: 7bit 18 | Content-Type: text/plain; charset=US-ASCII; 19 | format=flowed 20 | 21 | email that contains embedded message 22 | --=_5d4b2de51e6aad0435b4bfbd7a23594a 23 | Content-Transfer-Encoding: 8bit 24 | Content-Type: message/rfc822; 25 | name=demo.eml 26 | Content-Disposition: attachment; 27 | filename=demo.eml; 28 | size=889 29 | 30 | Return-Path: demo@cerstor.cz 31 | Received: from webmail.my-office.cz (localhost [127.0.0.1]) 32 | by keira.cofis.cz 33 | ; Fri, 29 Jan 2016 14:22:13 +0100 34 | MIME-Version: 1.0 35 | Content-Type: multipart/mixed; 36 | boundary="=_995890bdbf8bd158f2cbae0e8d966000" 37 | Date: Fri, 29 Jan 2016 14:22:13 +0100 38 | From: demo-from@cerstor.cz 39 | To: demo-to@cerstor.cz 40 | Subject: demo 41 | Message-ID: <4cbaf57cb00891c53b32e1d63367740c@cerstor.cz> 42 | X-Sender: demo@cerstor.cz 43 | User-Agent: Roundcube Webmail/1.0.0 44 | 45 | --=_995890bdbf8bd158f2cbae0e8d966000 46 | Content-Transfer-Encoding: 7bit 47 | Content-Type: text/plain; charset=US-ASCII; 48 | format=flowed 49 | 50 | demo text 51 | --=_995890bdbf8bd158f2cbae0e8d966000 52 | Content-Transfer-Encoding: base64 53 | Content-Type: text/plain; 54 | name=testfile.txt 55 | Content-Disposition: attachment; 56 | filename=testfile.txt; 57 | size=29 58 | 59 | IHRoaXMgaXMgY29udGVudCBvZiB0ZXN0IGZpbGU= 60 | --=_995890bdbf8bd158f2cbae0e8d966000-- 61 | 62 | 63 | --=_5d4b2de51e6aad0435b4bfbd7a23594a-- 64 | -------------------------------------------------------------------------------- /tests/messages/embedded_email_without_content_disposition-embedded.eml: -------------------------------------------------------------------------------- 1 | Received: from webmail.my-office.cz (localhost [127.0.0.1]) 2 | by keira.cofis.cz 3 | ; Fri, 29 Jan 2016 14:25:40 +0100 4 | From: demo@cerstor.cz 5 | To: demo@cerstor.cz 6 | Date: Fri, 5 Apr 2019 12:10:49 +0200 7 | Subject: embedded_message_subject 8 | Message-ID: 9 | Accept-Language: pl-PL, nl-NL 10 | Content-Language: pl-PL 11 | Content-Type: multipart/mixed; 12 | boundary="_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_" 13 | MIME-Version: 1.0 14 | 15 | --_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_ 16 | Content-Type: multipart/alternative; 17 | boundary="_000_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_" 18 | 19 | --_000_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_ 20 | Content-Type: text/plain; charset="iso-8859-2" 21 | Content-Transfer-Encoding: quoted-printable 22 | 23 | some txt 24 | 25 | 26 | 27 | 28 | 29 | --_000_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_ 30 | Content-Type: text/html; charset="iso-8859-2" 31 | Content-Transfer-Encoding: quoted-printable 32 | 33 | 34 |

some txt

35 | 36 | 37 | --_000_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_-- 38 | 39 | --_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_ 40 | Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; 41 | name="file1.xlsx" 42 | Content-Description: file1.xlsx 43 | Content-Disposition: attachment; filename="file1.xlsx"; size=29; 44 | creation-date="Fri, 05 Apr 2019 10:06:01 GMT"; 45 | modification-date="Fri, 05 Apr 2019 10:10:49 GMT" 46 | Content-Transfer-Encoding: base64 47 | 48 | IHRoaXMgaXMgY29udGVudCBvZiB0ZXN0IGZpbGU= 49 | 50 | --_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_ 51 | Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; 52 | name="file2.xlsx" 53 | Content-Description: file2 54 | Content-Disposition: attachment; filename="file2.xlsx"; size=29; 55 | creation-date="Fri, 05 Apr 2019 10:10:19 GMT"; 56 | modification-date="Wed, 03 Apr 2019 11:04:32 GMT" 57 | Content-Transfer-Encoding: base64 58 | 59 | IHRoaXMgaXMgY29udGVudCBvZiB0ZXN0IGZpbGU= 60 | 61 | --_005_AC39946EBF5C034B87BABD5343E96979012671D40E38VM002emonsn_-- 62 | -------------------------------------------------------------------------------- /tests/messages/example_attachment.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Delivered-To: 3 | Received: from mx.domain.tld 4 | by localhost (Dovecot) with LMTP id T7mwLn3ddlvKWwAA0J78UA 5 | for ; Fri, 17 Aug 2018 16:36:45 +0200 6 | Received: from localhost (localhost [127.0.0.1]) 7 | by mx.domain.tld (Postfix) with ESMTP id B642913BA0BE2 8 | for ; Fri, 17 Aug 2018 16:36:45 +0200 (CEST) 9 | X-Virus-Scanned: Debian amavisd-new at mx.domain.tld 10 | X-Spam-Flag: NO 11 | X-Spam-Score: 1.103 12 | X-Spam-Level: * 13 | X-Spam-Status: No, score=1.103 required=6.31 tests=[ALL_TRUSTED=-1, 14 | OBFU_TEXT_ATTACH=1, TRACKER_ID=1.102, TVD_SPACE_RATIO=0.001] 15 | autolearn=no autolearn_force=no 16 | Received: from mx.domain.tld ([127.0.0.1]) 17 | by localhost (mx.domain.tld [127.0.0.1]) (amavisd-new, port 10024) 18 | with ESMTP id L8E9vyX80d44 for ; 19 | Fri, 17 Aug 2018 16:36:39 +0200 (CEST) 20 | Received: from [127.0.0.1] (ip.dynamic.domain.tld [192.168.0.24]) 21 | (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) 22 | (No client certificate requested) 23 | by mx.domain.tld (Postfix) with ESMTPSA id EF01E13BA0BD7 24 | for ; Fri, 17 Aug 2018 16:36:38 +0200 (CEST) 25 | Sender: testsender 26 | Message-ID: 27 | Date: Fri, 17 Aug 2018 14:36:24 +0000 28 | Subject: ogqMVHhz7swLaq2PfSWsZj0k99w8wtMbrb4RuHdNg53i76B7icIIM0zIWpwGFtnk 29 | From: testfrom 30 | Reply-To: testreply_to 31 | To: testnameto 32 | Cc: testnamecc 33 | MIME-Version: 1.0 34 | Content-Type: multipart/mixed; 35 | boundary="_=_swift_v4_1534516584_32c032a3715d2dfd5cd84c26f84dba8d_=_" 36 | X-Priority: 1 (Highest) 37 | 38 | 39 | 40 | 41 | --_=_swift_v4_1534516584_32c032a3715d2dfd5cd84c26f84dba8d_=_ 42 | Content-Type: text/plain; charset=utf-8 43 | Content-Transfer-Encoding: quoted-printable 44 | 45 | n1IaXFkbeqKyg4lYToaJ3u1Ond2EDrN3UWuiLFNjOLJEAabSYagYQaOHtV5QDlZE 46 | 47 | --_=_swift_v4_1534516584_32c032a3715d2dfd5cd84c26f84dba8d_=_ 48 | Content-Type: application/octet-stream; name=6mfFxiU5Yhv9WYJx.txt 49 | Content-Transfer-Encoding: base64 50 | Content-Disposition: attachment; filename=6mfFxiU5Yhv9WYJx.txt 51 | 52 | em5rNTUxTVAzVFAzV1BwOUtsMWduTEVycldFZ2tKRkF0dmFLcWtUZ3JrM2RLSThkWDM4WVQ4QmFW 53 | eFJjT0VSTg== 54 | 55 | --_=_swift_v4_1534516584_32c032a3715d2dfd5cd84c26f84dba8d_=_-- 56 | 57 | -------------------------------------------------------------------------------- /tests/messages/four_nested_emails.eml: -------------------------------------------------------------------------------- 1 | To: test@example.com 2 | From: test@example.com 3 | Subject: 3-third-subject 4 | Content-Type: multipart/mixed; 5 | boundary="------------2E5D78A17C812FEFF825F7D5" 6 | 7 | This is a multi-part message in MIME format. 8 | --------------2E5D78A17C812FEFF825F7D5 9 | Content-Type: text/plain; charset=iso-8859-15; format=flowed 10 | Content-Transfer-Encoding: 7bit 11 | 12 | 3-third-content 13 | --------------2E5D78A17C812FEFF825F7D5 14 | Content-Type: message/rfc822; 15 | name="2-second-email.eml" 16 | Content-Transfer-Encoding: 7bit 17 | Content-Disposition: attachment; 18 | filename="2-second-email.eml" 19 | 20 | To: test@example.com 21 | From: test@example.com 22 | Subject: 2-second-subject 23 | Content-Type: multipart/mixed; 24 | boundary="------------9919377E37A03209B057D47F" 25 | 26 | This is a multi-part message in MIME format. 27 | --------------9919377E37A03209B057D47F 28 | Content-Type: text/plain; charset=iso-8859-15; format=flowed 29 | Content-Transfer-Encoding: 7bit 30 | 31 | 2-second-content 32 | --------------9919377E37A03209B057D47F 33 | Content-Type: message/rfc822; 34 | name="1-first-email.eml" 35 | Content-Transfer-Encoding: 7bit 36 | Content-Disposition: attachment; 37 | filename="1-first-email.eml" 38 | 39 | To: test@example.com 40 | From: test@example.com 41 | Subject: 1-first-subject 42 | Content-Type: multipart/mixed; 43 | boundary="------------0919377E37A03209B057D47A" 44 | 45 | This is a multi-part message in MIME format. 46 | --------------0919377E37A03209B057D47A 47 | Content-Type: text/plain; charset=iso-8859-15; format=flowed 48 | Content-Transfer-Encoding: 7bit 49 | 50 | 1-first-content 51 | --------------0919377E37A03209B057D47A 52 | Content-Type: message/rfc822; 53 | name="0-zero-email.eml" 54 | Content-Transfer-Encoding: 7bit 55 | Content-Disposition: attachment; 56 | filename="0-zero-email.eml" 57 | 58 | To: test@example.com 59 | From: test@example.com 60 | Subject: 0-zero-subject 61 | Content-Type: text/plain; charset=iso-8859-15; format=flowed 62 | Content-Transfer-Encoding: 7bit 63 | 64 | 0-zero-content 65 | --------------0919377E37A03209B057D47A-- 66 | 67 | --------------9919377E37A03209B057D47F-- 68 | 69 | --------------2E5D78A17C812FEFF825F7D5-- 70 | -------------------------------------------------------------------------------- /tests/messages/gbk_charset.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: Nuu 4 | Date: Wed, 13 Sep 2017 13:05:45 +0200 5 | Content-Type: text/plain; 6 | charset="X-GBK" 7 | Content-Transfer-Encoding: quoted-printable 8 | 9 | Hi 10 | -------------------------------------------------------------------------------- /tests/messages/html_only.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: Nuu 4 | Date: Wed, 13 Sep 2017 13:05:45 +0200 5 | Content-Type: text/html; 6 | charset="us-ascii" 7 | Content-Transfer-Encoding: quoted-printable 8 | 9 | Hi -------------------------------------------------------------------------------- /tests/messages/imap_mime_header_decode_returns_false.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: =?UTF-8?B?nnDusSNdG92w6Fuw61fMjAxOF8wMy0xMzMyNTMzMTkzLnBkZg==?= 4 | Date: Wed, 13 Sep 2017 13:05:45 +0200 5 | Content-Type: text/plain; 6 | charset="us-ascii" 7 | Content-Transfer-Encoding: quoted-printable 8 | 9 | Hi 10 | -------------------------------------------------------------------------------- /tests/messages/inline_attachment.eml: -------------------------------------------------------------------------------- 1 | Content-Type: multipart/mixed; 2 | boundary="----=_Part_1114403_1160068121.1505882828080" 3 | 4 | ------=_Part_1114403_1160068121.1505882828080 5 | Content-Type: multipart/related; 6 | boundary="----=_Part_1114404_576719783.1505882828080" 7 | 8 | ------=_Part_1114404_576719783.1505882828080 9 | Content-Type: text/html;charset=UTF-8 10 | Content-Transfer-Encoding: quoted-printable 11 | 12 | 13 | ------=_Part_1114404_576719783.1505882828080 14 | Content-Type: image/png 15 | Content-Disposition: inline 16 | Content-Transfer-Encoding: base64 17 | Content-ID: 18 | 19 | iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAB+FBMVEUAAAA/mUPidDHiLi5Cn0Xk 20 | NTPmeUrkdUg/m0Q0pEfcpSbwaVdKskg+lUP4zA/iLi3msSHkOjVAmETdJSjtYFE/lkPnRj3sWUs8 21 | kkLeqCVIq0fxvhXqUkbVmSjwa1n1yBLepyX1xxP0xRXqUkboST9KukpHpUbuvRrzrhF/ljbwalju 22 | ZFM4jELaoSdLtElJrUj1xxP6zwzfqSU4i0HYnydMtUlIqUfywxb60AxZqEXaoifgMCXptR9MtklH 23 | pEY2iUHWnSjvvRr70QujkC+pUC/90glMuEnlOjVMt0j70QriLS1LtEnnRj3qUUXfIidOjsxAhcZF 24 | o0bjNDH0xxNLr0dIrUdmntVTkMoyfL8jcLBRuErhJyrgKyb4zA/5zg3tYFBBmUTmQTnhMinruBzv 25 | vhnxwxZ/st+Ktt5zp9hqota2vtK6y9FemNBblc9HiMiTtMbFtsM6gcPV2r6dwroseLrMrbQrdLGd 26 | yKoobKbo3Zh+ynrgVllZulTsXE3rV0pIqUf42UVUo0JyjEHoS0HmsiHRGR/lmRz/1hjqnxjvpRWf 27 | wtOhusaz0LRGf7FEfbDVmqHXlJeW0pbXq5bec3fX0nTnzmuJuWvhoFFhm0FtrziBsjaAaDCYWC+u 28 | Si6jQS3FsSfLJiTirCOkuCG1KiG+wSC+GBvgyhTszQ64Z77KAAAARXRSTlMAIQRDLyUgCwsE6ebm 29 | 5ubg2dLR0byXl4FDQzU1NDEuLSUgC+vr6urq6ubb29vb2tra2tG8vLu7u7uXl5eXgYGBgYGBLiUA 30 | LabIAAABsElEQVQoz12S9VPjQBxHt8VaOA6HE+AOzv1wd7pJk5I2adpCC7RUcHd3d3fXf5PvLkxh 31 | eD++z+yb7GSRlwD/+Hj/APQCZWxM5M+goF+RMbHK594v+tPoiN1uHxkt+xzt9+R9wnRTZZQpXQ0T 32 | 5uP1IQxToyOAZiQu5HEpjeA4SWIoksRxNiGC1tRZJ4LNxgHgnU5nJZBDvuDdl8lzQRBsQ+s9PZt7 33 | s7Pz8wsL39/DkIfZ4xlB2Gqsq62ta9oxVlVrNZpihFRpGO9fzQw1ms0NDWZz07iGkJmIFH8xxkc3 34 | a/WWlubmFkv9AB2SEpDvKxbjidN2faseaNV3zoHXvv7wMODJdkOHAegweAfFPx4G67KluxzottCU 35 | 9n8CUqXzcIQdXOytAHqXxomvykhEKN9EFutG22p//0rbNvHVxiJywa8yS2KDfV1dfbu31H8jF1RH 36 | iTKtWYeHxUvq3bn0pyjCRaiRU6aDO+gb3aEfEeVNsDgm8zzLy9egPa7Qt8TSJdwhjplk06HH43ZN 37 | J3s91KKCHQ5x4sw1fRGYDZ0n1L4FKb9/BP5JLYxToheoFCVxz57PPS8UhhEpLBVeAAAAAElFTkSu 38 | QmCC 39 | ------=_Part_1114404_576719783.1505882828080-- 40 | 41 | ------=_Part_1114403_1160068121.1505882828080-- 42 | -------------------------------------------------------------------------------- /tests/messages/issue-382.eml: -------------------------------------------------------------------------------- 1 | From: MAILER-DAEMON@mta-09.someserver.com (Mail Delivery System) 2 | To: to@here.com 3 | Subject: Test 4 | Date: Wed, 13 Sep 2017 13:05:45 +0200 5 | Content-Type: text/plain; 6 | charset="us-ascii" 7 | Content-Transfer-Encoding: quoted-printable 8 | 9 | Hi -------------------------------------------------------------------------------- /tests/messages/issue-40.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Delivered-To: receipent@receipent_domain.pl 3 | Received: from h2.server.pl 4 | \tby h2.server.pl with LMTP 5 | \tid 4IDTIEUkm18ZSSkA87l24w 6 | \t(envelope-from ) 7 | \tfor ; Thu, 29 Oct 2020 21:21:25 +0100 8 | Return-path: 9 | Envelope-to: receipent@receipent_domain.pl 10 | Delivery-date: Thu, 29 Oct 2020 21:21:25 +0100 11 | Received: from sender_domain.pl ([server ip]) 12 | \tby h2.server.pl with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 13 | \t(Exim 4.94) 14 | \t(envelope-from ) 15 | \tid 1kYEQG-00BPgD-S0 16 | \tfor receipent@receipent_domain.pl; Thu, 29 Oct 2020 21:21:25 +0100 17 | Received: by sender_domain.pl (Postfix, from userid 1000) 18 | \tid 57DADAB; Thu, 29 Oct 2020 21:21:23 +0100 (CET) 19 | DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=sender_domain.pl; s=default; 20 | \tt=1604002883; bh=CsZufJouWdjY/W12No6MSSMwbp0VaS8EOMGg9WptEaI=; 21 | \th=From:To:Subject:Date; 22 | \tb=v0NAncnNT/w+gInANxAkMt20ktM4LZquuwlokUmLpPyO3++8dy112olu63Dkn9L2E 23 | \t GwfHGqW+8f7g494UK6asUKqTx8fHxlEJbHqAiEV5QrlynSeZDFXsKvGDW8XNMFBKop 24 | \t sAjvp8NTUiNcA4MTbFaZ7RX15A/9d9QVEynU8MaNP2ZYKnq9J/JXgUjjMnx+FiULqf 25 | \t xJN/5rjwHRx7f6JQoXXUxuck6Zh4tSDiLLnDFasrSxed6sTNfnZMAggCyb1++estNk 26 | \t q6HNBwp85Az3ELo10RbBF/WM2FhxxFz1khncRtCyLXLUZ2lzhjan765KXpeYg7FUa9 27 | \t zItPWVTaTzTEg== 28 | From: faked_sender@sender_domain.pl 29 | To: receipent@receipent_domain.pl 30 | Subject: Zly from 31 | Message-Id: <20201029202123.57DADAB@sender_domain.pl> 32 | Date: Thu, 29 Oct 2020 21:21:01 +0100 (CET) 33 | Forward-Confirmed-ReverseDNS: Reverse and forward lookup success on server ip, -10 Spam score 34 | SPFCheck: Server passes SPF test, -30 Spam score 35 | X-DKIM: signer='sender_domain.pl' status='pass' reason='' 36 | DKIMCheck: Server passes DKIM test, -20 Spam score 37 | X-Spam-Score: -0.2 (/) 38 | 39 | Test message 40 | -------------------------------------------------------------------------------- /tests/messages/issue-401.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: 1;00pm Client running few minutes late 4 | Date: Wed, 13 Sep 2017 13:05:45 +0200 5 | Content-Type: text/plain; 6 | charset="us-ascii" 7 | Content-Transfer-Encoding: quoted-printable 8 | 9 | Hi -------------------------------------------------------------------------------- /tests/messages/issue-410.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: =?ISO-2022-JP?B?GyRCIXlCaBsoQjEzMhskQjlmISEhViUsITwlRyVzGyhCJhskQiUoJS8lOSVGJWolIiFXQGxMZ0U5JE4kPyRhJE4jURsoQiYbJEIjQSU1JW0lcyEhIVo3bjQpJSglLyU5JUYlaiUiISYlbyE8JS8hWxsoQg==?= 4 | Date: Wed, 13 Sep 2017 13:05:45 +0200 5 | MIME-Version: 1.0 6 | Content-Type: multipart/mixed; 7 | boundary="------------B832AF745285AEEC6D5AEE42" 8 | 9 | Hi 10 | --------------B832AF745285AEEC6D5AEE42 11 | Content-Transfer-Encoding: base64 12 | Content-Disposition: attachment; 13 | filename="=?ISO-2022-JP?B?GyRCIXlCaBsoQjEzMhskQjlmISEhViUsITwlRyVzGyhCJhskQiUoJS8lOSVGJWolIiFXQGxMZ0U5JE4kPyRhJE4jURsoQiYbJEIjQSU1JW0lcyEhIVo3bjQpJSglLyU5JUYlaiUiISYlbyE8JS8hWxsoQg==?=" 14 | 15 | SGkh 16 | --------------B832AF745285AEEC6D5AEE42-- -------------------------------------------------------------------------------- /tests/messages/issue-410b.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: =?iso-8859-1?Q?386_-_400021804_-_19.,_Heiligenst=E4dter_Stra=DFe_80_-_081?= 4 | =?iso-8859-1?Q?9306_-_Anfrage_Vergabevorschlag?= 5 | Date: Wed, 13 Sep 2017 13:05:45 +0200 6 | MIME-Version: 1.0 7 | Content-Type: multipart/mixed; 8 | boundary="------------B832AF745285AEEC6D5AEE42" 9 | 10 | Hi 11 | --------------B832AF745285AEEC6D5AEE42 12 | Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; 13 | name="=?iso-8859-1?Q?2021=5FM=E4ngelliste=5F0819306.xlsx?=" 14 | Content-Description: =?iso-8859-1?Q?2021=5FM=E4ngelliste=5F0819306.xlsx?= 15 | Content-Disposition: attachment; 16 | filename="=?iso-8859-1?Q?2021=5FM=E4ngelliste=5F0819306.xlsx?="; size=11641; 17 | creation-date="Mon, 10 Jan 2022 09:01:00 GMT"; 18 | modification-date="Mon, 10 Jan 2022 09:01:00 GMT" 19 | Content-Transfer-Encoding: base64 20 | 21 | SGkh 22 | --------------B832AF745285AEEC6D5AEE42-- -------------------------------------------------------------------------------- /tests/messages/issue-410symbols.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: =?iso-8859-1?Q?386_-_400021804_-_19.,_Heiligenst=E4dter_Stra=DFe_80_-_081?= 4 | =?iso-8859-1?Q?9306_-_Anfrage_Vergabevorschlag?= 5 | Date: Wed, 13 Sep 2017 13:05:45 +0200 6 | MIME-Version: 1.0 7 | Content-Type: multipart/mixed; 8 | boundary="------------B832AF745285AEEC6D5AEE42" 9 | 10 | Hi 11 | --------------B832AF745285AEEC6D5AEE42 12 | Content-Type: application/pdf; name="Checkliste 10.,DAVIDGASSE 76-80;2;2.pdf" 13 | Content-Description: Checkliste 10.,DAVIDGASSE 76-80;2;2.pdf 14 | Content-Disposition: attachment; 15 | filename="Checkliste 10.,DAVIDGASSE 76-80;2;2.pdf"; size=3439313; 16 | creation-date="Tue, 12 Sep 2023 06:53:03 GMT"; 17 | modification-date="Tue, 12 Sep 2023 08:18:16 GMT" 18 | Content-ID: <34A0EDD24A954140A472605B7526F190@there.com> 19 | Content-Transfer-Encoding: base64 20 | 21 | SGkh 22 | --------------B832AF745285AEEC6D5AEE42-- -------------------------------------------------------------------------------- /tests/messages/issue-413.eml: -------------------------------------------------------------------------------- 1 | Return-Path: 2 | Delivered-To: gmx@tonymarston.co.uk 3 | Received: from ion.dnsprotect.com 4 | by ion.dnsprotect.com with LMTP 5 | id oPy8IzIke2Rr4gIAzEkvSQ 6 | (envelope-from ) 7 | for ; Sat, 03 Jun 2023 07:29:54 -0400 8 | Return-path: 9 | Envelope-to: gmx@tonymarston.net 10 | Delivery-date: Sat, 03 Jun 2023 07:29:54 -0400 11 | Received: from [::1] (port=48740 helo=ion.dnsprotect.com) 12 | by ion.dnsprotect.com with esmtpa (Exim 4.96) 13 | (envelope-from ) 14 | id 1q5PSF-000nPQ-1F 15 | for gmx@tonymarston.net; 16 | Sat, 03 Jun 2023 07:29:54 -0400 17 | MIME-Version: 1.0 18 | Date: Sat, 03 Jun 2023 07:29:54 -0400 19 | From: radicore 20 | To: gmx@tonymarston.net 21 | Subject: Test Message 22 | User-Agent: Roundcube Webmail/1.6.0 23 | Message-ID: 24 | X-Sender: radicore@radicore.org 25 | Content-Type: text/plain; charset=US-ASCII; 26 | format=flowed 27 | Content-Transfer-Encoding: 7bit 28 | X-From-Rewrite: unmodified, already matched 29 | 30 | This is just a test, so ignore it (if you can!) 31 | 32 | Tony Marston 33 | -------------------------------------------------------------------------------- /tests/messages/issue-414.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: Test 4 | Date: Fri, 29 Sep 2017 10:55:23 +0200 5 | MIME-Version: 1.0 6 | Content-Type: multipart/mixed; 7 | boundary="------------5B1F217006A67C28E756A62E" 8 | 9 | This is a multi-part message in MIME format. 10 | 11 | --------------5B1F217006A67C28E756A62E 12 | Content-Type: text/plain; charset=UTF-8; 13 | name="../../example/MyFile.txt" 14 | Content-Transfer-Encoding: base64 15 | Content-Disposition: attachment; 16 | filename="../../example/MyFile.txt" 17 | 18 | TXlGaWxlQ29udGVudA== 19 | --------------5B1F217006A67C28E756A62E 20 | Content-Type: text/plain; charset=UTF-8; 21 | name="php://foo" 22 | Content-Transfer-Encoding: base64 23 | Content-Disposition: attachment; 24 | filename="php://foo" 25 | 26 | TXlGaWxlQ29udGVudA== 27 | --------------5B1F217006A67C28E756A62E-- 28 | -------------------------------------------------------------------------------- /tests/messages/issue-462.eml: -------------------------------------------------------------------------------- 1 | From: "postmaster@" 2 | To: receipent@receipent_domain.tld 3 | Subject: Undeliverable: Some subject 4 | 5 | Test message 6 | -------------------------------------------------------------------------------- /tests/messages/issue-511.eml: -------------------------------------------------------------------------------- 1 | From: COMPANYNAME | =?iso-8859-2?q?us=B3ugi?= 2 | To: receipent@receipent_domain.tld 3 | Subject: =?utf-8?B?UkU6IFtFWFRFUk5BTF0gUmU6IExvcmVtIElwc3VtIC8=?= =?utf-8?Q?40_one?= 4 | 5 | Test message 6 | -------------------------------------------------------------------------------- /tests/messages/ks_c_5601-1987_headers.eml: -------------------------------------------------------------------------------- 1 | Subject: =?ks_c_5601-1987?B?UkU6IMi4v/i01LKyIEVyc2m01MDMILjevcPB9rimILq4s8K9wLTP?= 2 | =?ks_c_5601-1987?B?tNku?= 3 | MIME-Version: 1.0 4 | Content-Type: text/plain 5 | Date: Wed, 27 Sep 2017 12:48:51 +0200 6 | Thread-Topic: =?ks_c_5601-1987?B?yLi/+LTUsrIgRXJzabTUwMwguN69w8H2uKYgurizwr3AtM+02S4=?= 7 | From: =?ks_c_5601-1987?B?seggx/bB+A==?= 8 | To: to@here.com 9 | 10 | Content 11 | -------------------------------------------------------------------------------- /tests/messages/mail_that_is_attachment.eml: -------------------------------------------------------------------------------- 1 | Sender: xxx@yyy.cz 2 | MIME-Version: 1.0 3 | Message-ID: <2244696771454641389@google.com> 4 | Date: Sun, 15 Feb 2015 10:21:51 +0000 5 | Subject: Report domain: yyy.cz Submitter: google.com Report-ID: 2244696771454641389 6 | From: noreply-dmarc-support via xxx 7 | To: xxx@yyy.cz 8 | Content-Type: application/zip; 9 | name="google.com!yyy.cz!1423872000!1423958399.zip" 10 | Content-Disposition: attachment; 11 | filename="google.com!yyy.cz!1423872000!1423958399.zip" 12 | Content-Transfer-Encoding: base64 13 | Reply-To: noreply-dmarc-support@google.com 14 | 15 | UEsDBAoAAAAIABRPT0bdJB+DSwIAALgKAAAuAAAAZ29vZ2xlLmNvbSFzdW5mb3guY3ohMTQyMzg3 16 | MjAwMCExNDIzOTU4Mzk5LnhtbO1WwY6bMBC971dEuQcDIQSQQ3rqF7RnZIwh7oJt2WY32a+viQ2h 17 | u9moqnarqOop8Gbmjd/4OQbuj127eCJSUc52y8DzlwvCMK8oa3bL79++rpLlYp8/wJqQqkT4MX9Y 18 | LKAkgktddESjCmk0YAblsikY6kjecN60xMO8g2ACbQ7pEG1zxg1De1pVHZJ4pXox0H2Zl9k8V3PU 19 | EhWYM42wLiireX7QWmQAuErvUgkQKCkDiKlnIj1x2tunXRjF8SbxDfFbMtvFaaJVHoZRFKfxdhtE 20 | myiOgnWSQnAJ23SjmxQSscYpM1BJGsryIArXyTb0fdPMImOcsOocTTfJOjWUw7slA7+yTd3mA4aC 21 | txSfCtGXLVUHMi2Em1GxXPVGytHDL4bMIjaMqkfa5RIC++BAJeozNvxaSOSS/CBYQyAcoi6QGjGB 22 | dR4MyoaH80qvrcrMEnM5LlDy52kEivcSk4KKPIz9bVYnpZ9Fvr/OsB9kWbgOTa8pZSzCvGemLQT2 23 | YYRdZ/KE2t6MrxoDw0yoElxRbTxtvMaImckMmeUNIxFIKZMwTceJr11gGtFM7aueZr9GjZBWhGla 24 | U3OiprIDQRWRRS15N9+nOex43lRD1OtDIYnqW30hfLXY2xZw7h4YnCT3Mqma08GZ3g+gvhgMvFYy 25 | JI82+R3HpL4XbDdesIm84SB/tE9Gr99wSm3+k646xQbu0Sl/uptW0Sfu5tXzH6b3dP7vd1f/+vl/ 26 | KU83eRnpzbX6uY5JzMeJZ25PLwji920S/r8m/tVrAoLLR+hPUEsBAgoACgAAAAgAFE9PRt0kH4NL 27 | AgAAuAoAAC4AAAAAAAAAAAAAAAAAAAAAAGdvb2dsZS5jb20hc3VuZm94LmN6ITE0MjM4NzIwMDAh 28 | MTQyMzk1ODM5OS54bWxQSwUGAAAAAAEAAQBcAAAAlwIAAAAA -------------------------------------------------------------------------------- /tests/messages/missing_date.eml: -------------------------------------------------------------------------------- 1 | From: from@here.com 2 | To: to@here.com 3 | Subject: Nuu 4 | Content-Type: text/plain; charset="us-ascii" 5 | Content-Transfer-Encoding: quoted-printable 6 | 7 | Hi 8 | -------------------------------------------------------------------------------- /tests/messages/missing_from.eml: -------------------------------------------------------------------------------- 1 | To: to@here.com 2 | Subject: Nuu 3 | Date: Wed, 13 Sep 2017 13:05:45 +0200 4 | Content-Type: text/plain; charset="us-ascii" 5 | Content-Transfer-Encoding: quoted-printable 6 | 7 | Hi 8 | -------------------------------------------------------------------------------- /tests/messages/mixed_filename.eml: -------------------------------------------------------------------------------- 1 | Date: Fri, 02 Feb 2018 22:23:06 +0300 2 | To: foo@bar.com 3 | Subject: =?windows-1251?B?0eLl5ujpIO/w4OnxLevo8fI=?= 4 | From: =?windows-1251?B?z/Dg6fH7IHx8IM/g8PLK7uw=?= 5 | Content-Transfer-Encoding: quoted-printable 6 | Content-Type: multipart/mixed; 7 | boundary="=_743251f7a933f6b30c004fcb14eabb57" 8 | Content-Disposition: inline 9 | 10 | This is a message in Mime Format. If you see this, your mail reader does not support this format. 11 | 12 | --=_743251f7a933f6b30c004fcb14eabb57 13 | Content-Type: text/html; charset=windows-1251 14 | Content-Transfer-Encoding: quoted-printable 15 | Content-Disposition: inline 16 | 17 | 18 | --=_743251f7a933f6b30c004fcb14eabb57 19 | Content-Type: application/octet-stream 20 | Content-Transfer-Encoding: base64 21 | Content-Disposition: attachment; filename="Price4VladDaKar.xlsx" 22 | 23 | UEsDBBQAAgAIAHOyQkwNlxQhWwEAAAYFAAATAAAAW0NvbnRlbnRfVHlwZXNdLnhtbK2UTU7D 24 | CwALANECAAAT1E4AAAA= 25 | --=_743251f7a933f6b30c004fcb14eabb57-- 26 | -------------------------------------------------------------------------------- /tests/messages/multiple_nested_attachments.eml: -------------------------------------------------------------------------------- 1 | Date: Mon, 15 Jan 2018 10:54:09 +0100 2 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 3 | Thunderbird/52.5.0 4 | MIME-Version: 1.0 5 | Content-Type: multipart/mixed; 6 | boundary="------------85793CE1578A77318D5A90A6" 7 | Content-Language: en-US 8 | 9 | This is a multi-part message in MIME format. 10 | --------------85793CE1578A77318D5A90A6 11 | Content-Type: multipart/alternative; 12 | boundary="------------32D598A7FC3F8A8E228998B0" 13 | 14 | 15 | --------------32D598A7FC3F8A8E228998B0 16 | Content-Type: text/plain; charset=utf-8; format=flowed 17 | Content-Transfer-Encoding: 7bit 18 | 19 | 20 | ------------------------------------------------------------------------ 21 | 22 | 23 | 24 | 25 | --------------32D598A7FC3F8A8E228998B0 26 | Content-Type: multipart/related; 27 | boundary="------------261DC39B47CFCDB73BCE3C18" 28 | 29 | 30 | --------------261DC39B47CFCDB73BCE3C18 31 | Content-Type: text/html; charset=utf-8 32 | Content-Transfer-Encoding: 8bit 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |


41 |

42 |
43 | 44 | 45 | Â 46 |
47 | 48 | 49 | 50 | 52 | 54 | 55 | 56 |

51 |

53 |
57 |
58 | 59 | 60 | 61 | --------------261DC39B47CFCDB73BCE3C18 62 | Content-Type: image/png; 63 | name="mleokdgdlgkkecep.png" 64 | Content-Transfer-Encoding: base64 65 | Content-ID: 66 | Content-Disposition: inline; 67 | filename="mleokdgdlgkkecep.png" 68 | 69 | iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAACklE 70 | QVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg== 71 | --------------261DC39B47CFCDB73BCE3C18-- 72 | 73 | --------------32D598A7FC3F8A8E228998B0-- 74 | 75 | --------------85793CE1578A77318D5A90A6 76 | Content-Type: image/png; 77 | name="FF4D00-1.png" 78 | Content-Transfer-Encoding: base64 79 | Content-Disposition: attachment; 80 | filename="FF4D00-1.png" 81 | 82 | iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAACklE 83 | QVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg== 84 | --------------85793CE1578A77318D5A90A6-- -------------------------------------------------------------------------------- /tests/messages/null_content_charset.eml: -------------------------------------------------------------------------------- 1 | Subject: test 2 | MIME-Version: 1.0 3 | Content-Type: text/plain 4 | Date: Wed, 27 Sep 2017 12:48:51 +0200 5 | From: from@there.com 6 | To: to@here.com 7 | 8 | Hi! -------------------------------------------------------------------------------- /tests/messages/pec.eml: -------------------------------------------------------------------------------- 1 | To: test@example.com 2 | From: test@example.com 3 | Subject: Certified 4 | Date: Mon, 2 Oct 2017 12:13:43 +0200 5 | Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha1"; boundary="----258A05BDE519DE69AAE8D59024C32F5E" 6 | 7 | This is an S/MIME signed message 8 | 9 | ------258A05BDE519DE69AAE8D59024C32F5E 10 | Content-Type: multipart/mixed; boundary="----------=_1506939223-24530-42" 11 | Content-Transfer-Encoding: binary 12 | 13 | ------------=_1506939223-24530-42 14 | Content-Type: multipart/alternative; 15 | boundary="----------=_1506939223-24530-43" 16 | Content-Transfer-Encoding: binary 17 | 18 | ------------=_1506939223-24530-43 19 | Content-Type: text/plain; charset="iso-8859-1" 20 | Content-Disposition: inline 21 | Content-Transfer-Encoding: quoted-printable 22 | 23 | Signed 24 | 25 | ------------=_1506939223-24530-43 26 | Content-Type: text/html; charset="iso-8859-1" 27 | Content-Disposition: inline 28 | Content-Transfer-Encoding: quoted-printable 29 | 30 | Signed 31 | 32 | ------------=_1506939223-24530-43-- 33 | 34 | ------------=_1506939223-24530-42 35 | Content-Type: application/xml; name="data.xml" 36 | Content-Disposition: inline; filename="data.xml" 37 | Content-Transfer-Encoding: base64 38 | 39 | PHhtbC8+ 40 | 41 | ------------=_1506939223-24530-42 42 | Content-Type: message/rfc822; name="postacert.eml" 43 | Content-Disposition: inline; filename="postacert.eml" 44 | Content-Transfer-Encoding: 7bit 45 | 46 | To: test@example.com 47 | From: test@example.com 48 | Subject: test-subject 49 | Date: Mon, 2 Oct 2017 12:13:50 +0200 50 | Content-Type: text/plain; charset=iso-8859-15; format=flowed 51 | Content-Transfer-Encoding: 7bit 52 | 53 | test-content 54 | 55 | ------------=_1506939223-24530-42-- 56 | 57 | ------258A05BDE519DE69AAE8D59024C32F5E 58 | Content-Type: application/x-pkcs7-signature; name="smime.p7s" 59 | Content-Transfer-Encoding: base64 60 | Content-Disposition: attachment; filename="smime.p7s" 61 | 62 | MQ== 63 | 64 | ------258A05BDE519DE69AAE8D59024C32F5E-- 65 | 66 | -------------------------------------------------------------------------------- /tests/messages/plain.eml: -------------------------------------------------------------------------------- 1 | From: from@someone.com 2 | To: to@someone-else.com 3 | Subject: Example 4 | Date: Mon, 21 Jan 2023 19:36:45 +0200 5 | Content-Type: text/plain; 6 | charset=\"us-ascii\" 7 | Content-Transfer-Encoding: quoted-printable 8 | 9 | Hi there! -------------------------------------------------------------------------------- /tests/messages/plain_only.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: Nuu 4 | Date: Wed, 13 Sep 2017 13:05:45 +0200 5 | Content-Type: text/plain; 6 | charset="us-ascii" 7 | Content-Transfer-Encoding: quoted-printable 8 | 9 | Hi -------------------------------------------------------------------------------- /tests/messages/plain_text_attachment.eml: -------------------------------------------------------------------------------- 1 | To: to@here.com 2 | From: from@there.com 3 | Subject: Plain text attachment 4 | Date: Tue, 21 Aug 2018 09:05:14 +0200 5 | MIME-Version: 1.0 6 | Content-Type: multipart/mixed; 7 | boundary="------------B832AF745285AEEC6D5AEE42" 8 | 9 | This is a multi-part message in MIME format. 10 | --------------B832AF745285AEEC6D5AEE42 11 | Content-Type: text/plain; charset=iso-8859-15; format=flowed 12 | Content-Transfer-Encoding: 7bit 13 | 14 | Test 15 | --------------B832AF745285AEEC6D5AEE42 16 | Content-Transfer-Encoding: base64 17 | Content-Disposition: attachment; 18 | filename="a.txt" 19 | 20 | SGkh 21 | --------------B832AF745285AEEC6D5AEE42-- 22 | -------------------------------------------------------------------------------- /tests/messages/references.eml: -------------------------------------------------------------------------------- 1 | Message-ID: <123@example.com> 2 | From: no_host 3 | Cc: "This one: is \"right\"" , No-address 4 | In-Reply-To: 5 | References: <231d9ac57aec7d8c1a0eacfeab8af6f3@example.com> <08F04024-A5B3-4FDE-BF2C-6710DE97D8D9@example.com> 6 | Content-Type: text/plain; 7 | charset="us-ascii" 8 | Content-Transfer-Encoding: quoted-printable 9 | 10 | Hi 11 | How are you? 12 | -------------------------------------------------------------------------------- /tests/messages/simple_multipart.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Date: Wed, 27 Sep 2017 12:48:51 +0200 4 | Subject: test 5 | Content-Type: multipart/alternative; 6 | boundary="----=_NextPart_000_0081_01D32C91.033E7020" 7 | 8 | This is a multipart message in MIME format. 9 | 10 | ------=_NextPart_000_0081_01D32C91.033E7020 11 | Content-Type: text/plain; 12 | charset="us-ascii" 13 | Content-Transfer-Encoding: 7bit 14 | 15 | MyPlain 16 | ------=_NextPart_000_0081_01D32C91.033E7020 17 | Content-Type: text/html; 18 | charset="us-ascii" 19 | Content-Transfer-Encoding: quoted-printable 20 | 21 | MyHtml 22 | ------=_NextPart_000_0081_01D32C91.033E7020-- 23 | 24 | -------------------------------------------------------------------------------- /tests/messages/structured_with_attachment.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: Test 4 | Date: Fri, 29 Sep 2017 10:55:23 +0200 5 | MIME-Version: 1.0 6 | Content-Type: multipart/mixed; 7 | boundary="------------5B1F217006A67C28E756A62E" 8 | 9 | This is a multi-part message in MIME format. 10 | --------------5B1F217006A67C28E756A62E 11 | Content-Type: text/plain; charset=iso-8859-15; format=flowed 12 | Content-Transfer-Encoding: 7bit 13 | 14 | Test 15 | 16 | --------------5B1F217006A67C28E756A62E 17 | Content-Type: text/plain; charset=UTF-8; 18 | name="MyFile.txt" 19 | Content-Transfer-Encoding: base64 20 | Content-Disposition: attachment; 21 | filename="MyFile.txt" 22 | 23 | TXlGaWxlQ29udGVudA== 24 | --------------5B1F217006A67C28E756A62E-- 25 | -------------------------------------------------------------------------------- /tests/messages/thread_my_topic.eml: -------------------------------------------------------------------------------- 1 | Message-ID: <123@example.com> 2 | From: from@there.com 3 | To: to@here.com 4 | Subject: Nuu 5 | Date: Wed, 13 Sep 2017 13:05:45 +0200 6 | Content-Type: text/plain; 7 | charset="us-ascii" 8 | Content-Transfer-Encoding: quoted-printable 9 | 10 | Hi 11 | -------------------------------------------------------------------------------- /tests/messages/thread_re_my_topic.eml: -------------------------------------------------------------------------------- 1 | Message-ID: <456@example.com> 2 | In-Reply-To: <123@example.com> 3 | From: from@there.com 4 | To: to@here.com 5 | Subject: Re: Nuu 6 | Date: Wed, 13 Sep 2017 13:05:45 +0200 7 | Content-Type: text/plain; 8 | charset="us-ascii" 9 | Content-Transfer-Encoding: quoted-printable 10 | 11 | Hi 12 | -------------------------------------------------------------------------------- /tests/messages/thread_unrelated.eml: -------------------------------------------------------------------------------- 1 | Message-ID: <999@example.com> 2 | From: from@there.com 3 | To: to@here.com 4 | Subject: Wut 5 | Date: Wed, 13 Sep 2017 13:05:45 +0200 6 | Content-Type: text/plain; 7 | charset="us-ascii" 8 | Content-Transfer-Encoding: quoted-printable 9 | 10 | Hi 11 | -------------------------------------------------------------------------------- /tests/messages/undefined_charset_header.eml: -------------------------------------------------------------------------------- 1 | X-Real-To: 2 | X-Stored-In: BlaBla 3 | Return-Path: 4 | Received: from 5 | by bla.bla (CommuniGate Pro RULE 6.1.13) 6 | with RULE id 14057804; Mon, 27 Feb 2017 13:21:44 +0930 7 | X-Autogenerated: Mirror 8 | Resent-From: 9 | Resent-Date: Mon, 27 Feb 2017 13:21:44 +0930 10 | Message-Id: <201702270351.BGF77614@bla.bla> 11 | From: =?X-IAS-German?B?bXlHb3Y=?= 12 | To: sales@bla.bla 13 | Subject: =?X-IAS-German?B?U3VibWl0IHlvdXIgdGF4IHJlZnVuZCB8IEF1c3RyYWxpYW4gVGF4YXRpb24gT2ZmaWNlLg==?= 14 | Date: 27 Feb 2017 04:51:29 +0100 15 | MIME-Version: 1.0 16 | Content-Type: text/html; 17 | charset="iso-8859-1" 18 | Content-Transfer-Encoding: quoted-printable 19 | 20 | ) -------------------------------------------------------------------------------- /tests/messages/undisclosed_recipients.eml: -------------------------------------------------------------------------------- 1 | Subject: test 2 | MIME-Version: 1.0 3 | Content-Type: text/plain 4 | Date: Wed, 27 Sep 2017 12:48:51 +0200 5 | From: from@there.com 6 | To: "Undisclosed Recipients" <> 7 | 8 | Hi! 9 | -------------------------------------------------------------------------------- /tests/messages/undisclosed_recipients_minus.eml: -------------------------------------------------------------------------------- 1 | Subject: test 2 | MIME-Version: 1.0 3 | Content-Type: text/plain 4 | Date: Wed, 27 Sep 2017 12:48:51 +0200 5 | From: from@there.com 6 | To: undisclosed-recipients:; 7 | 8 | Hi! 9 | -------------------------------------------------------------------------------- /tests/messages/undisclosed_recipients_space.eml: -------------------------------------------------------------------------------- 1 | Subject: test 2 | MIME-Version: 1.0 3 | Content-Type: text/plain 4 | Date: Wed, 27 Sep 2017 12:48:51 +0200 5 | From: from@there.com 6 | To: Undisclosed recipients:; 7 | 8 | Hi! 9 | -------------------------------------------------------------------------------- /tests/messages/unknown_encoding.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Date: Wed, 27 Sep 2017 12:48:51 +0200 4 | Subject: test 5 | Content-Type: multipart/alternative; 6 | boundary="----=_NextPart_000_0081_01D32C91.033E7020" 7 | 8 | This is a multipart message in MIME format. 9 | 10 | ------=_NextPart_000_0081_01D32C91.033E7020 11 | Content-Type: text/plain; 12 | charset= 13 | Content-Transfer-Encoding: foobar 14 | 15 | MyPlain 16 | 17 | ------=_NextPart_000_0081_01D32C91.033E7020 18 | Content-Type: text/html; 19 | charset="" 20 | Content-Transfer-Encoding: quoted-printable 21 | 22 | MyHtml 23 | ------=_NextPart_000_0081_01D32C91.033E7020-- 24 | 25 | -------------------------------------------------------------------------------- /tests/messages/without_charset_plain_only.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Subject: Nuu 4 | Date: Wed, 13 Sep 2017 13:05:45 +0200 5 | Content-Type: text/plain; charset= 6 | Content-Transfer-Encoding: quoted-printable 7 | 8 | Hi -------------------------------------------------------------------------------- /tests/messages/without_charset_simple_multipart.eml: -------------------------------------------------------------------------------- 1 | From: from@there.com 2 | To: to@here.com 3 | Date: Wed, 27 Sep 2017 12:48:51 +0200 4 | Subject: test 5 | Content-Type: multipart/alternative; 6 | boundary="----=_NextPart_000_0081_01D32C91.033E7020" 7 | 8 | This is a multipart message in MIME format. 9 | 10 | ------=_NextPart_000_0081_01D32C91.033E7020 11 | Content-Type: text/plain; 12 | charset= 13 | Content-Transfer-Encoding: 7bit 14 | 15 | MyPlain 16 | ------=_NextPart_000_0081_01D32C91.033E7020 17 | Content-Type: text/html; 18 | charset="" 19 | Content-Transfer-Encoding: quoted-printable 20 | 21 | MyHtml 22 | ------=_NextPart_000_0081_01D32C91.033E7020-- 23 | 24 | --------------------------------------------------------------------------------