Vendor packages updated
This commit is contained in:
21
vendor/phpmailer/phpmailer/.codecov.yml
vendored
21
vendor/phpmailer/phpmailer/.codecov.yml
vendored
@@ -1,21 +0,0 @@
|
||||
codecov:
|
||||
notify:
|
||||
after_n_builds: 2
|
||||
|
||||
coverage:
|
||||
round: nearest
|
||||
# Status will be green when coverage is between 70 and 100%.
|
||||
range: "70...100"
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
threshold: 2%
|
||||
paths:
|
||||
- "src"
|
||||
patch:
|
||||
default:
|
||||
threshold: 0%
|
||||
paths:
|
||||
- "src"
|
||||
|
||||
comment: false
|
||||
15
vendor/phpmailer/phpmailer/.editorconfig
vendored
15
vendor/phpmailer/phpmailer/.editorconfig
vendored
@@ -1,15 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
16
vendor/phpmailer/phpmailer/.gitattributes
vendored
16
vendor/phpmailer/phpmailer/.gitattributes
vendored
@@ -1,16 +0,0 @@
|
||||
* text=auto
|
||||
|
||||
/.codecov.yml export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.github export-ignore
|
||||
/.gitignore export-ignore
|
||||
/.phan export-ignore
|
||||
/.scrutinizer.yml export-ignore
|
||||
/changelog.md export-ignore
|
||||
/docs export-ignore
|
||||
/examples export-ignore
|
||||
/phpcs.xml.dist export-ignore
|
||||
/phpdoc.dist.xml export-ignore
|
||||
/phpunit.xml.dist export-ignore
|
||||
/test export-ignore
|
||||
/UPGRADING.md export-ignore
|
||||
@@ -1,6 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: Synchro
|
||||
patreon: marcusbointon
|
||||
tidelift: "packagist/phpmailer/phpmailer"
|
||||
custom: https://marcus.bointon.com/donations/
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: If you've found a bug in PHPMailer, this is the right place to report it
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please check these things before submitting your issue:
|
||||
|
||||
- [ ] *Read the error message* you're seeing - it often tells you what is wrong, and may contain useful links & instructions
|
||||
- [ ] Make sure you're using the latest version of PHPMailer
|
||||
- [ ] Check that your problem is not dealt with in [the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting), especially if you're having problems connecting to Gmail or GoDaddy
|
||||
- [ ] Include sufficient code to reproduce your problem
|
||||
- [ ] If you're having an SMTP issue, include the debug output generated with `SMTPDebug = 2` set
|
||||
- [ ] If you have a question about how to use PHPMailer (rather than reporting a bug in it), tag a question on Stack Overflow with `phpmailer`, but [**search first**](https://stackoverflow.com/questions/tagged/phpmailer)!
|
||||
|
||||
# Problem description
|
||||
|
||||
# Code to reproduce
|
||||
|
||||
# Debug output
|
||||
@@ -1,15 +0,0 @@
|
||||
FROM phpdoc/phpdoc
|
||||
|
||||
LABEL "repository"="https://github.com/PHPMailer/PHPMailer"
|
||||
|
||||
LABEL "com.github.actions.name"="Build Docs"
|
||||
LABEL "com.github.actions.description"="Build Docs with phpDocumentor"
|
||||
LABEL "com.github.actions.icon"="file-text"
|
||||
LABEL "com.github.actions.color"="blue"
|
||||
|
||||
# don't show errors
|
||||
RUN echo "display_errors = Off" > $PHP_INI_DIR/conf.d/errors.ini
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
/opt/phpdoc/bin/phpdoc
|
||||
@@ -1,14 +0,0 @@
|
||||
# Dependabot configuration.
|
||||
#
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 5
|
||||
commit-message:
|
||||
prefix: "GH Actions:"
|
||||
@@ -1,29 +0,0 @@
|
||||
name: Docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
permissions: {}
|
||||
jobs:
|
||||
build_and_publish:
|
||||
permissions:
|
||||
contents: write # to push changes in repo (jamesives/github-pages-deploy-action)
|
||||
|
||||
name: Build and publish Docs
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'PHPMailer/PHPMailer'
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Build Docs
|
||||
uses: ./.github/actions/build-docs
|
||||
- name: Publish Docs to gh-pages
|
||||
uses: JamesIves/github-pages-deploy-action@v4
|
||||
with:
|
||||
branch: gh-pages
|
||||
folder: docs
|
||||
env:
|
||||
BUILD_DIR: docs/
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
@@ -1,62 +0,0 @@
|
||||
name: Scorecards supply-chain security
|
||||
on:
|
||||
# Only the default branch is supported.
|
||||
branch_protection_rule:
|
||||
schedule:
|
||||
- cron: '39 20 * * 1'
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
# Declare default permission as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Used to receive a badge. (Upcoming feature)
|
||||
id-token: write
|
||||
# Needs for private repositories.
|
||||
contents: read
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:
|
||||
# - you want to enable the Branch-Protection check on a *public* repository, or
|
||||
# - you are installing Scorecards on a *private* repository
|
||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
|
||||
# repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
|
||||
|
||||
# Publish the results for public repositories to enable scorecard badges. For more details, see
|
||||
# https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories, `publish_results` will automatically be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -1,222 +0,0 @@
|
||||
name: "Tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
# Allow manually triggering the workflow.
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
|
||||
coding-standard:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Coding standards
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 'latest'
|
||||
coverage: none
|
||||
tools: cs2pr
|
||||
|
||||
# Install dependencies and handle caching in one go.
|
||||
# @link https://github.com/marketplace/actions/install-php-dependencies-with-composer
|
||||
- name: Install Composer dependencies
|
||||
uses: "ramsey/composer-install@v3"
|
||||
with:
|
||||
# Bust the cache at least once a month - output format: YYYY-MM.
|
||||
custom-cache-suffix: $(date -u "+%Y-%m")
|
||||
|
||||
- name: Check coding standards
|
||||
id: phpcs
|
||||
run: ./vendor/bin/phpcs -s --report-full --report-checkstyle=./phpcs-report.xml
|
||||
|
||||
- name: Show PHPCS results in PR
|
||||
if: ${{ always() && steps.phpcs.outcome == 'failure' }}
|
||||
run: cs2pr ./phpcs-report.xml
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
php: ['5.5', '7.2', '8.0', '8.4']
|
||||
experimental: [false]
|
||||
include:
|
||||
- php: '8.5'
|
||||
experimental: true
|
||||
|
||||
name: "Lint: PHP ${{ matrix.php }}"
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
coverage: none
|
||||
tools: cs2pr
|
||||
|
||||
# Install dependencies and handle caching in one go.
|
||||
# @link https://github.com/marketplace/actions/install-php-dependencies-with-composer
|
||||
- name: Install Composer dependencies
|
||||
uses: "ramsey/composer-install@v3"
|
||||
with:
|
||||
# Bust the cache at least once a month - output format: YYYY-MM.
|
||||
custom-cache-suffix: $(date -u "+%Y-%m")
|
||||
|
||||
- name: Lint against parse errors
|
||||
if: ${{ matrix.php != '8.5' }}
|
||||
run: composer lint -- --checkstyle | cs2pr
|
||||
|
||||
- name: Lint against future parse errors (PHP 8.5)
|
||||
if: ${{ matrix.php == '8.5' }}
|
||||
run: composer lint
|
||||
|
||||
test:
|
||||
needs: ['coding-standard', 'lint']
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
|
||||
extensions: ['optimal', 'minimal']
|
||||
coverage: [false]
|
||||
experimental: [false]
|
||||
include:
|
||||
# Run code coverage on high/low PHP.
|
||||
- php: '5.5'
|
||||
extensions: 'optimal'
|
||||
coverage: true
|
||||
experimental: false
|
||||
- php: '5.5'
|
||||
extensions: 'minimal'
|
||||
coverage: true
|
||||
experimental: false
|
||||
- php: '8.4'
|
||||
extensions: 'optimal'
|
||||
coverage: true
|
||||
experimental: false
|
||||
- php: '8.4'
|
||||
extensions: 'minimal'
|
||||
coverage: true
|
||||
experimental: false
|
||||
|
||||
# Experimental builds. These are allowed to fail.
|
||||
- php: '8.5'
|
||||
extensions: 'optimal'
|
||||
coverage: false
|
||||
experimental: true
|
||||
- php: '8.5'
|
||||
extensions: 'minimal'
|
||||
coverage: false
|
||||
experimental: true
|
||||
|
||||
name: "Test: PHP ${{ matrix.php }} - ${{ matrix.extensions }}"
|
||||
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# About the "extensions":
|
||||
#
|
||||
# In a "normal" test run, the "default" extension set for a PHP version is used
|
||||
# and it is ensured that certain extensions will be available, no matter what.
|
||||
#
|
||||
# For the "minimal" test run, all extensions are disabled and then only
|
||||
# a limited set of minimally required extensions are re-enabled.
|
||||
# The minimal set is based on the required extensions from PHPUnit + PHPMailer combined
|
||||
# + Curl for Composer.
|
||||
# Whether Xdebug will be enabled depends on the code coverage settings.
|
||||
#
|
||||
# Also see:
|
||||
# https://github.com/shivammathur/setup-php/?tab=readme-ov-file#heavy_plus_sign-php-extension-support
|
||||
# https://github.com/shivammathur/setup-php/wiki
|
||||
- name: Determine extensions to use
|
||||
id: set_extensions
|
||||
run: |
|
||||
if [[ "${{ matrix.extensions }}" == "optimal" ]]; then
|
||||
# Optimal.
|
||||
echo 'EXT=imap, mbstring, openssl, intl, ctype, filter, hash' >> $GITHUB_OUTPUT
|
||||
echo 'COMPOSER_OPTIONS=' >> $GITHUB_OUTPUT
|
||||
else
|
||||
# Minimal.
|
||||
echo 'EXT=none, curl, dom, json, libxml, mbstring, tokenizer, xml, xmlwriter, ctype, filter, hash' >> $GITHUB_OUTPUT
|
||||
echo 'COMPOSER_OPTIONS=--ignore-platform-req=ext-simplexml' >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
coverage: ${{ matrix.coverage && 'xdebug' || 'none' }}
|
||||
ini-values: sendmail_path=/usr/sbin/sendmail -t -i, error_reporting=E_ALL, display_errors=On
|
||||
extensions: ${{ steps.set_extensions.outputs.EXT }}
|
||||
|
||||
# Install dependencies and handle caching in one go.
|
||||
# @link https://github.com/marketplace/actions/install-php-dependencies-with-composer
|
||||
- name: Install PHP packages - normal
|
||||
if: ${{ matrix.php != '8.5' }}
|
||||
uses: "ramsey/composer-install@v3"
|
||||
with:
|
||||
composer-options: ${{ steps.set_extensions.outputs.COMPOSER_OPTIONS }}
|
||||
# Bust the cache at least once a month - output format: YYYY-MM.
|
||||
custom-cache-suffix: $(date -u "+%Y-%m")
|
||||
|
||||
- name: Install PHP packages - ignore-platform-reqs
|
||||
if: ${{ matrix.php == '8.5' }}
|
||||
uses: "ramsey/composer-install@v3"
|
||||
with:
|
||||
composer-options: --ignore-platform-reqs ${{ steps.set_extensions.outputs.COMPOSER_OPTIONS }}
|
||||
# Bust the cache at least once a month - output format: YYYY-MM.
|
||||
custom-cache-suffix: $(date -u "+%Y-%m")
|
||||
|
||||
# Install postfix and automatically retry if the install failed, which happens reguarly.
|
||||
# @link https://github.com/marketplace/actions/retry-step
|
||||
- name: Install postfix
|
||||
uses: nick-invision/retry@v3
|
||||
with:
|
||||
timeout_minutes: 2
|
||||
max_attempts: 3
|
||||
retry_wait_seconds: 8
|
||||
command: |
|
||||
sudo apt-get install --fix-broken -y libsqlite3-0 postfix
|
||||
sudo systemctl stop postfix.service
|
||||
|
||||
- name: Set up sendmail
|
||||
run: |
|
||||
smtp-sink -d "%d.%H.%M.%S" localhost:2500 1000 &
|
||||
mkdir -p build/logs
|
||||
sudo cp test/testbootstrap-dist.php test/testbootstrap.php
|
||||
sudo chmod +x test/fakesendmail.sh
|
||||
sudo mkdir -p /var/qmail/bin
|
||||
sudo cp test/fakesendmail.sh /var/qmail/bin/sendmail
|
||||
sudo cp test/fakesendmail.sh /usr/sbin/sendmail
|
||||
|
||||
- name: Run tests, no code coverage
|
||||
if: ${{ matrix.coverage == false }}
|
||||
run: ./vendor/bin/phpunit --no-coverage
|
||||
|
||||
- name: Run tests with code coverage
|
||||
if: ${{ matrix.coverage == true }}
|
||||
run: vendor/bin/phpunit
|
||||
|
||||
- name: Send coverage report to Codecov
|
||||
if: ${{ success() && matrix.coverage == true }}
|
||||
uses: codecov/codecov-action@v4
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
with:
|
||||
files: ./build/logs/clover.xml
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
16
vendor/phpmailer/phpmailer/.gitignore
vendored
16
vendor/phpmailer/phpmailer/.gitignore
vendored
@@ -1,16 +0,0 @@
|
||||
docs/*
|
||||
!docs/README.md
|
||||
test/message.txt
|
||||
test/testbootstrap.php
|
||||
build/
|
||||
vendor/
|
||||
*.pem
|
||||
composer.lock
|
||||
.phpcs.xml
|
||||
phpcs.xml
|
||||
.phpcs-cache
|
||||
/.rnd
|
||||
test/PHPMailerTest.php*nonexistent_file.txt
|
||||
test/*/PHPMailerTest.php*nonexistent_file.txt
|
||||
phpunit.xml
|
||||
/.phpunit.result.cache
|
||||
41
vendor/phpmailer/phpmailer/.phan/config.php
vendored
41
vendor/phpmailer/phpmailer/.phan/config.php
vendored
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This configuration will be read and overlaid on top of the
|
||||
* default configuration. Command line arguments will be applied
|
||||
* after this file is read.
|
||||
*/
|
||||
return [
|
||||
|
||||
// A list of directories that should be parsed for class and
|
||||
// method information. After excluding the directories
|
||||
// defined in exclude_analysis_directory_list, the remaining
|
||||
// files will be statically analyzed for errors.
|
||||
//
|
||||
// Thus, both first-party and third-party code being used by
|
||||
// your application should be included in this list.
|
||||
'directory_list' => [
|
||||
'src',
|
||||
'vendor',
|
||||
'examples'
|
||||
],
|
||||
|
||||
// A directory list that defines files that will be excluded
|
||||
// from static analysis, but whose class and method
|
||||
// information should be included.
|
||||
//
|
||||
// Generally, you'll want to include the directories for
|
||||
// third-party code (such as "vendor/") in this list.
|
||||
//
|
||||
// n.b.: If you'd like to parse but not analyze 3rd
|
||||
// party code, directories containing that code
|
||||
// should be added to the `directory_list` as
|
||||
// to `exclude_analysis_directory_list`.
|
||||
"exclude_analysis_directory_list" => [
|
||||
'vendor/'
|
||||
],
|
||||
|
||||
'skip_slow_php_options_warning' => true,
|
||||
|
||||
'exclude_file_regex' => '@^vendor/.*/(tests|Tests)/@',
|
||||
];
|
||||
17
vendor/phpmailer/phpmailer/README.md
vendored
17
vendor/phpmailer/phpmailer/README.md
vendored
@@ -20,25 +20,26 @@
|
||||
- Multipart/alternative emails for mail clients that do not read HTML email
|
||||
- Add attachments, including inline
|
||||
- Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings
|
||||
- SMTP authentication with LOGIN, PLAIN, CRAM-MD5, and XOAUTH2 mechanisms over SMTPS and SMTP+STARTTLS transports
|
||||
- Full UTF-8 support when using servers that support `SMTPUTF8`.
|
||||
- Support for iCal events in multiparts and attachments
|
||||
- SMTP authentication with `LOGIN`, `PLAIN`, `CRAM-MD5`, and `XOAUTH2` mechanisms over SMTPS and SMTP+STARTTLS transports
|
||||
- Validates email addresses automatically
|
||||
- Protects against header injection attacks
|
||||
- Error messages in over 50 languages!
|
||||
- DKIM and S/MIME signing support
|
||||
- Compatible with PHP 5.5 and later, including PHP 8.2
|
||||
- Compatible with PHP 5.5 and later, including PHP 8.4
|
||||
- Namespaced to prevent name clashes
|
||||
- Much more!
|
||||
|
||||
## Why you might need it
|
||||
Many PHP developers need to send email from their code. The only PHP function that supports this directly is [`mail()`](https://www.php.net/manual/en/function.mail.php). However, it does not provide any assistance for making use of popular features such as encryption, authentication, HTML messages, and attachments.
|
||||
Many PHP developers need to send email from their code. The only PHP function that supports this directly is [`mail()`](https://www.php.net/manual/en/function.mail.php). However, it does not provide any assistance for making use of popular features such as authentication, HTML messages, and attachments.
|
||||
|
||||
Formatting email correctly is surprisingly difficult. There are myriad overlapping (and conflicting) standards, requiring tight adherence to horribly complicated formatting and encoding rules – the vast majority of code that you'll find online that uses the `mail()` function directly is just plain wrong, if not unsafe!
|
||||
|
||||
The PHP `mail()` function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD, and macOS platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP client allows email sending on all platforms without needing a local mail server. Be aware though, that the `mail()` function should be avoided when possible; it's both faster and [safer](https://exploitbox.io/paper/Pwning-PHP-Mail-Function-For-Fun-And-RCE.html) to use SMTP to localhost.
|
||||
|
||||
*Please* don't be tempted to do it yourself – if you don't use PHPMailer, there are many other excellent libraries that
|
||||
you should look at before rolling your own. Try [SwiftMailer](https://swiftmailer.symfony.com/)
|
||||
, [Laminas/Mail](https://docs.laminas.dev/laminas-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail), etc.
|
||||
you should look at before rolling your own. Try [Symfony Mailer](https://symfony.com/doc/current/mailer.html), [Laminas/Mail](https://docs.laminas.dev/laminas-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail), etc.
|
||||
|
||||
## License
|
||||
This software is distributed under the [LGPL 2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) license, along with the [GPL Cooperation Commitment](https://gplcc.github.io/gplcc/). Please read [LICENSE](https://github.com/PHPMailer/PHPMailer/blob/master/LICENSE) for information on the software availability and distribution.
|
||||
@@ -47,7 +48,7 @@ This software is distributed under the [LGPL 2.1](https://www.gnu.org/licenses/o
|
||||
PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file:
|
||||
|
||||
```json
|
||||
"phpmailer/phpmailer": "^6.9.2"
|
||||
"phpmailer/phpmailer": "^6.12.0"
|
||||
```
|
||||
|
||||
or run
|
||||
@@ -74,7 +75,7 @@ require 'path/to/PHPMailer/src/PHPMailer.php';
|
||||
require 'path/to/PHPMailer/src/SMTP.php';
|
||||
```
|
||||
|
||||
If you're not using the `SMTP` class explicitly (you're probably not), you don't need a `use` line for the SMTP class. Even if you're not using exceptions, you do still need to load the `Exception` class as it is used internally.
|
||||
If you're not using the `SMTP` class explicitly (you're probably not), you don't need a `use` line for it. Even if you're not using exceptions, you do still need to load the `Exception` class as it is used internally.
|
||||
|
||||
## Legacy versions
|
||||
PHPMailer 5.2 (which is compatible with PHP 5.0 — 7.0) is no longer supported, even for security updates. You will find the latest version of 5.2 in the [5.2-stable branch](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable). If you're using PHP 5.5 or later (which you should be), switch to the 6.x releases.
|
||||
@@ -95,7 +96,7 @@ use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
//Load Composer's autoloader
|
||||
//Load Composer's autoloader (created by composer, not included with PHPMailer)
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
//Create an instance; passing `true` enables exceptions
|
||||
|
||||
48
vendor/phpmailer/phpmailer/SMTPUTF8.md
vendored
Normal file
48
vendor/phpmailer/phpmailer/SMTPUTF8.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# A short history of UTF-8 in email
|
||||
|
||||
## Background
|
||||
|
||||
For most of its existence, SMTP has been a 7-bit channel, only supporting US-ASCII characters. This has been a problem for many languages, especially those that use non-Latin scripts, and has led to the development of various workarounds.
|
||||
|
||||
The first major improvement, introduced in 1994 in [RFC 1652](https://www.rfc-editor.org/rfc/rfc1652) and extended in 2011 in [RFC 6152](https://www.rfc-editor.org/rfc/rfc6152), was the addition of the `8BITMIME` SMTP extension, which allowed raw 8-bit data to be included in message bodies sent over SMTP.
|
||||
This allowed the message *contents* to contain 8-bit data, including things like UTF-8 text, even though the SMTP protocol itself was still firmly 7-bit. This worked by having the server switch to 8-bit after the headers, and then back to 7-bit after the completion of a `DATA` command.
|
||||
|
||||
From 1996, messages could support [RFC 2047 encoding](https://www.rfc-editor.org/rfc/rfc2047), which permitted inserting characters from any character set into header *values* (but not names), but only by encoding them in somewhat unreadable ways to allow them to survive passage through a 7-bit channel. An example with a subject of "Schrödinger's cat" would be:
|
||||
|
||||
```
|
||||
Subject: =?utf-8?Q=Schr=C3=B6dinger=92s_Cat?=
|
||||
```
|
||||
|
||||
Here the accented `ö` is encoded as `=C3=B6`, which is the UTF-8 encoding of the 2-byte character, and the whole thing is wrapped in `=?utf-8?Q?` to indicate that it uses the UTF-8 charset and `quoted-printable` encoding. This is a bit of a hack, and not very human-friendly, but it works.
|
||||
|
||||
Similarly, 8-bit message bodies could be encoded using the same `quoted-printable` and `base64` content transfer encoding (CTE) schemes, which preserved the 8-bit content while encoding it in a format that could survive transmission through a 7-bit channel.
|
||||
|
||||
Domain names were originally also stuck in a 7-bit world, actually even more constrained to only a subset of the US-ASCII character set. But of course, many people want to have domains in their own language/script. Internationalized domain name (IDN) permitted this, using yet another complex encoding scheme called punycode, defined for domain names in 2003 in [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492). This finally allowed the domain part (after the `@`) of email addresses to contain UTF-8, though it was actually an illusion preserved by email client applications. For example, an address of
|
||||
`user@café.example.com` translates to
|
||||
`user@xn--caf-dma.example.com` in punycode, rendering it mostly unreadable, but 7-bit friendly, and remaining compatible with email clients that don't know about IDN.
|
||||
|
||||
The one remaining part of email that could not handle UTF-8 is the local part of email addresses (the part before the `@`).
|
||||
|
||||
I've only mentioned UTF-8 here, but most of these approaches also allowed other character sets that were popular, such as [the ISO-8859 family](https://en.wikipedia.org/wiki/ISO/IEC_8859). However, UTF-8 solves so many problems that these other character sets are gradually falling out of favour, as UTF-8 can support all languages.
|
||||
|
||||
This patchwork of overlapping approaches has served us well, but we have to admit that it's a mess.
|
||||
|
||||
## SMTPUTF8
|
||||
|
||||
`SMTPUTF8` is another SMTP extension, defined in [RFC 6531](https://www.rfc-editor.org/rfc/rfc6531) in 2012. This essentially solves the whole problem, allowing the entire SMTP conversation — commands, headers, and message bodies — to be sent in raw, unencoded UTF-8.
|
||||
|
||||
But there's a problem with this approach: adoption. If you send a UTF-8 message to a recipient whose mail server doesn't support this format, the sender has to somehow downgrade the message to make it survive a transition to 7-bit. This is a hard problem to solve, especially since there is no way to make a 7-bit system support UTF-8 in the local parts of addresses. This downgrade problem is what held up the adoption of `SMTPUTF8` in PHPMailer for many years, but in that time the *de facto* approach has become to simply fail in that situation, and tell the recipient it's time they upgraded their mail server 😅.
|
||||
|
||||
The vast majority of large email providers (gmail, Yahoo, Microsoft, etc), mail servers (postfix, exim, IIS, etc), and mail clients (Apple Mail, Outlook, Thunderbird, etc) now all support SMTPUTF8, so the need for backward compatibility is no longer what it was.
|
||||
|
||||
## SMTPUTF8 in PHPMailer
|
||||
|
||||
Several other PHP email libraries have implemented a halfway solution to `SMTPUTF8`, adding only the ability to support UTF-8 in email addresses, not elsewhere in the protocol. I wanted PHPMailer to do it "the right way", and this has taken much longer. PHPMailer now supports UTF-8 everywhere, and does not need to use transfer or header encodings for UTF-8 text when connecting to an `SMTPUTF8`-capable mail server.
|
||||
|
||||
This support is handled automatically: if you add an email address that requires UTF-8, PHPMailer will use UTF-8 for everything. If not, it will fall back to 7-bit and encode the message as necessary.
|
||||
|
||||
The one place you will need to be careful is in the selection of the address validator. By default, PHPMailer uses PHP's built-in `filter_var` validator, which does not allow UTF-8 email addresses. When PHPMailer spots that you have submitted a UTF-8 address, but have not altered the default validator, it will automatically switch to using a UTF-8-compatible validator. As soon as you do this, any SMTP connection you make will *require* that the server you connect to supports `SMTPUTF8`. You can select this validator explicitly by setting `PHPMailer::$validator = 'eai'` (an acronym for Email Address Internationalization).
|
||||
|
||||
### Postfix gotcha
|
||||
|
||||
Postfix has supported `SMTPUTF8` for a long time, but it has a peculiarity that it does not always advertise that it does so. However, rather surprisingly, if you use UTF-8 in the conversation, it will work anyway.
|
||||
125
vendor/phpmailer/phpmailer/UPGRADING.md
vendored
125
vendor/phpmailer/phpmailer/UPGRADING.md
vendored
@@ -1,125 +0,0 @@
|
||||
# Upgrading from PHPMailer 5.2 to 6.0
|
||||
|
||||
PHPMailer 6.0 is a major update, breaking backward compatibility.
|
||||
|
||||
If you're in doubt about how you should be using PHPMailer 6, take a look at the examples as they have all been updated to work in a PHPMailer 6.0 style.
|
||||
|
||||
## PHP Version
|
||||
|
||||
PHPMailer 6.0 requires PHP 5.5 or later, and is fully compatible with PHP versions all the way up to 8.4. PHPMailer 5.2 supported PHP 5.0 and upwards, so if you need to run on a legacy PHP version, see the [PHPMailer 5.2-stable branch on Github](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable), but bear in mind that this branch is no longer maintained.
|
||||
|
||||
## Loading PHPMailer
|
||||
|
||||
The single biggest change will be in the way that you load PHPMailer. In earlier versions you may have done this:
|
||||
|
||||
```php
|
||||
require 'PHPMailerAutoload.php';
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```php
|
||||
require 'class.phpmailer.php';
|
||||
require 'class.smtp.php';
|
||||
```
|
||||
|
||||
We recommend that you load PHPMailer via composer, using its standard autoloader, which you probably won't need to load if you're using it already, but in case you're not, you will need to do this instead:
|
||||
|
||||
```php
|
||||
require 'vendor/autoload.php';
|
||||
```
|
||||
|
||||
If you're not using composer, you can still load the classes manually, depending on what you're using:
|
||||
|
||||
```php
|
||||
require 'src/PHPMailer.php';
|
||||
require 'src/SMTP.php';
|
||||
require 'src/Exception.php';
|
||||
```
|
||||
|
||||
## Namespace
|
||||
PHPMailer 6 uses a [namespace](https://www.php.net/manual/en/language.namespaces.rationale.php) of `PHPMailer\PHPMailer`, because it's the PHPMailer project within the PHPMailer organisation. You **must** import (with a `use` statement) classes you're using explicitly into your own namespace, or reference them absolutely in the global namespace - all the examples do this. This means the fully-qualified name of the main PHPMailer class is `PHPMailer\PHPMailer\PHPMailer`, which is a bit of a mouthful, but there's no harm in it! If you are using other PHPMailer classes explicitly (such as `SMTP` or `Exception`), you will need to import them into your namespace too.
|
||||
|
||||
For example you might create an instance like this:
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace MyProject;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
require 'vendor/autoload.php';
|
||||
$mail = new PHPMailer;
|
||||
...
|
||||
```
|
||||
|
||||
or alternatively, using a fully qualified name:
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace MyProject;
|
||||
require 'vendor/autoload.php';
|
||||
$mail = new PHPMailer\PHPMailer\PHPMailer;
|
||||
...
|
||||
```
|
||||
|
||||
Note that `use` statements apply *only* to the file they appear in (they are local aliases), so if an included file contains `use` statements, it will not import the namespaced classes into the file you're including from.
|
||||
|
||||
## Namespaced exceptions
|
||||
PHPMailer now uses its own namespaced `Exception` class, so if you were previously catching exceptions of type `phpmailerException` (or subclasses of that), you will need to update them to use the PHPMailer namespace, and make any existing `Exception` references use the global namespace, i.e. `\Exception`. If your original code was:
|
||||
|
||||
```php
|
||||
try {
|
||||
...
|
||||
} catch (phpmailerException $e) {
|
||||
echo $e->errorMessage();
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
```
|
||||
|
||||
Convert it to:
|
||||
|
||||
```php
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
...
|
||||
try {
|
||||
...
|
||||
} catch (Exception $e) {
|
||||
echo $e->errorMessage();
|
||||
} catch (\Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
```
|
||||
|
||||
## OAuth2 Support
|
||||
The OAuth2 implementation has been completely redesigned using the [OAuth2 packages](https://oauth2-client.thephpleague.com) from the [League of extraordinary packages](https://thephpleague.com), providing support for many more OAuth services, and you'll need to update your code if you were using OAuth in 5.2. See [the examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) and documentation in the [PHPMailer wiki](https://github.com/PHPMailer/PHPMailer/wiki).
|
||||
|
||||
## Extras
|
||||
Additional classes previously bundled in the `Extras` folder (such as htmlfilter and EasyPeasyICS) have been removed - use equivalent packages from [packagist.org](https://packagist.org) instead.
|
||||
|
||||
## Other upgrade changes
|
||||
See the changelog for full details.
|
||||
* File structure simplified, classes live in the `src/` folder
|
||||
* Most statically called functions now use the `static` keyword instead of `self`, so it's possible to override static internal functions in subclasses, for example `validateAddress()`
|
||||
* Complete RFC standardisation on CRLF (`\r\n`) line breaks by default:
|
||||
* `PHPMailer::$LE` still exists, but all uses of it are changed to `static::$LE` for easier overriding. It may be changed to `\n` automatically when sending via `mail()` on UNIX-like OSs
|
||||
* `PHPMailer::CRLF` line ending constant removed
|
||||
* The length of the line break is no longer used in line length calculations
|
||||
* Similar changes to line break handling in SMTP and POP3 classes
|
||||
* All elements previously marked as deprecated have been removed:
|
||||
* `PHPMailer->Version`
|
||||
* `PHPMailer->ReturnPath`
|
||||
* `PHPMailer->PluginDir`
|
||||
* `PHPMailer->encodeQPphp()`
|
||||
* `SMTP->CRLF`
|
||||
* `SMTP->Version`
|
||||
* `SMTP->SMTP_PORT`
|
||||
* `POP3->CRLF`
|
||||
* `POP3->Version`
|
||||
* NTLM authentication has been removed - it never worked anyway!
|
||||
* `PHPMailer->Workstation`
|
||||
* `PHPMailer->Realm`
|
||||
* `SMTP::authenticate` method signature changed
|
||||
* `parseAddresses()` is now static
|
||||
* `validateAddress()` is now called statically from `parseAddresses()`
|
||||
* `idnSupported()` is now static and is called statically from `punyencodeAddress()`
|
||||
* `PHPMailer->SingleToArray` is now protected
|
||||
2
vendor/phpmailer/phpmailer/VERSION
vendored
2
vendor/phpmailer/phpmailer/VERSION
vendored
@@ -1 +1 @@
|
||||
6.9.3
|
||||
6.12.0
|
||||
|
||||
1078
vendor/phpmailer/phpmailer/changelog.md
vendored
1078
vendor/phpmailer/phpmailer/changelog.md
vendored
File diff suppressed because it is too large
Load Diff
9
vendor/phpmailer/phpmailer/docs/README.md
vendored
9
vendor/phpmailer/phpmailer/docs/README.md
vendored
@@ -1,9 +0,0 @@
|
||||
# PHPMailer Documentation
|
||||
|
||||
Generated documentation for PHPMailer is [available online](https://phpmailer.github.io/PHPMailer/), and is regenerated automatically whenever changes are made.
|
||||
|
||||
Pre-built PHPMailer API documentation is not provided in this repo, but you can generate it by running `phpdoc` in the top-level folder of this project, and documentation will be generated in this `docs` folder. You will need to have [phpDocumentor](https://www.phpdoc.org) installed. The configuration for phpdoc is in the [phpdoc.dist.xml file](https://github.com/PHPMailer/PHPMailer/blob/master/phpdoc.dist.xml).
|
||||
|
||||
Further help and information is available in [the PHPMailer README](https://github.com/PHPMailer/PHPMailer/blob/master/README.md), [the examples folder](https://github.com/PHPMailer/PHPMailer/tree/master/examples), and in [the GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki).
|
||||
|
||||
Fixes and additions to documentation are welcome - please submit pull requests or improve wiki pages.
|
||||
@@ -1,81 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This shows how to make a new public/private key pair suitable for use with DKIM.
|
||||
* You should only need to do this once, and the public key (**not** the private key!)
|
||||
* you generate should be inserted in your DNS matching the selector you want.
|
||||
*
|
||||
* You can also use the DKIM wizard here: https://www.sparkpost.com/resources/tools/dkim-wizard/
|
||||
* but be aware that having your private key known anywhere outside your own server
|
||||
* is a security risk, and it's easy enough to create your own on your own server.
|
||||
*
|
||||
* For security, any keys you create should not be accessible via your web site.
|
||||
*
|
||||
* 2048 bits is the recommended minimum key length - gmail won't accept less than 1024 bits.
|
||||
* To test your DKIM config, use Sparkpost's DKIM tester:
|
||||
* https://tools.sparkpost.com/dkim
|
||||
*
|
||||
* Note that you only need a *private* key to *send* a DKIM-signed message,
|
||||
* but receivers need your *public* key in order to verify it.
|
||||
*
|
||||
* Your public key will need to be formatted appropriately for your DNS and
|
||||
* inserted there using the selector you want to use.
|
||||
*/
|
||||
|
||||
//Set these to match your domain and chosen DKIM selector
|
||||
$domain = 'example.com';
|
||||
$selector = 'phpmailer';
|
||||
|
||||
//Private key filename for this selector
|
||||
$privatekeyfile = $selector . '_dkim_private.pem';
|
||||
//Public key filename for this selector
|
||||
$publickeyfile = $selector . '_dkim_public.pem';
|
||||
|
||||
if (file_exists($privatekeyfile)) {
|
||||
echo "Using existing keys - if you want to generate new keys, delete old key files first.\n\n";
|
||||
$privatekey = file_get_contents($privatekeyfile);
|
||||
$publickey = file_get_contents($publickeyfile);
|
||||
} else {
|
||||
//Create a 2048-bit RSA key with an SHA256 digest
|
||||
$pk = openssl_pkey_new(
|
||||
[
|
||||
'digest_alg' => 'sha256',
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
]
|
||||
);
|
||||
//Save private key
|
||||
openssl_pkey_export_to_file($pk, $privatekeyfile);
|
||||
//Save public key
|
||||
$pubKey = openssl_pkey_get_details($pk);
|
||||
$publickey = $pubKey['key'];
|
||||
file_put_contents($publickeyfile, $publickey);
|
||||
$privatekey = file_get_contents($privatekeyfile);
|
||||
}
|
||||
echo "Private key (keep this private!):\n\n" . $privatekey;
|
||||
echo "\n\nPublic key:\n\n" . $publickey;
|
||||
|
||||
//Prepare public key for DNS, e.g.
|
||||
//phpmailer._domainkey.example.com IN TXT "v=DKIM1; h=sha256; t=s; p=" "MIIBIjANBg...oXlwIDAQAB"...
|
||||
$dnskey = "$selector._domainkey.$domain IN TXT";
|
||||
$dnsvalue = '"v=DKIM1; h=sha256; t=s; p=" ';
|
||||
//Some DNS servers don't like ;(semi colon) chars unless backslash-escaped
|
||||
$dnsvalue2 = '"v=DKIM1\; h=sha256\; t=s\; p=" ';
|
||||
|
||||
//Strip and split the key into smaller parts and format for DNS
|
||||
//Many DNS systems don't like long TXT entries
|
||||
//but are OK if it's split into 255-char chunks
|
||||
//Remove PEM wrapper
|
||||
$publickey = preg_replace('/^-+.*?-+$/m', '', $publickey);
|
||||
//Strip line breaks
|
||||
$publickey = str_replace(["\r", "\n"], '', $publickey);
|
||||
//Split into chunks
|
||||
$keyparts = str_split($publickey, 253); //Becomes 255 when quotes are included
|
||||
//Quote each chunk
|
||||
foreach ($keyparts as $keypart) {
|
||||
$dnsvalue .= '"' . trim($keypart) . '" ';
|
||||
$dnsvalue2 .= '"' . trim($keypart) . '" ';
|
||||
}
|
||||
echo "\n\nDNS key:\n\n" . trim($dnskey);
|
||||
echo "\n\nDNS value:\n\n" . trim($dnsvalue);
|
||||
echo "\n\nDNS value (with escaping):\n\n" . trim($dnsvalue2);
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows sending a DKIM-signed message with PHPMailer.
|
||||
* More info about DKIM can be found here: https://www.dkim.org/info/dkim-faq.html
|
||||
* There's more to using DKIM than just this code - check out this article:
|
||||
* @see https://yomotherboard.com/how-to-setup-email-server-dkim-keys/
|
||||
* See also the DKIM_gen_keys example code in the examples folder,
|
||||
* which shows how to make a key pair from PHP.
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Usual setup
|
||||
$mail = new PHPMailer();
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
$mail->Subject = 'PHPMailer mail() test';
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
|
||||
//This should be the same as the domain of your From address
|
||||
$mail->DKIM_domain = 'example.com';
|
||||
//See the DKIM_gen_keys.phps script for making a key pair -
|
||||
//here we assume you've already done that.
|
||||
//Path to your private key:
|
||||
$mail->DKIM_private = 'dkim_private.pem';
|
||||
//Set this to your own selector
|
||||
$mail->DKIM_selector = 'phpmailer';
|
||||
//Put your private key's passphrase in here if it has one
|
||||
$mail->DKIM_passphrase = '';
|
||||
//The identity you're signing as - usually your From address
|
||||
$mail->DKIM_identity = $mail->From;
|
||||
//Suppress listing signed header fields in signature, defaults to true for debugging purpose
|
||||
$mail->DKIM_copyHeaderFields = false;
|
||||
//Optionally you can add extra headers for signing to meet special requirements
|
||||
$mail->DKIM_extraHeaders = ['List-Unsubscribe', 'List-Help'];
|
||||
|
||||
//When you send, the DKIM settings will be used to sign the message
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
}
|
||||
96
vendor/phpmailer/phpmailer/examples/README.md
vendored
96
vendor/phpmailer/phpmailer/examples/README.md
vendored
@@ -1,96 +0,0 @@
|
||||
[](https://github.com/PHPMailer/PHPMailer)
|
||||
# PHPMailer code examples
|
||||
|
||||
This folder contains a collection of examples of using [PHPMailer](https://github.com/PHPMailer/PHPMailer).
|
||||
|
||||
## About testing email sending
|
||||
|
||||
When working on email sending code you'll find yourself worrying about what might happen if all these test emails got sent to your mailing list. The solution is to use a fake mail server, one that acts just like the real thing, but just doesn't actually send anything out. Some offer web interfaces, feedback, logging, the ability to return specific error codes, all things that are useful for testing error handling, authentication etc. Here's a selection of mail testing tools you might like to try:
|
||||
|
||||
* [FakeEmail](https://github.com/tomwardill/FakeEmail), a Python-based fake mail server with a web interface.
|
||||
* [smtp-sink](https://www.postfix.org/smtp-sink.1.html), part of the Postfix mail server, so you may have this installed already. This is used in the GitHub actions configuration to run PHPMailer's unit tests.
|
||||
* [smtp4dev](https://github.com/rnwood/smtp4dev), a dummy SMTP server for Windows and Linux.
|
||||
* [fakesendmail.sh](https://github.com/PHPMailer/PHPMailer/blob/master/test/fakesendmail.sh), part of PHPMailer's test setup, this is a shell script that emulates sendmail for testing 'mail' or 'sendmail' methods in PHPMailer.
|
||||
* [HELO](https://usehelo.com), a very nice (commercial) mail server desktop app from BeyondCode, and [how to set it up for local testing](https://usehelo.com/blog/how-to-use-helo-with-phps-mail-function).
|
||||
* [msglint](https://www.splitbrain.org/_static/msglint/), not a mail server, the IETF's MIME structure analyser checks the formatting of your messages.
|
||||
* [MailHog](https://github.com/les-enovateurs/mailhog-examples), a Go-based email testing tool for developers with a web interface. You can use it with Docker and GitHub Actions to test your mails. The repository also contains a small part of PHPMailer's setup.
|
||||
* [aboutmy.email](https://aboutmy.email), a service for evaluating your email config – SPF, DKIM, DMARC, and compliance with list-unsubscribe, TLS, and many other settings.
|
||||
|
||||
Most of these examples use the `example.com` and `example.net` domains. These domains are reserved by IANA for illustrative purposes, as documented in [RFC 2606](https://www.rfc-editor.org/rfc/rfc2606). Don't use made-up domains like 'mydomain.com' or 'somedomain.com' in examples as someone, somewhere, probably owns them!
|
||||
|
||||
## Security note
|
||||
Before running these examples in a web server, you'll need to rename them with '.php' extensions. They are supplied as '.phps' files which will usually be displayed with syntax highlighting by PHP instead of running them. This prevents potential security issues with running potential spam-gateway code if you happen to deploy these code examples on a live site - _please don't do that!_
|
||||
|
||||
Similarly, don't leave your passwords in these files as they will be visible to the world!
|
||||
|
||||
## [mail.phps](mail.phps)
|
||||
|
||||
This is a basic example which creates an email message from an external HTML file, creates a plain text body, sets various addresses, adds an attachment and sends the message. It uses PHP's built-in mail() function which is the simplest to use, but relies on the presence of a local mail server, something which is not usually available on Windows. If you find yourself in that situation, either install a local mail server, or use a remote one and send using SMTP instead.
|
||||
|
||||
## [simple_contact_form.phps](simple_contact_form.phps)
|
||||
|
||||
This is probably the most common reason for using PHPMailer - building a contact form. This example has a basic, unstyled form and also illustrates how to filter input data before using it, how to validate addresses, how to avoid being abused as a spam gateway, and how to address messages correctly so that you don't fail SPF checks.
|
||||
|
||||
## [exceptions.phps](exceptions.phps)
|
||||
|
||||
Like the mail example, but shows how to use PHPMailer's optional exceptions for error handling.
|
||||
|
||||
## [extending.phps](extending.phps)
|
||||
|
||||
This shows how to create a subclass of PHPMailer to customise its behaviour and simplify coding in your app.
|
||||
|
||||
## [smtp.phps](smtp.phps)
|
||||
|
||||
A simple example sending using SMTP with authentication.
|
||||
|
||||
## [smtp_no_auth.phps](smtp_no_auth.phps)
|
||||
|
||||
A simple example sending using SMTP without authentication.
|
||||
|
||||
## [send_file_upload.phps](send_file_upload.phps)
|
||||
|
||||
Lots of people want to do this... This is a simple form which accepts a file upload and emails it.
|
||||
|
||||
## [send_multiple_file_upload.phps](send_multiple_file_upload.phps)
|
||||
|
||||
A slightly more complex form that allows uploading multiple files at once and sends all of them as attachments to an email.
|
||||
|
||||
## [sendmail.phps](sendmail.phps)
|
||||
|
||||
A simple example using sendmail. Sendmail is a program (usually found on Linux/BSD, OS X and other UNIX-alikes) that can be used to submit messages to a local mail server without a lengthy SMTP conversation. It's probably the fastest sending mechanism, but lacks some error reporting features. There are sendmail emulators for most popular mail servers including postfix, qmail, exim etc.
|
||||
|
||||
## [gmail.phps](gmail.phps)
|
||||
|
||||
Submitting email via Google's Gmail service is a popular use of PHPMailer. It's much the same as normal SMTP sending, just with some specific settings, namely using TLS encryption, authentication is enabled, and it connects to the SMTP submission port 587 on the smtp.gmail.com host. This example does all that.
|
||||
|
||||
## [gmail_xoauth.phps](gmail_xoauth.phps)
|
||||
|
||||
Gmail now likes you to use XOAUTH2 for SMTP authentication. This is extremely laborious to set up, but once it's done you can use it repeatedly and will no longer need Gmail's ineptly-named "Allow less secure apps" setting enabled. [Read the guide in the wiki](https://github.com/PHPMailer/PHPMailer/wiki/Using-Gmail-with-XOAUTH2) for how to set it up.
|
||||
|
||||
## [pop_before_smtp.phps](pop_before_smtp.phps)
|
||||
|
||||
Back in the stone age, before effective SMTP authentication mechanisms were available, it was common for ISPs to use POP-before-SMTP authentication. As it implies, you authenticate using the POP3 protocol (an older protocol now mostly replaced by the far superior IMAP), and then the SMTP server will allow send access from your IP address for a short while, usually 5-15 minutes. PHPMailer includes a basic POP3 protocol client with just enough functionality to carry out this sequence - it's just like a normal SMTP conversation (without authentication), but connects via POP3 first.
|
||||
|
||||
## [mailing_list.phps](mailing_list.phps)
|
||||
|
||||
This is a somewhat naïve, but reasonably efficient example of sending similar emails to a list of different addresses. It sets up a PHPMailer instance using SMTP, then connects to a MySQL database to retrieve a list of recipients. The code loops over this list, sending email to each person using their info and marks them as sent in the database. It makes use of SMTP keepalive which saves reconnecting and re-authenticating between each message.
|
||||
|
||||
## [ssl_options.phps](ssl_options.phps)
|
||||
|
||||
PHP 5.6 introduced SSL certificate verification by default, and this applies to mail servers exactly as it does to web servers. Unfortunately, SSL misconfiguration in mail servers is quite common, so this caused a common problem: those that were previously using servers with bad configs suddenly found they stopped working when they upgraded PHP. PHPMailer provides a mechanism to disable SSL certificate verification as a workaround and this example shows how to do it. Bear in mind that this is **not** a good approach - the right way is to fix your mail server config!
|
||||
|
||||
## [smime_signed_mail.phps](smime_signed_mail.phps)
|
||||
|
||||
An example of how to sign messages using [S/MIME](https://en.wikipedia.org/wiki/S/MIME), ensuring that your data can't be tampered with in transit, and proves to recipients that it was you that sent it.
|
||||
|
||||
* * *
|
||||
|
||||
## [smtp_check.phps](smtp_check.phps)
|
||||
|
||||
This is an example showing how to use the SMTP class by itself (without PHPMailer) to check an SMTP connection.
|
||||
|
||||
## [smtp_low_memory.phps](smtp_low_memory.phps)
|
||||
|
||||
This demonstrates how to extend the SMTP class and make PHPMailer use it. In this case it's an effort to make the SMTP class use less memory when sending large attachments.
|
||||
|
||||
* * *
|
||||
@@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows how to send via Microsoft Outlook's servers using XOAUTH2 authentication
|
||||
* using the league/oauth2-client to provide the OAuth2 token.
|
||||
* To use a different OAuth2 library create a wrapper class that implements OAuthTokenProvider and
|
||||
* pass that wrapper class to PHPMailer::setOAuth().
|
||||
*/
|
||||
|
||||
//Import PHPMailer classes into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\OAuth;
|
||||
//Alias the League Google OAuth2 provider class
|
||||
use Greew\OAuth2\Client\Provider\Azure;
|
||||
|
||||
//SMTP needs accurate times, and the PHP time zone MUST be set
|
||||
//This should be done in your php.ini, but this is how to do it if you don't have access to that
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
//Load dependencies from composer
|
||||
//If this causes an error, run 'composer install'
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
|
||||
//Tell PHPMailer to use SMTP
|
||||
$mail->isSMTP();
|
||||
|
||||
//Enable SMTP debugging
|
||||
//SMTP::DEBUG_OFF = off (for production use)
|
||||
//SMTP::DEBUG_CLIENT = client messages
|
||||
//SMTP::DEBUG_SERVER = client and server messages
|
||||
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
|
||||
|
||||
//Set the hostname of the mail server
|
||||
$mail->Host = 'smtp.office365.com';
|
||||
|
||||
//Set the SMTP port number:
|
||||
// - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
|
||||
// - 587 for SMTP+STARTTLS
|
||||
$mail->Port = 587;
|
||||
|
||||
//Set the encryption mechanism to use:
|
||||
// - SMTPS (implicit TLS on port 465) or
|
||||
// - STARTTLS (explicit TLS on port 587)
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
||||
|
||||
//Whether to use SMTP authentication
|
||||
$mail->SMTPAuth = true;
|
||||
|
||||
//Set AuthType to use XOAUTH2
|
||||
$mail->AuthType = 'XOAUTH2';
|
||||
|
||||
//Start Option 1: Use league/oauth2-client as OAuth2 token provider
|
||||
//Fill in authentication details here
|
||||
//Either the microsoft account owner, or the user that gave consent
|
||||
$email = 'someone@somemicrosoftaccount.com';
|
||||
$clientId = 'RANDOMCHARS-----duv1n2TS';
|
||||
$clientSecret = 'RANDOMCHARS-----lGyjPcRtvP';
|
||||
$tenantId = 'RANDOMCHARS-----HSFTAOIlagss';
|
||||
|
||||
//Obtained by configuring and running get_oauth_token.php
|
||||
//after setting up an app in Google Developer Console.
|
||||
$refreshToken = 'RANDOMCHARS-----DWxgOvPT003r-yFUV49TQYag7_Aod7y0';
|
||||
|
||||
//Create a new OAuth2 provider instance
|
||||
$provider = new Azure(
|
||||
[
|
||||
'clientId' => $clientId,
|
||||
'clientSecret' => $clientSecret,
|
||||
'tenantId' => $tenantId,
|
||||
]
|
||||
);
|
||||
|
||||
//Pass the OAuth provider instance to PHPMailer
|
||||
$mail->setOAuth(
|
||||
new OAuth(
|
||||
[
|
||||
'provider' => $provider,
|
||||
'clientId' => $clientId,
|
||||
'clientSecret' => $clientSecret,
|
||||
'refreshToken' => $refreshToken,
|
||||
'userName' => $email,
|
||||
]
|
||||
)
|
||||
);
|
||||
//End Option 1
|
||||
|
||||
//Option 2: Another OAuth library as OAuth2 token provider
|
||||
//Set up the other oauth library as per its documentation
|
||||
//Then create the wrapper class that implementations OAuthTokenProvider
|
||||
$oauthTokenProvider = new MyOAuthTokenProvider(/* Email, ClientId, ClientSecret, etc. */);
|
||||
|
||||
//Pass the implementation of OAuthTokenProvider to PHPMailer
|
||||
$mail->setOAuth($oauthTokenProvider);
|
||||
//End Option 2
|
||||
|
||||
//Set who the message is to be sent from
|
||||
//For Outlook, this generally needs to be the same as the user you logged in as
|
||||
$mail->setFrom($email, 'First Last');
|
||||
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('someone@someserver.com', 'John Doe');
|
||||
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer Outlook XOAUTH2 SMTP test';
|
||||
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//convert HTML into a basic plain-text alternative body
|
||||
$mail->CharSet = PHPMailer::CHARSET_UTF8;
|
||||
$mail->msgHTML(file_get_contents('contentsutf8.html'), __DIR__);
|
||||
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
|
||||
//Attach an image file
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
|
||||
//send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows how to use a callback function from PHPMailer.
|
||||
*/
|
||||
|
||||
//Import PHPMailer classes into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* Example PHPMailer callback function.
|
||||
* This is a global function, but you can also pass a closure (or any other callable)
|
||||
* to the `action_function` property.
|
||||
*
|
||||
* @param bool $result result of the send action
|
||||
* @param array $to email address of the recipient
|
||||
* @param array $cc cc email addresses
|
||||
* @param array $bcc bcc email addresses
|
||||
* @param string $subject the subject
|
||||
* @param string $body the email body
|
||||
*/
|
||||
function callbackAction($result, $to, $cc, $bcc, $subject, $body)
|
||||
{
|
||||
echo "Message subject: \"$subject\"\n";
|
||||
foreach ($to as $address) {
|
||||
echo "Message to {$address[1]} <{$address[0]}>\n";
|
||||
}
|
||||
foreach ($cc as $address) {
|
||||
echo "Message CC to {$address[1]} <{$address[0]}>\n";
|
||||
}
|
||||
foreach ($bcc as $toaddress) {
|
||||
echo "Message BCC to {$toaddress[1]} <{$toaddress[0]}>\n";
|
||||
}
|
||||
if ($result) {
|
||||
echo "Message sent successfully\n";
|
||||
} else {
|
||||
echo "Message send failed\n";
|
||||
}
|
||||
}
|
||||
|
||||
require_once '../vendor/autoload.php';
|
||||
|
||||
$mail = new PHPMailer();
|
||||
|
||||
try {
|
||||
$mail->isMail();
|
||||
$mail->setFrom('you@example.com', 'Your Name');
|
||||
$mail->addAddress('jane@example.com', 'Jane Doe');
|
||||
$mail->addCC('john@example.com', 'John Doe');
|
||||
$mail->Subject = 'PHPMailer Test Subject';
|
||||
$mail->msgHTML(file_get_contents('../examples/contents.html'));
|
||||
//Optional - msgHTML will create an alternate automatically
|
||||
$mail->AltBody = 'To view the message, please use an HTML compatible email viewer!';
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
$mail->action_function = 'callbackAction';
|
||||
$mail->send();
|
||||
} catch (Exception $e) {
|
||||
echo $e->errorMessage();
|
||||
}
|
||||
|
||||
//Alternative approach using a closure
|
||||
try {
|
||||
$mail->action_function = static function ($result, $to, $cc, $bcc, $subject, $body) {
|
||||
if ($result) {
|
||||
echo "Message sent successfully\n";
|
||||
} else {
|
||||
echo "Message send failed\n";
|
||||
}
|
||||
};
|
||||
$mail->send();
|
||||
} catch (Exception $e) {
|
||||
echo $e->errorMessage();
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows how to handle a simple contact form safely.
|
||||
*/
|
||||
|
||||
//Import PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
//Don't run this unless we're handling a form submission
|
||||
if (array_key_exists('email', $_POST)) {
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
require '../vendor/autoload.php';
|
||||
$isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
|
||||
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
//Send using SMTP to localhost (faster and safer than using mail()) – requires a local mail server
|
||||
//See other examples for how to use a remote server such as gmail
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'localhost';
|
||||
$mail->Port = 25;
|
||||
|
||||
//Use a fixed address in your own domain as the from address
|
||||
//**DO NOT** use the submitter's address here as it will be forgery
|
||||
//and will cause your messages to fail SPF checks
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
//Choose who the message should be sent to
|
||||
//You don't have to use a <select> like in this example, you can simply use a fixed address
|
||||
//the important thing is *not* to trust an email address submitted from the form directly,
|
||||
//as an attacker can substitute their own and try to use your form to send spam
|
||||
$addresses = [
|
||||
'sales' => 'sales@example.com',
|
||||
'support' => 'support@example.com',
|
||||
'accounts' => 'accounts@example.com',
|
||||
];
|
||||
//Validate address selection before trying to use it
|
||||
if (array_key_exists('dept', $_POST) && array_key_exists($_POST['dept'], $addresses)) {
|
||||
$mail->addAddress($addresses[$_POST['dept']]);
|
||||
} else {
|
||||
//Fall back to a fixed address if dept selection is invalid or missing
|
||||
$mail->addAddress('support@example.com');
|
||||
}
|
||||
//Put the submitter's address in a reply-to header
|
||||
//This will fail if the address provided is invalid,
|
||||
//in which case we should ignore the whole request
|
||||
if ($mail->addReplyTo($_POST['email'], $_POST['name'])) {
|
||||
$mail->Subject = 'PHPMailer contact form';
|
||||
//Keep it simple - don't use HTML
|
||||
$mail->isHTML(false);
|
||||
//Build a simple message body
|
||||
$mail->Body = <<<EOT
|
||||
Email: {$_POST['email']}
|
||||
Name: {$_POST['name']}
|
||||
Message: {$_POST['message']}
|
||||
EOT;
|
||||
|
||||
//Send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
//The reason for failing to send will be in $mail->ErrorInfo
|
||||
//but it's unsafe to display errors directly to users - process the error, log it on your server.
|
||||
if ($isAjax) {
|
||||
http_response_code(500);
|
||||
}
|
||||
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => 'Sorry, something went wrong. Please try again later.'
|
||||
];
|
||||
} else {
|
||||
$response = [
|
||||
"status" => true,
|
||||
"message" => 'Message sent! Thanks for contacting us.'
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$response = [
|
||||
"status" => false,
|
||||
"message" => 'Invalid email address, message ignored.'
|
||||
];
|
||||
}
|
||||
|
||||
if ($isAjax) {
|
||||
header('Content-type:application/json;charset=utf-8');
|
||||
echo json_encode($response);
|
||||
exit();
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Contact form</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Contact us</h1>
|
||||
<h2 id="status-message"><?php if (isset($response)) {
|
||||
echo $response['message'];
|
||||
}?></h2>
|
||||
<form method="POST" id="contact-form">
|
||||
<label for="name">Name: <input type="text" name="name" id="name"></label><br>
|
||||
<label for="email">Email address: <input type="email" name="email" id="email"></label><br>
|
||||
<label for="message">Message: <textarea name="message" id="message" rows="8" cols="20"></textarea></label><br>
|
||||
<label for="dept">Send query to department:</label>
|
||||
<select name="dept" id="dept">
|
||||
<option value="sales">Sales</option>
|
||||
<option value="support" selected>Technical support</option>
|
||||
<option value="accounts">Accounts</option>
|
||||
</select><br>
|
||||
<input type="submit" value="Send">
|
||||
</form>
|
||||
|
||||
<script type="application/javascript">
|
||||
const form = document.getElementById("contact-form")
|
||||
|
||||
function email(data) {
|
||||
const message = document.getElementById("status-message")
|
||||
fetch("", {
|
||||
method: "POST",
|
||||
body: data,
|
||||
headers: {
|
||||
'X-Requested-With' : 'XMLHttpRequest'
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(response => {message.innerHTML = response.message})
|
||||
.catch(error => {
|
||||
error.json().then(response => {
|
||||
message.innerHTML = response.message
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const submitEvent = form.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(form);
|
||||
|
||||
email(formData);
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows how to handle a simple contact form safely.
|
||||
*/
|
||||
|
||||
//Import PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
$msg = '';
|
||||
//Don't run this unless we're handling a form submission
|
||||
if (array_key_exists('email', $_POST)) {
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
//Send using SMTP to localhost (faster and safer than using mail()) – requires a local mail server
|
||||
//See other examples for how to use a remote server such as gmail
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'localhost';
|
||||
$mail->Port = 25;
|
||||
|
||||
//Use a fixed address in your own domain as the from address
|
||||
//**DO NOT** use the submitter's address here as it will be forgery
|
||||
//and will cause your messages to fail SPF checks
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
//Choose who the message should be sent to
|
||||
//You don't have to use a <select> like in this example, you can simply use a fixed address
|
||||
//the important thing is *not* to trust an email address submitted from the form directly,
|
||||
//as an attacker can substitute their own and try to use your form to send spam
|
||||
$addresses = [
|
||||
'sales' => 'sales@example.com',
|
||||
'support' => 'support@example.com',
|
||||
'accounts' => 'accounts@example.com',
|
||||
];
|
||||
//Validate address selection before trying to use it
|
||||
if (array_key_exists('dept', $_POST) && array_key_exists($_POST['dept'], $addresses)) {
|
||||
$mail->addAddress($addresses[$_POST['dept']]);
|
||||
} else {
|
||||
//Fall back to a fixed address if dept selection is invalid or missing
|
||||
$mail->addAddress('support@example.com');
|
||||
}
|
||||
//Put the submitter's address in a reply-to header
|
||||
//This will fail if the address provided is invalid,
|
||||
//in which case we should ignore the whole request
|
||||
if ($mail->addReplyTo($_POST['email'], $_POST['name'])) {
|
||||
$mail->Subject = 'PHPMailer contact form';
|
||||
//Keep it simple - don't use HTML
|
||||
$mail->isHTML(false);
|
||||
//Build a simple message body
|
||||
$mail->Body = <<<EOT
|
||||
Email: {$_POST['email']}
|
||||
Name: {$_POST['name']}
|
||||
Message: {$_POST['message']}
|
||||
EOT;
|
||||
//Send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
//The reason for failing to send will be in $mail->ErrorInfo
|
||||
//but it's unsafe to display errors directly to users - process the error, log it on your server.
|
||||
$msg = 'Sorry, something went wrong. Please try again later.';
|
||||
} else {
|
||||
$msg = 'Message sent! Thanks for contacting us.';
|
||||
}
|
||||
} else {
|
||||
$msg = 'Invalid email address, message ignored.';
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Contact form</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Contact us</h1>
|
||||
<?php if (!empty($msg)) {
|
||||
echo "<h2>$msg</h2>";
|
||||
} ?>
|
||||
<form method="POST">
|
||||
<label for="name">Name: <input type="text" name="name" id="name"></label><br>
|
||||
<label for="email">Email address: <input type="email" name="email" id="email"></label><br>
|
||||
<label for="message">Message: <textarea name="message" id="message" rows="8" cols="20"></textarea></label><br>
|
||||
<label for="dept">Send query to department:</label>
|
||||
<select name="dept" id="dept">
|
||||
<option value="sales">Sales</option>
|
||||
<option value="support" selected>Technical support</option>
|
||||
<option value="accounts">Accounts</option>
|
||||
</select><br>
|
||||
<input type="submit" value="Send">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>PHPMailer Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="width: 640px; font-family: Arial, Helvetica, sans-serif; font-size: 11px;">
|
||||
<h1>This is a test of PHPMailer.</h1>
|
||||
<div align="center">
|
||||
<a href="https://github.com/PHPMailer/PHPMailer/"><img src="images/phpmailer.png" height="90" width="340" alt="PHPMailer rocks"></a>
|
||||
</div>
|
||||
<p>This example uses <strong>HTML</strong>.</p>
|
||||
<p>ISO-8859-1 text: éèîüçÅñæß</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,23 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>PHPMailer Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<div style="width: 640px; font-family: Arial, Helvetica, sans-serif; font-size: 11px;">
|
||||
<h1>This is a test of PHPMailer.</h1>
|
||||
<div align="center">
|
||||
<a href="https://github.com/PHPMailer/PHPMailer/"><img src="images/phpmailer.png" height="90" width="340" alt="PHPMailer rocks"></a>
|
||||
</div>
|
||||
<p>This example uses <strong>HTML</strong> with the UTF-8 unicode charset.</p>
|
||||
<p>Chinese text: 郵件內容為空</p>
|
||||
<p>Russian text: Пустое тело сообщения</p>
|
||||
<p>Armenian text: Հաղորդագրությունը դատարկ է</p>
|
||||
<p>Czech text: Prázdné tělo zprávy</p>
|
||||
<p>Emoji: <span style="font-size: 48px">😂 🦄 💥 📤 📧</span></p>
|
||||
<p>Image data URL (base64)<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="#"></p>
|
||||
<p>Image data URL (URL-encoded)<img src="data:image/gif,GIF89a%01%00%01%00%00%00%00%21%F9%04%01%0A%00%01%00%2C%00%00%00%00%01%00%01%00%00%02%02L%01%00%3B" alt="#"></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows how to make use of PHPMailer's exceptions for error handling.
|
||||
*/
|
||||
|
||||
//Import PHPMailer classes into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
//Passing true to the constructor enables the use of exceptions for error handling
|
||||
$mail = new PHPMailer(true);
|
||||
try {
|
||||
//Set who the message is to be sent from
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
//Set an alternative reply-to address
|
||||
$mail->addReplyTo('replyto@example.com', 'First Last');
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer Exceptions test';
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//and convert the HTML into a basic plain-text alternative body
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
//Attach an image file
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
//send the message
|
||||
//Note that we don't need check the response from this because it will throw an exception if it has trouble
|
||||
$mail->send();
|
||||
echo 'Message sent!';
|
||||
} catch (Exception $e) {
|
||||
echo $e->errorMessage(); //Pretty error messages from PHPMailer
|
||||
} catch (\Exception $e) { //The leading slash means the Global PHP Exception class will be caught
|
||||
echo $e->getMessage(); //Boring error messages from anything else!
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows how to extend PHPMailer to simplify your coding.
|
||||
* If PHPMailer doesn't do something the way you want it to, or your code
|
||||
* contains too much boilerplate, don't edit the library files,
|
||||
* create a subclass instead and customise that.
|
||||
* That way all your changes will be retained when PHPMailer is updated.
|
||||
*/
|
||||
|
||||
//Import PHPMailer classes into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
/**
|
||||
* Use PHPMailer as a base class and extend it
|
||||
*/
|
||||
class MyPHPMailer extends PHPMailer
|
||||
{
|
||||
/**
|
||||
* myPHPMailer constructor.
|
||||
*
|
||||
* @param bool|null $exceptions
|
||||
* @param string $body A default HTML message body
|
||||
*/
|
||||
public function __construct($exceptions, $body = '')
|
||||
{
|
||||
//Don't forget to do this or other things may not be set correctly!
|
||||
parent::__construct($exceptions);
|
||||
//Set a default 'From' address
|
||||
$this->setFrom('joe@example.com', 'Joe User');
|
||||
//Send via SMTP
|
||||
$this->isSMTP();
|
||||
//Equivalent to setting `Host`, `Port` and `SMTPSecure` all at once
|
||||
$this->Host = 'tls://smtp.example.com:587';
|
||||
//Set an HTML and plain-text body, import relative image references
|
||||
$this->msgHTML($body, './images/');
|
||||
//Show debug output
|
||||
$this->SMTPDebug = SMTP::DEBUG_SERVER;
|
||||
//Inject a new debug output handler
|
||||
$this->Debugoutput = static function ($str, $level) {
|
||||
echo "Debug level $level; message: $str\n";
|
||||
};
|
||||
}
|
||||
|
||||
//Extend the send function
|
||||
public function send()
|
||||
{
|
||||
$this->Subject = '[Yay for me!] ' . $this->Subject;
|
||||
$r = parent::send();
|
||||
echo 'I sent a message with subject ' . $this->Subject;
|
||||
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
|
||||
//Now creating and sending a message becomes simpler when you use this class in your app code
|
||||
try {
|
||||
//Instantiate your new class, making use of the new `$body` parameter
|
||||
$mail = new myPHPMailer(true, '<strong>This is the message body</strong>');
|
||||
//Now you only need to set things that are different from the defaults you defined
|
||||
$mail->addAddress('jane@example.com', 'Jane User');
|
||||
$mail->Subject = 'Here is the subject';
|
||||
$mail->addAttachment(__FILE__, 'myPHPMailer.php');
|
||||
$mail->send(); //No need to check for errors - the exception handler will do it
|
||||
} catch (Exception $e) {
|
||||
//Note that this is catching the PHPMailer Exception class, not the global \Exception type!
|
||||
echo 'Caught a ' . get_class($e) . ': ' . $e->getMessage();
|
||||
}
|
||||
108
vendor/phpmailer/phpmailer/examples/gmail.phps
vendored
108
vendor/phpmailer/phpmailer/examples/gmail.phps
vendored
@@ -1,108 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows settings to use when sending via Google's Gmail servers.
|
||||
* This uses traditional id & password authentication - look at the gmail_xoauth.phps
|
||||
* example to see how to use XOAUTH2.
|
||||
* The IMAP section shows how to save this message to the 'Sent Mail' folder using IMAP commands.
|
||||
*/
|
||||
|
||||
//Import PHPMailer classes into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
|
||||
//Tell PHPMailer to use SMTP
|
||||
$mail->isSMTP();
|
||||
|
||||
//Enable SMTP debugging
|
||||
//SMTP::DEBUG_OFF = off (for production use)
|
||||
//SMTP::DEBUG_CLIENT = client messages
|
||||
//SMTP::DEBUG_SERVER = client and server messages
|
||||
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
|
||||
|
||||
//Set the hostname of the mail server
|
||||
$mail->Host = 'smtp.gmail.com';
|
||||
//Use `$mail->Host = gethostbyname('smtp.gmail.com');`
|
||||
//if your network does not support SMTP over IPv6,
|
||||
//though this may cause issues with TLS
|
||||
|
||||
//Set the SMTP port number:
|
||||
// - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
|
||||
// - 587 for SMTP+STARTTLS
|
||||
$mail->Port = 465;
|
||||
|
||||
//Set the encryption mechanism to use:
|
||||
// - SMTPS (implicit TLS on port 465) or
|
||||
// - STARTTLS (explicit TLS on port 587)
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||
|
||||
//Whether to use SMTP authentication
|
||||
$mail->SMTPAuth = true;
|
||||
|
||||
//Username to use for SMTP authentication - use full email address for gmail
|
||||
$mail->Username = 'username@gmail.com';
|
||||
|
||||
//Password to use for SMTP authentication
|
||||
$mail->Password = 'yourpassword';
|
||||
|
||||
//Set who the message is to be sent from
|
||||
//Note that with gmail you can only use your account address (same as `Username`)
|
||||
//or predefined aliases that you have configured within your account.
|
||||
//Do not use user-submitted addresses in here
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
|
||||
//Set an alternative reply-to address
|
||||
//This is a good place to put user-submitted addresses
|
||||
$mail->addReplyTo('replyto@example.com', 'First Last');
|
||||
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer GMail SMTP test';
|
||||
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//convert HTML into a basic plain-text alternative body
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
|
||||
//Attach an image file
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
|
||||
//send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
//Section 2: IMAP
|
||||
//Uncomment these to save your message in the 'Sent Mail' folder.
|
||||
#if (save_mail($mail)) {
|
||||
# echo "Message saved!";
|
||||
#}
|
||||
}
|
||||
|
||||
//Section 2: IMAP
|
||||
//IMAP commands requires the PHP IMAP Extension, found at: https://php.net/manual/en/imap.setup.php
|
||||
//Function to call which uses the PHP imap_*() functions to save messages: https://php.net/manual/en/book.imap.php
|
||||
//You can use imap_getmailboxes($imapStream, '/imap/ssl', '*' ) to get a list of available folders or labels, this can
|
||||
//be useful if you are trying to get this working on a non-Gmail IMAP server.
|
||||
function save_mail($mail)
|
||||
{
|
||||
//You can change 'Sent Mail' to any other folder or tag
|
||||
$path = '{imap.gmail.com:993/imap/ssl}[Gmail]/Sent Mail';
|
||||
|
||||
//Tell your server to open an IMAP connection using the same username and password as you used for SMTP
|
||||
$imapStream = imap_open($path, $mail->Username, $mail->Password);
|
||||
|
||||
$result = imap_append($imapStream, $path, $mail->getSentMIMEMessage());
|
||||
imap_close($imapStream);
|
||||
|
||||
return $result;
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows how to send via Google's Gmail servers using XOAUTH2 authentication
|
||||
* using the league/oauth2-client to provide the OAuth2 token.
|
||||
* To use a different OAuth2 library create a wrapper class that implements OAuthTokenProvider and
|
||||
* pass that wrapper class to PHPMailer::setOAuth().
|
||||
*/
|
||||
|
||||
//Import PHPMailer classes into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\OAuth;
|
||||
//Alias the League Google OAuth2 provider class
|
||||
use League\OAuth2\Client\Provider\Google;
|
||||
|
||||
//SMTP needs accurate times, and the PHP time zone MUST be set
|
||||
//This should be done in your php.ini, but this is how to do it if you don't have access to that
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
//Load dependencies from composer
|
||||
//If this causes an error, run 'composer install'
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
|
||||
//Tell PHPMailer to use SMTP
|
||||
$mail->isSMTP();
|
||||
|
||||
//Enable SMTP debugging
|
||||
//SMTP::DEBUG_OFF = off (for production use)
|
||||
//SMTP::DEBUG_CLIENT = client messages
|
||||
//SMTP::DEBUG_SERVER = client and server messages
|
||||
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
|
||||
|
||||
//Set the hostname of the mail server
|
||||
$mail->Host = 'smtp.gmail.com';
|
||||
|
||||
//Set the SMTP port number:
|
||||
// - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
|
||||
// - 587 for SMTP+STARTTLS
|
||||
$mail->Port = 465;
|
||||
|
||||
//Set the encryption mechanism to use:
|
||||
// - SMTPS (implicit TLS on port 465) or
|
||||
// - STARTTLS (explicit TLS on port 587)
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||
|
||||
//Whether to use SMTP authentication
|
||||
$mail->SMTPAuth = true;
|
||||
|
||||
//Set AuthType to use XOAUTH2
|
||||
$mail->AuthType = 'XOAUTH2';
|
||||
|
||||
//Start Option 1: Use league/oauth2-client as OAuth2 token provider
|
||||
//Fill in authentication details here
|
||||
//Either the gmail account owner, or the user that gave consent
|
||||
$email = 'someone@gmail.com';
|
||||
$clientId = 'RANDOMCHARS-----duv1n2.apps.googleusercontent.com';
|
||||
$clientSecret = 'RANDOMCHARS-----lGyjPcRtvP';
|
||||
|
||||
//Obtained by configuring and running get_oauth_token.php
|
||||
//after setting up an app in Google Developer Console.
|
||||
$refreshToken = 'RANDOMCHARS-----DWxgOvPT003r-yFUV49TQYag7_Aod7y0';
|
||||
|
||||
//Create a new OAuth2 provider instance
|
||||
$provider = new Google(
|
||||
[
|
||||
'clientId' => $clientId,
|
||||
'clientSecret' => $clientSecret,
|
||||
]
|
||||
);
|
||||
|
||||
//Pass the OAuth provider instance to PHPMailer
|
||||
$mail->setOAuth(
|
||||
new OAuth(
|
||||
[
|
||||
'provider' => $provider,
|
||||
'clientId' => $clientId,
|
||||
'clientSecret' => $clientSecret,
|
||||
'refreshToken' => $refreshToken,
|
||||
'userName' => $email,
|
||||
]
|
||||
)
|
||||
);
|
||||
//End Option 1
|
||||
|
||||
//Option 2: Another OAuth library as OAuth2 token provider
|
||||
//Set up the other oauth library as per its documentation
|
||||
//Then create the wrapper class that implements OAuthTokenProvider
|
||||
$oauthTokenProvider = new MyOAuthTokenProvider(/* Email, ClientId, ClientSecret, etc. */);
|
||||
|
||||
//Pass the implementation of OAuthTokenProvider to PHPMailer
|
||||
$mail->setOAuth($oauthTokenProvider);
|
||||
//End Option 2
|
||||
|
||||
//Set who the message is to be sent from
|
||||
//For gmail, this generally needs to be the same as the user you logged in as
|
||||
$mail->setFrom($email, 'First Last');
|
||||
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('someone@gmail.com', 'John Doe');
|
||||
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer GMail XOAUTH2 SMTP test';
|
||||
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//convert HTML into a basic plain-text alternative body
|
||||
$mail->CharSet = PHPMailer::CHARSET_UTF8;
|
||||
$mail->msgHTML(file_get_contents('contentsutf8.html'), __DIR__);
|
||||
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
|
||||
//send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB |
@@ -1,209 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 1280 640" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g id="Background" transform="matrix(8.70744,5.33177e-16,-5.33177e-16,-4.35372,-4208.74,2147.69)">
|
||||
<path d="M630.351,346.3L483.35,346.3L483.35,493.301L630.351,493.301L630.351,346.3L630.351,346.3Z" style="fill:rgb(51,51,51);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g id="PHPMailer" transform="matrix(0.986688,0,0,0.986688,12.9314,1.29196)">
|
||||
<g transform="matrix(1.14074,0,0,1,-76.5738,0)">
|
||||
<g id="path68" transform="matrix(2.14981,0,0,-2.46335,-776.134,1230.68)">
|
||||
<path d="M614.574,416.832L584.18,445.184L584.18,381.999L644.963,381.999L644.963,445.181L614.574,416.832Z" style="fill:rgb(248,203,102);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g id="path74" transform="matrix(2.14981,0,0,-2.56665,-776.135,1278.22)">
|
||||
<path d="M644.989,460.2L584.155,460.2L614.574,432.967L644.989,460.2Z" style="fill:rgb(248,203,102);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g transform="matrix(260.4,0,0,280,52.6877,289.686)">
|
||||
<path d="M0.488,-0.47C0.488,-0.441 0.484,-0.412 0.476,-0.385C0.468,-0.357 0.455,-0.333 0.439,-0.312C0.422,-0.29 0.4,-0.274 0.374,-0.261C0.348,-0.248 0.318,-0.242 0.282,-0.242L0.173,-0.242L0.173,0L0.055,0L0.055,-0.688L0.277,-0.688C0.314,-0.688 0.345,-0.683 0.371,-0.672C0.398,-0.662 0.419,-0.647 0.437,-0.627C0.454,-0.608 0.467,-0.585 0.476,-0.559C0.484,-0.532 0.488,-0.502 0.488,-0.47ZM0.369,-0.468C0.369,-0.503 0.36,-0.53 0.343,-0.549C0.326,-0.567 0.299,-0.576 0.264,-0.576L0.173,-0.576L0.173,-0.353L0.268,-0.353C0.285,-0.353 0.3,-0.356 0.313,-0.361C0.326,-0.367 0.336,-0.375 0.345,-0.385C0.353,-0.395 0.359,-0.407 0.363,-0.421C0.367,-0.435 0.369,-0.451 0.369,-0.468Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(260.4,0,0,280,184.157,289.686)">
|
||||
<path d="M0.38,0L0.38,-0.273L0.173,-0.273L0.173,0L0.055,0L0.055,-0.688L0.173,-0.688L0.173,-0.382L0.38,-0.382L0.38,-0.688L0.498,-0.688L0.498,0L0.38,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(260.4,0,0,280,327.324,289.686)">
|
||||
<path d="M0.488,-0.47C0.488,-0.441 0.484,-0.412 0.476,-0.385C0.468,-0.357 0.455,-0.333 0.439,-0.312C0.422,-0.29 0.4,-0.274 0.374,-0.261C0.348,-0.248 0.318,-0.242 0.282,-0.242L0.173,-0.242L0.173,0L0.055,0L0.055,-0.688L0.277,-0.688C0.314,-0.688 0.345,-0.683 0.371,-0.672C0.398,-0.662 0.419,-0.647 0.437,-0.627C0.454,-0.608 0.467,-0.585 0.476,-0.559C0.484,-0.532 0.488,-0.502 0.488,-0.47ZM0.369,-0.468C0.369,-0.503 0.36,-0.53 0.343,-0.549C0.326,-0.567 0.299,-0.576 0.264,-0.576L0.173,-0.576L0.173,-0.353L0.268,-0.353C0.285,-0.353 0.3,-0.356 0.313,-0.361C0.326,-0.367 0.336,-0.375 0.345,-0.385C0.353,-0.395 0.359,-0.407 0.363,-0.421C0.367,-0.435 0.369,-0.451 0.369,-0.468Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g transform="matrix(260.4,0,0,280,640.738,289.686)">
|
||||
<path d="M0.453,0L0.352,-0.161L0.128,-0.161L0.128,0L0.021,0L0.021,-0.688L0.128,-0.688L0.57,0L0.453,0ZM0.282,-0.27L0.128,-0.515L0.128,-0.27L0.282,-0.27Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(260.4,0,0,280,787.905,289.686)">
|
||||
<rect x="0.055" y="-0.688" width="0.119" height="0.688" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(260.4,0,0,280,816.346,289.686)">
|
||||
<path d="M0.124,0L0.124,-0.688L0.242,-0.688L0.242,-0.111L0.499,-0.111L0.499,0L0.124,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(260.4,0,0,280,936.864,289.686)">
|
||||
<path d="M0.089,0L0.089,-0.688L0.483,-0.688L0.483,-0.577L0.207,-0.577L0.207,-0.382L0.459,-0.382L0.459,-0.271L0.207,-0.271L0.207,-0.111L0.499,-0.111L0.499,0L0.089,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(233.533,0,0,280,1069.8,289.686)">
|
||||
<path d="M0.442,0L0.312,-0.261L0.173,-0.261L0.173,0L0.055,0L0.055,-0.688L0.336,-0.688C0.372,-0.688 0.402,-0.683 0.429,-0.674C0.455,-0.664 0.477,-0.65 0.495,-0.633C0.512,-0.615 0.525,-0.593 0.534,-0.568C0.543,-0.543 0.547,-0.514 0.547,-0.483C0.547,-0.457 0.544,-0.434 0.538,-0.412C0.531,-0.391 0.523,-0.372 0.512,-0.355C0.501,-0.339 0.487,-0.325 0.472,-0.314C0.457,-0.302 0.44,-0.294 0.422,-0.289L0.575,0L0.442,0ZM0.428,-0.477C0.428,-0.511 0.419,-0.535 0.401,-0.552C0.383,-0.568 0.357,-0.576 0.324,-0.576L0.173,-0.576L0.173,-0.373L0.327,-0.373C0.345,-0.373 0.36,-0.376 0.373,-0.381C0.385,-0.386 0.396,-0.393 0.404,-0.402C0.412,-0.411 0.418,-0.422 0.422,-0.435C0.426,-0.448 0.428,-0.462 0.428,-0.477Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,73.8296,353)">
|
||||
<g transform="matrix(41,0,0,41,0,29.709)">
|
||||
<path d="M0.352,-0.612L0.352,0L0.259,0L0.259,-0.612L0.022,-0.612L0.022,-0.688L0.588,-0.688L0.588,-0.612L0.352,-0.612Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,25.0444,29.709)">
|
||||
<path d="M0.155,-0.438C0.165,-0.456 0.175,-0.471 0.187,-0.484C0.198,-0.496 0.21,-0.507 0.224,-0.515C0.238,-0.523 0.253,-0.529 0.269,-0.532C0.285,-0.536 0.304,-0.538 0.324,-0.538C0.358,-0.538 0.385,-0.534 0.407,-0.524C0.429,-0.515 0.446,-0.503 0.458,-0.486C0.471,-0.47 0.479,-0.45 0.484,-0.427C0.489,-0.404 0.491,-0.379 0.491,-0.352L0.491,0L0.403,0L0.403,-0.335C0.403,-0.357 0.401,-0.377 0.399,-0.394C0.396,-0.411 0.391,-0.425 0.383,-0.436C0.375,-0.448 0.364,-0.456 0.35,-0.462C0.335,-0.467 0.317,-0.47 0.294,-0.47C0.273,-0.47 0.254,-0.466 0.238,-0.459C0.221,-0.451 0.206,-0.441 0.195,-0.427C0.183,-0.414 0.174,-0.397 0.167,-0.377C0.16,-0.358 0.157,-0.336 0.157,-0.312L0.157,0L0.069,0L0.069,-0.725L0.157,-0.725L0.157,-0.536C0.157,-0.525 0.157,-0.515 0.157,-0.504C0.156,-0.493 0.156,-0.483 0.156,-0.474C0.155,-0.465 0.155,-0.457 0.154,-0.451C0.154,-0.445 0.154,-0.44 0.153,-0.438L0.155,-0.438Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,47.8467,29.709)">
|
||||
<path d="M0.135,-0.246C0.135,-0.218 0.138,-0.192 0.143,-0.169C0.149,-0.146 0.158,-0.126 0.17,-0.109C0.182,-0.092 0.197,-0.079 0.215,-0.07C0.234,-0.061 0.256,-0.056 0.282,-0.056C0.32,-0.056 0.351,-0.064 0.374,-0.079C0.397,-0.094 0.412,-0.114 0.42,-0.137L0.498,-0.115C0.492,-0.101 0.484,-0.086 0.474,-0.071C0.464,-0.056 0.451,-0.043 0.435,-0.031C0.418,-0.019 0.397,-0.009 0.372,-0.002C0.347,0.006 0.317,0.01 0.282,0.01C0.204,0.01 0.145,-0.014 0.104,-0.06C0.063,-0.107 0.042,-0.176 0.042,-0.268C0.042,-0.317 0.049,-0.359 0.061,-0.393C0.073,-0.428 0.09,-0.456 0.112,-0.477C0.133,-0.499 0.158,-0.514 0.187,-0.524C0.216,-0.533 0.246,-0.538 0.279,-0.538C0.323,-0.538 0.36,-0.531 0.39,-0.517C0.42,-0.502 0.444,-0.483 0.462,-0.457C0.48,-0.432 0.493,-0.402 0.5,-0.368C0.508,-0.334 0.512,-0.297 0.512,-0.257L0.512,-0.246L0.135,-0.246ZM0.421,-0.313C0.416,-0.369 0.402,-0.409 0.378,-0.435C0.355,-0.46 0.321,-0.473 0.277,-0.473C0.263,-0.473 0.247,-0.471 0.231,-0.466C0.215,-0.461 0.2,-0.453 0.187,-0.441C0.173,-0.429 0.161,-0.413 0.152,-0.392C0.142,-0.371 0.137,-0.345 0.136,-0.313L0.421,-0.313Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,82.04,29.709)">
|
||||
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,109.387,29.709)">
|
||||
<path d="M0.547,0L0.547,-0.319L0.175,-0.319L0.175,0L0.082,0L0.082,-0.688L0.175,-0.688L0.175,-0.397L0.547,-0.397L0.547,-0.688L0.641,-0.688L0.641,0L0.547,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,138.996,29.709)">
|
||||
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,176.993,29.709)">
|
||||
<path d="M0.135,-0.246C0.135,-0.218 0.138,-0.192 0.143,-0.169C0.149,-0.146 0.158,-0.126 0.17,-0.109C0.182,-0.092 0.197,-0.079 0.215,-0.07C0.234,-0.061 0.256,-0.056 0.282,-0.056C0.32,-0.056 0.351,-0.064 0.374,-0.079C0.397,-0.094 0.412,-0.114 0.42,-0.137L0.498,-0.115C0.492,-0.101 0.484,-0.086 0.474,-0.071C0.464,-0.056 0.451,-0.043 0.435,-0.031C0.418,-0.019 0.397,-0.009 0.372,-0.002C0.347,0.006 0.317,0.01 0.282,0.01C0.204,0.01 0.145,-0.014 0.104,-0.06C0.063,-0.107 0.042,-0.176 0.042,-0.268C0.042,-0.317 0.049,-0.359 0.061,-0.393C0.073,-0.428 0.09,-0.456 0.112,-0.477C0.133,-0.499 0.158,-0.514 0.187,-0.524C0.216,-0.533 0.246,-0.538 0.279,-0.538C0.323,-0.538 0.36,-0.531 0.39,-0.517C0.42,-0.502 0.444,-0.483 0.462,-0.457C0.48,-0.432 0.493,-0.402 0.5,-0.368C0.508,-0.334 0.512,-0.297 0.512,-0.257L0.512,-0.246L0.135,-0.246ZM0.421,-0.313C0.416,-0.369 0.402,-0.409 0.378,-0.435C0.355,-0.46 0.321,-0.473 0.277,-0.473C0.263,-0.473 0.247,-0.471 0.231,-0.466C0.215,-0.461 0.2,-0.453 0.187,-0.441C0.173,-0.429 0.161,-0.413 0.152,-0.392C0.142,-0.371 0.137,-0.345 0.136,-0.313L0.421,-0.313Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,199.795,29.709)">
|
||||
<path d="M0.375,0L0.375,-0.335C0.375,-0.361 0.373,-0.382 0.37,-0.399C0.367,-0.417 0.361,-0.431 0.354,-0.441C0.346,-0.452 0.336,-0.459 0.324,-0.464C0.311,-0.468 0.296,-0.47 0.278,-0.47C0.26,-0.47 0.243,-0.467 0.228,-0.459C0.213,-0.452 0.2,-0.441 0.19,-0.427C0.179,-0.414 0.171,-0.397 0.165,-0.376C0.16,-0.356 0.157,-0.333 0.157,-0.306L0.157,0L0.069,0L0.069,-0.416C0.069,-0.427 0.069,-0.438 0.069,-0.45C0.069,-0.463 0.069,-0.474 0.068,-0.485C0.068,-0.496 0.068,-0.505 0.067,-0.513C0.067,-0.521 0.067,-0.526 0.066,-0.528L0.149,-0.528C0.15,-0.527 0.15,-0.522 0.15,-0.515C0.151,-0.508 0.151,-0.5 0.152,-0.49C0.152,-0.481 0.153,-0.472 0.153,-0.462C0.153,-0.453 0.153,-0.444 0.153,-0.438L0.155,-0.438C0.163,-0.453 0.171,-0.467 0.18,-0.479C0.189,-0.492 0.2,-0.502 0.212,-0.511C0.224,-0.52 0.238,-0.526 0.254,-0.531C0.27,-0.536 0.288,-0.538 0.309,-0.538C0.349,-0.538 0.381,-0.53 0.404,-0.514C0.427,-0.498 0.444,-0.473 0.453,-0.438L0.454,-0.438C0.462,-0.453 0.471,-0.467 0.48,-0.479C0.49,-0.492 0.502,-0.502 0.515,-0.511C0.528,-0.52 0.542,-0.526 0.559,-0.531C0.575,-0.536 0.593,-0.538 0.614,-0.538C0.641,-0.538 0.664,-0.535 0.683,-0.527C0.703,-0.52 0.719,-0.509 0.731,-0.494C0.743,-0.479 0.752,-0.46 0.758,-0.436C0.764,-0.413 0.767,-0.385 0.767,-0.352L0.767,0L0.68,0L0.68,-0.335C0.68,-0.361 0.679,-0.382 0.675,-0.399C0.672,-0.417 0.667,-0.431 0.659,-0.441C0.651,-0.452 0.641,-0.459 0.629,-0.464C0.617,-0.468 0.601,-0.47 0.583,-0.47C0.565,-0.47 0.548,-0.467 0.533,-0.46C0.518,-0.453 0.505,-0.442 0.495,-0.429C0.484,-0.415 0.476,-0.398 0.47,-0.377C0.465,-0.357 0.462,-0.333 0.462,-0.306L0.462,0L0.375,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,233.948,29.709)">
|
||||
<path d="M0.202,0.01C0.149,0.01 0.109,-0.004 0.083,-0.032C0.056,-0.06 0.042,-0.099 0.042,-0.147C0.042,-0.182 0.049,-0.211 0.062,-0.233C0.075,-0.255 0.093,-0.273 0.114,-0.286C0.135,-0.298 0.16,-0.307 0.187,-0.312C0.214,-0.317 0.242,-0.32 0.271,-0.32L0.389,-0.322L0.389,-0.351C0.389,-0.373 0.387,-0.391 0.382,-0.407C0.378,-0.422 0.371,-0.434 0.361,-0.444C0.352,-0.453 0.34,-0.46 0.326,-0.465C0.312,-0.469 0.295,-0.471 0.276,-0.471C0.259,-0.471 0.244,-0.47 0.23,-0.468C0.216,-0.465 0.204,-0.461 0.194,-0.454C0.184,-0.448 0.176,-0.439 0.17,-0.428C0.164,-0.418 0.16,-0.404 0.158,-0.387L0.066,-0.396C0.069,-0.416 0.075,-0.435 0.084,-0.453C0.094,-0.47 0.107,-0.485 0.123,-0.498C0.14,-0.511 0.161,-0.521 0.186,-0.528C0.212,-0.535 0.242,-0.538 0.278,-0.538C0.344,-0.538 0.394,-0.523 0.428,-0.492C0.461,-0.462 0.478,-0.418 0.478,-0.36L0.478,-0.133C0.478,-0.107 0.481,-0.087 0.488,-0.074C0.495,-0.061 0.508,-0.054 0.527,-0.054C0.532,-0.054 0.537,-0.055 0.542,-0.055C0.547,-0.056 0.552,-0.057 0.556,-0.058L0.556,-0.003C0.545,0 0.534,0.002 0.523,0.003C0.512,0.004 0.501,0.005 0.488,0.005C0.472,0.005 0.457,0.003 0.446,-0.002C0.434,-0.006 0.424,-0.013 0.417,-0.022C0.409,-0.031 0.403,-0.042 0.399,-0.055C0.396,-0.068 0.393,-0.083 0.392,-0.101L0.389,-0.101C0.38,-0.084 0.369,-0.069 0.358,-0.055C0.347,-0.042 0.334,-0.03 0.319,-0.02C0.304,-0.011 0.287,-0.003 0.268,0.002C0.249,0.007 0.227,0.01 0.202,0.01ZM0.222,-0.056C0.25,-0.056 0.275,-0.061 0.296,-0.072C0.317,-0.082 0.334,-0.095 0.348,-0.111C0.362,-0.127 0.372,-0.144 0.379,-0.163C0.386,-0.182 0.389,-0.2 0.389,-0.217L0.389,-0.261L0.293,-0.259C0.271,-0.258 0.251,-0.257 0.232,-0.254C0.212,-0.251 0.195,-0.246 0.181,-0.238C0.166,-0.23 0.154,-0.218 0.146,-0.204C0.137,-0.189 0.133,-0.17 0.133,-0.146C0.133,-0.117 0.141,-0.095 0.156,-0.08C0.171,-0.064 0.194,-0.056 0.222,-0.056Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,256.75,29.709)">
|
||||
<path d="M0.067,-0.641L0.067,-0.725L0.155,-0.725L0.155,-0.641L0.067,-0.641ZM0.067,0L0.067,-0.528L0.155,-0.528L0.155,0L0.067,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,265.859,29.709)">
|
||||
<rect x="0.067" y="-0.725" width="0.088" height="0.725" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,286.359,29.709)">
|
||||
<path d="M0.134,-0.267C0.134,-0.236 0.136,-0.208 0.141,-0.183C0.145,-0.158 0.153,-0.136 0.163,-0.117C0.174,-0.099 0.187,-0.085 0.204,-0.075C0.221,-0.065 0.243,-0.06 0.268,-0.06C0.299,-0.06 0.325,-0.068 0.346,-0.085C0.367,-0.102 0.38,-0.128 0.385,-0.163L0.474,-0.157C0.471,-0.135 0.464,-0.114 0.455,-0.094C0.445,-0.074 0.432,-0.056 0.415,-0.041C0.398,-0.026 0.378,-0.013 0.354,-0.004C0.329,0.005 0.302,0.01 0.27,0.01C0.229,0.01 0.194,0.003 0.165,-0.011C0.136,-0.025 0.112,-0.045 0.094,-0.069C0.076,-0.094 0.063,-0.123 0.055,-0.156C0.047,-0.189 0.042,-0.226 0.042,-0.265C0.042,-0.3 0.045,-0.331 0.051,-0.359C0.057,-0.386 0.065,-0.41 0.076,-0.43C0.087,-0.45 0.099,-0.467 0.113,-0.481C0.128,-0.495 0.143,-0.506 0.16,-0.514C0.177,-0.523 0.194,-0.529 0.213,-0.532C0.231,-0.536 0.25,-0.538 0.269,-0.538C0.299,-0.538 0.325,-0.534 0.348,-0.526C0.371,-0.518 0.391,-0.507 0.408,-0.492C0.425,-0.478 0.438,-0.462 0.449,-0.442C0.459,-0.423 0.466,-0.403 0.471,-0.38L0.38,-0.374C0.376,-0.403 0.364,-0.426 0.346,-0.443C0.327,-0.461 0.301,-0.469 0.267,-0.469C0.242,-0.469 0.221,-0.465 0.204,-0.457C0.187,-0.448 0.174,-0.436 0.163,-0.419C0.153,-0.402 0.145,-0.381 0.141,-0.356C0.136,-0.331 0.134,-0.301 0.134,-0.267Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,306.859,29.709)">
|
||||
<rect x="0.067" y="-0.725" width="0.088" height="0.725" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,315.968,29.709)">
|
||||
<path d="M0.202,0.01C0.149,0.01 0.109,-0.004 0.083,-0.032C0.056,-0.06 0.042,-0.099 0.042,-0.147C0.042,-0.182 0.049,-0.211 0.062,-0.233C0.075,-0.255 0.093,-0.273 0.114,-0.286C0.135,-0.298 0.16,-0.307 0.187,-0.312C0.214,-0.317 0.242,-0.32 0.271,-0.32L0.389,-0.322L0.389,-0.351C0.389,-0.373 0.387,-0.391 0.382,-0.407C0.378,-0.422 0.371,-0.434 0.361,-0.444C0.352,-0.453 0.34,-0.46 0.326,-0.465C0.312,-0.469 0.295,-0.471 0.276,-0.471C0.259,-0.471 0.244,-0.47 0.23,-0.468C0.216,-0.465 0.204,-0.461 0.194,-0.454C0.184,-0.448 0.176,-0.439 0.17,-0.428C0.164,-0.418 0.16,-0.404 0.158,-0.387L0.066,-0.396C0.069,-0.416 0.075,-0.435 0.084,-0.453C0.094,-0.47 0.107,-0.485 0.123,-0.498C0.14,-0.511 0.161,-0.521 0.186,-0.528C0.212,-0.535 0.242,-0.538 0.278,-0.538C0.344,-0.538 0.394,-0.523 0.428,-0.492C0.461,-0.462 0.478,-0.418 0.478,-0.36L0.478,-0.133C0.478,-0.107 0.481,-0.087 0.488,-0.074C0.495,-0.061 0.508,-0.054 0.527,-0.054C0.532,-0.054 0.537,-0.055 0.542,-0.055C0.547,-0.056 0.552,-0.057 0.556,-0.058L0.556,-0.003C0.545,0 0.534,0.002 0.523,0.003C0.512,0.004 0.501,0.005 0.488,0.005C0.472,0.005 0.457,0.003 0.446,-0.002C0.434,-0.006 0.424,-0.013 0.417,-0.022C0.409,-0.031 0.403,-0.042 0.399,-0.055C0.396,-0.068 0.393,-0.083 0.392,-0.101L0.389,-0.101C0.38,-0.084 0.369,-0.069 0.358,-0.055C0.347,-0.042 0.334,-0.03 0.319,-0.02C0.304,-0.011 0.287,-0.003 0.268,0.002C0.249,0.007 0.227,0.01 0.202,0.01ZM0.222,-0.056C0.25,-0.056 0.275,-0.061 0.296,-0.072C0.317,-0.082 0.334,-0.095 0.348,-0.111C0.362,-0.127 0.372,-0.144 0.379,-0.163C0.386,-0.182 0.389,-0.2 0.389,-0.217L0.389,-0.261L0.293,-0.259C0.271,-0.258 0.251,-0.257 0.232,-0.254C0.212,-0.251 0.195,-0.246 0.181,-0.238C0.166,-0.23 0.154,-0.218 0.146,-0.204C0.137,-0.189 0.133,-0.17 0.133,-0.146C0.133,-0.117 0.141,-0.095 0.156,-0.08C0.171,-0.064 0.194,-0.056 0.222,-0.056Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,338.771,29.709)">
|
||||
<path d="M0.464,-0.146C0.464,-0.121 0.459,-0.099 0.449,-0.08C0.44,-0.06 0.426,-0.044 0.408,-0.031C0.389,-0.018 0.367,-0.008 0.341,-0.001C0.314,0.006 0.284,0.01 0.25,0.01C0.219,0.01 0.191,0.007 0.167,0.003C0.142,-0.002 0.121,-0.01 0.102,-0.02C0.083,-0.03 0.068,-0.044 0.055,-0.061C0.043,-0.078 0.034,-0.099 0.028,-0.124L0.105,-0.139C0.113,-0.111 0.128,-0.09 0.152,-0.077C0.175,-0.064 0.208,-0.057 0.25,-0.057C0.268,-0.057 0.286,-0.058 0.302,-0.061C0.317,-0.064 0.331,-0.068 0.342,-0.074C0.354,-0.081 0.363,-0.089 0.369,-0.1C0.375,-0.11 0.378,-0.124 0.378,-0.139C0.378,-0.155 0.375,-0.168 0.367,-0.178C0.36,-0.189 0.349,-0.197 0.336,-0.204C0.323,-0.211 0.306,-0.217 0.287,-0.222C0.268,-0.227 0.247,-0.233 0.225,-0.239C0.203,-0.244 0.182,-0.25 0.162,-0.257C0.141,-0.264 0.122,-0.273 0.105,-0.284C0.088,-0.296 0.075,-0.31 0.064,-0.326C0.054,-0.343 0.049,-0.364 0.049,-0.389C0.049,-0.437 0.066,-0.474 0.1,-0.499C0.135,-0.524 0.185,-0.537 0.25,-0.537C0.309,-0.537 0.355,-0.526 0.389,-0.506C0.424,-0.485 0.445,-0.452 0.455,-0.407L0.375,-0.397C0.373,-0.411 0.367,-0.423 0.359,-0.432C0.352,-0.441 0.342,-0.449 0.331,-0.454C0.32,-0.46 0.308,-0.464 0.294,-0.467C0.28,-0.469 0.265,-0.47 0.25,-0.47C0.211,-0.47 0.181,-0.464 0.163,-0.452C0.144,-0.44 0.134,-0.422 0.134,-0.397C0.134,-0.383 0.138,-0.371 0.145,-0.362C0.152,-0.353 0.162,-0.345 0.174,-0.339C0.187,-0.332 0.202,-0.327 0.219,-0.322C0.237,-0.317 0.256,-0.312 0.277,-0.307C0.291,-0.304 0.306,-0.3 0.32,-0.296C0.335,-0.292 0.349,-0.287 0.363,-0.281C0.377,-0.275 0.39,-0.269 0.402,-0.261C0.414,-0.253 0.425,-0.244 0.434,-0.233C0.443,-0.223 0.45,-0.21 0.456,-0.196C0.461,-0.181 0.464,-0.165 0.464,-0.146Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,359.271,29.709)">
|
||||
<path d="M0.464,-0.146C0.464,-0.121 0.459,-0.099 0.449,-0.08C0.44,-0.06 0.426,-0.044 0.408,-0.031C0.389,-0.018 0.367,-0.008 0.341,-0.001C0.314,0.006 0.284,0.01 0.25,0.01C0.219,0.01 0.191,0.007 0.167,0.003C0.142,-0.002 0.121,-0.01 0.102,-0.02C0.083,-0.03 0.068,-0.044 0.055,-0.061C0.043,-0.078 0.034,-0.099 0.028,-0.124L0.105,-0.139C0.113,-0.111 0.128,-0.09 0.152,-0.077C0.175,-0.064 0.208,-0.057 0.25,-0.057C0.268,-0.057 0.286,-0.058 0.302,-0.061C0.317,-0.064 0.331,-0.068 0.342,-0.074C0.354,-0.081 0.363,-0.089 0.369,-0.1C0.375,-0.11 0.378,-0.124 0.378,-0.139C0.378,-0.155 0.375,-0.168 0.367,-0.178C0.36,-0.189 0.349,-0.197 0.336,-0.204C0.323,-0.211 0.306,-0.217 0.287,-0.222C0.268,-0.227 0.247,-0.233 0.225,-0.239C0.203,-0.244 0.182,-0.25 0.162,-0.257C0.141,-0.264 0.122,-0.273 0.105,-0.284C0.088,-0.296 0.075,-0.31 0.064,-0.326C0.054,-0.343 0.049,-0.364 0.049,-0.389C0.049,-0.437 0.066,-0.474 0.1,-0.499C0.135,-0.524 0.185,-0.537 0.25,-0.537C0.309,-0.537 0.355,-0.526 0.389,-0.506C0.424,-0.485 0.445,-0.452 0.455,-0.407L0.375,-0.397C0.373,-0.411 0.367,-0.423 0.359,-0.432C0.352,-0.441 0.342,-0.449 0.331,-0.454C0.32,-0.46 0.308,-0.464 0.294,-0.467C0.28,-0.469 0.265,-0.47 0.25,-0.47C0.211,-0.47 0.181,-0.464 0.163,-0.452C0.144,-0.44 0.134,-0.422 0.134,-0.397C0.134,-0.383 0.138,-0.371 0.145,-0.362C0.152,-0.353 0.162,-0.345 0.174,-0.339C0.187,-0.332 0.202,-0.327 0.219,-0.322C0.237,-0.317 0.256,-0.312 0.277,-0.307C0.291,-0.304 0.306,-0.3 0.32,-0.296C0.335,-0.292 0.349,-0.287 0.363,-0.281C0.377,-0.275 0.39,-0.269 0.402,-0.261C0.414,-0.253 0.425,-0.244 0.434,-0.233C0.443,-0.223 0.45,-0.21 0.456,-0.196C0.461,-0.181 0.464,-0.165 0.464,-0.146Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,391.162,29.709)">
|
||||
<path d="M0.155,-0.438C0.165,-0.456 0.175,-0.471 0.187,-0.484C0.198,-0.496 0.21,-0.507 0.224,-0.515C0.238,-0.523 0.253,-0.529 0.269,-0.532C0.285,-0.536 0.304,-0.538 0.324,-0.538C0.358,-0.538 0.385,-0.534 0.407,-0.524C0.429,-0.515 0.446,-0.503 0.458,-0.486C0.471,-0.47 0.479,-0.45 0.484,-0.427C0.489,-0.404 0.491,-0.379 0.491,-0.352L0.491,0L0.403,0L0.403,-0.335C0.403,-0.357 0.401,-0.377 0.399,-0.394C0.396,-0.411 0.391,-0.425 0.383,-0.436C0.375,-0.448 0.364,-0.456 0.35,-0.462C0.335,-0.467 0.317,-0.47 0.294,-0.47C0.273,-0.47 0.254,-0.466 0.238,-0.459C0.221,-0.451 0.206,-0.441 0.195,-0.427C0.183,-0.414 0.174,-0.397 0.167,-0.377C0.16,-0.358 0.157,-0.336 0.157,-0.312L0.157,0L0.069,0L0.069,-0.725L0.157,-0.725L0.157,-0.536C0.157,-0.525 0.157,-0.515 0.157,-0.504C0.156,-0.493 0.156,-0.483 0.156,-0.474C0.155,-0.465 0.155,-0.457 0.154,-0.451C0.154,-0.445 0.154,-0.44 0.153,-0.438L0.155,-0.438Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,413.964,29.709)">
|
||||
<path d="M0.271,-0.004C0.257,0 0.244,0.003 0.23,0.005C0.216,0.007 0.2,0.008 0.182,0.008C0.111,0.008 0.076,-0.032 0.076,-0.112L0.076,-0.464L0.015,-0.464L0.015,-0.528L0.08,-0.528L0.105,-0.646L0.164,-0.646L0.164,-0.528L0.262,-0.528L0.262,-0.464L0.164,-0.464L0.164,-0.131C0.164,-0.105 0.168,-0.088 0.177,-0.077C0.185,-0.067 0.199,-0.062 0.22,-0.062C0.228,-0.062 0.236,-0.063 0.244,-0.064C0.252,-0.065 0.261,-0.067 0.271,-0.069L0.271,-0.004Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,425.355,29.709)">
|
||||
<path d="M0.271,-0.004C0.257,0 0.244,0.003 0.23,0.005C0.216,0.007 0.2,0.008 0.182,0.008C0.111,0.008 0.076,-0.032 0.076,-0.112L0.076,-0.464L0.015,-0.464L0.015,-0.528L0.08,-0.528L0.105,-0.646L0.164,-0.646L0.164,-0.528L0.262,-0.528L0.262,-0.464L0.164,-0.464L0.164,-0.131C0.164,-0.105 0.168,-0.088 0.177,-0.077C0.185,-0.067 0.199,-0.062 0.22,-0.062C0.228,-0.062 0.236,-0.063 0.244,-0.064C0.252,-0.065 0.261,-0.067 0.271,-0.069L0.271,-0.004Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,436.746,29.709)">
|
||||
<path d="M0.514,-0.267C0.514,-0.227 0.511,-0.19 0.504,-0.156C0.498,-0.122 0.487,-0.093 0.472,-0.068C0.457,-0.044 0.437,-0.025 0.412,-0.011C0.387,0.003 0.356,0.01 0.32,0.01C0.282,0.01 0.249,0.003 0.221,-0.012C0.192,-0.026 0.171,-0.049 0.156,-0.082L0.153,-0.082C0.154,-0.081 0.154,-0.078 0.154,-0.073C0.154,-0.068 0.154,-0.062 0.155,-0.054C0.155,-0.046 0.155,-0.037 0.155,-0.028C0.155,-0.018 0.155,-0.008 0.155,0.001L0.155,0.208L0.067,0.208L0.067,-0.42C0.067,-0.433 0.067,-0.445 0.067,-0.457C0.067,-0.469 0.067,-0.479 0.066,-0.489C0.066,-0.499 0.066,-0.507 0.065,-0.514C0.065,-0.521 0.065,-0.525 0.064,-0.528L0.149,-0.528C0.15,-0.527 0.15,-0.524 0.151,-0.518C0.151,-0.512 0.152,-0.505 0.152,-0.497C0.153,-0.489 0.153,-0.48 0.154,-0.47C0.154,-0.461 0.154,-0.452 0.154,-0.443L0.156,-0.443C0.164,-0.46 0.174,-0.475 0.184,-0.487C0.194,-0.498 0.206,-0.508 0.22,-0.516C0.233,-0.524 0.248,-0.529 0.264,-0.532C0.281,-0.536 0.299,-0.538 0.32,-0.538C0.356,-0.538 0.387,-0.531 0.412,-0.518C0.437,-0.505 0.457,-0.487 0.472,-0.463C0.487,-0.44 0.498,-0.411 0.504,-0.378C0.511,-0.344 0.514,-0.307 0.514,-0.267ZM0.422,-0.265C0.422,-0.297 0.42,-0.326 0.416,-0.352C0.412,-0.377 0.405,-0.398 0.396,-0.416C0.386,-0.434 0.373,-0.447 0.357,-0.456C0.341,-0.465 0.321,-0.47 0.297,-0.47C0.278,-0.47 0.259,-0.467 0.242,-0.461C0.225,-0.456 0.21,-0.445 0.197,-0.43C0.184,-0.414 0.174,-0.392 0.167,-0.365C0.159,-0.337 0.155,-0.302 0.155,-0.258C0.155,-0.22 0.158,-0.189 0.165,-0.163C0.171,-0.137 0.18,-0.116 0.192,-0.1C0.204,-0.084 0.218,-0.073 0.236,-0.066C0.253,-0.059 0.274,-0.055 0.296,-0.055C0.321,-0.055 0.341,-0.06 0.357,-0.069C0.373,-0.079 0.386,-0.092 0.396,-0.11C0.405,-0.128 0.412,-0.15 0.416,-0.176C0.42,-0.202 0.422,-0.231 0.422,-0.265Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,459.548,29.709)">
|
||||
<path d="M0.464,-0.146C0.464,-0.121 0.459,-0.099 0.449,-0.08C0.44,-0.06 0.426,-0.044 0.408,-0.031C0.389,-0.018 0.367,-0.008 0.341,-0.001C0.314,0.006 0.284,0.01 0.25,0.01C0.219,0.01 0.191,0.007 0.167,0.003C0.142,-0.002 0.121,-0.01 0.102,-0.02C0.083,-0.03 0.068,-0.044 0.055,-0.061C0.043,-0.078 0.034,-0.099 0.028,-0.124L0.105,-0.139C0.113,-0.111 0.128,-0.09 0.152,-0.077C0.175,-0.064 0.208,-0.057 0.25,-0.057C0.268,-0.057 0.286,-0.058 0.302,-0.061C0.317,-0.064 0.331,-0.068 0.342,-0.074C0.354,-0.081 0.363,-0.089 0.369,-0.1C0.375,-0.11 0.378,-0.124 0.378,-0.139C0.378,-0.155 0.375,-0.168 0.367,-0.178C0.36,-0.189 0.349,-0.197 0.336,-0.204C0.323,-0.211 0.306,-0.217 0.287,-0.222C0.268,-0.227 0.247,-0.233 0.225,-0.239C0.203,-0.244 0.182,-0.25 0.162,-0.257C0.141,-0.264 0.122,-0.273 0.105,-0.284C0.088,-0.296 0.075,-0.31 0.064,-0.326C0.054,-0.343 0.049,-0.364 0.049,-0.389C0.049,-0.437 0.066,-0.474 0.1,-0.499C0.135,-0.524 0.185,-0.537 0.25,-0.537C0.309,-0.537 0.355,-0.526 0.389,-0.506C0.424,-0.485 0.445,-0.452 0.455,-0.407L0.375,-0.397C0.373,-0.411 0.367,-0.423 0.359,-0.432C0.352,-0.441 0.342,-0.449 0.331,-0.454C0.32,-0.46 0.308,-0.464 0.294,-0.467C0.28,-0.469 0.265,-0.47 0.25,-0.47C0.211,-0.47 0.181,-0.464 0.163,-0.452C0.144,-0.44 0.134,-0.422 0.134,-0.397C0.134,-0.383 0.138,-0.371 0.145,-0.362C0.152,-0.353 0.162,-0.345 0.174,-0.339C0.187,-0.332 0.202,-0.327 0.219,-0.322C0.237,-0.317 0.256,-0.312 0.277,-0.307C0.291,-0.304 0.306,-0.3 0.32,-0.296C0.335,-0.292 0.349,-0.287 0.363,-0.281C0.377,-0.275 0.39,-0.269 0.402,-0.261C0.414,-0.253 0.425,-0.244 0.434,-0.233C0.443,-0.223 0.45,-0.21 0.456,-0.196C0.461,-0.181 0.464,-0.165 0.464,-0.146Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,480.048,29.709)">
|
||||
<path d="M0.091,-0.427L0.091,-0.528L0.187,-0.528L0.187,-0.427L0.091,-0.427ZM0.091,0L0.091,-0.101L0.187,-0.101L0.187,0L0.091,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,491.439,29.709)">
|
||||
<path d="M0,0.01L0.201,-0.725L0.278,-0.725L0.079,0.01L0,0.01Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,502.831,29.709)">
|
||||
<path d="M0,0.01L0.201,-0.725L0.278,-0.725L0.079,0.01L0,0.01Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,514.222,29.709)">
|
||||
<path d="M0.268,0.208C0.237,0.208 0.21,0.204 0.187,0.198C0.164,0.192 0.144,0.183 0.127,0.172C0.11,0.16 0.097,0.146 0.086,0.13C0.076,0.114 0.069,0.097 0.064,0.077L0.152,0.064C0.158,0.089 0.171,0.108 0.191,0.121C0.211,0.134 0.237,0.141 0.27,0.141C0.29,0.141 0.308,0.138 0.324,0.132C0.34,0.127 0.354,0.118 0.366,0.106C0.377,0.094 0.386,0.078 0.392,0.058C0.398,0.039 0.401,0.015 0.401,-0.013L0.401,-0.098L0.4,-0.098C0.394,-0.085 0.386,-0.072 0.376,-0.06C0.367,-0.048 0.355,-0.037 0.341,-0.027C0.327,-0.018 0.311,-0.01 0.293,-0.005C0.275,0.001 0.254,0.004 0.23,0.004C0.197,0.004 0.168,-0.002 0.144,-0.013C0.12,-0.024 0.101,-0.041 0.086,-0.063C0.071,-0.086 0.059,-0.114 0.052,-0.147C0.045,-0.181 0.042,-0.219 0.042,-0.263C0.042,-0.306 0.045,-0.344 0.052,-0.377C0.059,-0.411 0.071,-0.44 0.087,-0.464C0.102,-0.487 0.123,-0.505 0.148,-0.518C0.173,-0.53 0.204,-0.537 0.24,-0.537C0.278,-0.537 0.31,-0.528 0.338,-0.511C0.365,-0.494 0.386,-0.47 0.401,-0.438L0.402,-0.438C0.402,-0.446 0.403,-0.455 0.403,-0.465C0.404,-0.475 0.404,-0.485 0.405,-0.494C0.405,-0.503 0.406,-0.511 0.406,-0.517C0.407,-0.524 0.408,-0.527 0.408,-0.528L0.492,-0.528C0.491,-0.525 0.491,-0.52 0.491,-0.513C0.49,-0.506 0.49,-0.498 0.49,-0.488C0.489,-0.479 0.489,-0.468 0.489,-0.456C0.489,-0.444 0.489,-0.432 0.489,-0.419L0.489,-0.015C0.489,0.059 0.471,0.114 0.434,0.152C0.398,0.189 0.342,0.208 0.268,0.208ZM0.401,-0.264C0.401,-0.301 0.397,-0.332 0.389,-0.359C0.381,-0.385 0.371,-0.406 0.358,-0.423C0.345,-0.439 0.33,-0.452 0.313,-0.459C0.296,-0.467 0.279,-0.471 0.262,-0.471C0.239,-0.471 0.22,-0.467 0.204,-0.459C0.188,-0.452 0.174,-0.439 0.164,-0.423C0.153,-0.406 0.145,-0.384 0.14,-0.358C0.135,-0.332 0.133,-0.301 0.133,-0.264C0.133,-0.226 0.135,-0.194 0.14,-0.168C0.145,-0.142 0.153,-0.121 0.164,-0.105C0.174,-0.09 0.187,-0.078 0.203,-0.071C0.219,-0.064 0.238,-0.061 0.26,-0.061C0.278,-0.061 0.295,-0.065 0.312,-0.072C0.329,-0.08 0.344,-0.092 0.357,-0.108C0.37,-0.124 0.381,-0.145 0.389,-0.171C0.397,-0.197 0.401,-0.228 0.401,-0.264Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,537.024,29.709)">
|
||||
<path d="M0.067,-0.641L0.067,-0.725L0.155,-0.725L0.155,-0.641L0.067,-0.641ZM0.067,0L0.067,-0.528L0.155,-0.528L0.155,0L0.067,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,546.133,29.709)">
|
||||
<path d="M0.271,-0.004C0.257,0 0.244,0.003 0.23,0.005C0.216,0.007 0.2,0.008 0.182,0.008C0.111,0.008 0.076,-0.032 0.076,-0.112L0.076,-0.464L0.015,-0.464L0.015,-0.528L0.08,-0.528L0.105,-0.646L0.164,-0.646L0.164,-0.528L0.262,-0.528L0.262,-0.464L0.164,-0.464L0.164,-0.131C0.164,-0.105 0.168,-0.088 0.177,-0.077C0.185,-0.067 0.199,-0.062 0.22,-0.062C0.228,-0.062 0.236,-0.063 0.244,-0.064C0.252,-0.065 0.261,-0.067 0.271,-0.069L0.271,-0.004Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,557.524,29.709)">
|
||||
<path d="M0.155,-0.438C0.165,-0.456 0.175,-0.471 0.187,-0.484C0.198,-0.496 0.21,-0.507 0.224,-0.515C0.238,-0.523 0.253,-0.529 0.269,-0.532C0.285,-0.536 0.304,-0.538 0.324,-0.538C0.358,-0.538 0.385,-0.534 0.407,-0.524C0.429,-0.515 0.446,-0.503 0.458,-0.486C0.471,-0.47 0.479,-0.45 0.484,-0.427C0.489,-0.404 0.491,-0.379 0.491,-0.352L0.491,0L0.403,0L0.403,-0.335C0.403,-0.357 0.401,-0.377 0.399,-0.394C0.396,-0.411 0.391,-0.425 0.383,-0.436C0.375,-0.448 0.364,-0.456 0.35,-0.462C0.335,-0.467 0.317,-0.47 0.294,-0.47C0.273,-0.47 0.254,-0.466 0.238,-0.459C0.221,-0.451 0.206,-0.441 0.195,-0.427C0.183,-0.414 0.174,-0.397 0.167,-0.377C0.16,-0.358 0.157,-0.336 0.157,-0.312L0.157,0L0.069,0L0.069,-0.725L0.157,-0.725L0.157,-0.536C0.157,-0.525 0.157,-0.515 0.157,-0.504C0.156,-0.493 0.156,-0.483 0.156,-0.474C0.155,-0.465 0.155,-0.457 0.154,-0.451C0.154,-0.445 0.154,-0.44 0.153,-0.438L0.155,-0.438Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,580.326,29.709)">
|
||||
<path d="M0.153,-0.528L0.153,-0.193C0.153,-0.168 0.155,-0.146 0.159,-0.129C0.163,-0.112 0.169,-0.098 0.177,-0.087C0.186,-0.077 0.197,-0.069 0.211,-0.065C0.225,-0.06 0.242,-0.058 0.262,-0.058C0.283,-0.058 0.302,-0.062 0.319,-0.069C0.335,-0.076 0.35,-0.087 0.362,-0.101C0.373,-0.115 0.383,-0.132 0.389,-0.152C0.396,-0.172 0.399,-0.196 0.399,-0.222L0.399,-0.528L0.487,-0.528L0.487,-0.113C0.487,-0.102 0.487,-0.09 0.487,-0.078C0.487,-0.066 0.487,-0.054 0.488,-0.043C0.488,-0.032 0.488,-0.023 0.489,-0.015C0.489,-0.007 0.489,-0.002 0.49,0L0.407,0C0.406,-0.002 0.406,-0.006 0.406,-0.013C0.405,-0.02 0.405,-0.029 0.405,-0.038C0.404,-0.047 0.404,-0.057 0.403,-0.066C0.403,-0.076 0.403,-0.084 0.403,-0.09L0.401,-0.09C0.393,-0.075 0.384,-0.061 0.374,-0.049C0.363,-0.036 0.352,-0.026 0.338,-0.017C0.325,-0.009 0.31,-0.002 0.292,0.003C0.275,0.007 0.255,0.01 0.232,0.01C0.203,0.01 0.178,0.006 0.157,-0.001C0.136,-0.008 0.118,-0.019 0.104,-0.034C0.091,-0.049 0.081,-0.068 0.074,-0.092C0.068,-0.115 0.065,-0.143 0.065,-0.176L0.065,-0.528L0.153,-0.528Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,603.128,29.709)">
|
||||
<path d="M0.514,-0.267C0.514,-0.082 0.449,0.01 0.32,0.01C0.28,0.01 0.247,0.003 0.22,-0.012C0.193,-0.026 0.172,-0.05 0.155,-0.082L0.154,-0.082C0.154,-0.074 0.154,-0.065 0.154,-0.056C0.153,-0.047 0.153,-0.038 0.152,-0.03C0.152,-0.022 0.151,-0.016 0.151,-0.01C0.15,-0.005 0.15,-0.001 0.149,0L0.064,0C0.065,-0.003 0.065,-0.008 0.065,-0.015C0.066,-0.022 0.066,-0.03 0.066,-0.04C0.067,-0.05 0.067,-0.061 0.067,-0.072C0.067,-0.084 0.067,-0.096 0.067,-0.109L0.067,-0.725L0.155,-0.725L0.155,-0.518C0.155,-0.508 0.155,-0.499 0.155,-0.49C0.155,-0.481 0.155,-0.473 0.154,-0.466C0.154,-0.458 0.154,-0.451 0.153,-0.443L0.155,-0.443C0.172,-0.477 0.193,-0.501 0.22,-0.516C0.247,-0.531 0.28,-0.538 0.32,-0.538C0.387,-0.538 0.436,-0.516 0.467,-0.471C0.498,-0.426 0.514,-0.358 0.514,-0.267ZM0.422,-0.264C0.422,-0.3 0.42,-0.331 0.415,-0.357C0.41,-0.383 0.403,-0.405 0.393,-0.422C0.383,-0.438 0.37,-0.451 0.354,-0.458C0.339,-0.466 0.32,-0.47 0.297,-0.47C0.274,-0.47 0.254,-0.466 0.236,-0.459C0.218,-0.451 0.204,-0.439 0.192,-0.423C0.18,-0.406 0.171,-0.384 0.165,-0.357C0.158,-0.33 0.155,-0.297 0.155,-0.258C0.155,-0.221 0.158,-0.189 0.165,-0.163C0.171,-0.137 0.18,-0.116 0.192,-0.1C0.204,-0.084 0.218,-0.073 0.236,-0.066C0.253,-0.059 0.274,-0.055 0.296,-0.055C0.318,-0.055 0.336,-0.059 0.352,-0.066C0.368,-0.074 0.381,-0.086 0.391,-0.103C0.402,-0.119 0.409,-0.141 0.414,-0.167C0.419,-0.194 0.422,-0.226 0.422,-0.264Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,625.931,29.709)">
|
||||
<rect x="0.091" y="-0.107" width="0.095" height="0.107" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,637.322,29.709)">
|
||||
<path d="M0.134,-0.267C0.134,-0.236 0.136,-0.208 0.141,-0.183C0.145,-0.158 0.153,-0.136 0.163,-0.117C0.174,-0.099 0.187,-0.085 0.204,-0.075C0.221,-0.065 0.243,-0.06 0.268,-0.06C0.299,-0.06 0.325,-0.068 0.346,-0.085C0.367,-0.102 0.38,-0.128 0.385,-0.163L0.474,-0.157C0.471,-0.135 0.464,-0.114 0.455,-0.094C0.445,-0.074 0.432,-0.056 0.415,-0.041C0.398,-0.026 0.378,-0.013 0.354,-0.004C0.329,0.005 0.302,0.01 0.27,0.01C0.229,0.01 0.194,0.003 0.165,-0.011C0.136,-0.025 0.112,-0.045 0.094,-0.069C0.076,-0.094 0.063,-0.123 0.055,-0.156C0.047,-0.189 0.042,-0.226 0.042,-0.265C0.042,-0.3 0.045,-0.331 0.051,-0.359C0.057,-0.386 0.065,-0.41 0.076,-0.43C0.087,-0.45 0.099,-0.467 0.113,-0.481C0.128,-0.495 0.143,-0.506 0.16,-0.514C0.177,-0.523 0.194,-0.529 0.213,-0.532C0.231,-0.536 0.25,-0.538 0.269,-0.538C0.299,-0.538 0.325,-0.534 0.348,-0.526C0.371,-0.518 0.391,-0.507 0.408,-0.492C0.425,-0.478 0.438,-0.462 0.449,-0.442C0.459,-0.423 0.466,-0.403 0.471,-0.38L0.38,-0.374C0.376,-0.403 0.364,-0.426 0.346,-0.443C0.327,-0.461 0.301,-0.469 0.267,-0.469C0.242,-0.469 0.221,-0.465 0.204,-0.457C0.187,-0.448 0.174,-0.436 0.163,-0.419C0.153,-0.402 0.145,-0.381 0.141,-0.356C0.136,-0.331 0.134,-0.301 0.134,-0.267Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,657.822,29.709)">
|
||||
<path d="M0.514,-0.265C0.514,-0.172 0.494,-0.103 0.453,-0.058C0.412,-0.013 0.353,0.01 0.276,0.01C0.239,0.01 0.206,0.004 0.177,-0.007C0.148,-0.018 0.124,-0.035 0.104,-0.058C0.084,-0.08 0.068,-0.109 0.058,-0.143C0.047,-0.178 0.042,-0.218 0.042,-0.265C0.042,-0.447 0.121,-0.538 0.279,-0.538C0.32,-0.538 0.355,-0.532 0.385,-0.521C0.415,-0.51 0.439,-0.493 0.458,-0.47C0.477,-0.447 0.491,-0.418 0.5,-0.384C0.51,-0.35 0.514,-0.31 0.514,-0.265ZM0.422,-0.265C0.422,-0.306 0.419,-0.34 0.412,-0.366C0.406,-0.393 0.397,-0.414 0.385,-0.43C0.372,-0.446 0.357,-0.457 0.34,-0.464C0.322,-0.47 0.302,-0.473 0.28,-0.473C0.258,-0.473 0.238,-0.47 0.219,-0.463C0.201,-0.456 0.186,-0.445 0.173,-0.429C0.161,-0.413 0.151,-0.391 0.144,-0.365C0.138,-0.338 0.134,-0.305 0.134,-0.265C0.134,-0.224 0.138,-0.19 0.145,-0.163C0.152,-0.136 0.162,-0.115 0.175,-0.099C0.187,-0.083 0.202,-0.071 0.219,-0.065C0.236,-0.058 0.255,-0.055 0.275,-0.055C0.297,-0.055 0.318,-0.058 0.336,-0.065C0.354,-0.071 0.37,-0.082 0.382,-0.098C0.395,-0.114 0.405,-0.136 0.412,-0.163C0.418,-0.19 0.422,-0.224 0.422,-0.265Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,680.624,29.709)">
|
||||
<path d="M0.375,0L0.375,-0.335C0.375,-0.361 0.373,-0.382 0.37,-0.399C0.367,-0.417 0.361,-0.431 0.354,-0.441C0.346,-0.452 0.336,-0.459 0.324,-0.464C0.311,-0.468 0.296,-0.47 0.278,-0.47C0.26,-0.47 0.243,-0.467 0.228,-0.459C0.213,-0.452 0.2,-0.441 0.19,-0.427C0.179,-0.414 0.171,-0.397 0.165,-0.376C0.16,-0.356 0.157,-0.333 0.157,-0.306L0.157,0L0.069,0L0.069,-0.416C0.069,-0.427 0.069,-0.438 0.069,-0.45C0.069,-0.463 0.069,-0.474 0.068,-0.485C0.068,-0.496 0.068,-0.505 0.067,-0.513C0.067,-0.521 0.067,-0.526 0.066,-0.528L0.149,-0.528C0.15,-0.527 0.15,-0.522 0.15,-0.515C0.151,-0.508 0.151,-0.5 0.152,-0.49C0.152,-0.481 0.153,-0.472 0.153,-0.462C0.153,-0.453 0.153,-0.444 0.153,-0.438L0.155,-0.438C0.163,-0.453 0.171,-0.467 0.18,-0.479C0.189,-0.492 0.2,-0.502 0.212,-0.511C0.224,-0.52 0.238,-0.526 0.254,-0.531C0.27,-0.536 0.288,-0.538 0.309,-0.538C0.349,-0.538 0.381,-0.53 0.404,-0.514C0.427,-0.498 0.444,-0.473 0.453,-0.438L0.454,-0.438C0.462,-0.453 0.471,-0.467 0.48,-0.479C0.49,-0.492 0.502,-0.502 0.515,-0.511C0.528,-0.52 0.542,-0.526 0.559,-0.531C0.575,-0.536 0.593,-0.538 0.614,-0.538C0.641,-0.538 0.664,-0.535 0.683,-0.527C0.703,-0.52 0.719,-0.509 0.731,-0.494C0.743,-0.479 0.752,-0.46 0.758,-0.436C0.764,-0.413 0.767,-0.385 0.767,-0.352L0.767,0L0.68,0L0.68,-0.335C0.68,-0.361 0.679,-0.382 0.675,-0.399C0.672,-0.417 0.667,-0.431 0.659,-0.441C0.651,-0.452 0.641,-0.459 0.629,-0.464C0.617,-0.468 0.601,-0.47 0.583,-0.47C0.565,-0.47 0.548,-0.467 0.533,-0.46C0.518,-0.453 0.505,-0.442 0.495,-0.429C0.484,-0.415 0.476,-0.398 0.47,-0.377C0.465,-0.357 0.462,-0.333 0.462,-0.306L0.462,0L0.375,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,714.777,29.709)">
|
||||
<path d="M0,0.01L0.201,-0.725L0.278,-0.725L0.079,0.01L0,0.01Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,726.168,29.709)">
|
||||
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,753.515,29.709)">
|
||||
<path d="M0.547,0L0.547,-0.319L0.175,-0.319L0.175,0L0.082,0L0.082,-0.688L0.175,-0.688L0.175,-0.397L0.547,-0.397L0.547,-0.688L0.641,-0.688L0.641,0L0.547,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,783.124,29.709)">
|
||||
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,810.471,29.709)">
|
||||
<path d="M0.667,0L0.667,-0.459C0.667,-0.476 0.667,-0.493 0.667,-0.51C0.668,-0.527 0.668,-0.543 0.669,-0.557C0.67,-0.574 0.67,-0.59 0.671,-0.605C0.667,-0.589 0.662,-0.572 0.657,-0.556C0.653,-0.542 0.648,-0.527 0.643,-0.511C0.638,-0.496 0.633,-0.481 0.628,-0.469L0.451,0L0.385,0L0.205,-0.469C0.203,-0.474 0.201,-0.479 0.199,-0.486L0.185,-0.529C0.182,-0.537 0.18,-0.544 0.178,-0.552C0.172,-0.569 0.167,-0.587 0.162,-0.605C0.162,-0.587 0.162,-0.569 0.163,-0.551C0.164,-0.536 0.164,-0.52 0.165,-0.503C0.165,-0.486 0.165,-0.472 0.165,-0.459L0.165,0L0.082,0L0.082,-0.688L0.205,-0.688L0.388,-0.211C0.39,-0.204 0.393,-0.196 0.396,-0.186C0.399,-0.176 0.402,-0.165 0.405,-0.154C0.408,-0.144 0.411,-0.133 0.413,-0.124C0.416,-0.114 0.417,-0.107 0.418,-0.102C0.419,-0.107 0.421,-0.114 0.424,-0.124C0.426,-0.134 0.429,-0.144 0.433,-0.155C0.436,-0.166 0.44,-0.176 0.443,-0.186C0.446,-0.196 0.449,-0.204 0.452,-0.211L0.631,-0.688L0.751,-0.688L0.751,0L0.667,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,844.624,29.709)">
|
||||
<path d="M0.202,0.01C0.149,0.01 0.109,-0.004 0.083,-0.032C0.056,-0.06 0.042,-0.099 0.042,-0.147C0.042,-0.182 0.049,-0.211 0.062,-0.233C0.075,-0.255 0.093,-0.273 0.114,-0.286C0.135,-0.298 0.16,-0.307 0.187,-0.312C0.214,-0.317 0.242,-0.32 0.271,-0.32L0.389,-0.322L0.389,-0.351C0.389,-0.373 0.387,-0.391 0.382,-0.407C0.378,-0.422 0.371,-0.434 0.361,-0.444C0.352,-0.453 0.34,-0.46 0.326,-0.465C0.312,-0.469 0.295,-0.471 0.276,-0.471C0.259,-0.471 0.244,-0.47 0.23,-0.468C0.216,-0.465 0.204,-0.461 0.194,-0.454C0.184,-0.448 0.176,-0.439 0.17,-0.428C0.164,-0.418 0.16,-0.404 0.158,-0.387L0.066,-0.396C0.069,-0.416 0.075,-0.435 0.084,-0.453C0.094,-0.47 0.107,-0.485 0.123,-0.498C0.14,-0.511 0.161,-0.521 0.186,-0.528C0.212,-0.535 0.242,-0.538 0.278,-0.538C0.344,-0.538 0.394,-0.523 0.428,-0.492C0.461,-0.462 0.478,-0.418 0.478,-0.36L0.478,-0.133C0.478,-0.107 0.481,-0.087 0.488,-0.074C0.495,-0.061 0.508,-0.054 0.527,-0.054C0.532,-0.054 0.537,-0.055 0.542,-0.055C0.547,-0.056 0.552,-0.057 0.556,-0.058L0.556,-0.003C0.545,0 0.534,0.002 0.523,0.003C0.512,0.004 0.501,0.005 0.488,0.005C0.472,0.005 0.457,0.003 0.446,-0.002C0.434,-0.006 0.424,-0.013 0.417,-0.022C0.409,-0.031 0.403,-0.042 0.399,-0.055C0.396,-0.068 0.393,-0.083 0.392,-0.101L0.389,-0.101C0.38,-0.084 0.369,-0.069 0.358,-0.055C0.347,-0.042 0.334,-0.03 0.319,-0.02C0.304,-0.011 0.287,-0.003 0.268,0.002C0.249,0.007 0.227,0.01 0.202,0.01ZM0.222,-0.056C0.25,-0.056 0.275,-0.061 0.296,-0.072C0.317,-0.082 0.334,-0.095 0.348,-0.111C0.362,-0.127 0.372,-0.144 0.379,-0.163C0.386,-0.182 0.389,-0.2 0.389,-0.217L0.389,-0.261L0.293,-0.259C0.271,-0.258 0.251,-0.257 0.232,-0.254C0.212,-0.251 0.195,-0.246 0.181,-0.238C0.166,-0.23 0.154,-0.218 0.146,-0.204C0.137,-0.189 0.133,-0.17 0.133,-0.146C0.133,-0.117 0.141,-0.095 0.156,-0.08C0.171,-0.064 0.194,-0.056 0.222,-0.056Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,867.426,29.709)">
|
||||
<path d="M0.067,-0.641L0.067,-0.725L0.155,-0.725L0.155,-0.641L0.067,-0.641ZM0.067,0L0.067,-0.528L0.155,-0.528L0.155,0L0.067,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,876.535,29.709)">
|
||||
<rect x="0.067" y="-0.725" width="0.088" height="0.725" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,885.644,29.709)">
|
||||
<path d="M0.135,-0.246C0.135,-0.218 0.138,-0.192 0.143,-0.169C0.149,-0.146 0.158,-0.126 0.17,-0.109C0.182,-0.092 0.197,-0.079 0.215,-0.07C0.234,-0.061 0.256,-0.056 0.282,-0.056C0.32,-0.056 0.351,-0.064 0.374,-0.079C0.397,-0.094 0.412,-0.114 0.42,-0.137L0.498,-0.115C0.492,-0.101 0.484,-0.086 0.474,-0.071C0.464,-0.056 0.451,-0.043 0.435,-0.031C0.418,-0.019 0.397,-0.009 0.372,-0.002C0.347,0.006 0.317,0.01 0.282,0.01C0.204,0.01 0.145,-0.014 0.104,-0.06C0.063,-0.107 0.042,-0.176 0.042,-0.268C0.042,-0.317 0.049,-0.359 0.061,-0.393C0.073,-0.428 0.09,-0.456 0.112,-0.477C0.133,-0.499 0.158,-0.514 0.187,-0.524C0.216,-0.533 0.246,-0.538 0.279,-0.538C0.323,-0.538 0.36,-0.531 0.39,-0.517C0.42,-0.502 0.444,-0.483 0.462,-0.457C0.48,-0.432 0.493,-0.402 0.5,-0.368C0.508,-0.334 0.512,-0.297 0.512,-0.257L0.512,-0.246L0.135,-0.246ZM0.421,-0.313C0.416,-0.369 0.402,-0.409 0.378,-0.435C0.355,-0.46 0.321,-0.473 0.277,-0.473C0.263,-0.473 0.247,-0.471 0.231,-0.466C0.215,-0.461 0.2,-0.453 0.187,-0.441C0.173,-0.429 0.161,-0.413 0.152,-0.392C0.142,-0.371 0.137,-0.345 0.136,-0.313L0.421,-0.313Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,908.446,29.709)">
|
||||
<path d="M0.069,0L0.069,-0.405C0.069,-0.416 0.069,-0.428 0.069,-0.439C0.069,-0.451 0.069,-0.462 0.068,-0.473C0.068,-0.483 0.068,-0.493 0.067,-0.503C0.067,-0.512 0.067,-0.521 0.066,-0.528L0.149,-0.528L0.152,-0.473C0.153,-0.463 0.153,-0.453 0.153,-0.444C0.153,-0.435 0.153,-0.427 0.153,-0.42L0.155,-0.42C0.161,-0.441 0.168,-0.458 0.175,-0.473C0.182,-0.488 0.19,-0.5 0.2,-0.51C0.209,-0.519 0.22,-0.526 0.233,-0.531C0.246,-0.536 0.262,-0.538 0.281,-0.538C0.288,-0.538 0.295,-0.538 0.301,-0.536C0.308,-0.535 0.313,-0.534 0.316,-0.533L0.316,-0.453C0.311,-0.454 0.304,-0.455 0.296,-0.456C0.288,-0.457 0.279,-0.458 0.27,-0.458C0.249,-0.458 0.232,-0.453 0.218,-0.444C0.204,-0.435 0.192,-0.422 0.183,-0.406C0.174,-0.39 0.168,-0.371 0.164,-0.348C0.159,-0.326 0.157,-0.302 0.157,-0.275L0.157,0L0.069,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,922.1,29.709)">
|
||||
<path d="M0,0.01L0.201,-0.725L0.278,-0.725L0.079,0.01L0,0.01Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,933.491,29.709)">
|
||||
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,960.837,29.709)">
|
||||
<path d="M0.547,0L0.547,-0.319L0.175,-0.319L0.175,0L0.082,0L0.082,-0.688L0.175,-0.688L0.175,-0.397L0.547,-0.397L0.547,-0.688L0.641,-0.688L0.641,0L0.547,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,990.446,29.709)">
|
||||
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,1017.79,29.709)">
|
||||
<path d="M0.667,0L0.667,-0.459C0.667,-0.476 0.667,-0.493 0.667,-0.51C0.668,-0.527 0.668,-0.543 0.669,-0.557C0.67,-0.574 0.67,-0.59 0.671,-0.605C0.667,-0.589 0.662,-0.572 0.657,-0.556C0.653,-0.542 0.648,-0.527 0.643,-0.511C0.638,-0.496 0.633,-0.481 0.628,-0.469L0.451,0L0.385,0L0.205,-0.469C0.203,-0.474 0.201,-0.479 0.199,-0.486L0.185,-0.529C0.182,-0.537 0.18,-0.544 0.178,-0.552C0.172,-0.569 0.167,-0.587 0.162,-0.605C0.162,-0.587 0.162,-0.569 0.163,-0.551C0.164,-0.536 0.164,-0.52 0.165,-0.503C0.165,-0.486 0.165,-0.472 0.165,-0.459L0.165,0L0.082,0L0.082,-0.688L0.205,-0.688L0.388,-0.211C0.39,-0.204 0.393,-0.196 0.396,-0.186C0.399,-0.176 0.402,-0.165 0.405,-0.154C0.408,-0.144 0.411,-0.133 0.413,-0.124C0.416,-0.114 0.417,-0.107 0.418,-0.102C0.419,-0.107 0.421,-0.114 0.424,-0.124C0.426,-0.134 0.429,-0.144 0.433,-0.155C0.436,-0.166 0.44,-0.176 0.443,-0.186C0.446,-0.196 0.449,-0.204 0.452,-0.211L0.631,-0.688L0.751,-0.688L0.751,0L0.667,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,1051.95,29.709)">
|
||||
<path d="M0.202,0.01C0.149,0.01 0.109,-0.004 0.083,-0.032C0.056,-0.06 0.042,-0.099 0.042,-0.147C0.042,-0.182 0.049,-0.211 0.062,-0.233C0.075,-0.255 0.093,-0.273 0.114,-0.286C0.135,-0.298 0.16,-0.307 0.187,-0.312C0.214,-0.317 0.242,-0.32 0.271,-0.32L0.389,-0.322L0.389,-0.351C0.389,-0.373 0.387,-0.391 0.382,-0.407C0.378,-0.422 0.371,-0.434 0.361,-0.444C0.352,-0.453 0.34,-0.46 0.326,-0.465C0.312,-0.469 0.295,-0.471 0.276,-0.471C0.259,-0.471 0.244,-0.47 0.23,-0.468C0.216,-0.465 0.204,-0.461 0.194,-0.454C0.184,-0.448 0.176,-0.439 0.17,-0.428C0.164,-0.418 0.16,-0.404 0.158,-0.387L0.066,-0.396C0.069,-0.416 0.075,-0.435 0.084,-0.453C0.094,-0.47 0.107,-0.485 0.123,-0.498C0.14,-0.511 0.161,-0.521 0.186,-0.528C0.212,-0.535 0.242,-0.538 0.278,-0.538C0.344,-0.538 0.394,-0.523 0.428,-0.492C0.461,-0.462 0.478,-0.418 0.478,-0.36L0.478,-0.133C0.478,-0.107 0.481,-0.087 0.488,-0.074C0.495,-0.061 0.508,-0.054 0.527,-0.054C0.532,-0.054 0.537,-0.055 0.542,-0.055C0.547,-0.056 0.552,-0.057 0.556,-0.058L0.556,-0.003C0.545,0 0.534,0.002 0.523,0.003C0.512,0.004 0.501,0.005 0.488,0.005C0.472,0.005 0.457,0.003 0.446,-0.002C0.434,-0.006 0.424,-0.013 0.417,-0.022C0.409,-0.031 0.403,-0.042 0.399,-0.055C0.396,-0.068 0.393,-0.083 0.392,-0.101L0.389,-0.101C0.38,-0.084 0.369,-0.069 0.358,-0.055C0.347,-0.042 0.334,-0.03 0.319,-0.02C0.304,-0.011 0.287,-0.003 0.268,0.002C0.249,0.007 0.227,0.01 0.202,0.01ZM0.222,-0.056C0.25,-0.056 0.275,-0.061 0.296,-0.072C0.317,-0.082 0.334,-0.095 0.348,-0.111C0.362,-0.127 0.372,-0.144 0.379,-0.163C0.386,-0.182 0.389,-0.2 0.389,-0.217L0.389,-0.261L0.293,-0.259C0.271,-0.258 0.251,-0.257 0.232,-0.254C0.212,-0.251 0.195,-0.246 0.181,-0.238C0.166,-0.23 0.154,-0.218 0.146,-0.204C0.137,-0.189 0.133,-0.17 0.133,-0.146C0.133,-0.117 0.141,-0.095 0.156,-0.08C0.171,-0.064 0.194,-0.056 0.222,-0.056Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,1074.75,29.709)">
|
||||
<path d="M0.067,-0.641L0.067,-0.725L0.155,-0.725L0.155,-0.641L0.067,-0.641ZM0.067,0L0.067,-0.528L0.155,-0.528L0.155,0L0.067,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,1083.86,29.709)">
|
||||
<rect x="0.067" y="-0.725" width="0.088" height="0.725" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,1092.97,29.709)">
|
||||
<path d="M0.135,-0.246C0.135,-0.218 0.138,-0.192 0.143,-0.169C0.149,-0.146 0.158,-0.126 0.17,-0.109C0.182,-0.092 0.197,-0.079 0.215,-0.07C0.234,-0.061 0.256,-0.056 0.282,-0.056C0.32,-0.056 0.351,-0.064 0.374,-0.079C0.397,-0.094 0.412,-0.114 0.42,-0.137L0.498,-0.115C0.492,-0.101 0.484,-0.086 0.474,-0.071C0.464,-0.056 0.451,-0.043 0.435,-0.031C0.418,-0.019 0.397,-0.009 0.372,-0.002C0.347,0.006 0.317,0.01 0.282,0.01C0.204,0.01 0.145,-0.014 0.104,-0.06C0.063,-0.107 0.042,-0.176 0.042,-0.268C0.042,-0.317 0.049,-0.359 0.061,-0.393C0.073,-0.428 0.09,-0.456 0.112,-0.477C0.133,-0.499 0.158,-0.514 0.187,-0.524C0.216,-0.533 0.246,-0.538 0.279,-0.538C0.323,-0.538 0.36,-0.531 0.39,-0.517C0.42,-0.502 0.444,-0.483 0.462,-0.457C0.48,-0.432 0.493,-0.402 0.5,-0.368C0.508,-0.334 0.512,-0.297 0.512,-0.257L0.512,-0.246L0.135,-0.246ZM0.421,-0.313C0.416,-0.369 0.402,-0.409 0.378,-0.435C0.355,-0.46 0.321,-0.473 0.277,-0.473C0.263,-0.473 0.247,-0.471 0.231,-0.466C0.215,-0.461 0.2,-0.453 0.187,-0.441C0.173,-0.429 0.161,-0.413 0.152,-0.392C0.142,-0.371 0.137,-0.345 0.136,-0.313L0.421,-0.313Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(41,0,0,41,1115.77,29.709)">
|
||||
<path d="M0.069,0L0.069,-0.405C0.069,-0.416 0.069,-0.428 0.069,-0.439C0.069,-0.451 0.069,-0.462 0.068,-0.473C0.068,-0.483 0.068,-0.493 0.067,-0.503C0.067,-0.512 0.067,-0.521 0.066,-0.528L0.149,-0.528L0.152,-0.473C0.153,-0.463 0.153,-0.453 0.153,-0.444C0.153,-0.435 0.153,-0.427 0.153,-0.42L0.155,-0.42C0.161,-0.441 0.168,-0.458 0.175,-0.473C0.182,-0.488 0.19,-0.5 0.2,-0.51C0.209,-0.519 0.22,-0.526 0.233,-0.531C0.246,-0.536 0.262,-0.538 0.281,-0.538C0.288,-0.538 0.295,-0.538 0.301,-0.536C0.308,-0.535 0.313,-0.534 0.316,-0.533L0.316,-0.453C0.311,-0.454 0.304,-0.455 0.296,-0.456C0.288,-0.457 0.279,-0.458 0.27,-0.458C0.249,-0.458 0.232,-0.453 0.218,-0.444C0.204,-0.435 0.192,-0.422 0.183,-0.406C0.174,-0.39 0.168,-0.371 0.164,-0.348C0.159,-0.326 0.157,-0.302 0.157,-0.275L0.157,0L0.069,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 53 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 KiB |
35
vendor/phpmailer/phpmailer/examples/mail.phps
vendored
35
vendor/phpmailer/phpmailer/examples/mail.phps
vendored
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows sending a message using PHP's mail() function.
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
//Set who the message is to be sent from
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
//Set an alternative reply-to address
|
||||
$mail->addReplyTo('replyto@example.com', 'First Last');
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer mail() test';
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//convert HTML into a basic plain-text alternative body
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
//Attach an image file
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
|
||||
//send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows how to send a message to a whole list of recipients efficiently.
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
error_reporting(E_STRICT | E_ALL);
|
||||
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Passing `true` enables PHPMailer exceptions
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
$body = file_get_contents('contents.html');
|
||||
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'smtp.example.com';
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->SMTPKeepAlive = true; //SMTP connection will not close after each email sent, reduces SMTP overhead
|
||||
$mail->Port = 25;
|
||||
$mail->Username = 'yourname@example.com';
|
||||
$mail->Password = 'yourpassword';
|
||||
$mail->setFrom('list@example.com', 'List manager');
|
||||
$mail->addReplyTo('list@example.com', 'List manager');
|
||||
$mail->addCustomHeader(
|
||||
'List-Unsubscribe',
|
||||
'<mailto:unsubscribes@example.com>, <https://www.example.com/unsubscribe.php>'
|
||||
);
|
||||
$mail->Subject = 'PHPMailer Simple database mailing list test';
|
||||
|
||||
//Same body for all messages, so set this before the sending loop
|
||||
//If you generate a different body for each recipient (e.g. you're using a templating system),
|
||||
//set it inside the loop
|
||||
$mail->msgHTML($body);
|
||||
//msgHTML also sets AltBody, but if you want a custom one, set it afterwards
|
||||
$mail->AltBody = 'To view the message, please use an HTML compatible email viewer!';
|
||||
|
||||
//Connect to the database and select the recipients from your mailing list that have not yet been sent to
|
||||
//You'll need to alter this to match your database
|
||||
$mysql = mysqli_connect('localhost', 'username', 'password');
|
||||
mysqli_select_db($mysql, 'mydb');
|
||||
$result = mysqli_query($mysql, 'SELECT full_name, email, photo FROM mailinglist WHERE sent = FALSE');
|
||||
|
||||
foreach ($result as $row) {
|
||||
try {
|
||||
$mail->addAddress($row['email'], $row['full_name']);
|
||||
} catch (Exception $e) {
|
||||
echo 'Invalid address skipped: ' . htmlspecialchars($row['email']) . '<br>';
|
||||
continue;
|
||||
}
|
||||
if (!empty($row['photo'])) {
|
||||
//Assumes the image data is stored in the DB
|
||||
$mail->addStringAttachment($row['photo'], 'YourPhoto.jpg');
|
||||
}
|
||||
$mail->replaceCustomHeader(
|
||||
'List-Unsubscribe',
|
||||
'<mailto:unsubscribes@example.com>, <https://www.example.com/unsubscribe.php?email=' .
|
||||
rawurlencode($row['email']) . '>'
|
||||
);
|
||||
|
||||
try {
|
||||
$mail->send();
|
||||
echo 'Message sent to :' . htmlspecialchars($row['full_name']) . ' (' .
|
||||
htmlspecialchars($row['email']) . ')<br>';
|
||||
//Mark it as sent in the DB
|
||||
mysqli_query(
|
||||
$mysql,
|
||||
"UPDATE mailinglist SET sent = TRUE WHERE email = '" .
|
||||
mysqli_real_escape_string($mysql, $row['email']) . "'"
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
echo 'Mailer Error (' . htmlspecialchars($row['email']) . ') ' . $mail->ErrorInfo . '<br>';
|
||||
//Reset the connection to abort sending this message
|
||||
//The loop will continue trying to send to the rest of the list
|
||||
$mail->getSMTPInstance()->reset();
|
||||
}
|
||||
//Clear all addresses and attachments for the next iteration
|
||||
$mail->clearAddresses();
|
||||
$mail->clearAttachments();
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows how to use POP-before-SMTP for authentication.
|
||||
* POP-before-SMTP is a very old technology that is hardly used any more.
|
||||
*/
|
||||
|
||||
//Import PHPMailer classes into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\POP3;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Authenticate via POP3.
|
||||
//After this you should be allowed to submit messages over SMTP for a few minutes.
|
||||
//Only applies if your host supports POP-before-SMTP.
|
||||
$pop = POP3::popBeforeSmtp('pop3.example.com', 110, 30, 'username', 'password', 1);
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
//Passing true to the constructor enables the use of exceptions for error handling
|
||||
$mail = new PHPMailer(true);
|
||||
try {
|
||||
$mail->isSMTP();
|
||||
//Enable SMTP debugging
|
||||
//SMTP::DEBUG_OFF = off (for production use)
|
||||
//SMTP::DEBUG_CLIENT = client messages
|
||||
//SMTP::DEBUG_SERVER = client and server messages
|
||||
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
|
||||
//Set the hostname of the mail server
|
||||
$mail->Host = 'mail.example.com';
|
||||
//Set the SMTP port number - likely to be 25, 465 or 587
|
||||
$mail->Port = 25;
|
||||
//Whether to use SMTP authentication
|
||||
$mail->SMTPAuth = false;
|
||||
//Set who the message is to be sent from
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
//Set an alternative reply-to address
|
||||
$mail->addReplyTo('replyto@example.com', 'First Last');
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer POP-before-SMTP test';
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//and convert the HTML into a basic plain-text alternative body
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
//Attach an image file
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
//send the message
|
||||
//Note that we don't need check the response from this because it will throw an exception if it has trouble
|
||||
$mail->send();
|
||||
echo 'Message sent!';
|
||||
} catch (Exception $e) {
|
||||
echo $e->errorMessage(); //Pretty error messages from PHPMailer
|
||||
} catch (\Exception $e) {
|
||||
echo $e->getMessage(); //Boring error messages from anything else!
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer simple file upload and send example.
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
$msg = '';
|
||||
if (array_key_exists('userfile', $_FILES)) {
|
||||
//First handle the upload
|
||||
//Don't trust provided filename - same goes for MIME types
|
||||
//See https://www.php.net/manual/en/features.file-upload.php#114004 for more thorough upload validation
|
||||
//Extract an extension from the provided filename
|
||||
$ext = PHPMailer::mb_pathinfo($_FILES['userfile']['name'], PATHINFO_EXTENSION);
|
||||
//Define a safe location to move the uploaded file to, preserving the extension
|
||||
$uploadfile = tempnam(sys_get_temp_dir(), hash('sha256', $_FILES['userfile']['name'])) . '.' . $ext;
|
||||
|
||||
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
|
||||
//Upload handled successfully
|
||||
//Now create a message
|
||||
$mail = new PHPMailer();
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
$mail->Subject = 'PHPMailer file sender';
|
||||
$mail->Body = 'My message body';
|
||||
//Attach the uploaded file
|
||||
if (!$mail->addAttachment($uploadfile, 'My uploaded file')) {
|
||||
$msg .= 'Failed to attach file ' . $_FILES['userfile']['name'];
|
||||
}
|
||||
if (!$mail->send()) {
|
||||
$msg .= 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
$msg .= 'Message sent!';
|
||||
}
|
||||
} else {
|
||||
$msg .= 'Failed to move file to ' . $uploadfile;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>PHPMailer Upload</title>
|
||||
</head>
|
||||
<body>
|
||||
<?php if (empty($msg)) { ?>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="100000"> Send this file: <input name="userfile" type="file">
|
||||
<input type="submit" value="Send File">
|
||||
</form>
|
||||
<?php } else {
|
||||
echo htmlspecialchars($msg);
|
||||
} ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer multiple files upload and send example
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
$msg = '';
|
||||
if (array_key_exists('userfile', $_FILES)) {
|
||||
//Create a message
|
||||
$mail = new PHPMailer();
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
$mail->Subject = 'PHPMailer file sender';
|
||||
$mail->Body = 'My message body';
|
||||
//Attach multiple files one by one
|
||||
for ($ct = 0, $ctMax = count($_FILES['userfile']['tmp_name']); $ct < $ctMax; $ct++) {
|
||||
//Extract an extension from the provided filename
|
||||
$ext = PHPMailer::mb_pathinfo($_FILES['userfile']['name'][$ct], PATHINFO_EXTENSION);
|
||||
//Define a safe location to move the uploaded file to, preserving the extension
|
||||
$uploadfile = tempnam(sys_get_temp_dir(), hash('sha256', $_FILES['userfile']['name'][$ct])) . '.' . $ext;
|
||||
$filename = $_FILES['userfile']['name'][$ct];
|
||||
if (move_uploaded_file($_FILES['userfile']['tmp_name'][$ct], $uploadfile)) {
|
||||
if (!$mail->addAttachment($uploadfile, $filename)) {
|
||||
$msg .= 'Failed to attach file ' . $filename;
|
||||
}
|
||||
} else {
|
||||
$msg .= 'Failed to move file to ' . $uploadfile;
|
||||
}
|
||||
}
|
||||
if (!$mail->send()) {
|
||||
$msg .= 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
$msg .= 'Message sent!';
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>PHPMailer Upload</title>
|
||||
</head>
|
||||
<body>
|
||||
<?php if (empty($msg)) { ?>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="100000">
|
||||
Select one or more files:
|
||||
<input name="userfile[]" type="file" multiple="multiple">
|
||||
<input type="submit" value="Send Files">
|
||||
</form>
|
||||
<?php } else {
|
||||
echo htmlspecialchars($msg);
|
||||
} ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows sending a message using a local sendmail binary.
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
//Set PHPMailer to use the sendmail transport
|
||||
$mail->isSendmail();
|
||||
//Set who the message is to be sent from
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
//Set an alternative reply-to address
|
||||
$mail->addReplyTo('replyto@example.com', 'First Last');
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer sendmail test';
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//convert HTML into a basic plain-text alternative body
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
//Attach an image file
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
|
||||
//send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
}
|
||||
100
vendor/phpmailer/phpmailer/examples/sendoauth2.phps
vendored
100
vendor/phpmailer/phpmailer/examples/sendoauth2.phps
vendored
@@ -1,100 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The SendOauth2 wrapper supports OAuth2 and Basic authorization/authentication for
|
||||
* Microsoft 365 Exchange email and Google Gmail. Both TheLeague's Google provider + client
|
||||
* and Google's 'official' GoogleAPI client are supported. The wrapper supports any authentication
|
||||
* mechanism provided by these systems: authorization_code grant and client_credentials grant
|
||||
* (aka Google 'service accounts'), client secrets and X.509 certificates, $_SESSION 'state'
|
||||
* and PKCE code exchanges, and creation on the fly of GoogleAPI's .json credentials files.
|
||||
* Appropriate scopes (client permissions) and 'provider' overrides are added automatically.
|
||||
*
|
||||
* The wrapper is installed with Composer from the decomplexity/SendOauth2 repo; see its README.
|
||||
*
|
||||
* The wrapper can also be invoked using fewer (or even no) arguments; this is for those websites
|
||||
* that use PHPMailer in several places. See the repo for details.
|
||||
*/
|
||||
|
||||
// Import PHPMailer classes
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
// Import SendOauth2B class
|
||||
use decomplexity\SendOauth2\SendOauth2B;
|
||||
|
||||
// Uncomment the next two lines to display PHP errors
|
||||
// error_reporting(E_ALL);
|
||||
// ini_set("display_errors", 1);
|
||||
|
||||
// Load Composer's autoloader
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
// Set timezone for SMTP
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
// Create an instance; passing `true` enables exceptions
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
try {
|
||||
// Server settings
|
||||
$mail->isSMTP(); // Use SMTP
|
||||
$mail->SMTPDebug = SMTP::DEBUG_OFF; // Set DEBUG_LOWLEVEL for SMTP diagnostics
|
||||
$mail->SMTPAuth = true; // Enable SMTP authentication
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable implicit TLS encryption
|
||||
$mail->Port = 587; // TCP port; MSFT doesn't like 465
|
||||
$mail->AuthType = 'XOAUTH2'; // Set AuthType to use XOAUTH2 ('LOGIN' for Basic auth)
|
||||
|
||||
// Sender and recipients
|
||||
$mail->setFrom('from@example.com', 'Mailer'); // 'Header' From address with optional sender name
|
||||
$mail->addAddress('joe@example.net', 'Joe User'); // Add a To: recipient
|
||||
|
||||
/**
|
||||
* Authenticate
|
||||
* Note that any ClientCertificatePrivateKey should include the -----BEGIN PRIVATE KEY----- and
|
||||
* -----END PRIVATE KEY-----
|
||||
*/
|
||||
|
||||
$oauthTokenProvider = new SendOauth2B(
|
||||
[
|
||||
'mail' => $mail, // PHPMailer instance
|
||||
'clientId' => 'long string', // for Google service account, Unique ID
|
||||
'clientSecret' => 'long string', // or null if using a certificate
|
||||
'clientCertificatePrivateKey' => 'ultra long string', // or null if using a clientSecret
|
||||
'clientCertificateThumbprint' => 'long string', // or null if using a clientSecret
|
||||
'serviceProvider' => 'Microsoft', // literal: also 'Google' or 'GoogleAPI'
|
||||
'authTypeSetting' => $mail->AuthType, // is set above - or insert here as 'XOAUTH2'
|
||||
'mailSMTPAddress' => 'me@mydomain.com', // Envelope/mailFrom/reverse-path From address
|
||||
'refreshToken' => 'very long string', // null if grantType is 'client_credentials'
|
||||
'grantType' => 'authorization_code', // or 'client_credentials'
|
||||
|
||||
'tenant' => 'long string', // MSFT tenant GUID. Null for Gmail
|
||||
|
||||
'hostedDomain' => 'mydomain.com', // Any Google (and optional). Null for MSFT
|
||||
|
||||
'projectID' => 'string', // GoogleAPI only. Else null
|
||||
'serviceAccountName' => 'string', // GoogleAPI service account only. Else null
|
||||
'impersonate' => 'you@mydomain.com', // Google API service account only. Else null
|
||||
// default to 'mailSMTPAddress', must be
|
||||
// a Google Wspace email adddress, not @gmail
|
||||
'gmailXoauth2Credentials' => 'your credentials.json', // File name - defaults to:
|
||||
// gmail-xoauth2-credentials.json
|
||||
'writeGmailCredentialsFile' => 'yes' or 'no', // Defaults to 'yes'; meaning the
|
||||
// credentials json is dynamically created
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
$mail->setOAuth($oauthTokenProvider); // Pass OAuthTokenProvider to PHPMailer
|
||||
$mail->Host = 'smtp.office365.com'; // Set SMTP server (smtp.gmail.com for Gmail)
|
||||
|
||||
// Content
|
||||
$mail->isHTML(true); // Set email format to HTML
|
||||
$mail->Subject = 'Here is the subject';
|
||||
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
|
||||
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
|
||||
|
||||
$mail->send();
|
||||
echo 'Message has been sent';
|
||||
} catch (Exception $e) {
|
||||
echo 'Message could not be sent. Mailer Error: ' . htmlspecialchars($mail->ErrorInfo, ENT_QUOTES);
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer simple contact form example.
|
||||
* If you want to accept and send uploads in your form, look at the send_file_upload example.
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
if (array_key_exists('to', $_POST)) {
|
||||
$err = false;
|
||||
$msg = '';
|
||||
$email = '';
|
||||
//Apply some basic validation and filtering to the subject
|
||||
if (array_key_exists('subject', $_POST)) {
|
||||
$subject = substr(strip_tags($_POST['subject']), 0, 255);
|
||||
} else {
|
||||
$subject = 'No subject given';
|
||||
}
|
||||
//Apply some basic validation and filtering to the query
|
||||
if (array_key_exists('query', $_POST)) {
|
||||
//Limit length and strip HTML tags
|
||||
$query = substr(strip_tags($_POST['query']), 0, 16384);
|
||||
} else {
|
||||
$query = '';
|
||||
$msg = 'No query provided!';
|
||||
$err = true;
|
||||
}
|
||||
//Apply some basic validation and filtering to the name
|
||||
if (array_key_exists('name', $_POST)) {
|
||||
//Limit length and strip HTML tags
|
||||
$name = substr(strip_tags($_POST['name']), 0, 255);
|
||||
} else {
|
||||
$name = '';
|
||||
}
|
||||
//Validate to address
|
||||
//Never allow arbitrary input for the 'to' address as it will turn your form into a spam gateway!
|
||||
//Substitute appropriate addresses from your own domain, or simply use a single, fixed address
|
||||
if (array_key_exists('to', $_POST) && in_array($_POST['to'], ['sales', 'support', 'accounts'], true)) {
|
||||
$to = $_POST['to'] . '@example.com';
|
||||
} else {
|
||||
$to = 'support@example.com';
|
||||
}
|
||||
//Make sure the address they provided is valid before trying to use it
|
||||
if (array_key_exists('email', $_POST) && PHPMailer::validateAddress($_POST['email'])) {
|
||||
$email = $_POST['email'];
|
||||
} else {
|
||||
$msg .= 'Error: invalid email address provided';
|
||||
$err = true;
|
||||
}
|
||||
if (!$err) {
|
||||
$mail = new PHPMailer();
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'localhost';
|
||||
$mail->Port = 25;
|
||||
$mail->CharSet = PHPMailer::CHARSET_UTF8;
|
||||
//It's important not to use the submitter's address as the from address as it's forgery,
|
||||
//which will cause your messages to fail SPF checks.
|
||||
//Use an address in your own domain as the from address, put the submitter's address in a reply-to
|
||||
$mail->setFrom('contact@example.com', (empty($name) ? 'Contact form' : $name));
|
||||
$mail->addAddress($to);
|
||||
$mail->addReplyTo($email, $name);
|
||||
$mail->Subject = 'Contact form: ' . $subject;
|
||||
$mail->Body = "Contact form submission\n\n" . $query;
|
||||
if (!$mail->send()) {
|
||||
$msg .= 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
$msg .= 'Message sent!';
|
||||
}
|
||||
}
|
||||
} ?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>PHPMailer Contact Form</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Contact us</h1>
|
||||
<?php if (empty($msg)) { ?>
|
||||
<form method="post">
|
||||
<label for="to">Send to:</label>
|
||||
<select name="to" id="to">
|
||||
<option value="sales">Sales</option>
|
||||
<option value="support" selected="selected">Support</option>
|
||||
<option value="accounts">Accounts</option>
|
||||
</select><br>
|
||||
<label for="subject">Subject: <input type="text" name="subject" id="subject" maxlength="255"></label><br>
|
||||
<label for="name">Your name: <input type="text" name="name" id="name" maxlength="255"></label><br>
|
||||
<label for="email">Your email address: <input type="email" name="email" id="email" maxlength="255"></label><br>
|
||||
<label for="query">Your question:</label><br>
|
||||
<textarea cols="30" rows="8" name="query" id="query" placeholder="Your question"></textarea><br>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
<?php } else {
|
||||
echo $msg;
|
||||
} ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,99 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This PHPMailer example shows S/MIME signing a message and then sending.
|
||||
*
|
||||
* Before you can sign the mail certificates are needed.
|
||||
*
|
||||
*
|
||||
* STEP 1 - Creating a certificate:
|
||||
* You can either use a self-signed certificate, pay for a signed one,
|
||||
* or use free alternatives such as StartSSL, Comodo etc.
|
||||
* Check out this link for more providers: https://kb.mozillazine.org/Getting_an_SMIME_certificate
|
||||
* In this example I am using Comodo.
|
||||
* The form is directly available via https://secure.comodo.com/products/frontpage?area=SecureEmailCertificate
|
||||
* Fill it out and you'll get an email with a link to download your certificate.
|
||||
* Usually the certificate will be directly installed into your browser (FireFox/Chrome).
|
||||
*
|
||||
*
|
||||
* STEP 2 - Exporting the certificate
|
||||
* This is specific to your browser, however, most browsers will give you the option
|
||||
* to export your recently added certificate in PKCS12 (.pfx)
|
||||
* Include your private key if you are asked for it.
|
||||
* Set up a password to protect your exported file.
|
||||
*
|
||||
* STEP 3 - Splitting the .pfx into a private key and the certificate.
|
||||
* I use openssl for this. You only need two commands. In my case the certificate file is called 'exported-cert.pfx'
|
||||
* To create the private key do the following:
|
||||
*
|
||||
* openssl pkcs12 -in exported-cert.pfx -nocerts -out cert.key
|
||||
*
|
||||
* Of course the way you name your file (-out) is up to you.
|
||||
* You will be asked for a password for the Import password. This is the password you
|
||||
* set while exporting the certificate into the pfx file.
|
||||
* Afterwards, you can password protect your private key (recommended)
|
||||
* Also make sure to set the permissions to a minimum level and suitable for your application.
|
||||
* To create the certificate file use the following command:
|
||||
*
|
||||
* openssl pkcs12 -in exported-cert.pfx -clcerts -nokeys -out cert.crt
|
||||
*
|
||||
* Again, the way you name your certificate is up to you. You will be also asked for the Import Password.
|
||||
* To create the certificate-chain file use the following command:
|
||||
*
|
||||
* openssl pkcs12 -in exported-cert.pfx -cacerts -out certchain.pem
|
||||
*
|
||||
* Again, the way you name your chain file is up to you. You will be also asked for the Import Password.
|
||||
*
|
||||
*
|
||||
* STEP 3 - Code
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
//Set who the message is to be sent from
|
||||
//IMPORTANT: This must match the email address of your certificate.
|
||||
//Although the certificate will be valid, an error will be thrown since it cannot be verified
|
||||
//that the sender and the signer are the same person.
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
//Set an alternative reply-to address
|
||||
$mail->addReplyTo('replyto@example.com', 'First Last');
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer mail() test';
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//Convert HTML into a basic plain-text alternative body
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
//Attach an image file
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
|
||||
//Configure message signing (the actual signing does not occur until sending)
|
||||
$mail->sign(
|
||||
'/path/to/cert.crt', //The location of your certificate file
|
||||
'/path/to/cert.key', //The location of your private key file
|
||||
//The password you protected your private key with (not the Import Password!
|
||||
//May be empty but the parameter must not be omitted!
|
||||
'yourSecretPrivateKeyPassword',
|
||||
'/path/to/certchain.pem' //The location of your chain file
|
||||
);
|
||||
|
||||
//Send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
}
|
||||
/*
|
||||
* REMARKS:
|
||||
* If your email client does not support S/MIME it will most likely just show an attachment smime.p7s,
|
||||
* which is the signature contained in the email.
|
||||
* Other clients, such as Thunderbird support S/MIME natively and will validate the signature
|
||||
* automatically and report the result in some way.
|
||||
*/
|
||||
62
vendor/phpmailer/phpmailer/examples/smtp.phps
vendored
62
vendor/phpmailer/phpmailer/examples/smtp.phps
vendored
@@ -1,62 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows making an SMTP connection with authentication.
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
|
||||
//SMTP needs accurate times, and the PHP time zone MUST be set
|
||||
//This should be done in your php.ini, but this is how to do it if you don't have access to that
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
//Tell PHPMailer to use SMTP
|
||||
$mail->isSMTP();
|
||||
//Enable SMTP debugging
|
||||
//SMTP::DEBUG_OFF = off (for production use)
|
||||
//SMTP::DEBUG_CLIENT = client messages
|
||||
//SMTP::DEBUG_SERVER = client and server messages
|
||||
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
|
||||
//Set the hostname of the mail server
|
||||
$mail->Host = 'mail.example.com';
|
||||
//Set the SMTP port number - likely to be 25, 465 or 587
|
||||
$mail->Port = 25;
|
||||
//Whether to use SMTP authentication
|
||||
$mail->SMTPAuth = true;
|
||||
//Username to use for SMTP authentication
|
||||
$mail->Username = 'yourname@example.com';
|
||||
//Password to use for SMTP authentication
|
||||
$mail->Password = 'yourpassword';
|
||||
//Set who the message is to be sent from
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
//Set an alternative reply-to address
|
||||
$mail->addReplyTo('replyto@example.com', 'First Last');
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer SMTP test';
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//convert HTML into a basic plain-text alternative body
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
//Attach an image file
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
|
||||
//SMTP XCLIENT attributes can be passed with setSMTPXclientAttribute method
|
||||
//$mail->setSMTPXclientAttribute('LOGIN', 'yourname@example.com');
|
||||
//$mail->setSMTPXclientAttribute('ADDR', '10.10.10.10');
|
||||
//$mail->setSMTPXclientAttribute('HELO', 'test.example.com');
|
||||
|
||||
//send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This uses the SMTP class alone to check that a connection can be made to an SMTP server,
|
||||
* authenticate, then disconnect
|
||||
*/
|
||||
|
||||
//Import the PHPMailer SMTP class into the global namespace
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//SMTP needs accurate times, and the PHP time zone MUST be set
|
||||
//This should be done in your php.ini, but this is how to do it if you don't have access to that
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
//Create a new SMTP instance
|
||||
$smtp = new SMTP();
|
||||
|
||||
//Enable connection-level debug output
|
||||
$smtp->do_debug = SMTP::DEBUG_CONNECTION;
|
||||
|
||||
try {
|
||||
//Connect to an SMTP server
|
||||
if (!$smtp->connect('mail.example.com', 25)) {
|
||||
throw new Exception('Connect failed');
|
||||
}
|
||||
//Say hello
|
||||
if (!$smtp->hello(gethostname())) {
|
||||
throw new Exception('EHLO failed: ' . $smtp->getError()['error']);
|
||||
}
|
||||
//Get the list of ESMTP services the server offers
|
||||
$e = $smtp->getServerExtList();
|
||||
//If server can do TLS encryption, use it
|
||||
if (is_array($e) && array_key_exists('STARTTLS', $e)) {
|
||||
$tlsok = $smtp->startTLS();
|
||||
if (!$tlsok) {
|
||||
throw new Exception('Failed to start encryption: ' . $smtp->getError()['error']);
|
||||
}
|
||||
//Repeat EHLO after STARTTLS
|
||||
if (!$smtp->hello(gethostname())) {
|
||||
throw new Exception('EHLO (2) failed: ' . $smtp->getError()['error']);
|
||||
}
|
||||
//Get new capabilities list, which will usually now include AUTH if it didn't before
|
||||
$e = $smtp->getServerExtList();
|
||||
}
|
||||
//If server supports authentication, do it (even if no encryption)
|
||||
if (is_array($e) && array_key_exists('AUTH', $e)) {
|
||||
if ($smtp->authenticate('username', 'password')) {
|
||||
echo 'Connected ok!';
|
||||
} else {
|
||||
throw new Exception('Authentication failed: ' . $smtp->getError()['error']);
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo 'SMTP error: ' . $e->getMessage(), "\n";
|
||||
}
|
||||
//Whatever happened, close the connection.
|
||||
$smtp->quit();
|
||||
@@ -1,117 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SMTP low memory example.
|
||||
*/
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
|
||||
/**
|
||||
* This class demonstrates sending an already-built RFC822 message via SMTP
|
||||
* by extending PHPMailer's SMTP class.
|
||||
* It uses less memory than PHPMailer's usual approach because it keeps
|
||||
* the message as a single string rather than splitting its lines into
|
||||
* an array, which can consume very large amounts of memory if you have
|
||||
* large attachments. The downside is that it's somewhat slower.
|
||||
* This is mainly of academic interest, but shows how you can change how
|
||||
* core classes work without having to alter the library itself.
|
||||
*/
|
||||
class SMTPLowMemory extends SMTP
|
||||
{
|
||||
public function data($msg_data)
|
||||
{
|
||||
//This will use the standard timelimit
|
||||
if (!$this->sendCommand('DATA', 'DATA', 354)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The server is ready to accept data!
|
||||
* According to rfc821 we should not send more than 1000 characters on a single line (including the LE)
|
||||
* so we will break the data up into lines by \r and/or \n then if needed we will break each of those into
|
||||
* smaller lines to fit within the limit.
|
||||
* We will also look for lines that start with a '.' and prepend an additional '.' (which does not count
|
||||
* towards the line-length limit), in order to implement the "dot stuffing" required by RFC5321 sections:
|
||||
* https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.2
|
||||
* https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1.6.
|
||||
*/
|
||||
|
||||
//Normalize line breaks
|
||||
$msg_data = str_replace(["\r\n", "\r"], "\n", $msg_data);
|
||||
|
||||
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
|
||||
* of the first line (':' separated) does not contain a space then it _should_ be a header and we will
|
||||
* process all lines before a blank line as headers.
|
||||
*/
|
||||
|
||||
$firstline = substr($msg_data, 0, strcspn($msg_data, "\n", 0));
|
||||
$field = substr($firstline, 0, strpos($firstline, ':'));
|
||||
$in_headers = false;
|
||||
if (!empty($field) && strpos($field, ' ') === false) {
|
||||
$in_headers = true;
|
||||
}
|
||||
|
||||
$offset = 0;
|
||||
$len = strlen($msg_data);
|
||||
while ($offset < $len) {
|
||||
//Get position of next line break
|
||||
$linelen = strcspn($msg_data, "\n", $offset);
|
||||
//Get the next line
|
||||
$line = substr($msg_data, $offset, $linelen);
|
||||
//Remember where we have got to
|
||||
$offset += ($linelen + 1);
|
||||
$lines_out = [];
|
||||
if ($in_headers && $line === '') {
|
||||
$in_headers = false;
|
||||
}
|
||||
//We need to break this line up into several smaller lines
|
||||
//This is a small micro-optimisation: isset($str[$len]) is equivalent to (strlen($str) > $len)
|
||||
while (isset($line[self::MAX_LINE_LENGTH])) {
|
||||
//Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on
|
||||
//so as to avoid breaking in the middle of a word
|
||||
$pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' ');
|
||||
//Deliberately matches both false and 0
|
||||
if (!$pos) {
|
||||
//No nice break found, add a hard break
|
||||
$pos = self::MAX_LINE_LENGTH - 1;
|
||||
$lines_out[] = substr($line, 0, $pos);
|
||||
$line = substr($line, $pos);
|
||||
} else {
|
||||
//Break at the found point
|
||||
$lines_out[] = substr($line, 0, $pos);
|
||||
//Move along by the amount we dealt with
|
||||
$line = substr($line, $pos + 1);
|
||||
}
|
||||
//If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1
|
||||
if ($in_headers) {
|
||||
$line = "\t" . $line;
|
||||
}
|
||||
}
|
||||
$lines_out[] = $line;
|
||||
|
||||
//Send the lines to the server
|
||||
foreach ($lines_out as $line_out) {
|
||||
//RFC2821 section 4.5.2
|
||||
if (!empty($line_out) && $line_out[0] === '.') {
|
||||
$line_out = '.' . $line_out;
|
||||
}
|
||||
$this->client_send($line_out . self::LE);
|
||||
}
|
||||
}
|
||||
|
||||
//Message data has been sent, complete the command
|
||||
//Increase timelimit for end of DATA command
|
||||
$savetimelimit = $this->Timelimit;
|
||||
$this->Timelimit *= 2;
|
||||
$result = $this->sendCommand('DATA END', '.', 250);
|
||||
//Restore timelimit
|
||||
$this->Timelimit = $savetimelimit;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
//To make PHPMailer use our custom SMTP class, we need to give it an instance
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->setSMTPInstance(new SMTPLowMemory());
|
||||
//Now carry on as normal
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows making an SMTP connection without using authentication.
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
|
||||
//SMTP needs accurate times, and the PHP time zone MUST be set
|
||||
//This should be done in your php.ini, but this is how to do it if you don't have access to that
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
//Tell PHPMailer to use SMTP
|
||||
$mail->isSMTP();
|
||||
//Enable SMTP debugging
|
||||
//SMTP::DEBUG_OFF = off (for production use)
|
||||
//SMTP::DEBUG_CLIENT = client messages
|
||||
//SMTP::DEBUG_SERVER = client and server messages
|
||||
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
|
||||
//Set the hostname of the mail server
|
||||
$mail->Host = 'mail.example.com';
|
||||
//Set the SMTP port number - likely to be 25, 465 or 587
|
||||
$mail->Port = 25;
|
||||
//We don't need to set this as it's the default value
|
||||
//$mail->SMTPAuth = false;
|
||||
//Set who the message is to be sent from
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
//Set an alternative reply-to address
|
||||
$mail->addReplyTo('replyto@example.com', 'First Last');
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer SMTP without auth test';
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//convert HTML into a basic plain-text alternative body
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
//Replace the plain text body with one created manually
|
||||
$mail->AltBody = 'This is a plain-text message body';
|
||||
//Attach an image file
|
||||
$mail->addAttachment('images/phpmailer_mini.png');
|
||||
|
||||
//send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This example shows settings to use when sending over SMTP with TLS and custom connection options.
|
||||
*/
|
||||
|
||||
//Import the PHPMailer class into the global namespace
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
|
||||
//SMTP needs accurate times, and the PHP time zone MUST be set
|
||||
//This should be done in your php.ini, but this is how to do it if you don't have access to that
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
require '../vendor/autoload.php';
|
||||
|
||||
//Create a new PHPMailer instance
|
||||
$mail = new PHPMailer();
|
||||
|
||||
//Tell PHPMailer to use SMTP
|
||||
$mail->isSMTP();
|
||||
|
||||
//Enable SMTP debugging
|
||||
//SMTP::DEBUG_OFF = off (for production use)
|
||||
//SMTP::DEBUG_CLIENT = client messages
|
||||
//SMTP::DEBUG_SERVER = client and server messages
|
||||
$mail->SMTPDebug = SMTP::DEBUG_CONNECTION;
|
||||
|
||||
//Set the hostname of the mail server
|
||||
$mail->Host = 'smtp.example.com';
|
||||
|
||||
//Set the SMTP port number:
|
||||
// - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
|
||||
// - 587 for SMTP+STARTTLS
|
||||
$mail->Port = 465;
|
||||
|
||||
//Set the encryption mechanism to use:
|
||||
// - SMTPS (implicit TLS on port 465) or
|
||||
// - STARTTLS (explicit TLS on port 587)
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||
|
||||
//Custom connection options
|
||||
//Note that these settings are INSECURE
|
||||
$mail->SMTPOptions = array(
|
||||
'ssl' => [
|
||||
'verify_peer' => true,
|
||||
'verify_depth' => 3,
|
||||
'allow_self_signed' => true,
|
||||
'peer_name' => 'smtp.example.com',
|
||||
'cafile' => '/etc/ssl/ca_cert.pem',
|
||||
],
|
||||
);
|
||||
|
||||
//Whether to use SMTP authentication
|
||||
$mail->SMTPAuth = true;
|
||||
|
||||
//Username to use for SMTP authentication - use full email address for gmail
|
||||
$mail->Username = 'username@example.com';
|
||||
|
||||
//Password to use for SMTP authentication
|
||||
$mail->Password = 'yourpassword';
|
||||
|
||||
//Set who the message is to be sent from
|
||||
$mail->setFrom('from@example.com', 'First Last');
|
||||
|
||||
//Set who the message is to be sent to
|
||||
$mail->addAddress('whoto@example.com', 'John Doe');
|
||||
|
||||
//Set the subject line
|
||||
$mail->Subject = 'PHPMailer SMTP options test';
|
||||
|
||||
//Read an HTML message body from an external file, convert referenced images to embedded,
|
||||
//convert HTML into a basic plain-text alternative body
|
||||
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
|
||||
|
||||
//Send the message, check for errors
|
||||
if (!$mail->send()) {
|
||||
echo 'Mailer Error: ' . $mail->ErrorInfo;
|
||||
} else {
|
||||
echo 'Message sent!';
|
||||
}
|
||||
@@ -3,25 +3,32 @@
|
||||
/**
|
||||
* Portuguese (European) PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
* @author Jonadabe <jonadabe@hotmail.com>
|
||||
* @author João Vieira <mail@joaovieira.eu>
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'Erro do SMTP: Não foi possível realizar a autenticação.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Erro do SMTP: Não foi possível realizar ligação com o servidor SMTP.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Erro do SMTP: Os dados foram rejeitados.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'A mensagem no e-mail está vazia.';
|
||||
$PHPMAILER_LANG['authenticate'] = 'Erro SMTP: Falha na autenticação.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'A sua versão do PHP tem um bug que pode causar mensagens corrompidas. Para resolver, utilize o envio por SMTP, desative a opção mail.add_x_header no ficheiro php.ini, mude para MacOS ou Linux, ou atualize o PHP para a versão 7.0.17+ ou 7.1.3+.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Erro SMTP: Não foi possível ligar ao servidor SMTP.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Erro SMTP: Dados não aceites.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'A mensagem de e-mail está vazia.';
|
||||
$PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Não foi possível executar: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder o ficheiro: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Abertura do ficheiro: Não foi possível abrir o ficheiro: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Ocorreram falhas nos endereços dos seguintes remententes: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Não foi possível iniciar uma instância da função mail.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Não foi enviado nenhum e-mail para o endereço de e-mail inválido: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Tem de fornecer pelo menos um endereço como destinatário do e-mail.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'Erro do SMTP: O endereço do seguinte destinatário falhou: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Erro ao assinar: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Extensão em falta: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder ao ficheiro: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Erro ao abrir o ficheiro: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'O envio falhou para o seguinte endereço do remetente: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Não foi possível instanciar a função mail.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Endereço de e-mail inválido: ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Nome ou valor do cabeçalho inválido.';
|
||||
$PHPMAILER_LANG['invalid_hostentry'] = 'Entrada de host inválida: ';
|
||||
$PHPMAILER_LANG['invalid_host'] = 'Host inválido: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = 'O cliente de e-mail não é suportado.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Deve fornecer pelo menos um endereço de destinatário.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'Erro SMTP: Falha no envio para os seguintes destinatários: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Erro ao assinar: ';
|
||||
$PHPMAILER_LANG['smtp_code'] = 'Código SMTP: ';
|
||||
$PHPMAILER_LANG['smtp_code_ex'] = 'Informações adicionais SMTP: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'Falha na função SMTP connect().';
|
||||
$PHPMAILER_LANG['smtp_detail'] = 'Detalhes: ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Erro do servidor SMTP: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';
|
||||
|
||||
42
vendor/phpmailer/phpmailer/phpcs.xml.dist
vendored
42
vendor/phpmailer/phpmailer/phpcs.xml.dist
vendored
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
||||
|
||||
<config name="testVersion" value="5.5-"/>
|
||||
|
||||
<arg name="basepath" value="."/>
|
||||
<arg name="cache" value=".phpcs-cache"/>
|
||||
<arg name="colors"/>
|
||||
<arg name="extensions" value="php,phps"/>
|
||||
<arg name="parallel" value="10"/>
|
||||
<!-- Show progress -->
|
||||
<arg value="p"/>
|
||||
|
||||
<file>get_oauth_token.php</file>
|
||||
<file>src</file>
|
||||
<file>test</file>
|
||||
<file>examples</file>
|
||||
<file>language</file>
|
||||
|
||||
<rule ref="PSR12">
|
||||
<exclude name="PSR1.Classes.ClassDeclaration.MissingNamespace"/>
|
||||
<exclude name="PSR1.Classes.ClassDeclaration.MultipleClasses"/>
|
||||
<exclude name="PSR1.Files.SideEffects.FoundWithSymbols"/>
|
||||
<exclude name="PSR1.Methods.CamelCapsMethodName"/>
|
||||
<exclude name="PSR1.Methods.CamelCapsMethodName.NotCamelCaps"/>
|
||||
<exclude name="PSR2.Methods.MethodDeclaration.Underscore"/>
|
||||
<exclude name="PSR12.Properties.ConstantVisibility.NotFound"/>
|
||||
</rule>
|
||||
<rule ref="PHPCompatibility">
|
||||
<exclude name="PHPCompatibility.Constants.NewConstants.stream_crypto_method_tlsv1_1_clientFound"/>
|
||||
<exclude name="PHPCompatibility.Constants.NewConstants.stream_crypto_method_tlsv1_2_clientFound"/>
|
||||
<exclude name="PHPCompatibility.Constants.RemovedConstants.intl_idna_variant_2003Deprecated"/>
|
||||
<exclude name="PHPCompatibility.FunctionUse.NewFunctions.random_bytesFound"/>
|
||||
<exclude name="PHPCompatibility.IniDirectives.RemovedIniDirectives.mbstring_func_overloadDeprecated"/>
|
||||
<exclude name="PHPCompatibility.ParameterValues.NewIDNVariantDefault.NotSet"/>
|
||||
</rule>
|
||||
|
||||
<rule ref="Generic.Files.LineLength.TooLong">
|
||||
<exclude-pattern>*/language/phpmailer\.lang*\.php$</exclude-pattern>
|
||||
</rule>
|
||||
</ruleset>
|
||||
20
vendor/phpmailer/phpmailer/phpdoc.dist.xml
vendored
20
vendor/phpmailer/phpmailer/phpdoc.dist.xml
vendored
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpdoc>
|
||||
<title>PHPMailer</title>
|
||||
<parser>
|
||||
<target>docs</target>
|
||||
<encoding>utf8</encoding>
|
||||
<markers>
|
||||
<item>TODO</item>
|
||||
</markers>
|
||||
</parser>
|
||||
<transformer>
|
||||
<target>docs</target>
|
||||
</transformer>
|
||||
<transformations>
|
||||
<template name="clean"/>
|
||||
</transformations>
|
||||
<files>
|
||||
<directory>src</directory>
|
||||
</files>
|
||||
</phpdoc>
|
||||
36
vendor/phpmailer/phpmailer/phpunit.xml.dist
vendored
36
vendor/phpmailer/phpmailer/phpunit.xml.dist
vendored
@@ -1,36 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd"
|
||||
backupGlobals="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
convertDeprecationsToExceptions="true"
|
||||
verbose="true"
|
||||
colors="true"
|
||||
forceCoversAnnotation="false"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="PHPMailerTests">
|
||||
<directory>./test/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<listeners>
|
||||
<listener class="PHPMailer\Test\DebugLogTestListener" />
|
||||
</listeners>
|
||||
<groups>
|
||||
<exclude>
|
||||
<group>languages</group>
|
||||
<group>pop3</group>
|
||||
</exclude>
|
||||
</groups>
|
||||
<filter>
|
||||
<whitelist addUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">./src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true"/>
|
||||
<log type="coverage-clover" target="build/logs/clover.xml"/>
|
||||
<log type="junit" target="build/logs/junit.xml"/>
|
||||
</logging>
|
||||
</phpunit>
|
||||
142
vendor/phpmailer/phpmailer/src/PHPMailer.php
vendored
142
vendor/phpmailer/phpmailer/src/PHPMailer.php
vendored
@@ -580,6 +580,10 @@ class PHPMailer
|
||||
* May be a callable to inject your own validator, but there are several built-in validators.
|
||||
* The default validator uses PHP's FILTER_VALIDATE_EMAIL filter_var option.
|
||||
*
|
||||
* If CharSet is UTF8, the validator is left at the default value,
|
||||
* and you send to addresses that use non-ASCII local parts, then
|
||||
* PHPMailer automatically changes to the 'eai' validator.
|
||||
*
|
||||
* @see PHPMailer::validateAddress()
|
||||
*
|
||||
* @var string|callable
|
||||
@@ -659,6 +663,14 @@ class PHPMailer
|
||||
*/
|
||||
protected $ReplyToQueue = [];
|
||||
|
||||
/**
|
||||
* Whether the need for SMTPUTF8 has been detected. Set by
|
||||
* preSend() if necessary.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $UseSMTPUTF8 = false;
|
||||
|
||||
/**
|
||||
* The array of attachments.
|
||||
*
|
||||
@@ -756,7 +768,7 @@ class PHPMailer
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '6.9.3';
|
||||
const VERSION = '6.12.0';
|
||||
|
||||
/**
|
||||
* Error severity: message only, continue processing.
|
||||
@@ -1110,19 +1122,22 @@ class PHPMailer
|
||||
$params = [$kind, $address, $name];
|
||||
//Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
|
||||
//Domain is assumed to be whatever is after the last @ symbol in the address
|
||||
if (static::idnSupported() && $this->has8bitChars(substr($address, ++$pos))) {
|
||||
if ('Reply-To' !== $kind) {
|
||||
if (!array_key_exists($address, $this->RecipientsQueue)) {
|
||||
$this->RecipientsQueue[$address] = $params;
|
||||
if ($this->has8bitChars(substr($address, ++$pos))) {
|
||||
if (static::idnSupported()) {
|
||||
if ('Reply-To' !== $kind) {
|
||||
if (!array_key_exists($address, $this->RecipientsQueue)) {
|
||||
$this->RecipientsQueue[$address] = $params;
|
||||
|
||||
return true;
|
||||
}
|
||||
} elseif (!array_key_exists($address, $this->ReplyToQueue)) {
|
||||
$this->ReplyToQueue[$address] = $params;
|
||||
|
||||
return true;
|
||||
}
|
||||
} elseif (!array_key_exists($address, $this->ReplyToQueue)) {
|
||||
$this->ReplyToQueue[$address] = $params;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//We have an 8-bit domain, but we are missing the necessary extensions to support it
|
||||
//Or we are already sending to this address
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1160,6 +1175,15 @@ class PHPMailer
|
||||
*/
|
||||
protected function addAnAddress($kind, $address, $name = '')
|
||||
{
|
||||
if (
|
||||
self::$validator === 'php' &&
|
||||
((bool) preg_match('/[\x80-\xFF]/', $address))
|
||||
) {
|
||||
//The caller has not altered the validator and is sending to an address
|
||||
//with UTF-8, so assume that they want UTF-8 support instead of failing
|
||||
$this->CharSet = self::CHARSET_UTF8;
|
||||
self::$validator = 'eai';
|
||||
}
|
||||
if (!in_array($kind, ['to', 'cc', 'bcc', 'Reply-To'])) {
|
||||
$error_message = sprintf(
|
||||
'%s: %s',
|
||||
@@ -1362,6 +1386,7 @@ class PHPMailer
|
||||
* * `pcre` Use old PCRE implementation;
|
||||
* * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
|
||||
* * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
|
||||
* * `eai` Use a pattern similar to the HTML5 spec for 'email' and to firefox, extended to support EAI (RFC6530).
|
||||
* * `noregex` Don't use a regex: super fast, really dumb.
|
||||
* Alternatively you may pass in a callable to inject your own validator, for example:
|
||||
*
|
||||
@@ -1432,6 +1457,24 @@ class PHPMailer
|
||||
'[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
|
||||
$address
|
||||
);
|
||||
case 'eai':
|
||||
/*
|
||||
* This is the pattern used in the HTML5 spec for validation of 'email' type
|
||||
* form input elements (as above), modified to accept Unicode email addresses.
|
||||
* This is also more lenient than Firefox' html5 spec, in order to make the regex faster.
|
||||
* 'eai' is an acronym for Email Address Internationalization.
|
||||
* This validator is selected automatically if you attempt to use recipient addresses
|
||||
* that contain Unicode characters in the local part.
|
||||
*
|
||||
* @see https://html.spec.whatwg.org/#e-mail-state-(type=email)
|
||||
* @see https://en.wikipedia.org/wiki/International_email
|
||||
*/
|
||||
return (bool) preg_match(
|
||||
'/^[-\p{L}\p{N}\p{M}.!#$%&\'*+\/=?^_`{|}~]+@[\p{L}\p{N}\p{M}](?:[\p{L}\p{N}\p{M}-]{0,61}' .
|
||||
'[\p{L}\p{N}\p{M}])?(?:\.[\p{L}\p{N}\p{M}]' .
|
||||
'(?:[-\p{L}\p{N}\p{M}]{0,61}[\p{L}\p{N}\p{M}])?)*$/usD',
|
||||
$address
|
||||
);
|
||||
case 'php':
|
||||
default:
|
||||
return filter_var($address, FILTER_VALIDATE_EMAIL) !== false;
|
||||
@@ -1565,9 +1608,26 @@ class PHPMailer
|
||||
$this->error_count = 0; //Reset errors
|
||||
$this->mailHeader = '';
|
||||
|
||||
//The code below tries to support full use of Unicode,
|
||||
//while remaining compatible with legacy SMTP servers to
|
||||
//the greatest degree possible: If the message uses
|
||||
//Unicode in the local parts of any addresses, it is sent
|
||||
//using SMTPUTF8. If not, it it sent using
|
||||
//punycode-encoded domains and plain SMTP.
|
||||
if (
|
||||
static::CHARSET_UTF8 === strtolower($this->CharSet) &&
|
||||
($this->anyAddressHasUnicodeLocalPart($this->RecipientsQueue) ||
|
||||
$this->anyAddressHasUnicodeLocalPart(array_keys($this->all_recipients)) ||
|
||||
$this->anyAddressHasUnicodeLocalPart($this->ReplyToQueue) ||
|
||||
$this->addressHasUnicodeLocalPart($this->From))
|
||||
) {
|
||||
$this->UseSMTPUTF8 = true;
|
||||
}
|
||||
//Dequeue recipient and Reply-To addresses with IDN
|
||||
foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
|
||||
$params[1] = $this->punyencodeAddress($params[1]);
|
||||
if (!$this->UseSMTPUTF8) {
|
||||
$params[1] = $this->punyencodeAddress($params[1]);
|
||||
}
|
||||
call_user_func_array([$this, 'addAnAddress'], $params);
|
||||
}
|
||||
if (count($this->to) + count($this->cc) + count($this->bcc) < 1) {
|
||||
@@ -2058,6 +2118,11 @@ class PHPMailer
|
||||
if (!$this->smtpConnect($this->SMTPOptions)) {
|
||||
throw new Exception($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
|
||||
}
|
||||
//If we have recipient addresses that need Unicode support,
|
||||
//but the server doesn't support it, stop here
|
||||
if ($this->UseSMTPUTF8 && !$this->smtp->getServerExt('SMTPUTF8')) {
|
||||
throw new Exception($this->lang('no_smtputf8'), self::STOP_CRITICAL);
|
||||
}
|
||||
//Sender already validated in preSend()
|
||||
if ('' === $this->Sender) {
|
||||
$smtp_from = $this->From;
|
||||
@@ -2159,6 +2224,7 @@ class PHPMailer
|
||||
$this->smtp->setDebugLevel($this->SMTPDebug);
|
||||
$this->smtp->setDebugOutput($this->Debugoutput);
|
||||
$this->smtp->setVerp($this->do_verp);
|
||||
$this->smtp->setSMTPUTF8($this->UseSMTPUTF8);
|
||||
if ($this->Host === null) {
|
||||
$this->Host = 'localhost';
|
||||
}
|
||||
@@ -2356,6 +2422,7 @@ class PHPMailer
|
||||
'smtp_detail' => 'Detail: ',
|
||||
'smtp_error' => 'SMTP server error: ',
|
||||
'variable_set' => 'Cannot set or reset variable: ',
|
||||
'no_smtputf8' => 'Server does not support SMTPUTF8 needed to send to Unicode addresses',
|
||||
];
|
||||
if (empty($lang_path)) {
|
||||
//Calculate an absolute path so it can work if CWD is not here
|
||||
@@ -2870,7 +2937,9 @@ class PHPMailer
|
||||
$bodyEncoding = $this->Encoding;
|
||||
$bodyCharSet = $this->CharSet;
|
||||
//Can we do a 7-bit downgrade?
|
||||
if (static::ENCODING_8BIT === $bodyEncoding && !$this->has8bitChars($this->Body)) {
|
||||
if ($this->UseSMTPUTF8) {
|
||||
$bodyEncoding = static::ENCODING_8BIT;
|
||||
} elseif (static::ENCODING_8BIT === $bodyEncoding && !$this->has8bitChars($this->Body)) {
|
||||
$bodyEncoding = static::ENCODING_7BIT;
|
||||
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
|
||||
$bodyCharSet = static::CHARSET_ASCII;
|
||||
@@ -3507,7 +3576,8 @@ class PHPMailer
|
||||
/**
|
||||
* Encode a header value (not including its label) optimally.
|
||||
* Picks shortest of Q, B, or none. Result includes folding if needed.
|
||||
* See RFC822 definitions for phrase, comment and text positions.
|
||||
* See RFC822 definitions for phrase, comment and text positions,
|
||||
* and RFC2047 for inline encodings.
|
||||
*
|
||||
* @param string $str The header value to encode
|
||||
* @param string $position What context the string will be used in
|
||||
@@ -3516,6 +3586,11 @@ class PHPMailer
|
||||
*/
|
||||
public function encodeHeader($str, $position = 'text')
|
||||
{
|
||||
$position = strtolower($position);
|
||||
if ($this->UseSMTPUTF8 && !("comment" === $position)) {
|
||||
return trim(static::normalizeBreaks($str));
|
||||
}
|
||||
|
||||
$matchcount = 0;
|
||||
switch (strtolower($position)) {
|
||||
case 'phrase':
|
||||
@@ -4180,7 +4255,7 @@ class PHPMailer
|
||||
if ('smtp' === $this->Mailer && null !== $this->smtp) {
|
||||
$lasterror = $this->smtp->getError();
|
||||
if (!empty($lasterror['error'])) {
|
||||
$msg .= $this->lang('smtp_error') . $lasterror['error'];
|
||||
$msg .= ' ' . $this->lang('smtp_error') . $lasterror['error'];
|
||||
if (!empty($lasterror['detail'])) {
|
||||
$msg .= ' ' . $this->lang('smtp_detail') . $lasterror['detail'];
|
||||
}
|
||||
@@ -4267,6 +4342,45 @@ class PHPMailer
|
||||
return filter_var('https://' . $host, FILTER_VALIDATE_URL) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the supplied address uses Unicode in the local part.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function addressHasUnicodeLocalPart($address)
|
||||
{
|
||||
return (bool) preg_match('/[\x80-\xFF].*@/', $address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether any of the supplied addresses use Unicode in the local part.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function anyAddressHasUnicodeLocalPart($addresses)
|
||||
{
|
||||
foreach ($addresses as $address) {
|
||||
if (is_array($address)) {
|
||||
$address = $address[0];
|
||||
}
|
||||
if ($this->addressHasUnicodeLocalPart($address)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the message requires SMTPUTF8 based on what's known so far.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function needsSMTPUTF8()
|
||||
{
|
||||
return $this->UseSMTPUTF8;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an error message in the current language.
|
||||
*
|
||||
|
||||
2
vendor/phpmailer/phpmailer/src/POP3.php
vendored
2
vendor/phpmailer/phpmailer/src/POP3.php
vendored
@@ -46,7 +46,7 @@ class POP3
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '6.9.3';
|
||||
const VERSION = '6.12.0';
|
||||
|
||||
/**
|
||||
* Default POP3 port number.
|
||||
|
||||
44
vendor/phpmailer/phpmailer/src/SMTP.php
vendored
44
vendor/phpmailer/phpmailer/src/SMTP.php
vendored
@@ -35,7 +35,7 @@ class SMTP
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '6.9.3';
|
||||
const VERSION = '6.12.0';
|
||||
|
||||
/**
|
||||
* SMTP line break constant.
|
||||
@@ -159,6 +159,15 @@ class SMTP
|
||||
*/
|
||||
public $do_verp = false;
|
||||
|
||||
/**
|
||||
* Whether to use SMTPUTF8.
|
||||
*
|
||||
* @see https://www.rfc-editor.org/rfc/rfc6531
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $do_smtputf8 = false;
|
||||
|
||||
/**
|
||||
* The timeout value for connection, in seconds.
|
||||
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2.
|
||||
@@ -913,7 +922,15 @@ class SMTP
|
||||
* $from. Returns true if successful or false otherwise. If True
|
||||
* the mail transaction is started and then one or more recipient
|
||||
* commands may be called followed by a data command.
|
||||
* Implements RFC 821: MAIL <SP> FROM:<reverse-path> <CRLF>.
|
||||
* Implements RFC 821: MAIL <SP> FROM:<reverse-path> <CRLF> and
|
||||
* two extensions, namely XVERP and SMTPUTF8.
|
||||
*
|
||||
* The server's EHLO response is not checked. If use of either
|
||||
* extensions is enabled even though the server does not support
|
||||
* that, mail submission will fail.
|
||||
*
|
||||
* XVERP is documented at https://www.postfix.org/VERP_README.html
|
||||
* and SMTPUTF8 is specified in RFC 6531.
|
||||
*
|
||||
* @param string $from Source address of this message
|
||||
*
|
||||
@@ -922,10 +939,11 @@ class SMTP
|
||||
public function mail($from)
|
||||
{
|
||||
$useVerp = ($this->do_verp ? ' XVERP' : '');
|
||||
$useSmtputf8 = ($this->do_smtputf8 ? ' SMTPUTF8' : '');
|
||||
|
||||
return $this->sendCommand(
|
||||
'MAIL FROM',
|
||||
'MAIL FROM:<' . $from . '>' . $useVerp,
|
||||
'MAIL FROM:<' . $from . '>' . $useSmtputf8 . $useVerp,
|
||||
250
|
||||
);
|
||||
}
|
||||
@@ -1364,6 +1382,26 @@ class SMTP
|
||||
return $this->do_verp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable use of SMTPUTF8.
|
||||
*
|
||||
* @param bool $enabled
|
||||
*/
|
||||
public function setSMTPUTF8($enabled = false)
|
||||
{
|
||||
$this->do_smtputf8 = $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SMTPUTF8 use.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getSMTPUTF8()
|
||||
{
|
||||
return $this->do_smtputf8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set error messages and codes.
|
||||
*
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - language file tests.
|
||||
*
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @author Juliette Reinders Folmer
|
||||
* @copyright 2010 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @copyright 2020 Juliette Reinders Folmer
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test;
|
||||
|
||||
use PHPUnit\Framework\TestListener;
|
||||
use Yoast\PHPUnitPolyfills\TestListeners\TestListenerDefaultImplementation;
|
||||
|
||||
class DebugLogTestListener implements TestListener
|
||||
{
|
||||
use TestListenerDefaultImplementation;
|
||||
|
||||
private static $debugLog = '';
|
||||
|
||||
public function add_error($test, $e, $time)
|
||||
{
|
||||
echo self::$debugLog;
|
||||
}
|
||||
|
||||
public function add_failure($test, $e, $time)
|
||||
{
|
||||
echo self::$debugLog;
|
||||
}
|
||||
|
||||
public function start_test($test)
|
||||
{
|
||||
self::$debugLog = '';
|
||||
}
|
||||
|
||||
public static function debugLog($str)
|
||||
{
|
||||
self::$debugLog .= $str . PHP_EOL;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Testing 1-2-3
|
||||
@@ -1 +0,0 @@
|
||||
Testing 1-2-3
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test overruling an existing translation
|
||||
* file with a custom one by passing in a `$langPath` parameter.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['empty_message'] = "Custom path test success (fr)";
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test overruling an existing translation
|
||||
* file with a custom one by passing in a `$langPath` parameter.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['empty_message'] = 'Custom path test success (nl)';
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test the fall-back logic.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['empty_message'] = 'XA Lang-script-country file found';
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test the fall-back logic.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['empty_message'] = 'XB Lang-script file found';
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test the fall-back logic.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['empty_message'] = 'XC Lang-country file found';
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test the fall-back logic.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['empty_message'] = 'XD Lang-country file found';
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test the fall-back logic.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['empty_message'] = 'XD Lang-script file found';
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test the fall-back logic.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['empty_message'] = 'XE Lang file found';
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest`.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['empty_message'] = 'This file should not be loaded as the path is passed incorrectly';
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test that arbitrary code in translation files is disregarded.
|
||||
*/
|
||||
|
||||
$composer = file_get_contents(__DIR__ . '/../../../composer.json');
|
||||
|
||||
echo $composer;
|
||||
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Confirming that test fixture was loaded correctly (yy).';
|
||||
$PHPMAILER_LANG['empty_message'] = $composer;
|
||||
$PHPMAILER_LANG['encoding'] = `ls -l`;
|
||||
$PHPMAILER_LANG['execute'] = exec('some harmful command');
|
||||
$PHPMAILER_LANG['signing'] = "Double quoted but not interpolated $composer";
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test that language strings not
|
||||
* set via a fixed, known group of array index keys are disregarded.
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Confirming that test fixture was loaded correctly (zz).';
|
||||
|
||||
// Keys not in the original array.
|
||||
$PHPMAILER_LANG['unknown'] = 'Unknown text.';
|
||||
$PHPMAILER_LANG['invalid'] = 'Invalid text.';
|
||||
|
||||
// Keys which exist in the original array, but use the wrong letter case or space instead of underscore.
|
||||
$PHPMAILER_LANG['Authenticate'] = 'Overruled text, index not same case';
|
||||
$PHPMAILER_LANG['CONNECT_HOST'] = 'Overruled text, index not same case';
|
||||
$PHPMAILER_LANG['Data_Not_Accepted'] = 'Overruled text, index not same case';
|
||||
$PHPMAILER_LANG['empty message'] = 'Overruled text, index not same case';
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - language file tests.
|
||||
*
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2010 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\Language;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Check language files for missing or excess translations.
|
||||
*
|
||||
* @group languages
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
final class TranslationCompletenessTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Holds a PHPMailer instance.
|
||||
*
|
||||
* @var PHPMailer
|
||||
*/
|
||||
private $Mail;
|
||||
|
||||
/**
|
||||
* Run before each test is started.
|
||||
*/
|
||||
protected function set_up()
|
||||
{
|
||||
$this->Mail = new PHPMailer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test language files for missing and excess translations.
|
||||
* All languages are compared with English, which is built-in.
|
||||
*/
|
||||
public function testTranslations()
|
||||
{
|
||||
$this->Mail->setLanguage('en');
|
||||
$definedStrings = $this->Mail->getTranslations();
|
||||
$err = '';
|
||||
foreach (new \DirectoryIterator(__DIR__ . '/../../language') as $fileInfo) {
|
||||
if ($fileInfo->isDot()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$matches = [];
|
||||
// Only look at language files, ignore anything else in there.
|
||||
if (preg_match('/^phpmailer\.lang-([a-z_]{2,})\.php$/', $fileInfo->getFilename(), $matches)) {
|
||||
$lang = $matches[1]; // Extract language code.
|
||||
$PHPMAILER_LANG = []; // Language strings get put in here.
|
||||
$lines = file($fileInfo->getPathname());
|
||||
foreach ($lines as $line) {
|
||||
// Translation file lines look like this:
|
||||
// `$PHPMAILER_LANG['authenticate'] = 'SMTP-Fehler: Authentifizierung fehlgeschlagen.';`
|
||||
// These files are parsed as text and not PHP so as to avoid the possibility of code injection.
|
||||
$matches = [];
|
||||
if (
|
||||
preg_match(
|
||||
'/^\$PHPMAILER_LANG\[\'([a-z\d_]+)\'\]\s*=\s*(["\'])(.+)*?\2;/',
|
||||
$line,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
// Overwrite language-specific strings so we'll never have missing translation keys.
|
||||
$PHPMAILER_LANG[$matches[1]] = (string)$matches[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include $fileInfo->getPathname(); // Get language strings.
|
||||
|
||||
$missing = array_diff(array_keys($definedStrings), array_keys($PHPMAILER_LANG));
|
||||
$extra = array_diff(array_keys($PHPMAILER_LANG), array_keys($definedStrings));
|
||||
if (!empty($missing)) {
|
||||
$err .= "\nMissing translations in $lang: " . implode(', ', $missing);
|
||||
}
|
||||
if (!empty($extra)) {
|
||||
$err .= "\nExtra translations in $lang: " . implode(', ', $extra);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have no extra and no missing translations, $err will be empty.
|
||||
self::assertEmpty($err, $err);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\OAuth;
|
||||
|
||||
use PHPMailer\PHPMailer\OAuth;
|
||||
use PHPMailer\PHPMailer\OAuthTokenProvider;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Test OAuth functionality.
|
||||
*/
|
||||
final class OAuthTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test OAuth class.
|
||||
*
|
||||
* @covers PHPMailer\PHPMailer\PHPMailer::getOAuth
|
||||
* @covers PHPMailer\PHPMailer\PHPMailer::setOAuth
|
||||
* @covers PHPMailer\PHPMailer\OAuth::__construct
|
||||
* @covers PHPMailer\PHPMailer\OAuthTokenProvider
|
||||
*/
|
||||
public function testOAuth()
|
||||
{
|
||||
$PHPMailer = new PHPMailer(true);
|
||||
$reflection = new \ReflectionClass($PHPMailer);
|
||||
$property = $reflection->getProperty('oauth');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($PHPMailer, true);
|
||||
self::assertTrue($PHPMailer->getOAuth(), 'Initial value of oauth property is not true');
|
||||
|
||||
$options = [
|
||||
'provider' => 'dummyprovider',
|
||||
'userName' => 'dummyusername',
|
||||
'clientSecret' => 'dummyclientsecret',
|
||||
'clientId' => 'dummyclientid',
|
||||
'refreshToken' => 'dummyrefreshtoken',
|
||||
];
|
||||
|
||||
$oauth = new OAuth($options);
|
||||
self::assertInstanceOf(OAuth::class, $oauth, 'Instantiation of OAuth class failed');
|
||||
self::assertInstanceOf(OAuthTokenProvider::class, $oauth, 'Instantiation of OAuth class failed');
|
||||
$subject = $PHPMailer->setOAuth($oauth);
|
||||
self::assertNull($subject, 'setOAuth() is not a void function');
|
||||
self::assertInstanceOf(
|
||||
OAuth::class,
|
||||
$PHPMailer->getOAuth(),
|
||||
'Setting Oauth property to an instance of the OAuth class failed'
|
||||
);
|
||||
$PHPMailer->setOAuth(new DummyOAuthProvider());
|
||||
self::assertInstanceOf(
|
||||
OAuthTokenProvider::class,
|
||||
$PHPMailer->getOAuth(),
|
||||
'Setting Oauth property to an instance of the OAuth class failed (2)'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DummyOauthProvider implements OAuthTokenProvider
|
||||
{
|
||||
public function getOauth64()
|
||||
{
|
||||
return 'oauth';
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\PreSendTestCase;
|
||||
|
||||
/**
|
||||
* Test adding embedded image(s) functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::addEmbeddedImage
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::createBody
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::getAttachments
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::inlineImageExists
|
||||
*/
|
||||
final class AddEmbeddedImageTest extends PreSendTestCase
|
||||
{
|
||||
/**
|
||||
* Test successfully adding an embedded image.
|
||||
*/
|
||||
public function testAddEmbeddedImage()
|
||||
{
|
||||
$pathToFile = realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer.png');
|
||||
$expected = [
|
||||
0 => $pathToFile,
|
||||
1 => 'phpmailer.png',
|
||||
2 => 'phpmailer.png',
|
||||
3 => 'base64',
|
||||
4 => 'image/png',
|
||||
5 => false,
|
||||
6 => 'inline',
|
||||
7 => 'my-attach',
|
||||
];
|
||||
|
||||
$this->Mail->Body = 'Embedded Image: <img alt="phpmailer" src="' .
|
||||
'cid:my-attach">' .
|
||||
'Here is an image!';
|
||||
$this->Mail->Subject .= ': Embedded Image';
|
||||
$this->Mail->isHTML(true);
|
||||
|
||||
// Test attaching the image.
|
||||
$result = $this->Mail->addEmbeddedImage(
|
||||
$pathToFile,
|
||||
'my-attach',
|
||||
'phpmailer.png',
|
||||
'base64',
|
||||
'image/png'
|
||||
);
|
||||
|
||||
self::assertTrue($result, $this->Mail->ErrorInfo);
|
||||
self::assertTrue($this->Mail->inlineImageExists(), 'Embedded image not present in attachments array');
|
||||
|
||||
$attachments = $this->Mail->getAttachments();
|
||||
self::assertIsArray($attachments, 'Attachments is not an array');
|
||||
self::assertArrayHasKey(0, $attachments, 'Attachments does not have the expected array entry');
|
||||
self::assertSame($expected, $attachments[0], 'Attachment info does not match the expected array');
|
||||
|
||||
// Test that the image was correctly added to the message body.
|
||||
$this->buildBody();
|
||||
self::assertTrue($this->Mail->preSend(), $this->Mail->ErrorInfo);
|
||||
|
||||
$sendMessage = $this->Mail->getSentMIMEMessage();
|
||||
$LE = PHPMailer::getLE();
|
||||
|
||||
self::assertStringContainsString(
|
||||
'Content-Type: image/png; name=phpmailer.png' . $LE,
|
||||
$sendMessage,
|
||||
'Embedded image header content type incorrect.'
|
||||
);
|
||||
|
||||
self::assertStringContainsString(
|
||||
'Content-ID: <my-attach>' . $LE,
|
||||
$sendMessage,
|
||||
'Embedded image header content ID incorrect.'
|
||||
);
|
||||
|
||||
self::assertStringContainsString(
|
||||
'Content-Disposition: inline; filename=phpmailer.png' . $LE,
|
||||
$sendMessage,
|
||||
'Embedded image header content disposition incorrect.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test adding an image without explicitly adding a name for the image will set the name as the existing file name.
|
||||
*/
|
||||
public function testAddingImageWithoutExplicitName()
|
||||
{
|
||||
$result = $this->Mail->addEmbeddedImage(__FILE__, '123');
|
||||
self::assertTrue($result, 'File failed to attach');
|
||||
|
||||
self::assertTrue($this->Mail->inlineImageExists(), 'Inline image not present in attachments array');
|
||||
|
||||
$attachments = $this->Mail->getAttachments();
|
||||
self::assertIsArray($attachments, 'Attachments is not an array');
|
||||
self::assertArrayHasKey(0, $attachments, 'Attachments does not have the expected array entry');
|
||||
self::assertSame($attachments[0][1], $attachments[0][2], 'Name is not the same as filename');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that embedding an image fails in select use cases.
|
||||
*
|
||||
* @dataProvider dataFailToAttach
|
||||
*
|
||||
* @param string $path Path to the attachment.
|
||||
* @param string $cid Content ID for the attachment.
|
||||
* @param string $exceptionMessage Unused in this test.
|
||||
* @param string $name Optional. Attachment name to use.
|
||||
* @param string $encoding Optional. File encoding to pass.
|
||||
*/
|
||||
public function testFailToAttach($path, $cid, $exceptionMessage, $name = '', $encoding = PHPMailer::ENCODING_BASE64)
|
||||
{
|
||||
$result = $this->Mail->addEmbeddedImage($path, $cid, $name, $encoding);
|
||||
self::assertFalse($result, 'Image did not fail to attach');
|
||||
|
||||
self::assertFalse($this->Mail->inlineImageExists(), 'Inline image present in attachments array');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that embedding an image throws an exception in select use cases.
|
||||
*
|
||||
* @dataProvider dataFailToAttach
|
||||
*
|
||||
* @param string $path Path to the attachment.
|
||||
* @param string $cid Content ID for the attachment.
|
||||
* @param string $exceptionMessage The exception message to expect.
|
||||
* @param string $name Optional. Attachment name to use.
|
||||
* @param string $encoding Optional. File encoding to pass.
|
||||
*/
|
||||
public function testFailToAttachException(
|
||||
$path,
|
||||
$cid,
|
||||
$exceptionMessage,
|
||||
$name = '',
|
||||
$encoding = PHPMailer::ENCODING_BASE64
|
||||
) {
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage($exceptionMessage);
|
||||
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->addEmbeddedImage($path, $cid, $name, $encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataFailToAttach()
|
||||
{
|
||||
return [
|
||||
'Invalid: non-existent file' => [
|
||||
'path' => 'thisfiledoesntexist',
|
||||
'cid' => 'xyz',
|
||||
'exceptionMessage' => 'Could not access file: thisfiledoesntexist',
|
||||
],
|
||||
'Invalid: invalid encoding' => [
|
||||
'path' => __FILE__,
|
||||
'cid' => 'cid',
|
||||
'exceptionMessage' => 'Unknown encoding: invalidencoding',
|
||||
'name' => 'test.png',
|
||||
'encoding' => 'invalidencoding',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\PreSendTestCase;
|
||||
|
||||
/**
|
||||
* Test adding string attachments functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::addStringAttachment
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::attachmentExists
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::createBody
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::getAttachments
|
||||
*/
|
||||
final class AddStringAttachmentTest extends PreSendTestCase
|
||||
{
|
||||
/**
|
||||
* Test successfully adding a simple plain string attachment.
|
||||
*/
|
||||
public function testAddPlainStringAttachment()
|
||||
{
|
||||
$sAttachment = 'These characters are the content of the ' .
|
||||
"string attachment.\nThis might be taken from a " .
|
||||
'database or some other such thing. ';
|
||||
|
||||
$expected = [
|
||||
0 => $sAttachment,
|
||||
1 => 'string_attach.txt',
|
||||
2 => 'string_attach.txt',
|
||||
3 => 'base64',
|
||||
4 => 'text/plain',
|
||||
5 => true,
|
||||
6 => 'attachment',
|
||||
7 => 0,
|
||||
];
|
||||
|
||||
$this->Mail->Body = 'Here is the text body';
|
||||
$this->Mail->Subject .= ': Plain + StringAttachment';
|
||||
|
||||
// Test attaching the plain string attachment.
|
||||
$result = $this->Mail->addStringAttachment($sAttachment, 'string_attach.txt');
|
||||
|
||||
self::assertTrue($result, $this->Mail->ErrorInfo);
|
||||
self::assertTrue($this->Mail->attachmentExists(), 'Plain text attachment not present in attachments array');
|
||||
|
||||
$attachments = $this->Mail->getAttachments();
|
||||
self::assertIsArray($attachments, 'Attachments is not an array');
|
||||
self::assertArrayHasKey(0, $attachments, 'Attachments does not have the expected array entry');
|
||||
self::assertSame($expected, $attachments[0], 'Attachment info does not match the expected array');
|
||||
|
||||
// Test that the plain text attachment was correctly added to the message body.
|
||||
$this->buildBody();
|
||||
self::assertTrue($this->Mail->preSend(), $this->Mail->ErrorInfo);
|
||||
|
||||
$sendMessage = $this->Mail->getSentMIMEMessage();
|
||||
$LE = PHPMailer::getLE();
|
||||
|
||||
self::assertStringContainsString(
|
||||
'Content-Type: text/plain; name=string_attach.txt' . $LE,
|
||||
$sendMessage,
|
||||
'Embedded image header content type incorrect.'
|
||||
);
|
||||
|
||||
self::assertStringNotContainsString(
|
||||
'Content-ID: ' . $LE,
|
||||
$sendMessage,
|
||||
'Embedded image header content ID not empty.'
|
||||
);
|
||||
|
||||
self::assertStringContainsString(
|
||||
'Content-Disposition: attachment; filename=string_attach.txt' . $LE,
|
||||
$sendMessage,
|
||||
'Embedded image header content disposition incorrect.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that adding a string attachment fails in select use cases.
|
||||
*
|
||||
* @dataProvider dataFailToAttach
|
||||
*
|
||||
* @param string $string String attachment data.
|
||||
* @param string $filename Name of the attachment.
|
||||
* @param string $exceptionMessage Unused in this test.
|
||||
* @param string $encoding Optional. File encoding to pass.
|
||||
*/
|
||||
public function testFailToAttach($string, $filename, $exceptionMessage, $encoding = PHPMailer::ENCODING_BASE64)
|
||||
{
|
||||
$result = $this->Mail->addStringAttachment($string, $filename, $encoding);
|
||||
self::assertFalse($result, 'String attachment did not fail to attach');
|
||||
|
||||
self::assertFalse($this->Mail->attachmentExists(), 'Attachment present in attachments array');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that adding a string attachment throws an exception in select use cases.
|
||||
*
|
||||
* @dataProvider dataFailToAttach
|
||||
*
|
||||
* @param string $string String attachment data.
|
||||
* @param string $filename Name of the attachment.
|
||||
* @param string $exceptionMessage The exception message to expect.
|
||||
* @param string $encoding Optional. File encoding to pass.
|
||||
*/
|
||||
public function testFailToAttachException(
|
||||
$string,
|
||||
$filename,
|
||||
$exceptionMessage,
|
||||
$encoding = PHPMailer::ENCODING_BASE64
|
||||
) {
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage($exceptionMessage);
|
||||
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->addStringAttachment($string, $filename, $encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataFailToAttach()
|
||||
{
|
||||
return [
|
||||
'Invalid: invalid encoding' => [
|
||||
'string' => 'hello',
|
||||
'filename' => 'test.txt',
|
||||
'exceptionMessage' => 'Unknown encoding: invalidencoding',
|
||||
'encoding' => 'invalidencoding',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\PreSendTestCase;
|
||||
|
||||
/**
|
||||
* Test adding stringified attachments functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::addStringEmbeddedImage
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::getAttachments
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::inlineImageExists
|
||||
*/
|
||||
final class AddStringEmbeddedImageTest extends PreSendTestCase
|
||||
{
|
||||
/**
|
||||
* Test successfully adding a stingified embedded image without a name.
|
||||
*/
|
||||
public function testHtmlStringEmbedNoName()
|
||||
{
|
||||
$attachmentFile = realpath(\PHPMAILER_INCLUDE_DIR . '/examples/images/phpmailer_mini.png');
|
||||
$attachmentString = file_get_contents($attachmentFile);
|
||||
$cid = hash('sha256', 'phpmailer_mini.png') . '@phpmailer.0';
|
||||
|
||||
$expected = [
|
||||
0 => $attachmentString,
|
||||
1 => '',
|
||||
2 => '',
|
||||
3 => 'base64',
|
||||
4 => '',
|
||||
5 => true,
|
||||
6 => 'inline',
|
||||
7 => $cid,
|
||||
];
|
||||
|
||||
$this->Mail->Body = 'This is the <strong>HTML</strong> part of the email.';
|
||||
$this->Mail->Subject .= ': HTML + unnamed embedded image';
|
||||
$this->Mail->isHTML(true);
|
||||
|
||||
$result = $this->Mail->addStringEmbeddedImage(
|
||||
$attachmentString,
|
||||
$cid,
|
||||
'', // Intentionally empty name.
|
||||
'base64',
|
||||
'', // Intentionally empty MIME type.
|
||||
'inline'
|
||||
);
|
||||
|
||||
self::assertTrue($result, $this->Mail->ErrorInfo);
|
||||
self::assertTrue($this->Mail->inlineImageExists(), 'Inline image not present in attachments array');
|
||||
|
||||
$attachments = $this->Mail->getAttachments();
|
||||
self::assertIsArray($attachments, 'Attachments is not an array');
|
||||
self::assertArrayHasKey(0, $attachments, 'Attachments does not have the expected array entry');
|
||||
self::assertSame($expected, $attachments[0], 'Attachment info does not match the expected array');
|
||||
|
||||
$this->buildBody();
|
||||
self::assertTrue($this->Mail->preSend(), $this->Mail->ErrorInfo);
|
||||
|
||||
$sendMessage = $this->Mail->getSentMIMEMessage();
|
||||
$LE = PHPMailer::getLE();
|
||||
|
||||
self::assertStringContainsString(
|
||||
'Content-Type: ' . $LE,
|
||||
$sendMessage,
|
||||
'Embedded image header content type incorrect.'
|
||||
);
|
||||
|
||||
self::assertStringContainsString(
|
||||
'Content-ID: <' . $cid . '>' . $LE,
|
||||
$sendMessage,
|
||||
'Embedded image header encoding incorrect.'
|
||||
);
|
||||
|
||||
self::assertStringContainsString(
|
||||
'Content-Disposition: inline' . $LE,
|
||||
$sendMessage,
|
||||
'Embedded image header content disposition incorrect.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that embedding a stringified attachment fails in select use cases.
|
||||
*
|
||||
* @dataProvider dataFailToAttach
|
||||
*
|
||||
* @param string $string The attachment binary data.
|
||||
* @param string $cid Content ID for the attachment.
|
||||
* @param string $exceptionMessage Unused in this test.
|
||||
* @param string $name Optional. Attachment name to use.
|
||||
* @param string $encoding Optional. File encoding to pass.
|
||||
*/
|
||||
public function testFailToAttach(
|
||||
$string,
|
||||
$cid,
|
||||
$exceptionMessage,
|
||||
$name = '',
|
||||
$encoding = PHPMailer::ENCODING_BASE64
|
||||
) {
|
||||
$result = $this->Mail->addStringEmbeddedImage($string, $cid, $name, $encoding);
|
||||
self::assertFalse($result, 'Stringified attachment did not fail to attach');
|
||||
|
||||
self::assertFalse($this->Mail->inlineImageExists(), 'Stringified attachment present in attachments array');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that embedding a stringified attachment throws an exception in select use cases.
|
||||
*
|
||||
* @dataProvider dataFailToAttach
|
||||
*
|
||||
* @param string $string The attachment binary data.
|
||||
* @param string $cid Content ID for the attachment.
|
||||
* @param string $exceptionMessage The exception message to expect.
|
||||
* @param string $name Optional. Attachment name to use.
|
||||
* @param string $encoding Optional. File encoding to pass.
|
||||
*/
|
||||
public function testFailToAttachException(
|
||||
$string,
|
||||
$cid,
|
||||
$exceptionMessage,
|
||||
$name = '',
|
||||
$encoding = PHPMailer::ENCODING_BASE64
|
||||
) {
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage($exceptionMessage);
|
||||
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->addStringEmbeddedImage($string, $cid, $name, $encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataFailToAttach()
|
||||
{
|
||||
return [
|
||||
'Invalid: invalid encoding' => [
|
||||
'string' => 'hello',
|
||||
'cid' => 'cid',
|
||||
'exceptionMessage' => 'Unknown encoding: invalidencoding',
|
||||
'name' => 'test.png',
|
||||
'encoding' => 'invalidencoding',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\Test\TestCase;
|
||||
|
||||
/**
|
||||
* Test address formatting.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::addrFormat
|
||||
*/
|
||||
final class AddrFormatTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test formatting an address for use in a message header
|
||||
*
|
||||
* @dataProvider dataAddrFormat
|
||||
*
|
||||
* @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name
|
||||
* @param string $expected The expected function output.
|
||||
*/
|
||||
public function testAddrFormat($addr, $expected)
|
||||
{
|
||||
$actual = $this->Mail->addrFormat($addr);
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$actual,
|
||||
'The return value from addrFormat() did not match the expected output.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataAddrFormat()
|
||||
{
|
||||
return [
|
||||
// Test cases with valid addresses.
|
||||
'Valid address: address with empty string name' => [
|
||||
'addr' => ['joe@example.com', ''],
|
||||
'expected' => 'joe@example.com',
|
||||
],
|
||||
'Valid address: address with null name' => [
|
||||
'addr' => ['joe@example.com', null],
|
||||
'expected' => 'joe@example.com',
|
||||
],
|
||||
'Valid address: address with falsy name' => [
|
||||
'addr' => ['joe@example.com', '0'],
|
||||
'expected' => '0 <joe@example.com>',
|
||||
],
|
||||
'Valid address: address with truthy name' => [
|
||||
'addr' => ['joe@example.com', 'Joe'],
|
||||
'expected' => 'Joe <joe@example.com>',
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\Test\SendTestCase;
|
||||
|
||||
/**
|
||||
* Test CRAM-MD5 authentication functionality.
|
||||
*/
|
||||
final class AuthCRAMMD5Test extends SendTestCase
|
||||
{
|
||||
/**
|
||||
* Test CRAM-MD5 authentication.
|
||||
* Needs a connection to a server that supports this auth mechanism, so commented out by default.
|
||||
*/
|
||||
public function testAuthCRAMMD5()
|
||||
{
|
||||
$this->markTestIncomplete(
|
||||
'Test needs a connection to a server supporting the CRAMMD5 auth mechanism.'
|
||||
);
|
||||
|
||||
$this->Mail->Host = 'hostname';
|
||||
$this->Mail->Port = 587;
|
||||
$this->Mail->SMTPAuth = true;
|
||||
$this->Mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
||||
$this->Mail->AuthType = 'CRAM-MD5';
|
||||
$this->Mail->Username = 'username';
|
||||
$this->Mail->Password = 'password';
|
||||
$this->Mail->Body = 'Test body';
|
||||
$this->Mail->Subject .= ': Auth CRAM-MD5';
|
||||
$this->Mail->From = 'from@example.com';
|
||||
$this->Mail->Sender = 'from@example.com';
|
||||
$this->Mail->clearAllRecipients();
|
||||
$this->Mail->addAddress('user@example.com');
|
||||
//self::assertTrue($this->mail->send(), $this->mail->ErrorInfo);
|
||||
}
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\TestCase;
|
||||
|
||||
/**
|
||||
* Test custom header functionality.
|
||||
*/
|
||||
final class CustomHeaderTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Tests setting and getting custom headers.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::addCustomHeader
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::getCustomHeaders
|
||||
*
|
||||
* @dataProvider dataAddAndGetCustomHeader
|
||||
*
|
||||
* @param array $headers Array of headers to set.
|
||||
* @param array|null $expected Optional. The expected set headers.
|
||||
* Only needs to be passed if different from the $headers array.
|
||||
*/
|
||||
public function testAddAndGetCustomHeader($headers, $expected = null)
|
||||
{
|
||||
if (isset($expected) === false) {
|
||||
$expected = $headers;
|
||||
}
|
||||
|
||||
// Test setting the custom header(s).
|
||||
foreach ($headers as $header) {
|
||||
if (isset($header[1])) {
|
||||
$set = $this->Mail->addCustomHeader($header[0], $header[1]);
|
||||
} else {
|
||||
$set = $this->Mail->addCustomHeader($header[0]);
|
||||
}
|
||||
|
||||
self::assertTrue($set, 'Custom header failed to set for ' . var_export($header, true));
|
||||
}
|
||||
|
||||
// Test retrieving the custom header(s) and verify they have been correctly set.
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->Mail->getCustomHeaders(),
|
||||
'Custom headers retrieved not the same as expected'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataAddAndGetCustomHeader()
|
||||
{
|
||||
return [
|
||||
'Single custom header' => [
|
||||
'headers' => [
|
||||
['foo', 'bar'],
|
||||
],
|
||||
],
|
||||
'Multiple custom headers' => [
|
||||
'headers' => [
|
||||
['foo', 'bar'],
|
||||
['foo', 'baz'],
|
||||
],
|
||||
],
|
||||
'Custom header: only name, no colon' => [
|
||||
'headers' => [
|
||||
['yux'],
|
||||
],
|
||||
'expected' => [
|
||||
['yux', ''],
|
||||
],
|
||||
],
|
||||
'Custom header: whitespace around name and value' => [
|
||||
'headers' => [
|
||||
[' name ', ' value '],
|
||||
],
|
||||
'expected' => [
|
||||
['name', 'value'],
|
||||
],
|
||||
],
|
||||
'Custom headers: "name: value" sets' => [
|
||||
'headers' => [
|
||||
['Content-Type: application/json'],
|
||||
['SomeHeader: Some Value'],
|
||||
],
|
||||
'expected' => [
|
||||
['Content-Type', 'application/json'],
|
||||
['SomeHeader', 'Some Value'],
|
||||
],
|
||||
],
|
||||
'Custom headers: "name:value" sets, no space and lots of space' => [
|
||||
'headers' => [
|
||||
['Content-Type:application/json'],
|
||||
['SomeHeader : Some Value'],
|
||||
],
|
||||
'expected' => [
|
||||
['Content-Type', 'application/json'],
|
||||
['SomeHeader', 'Some Value'],
|
||||
],
|
||||
],
|
||||
'Custom headers: "name: value" set with a colon in the value' => [
|
||||
'headers' => [
|
||||
['name: value:value'],
|
||||
],
|
||||
'expected' => [
|
||||
['name', 'value:value'],
|
||||
],
|
||||
],
|
||||
'Custom headers: "name: value" set without a value' => [
|
||||
'headers' => [
|
||||
['name:'],
|
||||
],
|
||||
'expected' => [
|
||||
['name', ''],
|
||||
],
|
||||
],
|
||||
'Custom header: "name: value" set with whitespace around name and value' => [
|
||||
'headers' => [
|
||||
[' name : value '],
|
||||
],
|
||||
'expected' => [
|
||||
['name', 'value'],
|
||||
],
|
||||
],
|
||||
'Custom headers: duplicate headers' => [
|
||||
'headers' => [
|
||||
['SomeHeader: Some Value'],
|
||||
['SomeHeader', 'Some Value']
|
||||
],
|
||||
'expected' => [
|
||||
['SomeHeader', 'Some Value'],
|
||||
['SomeHeader', 'Some Value'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests failing to set custom headers when the header info provided does not validate.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::addCustomHeader
|
||||
* @dataProvider dataAddCustomHeaderInvalid
|
||||
*
|
||||
* @param string $name Custom header name.
|
||||
* @param mixed $value Optional. Custom header value.
|
||||
*/
|
||||
public function testAddCustomHeaderInvalid($name, $value = null)
|
||||
{
|
||||
self::assertFalse($this->Mail->addCustomHeader($name, $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataAddCustomHeaderInvalid()
|
||||
{
|
||||
return [
|
||||
'Invalid: new line in value' => [
|
||||
'name' => 'SomeHeader',
|
||||
'value' => "Some\n Value",
|
||||
],
|
||||
'Invalid: new line in name' => [
|
||||
'name' => "Some\nHeader",
|
||||
'value' => 'Some Value',
|
||||
],
|
||||
'Invalid: empty name' => [
|
||||
'name' => ' ',
|
||||
],
|
||||
'Invalid: empty name and empty value' => [
|
||||
'name' => ' : ',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test removing previously set custom header.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::clearCustomHeader
|
||||
*/
|
||||
public function testClearCustomHeader()
|
||||
{
|
||||
// make sure 'foo' is cleared, even if there is more than one header set.
|
||||
$this->Mail->addCustomHeader('foo', 'bar');
|
||||
$this->Mail->addCustomHeader('foo', 'baz');
|
||||
self::assertSame([['foo', 'bar'], ['foo', 'baz']], $this->Mail->getCustomHeaders());
|
||||
|
||||
$this->Mail->clearCustomHeader('foo');
|
||||
|
||||
$cleared = $this->Mail->getCustomHeaders();
|
||||
self::assertIsArray($cleared);
|
||||
self::assertEmpty($cleared);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test removing previously set custom header value.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::clearCustomHeader
|
||||
*/
|
||||
public function testClearCustomHeaderValue()
|
||||
{
|
||||
// Test clearing 'name', 'value'
|
||||
$this->Mail->addCustomHeader('foo', 'bar');
|
||||
$this->Mail->addCustomHeader('foo', 'baz');
|
||||
self::assertSame([['foo', 'bar'], ['foo', 'baz']], $this->Mail->getCustomHeaders());
|
||||
|
||||
$this->Mail->clearCustomHeader('foo', 'bar');
|
||||
self::assertSame([['foo', 'baz']], array_values($this->Mail->getCustomHeaders()));
|
||||
|
||||
// Test clearing 'name: value'
|
||||
$this->Mail->addCustomHeader('foo', 'bar');
|
||||
self::assertSame([['foo', 'baz'], ['foo', 'bar']], array_values($this->Mail->getCustomHeaders()));
|
||||
|
||||
$this->Mail->clearCustomHeader('foo: bar');
|
||||
self::assertSame([['foo', 'baz']], array_values($this->Mail->getCustomHeaders()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test removing previously set custom headers.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::clearCustomHeaders
|
||||
*/
|
||||
public function testClearCustomHeaders()
|
||||
{
|
||||
$this->Mail->addCustomHeader('foo', 'bar');
|
||||
self::assertSame([['foo', 'bar']], $this->Mail->getCustomHeaders());
|
||||
|
||||
$this->Mail->clearCustomHeaders();
|
||||
|
||||
$cleared = $this->Mail->getCustomHeaders();
|
||||
self::assertIsArray($cleared);
|
||||
self::assertEmpty($cleared);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether setting a bad custom header throws exceptions.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::addCustomHeader
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function testInvalidHeaderException()
|
||||
{
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('Invalid header name or value');
|
||||
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->addCustomHeader('SomeHeader', "Some\n Value");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test replacing a previously set custom header.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::replaceCustomHeader
|
||||
*/
|
||||
public function testReplaceCustomHeader()
|
||||
{
|
||||
$this->Mail->addCustomHeader('foo', 'bar');
|
||||
$this->Mail->replaceCustomHeader('foo', 'baz');
|
||||
|
||||
// Test retrieving the custom header(s) and verify the updated value is seet.
|
||||
self::assertSame(
|
||||
[['foo', 'baz']],
|
||||
$this->Mail->getCustomHeaders(),
|
||||
'Custom header does not contain expected update'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\SendTestCase;
|
||||
|
||||
/**
|
||||
* Test DKIM signing functionality.
|
||||
*
|
||||
* @group dkim
|
||||
*/
|
||||
final class DKIMTest extends SendTestCase
|
||||
{
|
||||
/**
|
||||
* Whether or not to initialize the PHPMailer object to throw exceptions.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
const USE_EXCEPTIONS = true;
|
||||
|
||||
const PRIVATE_KEY_FILE = 'dkim_private.pem';
|
||||
|
||||
/**
|
||||
* Run after each test is completed.
|
||||
*/
|
||||
protected function tear_down()
|
||||
{
|
||||
if (file_exists(self::PRIVATE_KEY_FILE)) {
|
||||
unlink(self::PRIVATE_KEY_FILE);
|
||||
}
|
||||
|
||||
parent::tear_down();
|
||||
}
|
||||
|
||||
/**
|
||||
* DKIM body canonicalization tests.
|
||||
*
|
||||
* @link https://www.rfc-editor.org/rfc/rfc6376.html#section-3.4.4
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_BodyC
|
||||
*/
|
||||
public function testDKIMBodyCanonicalization()
|
||||
{
|
||||
// Example from https://www.rfc-editor.org/rfc/rfc6376.html#section-3.4.5.
|
||||
$prebody = " C \r\nD \t E\r\n\r\n\r\n";
|
||||
$postbody = " C \r\nD \t E\r\n";
|
||||
|
||||
self::assertSame(
|
||||
"\r\n",
|
||||
$this->Mail->DKIM_BodyC(''),
|
||||
'DKIM empty body canonicalization incorrect (Empty body)'
|
||||
);
|
||||
self::assertSame(
|
||||
'frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN/XKdLCPjaYaY=',
|
||||
base64_encode(hash('sha256', $this->Mail->DKIM_BodyC(''), true)),
|
||||
'DKIM canonicalized empty body hash mismatch'
|
||||
);
|
||||
self::assertSame($postbody, $this->Mail->DKIM_BodyC($prebody), 'DKIM body canonicalization incorrect');
|
||||
|
||||
//Ensure that non-break trailing whitespace in the body is preserved
|
||||
$prebody = " C \r\nD \t E \r\n\r\n\r\n";
|
||||
$postbody = " C \r\nD \t E \r\n";
|
||||
self::assertSame(
|
||||
$postbody,
|
||||
$this->Mail->DKIM_BodyC($prebody),
|
||||
'DKIM body canonicalization incorrect (trailing WSP)'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* DKIM header canonicalization tests.
|
||||
*
|
||||
* @link https://www.rfc-editor.org/rfc/rfc6376.html#section-3.4.2
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_HeaderC
|
||||
*/
|
||||
public function testDKIMHeaderCanonicalization()
|
||||
{
|
||||
// Example from https://www.rfc-editor.org/rfc/rfc6376.html#section-3.4.5.
|
||||
$preheaders = "A: X\r\nB : Y\t\r\n\tZ \r\n";
|
||||
$postheaders = "a:X\r\nb:Y Z\r\n";
|
||||
self::assertSame(
|
||||
$postheaders,
|
||||
$this->Mail->DKIM_HeaderC($preheaders),
|
||||
'DKIM header canonicalization incorrect'
|
||||
);
|
||||
|
||||
// Check that long folded lines with runs of spaces are canonicalized properly.
|
||||
$preheaders = 'Long-Header-1: <https://example.com/somescript.php?' .
|
||||
"id=1234567890&name=Abcdefghijklmnopquestuvwxyz&hash=\r\n abc1234\r\n" .
|
||||
"Long-Header-2: This is a long header value that contains runs of spaces and trailing \r\n" .
|
||||
' and is folded onto 2 lines';
|
||||
$postheaders = 'long-header-1:<https://example.com/somescript.php?id=1234567890&' .
|
||||
"name=Abcdefghijklmnopquestuvwxyz&hash= abc1234\r\nlong-header-2:This is a long" .
|
||||
' header value that contains runs of spaces and trailing and is folded onto 2 lines';
|
||||
self::assertSame(
|
||||
$postheaders,
|
||||
$this->Mail->DKIM_HeaderC($preheaders),
|
||||
'DKIM header canonicalization of long lines incorrect'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* DKIM copied header fields tests.
|
||||
*
|
||||
* @link https://www.rfc-editor.org/rfc/rfc6376.html#section-3.5
|
||||
*
|
||||
* @requires extension openssl
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_Add
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_Sign
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_QP
|
||||
*/
|
||||
public function testDKIMOptionalHeaderFieldsCopy()
|
||||
{
|
||||
$pk = openssl_pkey_new(
|
||||
[
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
]
|
||||
);
|
||||
openssl_pkey_export_to_file($pk, self::PRIVATE_KEY_FILE);
|
||||
$this->Mail->DKIM_private = self::PRIVATE_KEY_FILE;
|
||||
|
||||
// Example from https://www.rfc-editor.org/rfc/rfc6376.html#section-3.5.
|
||||
$from = 'from@example.com';
|
||||
$to = 'to@example.com';
|
||||
$date = 'date';
|
||||
$subject = 'example';
|
||||
|
||||
$headerLines = "From:$from\r\nTo:$to\r\nDate:$date\r\n";
|
||||
$copyHeaderFields = " z=From:$from\r\n |To:$to\r\n |Date:$date\r\n |Subject:$subject;\r\n";
|
||||
|
||||
$this->Mail->DKIM_copyHeaderFields = true;
|
||||
self::assertStringContainsString(
|
||||
$copyHeaderFields,
|
||||
$this->Mail->DKIM_Add($headerLines, $subject, ''),
|
||||
'DKIM header with copied header fields incorrect'
|
||||
);
|
||||
|
||||
$this->Mail->DKIM_copyHeaderFields = false;
|
||||
self::assertStringNotContainsString(
|
||||
$copyHeaderFields,
|
||||
$this->Mail->DKIM_Add($headerLines, $subject, ''),
|
||||
'DKIM header without copied header fields incorrect'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* DKIM signing extra headers tests.
|
||||
*
|
||||
* @requires extension openssl
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_Add
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_Sign
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_QP
|
||||
*/
|
||||
public function testDKIMExtraHeaders()
|
||||
{
|
||||
$pk = openssl_pkey_new(
|
||||
[
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
]
|
||||
);
|
||||
openssl_pkey_export_to_file($pk, self::PRIVATE_KEY_FILE);
|
||||
$this->Mail->DKIM_private = self::PRIVATE_KEY_FILE;
|
||||
|
||||
// Example from https://www.rfc-editor.org/rfc/rfc6376.html#section-3.5.
|
||||
$from = 'from@example.com';
|
||||
$to = 'to@example.com';
|
||||
$date = 'date';
|
||||
$subject = 'example';
|
||||
$anyHeader = 'foo';
|
||||
$unsubscribeUrl = '<https://www.example.com/unsubscribe/?newsletterId=anytoken&actionToken=anyToken' .
|
||||
'&otherParam=otherValue&anotherParam=anotherVeryVeryVeryLongValue>';
|
||||
|
||||
$this->Mail->addCustomHeader('X-AnyHeader', $anyHeader);
|
||||
$this->Mail->addCustomHeader('Baz', 'bar');
|
||||
$this->Mail->addCustomHeader('List-Unsubscribe', $unsubscribeUrl);
|
||||
|
||||
$this->Mail->DKIM_extraHeaders = ['Baz', 'List-Unsubscribe'];
|
||||
|
||||
$headerLines = "From:$from\r\nTo:$to\r\nDate:$date\r\n";
|
||||
$headerLines .= "X-AnyHeader:$anyHeader\r\nBaz:bar\r\n";
|
||||
$headerLines .= 'List-Unsubscribe:' . $this->Mail->encodeHeader($unsubscribeUrl) . "\r\n";
|
||||
|
||||
$headerFields = 'h=From:To:Date:Baz:List-Unsubscribe:Subject';
|
||||
|
||||
$result = $this->Mail->DKIM_Add($headerLines, $subject, '');
|
||||
|
||||
self::assertStringContainsString($headerFields, $result, 'DKIM header with extra headers incorrect');
|
||||
}
|
||||
|
||||
/**
|
||||
* DKIM Signing tests.
|
||||
*
|
||||
* @requires extension openssl
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_Add
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_Sign
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_QP
|
||||
*/
|
||||
public function testDKIMSigningMail()
|
||||
{
|
||||
$this->Mail->Subject .= ': DKIM signing';
|
||||
$this->Mail->Body = 'This message is DKIM signed.';
|
||||
$this->buildBody();
|
||||
|
||||
// Make a new key pair.
|
||||
// Note: 2048 bits is the recommended minimum key length - gmail won't accept less than 1024 bits.
|
||||
$pk = openssl_pkey_new(
|
||||
[
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
]
|
||||
);
|
||||
openssl_pkey_export_to_file($pk, self::PRIVATE_KEY_FILE);
|
||||
|
||||
$this->Mail->DKIM_domain = 'example.com';
|
||||
$this->Mail->DKIM_private = self::PRIVATE_KEY_FILE;
|
||||
$this->Mail->DKIM_selector = 'phpmailer';
|
||||
$this->Mail->DKIM_passphrase = ''; //key is not encrypted
|
||||
self::assertTrue($this->Mail->send(), 'DKIM signed mail failed');
|
||||
|
||||
$this->Mail->isMail();
|
||||
self::assertTrue($this->Mail->send(), 'DKIM signed mail via mail() failed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify behaviour of the DKIM_Sign method when Open SSL is not available and exceptions is enabled.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_Sign
|
||||
*/
|
||||
public function testDKIMSignOpenSSLNotAvailableException()
|
||||
{
|
||||
if (extension_loaded('openssl')) {
|
||||
$this->markTestSkipped('Test requires OpenSSL *not* to be available');
|
||||
}
|
||||
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('Extension missing: openssl');
|
||||
|
||||
$this->Mail->DKIM_Sign('foo');
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\TestCase;
|
||||
|
||||
/**
|
||||
* Test DKIM signing functionality.
|
||||
*
|
||||
* @group dkim
|
||||
*/
|
||||
final class DKIMWithoutExceptionsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Whether or not to initialize the PHPMailer object to throw exceptions.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
const USE_EXCEPTIONS = false;
|
||||
|
||||
/**
|
||||
* Verify behaviour of the DKIM_Sign method when Open SSL is not available and exceptions is disabled.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::DKIM_Sign
|
||||
*/
|
||||
public function testDKIMSignOpenSSLNotAvailable()
|
||||
{
|
||||
if (extension_loaded('openssl')) {
|
||||
$this->markTestSkipped('Test requires OpenSSL *not* to be available');
|
||||
}
|
||||
|
||||
$signature = $this->Mail->DKIM_Sign('foo');
|
||||
self::assertSame('', $signature);
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\DSNConfigurator;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\SMTP;
|
||||
use PHPMailer\Test\TestCase;
|
||||
|
||||
/**
|
||||
* Test configuring with DSN.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\DSNConfigurator
|
||||
*/
|
||||
final class DSNConfiguratorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test throwing exception if DSN is invalid.
|
||||
*/
|
||||
public function testInvalidDSN()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('Malformed DSN');
|
||||
|
||||
$configurator->configure($this->Mail, 'localhost');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test throwing exception if DSN scheme is invalid.
|
||||
*/
|
||||
public function testInvalidScheme()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('Invalid scheme: "ftp".');
|
||||
|
||||
$configurator->configure($this->Mail, 'ftp://localhost');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring mail.
|
||||
*/
|
||||
public function testConfigureMail()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$configurator->configure($this->Mail, 'mail://localhost');
|
||||
|
||||
self::assertEquals($this->Mail->Mailer, 'mail');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring sendmail.
|
||||
*/
|
||||
public function testConfigureSendmail()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$configurator->configure($this->Mail, 'sendmail://localhost');
|
||||
|
||||
self::assertEquals($this->Mail->Mailer, 'sendmail');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring qmail.
|
||||
*/
|
||||
public function testConfigureQmail()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$configurator->configure($this->Mail, 'qmail://localhost');
|
||||
|
||||
self::assertEquals($this->Mail->Mailer, 'qmail');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring SMTP without authentication.
|
||||
*/
|
||||
public function testConfigureSmtpWithoutAuthentication()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$configurator->configure($this->Mail, 'smtp://localhost');
|
||||
|
||||
self::assertEquals($this->Mail->Mailer, 'smtp');
|
||||
self::assertEquals($this->Mail->Host, 'localhost');
|
||||
self::assertFalse($this->Mail->SMTPAuth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring SMTP with authentication.
|
||||
*/
|
||||
public function testConfigureSmtpWithAuthentication()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$configurator->configure($this->Mail, 'smtp://user:pass@remotehost');
|
||||
|
||||
self::assertEquals($this->Mail->Mailer, 'smtp');
|
||||
self::assertEquals($this->Mail->Host, 'remotehost');
|
||||
|
||||
self::assertTrue($this->Mail->SMTPAuth);
|
||||
self::assertEquals($this->Mail->Username, 'user');
|
||||
self::assertEquals($this->Mail->Password, 'pass');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring SMTP without port.
|
||||
*/
|
||||
public function testConfigureSmtpWithoutPort()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$configurator->configure($this->Mail, 'smtp://localhost');
|
||||
|
||||
self::assertEquals($this->Mail->Mailer, 'smtp');
|
||||
self::assertEquals($this->Mail->Host, 'localhost');
|
||||
self::assertEquals($this->Mail->Port, SMTP::DEFAULT_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring SMTP with port.
|
||||
*/
|
||||
public function testConfigureSmtpWitPort()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$configurator->configure($this->Mail, 'smtp://localhost:2525');
|
||||
|
||||
self::assertEquals($this->Mail->Mailer, 'smtp');
|
||||
self::assertEquals($this->Mail->Host, 'localhost');
|
||||
self::assertEquals($this->Mail->Port, 2525);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring SMTPs without port.
|
||||
*/
|
||||
public function testConfigureSmtpsWithoutPort()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$configurator->configure($this->Mail, 'smtps://user:pass@remotehost');
|
||||
|
||||
self::assertEquals($this->Mail->Mailer, 'smtp');
|
||||
self::assertEquals($this->Mail->SMTPSecure, PHPMailer::ENCRYPTION_STARTTLS);
|
||||
|
||||
self::assertEquals($this->Mail->Host, 'remotehost');
|
||||
self::assertEquals($this->Mail->Port, SMTP::DEFAULT_SECURE_PORT);
|
||||
|
||||
self::assertTrue($this->Mail->SMTPAuth);
|
||||
self::assertEquals($this->Mail->Username, 'user');
|
||||
self::assertEquals($this->Mail->Password, 'pass');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring SMTPs with port.
|
||||
*/
|
||||
public function testConfigureWithUnknownOption()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('Unknown option: "UnknownOption".');
|
||||
|
||||
$configurator->configure($this->Mail, 'mail://locahost?UnknownOption=Value');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cofiguring options with query sting.
|
||||
*/
|
||||
public function testConfigureWithOptions()
|
||||
{
|
||||
$configurator = new DSNConfigurator();
|
||||
|
||||
$configurator->configure(
|
||||
$this->Mail,
|
||||
'sendmail://localhost?Sendmail=/usr/local/bin/sendmail&AllowEmpty=1&WordWrap=78'
|
||||
);
|
||||
|
||||
self::assertEquals($this->Mail->Mailer, 'sendmail');
|
||||
self::assertEquals($this->Mail->Sendmail, '/usr/local/bin/sendmail');
|
||||
self::assertEquals($this->Mail->AllowEmpty, true);
|
||||
self::assertEquals($this->Mail->WordWrap, 78);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test shortcut.
|
||||
*/
|
||||
public function testShortcut()
|
||||
{
|
||||
$mailer = DSNConfigurator::mailer('smtps://user@gmail.com:secret@smtp.gmail.com?SMTPDebug=3&Timeout=1000');
|
||||
|
||||
self::assertEquals($mailer->Mailer, 'smtp');
|
||||
self::assertEquals($mailer->SMTPSecure, PHPMailer::ENCRYPTION_STARTTLS);
|
||||
|
||||
self::assertEquals($mailer->Host, 'smtp.gmail.com');
|
||||
self::assertEquals($mailer->Port, SMTP::DEFAULT_SECURE_PORT);
|
||||
|
||||
self::assertTrue($mailer->SMTPAuth);
|
||||
self::assertEquals($mailer->Username, 'user@gmail.com');
|
||||
self::assertEquals($mailer->Password, 'secret');
|
||||
|
||||
self::assertEquals($mailer->SMTPDebug, 3);
|
||||
self::assertEquals($mailer->Timeout, 1000);
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\TestCase;
|
||||
|
||||
/**
|
||||
* Test encoding a string using Q encoding functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::encodeQ
|
||||
*/
|
||||
final class EncodeQTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test encoding a string using Q encoding.
|
||||
*
|
||||
* @dataProvider dataEncodeQ
|
||||
*
|
||||
* @param string $input The text to encode.
|
||||
* @param string $expected The expected function return value.
|
||||
* @param string $position Optional. Input for the position parameter.
|
||||
* @param string $charset Optional. The charset to use.
|
||||
*/
|
||||
public function testEncodeQ($input, $expected, $position = null, $charset = null)
|
||||
{
|
||||
if (isset($charset)) {
|
||||
$this->Mail->CharSet = $charset;
|
||||
}
|
||||
|
||||
if (isset($position)) {
|
||||
$result = $this->Mail->encodeQ($input, $position);
|
||||
} else {
|
||||
$result = $this->Mail->encodeQ($input);
|
||||
}
|
||||
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataEncodeQ()
|
||||
{
|
||||
return [
|
||||
'Encode for text; char encoding default (iso88591)' => [
|
||||
'input' => "\xa1Hola! Se\xf1or!",
|
||||
'expected' => '=A1Hola!_Se=F1or!',
|
||||
'position' => 'text',
|
||||
],
|
||||
'Encode for TEXT (uppercase); char encoding default (iso88591)' => [
|
||||
'input' => "\xa1Hola! Se\xf1or!",
|
||||
'expected' => '=A1Hola!_Se=F1or!',
|
||||
'position' => 'TEXT',
|
||||
],
|
||||
'Encode for comment; char encoding default (iso88591)' => [
|
||||
'input' => "\xa1Hola! Se\xf1or!",
|
||||
'expected' => '=A1Hola!_Se=F1or!',
|
||||
'position' => 'comment',
|
||||
],
|
||||
'Encode for Phrase (mixed case); char encoding default (iso88591)' => [
|
||||
'input' => "\xa1Hola! Se\xf1or!",
|
||||
'expected' => '=A1Hola!_Se=F1or!',
|
||||
'position' => 'Phrase',
|
||||
],
|
||||
'Encode for text; char encoding explicit: utf-8' => [
|
||||
'input' => "\xc2\xa1Hola! Se\xc3\xb1or!",
|
||||
'expected' => '=C2=A1Hola!_Se=C3=B1or!',
|
||||
'position' => 'text',
|
||||
'charset' => PHPMailer::CHARSET_UTF8,
|
||||
],
|
||||
'Encode for text; char encoding explicit: utf-8; string contains "=" character' => [
|
||||
'input' => "Nov\xc3\xa1=",
|
||||
'expected' => 'Nov=C3=A1=3D',
|
||||
'position' => 'text',
|
||||
'charset' => PHPMailer::CHARSET_UTF8,
|
||||
],
|
||||
'Encode for text; char encoding default (iso88591); string containing new lines' => [
|
||||
'input' => "\xa1Hola!\r\nSe\xf1or!\r\n",
|
||||
'expected' => '=A1Hola!Se=F1or!',
|
||||
'position' => 'text',
|
||||
],
|
||||
'Encode for text; char encoding explicit: utf-8; phrase vs text regex (text)' => [
|
||||
'input' => "Hello?\xbdWorld\x5e\xa9",
|
||||
'expected' => 'Hello=3F=BDWorld^=A9',
|
||||
'position' => 'text',
|
||||
'charset' => PHPMailer::CHARSET_UTF8,
|
||||
],
|
||||
'Encode for phrase; char encoding explicit: utf-8; phrase vs text regex (phrase)' => [
|
||||
'input' => "Hello?\xbdWorld\x5e\xa9",
|
||||
'expected' => 'Hello=3F=BDWorld=5E=A9',
|
||||
'position' => 'phrase',
|
||||
'charset' => PHPMailer::CHARSET_UTF8,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\TestCase;
|
||||
|
||||
/**
|
||||
* Test string encoding functionality.
|
||||
*/
|
||||
final class EncodeStringTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Encoding and charset tests.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::encodeString
|
||||
*
|
||||
* @dataProvider dataEncodeString
|
||||
*
|
||||
* @param string $input Text to encode.
|
||||
* @param string $expected Expected function return value.
|
||||
* @param string $encoding Optional. Encoding to use.
|
||||
*/
|
||||
public function testEncodeString($input, $expected, $encoding = null)
|
||||
{
|
||||
if (isset($encoding)) {
|
||||
$result = $this->Mail->encodeString($input, $encoding);
|
||||
} else {
|
||||
$result = $this->Mail->encodeString($input);
|
||||
}
|
||||
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataEncodeString()
|
||||
{
|
||||
$input = 'hello';
|
||||
$LE = PHPMailer::getLE();
|
||||
$base64_expected = base64_encode($input) . $LE;
|
||||
|
||||
return [
|
||||
'Simple string; no explicit encoding (using base64 default)' => [
|
||||
'input' => $input,
|
||||
'expected' => $base64_expected,
|
||||
],
|
||||
'Simple string; base64 encoding (lowercase)' => [
|
||||
'input' => $input,
|
||||
'expected' => $base64_expected,
|
||||
'encoding' => PHPMailer::ENCODING_BASE64,
|
||||
],
|
||||
'Simple string; base64 encoding (uppercase)' => [
|
||||
'input' => $input,
|
||||
'expected' => $base64_expected,
|
||||
'encoding' => strtoupper(PHPMailer::ENCODING_BASE64),
|
||||
],
|
||||
'Simple string; 7-bit encoding' => [
|
||||
'input' => $input,
|
||||
'expected' => $input . $LE,
|
||||
'encoding' => PHPMailer::ENCODING_7BIT,
|
||||
],
|
||||
'Simple string; 8-bit encoding' => [
|
||||
'input' => $input,
|
||||
'expected' => $input . $LE,
|
||||
'encoding' => PHPMailer::ENCODING_8BIT,
|
||||
],
|
||||
'Simple string; binary encoding' => [
|
||||
'input' => $input,
|
||||
'expected' => $input,
|
||||
'encoding' => PHPMailer::ENCODING_BINARY,
|
||||
],
|
||||
'Simple string; binary encoding (mixed case)' => [
|
||||
'input' => $input,
|
||||
'expected' => $input,
|
||||
'encoding' => ucfirst(PHPMailer::ENCODING_BINARY),
|
||||
],
|
||||
'Simple string; quoted printable encoding' => [
|
||||
'input' => $input,
|
||||
'expected' => $input,
|
||||
'encoding' => PHPMailer::ENCODING_QUOTED_PRINTABLE,
|
||||
],
|
||||
'String with line breaks; 8-bit encoding' => [
|
||||
'input' => "hello\rWorld\r",
|
||||
'expected' => "hello{$LE}World{$LE}",
|
||||
'encoding' => PHPMailer::ENCODING_8BIT,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test passing an incorrect encoding.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::encodeString
|
||||
*/
|
||||
public function testInvalidEncoding()
|
||||
{
|
||||
$result = $this->Mail->encodeString('hello', 'asdfghjkl');
|
||||
self::assertSame('', $result, 'Invalid encoding should result in an empty string');
|
||||
|
||||
self::assertNotEmpty($this->Mail->ErrorInfo, 'Invalid encoding not detected');
|
||||
self::assertTrue($this->Mail->isError(), 'Error count not correctly incremented');
|
||||
self::assertSame('Unknown encoding: asdfghjkl', $this->Mail->ErrorInfo, 'Error info not correctly set');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test passing an incorrect encoding results in an exception being thrown when PHPMailer is
|
||||
* instantiated with `$exceptions = true`.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::encodeString
|
||||
*/
|
||||
public function testInvalidEncodingException()
|
||||
{
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('Unknown encoding: asdfghjkl');
|
||||
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->encodeString('hello', 'asdfghjkl');
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use ReflectionMethod;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Test file accessibility verification functionality.
|
||||
*
|
||||
* {@internal There is one test case known to be missing, which is a test
|
||||
* with a valid UNC path. If someone can figure out a way to add a test for
|
||||
* that case, that would be awesome!}
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::fileIsAccessible
|
||||
*/
|
||||
final class FileIsAccessibleTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Verify whether the "is a file accessible" check works correctly.
|
||||
*
|
||||
* @dataProvider dataFileIsAccessible
|
||||
*
|
||||
* @param string $input A relative or absolute path to a file.
|
||||
* @param bool $expected The expected function return value.
|
||||
*/
|
||||
public function testFileIsAccessible($input, $expected)
|
||||
{
|
||||
$reflMethod = new ReflectionMethod(PHPMailer::class, 'fileIsAccessible');
|
||||
$reflMethod->setAccessible(true);
|
||||
$result = $reflMethod->invoke(null, $input);
|
||||
$reflMethod->setAccessible(false);
|
||||
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataFileIsAccessible()
|
||||
{
|
||||
$fixturesPath = dirname(__DIR__) . '/Fixtures/FileIsAccessibleTest/';
|
||||
|
||||
return [
|
||||
'Valid: accessible file' => [
|
||||
'input' => $fixturesPath . 'accessible.txt',
|
||||
'expected' => true,
|
||||
],
|
||||
'Invalid: path not permitted' => [
|
||||
'input' => 'https://github.com/PHPMailer/PHPMailer/',
|
||||
'expected' => false,
|
||||
],
|
||||
'Invalid: file does not exist' => [
|
||||
'input' => $fixturesPath . 'thisfiledoesnotexist.txt',
|
||||
'expected' => false,
|
||||
],
|
||||
'Invalid: file in UNC path does not exist' => [
|
||||
'input' => '\\\\nowhere\nothing',
|
||||
'expected' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the "is a file accessible" check correctly fails when the file permission make
|
||||
* the file unreadable.
|
||||
*/
|
||||
public function testFileIsAccessibleFailsOnUnreadableFile()
|
||||
{
|
||||
if (\DIRECTORY_SEPARATOR === '\\') {
|
||||
// Windows does not respect chmod permission.
|
||||
$this->markTestSkipped('This test requires a non-Windows OS.');
|
||||
}
|
||||
|
||||
$path = dirname(__DIR__) . '/Fixtures/FileIsAccessibleTest/';
|
||||
$file = $path . 'inaccessible.txt';
|
||||
chmod($file, octdec('0'));
|
||||
|
||||
$reflMethod = new ReflectionMethod(PHPMailer::class, 'fileIsAccessible');
|
||||
$reflMethod->setAccessible(true);
|
||||
$result = $reflMethod->invoke(null, $file);
|
||||
$reflMethod->setAccessible(false);
|
||||
|
||||
// Reset to the default for git files before running assertions.
|
||||
chmod($file, octdec('644'));
|
||||
|
||||
self::assertFalse($result);
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Test file name to type functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::filenameToType
|
||||
*/
|
||||
final class FilenameToTypeTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Verify mapping a file name to a MIME type.
|
||||
*
|
||||
* @dataProvider dataFilenameToType
|
||||
*
|
||||
* @param string $filename Filename input.
|
||||
* @param string $expected Expected function output.
|
||||
*/
|
||||
public function testFilenameToType($filename, $expected)
|
||||
{
|
||||
$result = PHPMailer::filenameToType($filename);
|
||||
self::assertSame($expected, $result, 'Failed to map file name to a MIME type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataFilenameToType()
|
||||
{
|
||||
return [
|
||||
'Empty string' => [
|
||||
'filename' => '',
|
||||
'expected' => 'application/octet-stream',
|
||||
],
|
||||
'File name without query string' => [
|
||||
'filename' => 'abc.png',
|
||||
'expected' => 'image/png',
|
||||
],
|
||||
'File name with query string' => [
|
||||
'filename' => 'abc.jpg?xyz=1',
|
||||
'expected' => 'image/jpeg',
|
||||
],
|
||||
'Full path to file, linux style' => [
|
||||
'filename' => '/usr/sbin/subdir/docs.pdf',
|
||||
'expected' => 'application/pdf',
|
||||
],
|
||||
'Full path to file, windows style' => [
|
||||
'filename' => 'D:\subdir\with spaces\subdir\myapp.zip',
|
||||
'expected' => 'application/zip',
|
||||
],
|
||||
'Unknown extension, should return default MIME type' => [
|
||||
'filename' => 'abc.xyzpdq',
|
||||
'expected' => 'application/octet-stream',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\PreSendTestCase;
|
||||
|
||||
/**
|
||||
* Test unique ID generation functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::generateId
|
||||
*/
|
||||
final class GenerateIdTest extends PreSendTestCase
|
||||
{
|
||||
/**
|
||||
* Test generating a unique ID.
|
||||
*
|
||||
* To fully test the method under test, the tests should be run on the following system configurations:
|
||||
* - PHP >= 7.0 to hit `random_bytes()`;
|
||||
* - PHP < 7.0 with OpenSSL enabled to hit `openssl_random_pseudo_bytes()`;
|
||||
* - PHP < 7.0 with the OpenSSL extension disabled;
|
||||
* - PHP >= 7.0 with the OpenSSL extension disabled and the `random_bytes()` function
|
||||
* in the php.ini `disable_functions` list.
|
||||
*
|
||||
* Note: The exact text string length of result may vary due to the str_replace() in the final statement
|
||||
* of the method, but it should always be at least 32 characters long.
|
||||
*/
|
||||
public function testGenerateID()
|
||||
{
|
||||
$this->Mail->Body = 'Testing 1, 2, 3';
|
||||
$this->Mail->isHTML();
|
||||
$this->Mail->AltBody = $this->Mail->Body;
|
||||
$this->buildBody();
|
||||
$this->Mail->preSend();
|
||||
$message = $this->Mail->getSentMIMEMessage();
|
||||
|
||||
// Find the generated ID in the message.
|
||||
self::assertSame(
|
||||
1,
|
||||
preg_match(
|
||||
'`Content-Type: multipart/alternative;\s+boundary="(b[1-3]=_[A-Za-z0-9]{32,})"`',
|
||||
$message,
|
||||
$matches
|
||||
),
|
||||
'Boundary identifier header line not found in message'
|
||||
);
|
||||
|
||||
// Check that the generated ID is used in at least one boundary.
|
||||
$LE = PHPMailer::getLE();
|
||||
self::assertStringContainsString(
|
||||
$LE . '--' . $matches[1] . $LE,
|
||||
$message,
|
||||
'No boundaries using the generated ID found in message'
|
||||
);
|
||||
}
|
||||
|
||||
public function testBoundaries()
|
||||
{
|
||||
$boundaries = $this->Mail->getBoundaries();
|
||||
self::assertMatchesRegularExpression('/b[1-3]=_[A-Za-z0-9]{32,}/', $boundaries[1]);
|
||||
self::assertMatchesRegularExpression('/b[1-3]=_[A-Za-z0-9]{32,}/', $boundaries[2]);
|
||||
self::assertMatchesRegularExpression('/b[1-3]=_[A-Za-z0-9]{32,}/', $boundaries[3]);
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\Test\PreSendTestCase;
|
||||
|
||||
/**
|
||||
* Test setting and retrieving message ID.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::createHeader
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::getLastMessageID
|
||||
*/
|
||||
final class GetLastMessageIDTest extends PreSendTestCase
|
||||
{
|
||||
/**
|
||||
* Test setting and retrieving an invalid message ID.
|
||||
*
|
||||
* @dataProvider dataMessageIDInvalid
|
||||
*
|
||||
* @param string $id Custom, invalid message ID.
|
||||
*/
|
||||
public function testMessageIDInvalid($id)
|
||||
{
|
||||
$this->Mail->Body = 'Test message ID.';
|
||||
$this->Mail->MessageID = $id;
|
||||
$this->buildBody();
|
||||
$this->Mail->preSend();
|
||||
$lastid = $this->Mail->getLastMessageID();
|
||||
self::assertNotSame($id, $lastid, 'Invalid Message ID allowed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataMessageIDInvalid()
|
||||
{
|
||||
$hash = hash('sha256', 12345);
|
||||
|
||||
return [
|
||||
'Invalid: plain hash' => [$hash],
|
||||
'Invalid: missing brackets' => [$hash . '@example.com'],
|
||||
'Invalid: missing @' => ['<' . $hash . 'example.com>'],
|
||||
'Invalid: new line after bracket' => ['<' . $hash . "@example.com>\n"],
|
||||
'Invalid: no text before @' => ['<@example.com>'],
|
||||
'Invalid: no text after @' => ['<' . $hash . '@>'],
|
||||
'Invalid: no text before or after @' => ['<@>'],
|
||||
'Invalid: multiple @ signs' => ['<' . $hash . '@example@com>'],
|
||||
'Invalid: new line after end bracket' => ['<' . $hash . "@>\n"],
|
||||
'Invalid: brackets within 1' => ['<' . $hash . '<@>example.com>'],
|
||||
'Invalid: brackets within 2' => ['<<' . $hash . '@example>com>'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting and retrieving a valid, custom message ID.
|
||||
*
|
||||
* @dataProvider dataMessageIDValid
|
||||
*
|
||||
* @param string $id Custom, valid message ID.
|
||||
*/
|
||||
public function testMessageIDValid($id)
|
||||
{
|
||||
$this->Mail->Body = 'Test message ID.';
|
||||
$this->Mail->MessageID = $id;
|
||||
$this->buildBody();
|
||||
$this->Mail->preSend();
|
||||
$lastid = $this->Mail->getLastMessageID();
|
||||
self::assertSame($id, $lastid, 'Custom Message ID not used');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataMessageIDValid()
|
||||
{
|
||||
$hash = hash('sha256', 12345);
|
||||
|
||||
return [
|
||||
'hashed pre @' => ['<' . $hash . '@example.com>'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting and retrieving an empty message ID.
|
||||
*/
|
||||
public function testMessageIDEmpty()
|
||||
{
|
||||
$this->Mail->Body = 'Test message ID.';
|
||||
$this->Mail->MessageID = '';
|
||||
$this->buildBody();
|
||||
$this->Mail->preSend();
|
||||
$lastid = $this->Mail->getLastMessageID();
|
||||
self::assertMatchesRegularExpression('/^<.+@.+>$/D', $lastid, 'Invalid default Message ID');
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\PreSendTestCase;
|
||||
|
||||
/**
|
||||
* Test line length detection and handling.
|
||||
*/
|
||||
final class HasLineLongerThanMaxTest extends PreSendTestCase
|
||||
{
|
||||
/**
|
||||
* Test constructing a multipart message that contains lines that are too long for RFC compliance.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::hasLineLongerThanMax
|
||||
*/
|
||||
public function testLongBody()
|
||||
{
|
||||
$oklen = str_repeat(str_repeat('0', PHPMailer::MAX_LINE_LENGTH) . PHPMailer::getLE(), 2);
|
||||
// Use +2 to ensure line length is over limit - LE may only be 1 char.
|
||||
$badlen = str_repeat(str_repeat('1', PHPMailer::MAX_LINE_LENGTH + 2) . PHPMailer::getLE(), 2);
|
||||
|
||||
$this->Mail->Body = 'This message contains lines that are too long.' .
|
||||
PHPMailer::getLE() . $oklen . $badlen . $oklen;
|
||||
self::assertTrue(
|
||||
PHPMailer::hasLineLongerThanMax($this->Mail->Body),
|
||||
'Test content does not contain long lines!'
|
||||
);
|
||||
|
||||
$this->Mail->isHTML();
|
||||
$this->buildBody();
|
||||
$this->Mail->AltBody = $this->Mail->Body;
|
||||
$this->Mail->Encoding = '8bit';
|
||||
$this->Mail->preSend();
|
||||
$message = $this->Mail->getSentMIMEMessage();
|
||||
self::assertFalse(
|
||||
PHPMailer::hasLineLongerThanMax($message),
|
||||
'Long line not corrected (Max: ' . (PHPMailer::MAX_LINE_LENGTH + strlen(PHPMailer::getLE())) . ' chars)'
|
||||
);
|
||||
self::assertStringContainsString(
|
||||
'Content-Transfer-Encoding: quoted-printable',
|
||||
$message,
|
||||
'Long line did not cause transfer encoding switch.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test constructing a message that does NOT contain lines that are too long for RFC compliance.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::hasLineLongerThanMax
|
||||
*/
|
||||
public function testShortBody()
|
||||
{
|
||||
$oklen = str_repeat(str_repeat('0', PHPMailer::MAX_LINE_LENGTH) . PHPMailer::getLE(), 10);
|
||||
|
||||
$this->Mail->Body = 'This message does not contain lines that are too long.' .
|
||||
PHPMailer::getLE() . $oklen;
|
||||
self::assertFalse(
|
||||
PHPMailer::hasLineLongerThanMax($this->Mail->Body),
|
||||
'Test content contains long lines!'
|
||||
);
|
||||
|
||||
$this->buildBody();
|
||||
$this->Mail->Encoding = '8bit';
|
||||
$this->Mail->preSend();
|
||||
$message = $this->Mail->getSentMIMEMessage();
|
||||
self::assertFalse(PHPMailer::hasLineLongerThanMax($message), 'Long line not corrected.');
|
||||
self::assertStringNotContainsString(
|
||||
'Content-Transfer-Encoding: quoted-printable',
|
||||
$message,
|
||||
'Short line caused transfer encoding switch.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test line length detection.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::createBody
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::hasLineLongerThanMax
|
||||
*/
|
||||
public function testLineLength()
|
||||
{
|
||||
// May have been altered by earlier tests, can interfere with line break format.
|
||||
$this->Mail->isSMTP();
|
||||
$this->Mail->preSend();
|
||||
$oklen = str_repeat(str_repeat('0', PHPMailer::MAX_LINE_LENGTH) . "\r\n", 2);
|
||||
$badlen = str_repeat(str_repeat('1', PHPMailer::MAX_LINE_LENGTH + 1) . "\r\n", 2);
|
||||
self::assertTrue(PHPMailer::hasLineLongerThanMax($badlen), 'Long line not detected (only)');
|
||||
self::assertTrue(PHPMailer::hasLineLongerThanMax($oklen . $badlen), 'Long line not detected (first)');
|
||||
self::assertTrue(PHPMailer::hasLineLongerThanMax($badlen . $oklen), 'Long line not detected (last)');
|
||||
self::assertTrue(
|
||||
PHPMailer::hasLineLongerThanMax($oklen . $badlen . $oklen),
|
||||
'Long line not detected (middle)'
|
||||
);
|
||||
self::assertFalse(PHPMailer::hasLineLongerThanMax($oklen), 'Long line false positive');
|
||||
|
||||
$this->Mail->isHTML(false);
|
||||
$this->Mail->Subject .= ': Line length test';
|
||||
$this->Mail->CharSet = 'UTF-8';
|
||||
$this->Mail->Encoding = '8bit';
|
||||
$this->Mail->Body = $oklen . $badlen . $oklen . $badlen;
|
||||
$this->buildBody();
|
||||
self::assertTrue($this->Mail->preSend(), $this->Mail->ErrorInfo);
|
||||
self::assertSame('quoted-printable', $this->Mail->Encoding, 'Long line did not override transfer encoding');
|
||||
}
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\TestCase;
|
||||
|
||||
/**
|
||||
* Test HTML to text conversion functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::html2text
|
||||
*/
|
||||
final class Html2TextTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test converting an arbitrary HTML string into plain text.
|
||||
*
|
||||
* @dataProvider dataHtml2Text
|
||||
*
|
||||
* @param string $input Arbitrary string, potentially containing HTML.
|
||||
* @param string $expected The expected function return value.
|
||||
* @param string $charset Optional. Charset to use.
|
||||
*/
|
||||
public function testHtml2Text($input, $expected, $charset = null)
|
||||
{
|
||||
if (isset($charset)) {
|
||||
$this->Mail->CharSet = $charset;
|
||||
}
|
||||
|
||||
$result = $this->Mail->html2text($input);
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataHtml2Text()
|
||||
{
|
||||
return [
|
||||
'Plain text, no encoded entities, surrounded by whitespace' => [
|
||||
'input' => ' Lorem ipsum dolor sit amet, consectetur adipiscing elit. ',
|
||||
'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
],
|
||||
'Plain text with encoded entities' => [
|
||||
'input' => 'Iñtërnâtiônàlizætiøn',
|
||||
'expected' => 'Iñtërnâtiônàlizætiøn',
|
||||
'charset' => PHPMailer::CHARSET_UTF8
|
||||
],
|
||||
|
||||
'Simple HTML, including HTML comment and encoded quotes' => [
|
||||
'input' => '<p>Test paragraph.</p>'
|
||||
. '<!-- Comment -->'
|
||||
. ' <a href="#fragment">Other text with ' and "</a>',
|
||||
'expected' => 'Test paragraph. Other text with \' and "',
|
||||
],
|
||||
'Simple HTML, including self-closing tags' => [
|
||||
'input' => '<p>Test<br/>paragraph<br /><img src="file.png" alt="alt text" />.</p>',
|
||||
'expected' => 'Testparagraph.',
|
||||
],
|
||||
'Simple HTML, paragraph fusing' => [
|
||||
'input' => '<div>
|
||||
<P style="color:blue;">color is blue</P><p>size is <span style="font-size:200%;">huge</span></p>
|
||||
<p>material is wood</p>
|
||||
</div>',
|
||||
'expected' => 'color is bluesize is huge
|
||||
material is wood',
|
||||
],
|
||||
'Full HTML message with head, title, body etc' => [
|
||||
'input' => <<<EOT
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML email test</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>PHPMailer does HTML!</h1>
|
||||
<p>This is a <strong>test message</strong> written in HTML.<br>
|
||||
Go to <a href="https://github.com/PHPMailer/PHPMailer">
|
||||
https://github.com/PHPMailer/PHPMailer</a>
|
||||
for new versions of PHPMailer.</p>
|
||||
<p>Thank you!</p>
|
||||
</body>
|
||||
</html>
|
||||
EOT
|
||||
,
|
||||
// Note: be careful when updating & saving this file. The trailing space on
|
||||
// the line with "Go to " needs to be preserved!
|
||||
'expected' => <<<EOT
|
||||
PHPMailer does HTML!
|
||||
This is a test message written in HTML.
|
||||
Go to
|
||||
https://github.com/PHPMailer/PHPMailer
|
||||
for new versions of PHPMailer.
|
||||
Thank you!
|
||||
EOT
|
||||
,
|
||||
],
|
||||
// PHP bug: https://bugs.php.net/bug.php?id=78346
|
||||
'Plain text, with PHP short open echo tags' => [
|
||||
'input' => '<?= \'<?= 1 ?>\' ?>2',
|
||||
'expected' => '2',
|
||||
],
|
||||
'HTML with script tag' => [
|
||||
'input' => 'lorem<script>alert("xss")</script>ipsum',
|
||||
'expected' => 'loremipsum',
|
||||
],
|
||||
'HTML with style tag with content. uppercase HTML tags' => [
|
||||
'input' => "lorem<STYLE>* { display: 'none' }</STYLE>ipsum",
|
||||
'expected' => 'loremipsum',
|
||||
],
|
||||
'HTML with script tag nested in style tag' => [
|
||||
'input' => "lorem<style>* { display: 'none' }<script>alert('xss')</script></style>ipsum",
|
||||
'expected' => 'loremipsum',
|
||||
],
|
||||
|
||||
'Plain text which will turn into HTML script tag on decoding' => [
|
||||
'input' => 'lorem<script>alert("xss")</script>ipsum',
|
||||
'expected' => 'lorem<script>alert("xss")</script>ipsum',
|
||||
],
|
||||
'HTML with a "less than" sign in the text' => [
|
||||
'input' => '<p><span style="color: #ff0000; background-color: #000000;">Complex</span> '
|
||||
. '<span style="font-family: impact,chicago;">text <50% </span> '
|
||||
. '<a href="https://example.com/"><em>with</em></a> '
|
||||
. '<span style="font-size: 36pt;"><strong>tags</strong></span></p>',
|
||||
'expected' => 'Complex text',
|
||||
],
|
||||
'HTML with an encoded "less than" sign in the text' => [
|
||||
'input' => '<p><span style="color: #ff0000; background-color: #000000;">Complex</span> '
|
||||
. '<span style="font-family: impact,chicago;">text <50% </span> '
|
||||
. '<a href="https://example.com/"><em>with</em></a> '
|
||||
. '<span style="font-size: 36pt;"><strong>tags</strong></span></p>',
|
||||
'expected' => 'Complex text <50% with tags',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the use of the `$callback` parameter to use a custom callback function or fall back to the
|
||||
* native implementation.
|
||||
*
|
||||
* @dataProvider dataHtml2TextAdvanced
|
||||
*
|
||||
* @param string $input Arbitrary string, potentially containing HTML.
|
||||
* @param callable $callback A callback function to use.
|
||||
* @param string $expected The expected function return value.
|
||||
*/
|
||||
public function testHtml2TextAdvanced($input, $callback, $expected)
|
||||
{
|
||||
$result = $this->Mail->html2text($input, $callback);
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* Note: the callbacks used here are inherently unsafe, but that's not the point
|
||||
* of the test. The point is to make sure that the function logic correctly chooses
|
||||
* the use of the native conversion versus a provided callback function, not to test
|
||||
* that the callback does the conversion correctly.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataHtml2TextAdvanced()
|
||||
{
|
||||
return [
|
||||
'No HTML, simple (unsafe) function name callback' => [
|
||||
'input' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
'callback' => 'strip_tags',
|
||||
'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
],
|
||||
'Has HTML, simple (unsafe) closure callback' => [
|
||||
'input' => 'Lorem <div>ipsum</div> dolor sit amet<br/>,'
|
||||
. ' consectetur <script>adipiscing()</script> elit.',
|
||||
'callback' => static function ($html) {
|
||||
return strip_tags($html);
|
||||
},
|
||||
'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing() elit.',
|
||||
],
|
||||
'Has HTML, simple (unsafe) static class method callback' => [
|
||||
'input' => 'Lorem <div>ipsum</div> dolor sit amet<br/>,'
|
||||
. ' consectetur <script>adipiscing()</script> elit.',
|
||||
'callback' => [__CLASS__, 'methodBasedCallback'],
|
||||
'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing() elit.',
|
||||
],
|
||||
'Has HTML, simple (unsafe) object method callback' => [
|
||||
'input' => 'Lorem <div>ipsum</div> dolor sit amet<br/>,'
|
||||
. ' consectetur <script>adipiscing()</script> elit.',
|
||||
'callback' => [$this, 'methodBasedCallback'],
|
||||
'expected' => 'Lorem ipsum dolor sit amet, consectetur adipiscing() elit.',
|
||||
],
|
||||
'Has HTML, explicitly use internal converter (callback = true)' => [
|
||||
'input' => 'Lorem <div>ipsum</div> dolor sit amet<br/>,'
|
||||
. ' consectetur <script>adipiscing()</script> elit.',
|
||||
'callback' => true,
|
||||
'expected' => 'Lorem ipsum dolor sit amet, consectetur elit.',
|
||||
],
|
||||
'Has HTML, use internal converter due to passing invalid callback (function)' => [
|
||||
'input' => 'Lorem <div>ipsum</div> dolor sit amet<br/>,'
|
||||
. ' consectetur <script>adipiscing()</script> elit.',
|
||||
'callback' => 'functionwhichdoesnotexist',
|
||||
'expected' => 'Lorem ipsum dolor sit amet, consectetur elit.',
|
||||
],
|
||||
'Has HTML, use internal converter due to passing invalid callback (static method)' => [
|
||||
'input' => 'Lorem <div>ipsum</div> dolor sit amet<br/>,'
|
||||
. ' consectetur <script>adipiscing()</script> elit.',
|
||||
'callback' => ['claswhichdoesnotexist', 'foo'],
|
||||
'expected' => 'Lorem ipsum dolor sit amet, consectetur elit.',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplistic callback function.
|
||||
*/
|
||||
public static function methodBasedCallback($html)
|
||||
{
|
||||
return strip_tags($html);
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\Test\PreSendTestCase;
|
||||
|
||||
/**
|
||||
* Test ICal calendar events handling.
|
||||
*/
|
||||
final class ICalTest extends PreSendTestCase
|
||||
{
|
||||
/**
|
||||
* Test ICal method.
|
||||
*
|
||||
* @dataProvider dataICalMethod
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::createBody
|
||||
*
|
||||
* @param string $methodLine The Ical method line to use.
|
||||
* @param string $expected The expected method in the content type header.
|
||||
*/
|
||||
public function testICalMethod($methodLine, $expected)
|
||||
{
|
||||
$this->Mail->Subject .= ': ICal method';
|
||||
$this->Mail->Body = '<h3>ICal method test.</h3>';
|
||||
$this->Mail->AltBody = 'ICal method test.';
|
||||
$this->Mail->Ical = 'BEGIN:VCALENDAR'
|
||||
. "\r\nVERSION:2.0"
|
||||
. "\r\nPRODID:-//PHPMailer//PHPMailer Calendar Plugin 1.0//EN"
|
||||
. $methodLine
|
||||
. "\r\nCALSCALE:GREGORIAN"
|
||||
. "\r\nX-MICROSOFT-CALSCALE:GREGORIAN"
|
||||
. "\r\nBEGIN:VEVENT"
|
||||
. "\r\nUID:201909250755-42825@test"
|
||||
. "\r\nDTSTART;20190930T080000Z"
|
||||
. "\r\nSEQUENCE:2"
|
||||
. "\r\nTRANSP:OPAQUE"
|
||||
. "\r\nSTATUS:CONFIRMED"
|
||||
. "\r\nDTEND:20190930T084500Z"
|
||||
. "\r\nLOCATION:[London] London Eye"
|
||||
. "\r\nSUMMARY:Test ICal method"
|
||||
. "\r\nATTENDEE;CN=Attendee, Test;ROLE=OPT-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP="
|
||||
. "\r\n TRUE:MAILTO:attendee-test@example.com"
|
||||
. "\r\nCLASS:PUBLIC"
|
||||
. "\r\nDESCRIPTION:Some plain text"
|
||||
. "\r\nORGANIZER;CN=\"Example, Test\":MAILTO:test@example.com"
|
||||
. "\r\nDTSTAMP:20190925T075546Z"
|
||||
. "\r\nCREATED:20190925T075709Z"
|
||||
. "\r\nLAST-MODIFIED:20190925T075546Z"
|
||||
. "\r\nEND:VEVENT"
|
||||
. "\r\nEND:VCALENDAR";
|
||||
$this->buildBody();
|
||||
$this->Mail->preSend();
|
||||
|
||||
$expected = 'Content-Type: text/calendar; method=' . $expected . ';';
|
||||
|
||||
self::assertStringContainsString(
|
||||
$expected,
|
||||
$this->Mail->getSentMIMEMessage(),
|
||||
'Wrong ICal method in Content-Type header'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataICalMethod()
|
||||
{
|
||||
return [
|
||||
'Valid method: request (default)' => [
|
||||
'methodLine' => "\r\nMETHOD:REQUEST",
|
||||
'expected' => 'REQUEST',
|
||||
],
|
||||
'Valid method: publish' => [
|
||||
'methodLine' => "\r\nMETHOD:PUBLISH",
|
||||
'expected' => 'PUBLISH',
|
||||
],
|
||||
'Valid method: reply' => [
|
||||
'methodLine' => "\r\nMETHOD:REPLY",
|
||||
'expected' => 'REPLY',
|
||||
],
|
||||
'Valid method: add' => [
|
||||
'methodLine' => "\r\nMETHOD:ADD",
|
||||
'expected' => 'ADD',
|
||||
],
|
||||
'Valid method: cancel' => [
|
||||
'methodLine' => "\r\nMETHOD:CANCEL",
|
||||
'expected' => 'CANCEL',
|
||||
],
|
||||
'Valid method: refresh' => [
|
||||
'methodLine' => "\r\nMETHOD:REFRESH",
|
||||
'expected' => 'REFRESH',
|
||||
],
|
||||
'Valid method: counter' => [
|
||||
'methodLine' => "\r\nMETHOD:COUNTER",
|
||||
'expected' => 'COUNTER',
|
||||
],
|
||||
'Valid method: declinecounter' => [
|
||||
'methodLine' => "\r\nMETHOD:DECLINECOUNTER",
|
||||
'expected' => 'DECLINECOUNTER',
|
||||
],
|
||||
// Test ICal invalid method to use default (REQUEST).
|
||||
'Invalid method' => [
|
||||
'methodLine' => "\r\nMETHOD:INVALID",
|
||||
'expected' => 'REQUEST',
|
||||
],
|
||||
// Test ICal missing method to use default (REQUEST).
|
||||
'Missing method' => [
|
||||
'methodLine' => '',
|
||||
'expected' => 'REQUEST',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use ReflectionMethod;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Test path validation functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::isPermittedPath
|
||||
*/
|
||||
final class IsPermittedPathTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test whether the validation of whether a path is of a permitted type works correctly.
|
||||
*
|
||||
* @dataProvider dataIsPermittedPath
|
||||
*
|
||||
* @param string $input A relative or absolute path to a file.
|
||||
* @param bool $expected The expected function return value.
|
||||
*/
|
||||
public function testIsPermittedPath($input, $expected)
|
||||
{
|
||||
$reflMethod = new ReflectionMethod(PHPMailer::class, 'isPermittedPath');
|
||||
$reflMethod->setAccessible(true);
|
||||
$result = $reflMethod->invoke(null, $input);
|
||||
$reflMethod->setAccessible(false);
|
||||
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataIsPermittedPath()
|
||||
{
|
||||
return [
|
||||
'Valid: full, local path; Linux style, forward slashes' => [
|
||||
'input' => '/usr/sbin/subdir/docs.pdf',
|
||||
'expected' => true,
|
||||
],
|
||||
'Valid: full, local path; Windows style, backslashes' => [
|
||||
'input' => 'D:\subdir\with spaces\subdir\myapp.zip',
|
||||
'expected' => true,
|
||||
],
|
||||
'Valid: full, local path; Windows style, forward slashes' => [
|
||||
'input' => 'D:/subdir/with spaces/subdir/',
|
||||
'expected' => true,
|
||||
],
|
||||
'Valid: relative local path; forward slashes' => [
|
||||
'input' => '/etc/hostname',
|
||||
'expected' => true,
|
||||
],
|
||||
'Valid: relative local path; forward slashes, path traversal' => [
|
||||
'input' => './../../subdir/.htaccess',
|
||||
'expected' => true,
|
||||
],
|
||||
'Valid: relative local path; backslashes, path traversal' => [
|
||||
'input' => '..\subdir\\',
|
||||
'expected' => true,
|
||||
],
|
||||
'Valid: file name only' => [
|
||||
'input' => 'composer.json',
|
||||
'expected' => true,
|
||||
],
|
||||
'Valid: UNC path' => [
|
||||
'input' => '\\\\nowhere\\nothing',
|
||||
'expected' => true,
|
||||
],
|
||||
|
||||
'Invalid: phar file reference' => [
|
||||
'input' => 'phar://phar.php',
|
||||
'expected' => false,
|
||||
],
|
||||
'Invalid: external URL; protocol: https' => [
|
||||
'input' => 'https://github.com/PHPMailer/PHPMailer/',
|
||||
'expected' => false,
|
||||
],
|
||||
'Invalid: external URL; protocol: http (uppercase)' => [
|
||||
'input' => 'HTTP://github.com/PHPMailer/PHPMailer/',
|
||||
'expected' => false,
|
||||
],
|
||||
'Invalid: external URL; protocol: ssh2.sftp' => [
|
||||
'input' => 'ssh2.sftp://user:pass@attacker-controlled.example.com:22/tmp/payload.phar',
|
||||
'expected' => false,
|
||||
],
|
||||
'Invalid: external URL; protocol: x-1.cd+-' => [
|
||||
'input' => 'x-1.cd+-://example.com/test.php',
|
||||
'expected' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Test host validation functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::isValidHost
|
||||
*/
|
||||
final class IsValidHostTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test host validation when a valid host is passed.
|
||||
*
|
||||
* @dataProvider dataValidHost
|
||||
*
|
||||
* @param string $input Input text string.
|
||||
*/
|
||||
public function testValidHost($input)
|
||||
{
|
||||
self::assertTrue(PHPMailer::isValidHost($input), 'Good hostname denied');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataValidHost()
|
||||
{
|
||||
return [
|
||||
'localhost' => ['localhost'],
|
||||
'Domain alias' => ['a'],
|
||||
'Domain: lowercase' => ['example.com'],
|
||||
'Domain: uppercase' => ['EXAMPLE.COM'],
|
||||
'Domain: mixed case' => ['Example.Com'],
|
||||
'Domain: with dash' => ['my-example.com'],
|
||||
'Domain: with subdomain' => ['smtp.gmail.com'],
|
||||
'IPv4 address: 127.0.0.1' => ['127.0.0.1'],
|
||||
'IPv4 address: external' => ['27.145.58.181'],
|
||||
'Long hex address' => [trim(str_repeat('a0123456789.', 21), '.')],
|
||||
'Bracketed IPv6: localhost' => ['[::1]'],
|
||||
'Bracketed IPv6' => ['[0:1234:dc0:41:216:3eff:fe67:3e01]'],
|
||||
'Bracketed IPv6 uppercase' => ['[0:1234:DC0:41:216:3EFF:FE67:3E01]'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test host validation when an invalid host is passed.
|
||||
*
|
||||
* @dataProvider dataInvalidHost
|
||||
*
|
||||
* @param string $input Input text string.
|
||||
*/
|
||||
public function testInvalidHost($input)
|
||||
{
|
||||
self::assertFalse(PHPMailer::isValidHost($input), 'Bad hostname accepted');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataInvalidHost()
|
||||
{
|
||||
return [
|
||||
'Invalid type: null' => [null],
|
||||
'Invalid type: int' => [123],
|
||||
'Invalid type: float' => [1.5],
|
||||
'Invalid type: object' => [new \stdClass()],
|
||||
'Invalid type: array' => [[]],
|
||||
'Invalid input: empty string' => [''],
|
||||
'Invalid input: domain - empty subdomain' => ['.example.com'],
|
||||
'Invalid input: domain - with underscore' => ['my_example.com'],
|
||||
'Invalid input: IPv4, no dots' => ['127001'],
|
||||
'Invalid input: IPv4, too few groups' => ['168.0.001'],
|
||||
'Invalid input: IPv4, too many groups' => ['22.55.14.73.9'],
|
||||
'Invalid input: IPv4 address outside range' => ['999.0.0.0'],
|
||||
'Invalid input: hex address, wrong size' => [trim(str_repeat('a0123456789.', 22), '.')],
|
||||
'Invalid input: bracketed, not IPv6 (num)' => ['[1234]'],
|
||||
'Invalid input: bracketed, not IPv6 (hex)' => ['[abCDef]'],
|
||||
'Invalid input: bracketed, triple :' => ['[1234:::1]'],
|
||||
'Invalid input: IPv6 empty brackets' => ['[]'],
|
||||
'Invalid input: IPv6 without brackets' => ['0:1234:dc0:41:216:3eff:fe67:3e01'],
|
||||
'Invalid input: IPv6 too few groups' => ['[0:1234:dc0:41]'],
|
||||
'Invalid input: IPv6 too many groups' => ['[012q:1234:dc0:41:216:3eff:fe67:3e01:6fa5]'],
|
||||
'Invalid input: IPv6 non-hex char' => ['[012q:1234:dc0:41:216:3eff:fe67:3e01]'],
|
||||
'Invalid input: IPv6 disallowed chars' => ['[0:12_4:dc$:41:216:3e+f:fe67:3e01]'],
|
||||
'Invalid input: IPv6 double bracketed' => ['[[::1]]'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,480 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use ReflectionMethod;
|
||||
use PHPMailer\Test\TestCase;
|
||||
|
||||
/**
|
||||
* Test localized error message functionality.
|
||||
*
|
||||
* {@internal In a number of tests unassigned language codes are being used
|
||||
* on purpose so as not to conflict with translations which will potentially be
|
||||
* added in the future.
|
||||
* If at any point in the future, these code would be _assigned_, the tests should
|
||||
* be updated to use some other, as yet unassigned language code.}
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::getTranslations
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::lang
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::setLanguage
|
||||
*/
|
||||
final class LocalizationTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test setting the preferred language for error messages.
|
||||
*
|
||||
* @dataProvider dataSetLanguageSuccess
|
||||
*
|
||||
* @param string $phrase The "empty_message" phrase in the expected language for verification.
|
||||
* @param string $langCode Optional. Language code.
|
||||
* @param string $langPath Optional. Path to the language file directory.
|
||||
*/
|
||||
public function testSetLanguageSuccess($phrase, $langCode = null, $langPath = null)
|
||||
{
|
||||
if (isset($langCode, $langPath)) {
|
||||
$result = $this->Mail->setLanguage($langCode, $langPath);
|
||||
} elseif (isset($langCode)) {
|
||||
$result = $this->Mail->setLanguage($langCode);
|
||||
} else {
|
||||
$result = $this->Mail->setLanguage();
|
||||
}
|
||||
|
||||
$lang = $this->Mail->getTranslations();
|
||||
|
||||
self::assertTrue(
|
||||
$result,
|
||||
'Setting the language failed. Translations set to: ' . var_export($lang, true)
|
||||
);
|
||||
|
||||
self::assertIsArray($lang, 'Translations is not an array');
|
||||
self::assertArrayHasKey('empty_message', $lang, 'The "empty_message" key is unavailable');
|
||||
self::assertSame($phrase, $lang['empty_message'], 'The "empty_message" translation is not as expected');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataSetLanguageSuccess()
|
||||
{
|
||||
$customPath = dirname(__DIR__) . '/Fixtures/LocalizationTest/';
|
||||
|
||||
return [
|
||||
'Default language (en)' => [
|
||||
'phrase' => 'Message body empty',
|
||||
],
|
||||
'Renamed language (dk => da)' => [
|
||||
'phrase' => 'Meddelelsen er uden indhold',
|
||||
'langCode' => 'dk',
|
||||
],
|
||||
'Available language: "nl"' => [
|
||||
'phrase' => 'Berichttekst is leeg',
|
||||
'langCode' => 'nl',
|
||||
],
|
||||
'Available language: "NL" (uppercase)' => [
|
||||
'phrase' => 'Berichttekst is leeg',
|
||||
'langCode' => 'NL',
|
||||
],
|
||||
'Available language: "pt_br"' => [
|
||||
'phrase' => 'Mensagem vazia',
|
||||
'langCode' => 'pt_br',
|
||||
],
|
||||
'Available language: "Zh_Cn" (mixed case)' => [
|
||||
'phrase' => '邮件正文为空。',
|
||||
'langCode' => 'Zh_Cn',
|
||||
],
|
||||
'Available language: "sr_latn"' => [
|
||||
'phrase' => 'Sadržaj poruke je prazan.',
|
||||
'langCode' => 'sr_latn',
|
||||
],
|
||||
'Custom path: available language with code in "lang-script-country" format' => [
|
||||
'phrase' => 'XA Lang-script-country file found',
|
||||
'langCode' => 'xa_scri_cc',
|
||||
'langPath' => $customPath,
|
||||
],
|
||||
'Custom path: available language: "nl" (single quoted translation text)' => [
|
||||
'phrase' => 'Custom path test success (nl)',
|
||||
'langCode' => 'nl',
|
||||
'langPath' => $customPath,
|
||||
],
|
||||
'Custom path: available language: "fr" (double quoted translation text)' => [
|
||||
'phrase' => 'Custom path test success (fr)',
|
||||
'langCode' => 'fr',
|
||||
'langPath' => $customPath,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the fall-back logic for when a more specific language code is passed, for which a translation
|
||||
* doesn't exist, while a translation for a related ("parent") language code does exist.
|
||||
*
|
||||
* {@internal This test re-uses the logic of the success test, but having it as a separate test
|
||||
* allows for the test to report under its own name, making the test results more descriptive.}
|
||||
*
|
||||
* @dataProvider dataSetLanguageSuccessFallBackLogic
|
||||
*
|
||||
* @param string $phrase The "empty_message" phrase in the expected language for verification.
|
||||
* @param string $langCode Optional. Language code.
|
||||
* @param string $langPath Optional. Path to the language file directory.
|
||||
*/
|
||||
public function testSetLanguageSuccessFallBackLogic($phrase, $langCode = null, $langPath = null)
|
||||
{
|
||||
$this->testSetLanguageSuccess($phrase, $langCode, $langPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataSetLanguageSuccessFallBackLogic()
|
||||
{
|
||||
$customPath = dirname(__DIR__) . '/Fixtures/LocalizationTest/';
|
||||
|
||||
return [
|
||||
'Request: "lang-script-country" (not available), receive "lang-script"' => [
|
||||
'phrase' => 'XB Lang-script file found',
|
||||
'langCode' => 'xb_scri_cc',
|
||||
'langPath' => $customPath,
|
||||
],
|
||||
'Request: "lang-script-country" (not available), receive "lang-country"' => [
|
||||
'phrase' => 'XC Lang-country file found',
|
||||
'langCode' => 'xc_scri_cc',
|
||||
'langPath' => $customPath,
|
||||
],
|
||||
'Request: "lang-script-country" (not available), receive "lang-country" (prefer country over script)' => [
|
||||
'phrase' => 'XD Lang-country file found',
|
||||
'langCode' => 'xd_scri_cc',
|
||||
'langPath' => $customPath,
|
||||
],
|
||||
'Request: "lang-script-country" (not available), receive "lang" (no country or script available)' => [
|
||||
'phrase' => 'XE Lang file found',
|
||||
'langCode' => 'xe_scri_cc',
|
||||
'langPath' => $customPath,
|
||||
],
|
||||
|
||||
'Request: "lang-script" (not available), receive "lang" even when "lang_country" exists' => [
|
||||
'phrase' => '郵件內容為空',
|
||||
'langCode' => 'zh_Hant',
|
||||
],
|
||||
'Request: "lang-script" (not available), receive "lang" (no country or script available)' => [
|
||||
'phrase' => 'Corps du message vide.',
|
||||
'langCode' => 'fr_latn',
|
||||
],
|
||||
|
||||
'Request: "lang-country" (not available), receive "lang" even when "lang_script" exists' => [
|
||||
'phrase' => 'Садржај поруке је празан.',
|
||||
'langCode' => 'sr_rs',
|
||||
],
|
||||
'Request: "lang-country" (not available), receive "lang" (no country or script available)' => [
|
||||
'phrase' => 'Berichttekst is leeg',
|
||||
'langCode' => 'nl_NL',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that setting the preferred language for error messages fails when the language file
|
||||
* could not be found/is inaccessible.
|
||||
*
|
||||
* @dataProvider dataSetLanguageFail
|
||||
*
|
||||
* @param string $langCode Optional. Language code.
|
||||
* @param string $langPath Optional. Path to the language file directory.
|
||||
*/
|
||||
public function testSetLanguageFail($langCode = null, $langPath = null)
|
||||
{
|
||||
if (isset($langCode, $langPath)) {
|
||||
$result = $this->Mail->setLanguage($langCode, $langPath);
|
||||
} elseif (isset($langCode)) {
|
||||
$result = $this->Mail->setLanguage($langCode);
|
||||
} else {
|
||||
$result = $this->Mail->setLanguage();
|
||||
}
|
||||
|
||||
$lang = $this->Mail->getTranslations();
|
||||
|
||||
self::assertFalse(
|
||||
$result,
|
||||
'Setting the language did not fail. Translations set to: ' . var_export($lang, true)
|
||||
);
|
||||
|
||||
// Verify that the translations have still be set (in English).
|
||||
self::assertIsArray($lang, 'Translations is not an array');
|
||||
self::assertArrayHasKey('empty_message', $lang, 'The "empty_message" key is unavailable');
|
||||
self::assertSame(
|
||||
'Message body empty',
|
||||
$lang['empty_message'],
|
||||
'The "empty_message" translation is not as expected'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataSetLanguageFail()
|
||||
{
|
||||
$customPath = dirname(__DIR__) . '/Fixtures/LocalizationTest/';
|
||||
|
||||
return [
|
||||
'Unavailable language (Quechuan), fall back to default (en)' => [
|
||||
'langCode' => 'qu',
|
||||
],
|
||||
'Unavailable Language-country code (is_IS), unavailable lang code (is), fall back to default (en)' => [
|
||||
'langCode' => 'is_IS',
|
||||
],
|
||||
'Unavailable Language-script code (pa_Arab), unavailable lang code (pa), fall back to default (en)' => [
|
||||
'langCode' => 'pa_Arab',
|
||||
],
|
||||
'Invalid lang-country-script order (sr_rs_latin), fall back to default (en)' => [
|
||||
'phrase' => 'Садржај поруке је празан.',
|
||||
'langCode' => 'sr_rs_latin',
|
||||
],
|
||||
'Available language-country code, but using dash (pt-br): fall back to default (en)' => [
|
||||
'langCode' => 'pt-br',
|
||||
],
|
||||
/*
|
||||
* Note: The first two letters of this three letter language code should match an existing
|
||||
* language file for this test to test this properly.
|
||||
*/
|
||||
'Invalid language code (ISO 639-2 "hrv"): fallback to default (en)' => [
|
||||
'phrase' => 'Message body empty',
|
||||
'langCode' => 'hrv',
|
||||
],
|
||||
'Custom path: unavailable language (Quechuan)' => [
|
||||
'langCode' => 'qu',
|
||||
'langPath' => $customPath,
|
||||
],
|
||||
'Custom path: not a local/permitted path' => [
|
||||
'langCode' => 'xx', // Unassigned lang code.
|
||||
'langPath' => 'https://example.com/files/',
|
||||
],
|
||||
'Custom path: path traversal' => [
|
||||
'langCode' => 'xx', // Unassigned lang code.
|
||||
'langPath' => './../../composer.json?',
|
||||
],
|
||||
'Custom path: missing trailing slash, file exists but should not be loaded' => [
|
||||
'langCode' => 'xx', // Unassigned lang code.
|
||||
'langPath' => dirname(__DIR__) . '/Fixtures/LocalizationTest',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that arbitrary code in a language file does not get executed.
|
||||
*/
|
||||
public function testSetLanguageDoesNotExecuteCodeInLangFile()
|
||||
{
|
||||
$result = $this->Mail->setLanguage(
|
||||
'yy', // Unassigned lang code.
|
||||
dirname(__DIR__) . '/Fixtures/LocalizationTest/'
|
||||
);
|
||||
$lang = $this->Mail->getTranslations();
|
||||
|
||||
self::assertTrue($result, 'Setting the language failed. Translations set to: ' . var_export($lang, true));
|
||||
self::assertIsArray($lang, 'Translations is not an array');
|
||||
|
||||
// Verify that the fixture file was loaded.
|
||||
self::assertArrayHasKey('extension_missing', $lang, 'The "extension_missing" translation key was not found');
|
||||
self::assertSame(
|
||||
'Confirming that test fixture was loaded correctly (yy).',
|
||||
$lang['extension_missing'],
|
||||
'The "extension_missing" translation is not as expected'
|
||||
);
|
||||
|
||||
// Verify that arbitrary code in a translation file does not get processed.
|
||||
self::assertArrayHasKey('empty_message', $lang, 'The "empty_message" translation key was not found');
|
||||
self::assertSame(
|
||||
'Message body empty',
|
||||
$lang['empty_message'],
|
||||
'The "empty_message" translation is not as expected'
|
||||
);
|
||||
|
||||
self::assertArrayHasKey('encoding', $lang, 'The "encoding" translation key was not found');
|
||||
self::assertSame(
|
||||
'Unknown encoding: ',
|
||||
$lang['encoding'],
|
||||
'The "encoding" translation is not as expected'
|
||||
);
|
||||
|
||||
self::assertArrayHasKey('execute', $lang, 'The "execute" translation key was not found');
|
||||
self::assertSame(
|
||||
'Could not execute: ',
|
||||
$lang['execute'],
|
||||
'The "execute" translation is not as expected'
|
||||
);
|
||||
|
||||
self::assertArrayHasKey('signing', $lang, 'The "signing" translation key was not found');
|
||||
self::assertSame(
|
||||
'Double quoted but not interpolated $composer',
|
||||
$lang['signing'],
|
||||
'The "signing" translation is not as expected'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that text strings passed in from a language file for arbitrary keys do not get processed.
|
||||
*/
|
||||
public function testSetLanguageOnlyProcessesKnownKeys()
|
||||
{
|
||||
$result = $this->Mail->setLanguage(
|
||||
'zz', // Unassigned lang code.
|
||||
dirname(__DIR__) . '/Fixtures/LocalizationTest/'
|
||||
);
|
||||
$lang = $this->Mail->getTranslations();
|
||||
|
||||
self::assertTrue($result, 'Setting the language failed. Translations set to: ' . var_export($lang, true));
|
||||
self::assertIsArray($lang, 'Translations is not an array');
|
||||
|
||||
// Verify that the fixture file was loaded.
|
||||
self::assertArrayHasKey('extension_missing', $lang, 'The "extension_missing" translation key was not found');
|
||||
self::assertSame(
|
||||
'Confirming that test fixture was loaded correctly (zz).',
|
||||
$lang['extension_missing'],
|
||||
'The "extension_missing" translation is not as expected'
|
||||
);
|
||||
|
||||
// Verify that unknown translation keys do not get processed.
|
||||
self::assertArrayNotHasKey('unknown', $lang, 'The "unknown" key was found');
|
||||
self::assertNotContains(
|
||||
'Unknown text.',
|
||||
$lang,
|
||||
'The text for the "unknown" key was found in the array'
|
||||
);
|
||||
|
||||
self::assertArrayNotHasKey('invalid', $lang, 'The "invalid" key was found');
|
||||
self::assertNotContains(
|
||||
'Invalid text.',
|
||||
$lang,
|
||||
'The text for the "invalid" key was found in the array'
|
||||
);
|
||||
|
||||
// Verify that known translation keys which do not match the expected case do not get processed.
|
||||
self::assertNotContains(
|
||||
'Overruled text, index not same case',
|
||||
$lang,
|
||||
'Non-exact key matches were processed anyway'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test retrieving the applicable language strings.
|
||||
*
|
||||
* @dataProvider dataGetTranslations
|
||||
*
|
||||
* @param string $langCode Optional. The language to set.
|
||||
*/
|
||||
public function testGetTranslations($langCode = null)
|
||||
{
|
||||
if (isset($langCode)) {
|
||||
$this->Mail->setLanguage($langCode);
|
||||
}
|
||||
|
||||
$result = $this->Mail->getTranslations();
|
||||
self::assertIsArray($result);
|
||||
self::assertNotCount(0, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataGetTranslations()
|
||||
{
|
||||
return [
|
||||
'No explicit language set' => [
|
||||
'langCode' => null,
|
||||
],
|
||||
'Language explicitly set' => [
|
||||
'langCode' => 'es',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test retrieving a - potentially localized - text string.
|
||||
*
|
||||
* @dataProvider dataLang
|
||||
*
|
||||
* @param string $input Text string identifier key.
|
||||
* @param string $expected Expected function return value.
|
||||
* @param string $langCode Optional. The language to retrieve the text in.
|
||||
*/
|
||||
public function testLang($input, $expected, $langCode = null)
|
||||
{
|
||||
if (isset($langCode)) {
|
||||
$this->Mail->setLanguage($langCode);
|
||||
}
|
||||
|
||||
$reflMethod = new ReflectionMethod($this->Mail, 'lang');
|
||||
$reflMethod->setAccessible(true);
|
||||
$result = $reflMethod->invoke($this->Mail, $input);
|
||||
$reflMethod->setAccessible(false);
|
||||
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataLang()
|
||||
{
|
||||
return [
|
||||
'Key: "invalid_address", default language (en)' => [
|
||||
'input' => 'invalid_address',
|
||||
'expected' => 'Invalid address: ',
|
||||
],
|
||||
'Key: "provide_address", explicit language: en' => [
|
||||
'input' => 'provide_address',
|
||||
'expected' => 'You must provide at least one recipient email address.',
|
||||
'langCode' => 'en',
|
||||
],
|
||||
'Key: "encoding", explicit language: nl' => [
|
||||
'input' => 'encoding',
|
||||
'expected' => 'Onbekende codering: ',
|
||||
'langCode' => 'nl',
|
||||
],
|
||||
'Key: "mailer_not_supported", explicit language: ja' => [
|
||||
'input' => 'mailer_not_supported',
|
||||
'expected' => ' メーラーがサポートされていません。',
|
||||
'langCode' => 'ja',
|
||||
],
|
||||
'Key: "smtp_connect_failed", default language (en)' => [
|
||||
'input' => 'smtp_connect_failed',
|
||||
'expected' => 'SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting',
|
||||
],
|
||||
'Key: "smtp_connect_failed", explicit language: es' => [
|
||||
'input' => 'smtp_connect_failed',
|
||||
'expected' => 'SMTP Connect() falló. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting',
|
||||
'langCode' => 'es',
|
||||
],
|
||||
'Non-existent key returns key, default language (en)' => [
|
||||
'input' => 'notasupportedkey',
|
||||
'expected' => 'notasupportedkey',
|
||||
],
|
||||
'Non-existent key returns key, explicit language: es' => [
|
||||
'input' => 'notasupportedkey',
|
||||
'expected' => 'notasupportedkey',
|
||||
'langCode' => 'es',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\Test\SendTestCase;
|
||||
|
||||
/**
|
||||
* Test sending mail using the various available mail transport options.
|
||||
*/
|
||||
final class MailTransportTest extends SendTestCase
|
||||
{
|
||||
/**
|
||||
* Test sending using SendMail.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::isSendmail
|
||||
*/
|
||||
public function testSendmailSend()
|
||||
{
|
||||
$this->Mail->Body = 'Sending via sendmail';
|
||||
$this->buildBody();
|
||||
$subject = $this->Mail->Subject;
|
||||
|
||||
$this->Mail->Subject = $subject . ': sendmail';
|
||||
$this->Mail->isSendmail();
|
||||
|
||||
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sending using Qmail.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::isQmail
|
||||
*/
|
||||
public function testQmailSend()
|
||||
{
|
||||
// Only run if we have qmail installed.
|
||||
if (file_exists('/var/qmail/bin/qmail-inject') === false) {
|
||||
self::markTestSkipped('Qmail is not installed');
|
||||
}
|
||||
|
||||
$this->Mail->Body = 'Sending via qmail';
|
||||
$this->buildBody();
|
||||
$subject = $this->Mail->Subject;
|
||||
|
||||
$this->Mail->Subject = $subject . ': qmail';
|
||||
$this->Mail->isQmail();
|
||||
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sending using PHP mail() function.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::isMail
|
||||
*/
|
||||
public function testMailSend()
|
||||
{
|
||||
$sendmail = ini_get('sendmail_path');
|
||||
// No path in sendmail_path.
|
||||
if (strpos($sendmail, '/') === false) {
|
||||
ini_set('sendmail_path', '/usr/sbin/sendmail -t -i ');
|
||||
}
|
||||
|
||||
$this->Mail->Body = 'Sending via mail()';
|
||||
$this->buildBody();
|
||||
$this->Mail->Subject = $this->Mail->Subject . ': mail()';
|
||||
$this->Mail->clearAddresses();
|
||||
$this->Mail->clearCCs();
|
||||
$this->Mail->clearBCCs();
|
||||
$this->setAddress('testmailsend@example.com', 'totest');
|
||||
$this->setAddress('cctestmailsend@example.com', 'cctest', $sType = 'cc');
|
||||
$this->setAddress('bcctestmailsend@example.com', 'bcctest', $sType = 'bcc');
|
||||
|
||||
self::assertContains('testmailsend@example.com', $this->Mail->getToAddresses()[0], 'To address not found');
|
||||
self::assertContains('cctestmailsend@example.com', $this->Mail->getCcAddresses()[0], 'CC address not found');
|
||||
self::assertContains('bcctestmailsend@example.com', $this->Mail->getBccAddresses()[0], 'BCC address not found');
|
||||
|
||||
self::assertTrue(
|
||||
$this->Mail->getAllRecipientAddresses()['testmailsend@example.com'],
|
||||
'To address not in recipient addresses'
|
||||
);
|
||||
self::assertTrue(
|
||||
$this->Mail->getAllRecipientAddresses()['cctestmailsend@example.com'],
|
||||
'CC address not in recipient addresses'
|
||||
);
|
||||
self::assertTrue(
|
||||
$this->Mail->getAllRecipientAddresses()['bcctestmailsend@example.com'],
|
||||
'BCC address not in recipient addresses'
|
||||
);
|
||||
|
||||
$this->Mail->createHeader();
|
||||
$this->Mail->isMail();
|
||||
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
|
||||
|
||||
$msg = $this->Mail->getSentMIMEMessage();
|
||||
self::assertStringNotContainsString("\r\n\r\nMIME-Version:", $msg, 'Incorrect MIME headers');
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Test Multi-byte-safe pathinfo replacement functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::mb_pathinfo
|
||||
*/
|
||||
final class MbPathinfoTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Verify retrieving information about a file path when the $options parameter has been passed.
|
||||
*
|
||||
* @dataProvider dataMb_pathinfoWithoutOptions
|
||||
*
|
||||
* @param string $path Path input.
|
||||
* @param string $expected Expected function output.
|
||||
*/
|
||||
public function testMb_pathinfoWithoutOptions($path, $expected)
|
||||
{
|
||||
$result = PHPMailer::mb_pathinfo($path);
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataMb_pathinfoWithoutOptions()
|
||||
{
|
||||
return [
|
||||
'Empty string' => [
|
||||
'path' => '',
|
||||
'expected' => [
|
||||
'dirname' => '',
|
||||
'basename' => '',
|
||||
'extension' => '',
|
||||
'filename' => '',
|
||||
],
|
||||
],
|
||||
'Unix path with singlebyte filename' => [
|
||||
'path' => '/mnt/music/music.mp3',
|
||||
'expected' => [
|
||||
'dirname' => '/mnt/music',
|
||||
'basename' => 'music.mp3',
|
||||
'extension' => 'mp3',
|
||||
'filename' => 'music',
|
||||
],
|
||||
],
|
||||
'Windows path with singlebyte filename' => [
|
||||
'path' => 'c:\mnt\music\music.mp3',
|
||||
'expected' => [
|
||||
'dirname' => 'c:\mnt\music',
|
||||
'basename' => 'music.mp3',
|
||||
'extension' => 'mp3',
|
||||
'filename' => 'music',
|
||||
],
|
||||
],
|
||||
'Unix path with multibyte filename' => [
|
||||
'path' => '/mnt/files/飛兒樂 團光茫.mp3',
|
||||
'expected' => [
|
||||
'dirname' => '/mnt/files',
|
||||
'basename' => '飛兒樂 團光茫.mp3',
|
||||
'extension' => 'mp3',
|
||||
'filename' => '飛兒樂 團光茫',
|
||||
],
|
||||
],
|
||||
'Windows path with multibyte filename' => [
|
||||
'path' => 'c:\mnt\files\飛兒樂 團光茫.mp3',
|
||||
'expected' => [
|
||||
'dirname' => 'c:\mnt\files',
|
||||
'basename' => '飛兒樂 團光茫.mp3',
|
||||
'extension' => 'mp3',
|
||||
'filename' => '飛兒樂 團光茫',
|
||||
],
|
||||
],
|
||||
'Filename, not path, contains spaces' => [
|
||||
'path' => 'my file.png',
|
||||
'expected' => [
|
||||
'dirname' => '',
|
||||
'basename' => 'my file.png',
|
||||
'extension' => 'png',
|
||||
'filename' => 'my file',
|
||||
],
|
||||
],
|
||||
'Path, no file name, linux style, contains spaces' => [
|
||||
'path' => '/mnt/sub directory/another sub/',
|
||||
'expected' => [
|
||||
'dirname' => '/mnt/sub directory',
|
||||
'basename' => 'another sub',
|
||||
'extension' => '',
|
||||
'filename' => 'another sub',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify retrieving information about a file path when the $options parameter has been passed.
|
||||
*
|
||||
* @dataProvider dataMb_pathinfoWithOptions
|
||||
*
|
||||
* @param int|string $options Input to pass to the $options parameter.
|
||||
* @param string $expected Expected function output.
|
||||
*/
|
||||
public function testMb_pathinfoWithOptions($options, $expected)
|
||||
{
|
||||
$path = '/mnt/files/飛兒樂 團光茫.mp3';
|
||||
$result = PHPMailer::mb_pathinfo($path, $options);
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataMb_pathinfoWithOptions()
|
||||
{
|
||||
return [
|
||||
'Option: PATHINFO_DIRNAME' => [
|
||||
'options' => PATHINFO_DIRNAME,
|
||||
'expected' => '/mnt/files',
|
||||
],
|
||||
'Option: PATHINFO_BASENAME' => [
|
||||
'options' => PATHINFO_BASENAME,
|
||||
'expected' => '飛兒樂 團光茫.mp3',
|
||||
],
|
||||
'Option: PATHINFO_EXTENSION' => [
|
||||
'options' => PATHINFO_EXTENSION,
|
||||
'expected' => 'mp3',
|
||||
],
|
||||
'Option: PATHINFO_FILENAME' => [
|
||||
'options' => PATHINFO_FILENAME,
|
||||
'expected' => '飛兒樂 團光茫',
|
||||
],
|
||||
'Option: dirname' => [
|
||||
'options' => 'dirname',
|
||||
'expected' => '/mnt/files',
|
||||
],
|
||||
'Option: basename' => [
|
||||
'options' => 'basename',
|
||||
'expected' => '飛兒樂 團光茫.mp3',
|
||||
],
|
||||
'Option: extension' => [
|
||||
'options' => 'extension',
|
||||
'expected' => 'mp3',
|
||||
],
|
||||
'Option: filename' => [
|
||||
'options' => 'filename',
|
||||
'expected' => '飛兒樂 團光茫',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Test mime type mapping functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::_mime_types
|
||||
*/
|
||||
final class MimeTypesTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test mime type mapping.
|
||||
*
|
||||
* @dataProvider dataMime_Types
|
||||
*
|
||||
* @param string $input Input text string.
|
||||
* @param string $expected Expected function output.
|
||||
*/
|
||||
public function testMime_Types($input, $expected)
|
||||
{
|
||||
$result = PHPMailer::_mime_types($input);
|
||||
self::assertSame($expected, $result, 'MIME TYPE lookup failed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataMime_Types()
|
||||
{
|
||||
return [
|
||||
'Extension: pdf (lowercase)' => [
|
||||
'input' => 'pdf',
|
||||
'expected' => 'application/pdf',
|
||||
],
|
||||
'Extension: PHP (uppercase)' => [
|
||||
'input' => 'PHP',
|
||||
'expected' => 'application/x-httpd-php',
|
||||
],
|
||||
'Extension: Doc (mixed case)' => [
|
||||
'input' => 'Doc',
|
||||
'expected' => 'application/msword',
|
||||
],
|
||||
'Extension which is not in the list' => [
|
||||
'input' => 'md',
|
||||
'expected' => 'application/octet-stream',
|
||||
],
|
||||
'Empty string' => [
|
||||
'input' => '',
|
||||
'expected' => 'application/octet-stream',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHPMailer - PHP email transport unit tests.
|
||||
* PHP version 5.5.
|
||||
*
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
* @author Andy Prevost
|
||||
* @copyright 2012 - 2020 Marcus Bointon
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
|
||||
*/
|
||||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\TestCase as MailerTestCase;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Test normalize line breaks functionality.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::normalizeBreaks
|
||||
*/
|
||||
final class NormalizeBreaksTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test line break normalization.
|
||||
*
|
||||
* @dataProvider dataNormalizeBreaks
|
||||
*
|
||||
* @param string $input Input text string.
|
||||
* @param string $expected Expected function output.
|
||||
* @param string $breaktype Optional. What kind of line break to use.
|
||||
*/
|
||||
public function testNormalizeBreaks($input, $expected, $breaktype = null)
|
||||
{
|
||||
$result = PHPMailer::normalizeBreaks($input, $breaktype);
|
||||
self::assertSame($expected, $result, 'Line break reformatting failed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dataNormalizeBreaks()
|
||||
{
|
||||
$LE = PHPMailer::getLE();
|
||||
$baseExpected = 'hello' . PHPMailer::CRLF . 'World' . PHPMailer::CRLF . 'Again' . PHPMailer::CRLF;
|
||||
|
||||
return [
|
||||
'Text without line breaks' => [
|
||||
'input' => 'hello World!',
|
||||
'expected' => 'hello World!',
|
||||
],
|
||||
'Unix line breaks' => [
|
||||
'input' => "hello\nWorld\nAgain\n",
|
||||
'expected' => $baseExpected,
|
||||
],
|
||||
'Mac line breaks' => [
|
||||
'input' => "hello\rWorld\rAgain\r",
|
||||
'expected' => $baseExpected,
|
||||
],
|
||||
'Windows line breaks' => [
|
||||
'input' => "hello\r\nWorld\r\nAgain\r\n",
|
||||
'expected' => $baseExpected,
|
||||
],
|
||||
'Mixed line breaks' => [
|
||||
'input' => "hello\nWorld\rAgain\r\n",
|
||||
'expected' => $baseExpected,
|
||||
],
|
||||
'Mac line breaks, enforce Unix' => [
|
||||
'input' => "1\r2\r3\r",
|
||||
'expected' => "1\n2\n3\n",
|
||||
'breaktype' => "\n",
|
||||
],
|
||||
'Unix line breaks, enforce Mac' => [
|
||||
'input' => "1\n2\n3\n",
|
||||
'expected' => "1\r2\r3\r",
|
||||
'breaktype' => "\r",
|
||||
],
|
||||
'Mixed line breaks, enforce preset' => [
|
||||
'input' => "1\r\n2\r3\n",
|
||||
'expected' => "1{$LE}2{$LE}3{$LE}",
|
||||
'breaktype' => $LE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test line break normalization with a custom line ending setting.
|
||||
*/
|
||||
public function testNormalizeBreaksWithCustomLineEnding()
|
||||
{
|
||||
$input = "hello\rWorld\rAgain\r";
|
||||
$expected = "hello\n\rWorld\n\rAgain\n\r";
|
||||
|
||||
$origLE = PHPMailer::getLE();
|
||||
MailerTestCase::updateStaticProperty(PHPMailer::class, 'LE', "\n\r");
|
||||
$result = PHPMailer::normalizeBreaks($input);
|
||||
|
||||
/*
|
||||
* Reset the static property *before* the assertion to ensure the reset executes
|
||||
* even when the test would fail.
|
||||
*/
|
||||
MailerTestCase::updateStaticProperty(PHPMailer::class, 'LE', $origLE);
|
||||
|
||||
self::assertSame($expected, $result, 'Line break reformatting failed');
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user