Compare commits
202 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
ebf1655bd5 | |
|
|
b938991866 | |
|
|
7e3f24386f | |
|
|
1a0004b51b | |
|
|
a969e57c06 | |
|
|
28caa24930 | |
|
|
5f710689e5 | |
|
|
827e170f50 | |
|
|
0d4c5ee8da | |
|
|
14e1efe293 | |
|
|
dca8e03946 | |
|
|
84097ce614 | |
|
|
7ff3620f50 | |
|
|
85df414ab4 | |
|
|
d04efe78e1 | |
|
|
2b240b44e9 | |
|
|
4c06f874c9 | |
|
|
4e8292f43c | |
|
|
8d27fb6b7c | |
|
|
34b209f864 | |
|
|
31e3d491aa | |
|
|
96d82b913a | |
|
|
8ff00047a8 | |
|
|
a767d446c2 | |
|
|
b6729d7bd2 | |
|
|
360ae911ce | |
|
|
6db653f5a8 | |
|
|
2050f506c3 | |
|
|
6631e9049e | |
|
|
12494b1830 | |
|
|
381c209df1 | |
|
|
57ef8c914f | |
|
|
6dc895d1d9 | |
|
|
127dde31e2 | |
|
|
606c699536 | |
|
|
abe4691505 | |
|
|
7284079a6d | |
|
|
b9d0e242fb | |
|
|
c24a4147cd | |
|
|
19fb4e2727 | |
|
|
051b81791f | |
|
|
d34204b729 | |
|
|
cc366ae351 | |
|
|
f5cc77c68a | |
|
|
da2c9f9919 | |
|
|
5e41861a0e | |
|
|
a0a3e6a3ef | |
|
|
1645b1a7be | |
|
|
a522b78c67 | |
|
|
a0ee4a34ed | |
|
|
a39e1db862 | |
|
|
25658b754f | |
|
|
d616c7fc76 | |
|
|
15c3d21fa1 | |
|
|
b336ed18b5 | |
|
|
37d628dd22 | |
|
|
9aa8367be6 | |
|
|
4384c206d3 | |
|
|
8b7828d3b0 | |
|
|
8a06a2ddd1 | |
|
|
8f59b82488 | |
|
|
eec5710309 | |
|
|
a231b7d4c4 | |
|
|
74e7f4c72a | |
|
|
07db4a7a0f | |
|
|
6f42027abe | |
|
|
494e8d60e4 | |
|
|
ad20fe54b9 | |
|
|
d9cf457a92 | |
|
|
060cf931c3 | |
|
|
54a5a950dd | |
|
|
effe349964 | |
|
|
22b1e59f53 | |
|
|
5ef071ed30 | |
|
|
e75e5ee3e3 | |
|
|
36ea61cf21 | |
|
|
8bc8f15714 | |
|
|
c523ee67a8 | |
|
|
c7111310c6 | |
|
|
d49feed6fd | |
|
|
b17101946b | |
|
|
1cf86b0762 | |
|
|
97ccd46848 | |
|
|
86b9838806 | |
|
|
46f72568d5 | |
|
|
ad2821203f | |
|
|
54b2ab00d3 | |
|
|
73afb4a8b1 | |
|
|
c09730a7d7 | |
|
|
306ea7022f | |
|
|
0f9ebf7c3c | |
|
|
6aad52aa06 | |
|
|
7a18c0bc98 | |
|
|
9489d4c5c3 | |
|
|
2e38fff8f3 | |
|
|
9a5f46f747 | |
|
|
7251db8b19 | |
|
|
27e89fabc3 | |
|
|
c60f5ab888 | |
|
|
e8f4d86c66 | |
|
|
dc2ecee788 | |
|
|
07755f0f69 | |
|
|
512e26bffc | |
|
|
b135f4f284 | |
|
|
5acdb20adf | |
|
|
a26214d5a3 | |
|
|
0b6ed12ed3 | |
|
|
817d1e604e | |
|
|
94f8565fd0 | |
|
|
d9e3b36b47 | |
|
|
fe380a85e0 | |
|
|
29f48d454e | |
|
|
6ed58a9c60 | |
|
|
9500c37b70 | |
|
|
39a1bc905c | |
|
|
22a8dce04e | |
|
|
9b899a0f22 | |
|
|
8e8b503db9 | |
|
|
bcc4d84893 | |
|
|
b0f96abda0 | |
|
|
0d5d8854f9 | |
|
|
1191a4ef0b | |
|
|
5060f5405c | |
|
|
cae960ed2b | |
|
|
b1860a4e86 | |
|
|
f4d321633d | |
|
|
238af6720e | |
|
|
95ff455f9d | |
|
|
bda1fee442 | |
|
|
ec08e9497d | |
|
|
a49806c893 | |
|
|
759c73ef98 | |
|
|
c8fdd4178e | |
|
|
041c556075 | |
|
|
7f75a4220a | |
|
|
eef3fef3ae | |
|
|
d418826b0d | |
|
|
7e878a18f1 | |
|
|
a209299105 | |
|
|
0d6eaeb3a9 | |
|
|
80cd2d5f3a | |
|
|
1714708220 | |
|
|
5ce9b04aae | |
|
|
086dfbe727 | |
|
|
63540d8cf3 | |
|
|
6f0f7a7f68 | |
|
|
9f0387fb37 | |
|
|
6cab1544fa | |
|
|
5bc453d6c5 | |
|
|
4c917a9b46 | |
|
|
5470c1e795 | |
|
|
fd9f8d33cb | |
|
|
6a6e66abf4 | |
|
|
b1b1f65f0b | |
|
|
7e61c84718 | |
|
|
5ddea0610b | |
|
|
3c93e8d6f3 | |
|
|
e72170c6ba | |
|
|
69a2b8038f | |
|
|
0ce6905391 | |
|
|
a848a67c50 | |
|
|
22885eaf4a | |
|
|
b41dd255a2 | |
|
|
85f7f98f59 | |
|
|
f2af1cafb5 | |
|
|
34c6423ac6 | |
|
|
81eedda461 | |
|
|
d43654d445 | |
|
|
19f17f8aeb | |
|
|
fef2d5cf15 | |
|
|
f78d341f06 | |
|
|
276eb1e879 | |
|
|
855bf067fc | |
|
|
da0cffbc05 | |
|
|
71dfc112c9 | |
|
|
f1255a0a55 | |
|
|
97f4e58e18 | |
|
|
f7b82634c9 | |
|
|
99b482752e | |
|
|
d2fc22a4f1 | |
|
|
a3ddc21741 | |
|
|
bf8e97d3c8 | |
|
|
800919c6a4 | |
|
|
2f92d9c841 | |
|
|
5b970527ae | |
|
|
ca34869b2c | |
|
|
096b24646e | |
|
|
91ef7d0e54 | |
|
|
f202f351ca | |
|
|
52d0fe4916 | |
|
|
fc8c76f3be | |
|
|
0ff2d3c8ea | |
|
|
a2fa102104 | |
|
|
ffbe1ad27f | |
|
|
ce9d1b6883 | |
|
|
90cdf758c2 | |
|
|
5fc635571b | |
|
|
8ca031797f | |
|
|
912f278a48 | |
|
|
2efdf63a32 | |
|
|
da0212d7d4 | |
|
|
6ec886b292 |
|
|
@ -8,7 +8,14 @@ updates:
|
|||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
interval: "cron"
|
||||
cronjob: "10 22 5,20 * *" # At 22:10, every 5th and 20th day of the month.
|
||||
open-pull-requests-limit: 5
|
||||
commit-message:
|
||||
prefix: "GH Actions:"
|
||||
groups:
|
||||
action-runners:
|
||||
applies-to: version-updates
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
|
|
|
|||
|
|
@ -14,13 +14,14 @@ jobs:
|
|||
if: github.repository == 'PHPMailer/PHPMailer'
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
- name: Build Docs
|
||||
uses: ./.github/actions/build-docs
|
||||
- name: Publish Docs to gh-pages
|
||||
uses: JamesIves/github-pages-deploy-action@v4
|
||||
uses: JamesIves/github-pages-deploy-action@9d877eea73427180ae43cf98e8914934fe157a1a # v4.7.6
|
||||
with:
|
||||
branch: gh-pages
|
||||
folder: docs
|
||||
|
|
|
|||
|
|
@ -7,30 +7,29 @@ on:
|
|||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
# Don't run the cron job on forks.
|
||||
if: ${{ github.event_name != 'schedule' || github.event.repository.fork == false }}
|
||||
|
||||
name: Scorecards analysis
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
# Required when publishing results (badge / API / code scanning)
|
||||
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
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46
|
||||
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
|
|
@ -49,7 +48,7 @@ jobs:
|
|||
# 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
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
|
|
@ -57,6 +56,6 @@ jobs:
|
|||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ on:
|
|||
# Allow manually triggering the workflow.
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
|
||||
|
|
@ -15,12 +14,17 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
name: Coding standards
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0
|
||||
with:
|
||||
php-version: 'latest'
|
||||
coverage: none
|
||||
|
|
@ -29,7 +33,7 @@ jobs:
|
|||
# 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"
|
||||
uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # 3.1.1
|
||||
with:
|
||||
# Bust the cache at least once a month - output format: YYYY-MM.
|
||||
custom-cache-suffix: $(date -u "+%Y-%m")
|
||||
|
|
@ -46,40 +50,46 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
php: ['5.5', '7.2', '8.0', '8.4']
|
||||
php: ['5.5', '7.2', '8.0', '8.5']
|
||||
experimental: [false]
|
||||
include:
|
||||
- php: '8.5'
|
||||
- php: 'nightly'
|
||||
experimental: true
|
||||
|
||||
name: "Lint: PHP ${{ matrix.php }}"
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
ini-values: error_reporting=-1, display_errors=On, display_startup_errors=On
|
||||
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"
|
||||
uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # 3.1.1
|
||||
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' }}
|
||||
if: ${{ matrix.php != 'nightly' }}
|
||||
run: composer lint -- --checkstyle | cs2pr
|
||||
|
||||
- name: Lint against future parse errors (PHP 8.5)
|
||||
if: ${{ matrix.php == '8.5' }}
|
||||
- name: Lint against future parse errors (PHP nightly)
|
||||
if: ${{ matrix.php == 'nightly' }}
|
||||
run: composer lint
|
||||
|
||||
test:
|
||||
|
|
@ -87,7 +97,7 @@ jobs:
|
|||
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']
|
||||
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
|
||||
extensions: ['optimal', 'minimal']
|
||||
coverage: [false]
|
||||
experimental: [false]
|
||||
|
|
@ -101,21 +111,21 @@ jobs:
|
|||
extensions: 'minimal'
|
||||
coverage: true
|
||||
experimental: false
|
||||
- php: '8.4'
|
||||
- php: '8.5'
|
||||
extensions: 'optimal'
|
||||
coverage: true
|
||||
experimental: false
|
||||
- php: '8.4'
|
||||
- php: '8.5'
|
||||
extensions: 'minimal'
|
||||
coverage: true
|
||||
experimental: false
|
||||
|
||||
# Experimental builds. These are allowed to fail.
|
||||
- php: '8.5'
|
||||
- php: '8.6'
|
||||
extensions: 'optimal'
|
||||
coverage: false
|
||||
experimental: true
|
||||
- php: '8.5'
|
||||
- php: '8.6'
|
||||
extensions: 'minimal'
|
||||
coverage: false
|
||||
experimental: true
|
||||
|
|
@ -124,9 +134,14 @@ jobs:
|
|||
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
# About the "extensions":
|
||||
#
|
||||
|
|
@ -156,26 +171,26 @@ jobs:
|
|||
fi
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0
|
||||
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
|
||||
ini-values: sendmail_path=/usr/sbin/sendmail -t -i, error_reporting=-1, display_errors=On, display_startup_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"
|
||||
if: ${{ matrix.php != '8.6' }}
|
||||
uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # 3.1.1
|
||||
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"
|
||||
if: ${{ matrix.php == '8.6' }}
|
||||
uses: "ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520" # 3.1.1
|
||||
with:
|
||||
composer-options: --ignore-platform-reqs ${{ steps.set_extensions.outputs.COMPOSER_OPTIONS }}
|
||||
# Bust the cache at least once a month - output format: YYYY-MM.
|
||||
|
|
@ -184,7 +199,7 @@ jobs:
|
|||
# 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
|
||||
uses: nick-invision/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
|
||||
with:
|
||||
timeout_minutes: 2
|
||||
max_attempts: 3
|
||||
|
|
@ -212,8 +227,8 @@ jobs:
|
|||
run: vendor/bin/phpunit
|
||||
|
||||
- name: Send coverage report to Codecov
|
||||
if: ${{ success() && matrix.coverage == true }}
|
||||
uses: codecov/codecov-action@v4
|
||||
if: ${{ success() && matrix.coverage == true && github.event.repository.fork == false }}
|
||||
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
- 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.4
|
||||
- Compatible with PHP 5.5 and later, including PHP 8.5
|
||||
- Namespaced to prevent name clashes
|
||||
- Much more!
|
||||
|
||||
|
|
@ -48,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.12.0"
|
||||
"phpmailer/phpmailer": "^7.0.0"
|
||||
```
|
||||
|
||||
or run
|
||||
|
|
|
|||
26
changelog.md
26
changelog.md
|
|
@ -1,23 +1,31 @@
|
|||
# PHPMailer Change Log
|
||||
|
||||
## Version 7.0.0 (October 15th, 2025)
|
||||
## Version 7.0.2 (January 9th, 2026)
|
||||
* Fixes for sendmail parameter problems in WordPress, thanks to @SirLouen
|
||||
* Reduce memory consumption when sending large attachments by @RobinvanderVliet
|
||||
|
||||
This is exactly the same as 6.11.1 but bumps the major version number to indicate the presence of a BC break in child
|
||||
classes. Specifically, `lang()`, `setLanguage()`, and `$language` are now static, and should be called statically.
|
||||
## Version 7.0.1 (November 25th, 2025)
|
||||
* Use From domain when generating CIDs in msgHTML.
|
||||
* Update to PHPCompatibility 10, resolve numerous PHPCS issues in PHP 8.5.
|
||||
* Revise GitHub actions for PHP 8.5 and experimental 8.6 tests.
|
||||
* Switch gmail example from the deprecated IMAP extension to use `directorytree/imapengine` for IMAP uploads.
|
||||
* Set `htmlspecialchars()` flags explicitly and consistently.
|
||||
* Convert XOAUTH2 token exceptions into PHPMailer Exceptions. The original exception is available as an inner exception.
|
||||
* Deprecate VERSION constants in POP3 and SMTP classes.
|
||||
* Remove dependency on `roave/security-advisories`; it's now built into composer 2.9.
|
||||
* Update Dutch, Esperanto, and Norwegian translations.
|
||||
|
||||
## Version 7.0.0 (October 15th, 2025)
|
||||
This is exactly the same as 6.11.1 but bumps the major version number to indicate the presence of a BC break in child classes. Specifically, `lang()`, `setLanguage()`, and `$language` are now static, and should be called statically.
|
||||
|
||||
## Version 6.12.0 (October 15th, 2025)
|
||||
This is exactly the same as 6.10.0, reverting all the changes in 6.11.0 and 6.11.1, which inadvertently introduced a BC break affecting child classes. 6.11.1 has been re-released as 7.0.0.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you have code that depends on the changes that were in 6.11.0 and 6.11.1, please upgrade to 7.0.0 instead.
|
||||
|
||||
## Version 6.11.1 (September 30th, 2025)
|
||||
* Avoid function signature problems with the deprecation of `$useimap` in `parseAddresses`.
|
||||
|
||||
## Version 6.11.0 (September 29th, 2025)
|
||||
|
||||
* Add support for [RFC4954](https://www.rfc-editor.org/rfc/rfc4954#section-4) two-part authentication for large XOAUTH2
|
||||
tokens.
|
||||
* Add support for [RFC4954](https://www.rfc-editor.org/rfc/rfc4954#section-4) two-part authentication for large XOAUTH2 tokens.
|
||||
* Also support empty tokens.
|
||||
* Avoid bogus static analyser deprecation warnings in `setFrom`.
|
||||
* Make language loading entirely static, thanks to @SirLouen.
|
||||
|
|
|
|||
|
|
@ -42,22 +42,25 @@
|
|||
"doctrine/annotations": "^1.2.6 || ^1.13.3",
|
||||
"php-parallel-lint/php-console-highlighter": "^1.0.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.3.2",
|
||||
"phpcompatibility/php-compatibility": "^9.3.5",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"squizlabs/php_codesniffer": "^3.7.2",
|
||||
"phpcompatibility/php-compatibility": "^10.0.0@dev",
|
||||
"squizlabs/php_codesniffer": "^3.13.5",
|
||||
"yoast/phpunit-polyfills": "^1.0.4"
|
||||
},
|
||||
"suggest": {
|
||||
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
|
||||
"ext-imap": "Needed to support advanced email address parsing according to RFC822",
|
||||
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
|
||||
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
|
||||
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
|
||||
"hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication",
|
||||
"league/oauth2-google": "Needed for Google XOAUTH2 authentication",
|
||||
"psr/log": "For optional PSR-3 debug logging",
|
||||
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
|
||||
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication",
|
||||
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
|
||||
"directorytree/imapengine": "For uploading sent messages via IMAP, see gmail example"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PHPMailer\\PHPMailer\\": "src/"
|
||||
|
|
@ -71,6 +74,7 @@
|
|||
"license": "LGPL-2.1-only",
|
||||
"scripts": {
|
||||
"check": "./vendor/bin/phpcs",
|
||||
"style": "./vendor/bin/phpcbf",
|
||||
"test": "./vendor/bin/phpunit --no-coverage",
|
||||
"coverage": "./vendor/bin/phpunit",
|
||||
"lint": [
|
||||
|
|
|
|||
|
|
@ -83,26 +83,24 @@ if (!$mail->send()) {
|
|||
echo 'Message sent!';
|
||||
//Section 2: IMAP
|
||||
//Uncomment these to save your message in the 'Sent Mail' folder.
|
||||
#if (save_mail($mail)) {
|
||||
# echo "Message saved!";
|
||||
#}
|
||||
#save_mail($mail->getSentMIMEMessage());
|
||||
}
|
||||
|
||||
//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)
|
||||
//This example uses the directorytree/imapengine IMAP library: https://imapengine.com
|
||||
//Earlier versions of this code used the deprecated PHP imap_* functions.
|
||||
function save_mail($message)
|
||||
{
|
||||
//You can change 'Sent Mail' to any other folder or tag
|
||||
$path = '{imap.gmail.com:993/imap/ssl}[Gmail]/Sent Mail';
|
||||
$mailbox = new \DirectoryTree\ImapEngine\Mailbox([
|
||||
'host' => 'imap.gmail.com',
|
||||
'port' => 993,
|
||||
'encryption' => 'ssl',
|
||||
'username' => 'user@example.com',
|
||||
'password' => 'password',
|
||||
]);
|
||||
|
||||
//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);
|
||||
// Find the "sent" messages folder – yours may have a different name.
|
||||
$folder = $mailbox->folders()->find('Sent Mail');
|
||||
|
||||
$result = imap_append($imapStream, $path, $mail->getSentMIMEMessage());
|
||||
imap_close($imapStream);
|
||||
|
||||
return $result;
|
||||
$folder->messages()->append($message);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
error_reporting(E_STRICT | E_ALL);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
date_default_timezone_set('Etc/UTC');
|
||||
|
||||
|
|
@ -51,7 +51,10 @@ foreach ($result as $row) {
|
|||
try {
|
||||
$mail->addAddress($row['email'], $row['full_name']);
|
||||
} catch (Exception $e) {
|
||||
echo 'Invalid address skipped: ' . htmlspecialchars($row['email']) . '<br>';
|
||||
printf(
|
||||
'Invalid address skipped: %s<br>',
|
||||
htmlspecialchars($row['email'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (!empty($row['photo'])) {
|
||||
|
|
@ -66,8 +69,11 @@ foreach ($result as $row) {
|
|||
|
||||
try {
|
||||
$mail->send();
|
||||
echo 'Message sent to :' . htmlspecialchars($row['full_name']) . ' (' .
|
||||
htmlspecialchars($row['email']) . ')<br>';
|
||||
printf(
|
||||
'Message sent to : %s (%s)<br>',
|
||||
htmlspecialchars($row['full_name'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401),
|
||||
htmlspecialchars($row['email'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401)
|
||||
);
|
||||
//Mark it as sent in the DB
|
||||
mysqli_query(
|
||||
$mysql,
|
||||
|
|
@ -75,7 +81,11 @@ foreach ($result as $row) {
|
|||
mysqli_real_escape_string($mysql, $row['email']) . "'"
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
echo 'Mailer Error (' . htmlspecialchars($row['email']) . ') ' . $mail->ErrorInfo . '<br>';
|
||||
printf(
|
||||
'Mailer Error (%s) %s<br>',
|
||||
htmlspecialchars($row['email'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401),
|
||||
$mail->ErrorInfo
|
||||
);
|
||||
//Reset the connection to abort sending this message
|
||||
//The loop will continue trying to send to the rest of the list
|
||||
$mail->getSMTPInstance()->reset();
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ if (array_key_exists('userfile', $_FILES)) {
|
|||
<input type="submit" value="Send File">
|
||||
</form>
|
||||
<?php } else {
|
||||
echo htmlspecialchars($msg);
|
||||
echo htmlspecialchars($msg, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401);
|
||||
} ?>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ if (array_key_exists('userfile', $_FILES)) {
|
|||
<input type="submit" value="Send Files">
|
||||
</form>
|
||||
<?php } else {
|
||||
echo htmlspecialchars($msg);
|
||||
echo htmlspecialchars($msg, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401);
|
||||
} ?>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -178,5 +178,5 @@ if (!isset($_GET['code'])) {
|
|||
);
|
||||
//Use this to interact with an API on the users behalf
|
||||
//Use this to get a new access token if the old one expires
|
||||
echo 'Refresh Token: ', htmlspecialchars($token->getRefreshToken());
|
||||
echo 'Refresh Token: ', htmlspecialchars($token->getRefreshToken(), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,3 +34,6 @@ $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fejlede.';
|
|||
$PHPMAILER_LANG['smtp_detail'] = 'Detalje: ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'SMTP server fejl: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Kunne ikke definere eller nulstille variablen: ';
|
||||
$PHPMAILER_LANG['no_smtputf8'] = 'Serveren understøtter ikke SMTPUTF8 som påkrævet for at sende til Unicode adresser';
|
||||
$PHPMAILER_LANG['imap_recommended'] = 'Brug af forenklet adresseparser anbefales ikke. Installer PHP IMAP udvidelsen for fuld RFC822 parsing.';
|
||||
$PHPMAILER_LANG['deprecated_argument'] = 'Udfaset argument: ';
|
||||
|
|
|
|||
|
|
@ -3,24 +3,35 @@
|
|||
/**
|
||||
* Esperanto PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
* @author Robin van der Vliet <info@robinvandervliet.com>
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'Eraro de servilo SMTP : aŭtentigo malsukcesis.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Eraro de servilo SMTP : konektado al servilo malsukcesis.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Eraro de servilo SMTP : neĝustaj datumoj.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Teksto de mesaĝo mankas.';
|
||||
$PHPMAILER_LANG['authenticate'] = 'SMTP-eraro: Ne eblis aŭtentigi.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'Via versio de PHP estas trafita de cimo, kiu povas kaŭzi difektitajn mesaĝojn. Por ripari tion, ŝanĝu al sendado per SMTP, malŝaltu la opcion mail.add_x_header en via php.ini, ŝanĝu al MacOS aŭ Linux, aŭ ĝisdatigu vian PHP al versio 7.0.17+ aŭ 7.1.3+.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'SMTP-eraro: Ne eblis konektiĝi al la SMTP-gastiganto.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-eraro: Datumoj ne akceptitaj.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Mesaĝokorpo malplena';
|
||||
$PHPMAILER_LANG['encoding'] = 'Nekonata kodoprezento: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Lanĉi rulumadon ne eblis: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Aliro al dosiero ne sukcesis: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Eraro de dosiero: malfermo neeblas: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Jena adreso de sendinto malsukcesis: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Genero de retmesaĝa funkcio neeblis.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Retadreso ne validas: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' mesaĝilo ne subtenata.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Vi devas tajpi almenaŭ unu recevontan retadreson.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'Eraro de servilo SMTP : la jenaj poŝtrecivuloj kaŭzis eraron: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Eraro de subskribo: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP konektado malsukcesis.';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Eraro de servilo SMTP : ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Variablo ne pravalorizeblas aŭ ne repravalorizeblas: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Mankas etendo: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Ne eblis plenumi: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Kromprogramo mankas: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Ne eblis aliri la dosieron: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Dosiera eraro: Ne eblis malfermi la dosieron: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'La sekva(j) sendinto(j) malsukcesis: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Ne eblis funkciigi la retpoŝtan funkcion.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Nevalida adreso: ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Nevalida kaplinia nomo aŭ valoro';
|
||||
$PHPMAILER_LANG['invalid_hostentry'] = 'Nevalida enigo de gastiganto: ';
|
||||
$PHPMAILER_LANG['invalid_host'] = 'Nevalida gastiganto: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' retpoŝtilo ne estas subtenata.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Vi devas provizi almenaŭ unu retpoŝtadreson de ricevonto.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'SMTP-eraro: La sekva(j) ricevonto(j) malsukcesis: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Subskriba eraro: ';
|
||||
$PHPMAILER_LANG['smtp_code'] = 'SMTP-kodo: ';
|
||||
$PHPMAILER_LANG['smtp_code_ex'] = 'Pliaj SMTP-informoj: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'La SMTP-konektiĝo malsukcesis.';
|
||||
$PHPMAILER_LANG['smtp_detail'] = 'Informoj: ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Eraro de SMTP-servilo: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Ne eblas agordi aŭ reagordi la variablon: ';
|
||||
$PHPMAILER_LANG['no_smtputf8'] = 'La servilo ne subtenas SMTPUTF8, kiu estas bezonata por sendi al Unicode-adresoj.';
|
||||
$PHPMAILER_LANG['imap_recommended'] = 'Uzado de la simpligita adresanalizilo ne estas rekomendita. Instalu la IMAP-kromprogramon por PHP por plena RFC822-analizado.';
|
||||
$PHPMAILER_LANG['deprecated_argument'] = 'Malrekomendita argumento: ';
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'Error SMTP: Imposible autentificar.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'Tu versión de PHP está afectada por un bug que puede resultar en mensajes corruptos. Para arreglarlo, cambia a enviar usando SMTP, deshabilita la opción mail.add_x_header en tu php.ini, cambia a MacOS o Linux, o actualiza tu PHP a la versión 7.0.17+ o 7.1.3+.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'Tu versión de PHP ha sido afectada por un bug que puede resultar en mensajes corruptos. Para arreglarlo, cambia a enviar usando SMTP, deshabilita la opción mail.add_x_header en tu php.ini, cambia a MacOS o Linux, o actualiza tu PHP a la versión 7.0.17+ o 7.1.3+.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Error SMTP: Imposible conectar al servidor SMTP.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Datos no aceptados.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'El cuerpo del mensaje está vacío.';
|
||||
|
|
@ -18,7 +18,7 @@ $PHPMAILER_LANG['execute'] = 'Imposible ejecutar: ';
|
|||
$PHPMAILER_LANG['extension_missing'] = 'Extensión faltante: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Imposible acceder al archivo: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Error de Archivo: Imposible abrir el archivo: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'La(s) siguiente(s) direcciones de remitente fallaron: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'La siguiente dirección de remitente falló: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Imposible crear una instancia de la función Mail.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Imposible enviar: dirección de email inválido: ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Nombre o valor de encabezado no válido';
|
||||
|
|
@ -34,3 +34,5 @@ $PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falló.';
|
|||
$PHPMAILER_LANG['smtp_detail'] = 'Detalle: ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Error del servidor SMTP: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'No se pudo configurar la variable: ';
|
||||
$PHPMAILER_LANG['imap_recommended'] = 'No se recomienda usar el analizador de direcciones simplificado. Instala la extensión IMAP de PHP para un análisis RFC822 más completo.';
|
||||
$PHPMAILER_LANG['deprecated_argument'] = 'Argumento obsoleto: ';
|
||||
|
|
|
|||
|
|
@ -3,20 +3,21 @@
|
|||
/**
|
||||
* Norwegian Bokmål PHPMailer language file: refer to English translation for definitive list
|
||||
* @package PHPMailer
|
||||
* @author Wera AS <wordpress@wera.no>
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'SMTP-feil: Kunne ikke autentiseres.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'Din versjon av PHP er berørt av en feil som kan føre til ødelagte meldinger. For å løse problemet kan du bytte til SMTP, deaktivere alternativet mail.add_x_header i php.ini, bytte til MacOS eller Linux eller oppgradere PHP til versjon 7.0.17+ eller 7.1.3+.';
|
||||
$PHPMAILER_LANG['authenticate'] = 'SMTP-feil: Kunne ikke autentisere.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'Din versjon av PHP er påvirket av en feil som kan føre til ødelagte meldinger. For å løse problemet kan du bytte til sending via SMTP, deaktivere mail.add_x_header-alternativet i php.ini, bytte til MacOS eller Linux, eller oppgradere PHP til versjon 7.0.17+ eller 7.1.3+.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'SMTP-feil: Kunne ikke koble til SMTP-vert.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-feil: data ikke akseptert.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Meldingstekst mangler';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Meldingsinnholdet er tomt';
|
||||
$PHPMAILER_LANG['encoding'] = 'Ukjent koding: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Kunne ikke utføres: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Utvidelse mangler: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Kunne ikke få tilgang til filen: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Feil i fil: Kunne ikke åpne filen: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Følgende Fra-adresse mislyktes: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Kunne ikke instansiere e-postfunksjonen.';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Følgende avsenderadresse mislyktes: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Kunne ikke starte e-postfunksjonen.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Ugyldig adresse: ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Ugyldig headernavn eller verdi';
|
||||
$PHPMAILER_LANG['invalid_hostentry'] = 'Ugyldig vertsinngang: ';
|
||||
|
|
@ -31,3 +32,6 @@
|
|||
$PHPMAILER_LANG['smtp_detail'] = 'Detaljer: ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfeil: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Kan ikke angi eller tilbakestille variabel: ';
|
||||
$PHPMAILER_LANG['no_smtputf8'] = 'Serveren støtter ikke SMTPUTF8, som er nødvendig for å sende til Unicode-adresser.';
|
||||
$PHPMAILER_LANG['imap_recommended'] = 'Det anbefales ikke å bruke forenklet adresseanalyse. Installer PHP IMAP-utvidelsen for full RFC822-analyse.';
|
||||
$PHPMAILER_LANG['deprecated_argument'] = 'Avviklet argument: ';
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@
|
|||
* Dutch PHPMailer language file: refer to PHPMailer.php for definitive list.
|
||||
* @package PHPMailer
|
||||
* @author Tuxion <team@tuxion.nl>
|
||||
* @author Robin van der Vliet <info@robinvandervliet.com>
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'SMTP-fout: authenticatie mislukt.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'PHP versie gededecteerd die onderhavig is aan een bug die kan resulteren in gecorrumpeerde berichten. Om dit te voorkomen, gebruik SMTP voor het verzenden van berichten, zet de mail.add_x_header optie in uw php.ini file uit, gebruik MacOS of Linux, of pas de gebruikte PHP versie aan naar versie 7.0.17+ or 7.1.3+.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'PHP-versie gedetecteerd die onderhevig is aan een bug die kan resulteren in gecorrumpeerde berichten. Om dit te voorkomen, gebruik SMTP voor het verzenden van berichten, zet de optie mail.add_x_header in uw php.ini uit, gebruik MacOS of Linux, of pas de gebruikte PHP-versie aan naar versie 7.0.17+ or 7.1.3+.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'SMTP-fout: kon niet verbinden met SMTP-host.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-fout: data niet geaccepteerd.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Berichttekst is leeg';
|
||||
|
|
@ -16,19 +17,22 @@ $PHPMAILER_LANG['execute'] = 'Kon niet uitvoeren: ';
|
|||
$PHPMAILER_LANG['extension_missing'] = 'Extensie afwezig: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Kreeg geen toegang tot bestand: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Bestandsfout: kon bestand niet openen: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Het volgende afzendersadres is mislukt: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Het volgende afzenderadres is mislukt: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Kon mailfunctie niet initialiseren.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Ongeldig adres: ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Ongeldige header naam of waarde';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Ongeldige headernaam of -waarde';
|
||||
$PHPMAILER_LANG['invalid_hostentry'] = 'Ongeldige hostentry: ';
|
||||
$PHPMAILER_LANG['invalid_host'] = 'Ongeldige host: ';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Er moet minstens één ontvanger worden opgegeven.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'SMTP-fout: de volgende ontvangers zijn mislukt: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Signeerfout: ';
|
||||
$PHPMAILER_LANG['smtp_code'] = 'SMTP code: ';
|
||||
$PHPMAILER_LANG['smtp_code_ex'] = 'Aanvullende SMTP informatie: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Verbinding mislukt.';
|
||||
$PHPMAILER_LANG['smtp_code'] = 'SMTP-code: ';
|
||||
$PHPMAILER_LANG['smtp_code_ex'] = 'Aanvullende SMTP-informatie: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP-verbinding mislukt.';
|
||||
$PHPMAILER_LANG['smtp_detail'] = 'Detail: ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfout: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Kan de volgende variabele niet instellen of resetten: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Kan de volgende variabele niet instellen of herstellen: ';
|
||||
$PHPMAILER_LANG['no_smtputf8'] = 'De server ondersteunt geen SMTPUTF8 dat nodig is om naar Unicode-adressen te sturen.';
|
||||
$PHPMAILER_LANG['imap_recommended'] = 'Het gebruik van de vereenvoudigde adresparser is niet aanbevolen. Installeer de IMAP-extensie voor PHP voor volledige RFC822-ondersteuning.';
|
||||
$PHPMAILER_LANG['deprecated_argument'] = 'Verouderd argument: ';
|
||||
|
|
|
|||
|
|
@ -5,29 +5,29 @@
|
|||
* @package PHPMailer
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['authenticate'] = 'Błąd SMTP: Nie można przeprowadzić uwierzytelnienia.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'Twoja wersja PHP zawiera błąd, który może powodować uszkodzenie wiadomości. Aby go naprawić, przełącz się na wysyłanie za pomocą SMTP, wyłącz opcję mail.add_x_header w php.ini, przełącz się na MacOS lub Linux lub zaktualizuj PHP do wersji 7.0.17+ lub 7.1.3+.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Błąd SMTP: Nie można połączyć się z wybranym hostem.';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Błąd SMTP: Dane nie zostały przyjęte.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Wiadomość jest pusta.';
|
||||
$PHPMAILER_LANG['encoding'] = 'Błędny sposób kodowania znaków: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Nie można uruchomić: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Brakujące rozszerzenie: ';
|
||||
$PHPMAILER_LANG['authenticate'] = 'Błąd SMTP: nie udało się przeprowadzić uwierzytelnienia.';
|
||||
$PHPMAILER_LANG['buggy_php'] = 'Używana wersja PHP zawiera błąd, który może powodować uszkodzenie wiadomości. Aby temu zapobiec, użyj wysyłki przez SMTP, wyłącz opcję mail.add_x_header w php.ini, przejdź na macOS lub Linux, lub zaktualizuj PHP do wersji 7.0.17+ albo 7.1.3+.';
|
||||
$PHPMAILER_LANG['connect_host'] = 'Błąd SMTP: nie udało się połączyć z serwerem (hostem).';
|
||||
$PHPMAILER_LANG['data_not_accepted'] = 'Błąd SMTP: dane wiadomości nie zostały przyjęte przez serwer.';
|
||||
$PHPMAILER_LANG['empty_message'] = 'Nie można wysłać pustej wiadomości.';
|
||||
$PHPMAILER_LANG['encoding'] = 'Nieobsługiwane kodowanie znaków: ';
|
||||
$PHPMAILER_LANG['execute'] = 'Nie udało się uruchomić polecenia: ';
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Brak wymaganego rozszerzenia PHP: ';
|
||||
$PHPMAILER_LANG['file_access'] = 'Brak dostępu do pliku: ';
|
||||
$PHPMAILER_LANG['file_open'] = 'Nie można otworzyć pliku: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Następujący adres nadawcy jest nieprawidłowy lub nie istnieje: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Nie można wywołać funkcji mail(). Sprawdź konfigurację serwera.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Nie można wysłać wiadomości, ' . 'następujący adres odbiorcy jest nieprawidłowy lub nie istnieje: ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Nieprawidłowa nazwa lub wartość nagłówka';
|
||||
$PHPMAILER_LANG['file_open'] = 'Nie udało się otworzyć pliku: ';
|
||||
$PHPMAILER_LANG['from_failed'] = 'Nieprawidłowy adres nadawcy: ';
|
||||
$PHPMAILER_LANG['instantiate'] = 'Nie można zainicjować funkcji mail(). Sprawdź konfigurację serwera.';
|
||||
$PHPMAILER_LANG['invalid_address'] = 'Nie można wysłać wiadomości. Nieprawidłowy adres odbiorcy: ';
|
||||
$PHPMAILER_LANG['invalid_header'] = 'Nieprawidłowa nazwa lub wartość nagłówka.';
|
||||
$PHPMAILER_LANG['invalid_hostentry'] = 'Nieprawidłowy wpis hosta: ';
|
||||
$PHPMAILER_LANG['invalid_host'] = 'Nieprawidłowy host: ';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Należy podać prawidłowy adres email odbiorcy.';
|
||||
$PHPMAILER_LANG['invalid_host'] = 'Nieprawidłowa nazwa hosta: ';
|
||||
$PHPMAILER_LANG['provide_address'] = 'Musisz podać co najmniej jeden prawidłowy adres e-mail odbiorcy.';
|
||||
$PHPMAILER_LANG['mailer_not_supported'] = 'Wybrana metoda wysyłki wiadomości nie jest obsługiwana.';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'Błąd SMTP: Następujący odbiorcy są nieprawidłowi lub nie istnieją: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Błąd podpisywania wiadomości: ';
|
||||
$PHPMAILER_LANG['smtp_code'] = 'Kod SMTP: ';
|
||||
$PHPMAILER_LANG['smtp_code_ex'] = 'Dodatkowe informacje SMTP: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'Wywołanie funkcji SMTP Connect() zostało zakończone niepowodzeniem.';
|
||||
$PHPMAILER_LANG['smtp_detail'] = 'Szczegóły: ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Błąd SMTP: ';
|
||||
$PHPMAILER_LANG['recipients_failed'] = 'Błąd SMTP: nie udało się wysłać do następujących odbiorców: ';
|
||||
$PHPMAILER_LANG['signing'] = 'Błąd podpisywania wiadomości cyfrowo: ';
|
||||
$PHPMAILER_LANG['smtp_code'] = 'Kod odpowiedzi SMTP: ';
|
||||
$PHPMAILER_LANG['smtp_code_ex'] = 'Dodatkowe informacje serwera SMTP: ';
|
||||
$PHPMAILER_LANG['smtp_connect_failed'] = 'Nie udało się nawiązać połączenia za pomocą SMTP Connect().';
|
||||
$PHPMAILER_LANG['smtp_detail'] = 'Szczegóły błędu: ';
|
||||
$PHPMAILER_LANG['smtp_error'] = 'Błąd serwera SMTP: ';
|
||||
$PHPMAILER_LANG['variable_set'] = 'Nie można ustawić lub zmodyfikować zmiennej: ';
|
||||
|
|
|
|||
|
|
@ -27,16 +27,26 @@
|
|||
<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="PHPCompatibility"/>
|
||||
|
||||
|
||||
<!--
|
||||
#############################################################################
|
||||
SELECTIVE EXCLUSIONS
|
||||
Exclude specific files for specific sniffs and/or exclude sub-groups in sniffs.
|
||||
#############################################################################
|
||||
-->
|
||||
|
||||
<rule ref="Generic.Files.LineLength.TooLong">
|
||||
<exclude-pattern>*/language/phpmailer\.lang*\.php$</exclude-pattern>
|
||||
</rule>
|
||||
|
||||
<!-- Excludes related to linting ignore comment for one specific test file. -->
|
||||
<rule ref="PSR12.Files.OpenTag.NotAlone">
|
||||
<exclude-pattern>*/test/Fixtures/LocalizationTest/phpmailer.lang-yz\.php</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="PSR12.Files.FileHeader.SpacingAfterBlock">
|
||||
<exclude-pattern>*/test/Fixtures/LocalizationTest/phpmailer.lang-yz\.php</exclude-pattern>
|
||||
</rule>
|
||||
|
||||
</ruleset>
|
||||
|
|
|
|||
|
|
@ -561,9 +561,9 @@ class PHPMailer
|
|||
* string $body the email body
|
||||
* string $from email address of sender
|
||||
* string $extra extra information of possible use
|
||||
* "smtp_transaction_id' => last smtp transaction id
|
||||
* 'smtp_transaction_id' => last smtp transaction id
|
||||
*
|
||||
* @var string
|
||||
* @var callable|callable-string
|
||||
*/
|
||||
public $action_function = '';
|
||||
|
||||
|
|
@ -711,7 +711,7 @@ class PHPMailer
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $language = [];
|
||||
protected static $language = [];
|
||||
|
||||
/**
|
||||
* The number of errors encountered.
|
||||
|
|
@ -768,7 +768,7 @@ class PHPMailer
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '6.12.0';
|
||||
const VERSION = '7.0.2';
|
||||
|
||||
/**
|
||||
* Error severity: message only, continue processing.
|
||||
|
|
@ -876,6 +876,7 @@ class PHPMailer
|
|||
private function mailPassthru($to, $subject, $body, $header, $params)
|
||||
{
|
||||
//Check overloading of mail function to avoid double-encoding
|
||||
// phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.mbstring_func_overloadDeprecatedRemoved
|
||||
if ((int)ini_get('mbstring.func_overload') & 1) {
|
||||
$subject = $this->secureHeader($subject);
|
||||
} else {
|
||||
|
|
@ -987,6 +988,54 @@ class PHPMailer
|
|||
$this->Mailer = 'mail';
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract sendmail path and parse to deal with known parameters.
|
||||
*
|
||||
* @param string $sendmailPath The sendmail path as set in php.ini
|
||||
*
|
||||
* @return string The sendmail path without the known parameters
|
||||
*/
|
||||
private function parseSendmailPath($sendmailPath)
|
||||
{
|
||||
$sendmailPath = trim((string)$sendmailPath);
|
||||
if ($sendmailPath === '') {
|
||||
return $sendmailPath;
|
||||
}
|
||||
|
||||
$parts = preg_split('/\s+/', $sendmailPath);
|
||||
if (empty($parts)) {
|
||||
return $sendmailPath;
|
||||
}
|
||||
|
||||
$command = array_shift($parts);
|
||||
$remainder = [];
|
||||
|
||||
// Parse only -t, -i, -oi and -f parameters.
|
||||
for ($i = 0; $i < count($parts); ++$i) {
|
||||
$part = $parts[$i];
|
||||
if (preg_match('/^-(i|oi|t)$/', $part, $matches)) {
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/^-f(.*)$/', $part, $matches)) {
|
||||
$address = $matches[1];
|
||||
if ($address === '' && isset($parts[$i + 1]) && strpos($parts[$i + 1], '-') !== 0) {
|
||||
$address = $parts[++$i];
|
||||
}
|
||||
$this->Sender = $address;
|
||||
continue;
|
||||
}
|
||||
|
||||
$remainder[] = $part;
|
||||
}
|
||||
|
||||
// The params that are not parsed are added back to the command.
|
||||
if (!empty($remainder)) {
|
||||
$command .= ' ' . implode(' ', $remainder);
|
||||
}
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send messages using $Sendmail.
|
||||
*/
|
||||
|
|
@ -995,10 +1044,9 @@ class PHPMailer
|
|||
$ini_sendmail_path = ini_get('sendmail_path');
|
||||
|
||||
if (false === stripos($ini_sendmail_path, 'sendmail')) {
|
||||
$this->Sendmail = '/usr/sbin/sendmail';
|
||||
} else {
|
||||
$this->Sendmail = $ini_sendmail_path;
|
||||
$ini_sendmail_path = '/usr/sbin/sendmail';
|
||||
}
|
||||
$this->Sendmail = $this->parseSendmailPath($ini_sendmail_path);
|
||||
$this->Mailer = 'sendmail';
|
||||
}
|
||||
|
||||
|
|
@ -1010,10 +1058,9 @@ class PHPMailer
|
|||
$ini_sendmail_path = ini_get('sendmail_path');
|
||||
|
||||
if (false === stripos($ini_sendmail_path, 'qmail')) {
|
||||
$this->Sendmail = '/var/qmail/bin/qmail-inject';
|
||||
} else {
|
||||
$this->Sendmail = $ini_sendmail_path;
|
||||
$ini_sendmail_path = '/var/qmail/bin/qmail-inject';
|
||||
}
|
||||
$this->Sendmail = $this->parseSendmailPath($ini_sendmail_path);
|
||||
$this->Mailer = 'qmail';
|
||||
}
|
||||
|
||||
|
|
@ -1102,7 +1149,7 @@ class PHPMailer
|
|||
//At-sign is missing.
|
||||
$error_message = sprintf(
|
||||
'%s (%s): %s',
|
||||
$this->lang('invalid_address'),
|
||||
self::lang('invalid_address'),
|
||||
$kind,
|
||||
$address
|
||||
);
|
||||
|
|
@ -1187,7 +1234,7 @@ class PHPMailer
|
|||
if (!in_array($kind, ['to', 'cc', 'bcc', 'Reply-To'])) {
|
||||
$error_message = sprintf(
|
||||
'%s: %s',
|
||||
$this->lang('Invalid recipient kind'),
|
||||
self::lang('Invalid recipient kind'),
|
||||
$kind
|
||||
);
|
||||
$this->setError($error_message);
|
||||
|
|
@ -1201,7 +1248,7 @@ class PHPMailer
|
|||
if (!static::validateAddress($address)) {
|
||||
$error_message = sprintf(
|
||||
'%s (%s): %s',
|
||||
$this->lang('invalid_address'),
|
||||
self::lang('invalid_address'),
|
||||
$kind,
|
||||
$address
|
||||
);
|
||||
|
|
@ -1220,12 +1267,16 @@ class PHPMailer
|
|||
|
||||
return true;
|
||||
}
|
||||
} elseif (!array_key_exists(strtolower($address), $this->ReplyTo)) {
|
||||
$this->ReplyTo[strtolower($address)] = [$address, $name];
|
||||
} else {
|
||||
foreach ($this->ReplyTo as $replyTo) {
|
||||
if (0 === strcasecmp($replyTo[0], $address)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$this->ReplyTo[] = [$address, $name];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1238,38 +1289,38 @@ class PHPMailer
|
|||
* @see https://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
|
||||
*
|
||||
* @param string $addrstr The address list string
|
||||
* @param bool $useimap Whether to use the IMAP extension to parse the list
|
||||
* @param null $useimap Unused. Argument has been deprecated in PHPMailer 6.11.0.
|
||||
* Previously this argument determined whether to use
|
||||
* the IMAP extension to parse the list and accepted a boolean value.
|
||||
* @param string $charset The charset to use when decoding the address list string.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591)
|
||||
public static function parseAddresses($addrstr, $useimap = null, $charset = self::CHARSET_ISO88591)
|
||||
{
|
||||
if ($useimap !== null) {
|
||||
trigger_error(self::lang('deprecated_argument') . '$useimap', E_USER_DEPRECATED);
|
||||
}
|
||||
$addresses = [];
|
||||
if ($useimap && function_exists('imap_rfc822_parse_adrlist')) {
|
||||
if (function_exists('imap_rfc822_parse_adrlist')) {
|
||||
//Use this built-in parser if it's available
|
||||
// phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.imap_rfc822_parse_adrlistRemoved -- wrapped in function_exists()
|
||||
$list = imap_rfc822_parse_adrlist($addrstr, '');
|
||||
// Clear any potential IMAP errors to get rid of notices being thrown at end of script.
|
||||
// phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.imap_errorsRemoved -- wrapped in function_exists()
|
||||
imap_errors();
|
||||
foreach ($list as $address) {
|
||||
if (
|
||||
'.SYNTAX-ERROR.' !== $address->host &&
|
||||
static::validateAddress($address->mailbox . '@' . $address->host)
|
||||
) {
|
||||
//Decode the name part if it's present and encoded
|
||||
//Decode the name part if it's present and maybe encoded
|
||||
if (
|
||||
property_exists($address, 'personal') &&
|
||||
//Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
|
||||
defined('MB_CASE_UPPER') &&
|
||||
preg_match('/^=\?.*\?=$/s', $address->personal)
|
||||
property_exists($address, 'personal')
|
||||
&& is_string($address->personal)
|
||||
&& $address->personal !== ''
|
||||
) {
|
||||
$origCharset = mb_internal_encoding();
|
||||
mb_internal_encoding($charset);
|
||||
//Undo any RFC2047-encoded spaces-as-underscores
|
||||
$address->personal = str_replace('_', '=20', $address->personal);
|
||||
//Decode the name
|
||||
$address->personal = mb_decode_mimeheader($address->personal);
|
||||
mb_internal_encoding($origCharset);
|
||||
$address->personal = static::decodeHeader($address->personal, $charset);
|
||||
}
|
||||
|
||||
$addresses[] = [
|
||||
|
|
@ -1280,40 +1331,51 @@ class PHPMailer
|
|||
}
|
||||
} else {
|
||||
//Use this simpler parser
|
||||
$list = explode(',', $addrstr);
|
||||
foreach ($list as $address) {
|
||||
$address = trim($address);
|
||||
//Is there a separate name part?
|
||||
if (strpos($address, '<') === false) {
|
||||
//No separate name, just use the whole thing
|
||||
if (static::validateAddress($address)) {
|
||||
$addresses[] = [
|
||||
'name' => '',
|
||||
'address' => $address,
|
||||
];
|
||||
}
|
||||
} else {
|
||||
list($name, $email) = explode('<', $address);
|
||||
$email = trim(str_replace('>', '', $email));
|
||||
$name = trim($name);
|
||||
if (static::validateAddress($email)) {
|
||||
//Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
|
||||
//If this name is encoded, decode it
|
||||
if (defined('MB_CASE_UPPER') && preg_match('/^=\?.*\?=$/s', $name)) {
|
||||
$origCharset = mb_internal_encoding();
|
||||
mb_internal_encoding($charset);
|
||||
//Undo any RFC2047-encoded spaces-as-underscores
|
||||
$name = str_replace('_', '=20', $name);
|
||||
//Decode the name
|
||||
$name = mb_decode_mimeheader($name);
|
||||
mb_internal_encoding($origCharset);
|
||||
}
|
||||
$addresses[] = [
|
||||
//Remove any surrounding quotes and spaces from the name
|
||||
'name' => trim($name, '\'" '),
|
||||
'address' => $email,
|
||||
];
|
||||
}
|
||||
$addresses = static::parseSimplerAddresses($addrstr, $charset);
|
||||
}
|
||||
|
||||
return $addresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a string containing one or more RFC822-style comma-separated email addresses
|
||||
* with the form "display name <address>" into an array of name/address pairs.
|
||||
* Uses a simpler parser that does not require the IMAP extension but doesnt support
|
||||
* the full RFC822 spec. For full RFC822 support, use the PHP IMAP extension.
|
||||
*
|
||||
* @param string $addrstr The address list string
|
||||
* @param string $charset The charset to use when decoding the address list string.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function parseSimplerAddresses($addrstr, $charset)
|
||||
{
|
||||
// Emit a runtime notice to recommend using the IMAP extension for full RFC822 parsing
|
||||
trigger_error(self::lang('imap_recommended'), E_USER_NOTICE);
|
||||
|
||||
$addresses = [];
|
||||
$list = explode(',', $addrstr);
|
||||
foreach ($list as $address) {
|
||||
$address = trim($address);
|
||||
//Is there a separate name part?
|
||||
if (strpos($address, '<') === false) {
|
||||
//No separate name, just use the whole thing
|
||||
if (static::validateAddress($address)) {
|
||||
$addresses[] = [
|
||||
'name' => '',
|
||||
'address' => $address,
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$parsed = static::parseEmailString($address);
|
||||
$email = $parsed['email'];
|
||||
if (static::validateAddress($email)) {
|
||||
$name = static::decodeHeader($parsed['name'], $charset);
|
||||
$addresses[] = [
|
||||
//Remove any surrounding quotes and spaces from the name
|
||||
'name' => trim($name, '\'" '),
|
||||
'address' => $email,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1321,6 +1383,42 @@ class PHPMailer
|
|||
return $addresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a string containing an email address with an optional name
|
||||
* and divide it into a name and email address.
|
||||
*
|
||||
* @param string $input The email with name.
|
||||
*
|
||||
* @return array{name: string, email: string}
|
||||
*/
|
||||
private static function parseEmailString($input)
|
||||
{
|
||||
$input = trim((string)$input);
|
||||
|
||||
if ($input === '') {
|
||||
return ['name' => '', 'email' => ''];
|
||||
}
|
||||
|
||||
$pattern = '/^\s*(?:(?:"([^"]*)"|\'([^\']*)\'|([^<]*?))\s*)?<\s*([^>]+)\s*>\s*$/';
|
||||
if (preg_match($pattern, $input, $matches)) {
|
||||
$name = '';
|
||||
// Double quotes including special scenarios.
|
||||
if (isset($matches[1]) && $matches[1] !== '') {
|
||||
$name = $matches[1];
|
||||
// Single quotes including special scenarios.
|
||||
} elseif (isset($matches[2]) && $matches[2] !== '') {
|
||||
$name = $matches[2];
|
||||
// Simplest scenario, name and email are in the format "Name <email>".
|
||||
} elseif (isset($matches[3])) {
|
||||
$name = trim($matches[3]);
|
||||
}
|
||||
|
||||
return ['name' => $name, 'email' => trim($matches[4])];
|
||||
}
|
||||
|
||||
return ['name' => '', 'email' => $input];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the From and FromName properties.
|
||||
*
|
||||
|
|
@ -1334,6 +1432,10 @@ class PHPMailer
|
|||
*/
|
||||
public function setFrom($address, $name = '', $auto = true)
|
||||
{
|
||||
if (is_null($name)) {
|
||||
//Helps avoid a deprecation warning in the preg_replace() below
|
||||
$name = '';
|
||||
}
|
||||
$address = trim((string)$address);
|
||||
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
|
||||
//Don't validate now addresses with IDN. Will be done in send().
|
||||
|
|
@ -1345,7 +1447,7 @@ class PHPMailer
|
|||
) {
|
||||
$error_message = sprintf(
|
||||
'%s (From): %s',
|
||||
$this->lang('invalid_address'),
|
||||
self::lang('invalid_address'),
|
||||
$address
|
||||
);
|
||||
$this->setError($error_message);
|
||||
|
|
@ -1532,9 +1634,11 @@ class PHPMailer
|
|||
);
|
||||
} elseif (defined('INTL_IDNA_VARIANT_2003')) {
|
||||
//Fall back to this old, deprecated/removed encoding
|
||||
// phpcs:ignore PHPCompatibility.Constants.RemovedConstants.intl_idna_variant_2003DeprecatedRemoved
|
||||
$punycode = idn_to_ascii($domain, $errorcode, \INTL_IDNA_VARIANT_2003);
|
||||
} else {
|
||||
//Fall back to a default we don't know about
|
||||
// phpcs:ignore PHPCompatibility.ParameterValues.NewIDNVariantDefault.NotSet
|
||||
$punycode = idn_to_ascii($domain, $errorcode);
|
||||
}
|
||||
if (false !== $punycode) {
|
||||
|
|
@ -1601,7 +1705,7 @@ class PHPMailer
|
|||
&& ini_get('mail.add_x_header') === '1'
|
||||
&& stripos(PHP_OS, 'WIN') === 0
|
||||
) {
|
||||
trigger_error($this->lang('buggy_php'), E_USER_WARNING);
|
||||
trigger_error(self::lang('buggy_php'), E_USER_WARNING);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -1631,7 +1735,7 @@ class PHPMailer
|
|||
call_user_func_array([$this, 'addAnAddress'], $params);
|
||||
}
|
||||
if (count($this->to) + count($this->cc) + count($this->bcc) < 1) {
|
||||
throw new Exception($this->lang('provide_address'), self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('provide_address'), self::STOP_CRITICAL);
|
||||
}
|
||||
|
||||
//Validate From, Sender, and ConfirmReadingTo addresses
|
||||
|
|
@ -1648,7 +1752,7 @@ class PHPMailer
|
|||
if (!static::validateAddress($this->{$address_kind})) {
|
||||
$error_message = sprintf(
|
||||
'%s (%s): %s',
|
||||
$this->lang('invalid_address'),
|
||||
self::lang('invalid_address'),
|
||||
$address_kind,
|
||||
$this->{$address_kind}
|
||||
);
|
||||
|
|
@ -1670,7 +1774,7 @@ class PHPMailer
|
|||
$this->setMessageType();
|
||||
//Refuse to send an empty message unless we are specifically allowing it
|
||||
if (!$this->AllowEmpty && empty($this->Body)) {
|
||||
throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('empty_message'), self::STOP_CRITICAL);
|
||||
}
|
||||
|
||||
//Trim subject consistently
|
||||
|
|
@ -1802,23 +1906,27 @@ class PHPMailer
|
|||
//PHP config has a sender address we can use
|
||||
$this->Sender = ini_get('sendmail_from');
|
||||
}
|
||||
//CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
|
||||
|
||||
$sendmailArgs = [];
|
||||
|
||||
// CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
|
||||
// Also don't add the -f automatically unless it has been set either via Sender
|
||||
// or sendmail_path. Otherwise it can introduce new problems.
|
||||
// @see http://github.com/PHPMailer/PHPMailer/issues/2298
|
||||
if (!empty($this->Sender) && static::validateAddress($this->Sender) && self::isShellSafe($this->Sender)) {
|
||||
if ($this->Mailer === 'qmail') {
|
||||
$sendmailFmt = '%s -f%s';
|
||||
} else {
|
||||
$sendmailFmt = '%s -oi -f%s -t';
|
||||
}
|
||||
} else {
|
||||
//allow sendmail to choose a default envelope sender. It may
|
||||
//seem preferable to force it to use the From header as with
|
||||
//SMTP, but that introduces new problems (see
|
||||
//<https://github.com/PHPMailer/PHPMailer/issues/2298>), and
|
||||
//it has historically worked this way.
|
||||
$sendmailFmt = '%s -oi -t';
|
||||
$sendmailArgs[] = '-f' . $this->Sender;
|
||||
}
|
||||
|
||||
$sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender);
|
||||
// Qmail doesn't accept all the sendmail parameters
|
||||
// @see https://github.com/PHPMailer/PHPMailer/issues/3189
|
||||
if ($this->Mailer !== 'qmail') {
|
||||
$sendmailArgs[] = '-i';
|
||||
$sendmailArgs[] = '-t';
|
||||
}
|
||||
|
||||
$resultArgs = (empty($sendmailArgs) ? '' : ' ' . implode(' ', $sendmailArgs));
|
||||
|
||||
$sendmail = trim(escapeshellcmd($this->Sendmail) . $resultArgs);
|
||||
$this->edebug('Sendmail path: ' . $this->Sendmail);
|
||||
$this->edebug('Sendmail command: ' . $sendmail);
|
||||
$this->edebug('Envelope sender: ' . $this->Sender);
|
||||
|
|
@ -1828,33 +1936,35 @@ class PHPMailer
|
|||
foreach ($this->SingleToArray as $toAddr) {
|
||||
$mail = @popen($sendmail, 'w');
|
||||
if (!$mail) {
|
||||
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
|
||||
}
|
||||
$this->edebug("To: {$toAddr}");
|
||||
fwrite($mail, 'To: ' . $toAddr . "\n");
|
||||
fwrite($mail, $header);
|
||||
fwrite($mail, $body);
|
||||
$result = pclose($mail);
|
||||
$addrinfo = static::parseAddresses($toAddr, true, $this->CharSet);
|
||||
$this->doCallback(
|
||||
($result === 0),
|
||||
[[$addrinfo['address'], $addrinfo['name']]],
|
||||
$this->cc,
|
||||
$this->bcc,
|
||||
$this->Subject,
|
||||
$body,
|
||||
$this->From,
|
||||
[]
|
||||
);
|
||||
$addrinfo = static::parseAddresses($toAddr, null, $this->CharSet);
|
||||
foreach ($addrinfo as $addr) {
|
||||
$this->doCallback(
|
||||
($result === 0),
|
||||
[[$addr['address'], $addr['name']]],
|
||||
$this->cc,
|
||||
$this->bcc,
|
||||
$this->Subject,
|
||||
$body,
|
||||
$this->From,
|
||||
[]
|
||||
);
|
||||
}
|
||||
$this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
|
||||
if (0 !== $result) {
|
||||
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$mail = @popen($sendmail, 'w');
|
||||
if (!$mail) {
|
||||
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
|
||||
}
|
||||
fwrite($mail, $header);
|
||||
fwrite($mail, $body);
|
||||
|
|
@ -1871,7 +1981,7 @@ class PHPMailer
|
|||
);
|
||||
$this->edebug("Result: " . ($result === 0 ? 'true' : 'false'));
|
||||
if (0 !== $result) {
|
||||
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2000,7 +2110,8 @@ class PHPMailer
|
|||
$this->Sender = ini_get('sendmail_from');
|
||||
}
|
||||
if (!empty($this->Sender) && static::validateAddress($this->Sender)) {
|
||||
if (self::isShellSafe($this->Sender)) {
|
||||
$phpmailer_path = ini_get('sendmail_path');
|
||||
if (self::isShellSafe($this->Sender) && strpos($phpmailer_path, ' -f') === false) {
|
||||
$params = sprintf('-f%s', $this->Sender);
|
||||
}
|
||||
$old_from = ini_get('sendmail_from');
|
||||
|
|
@ -2010,17 +2121,19 @@ class PHPMailer
|
|||
if ($this->SingleTo && count($toArr) > 1) {
|
||||
foreach ($toArr as $toAddr) {
|
||||
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
|
||||
$addrinfo = static::parseAddresses($toAddr, true, $this->CharSet);
|
||||
$this->doCallback(
|
||||
$result,
|
||||
[[$addrinfo['address'], $addrinfo['name']]],
|
||||
$this->cc,
|
||||
$this->bcc,
|
||||
$this->Subject,
|
||||
$body,
|
||||
$this->From,
|
||||
[]
|
||||
);
|
||||
$addrinfo = static::parseAddresses($toAddr, null, $this->CharSet);
|
||||
foreach ($addrinfo as $addr) {
|
||||
$this->doCallback(
|
||||
$result,
|
||||
[[$addr['address'], $addr['name']]],
|
||||
$this->cc,
|
||||
$this->bcc,
|
||||
$this->Subject,
|
||||
$body,
|
||||
$this->From,
|
||||
[]
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
|
||||
|
|
@ -2030,7 +2143,7 @@ class PHPMailer
|
|||
ini_set('sendmail_from', $old_from);
|
||||
}
|
||||
if (!$result) {
|
||||
throw new Exception($this->lang('instantiate'), self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('instantiate'), self::STOP_CRITICAL);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -2116,12 +2229,12 @@ class PHPMailer
|
|||
$header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
|
||||
$bad_rcpt = [];
|
||||
if (!$this->smtpConnect($this->SMTPOptions)) {
|
||||
throw new Exception($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
|
||||
throw new Exception(self::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);
|
||||
throw new Exception(self::lang('no_smtputf8'), self::STOP_CRITICAL);
|
||||
}
|
||||
//Sender already validated in preSend()
|
||||
if ('' === $this->Sender) {
|
||||
|
|
@ -2133,7 +2246,7 @@ class PHPMailer
|
|||
$this->smtp->xclient($this->SMTPXClient);
|
||||
}
|
||||
if (!$this->smtp->mail($smtp_from)) {
|
||||
$this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
|
||||
$this->setError(self::lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
|
||||
throw new Exception($this->ErrorInfo, self::STOP_CRITICAL);
|
||||
}
|
||||
|
||||
|
|
@ -2155,7 +2268,7 @@ class PHPMailer
|
|||
|
||||
//Only send the DATA command if we have viable recipients
|
||||
if ((count($this->all_recipients) > count($bad_rcpt)) && !$this->smtp->data($header . $body)) {
|
||||
throw new Exception($this->lang('data_not_accepted'), self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('data_not_accepted'), self::STOP_CRITICAL);
|
||||
}
|
||||
|
||||
$smtp_transaction_id = $this->smtp->getLastTransactionID();
|
||||
|
|
@ -2186,7 +2299,7 @@ class PHPMailer
|
|||
foreach ($bad_rcpt as $bad) {
|
||||
$errstr .= $bad['to'] . ': ' . $bad['error'];
|
||||
}
|
||||
throw new Exception($this->lang('recipients_failed') . $errstr, self::STOP_CONTINUE);
|
||||
throw new Exception(self::lang('recipients_failed') . $errstr, self::STOP_CONTINUE);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -2240,7 +2353,7 @@ class PHPMailer
|
|||
$hostinfo
|
||||
)
|
||||
) {
|
||||
$this->edebug($this->lang('invalid_hostentry') . ' ' . trim($hostentry));
|
||||
$this->edebug(self::lang('invalid_hostentry') . ' ' . trim($hostentry));
|
||||
//Not a valid host entry
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2252,7 +2365,7 @@ class PHPMailer
|
|||
|
||||
//Check the host name is a valid name or IP address before trying to use it
|
||||
if (!static::isValidHost($hostinfo[2])) {
|
||||
$this->edebug($this->lang('invalid_host') . ' ' . $hostinfo[2]);
|
||||
$this->edebug(self::lang('invalid_host') . ' ' . $hostinfo[2]);
|
||||
continue;
|
||||
}
|
||||
$prefix = '';
|
||||
|
|
@ -2272,7 +2385,7 @@ class PHPMailer
|
|||
if (static::ENCRYPTION_STARTTLS === $secure || static::ENCRYPTION_SMTPS === $secure) {
|
||||
//Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
|
||||
if (!$sslext) {
|
||||
throw new Exception($this->lang('extension_missing') . 'openssl', self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('extension_missing') . 'openssl', self::STOP_CRITICAL);
|
||||
}
|
||||
}
|
||||
$host = $hostinfo[2];
|
||||
|
|
@ -2324,7 +2437,7 @@ class PHPMailer
|
|||
$this->oauth
|
||||
)
|
||||
) {
|
||||
throw new Exception($this->lang('authenticate'));
|
||||
throw new Exception(self::lang('authenticate'));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -2374,7 +2487,7 @@ class PHPMailer
|
|||
*
|
||||
* @return bool Returns true if the requested language was loaded, false otherwise.
|
||||
*/
|
||||
public function setLanguage($langcode = 'en', $lang_path = '')
|
||||
public static function setLanguage($langcode = 'en', $lang_path = '')
|
||||
{
|
||||
//Backwards compatibility for renamed language codes
|
||||
$renamed_langcodes = [
|
||||
|
|
@ -2423,6 +2536,9 @@ class PHPMailer
|
|||
'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',
|
||||
'imap_recommended' => 'Using simplified address parser is not recommended. ' .
|
||||
'Install the PHP IMAP extension for full RFC822 parsing.',
|
||||
'deprecated_argument' => 'Deprecated Argument: ',
|
||||
];
|
||||
if (empty($lang_path)) {
|
||||
//Calculate an absolute path so it can work if CWD is not here
|
||||
|
|
@ -2489,7 +2605,7 @@ class PHPMailer
|
|||
}
|
||||
}
|
||||
}
|
||||
$this->language = $PHPMAILER_LANG;
|
||||
self::$language = $PHPMAILER_LANG;
|
||||
|
||||
return $foundlang; //Returns false if language not found
|
||||
}
|
||||
|
|
@ -2501,11 +2617,11 @@ class PHPMailer
|
|||
*/
|
||||
public function getTranslations()
|
||||
{
|
||||
if (empty($this->language)) {
|
||||
$this->setLanguage(); // Set the default language.
|
||||
if (empty(self::$language)) {
|
||||
self::setLanguage(); // Set the default language.
|
||||
}
|
||||
|
||||
return $this->language;
|
||||
return self::$language;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2896,6 +3012,7 @@ class PHPMailer
|
|||
$bytes = '';
|
||||
if (function_exists('random_bytes')) {
|
||||
try {
|
||||
// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.random_bytesFound -- Wrapped in function_exists.
|
||||
$bytes = random_bytes($len);
|
||||
} catch (\Exception $e) {
|
||||
//Do nothing
|
||||
|
|
@ -2928,10 +3045,6 @@ class PHPMailer
|
|||
//Create unique IDs and preset boundaries
|
||||
$this->setBoundaries();
|
||||
|
||||
if ($this->sign_key_file) {
|
||||
$body .= $this->getMailMIME() . static::$LE;
|
||||
}
|
||||
|
||||
$this->setWordWrap();
|
||||
|
||||
$bodyEncoding = $this->Encoding;
|
||||
|
|
@ -2963,6 +3076,12 @@ class PHPMailer
|
|||
if (static::ENCODING_BASE64 !== $altBodyEncoding && static::hasLineLongerThanMax($this->AltBody)) {
|
||||
$altBodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
|
||||
}
|
||||
|
||||
if ($this->sign_key_file) {
|
||||
$this->Encoding = $bodyEncoding;
|
||||
$body .= $this->getMailMIME() . static::$LE;
|
||||
}
|
||||
|
||||
//Use this as a preamble in all multipart message types
|
||||
$mimepre = '';
|
||||
switch ($this->message_type) {
|
||||
|
|
@ -3144,12 +3263,12 @@ class PHPMailer
|
|||
if ($this->isError()) {
|
||||
$body = '';
|
||||
if ($this->exceptions) {
|
||||
throw new Exception($this->lang('empty_message'), self::STOP_CRITICAL);
|
||||
throw new Exception(self::lang('empty_message'), self::STOP_CRITICAL);
|
||||
}
|
||||
} elseif ($this->sign_key_file) {
|
||||
try {
|
||||
if (!defined('PKCS7_TEXT')) {
|
||||
throw new Exception($this->lang('extension_missing') . 'openssl');
|
||||
throw new Exception(self::lang('extension_missing') . 'openssl');
|
||||
}
|
||||
|
||||
$file = tempnam(sys_get_temp_dir(), 'srcsign');
|
||||
|
|
@ -3187,7 +3306,7 @@ class PHPMailer
|
|||
$body = $parts[1];
|
||||
} else {
|
||||
@unlink($signed);
|
||||
throw new Exception($this->lang('signing') . openssl_error_string());
|
||||
throw new Exception(self::lang('signing') . openssl_error_string());
|
||||
}
|
||||
} catch (Exception $exc) {
|
||||
$body = '';
|
||||
|
|
@ -3332,7 +3451,7 @@ class PHPMailer
|
|||
) {
|
||||
try {
|
||||
if (!static::fileIsAccessible($path)) {
|
||||
throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
|
||||
throw new Exception(self::lang('file_access') . $path, self::STOP_CONTINUE);
|
||||
}
|
||||
|
||||
//If a MIME type is not specified, try to work it out from the file name
|
||||
|
|
@ -3345,7 +3464,7 @@ class PHPMailer
|
|||
$name = $filename;
|
||||
}
|
||||
if (!$this->validateEncoding($encoding)) {
|
||||
throw new Exception($this->lang('encoding') . $encoding);
|
||||
throw new Exception(self::lang('encoding') . $encoding);
|
||||
}
|
||||
|
||||
$this->attachment[] = [
|
||||
|
|
@ -3506,11 +3625,11 @@ class PHPMailer
|
|||
{
|
||||
try {
|
||||
if (!static::fileIsAccessible($path)) {
|
||||
throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE);
|
||||
throw new Exception(self::lang('file_open') . $path, self::STOP_CONTINUE);
|
||||
}
|
||||
$file_buffer = file_get_contents($path);
|
||||
if (false === $file_buffer) {
|
||||
throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE);
|
||||
throw new Exception(self::lang('file_open') . $path, self::STOP_CONTINUE);
|
||||
}
|
||||
$file_buffer = $this->encodeString($file_buffer, $encoding);
|
||||
|
||||
|
|
@ -3563,9 +3682,9 @@ class PHPMailer
|
|||
$encoded = $this->encodeQP($str);
|
||||
break;
|
||||
default:
|
||||
$this->setError($this->lang('encoding') . $encoding);
|
||||
$this->setError(self::lang('encoding') . $encoding);
|
||||
if ($this->exceptions) {
|
||||
throw new Exception($this->lang('encoding') . $encoding);
|
||||
throw new Exception(self::lang('encoding') . $encoding);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -3671,6 +3790,42 @@ class PHPMailer
|
|||
return trim(static::normalizeBreaks($encoded));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode an RFC2047-encoded header value
|
||||
* Attempts multiple strategies so it works even when the mbstring extension is disabled.
|
||||
*
|
||||
* @param string $value The header value to decode
|
||||
* @param string $charset The target charset to convert to, defaults to ISO-8859-1 for BC
|
||||
*
|
||||
* @return string The decoded header value
|
||||
*/
|
||||
public static function decodeHeader($value, $charset = self::CHARSET_ISO88591)
|
||||
{
|
||||
if (!is_string($value) || $value === '') {
|
||||
return '';
|
||||
}
|
||||
// Detect the presence of any RFC2047 encoded-words
|
||||
$hasEncodedWord = (bool) preg_match('/=\?.*\?=/s', $value);
|
||||
if ($hasEncodedWord && defined('MB_CASE_UPPER')) {
|
||||
$origCharset = mb_internal_encoding();
|
||||
// Always decode to UTF-8 to provide a consistent, modern output encoding.
|
||||
mb_internal_encoding($charset);
|
||||
if (PHP_VERSION_ID < 80300) {
|
||||
// Undo any RFC2047-encoded spaces-as-underscores.
|
||||
$value = str_replace('_', '=20', $value);
|
||||
} else {
|
||||
// PHP 8.3+ already interprets underscores as spaces. Remove additional
|
||||
// linear whitespace between adjacent encoded words to avoid double spacing.
|
||||
$value = preg_replace('/(\?=)\s+(=\?)/', '$1$2', $value);
|
||||
}
|
||||
// Decode the header value
|
||||
$value = mb_decode_mimeheader($value);
|
||||
mb_internal_encoding($origCharset);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string contains multi-byte characters.
|
||||
*
|
||||
|
|
@ -3840,7 +3995,7 @@ class PHPMailer
|
|||
}
|
||||
|
||||
if (!$this->validateEncoding($encoding)) {
|
||||
throw new Exception($this->lang('encoding') . $encoding);
|
||||
throw new Exception(self::lang('encoding') . $encoding);
|
||||
}
|
||||
|
||||
//Append to $attachment array
|
||||
|
|
@ -3899,7 +4054,7 @@ class PHPMailer
|
|||
) {
|
||||
try {
|
||||
if (!static::fileIsAccessible($path)) {
|
||||
throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
|
||||
throw new Exception(self::lang('file_access') . $path, self::STOP_CONTINUE);
|
||||
}
|
||||
|
||||
//If a MIME type is not specified, try to work it out from the file name
|
||||
|
|
@ -3908,7 +4063,7 @@ class PHPMailer
|
|||
}
|
||||
|
||||
if (!$this->validateEncoding($encoding)) {
|
||||
throw new Exception($this->lang('encoding') . $encoding);
|
||||
throw new Exception(self::lang('encoding') . $encoding);
|
||||
}
|
||||
|
||||
$filename = (string) static::mb_pathinfo($path, PATHINFO_BASENAME);
|
||||
|
|
@ -3974,7 +4129,7 @@ class PHPMailer
|
|||
}
|
||||
|
||||
if (!$this->validateEncoding($encoding)) {
|
||||
throw new Exception($this->lang('encoding') . $encoding);
|
||||
throw new Exception(self::lang('encoding') . $encoding);
|
||||
}
|
||||
|
||||
//Append to $attachment array
|
||||
|
|
@ -4231,7 +4386,7 @@ class PHPMailer
|
|||
}
|
||||
if (strpbrk($name . $value, "\r\n") !== false) {
|
||||
if ($this->exceptions) {
|
||||
throw new Exception($this->lang('invalid_header'));
|
||||
throw new Exception(self::lang('invalid_header'));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -4255,15 +4410,15 @@ 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 .= ' ' . self::lang('smtp_error') . $lasterror['error'];
|
||||
if (!empty($lasterror['detail'])) {
|
||||
$msg .= ' ' . $this->lang('smtp_detail') . $lasterror['detail'];
|
||||
$msg .= ' ' . self::lang('smtp_detail') . $lasterror['detail'];
|
||||
}
|
||||
if (!empty($lasterror['smtp_code'])) {
|
||||
$msg .= ' ' . $this->lang('smtp_code') . $lasterror['smtp_code'];
|
||||
$msg .= ' ' . self::lang('smtp_code') . $lasterror['smtp_code'];
|
||||
}
|
||||
if (!empty($lasterror['smtp_code_ex'])) {
|
||||
$msg .= ' ' . $this->lang('smtp_code_ex') . $lasterror['smtp_code_ex'];
|
||||
$msg .= ' ' . self::lang('smtp_code_ex') . $lasterror['smtp_code_ex'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4388,21 +4543,21 @@ class PHPMailer
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function lang($key)
|
||||
protected static function lang($key)
|
||||
{
|
||||
if (count($this->language) < 1) {
|
||||
$this->setLanguage(); //Set the default language
|
||||
if (count(self::$language) < 1) {
|
||||
self::setLanguage(); //Set the default language
|
||||
}
|
||||
|
||||
if (array_key_exists($key, $this->language)) {
|
||||
if (array_key_exists($key, self::$language)) {
|
||||
if ('smtp_connect_failed' === $key) {
|
||||
//Include a link to troubleshooting docs on SMTP connection failure.
|
||||
//This is by far the biggest cause of support questions
|
||||
//but it's usually not PHPMailer's fault.
|
||||
return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting';
|
||||
return self::$language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting';
|
||||
}
|
||||
|
||||
return $this->language[$key];
|
||||
return self::$language[$key];
|
||||
}
|
||||
|
||||
//Return the key as a fallback
|
||||
|
|
@ -4417,7 +4572,7 @@ class PHPMailer
|
|||
*/
|
||||
private function getSmtpErrorMessage($base_key)
|
||||
{
|
||||
$message = $this->lang($base_key);
|
||||
$message = self::lang($base_key);
|
||||
$error = $this->smtp->getError();
|
||||
if (!empty($error['error'])) {
|
||||
$message .= ' ' . $error['error'];
|
||||
|
|
@ -4461,7 +4616,7 @@ class PHPMailer
|
|||
//Ensure name is not empty, and that neither name nor value contain line breaks
|
||||
if (empty($name) || strpbrk($name . $value, "\r\n") !== false) {
|
||||
if ($this->exceptions) {
|
||||
throw new Exception($this->lang('invalid_header'));
|
||||
throw new Exception(self::lang('invalid_header'));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -4492,10 +4647,10 @@ class PHPMailer
|
|||
* Converts data-uri images into embedded attachments.
|
||||
* If you don't want to apply these transformations to your HTML, just set Body and AltBody directly.
|
||||
*
|
||||
* @param string $message HTML message string
|
||||
* @param string $basedir Absolute path to a base directory to prepend to relative paths to images
|
||||
* @param bool|callable $advanced Whether to use the internal HTML to text converter
|
||||
* or your own custom converter
|
||||
* @param string $message HTML message string
|
||||
* @param string $basedir Absolute path to a base directory to prepend to relative paths to images
|
||||
* @param bool|callable $advanced Whether to use the internal HTML to text converter
|
||||
* or your own custom converter
|
||||
* @return string The transformed message body
|
||||
*
|
||||
* @throws Exception
|
||||
|
|
@ -4504,6 +4659,12 @@ class PHPMailer
|
|||
*/
|
||||
public function msgHTML($message, $basedir = '', $advanced = false)
|
||||
{
|
||||
$cid_domain = 'phpmailer.0';
|
||||
if (filter_var($this->From, FILTER_VALIDATE_EMAIL)) {
|
||||
//prepend with a character to create valid RFC822 string in order to validate
|
||||
$cid_domain = substr($this->From, strrpos($this->From, '@') + 1);
|
||||
}
|
||||
|
||||
preg_match_all('/(?<!-)(src|background)=["\'](.*)["\']/Ui', $message, $images);
|
||||
if (array_key_exists(2, $images)) {
|
||||
if (strlen($basedir) > 1 && '/' !== substr($basedir, -1)) {
|
||||
|
|
@ -4525,7 +4686,7 @@ class PHPMailer
|
|||
}
|
||||
//Hash the decoded data, not the URL, so that the same data-URI image used in multiple places
|
||||
//will only be embedded once, even if it used a different encoding
|
||||
$cid = substr(hash('sha256', $data), 0, 32) . '@phpmailer.0'; //RFC2392 S 2
|
||||
$cid = substr(hash('sha256', $data), 0, 32) . '@' . $cid_domain; //RFC2392 S 2
|
||||
|
||||
if (!$this->cidExists($cid)) {
|
||||
$this->addStringEmbeddedImage(
|
||||
|
|
@ -4559,7 +4720,7 @@ class PHPMailer
|
|||
$directory = '';
|
||||
}
|
||||
//RFC2392 S 2
|
||||
$cid = substr(hash('sha256', $url), 0, 32) . '@phpmailer.0';
|
||||
$cid = substr(hash('sha256', $url), 0, 32) . '@' . $cid_domain;
|
||||
if (strlen($basedir) > 1 && '/' !== substr($basedir, -1)) {
|
||||
$basedir .= '/';
|
||||
}
|
||||
|
|
@ -4854,7 +5015,7 @@ class PHPMailer
|
|||
|
||||
return true;
|
||||
}
|
||||
$this->setError($this->lang('variable_set') . $name);
|
||||
$this->setError(self::lang('variable_set') . $name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -4992,7 +5153,7 @@ class PHPMailer
|
|||
{
|
||||
if (!defined('PKCS7_TEXT')) {
|
||||
if ($this->exceptions) {
|
||||
throw new Exception($this->lang('extension_missing') . 'openssl');
|
||||
throw new Exception(self::lang('extension_missing') . 'openssl');
|
||||
}
|
||||
|
||||
return '';
|
||||
|
|
@ -5007,12 +5168,14 @@ class PHPMailer
|
|||
}
|
||||
if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) {
|
||||
if (\PHP_MAJOR_VERSION < 8) {
|
||||
// phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.openssl_pkey_freeDeprecated
|
||||
openssl_pkey_free($privKey);
|
||||
}
|
||||
|
||||
return base64_encode($signature);
|
||||
}
|
||||
if (\PHP_MAJOR_VERSION < 8) {
|
||||
// phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.openssl_pkey_freeDeprecated
|
||||
openssl_pkey_free($privKey);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,8 +45,9 @@ class POP3
|
|||
* The POP3 PHPMailer Version number.
|
||||
*
|
||||
* @var string
|
||||
* @deprecated This constant will be removed in PHPMailer 8.0. Use `PHPMailer::VERSION` instead.
|
||||
*/
|
||||
const VERSION = '6.12.0';
|
||||
const VERSION = '7.0.2';
|
||||
|
||||
/**
|
||||
* Default POP3 port number.
|
||||
|
|
|
|||
90
src/SMTP.php
90
src/SMTP.php
|
|
@ -34,8 +34,9 @@ class SMTP
|
|||
* The PHPMailer SMTP version number.
|
||||
*
|
||||
* @var string
|
||||
* @deprecated This constant will be removed in PHPMailer 8.0. Use `PHPMailer::VERSION` instead.
|
||||
*/
|
||||
const VERSION = '6.12.0';
|
||||
const VERSION = '7.0.2';
|
||||
|
||||
/**
|
||||
* SMTP line break constant.
|
||||
|
|
@ -205,6 +206,7 @@ class SMTP
|
|||
'Haraka' => '/[\d]{3} Message Queued \((.*)\)/',
|
||||
'ZoneMTA' => '/[\d]{3} Message queued as (.*)/',
|
||||
'Mailjet' => '/[\d]{3} OK queued as (.*)/',
|
||||
'Gsmtp' => '/[\d]{3} 2\.0\.0 OK (.*) - gsmtp/',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -493,7 +495,9 @@ class SMTP
|
|||
//PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
|
||||
//so add them back in manually if we can
|
||||
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
|
||||
// phpcs:ignore PHPCompatibility.Constants.NewConstants.stream_crypto_method_tlsv1_2_clientFound
|
||||
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
|
||||
// phpcs:ignore PHPCompatibility.Constants.NewConstants.stream_crypto_method_tlsv1_1_clientFound
|
||||
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
|
||||
}
|
||||
|
||||
|
|
@ -632,11 +636,48 @@ class SMTP
|
|||
if (null === $OAuth) {
|
||||
return false;
|
||||
}
|
||||
$oauth = $OAuth->getOauth64();
|
||||
|
||||
//Start authentication
|
||||
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
|
||||
return false;
|
||||
try {
|
||||
$oauth = $OAuth->getOauth64();
|
||||
} catch (\Exception $e) {
|
||||
// We catch all exceptions and convert them to PHPMailer exceptions to be able to
|
||||
// handle them correctly later
|
||||
throw new Exception("SMTP authentication error", 0, $e);
|
||||
}
|
||||
/*
|
||||
* An SMTP command line can have a maximum length of 512 bytes, including the command name,
|
||||
* so the base64-encoded OAUTH token has a maximum length of:
|
||||
* 512 - 13 (AUTH XOAUTH2) - 2 (CRLF) = 497 bytes
|
||||
* If the token is longer than that, the command and the token must be sent separately as described in
|
||||
* https://www.rfc-editor.org/rfc/rfc4954#section-4
|
||||
*/
|
||||
if ($oauth === '') {
|
||||
//Sending an empty auth token is legitimate, but it must be encoded as '='
|
||||
//to indicate it's not a 2-part command
|
||||
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 =', 235)) {
|
||||
return false;
|
||||
}
|
||||
} elseif (strlen($oauth) <= 497) {
|
||||
//Authenticate using a token in the initial-response part
|
||||
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
//The token is too long, so we need to send it in two parts.
|
||||
//Send the auth command without a token and expect a 334
|
||||
if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2', 334)) {
|
||||
return false;
|
||||
}
|
||||
//Send the token
|
||||
if (!$this->sendCommand('OAuth TOKEN', $oauth, [235, 334])) {
|
||||
return false;
|
||||
}
|
||||
//If the server answers with 334, send an empty line and wait for a 235
|
||||
if (
|
||||
substr($this->last_reply, 0, 3) === '334'
|
||||
&& $this->sendCommand('AUTH End', '', 235)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -729,6 +770,25 @@ class SMTP
|
|||
}
|
||||
}
|
||||
|
||||
private function iterateLines($s)
|
||||
{
|
||||
$start = 0;
|
||||
$length = strlen($s);
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$c = $s[$i];
|
||||
if ($c === "\n" || $c === "\r") {
|
||||
yield substr($s, $start, $i - $start);
|
||||
if ($c === "\r" && $i + 1 < $length && $s[$i + 1] === "\n") {
|
||||
$i++;
|
||||
}
|
||||
$start = $i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
yield substr($s, $start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP DATA command.
|
||||
* Issues a data command and sends the msg_data to the server,
|
||||
|
|
@ -757,15 +817,16 @@ class SMTP
|
|||
* NOTE: this does not count towards line-length limit.
|
||||
*/
|
||||
|
||||
//Normalize line breaks before exploding
|
||||
$lines = explode("\n", str_replace(["\r\n", "\r"], "\n", $msg_data));
|
||||
//Iterate over lines with normalized line breaks
|
||||
$lines = $this->iterateLines($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.
|
||||
*/
|
||||
|
||||
$field = substr($lines[0], 0, strpos($lines[0], ':'));
|
||||
$first_line = $lines->current();
|
||||
$field = substr($first_line, 0, strpos($first_line, ':'));
|
||||
$in_headers = false;
|
||||
if (!empty($field) && strpos($field, ' ') === false) {
|
||||
$in_headers = true;
|
||||
|
|
@ -1309,7 +1370,16 @@ class SMTP
|
|||
|
||||
//stream_select returns false when the `select` system call is interrupted
|
||||
//by an incoming signal, try the select again
|
||||
if (stripos($message, 'interrupted system call') !== false) {
|
||||
if (
|
||||
stripos($message, 'interrupted system call') !== false ||
|
||||
(
|
||||
// on applications with a different locale than english, the message above is not found because
|
||||
// it's translated. So we also check for the SOCKET_EINTR constant which is defined under
|
||||
// Windows and UNIX-like platforms (if available on the platform).
|
||||
defined('SOCKET_EINTR') &&
|
||||
stripos($message, 'stream_select(): Unable to select [' . SOCKET_EINTR . ']') !== false
|
||||
)
|
||||
) {
|
||||
$this->edebug(
|
||||
'SMTP -> get_lines(): retrying stream_select',
|
||||
self::DEBUG_LOWLEVEL
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
ujKpHkhiv0V4kA8yZpxQDcXp84JE
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -12,6 +12,5 @@ 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";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<?php // lint < 8.5.
|
||||
|
||||
/**
|
||||
* Test fixture.
|
||||
*
|
||||
* Used in the `PHPMailer\LocalizationTest` to test that arbitrary code in translation files is disregarded.
|
||||
*
|
||||
* Note: this test fixture uses a syntax (backticks) which has been deprecated in PHP 8.5 and
|
||||
* is slated for removal in PHP 9.0.
|
||||
* For that reason, the file is excluded from the linting check on PHP 8.5 and above.
|
||||
*
|
||||
* @phpcs:disable PHPCompatibility.LanguageConstructs.RemovedLanguageConstructs.t_backtickDeprecated
|
||||
*/
|
||||
|
||||
$PHPMAILER_LANG['extension_missing'] = 'Confirming that test fixture was loaded correctly (yz).';
|
||||
$PHPMAILER_LANG['encoding'] = `ls -l`;
|
||||
|
|
@ -36,7 +36,7 @@ final class OAuthTest extends TestCase
|
|||
$PHPMailer = new PHPMailer(true);
|
||||
$reflection = new \ReflectionClass($PHPMailer);
|
||||
$property = $reflection->getProperty('oauth');
|
||||
$property->setAccessible(true);
|
||||
(\PHP_VERSION_ID < 80100) && $property->setAccessible(true);
|
||||
$property->setValue($PHPMailer, true);
|
||||
self::assertTrue($PHPMailer->getOAuth(), 'Initial value of oauth property is not true');
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\SendTestCase;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use PHPMailer\Test\TestCase;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@ final class FileIsAccessibleTest extends TestCase
|
|||
public function testFileIsAccessible($input, $expected)
|
||||
{
|
||||
$reflMethod = new ReflectionMethod(PHPMailer::class, 'fileIsAccessible');
|
||||
$reflMethod->setAccessible(true);
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(true);
|
||||
$result = $reflMethod->invoke(null, $input);
|
||||
$reflMethod->setAccessible(false);
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(false);
|
||||
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
|
@ -91,9 +91,9 @@ final class FileIsAccessibleTest extends TestCase
|
|||
chmod($file, octdec('0'));
|
||||
|
||||
$reflMethod = new ReflectionMethod(PHPMailer::class, 'fileIsAccessible');
|
||||
$reflMethod->setAccessible(true);
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(true);
|
||||
$result = $reflMethod->invoke(null, $file);
|
||||
$reflMethod->setAccessible(false);
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(false);
|
||||
|
||||
// Reset to the default for git files before running assertions.
|
||||
chmod($file, octdec('644'));
|
||||
|
|
|
|||
|
|
@ -56,6 +56,46 @@ final class HasLineLongerThanMaxTest extends PreSendTestCase
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test constructing a SMIME signed message that contains lines that are too long for RFC compliance.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::hasLineLongerThanMax
|
||||
*/
|
||||
public function testLongBodySmime()
|
||||
{
|
||||
$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->sign(
|
||||
__DIR__ . '/../Fixtures/HasLineLongerThanMaxTest/cert.pem',
|
||||
__DIR__ . '/../Fixtures/HasLineLongerThanMaxTest/key.pem',
|
||||
null
|
||||
);
|
||||
$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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ final class IsPermittedPathTest extends TestCase
|
|||
public function testIsPermittedPath($input, $expected)
|
||||
{
|
||||
$reflMethod = new ReflectionMethod(PHPMailer::class, 'isPermittedPath');
|
||||
$reflMethod->setAccessible(true);
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(true);
|
||||
$result = $reflMethod->invoke(null, $input);
|
||||
$reflMethod->setAccessible(false);
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(false);
|
||||
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace PHPMailer\Test\PHPMailer;
|
|||
|
||||
use ReflectionMethod;
|
||||
use PHPMailer\Test\TestCase;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
|
||||
/**
|
||||
* Test localized error message functionality.
|
||||
|
|
@ -305,13 +306,6 @@ final class LocalizationTest extends TestCase
|
|||
'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: ',
|
||||
|
|
@ -327,6 +321,37 @@ final class LocalizationTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that arbitrary code in a language file does not get executed.
|
||||
*/
|
||||
public function testSetLanguageDoesNotExecuteCodeWithBackticksInLangFile()
|
||||
{
|
||||
$result = $this->Mail->setLanguage(
|
||||
'yz', // 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 (yz).',
|
||||
$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('encoding', $lang, 'The "encoding" translation key was not found');
|
||||
self::assertSame(
|
||||
'Unknown encoding: ',
|
||||
$lang['encoding'],
|
||||
'The "encoding" translation is not as expected'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that text strings passed in from a language file for arbitrary keys do not get processed.
|
||||
*/
|
||||
|
|
@ -419,13 +444,13 @@ final class LocalizationTest extends TestCase
|
|||
public function testLang($input, $expected, $langCode = null)
|
||||
{
|
||||
if (isset($langCode)) {
|
||||
$this->Mail->setLanguage($langCode);
|
||||
PHPMailer::setLanguage($langCode);
|
||||
}
|
||||
|
||||
$reflMethod = new ReflectionMethod($this->Mail, 'lang');
|
||||
$reflMethod->setAccessible(true);
|
||||
$result = $reflMethod->invoke($this->Mail, $input);
|
||||
$reflMethod->setAccessible(false);
|
||||
$reflMethod = new ReflectionMethod(PHPMailer::class, 'lang');
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(true);
|
||||
$result = $reflMethod->invoke(null, $input);
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(false);
|
||||
|
||||
self::assertSame($expected, $result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,23 @@ use PHPMailer\Test\SendTestCase;
|
|||
*/
|
||||
final class MailTransportTest extends SendTestCase
|
||||
{
|
||||
/** @var string */
|
||||
private $originalSendmailFrom = '';
|
||||
|
||||
protected function set_up()
|
||||
{
|
||||
parent::set_up();
|
||||
|
||||
$from = ini_get('sendmail_from');
|
||||
$this->originalSendmailFrom = $from === false ? '' : $from;
|
||||
}
|
||||
|
||||
protected function tear_down()
|
||||
{
|
||||
ini_set('sendmail_from', $this->originalSendmailFrom);
|
||||
parent::tear_down();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sending using SendMail.
|
||||
*
|
||||
|
|
@ -65,12 +82,6 @@ final class MailTransportTest extends SendTestCase
|
|||
*/
|
||||
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()';
|
||||
|
|
@ -105,4 +116,146 @@ final class MailTransportTest extends SendTestCase
|
|||
$msg = $this->Mail->getSentMIMEMessage();
|
||||
self::assertStringNotContainsString("\r\n\r\nMIME-Version:", $msg, 'Incorrect MIME headers');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sending using PHP mail() function with Sender address
|
||||
* and explicit sendmail_from ini set.
|
||||
* Test running required with:
|
||||
* php -d sendmail_path="/usr/sbin/sendmail -t -i -frpath@example.org" ./vendor/bin/phpunit
|
||||
*
|
||||
* @group sendmailparams
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::isMail
|
||||
*/
|
||||
public function testMailSendWithSendmailParams()
|
||||
{
|
||||
$sender = 'rpath@example.org';
|
||||
|
||||
if (strpos(ini_get('sendmail_path'), $sender) === false) {
|
||||
self::markTestSkipped('Custom Sendmail php.ini not available');
|
||||
}
|
||||
|
||||
$this->Mail->Body = 'Sending via mail()';
|
||||
$this->buildBody();
|
||||
$this->Mail->Subject = $this->Mail->Subject . ': mail()';
|
||||
$this->Mail->clearAddresses();
|
||||
$this->setAddress('testmailsend@example.com', 'totest');
|
||||
|
||||
ini_set('sendmail_from', $sender);
|
||||
$this->Mail->createHeader();
|
||||
$this->Mail->isMail();
|
||||
|
||||
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sending using SendMail with Sender address
|
||||
* and explicit sendmail_from ini set.
|
||||
* Test running required with:
|
||||
* php -d sendmail_path="/usr/sbin/sendmail -t -i -frpath@example.org" ./vendor/bin/phpunit
|
||||
*
|
||||
* @group sendmailparams
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::isSendmail
|
||||
*/
|
||||
public function testSendmailSendWithSendmailParams()
|
||||
{
|
||||
$sender = 'rpath@example.org';
|
||||
|
||||
if (strpos(ini_get('sendmail_path'), $sender) === false) {
|
||||
self::markTestSkipped('Custom Sendmail php.ini not available');
|
||||
}
|
||||
|
||||
$this->Mail->Body = 'Sending via sendmail';
|
||||
$this->buildBody();
|
||||
$subject = $this->Mail->Subject;
|
||||
|
||||
$this->Mail->Subject = $subject . ': sendmail';
|
||||
ini_set('sendmail_from', $sender);
|
||||
$this->Mail->isSendmail();
|
||||
|
||||
self::assertTrue($this->Mail->send(), $this->Mail->ErrorInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test parsing of sendmail path and with certain parameters.
|
||||
*
|
||||
* @group sendmailparams
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::parseSendmailPath
|
||||
* @dataProvider sendmailPathProvider
|
||||
*
|
||||
* @param string $sendmailPath The sendmail path to parse.
|
||||
* @param string $expectedCommand The expected command after parsing.
|
||||
* @param string $expectedSender The expected Sender (-f parameter) after parsing.
|
||||
*/
|
||||
public function testParseSendmailPath($sendmailPath, $expectedCommand, $expectedSender)
|
||||
{
|
||||
$mailer = $this->Mail;
|
||||
|
||||
$parseSendmailPath = \Closure::bind(
|
||||
function ($path) {
|
||||
return $this->{'parseSendmailPath'}($path);
|
||||
},
|
||||
$mailer,
|
||||
\PHPMailer\PHPMailer\PHPMailer::class
|
||||
);
|
||||
$command = $parseSendmailPath($sendmailPath);
|
||||
|
||||
self::assertSame($expectedCommand, $command, 'Sendmail command not parsed correctly');
|
||||
self::assertSame($expectedSender, $mailer->Sender, 'Sender property not set correctly');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testParseSendmailPath.
|
||||
*
|
||||
* @return array{
|
||||
* 0: string, // The sendmail path to parse.
|
||||
* 1: string, // The expected command after parsing.
|
||||
* 2: string // The expected Sender (-f parameter) after parsing.
|
||||
* }
|
||||
*/
|
||||
|
||||
public function sendmailPathProvider()
|
||||
{
|
||||
return [
|
||||
'path only' => [
|
||||
'/usr/sbin/sendmail',
|
||||
'/usr/sbin/sendmail',
|
||||
''
|
||||
],
|
||||
'with i and t' => [
|
||||
'/usr/sbin/sendmail -i -t',
|
||||
'/usr/sbin/sendmail',
|
||||
''
|
||||
],
|
||||
'with f concatenated' => [
|
||||
'/usr/sbin/sendmail -frpath@example.org -i',
|
||||
'/usr/sbin/sendmail',
|
||||
'rpath@example.org'
|
||||
],
|
||||
'with f separated' => [
|
||||
'/usr/sbin/sendmail -f rpath@example.org -t',
|
||||
'/usr/sbin/sendmail',
|
||||
'rpath@example.org',
|
||||
],
|
||||
'with extra flags preserved' => [
|
||||
'/opt/sendmail -x -y -fuser@example.org',
|
||||
'/opt/sendmail -x -y',
|
||||
'user@example.org',
|
||||
],
|
||||
"extra flags with values preserved" => [
|
||||
'/opt/sendmail -X /path/to/logfile -fuser@example.org',
|
||||
'/opt/sendmail -X /path/to/logfile',
|
||||
'user@example.org',
|
||||
],
|
||||
"extra flags concatenated preserved" => [
|
||||
'/opt/sendmail -X/path/to/logfile -t -i',
|
||||
'/opt/sendmail -X/path/to/logfile',
|
||||
'',
|
||||
],
|
||||
"option values with regular parameters" => [
|
||||
'/opt/sendmail -oi -t',
|
||||
'/opt/sendmail',
|
||||
'',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ EOT;
|
|||
$PHPMailer = new PHPMailer();
|
||||
$reflection = new \ReflectionClass($PHPMailer);
|
||||
$property = $reflection->getProperty('message_type');
|
||||
$property->setAccessible(true);
|
||||
(\PHP_VERSION_ID < 80100) && $property->setAccessible(true);
|
||||
$property->setValue($PHPMailer, 'inline');
|
||||
self::assertIsString($PHPMailer->createBody());
|
||||
|
||||
|
|
@ -278,6 +278,8 @@ EOT;
|
|||
|
||||
/**
|
||||
* Send a message containing ISO-8859-1 text.
|
||||
*
|
||||
* @requires extension mbstring
|
||||
*/
|
||||
public function testHtmlIso8859()
|
||||
{
|
||||
|
|
@ -595,6 +597,7 @@ EOT;
|
|||
*/
|
||||
public function testEmbeddedImage()
|
||||
{
|
||||
$this->Mail->From = '';
|
||||
$this->Mail->msgHTML('<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
|
@ -613,6 +616,32 @@ EOT;
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* An embedded attachment test with custom cid domain.
|
||||
*/
|
||||
public function testEmbeddedImageCustomCidDomain()
|
||||
{
|
||||
$result = $this->Mail->setFrom('test@example.com');
|
||||
self::assertTrue($result, 'setFrom failed');
|
||||
|
||||
$this->Mail->msgHTML('<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>E-Mail Inline Image Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<p><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></p>
|
||||
</body>
|
||||
</html>', '', false);
|
||||
$this->Mail->preSend();
|
||||
self::assertStringContainsString(
|
||||
'Content-ID: <bb229a48bee31f5d54ca12dc9bd960c6@example.com>',
|
||||
$this->Mail->getSentMIMEMessage(),
|
||||
'Embedded image header encoding incorrect.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* An embedded attachment test.
|
||||
*/
|
||||
|
|
@ -1121,7 +1150,7 @@ EOT;
|
|||
public function testConvertEncoding()
|
||||
{
|
||||
if (!PHPMailer::idnSupported()) {
|
||||
self::markTestSkipped('intl and/or mbstring extensions are not available');
|
||||
self::markTestSkipped('Both intl and mbstring extensions are required.');
|
||||
}
|
||||
|
||||
$this->Mail->clearAllRecipients();
|
||||
|
|
@ -1166,7 +1195,7 @@ EOT;
|
|||
public function testDuplicateIDNRemoved()
|
||||
{
|
||||
if (!PHPMailer::idnSupported()) {
|
||||
self::markTestSkipped('intl and/or mbstring extensions are not available');
|
||||
self::markTestSkipped('Both intl and mbstring extensions are required.');
|
||||
}
|
||||
|
||||
$this->Mail->clearAllRecipients();
|
||||
|
|
@ -1243,7 +1272,7 @@ EOT;
|
|||
|
||||
//Beyond this point we need UTF-8 support
|
||||
if (!PHPMailer::idnSupported()) {
|
||||
self::markTestSkipped('intl and/or mbstring extensions are not available');
|
||||
self::markTestSkipped('Both intl and mbstring extensions are required.');
|
||||
}
|
||||
|
||||
//Using a punycodable domain does not need SMTPUTF8
|
||||
|
|
|
|||
|
|
@ -14,147 +14,14 @@
|
|||
namespace PHPMailer\Test\PHPMailer;
|
||||
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use ReflectionMethod;
|
||||
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
|
||||
|
||||
/**
|
||||
* Test RFC822 address splitting.
|
||||
*
|
||||
* @todo Additional tests need to be added to verify the correct handling of inputs which
|
||||
* include a different encoding than UTF8 or even mixed encoding. For more information
|
||||
* on what these test cases should look like and should test, please see
|
||||
* {@link https://github.com/PHPMailer/PHPMailer/pull/2449} for context.
|
||||
*
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::parseAddresses
|
||||
*/
|
||||
final class ParseAddressesTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Test RFC822 address splitting using the PHPMailer native implementation
|
||||
* with the Mbstring extension available.
|
||||
*
|
||||
* @requires extension mbstring
|
||||
*
|
||||
* @dataProvider dataAddressSplitting
|
||||
*
|
||||
* @param string $addrstr The address list string.
|
||||
* @param array $expected The expected function output.
|
||||
* @param string $charset Optional. The charset to use.
|
||||
*/
|
||||
public function testAddressSplittingNative($addrstr, $expected, $charset = null)
|
||||
{
|
||||
if (isset($charset)) {
|
||||
$parsed = PHPMailer::parseAddresses($addrstr, false, $charset);
|
||||
} else {
|
||||
$parsed = PHPMailer::parseAddresses($addrstr, false);
|
||||
}
|
||||
|
||||
$expectedOutput = $expected['default'];
|
||||
if (empty($expected['native+mbstring']) === false) {
|
||||
$expectedOutput = $expected['native+mbstring'];
|
||||
} elseif (empty($expected['native']) === false) {
|
||||
$expectedOutput = $expected['native'];
|
||||
}
|
||||
|
||||
$this->verifyExpectations($parsed, $expectedOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RFC822 address splitting using the IMAP implementation
|
||||
* with the Mbstring extension available.
|
||||
*
|
||||
* @requires extension imap
|
||||
* @requires extension mbstring
|
||||
*
|
||||
* @dataProvider dataAddressSplitting
|
||||
*
|
||||
* @param string $addrstr The address list string.
|
||||
* @param array $expected The expected function output.
|
||||
* @param string $charset Optional. The charset to use.
|
||||
*/
|
||||
public function testAddressSplittingImap($addrstr, $expected, $charset = null)
|
||||
{
|
||||
if (isset($charset)) {
|
||||
$parsed = PHPMailer::parseAddresses($addrstr, true, $charset);
|
||||
} else {
|
||||
$parsed = PHPMailer::parseAddresses($addrstr, true);
|
||||
}
|
||||
|
||||
$expectedOutput = $expected['default'];
|
||||
if (empty($expected['imap+mbstring']) === false) {
|
||||
$expectedOutput = $expected['imap+mbstring'];
|
||||
} elseif (empty($expected['imap']) === false) {
|
||||
$expectedOutput = $expected['imap'];
|
||||
}
|
||||
|
||||
$this->verifyExpectations($parsed, $expectedOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RFC822 address splitting using the PHPMailer native implementation
|
||||
* without the Mbstring extension.
|
||||
*
|
||||
* @dataProvider dataAddressSplitting
|
||||
*
|
||||
* @param string $addrstr The address list string.
|
||||
* @param array $expected The expected function output.
|
||||
* @param string $charset Optional. The charset to use.
|
||||
*/
|
||||
public function testAddressSplittingNativeNoMbstring($addrstr, $expected, $charset = null)
|
||||
{
|
||||
if (extension_loaded('mbstring')) {
|
||||
self::markTestSkipped('Test requires MbString *not* to be available');
|
||||
}
|
||||
|
||||
if (isset($charset)) {
|
||||
$parsed = PHPMailer::parseAddresses($addrstr, false, $charset);
|
||||
} else {
|
||||
$parsed = PHPMailer::parseAddresses($addrstr, false);
|
||||
}
|
||||
|
||||
$expectedOutput = $expected['default'];
|
||||
if (empty($expected['native--mbstring']) === false) {
|
||||
$expectedOutput = $expected['native--mbstring'];
|
||||
} elseif (empty($expected['native']) === false) {
|
||||
$expectedOutput = $expected['native'];
|
||||
}
|
||||
|
||||
$this->verifyExpectations($parsed, $expectedOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RFC822 address splitting using the IMAP implementation
|
||||
* without the Mbstring extension.
|
||||
*
|
||||
* @requires extension imap
|
||||
*
|
||||
* @dataProvider dataAddressSplitting
|
||||
*
|
||||
* @param string $addrstr The address list string.
|
||||
* @param array $expected The expected function output.
|
||||
* @param string $charset Optional. The charset to use.
|
||||
*/
|
||||
public function testAddressSplittingImapNoMbstring($addrstr, $expected, $charset = null)
|
||||
{
|
||||
if (extension_loaded('mbstring')) {
|
||||
self::markTestSkipped('Test requires MbString *not* to be available');
|
||||
}
|
||||
|
||||
if (isset($charset)) {
|
||||
$parsed = PHPMailer::parseAddresses($addrstr, true, $charset);
|
||||
} else {
|
||||
$parsed = PHPMailer::parseAddresses($addrstr, true);
|
||||
}
|
||||
|
||||
$expectedOutput = $expected['default'];
|
||||
if (empty($expected['imap--mbstring']) === false) {
|
||||
$expectedOutput = $expected['imap--mbstring'];
|
||||
} elseif (empty($expected['imap']) === false) {
|
||||
$expectedOutput = $expected['imap'];
|
||||
}
|
||||
|
||||
$this->verifyExpectations($parsed, $expectedOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the expectations.
|
||||
*
|
||||
|
|
@ -173,19 +40,135 @@ final class ParseAddressesTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RFC822 address splitting using the native implementation
|
||||
*
|
||||
* @dataProvider dataAddressSplittingNative
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::parseSimplerAddresses
|
||||
*
|
||||
* @param string $addrstr The address list string.
|
||||
* @param array $expected The expected function output.
|
||||
* @param string $charset Optional.The charset to use.
|
||||
*/
|
||||
public function testAddressSplittingNative($addrstr, $expected, $charset = PHPMailer::CHARSET_ISO88591)
|
||||
{
|
||||
set_error_handler(static function ($errno, $errstr) {
|
||||
throw new \Exception($errstr, $errno);
|
||||
}, E_USER_NOTICE);
|
||||
|
||||
try {
|
||||
$this->expectException(\Exception::class);
|
||||
|
||||
$reflMethod = new ReflectionMethod(PHPMailer::class, 'parseSimplerAddresses');
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(true);
|
||||
$parsed = $reflMethod->invoke(null, $addrstr, $charset);
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(false);
|
||||
$this->verifyExpectations($parsed, $expected);
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testAddressSplittingNative.
|
||||
*
|
||||
* @return array
|
||||
* addrstr: string,
|
||||
* expected: array{name: string, address: string}[]
|
||||
* charset: string
|
||||
*/
|
||||
public function dataAddressSplittingNative()
|
||||
{
|
||||
return [
|
||||
'Valid address: single address without name' => [
|
||||
'addrstr' => 'joe@example.com',
|
||||
'expected' => [
|
||||
['name' => '', 'address' => 'joe@example.com'],
|
||||
],
|
||||
],
|
||||
'Valid address: two addresses with names' => [
|
||||
'addrstr' => 'Joe User <joe@example.com>, Jill User <jill@example.net>',
|
||||
'expected' => [
|
||||
['name' => 'Joe User', 'address' => 'joe@example.com'],
|
||||
['name' => 'Jill User', 'address' => 'jill@example.net'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if email addresses are parsed and split into a name and address.
|
||||
*
|
||||
* @dataProvider dataParseEmailString
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::parseEmailString
|
||||
* @param mixed $addrstr
|
||||
* @param mixed $expected
|
||||
*/
|
||||
public function testParseEmailString($addrstr, $expected)
|
||||
{
|
||||
$reflMethod = new ReflectionMethod(PHPMailer::class, 'parseEmailString');
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(true);
|
||||
$parsed = $reflMethod->invoke(null, $addrstr);
|
||||
(\PHP_VERSION_ID < 80100) && $reflMethod->setAccessible(false);
|
||||
$this->assertEquals($parsed, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for testParseEmailString.
|
||||
*
|
||||
* @return array The array is expected to have an `addrstr` and an `expected` key.
|
||||
*/
|
||||
public function dataParseEmailString()
|
||||
{
|
||||
return [
|
||||
'Valid address: simple address' => [
|
||||
'addrstr' => 'Joe User <joe@example.com>',
|
||||
'expected' => ['name' => 'Joe User', 'email' => 'joe@example.com'],
|
||||
],
|
||||
'Valid address: simple address with double quotes' => [
|
||||
'addrstr' => '"Joe User" <joe@example.com>',
|
||||
'expected' => ['name' => 'Joe User', 'email' => 'joe@example.com'],
|
||||
],
|
||||
'Valid address: simple address with single quotes' => [
|
||||
'addrstr' => '\'Joe User\' <joe@example.com>',
|
||||
'expected' => ['name' => 'Joe User', 'email' => 'joe@example.com'],
|
||||
],
|
||||
'Valid address: complex address with single quotes' => [
|
||||
'addrstr' => '\'Joe<User\' <joe@example.com>',
|
||||
'expected' => ['name' => 'Joe<User', 'email' => 'joe@example.com'],
|
||||
],
|
||||
'Valid address: complex address with triangle bracket' => [
|
||||
'addrstr' => '"test<stage" <test@example.com>',
|
||||
'expected' => ['name' => 'test<stage', 'email' => 'test@example.com'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test RFC822 address splitting using the PHPMailer implementation
|
||||
*
|
||||
* @dataProvider dataAddressSplitting
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::parseAddresses
|
||||
*
|
||||
* @requires extension imap
|
||||
* @requires extension mbstring
|
||||
*
|
||||
* @param string $addrstr The address list string.
|
||||
* @param array $expected The expected function output.
|
||||
* @param string $charset Optional. The charset to use.
|
||||
*/
|
||||
public function testAddressSplitting($addrstr, $expected)
|
||||
{
|
||||
$parsed = PHPMailer::parseAddresses($addrstr, null, PHPMailer::CHARSET_UTF8);
|
||||
|
||||
$this->verifyExpectations($parsed, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider.
|
||||
*
|
||||
* @return array The array is expected to have an `addrstr` and an `expected` key.
|
||||
* The `expected` key should - as a minimum - have a `default` key.
|
||||
* Optionally, the following extra keys are supported:
|
||||
* - `native` Expected output from the native implementation with or without Mbstring.
|
||||
* - `native+mbstring` Expected output from the native implementation with Mbstring.
|
||||
* - `native--mbstring` Expected output from the native implementation without Mbstring.
|
||||
* - `imap` Expected output from the IMAP implementation with or without Mbstring.
|
||||
* - `imap+mbstring` Expected output from the IMAP implementation with Mbstring.
|
||||
* - `imap--mbstring` Expected output from the IMAP implementation without Mbstring.
|
||||
* Also optionally, an additional `charset` key can be passed,
|
||||
* The `expected` key should - as a minimum.
|
||||
*/
|
||||
public function dataAddressSplitting()
|
||||
{
|
||||
|
|
@ -194,54 +177,39 @@ final class ParseAddressesTest extends TestCase
|
|||
'Valid address: single address without name' => [
|
||||
'addrstr' => 'joe@example.com',
|
||||
'expected' => [
|
||||
'default' => [
|
||||
['name' => '', 'address' => 'joe@example.com'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'Valid address: single address with name' => [
|
||||
'addrstr' => 'Joe User <joe@example.com>',
|
||||
'expected' => [
|
||||
'default' => [
|
||||
['name' => 'Joe User', 'address' => 'joe@example.com'],
|
||||
],
|
||||
['name' => 'Joe User', 'address' => 'joe@example.com'],
|
||||
],
|
||||
],
|
||||
'Valid address: single RFC2047 address folded onto multiple lines' => [
|
||||
'addrstr' => "=?iso-8859-1?B?QWJjZGVmZ2ggSWprbG3DsSDmnIPorbDlrqTpoJDntITn?=\r\n" .
|
||||
' =?iso-8859-1?B?s7vntbE=?= <xyz@example.com>',
|
||||
'addrstr' => "=?ISO-8859-1?Q?J=F6rg?=\r\n" .
|
||||
' =?ISO-8859-1?Q?_M=FCller?= <xyz@example.com>',
|
||||
'expected' => [
|
||||
'default' => [
|
||||
['name' => 'Abcdefgh Ijklmñ 會議室預約系統', 'address' => 'xyz@example.com'],
|
||||
],
|
||||
['name' => 'Jörg Müller', 'address' => 'xyz@example.com'],
|
||||
],
|
||||
],
|
||||
'Valid address: single RFC2047 address with space encoded as _' => [
|
||||
'addrstr' => '=?iso-8859-1?Q?Abcdefgh_ijklm=C3=B1?= <xyz@example.com>',
|
||||
'addrstr' => '=?iso-8859-1?Q?Abcdefgh_ijklm=F1?= <xyz@example.com>',
|
||||
'expected' => [
|
||||
'default' => [
|
||||
['name' => 'Abcdefgh ijklmñ', 'address' => 'xyz@example.com'],
|
||||
],
|
||||
['name' => 'Abcdefgh ijklmñ', 'address' => 'xyz@example.com'],
|
||||
],
|
||||
],
|
||||
'Valid address: single address, quotes within name' => [
|
||||
'addrstr' => 'Tim "The Book" O\'Reilly <foo@example.com>',
|
||||
'expected' => [
|
||||
'default' => [
|
||||
['name' => 'Tim "The Book" O\'Reilly', 'address' => 'foo@example.com'],
|
||||
],
|
||||
'imap' => [
|
||||
['name' => 'Tim The Book O\'Reilly', 'address' => 'foo@example.com'],
|
||||
],
|
||||
['name' => 'Tim The Book O\'Reilly', 'address' => 'foo@example.com'],
|
||||
],
|
||||
],
|
||||
'Valid address: two addresses with names' => [
|
||||
'addrstr' => 'Joe User <joe@example.com>, Jill User <jill@example.net>',
|
||||
'expected' => [
|
||||
'default' => [
|
||||
['name' => 'Joe User', 'address' => 'joe@example.com'],
|
||||
['name' => 'Jill User', 'address' => 'jill@example.net'],
|
||||
],
|
||||
['name' => 'Joe User', 'address' => 'joe@example.com'],
|
||||
['name' => 'Jill User', 'address' => 'jill@example.net'],
|
||||
],
|
||||
],
|
||||
'Valid address: two addresses with names, one without' => [
|
||||
|
|
@ -249,106 +217,104 @@ final class ParseAddressesTest extends TestCase
|
|||
. 'Jill User <jill@example.net>,'
|
||||
. 'frank@example.com,',
|
||||
'expected' => [
|
||||
'default' => [
|
||||
['name' => 'Joe User', 'address' => 'joe@example.com'],
|
||||
['name' => 'Jill User', 'address' => 'jill@example.net'],
|
||||
['name' => '', 'address' => 'frank@example.com'],
|
||||
],
|
||||
['name' => 'Joe User', 'address' => 'joe@example.com'],
|
||||
['name' => 'Jill User', 'address' => 'jill@example.net'],
|
||||
['name' => '', 'address' => 'frank@example.com'],
|
||||
],
|
||||
],
|
||||
'Valid address: multiple address, various formats, including one utf8-encoded name' => [
|
||||
'Valid address: multiple address, various formats, including one utf8-encoded names' => [
|
||||
'addrstr' => 'joe@example.com, <me@example.com>, Joe Doe <doe@example.com>,' .
|
||||
' "John O\'Groats" <johnog@example.net>,' .
|
||||
' =?utf-8?B?0J3QsNC30LLQsNC90LjQtSDRgtC10YHRgtCw?= <encoded@example.org>',
|
||||
' =?utf-8?B?0J3QsNC30LLQsNC90LjQtSDRgtC10YHRgtCw?= <encoded@example.org>,' .
|
||||
' =?UTF-8?Q?Welcome_to_our_caf=C3=A9!?= =?ISO-8859-1?Q?_Willkommen_in_unserem_Caf=E9!?=' .
|
||||
' =?KOI8-R?Q?_=F0=D2=C9=D7=C5=D4_=D7_=CE=C1=DB=C5_=CB=C1=C6=C5!?= <encoded3@example.org>',
|
||||
'expected' => [
|
||||
'default' => [
|
||||
[
|
||||
'name' => '',
|
||||
'address' => 'joe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => '',
|
||||
'address' => 'me@example.com',
|
||||
],
|
||||
[
|
||||
'name' => 'Joe Doe',
|
||||
'address' => 'doe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => "John O'Groats",
|
||||
'address' => 'johnog@example.net',
|
||||
],
|
||||
[
|
||||
'name' => 'Название теста',
|
||||
'address' => 'encoded@example.org',
|
||||
],
|
||||
['name' => '', 'address' => 'joe@example.com'],
|
||||
['name' => '', 'address' => 'me@example.com'],
|
||||
['name' => 'Joe Doe', 'address' => 'doe@example.com'],
|
||||
['name' => "John O'Groats", 'address' => 'johnog@example.net'],
|
||||
['name' => 'Название теста', 'address' => 'encoded@example.org'],
|
||||
[
|
||||
'name' => 'Welcome to our café! Willkommen in unserem Café! Привет в наше кафе!',
|
||||
'address' => 'encoded3@example.org'
|
||||
],
|
||||
'native--mbstring' => [
|
||||
[
|
||||
'name' => '',
|
||||
'address' => 'joe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => '',
|
||||
'address' => 'me@example.com',
|
||||
],
|
||||
[
|
||||
'name' => 'Joe Doe',
|
||||
'address' => 'doe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => "John O'Groats",
|
||||
'address' => 'johnog@example.net',
|
||||
],
|
||||
[
|
||||
'name' => '=?utf-8?B?0J3QsNC30LLQsNC90LjQtSDRgtC10YHRgtCw?=',
|
||||
'address' => 'encoded@example.org',
|
||||
],
|
||||
],
|
||||
'imap--mbstring' => [
|
||||
[
|
||||
'name' => '',
|
||||
'address' => 'joe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => '',
|
||||
'address' => 'me@example.com',
|
||||
],
|
||||
[
|
||||
'name' => 'Joe Doe',
|
||||
'address' => 'doe@example.com',
|
||||
],
|
||||
[
|
||||
'name' => "John O'Groats",
|
||||
'address' => 'johnog@example.net',
|
||||
],
|
||||
[
|
||||
'name' => '=?utf-8?B?0J3QsNC30LLQsNC90LjQtSDRgtC10YHRgtCw?=',
|
||||
'address' => 'encoded@example.org',
|
||||
],
|
||||
],
|
||||
],
|
||||
'charset' => PHPMailer::CHARSET_UTF8,
|
||||
]
|
||||
],
|
||||
|
||||
// Test cases with invalid addresses.
|
||||
'Invalid address: single address, incomplete email' => [
|
||||
'addrstr' => 'Jill User <doug@>',
|
||||
'expected' => [
|
||||
'default' => [],
|
||||
],
|
||||
'expected' => [],
|
||||
],
|
||||
'Invalid address: single address, invalid characters in email' => [
|
||||
'addrstr' => 'Joe User <{^c\@**Dog^}@cartoon.com>',
|
||||
'expected' => [
|
||||
'default' => [],
|
||||
],
|
||||
'expected' => [],
|
||||
],
|
||||
'Invalid address: multiple addresses, invalid periods' => [
|
||||
'addrstr' => 'Joe User <joe@example.com.>, Jill User <jill.@example.net>',
|
||||
'expected' => [
|
||||
'default' => [],
|
||||
],
|
||||
'expected' => [],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test decodeHeader using the PHPMailer
|
||||
* with the Mbstring extension available.
|
||||
*
|
||||
* @dataProvider dataDecodeHeader
|
||||
* @covers \PHPMailer\PHPMailer\PHPMailer::decodeHeader
|
||||
*
|
||||
* @requires extension mbstring
|
||||
*
|
||||
* @param string $addrstr The header string.
|
||||
* @param array $expected The expected function output.
|
||||
*/
|
||||
public function testDecodeHeader($str, $expected)
|
||||
{
|
||||
$parsed = PHPMailer::decodeHeader($str, PHPMailer::CHARSET_UTF8);
|
||||
|
||||
$this->assertEquals($parsed, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for decodeHeader.
|
||||
*
|
||||
* @return array The array is expected to have an `addrstr` and an `expected` key.
|
||||
* The `expected` key should - as a minimum - have a single value.
|
||||
*/
|
||||
public function dataDecodeHeader()
|
||||
{
|
||||
return [
|
||||
'UTF-8 B-encoded' => [
|
||||
'name' => '=?utf-8?B?0J3QsNC30LLQsNC90LjQtSDRgtC10YHRgtCw?=',
|
||||
'expected' => 'Название теста',
|
||||
],
|
||||
'UTF-8 Q-encoded' => [
|
||||
'name' => '=?UTF-8?Q?=D0=9D=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8?=' .
|
||||
' =?UTF-8?Q?=D0=B5_=D1=82=D0=B5=D1=81=D1=82=D0=B0?=',
|
||||
'expected' => 'Название теста',
|
||||
],
|
||||
'UTF-8 Q-encoded with multiple wrong labels and space encoded as _' => [
|
||||
'name' => '=?UTF-8?Q?Welcome_to_our_caf=C3=A9!?= =?ISO-8859-1?Q?_Willkommen_in_unserem_Caf=E9!?=' .
|
||||
' =?KOI8-R?Q?_=F0=D2=C9=D7=C5=D4_=D7_=CE=C1=DB=C5_=CB=C1=C6=C5!?=',
|
||||
'expected' => 'Welcome to our café! Willkommen in unserem Café! Привет в наше кафе!',
|
||||
],
|
||||
'ISO-8859-1 Q-encoded' => [
|
||||
'name' => '=?ISO-8859-1?Q?Willkommen_in_unserem_Caf=E9!?=',
|
||||
'expected' => 'Willkommen in unserem Café!',
|
||||
],
|
||||
'Valid but wrongly labeled UTF-8 as ISO-8859-1' => [
|
||||
'name' => '=?iso-8859-1?B?5pyD6K2w5a6k?=',
|
||||
'expected' => "æ\xC2\x9C\xC2\x83è°å®¤",
|
||||
],
|
||||
'SMTPUTF8 encoded' => [
|
||||
'name' => '=?UTF-8?B?SGVsbG8g8J+MjSDkuJbnlYwgY2Fmw6k=?=',
|
||||
'expected' => 'Hello 🌍 世界 café',
|
||||
],
|
||||
'Multiple lines' => [
|
||||
'name' => '=?UTF-8?B?0YLQtdGB0YIg0YLQtdGB0YIg0YLQtdGB0YIg0YLQtdGB0YIg0YLQtdGB0YIg?='
|
||||
. "\n =?UTF-8?B?0YLQtdGB0YIg0YLQtdGB0YI=?=",
|
||||
'expected' => 'тест тест тест тест тест тест тест',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ final class ReplyToGetSetClearTest extends PreSendTestCase
|
|||
|
||||
if (isset($expected) === false) {
|
||||
$expected = [
|
||||
'key' => $address,
|
||||
'address' => $address,
|
||||
'name' => $name,
|
||||
];
|
||||
|
|
@ -62,25 +61,19 @@ final class ReplyToGetSetClearTest extends PreSendTestCase
|
|||
self::assertIsArray($retrieved, 'ReplyTo property is not an array');
|
||||
self::assertCount(1, $retrieved, 'ReplyTo property does not contain exactly one address');
|
||||
|
||||
$key = $expected['key'];
|
||||
self::assertArrayHasKey(
|
||||
$key,
|
||||
$retrieved,
|
||||
'ReplyTo property does not contain an entry with this address as the key'
|
||||
);
|
||||
self::assertCount(
|
||||
2,
|
||||
$retrieved[$key],
|
||||
$retrieved[0],
|
||||
'ReplyTo array for this address does not contain exactly two array items'
|
||||
);
|
||||
self::assertSame(
|
||||
$expected['address'],
|
||||
$retrieved[$key][0],
|
||||
$retrieved[0][0],
|
||||
'ReplyTo array for this address does not contain added address'
|
||||
);
|
||||
self::assertSame(
|
||||
$expected['name'],
|
||||
$retrieved[$key][1],
|
||||
$retrieved[0][1],
|
||||
'ReplyTo array for this address does not contain added name'
|
||||
);
|
||||
}
|
||||
|
|
@ -100,7 +93,6 @@ final class ReplyToGetSetClearTest extends PreSendTestCase
|
|||
'address' => " \tMiXeD@Example.Com \r\n",
|
||||
'name' => null,
|
||||
'expected' => [
|
||||
'key' => 'mixed@example.com',
|
||||
'address' => 'MiXeD@Example.Com',
|
||||
'name' => '',
|
||||
],
|
||||
|
|
@ -113,7 +105,6 @@ final class ReplyToGetSetClearTest extends PreSendTestCase
|
|||
'address' => 'a@example.com',
|
||||
'name' => "\t\t ReplyTo\r\nname ",
|
||||
'expected' => [
|
||||
'key' => 'a@example.com',
|
||||
'address' => 'a@example.com',
|
||||
'name' => 'ReplyToname',
|
||||
],
|
||||
|
|
@ -292,9 +283,11 @@ final class ReplyToGetSetClearTest extends PreSendTestCase
|
|||
|
||||
// Addresses with IDN are returned by get*Addresses() after preSend() call.
|
||||
$domain = $this->Mail->punyencodeAddress($domain);
|
||||
$expected = array('test+replyto' . $domain, '');
|
||||
$retrieved = $this->Mail->getReplyToAddresses();
|
||||
self::assertSame(
|
||||
['test+replyto' . $domain => ['test+replyto' . $domain, '']],
|
||||
$this->Mail->getReplyToAddresses(),
|
||||
$expected,
|
||||
$retrieved[0],
|
||||
'Bad "reply-to" addresses'
|
||||
);
|
||||
}
|
||||
|
|
@ -377,24 +370,24 @@ final class ReplyToGetSetClearTest extends PreSendTestCase
|
|||
self::assertCount(1, $retrieved, 'Stored addresses after preSend() is not 1');
|
||||
|
||||
// Verify that the registered reply-to address is the initially added lowercase punycode one.
|
||||
self::assertArrayHasKey(
|
||||
self::assertSame(
|
||||
$expectedAddress,
|
||||
$retrieved,
|
||||
$retrieved[0][0],
|
||||
'ReplyTo property does not contain an entry with this address as the key'
|
||||
);
|
||||
self::assertCount(
|
||||
2,
|
||||
$retrieved[$expectedAddress],
|
||||
$retrieved[0],
|
||||
'ReplyTo array for this address does not contain exactly two array items'
|
||||
);
|
||||
self::assertSame(
|
||||
$expectedAddress,
|
||||
$retrieved[$expectedAddress][0],
|
||||
$retrieved[0][0],
|
||||
'ReplyTo array for this address does not contain added address'
|
||||
);
|
||||
self::assertSame(
|
||||
'',
|
||||
$retrieved[$expectedAddress][1],
|
||||
$retrieved[0][1],
|
||||
'ReplyTo array for this address does not contain added name'
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ abstract class TestCase extends PolyfillTestCase
|
|||
private $PHPMailerStaticProps = [
|
||||
'LE' => PHPMailer::CRLF,
|
||||
'validator' => 'php',
|
||||
'language' => [],
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue