Compare commits

..

No commits in common. "master" and "v5.2.25" have entirely different histories.

244 changed files with 16599 additions and 20020 deletions

View File

@ -1,21 +0,0 @@
codecov:
notify:
after_n_builds: 2
coverage:
round: nearest
# Status will be green when coverage is between 70 and 100%.
range: "70...100"
status:
project:
default:
threshold: 2%
paths:
- "src"
patch:
default:
threshold: 0%
paths:
- "src"
comment: false

View File

@ -1,15 +0,0 @@
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2

21
.gitattributes vendored
View File

@ -1,17 +1,12 @@
* text=auto
/.codecov.yml export-ignore
/.editorconfig export-ignore
/.gitattributes export-ignore
/.github export-ignore
/.gitignore export-ignore
/.phan export-ignore
/.scrutinizer.yml export-ignore
/changelog.md export-ignore
/docs export-ignore
/examples export-ignore
/phpcs.xml.dist export-ignore
/phpdoc.dist.xml export-ignore
/phpunit.xml.dist export-ignore
/test export-ignore
/UPGRADING.md export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.scrutinizer.yml export-ignore
/.travis.yml export-ignore
/travis.phpunit.xml.dist export-ignore
/SECURITY.md export-ignore
/changelog.md export-ignore
/README.md export-ignore

6
.github/FUNDING.yml vendored
View File

@ -1,6 +0,0 @@
# These are supported funding model platforms
github: Synchro
patreon: marcusbointon
tidelift: "packagist/phpmailer/phpmailer"
custom: https://marcus.bointon.com/donations/

1
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1 @@
Non-security issues and pull requests are no longer being accepted for the legacy PHPMailer 5.2 branch. Migrate to PHPMailer 6.0 (or later) and report your issue there.

View File

@ -1,23 +0,0 @@
---
name: Bug report
about: If you've found a bug in PHPMailer, this is the right place to report it
title: ''
labels: ''
assignees: ''
---
Please check these things before submitting your issue:
- [ ] *Read the error message* you're seeing - it often tells you what is wrong, and may contain useful links & instructions
- [ ] Make sure you're using the latest version of PHPMailer
- [ ] Check that your problem is not dealt with in [the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting), especially if you're having problems connecting to Gmail or GoDaddy
- [ ] Include sufficient code to reproduce your problem
- [ ] If you're having an SMTP issue, include the debug output generated with `SMTPDebug = 2` set
- [ ] If you have a question about how to use PHPMailer (rather than reporting a bug in it), tag a question on Stack Overflow with `phpmailer`, but [**search first**](https://stackoverflow.com/questions/tagged/phpmailer)!
# Problem description
# Code to reproduce
# Debug output

1
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1 @@
Non-security issues and pull requests are no longer being accepted for the legacy PHPMailer 5.2 branch. Migrate to PHPMailer 6.0 (or later) and report your issue there.

View File

@ -1,15 +0,0 @@
FROM phpdoc/phpdoc
LABEL "repository"="https://github.com/PHPMailer/PHPMailer"
LABEL "com.github.actions.name"="Build Docs"
LABEL "com.github.actions.description"="Build Docs with phpDocumentor"
LABEL "com.github.actions.icon"="file-text"
LABEL "com.github.actions.color"="blue"
# don't show errors
RUN echo "display_errors = Off" > $PHP_INI_DIR/conf.d/errors.ini
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -1,5 +0,0 @@
#!/bin/sh
set -eu
/opt/phpdoc/bin/phpdoc

View File

@ -1,21 +0,0 @@
# Dependabot configuration.
#
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "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"

View File

@ -1,30 +0,0 @@
name: Docs
on:
push:
branches:
- master
permissions: {}
jobs:
build_and_publish:
permissions:
contents: write # to push changes in repo (jamesives/github-pages-deploy-action)
name: Build and publish Docs
runs-on: ubuntu-latest
if: github.repository == 'PHPMailer/PHPMailer'
steps:
- name: Checkout sources
uses: actions/checkout@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@9d877eea73427180ae43cf98e8914934fe157a1a # v4.7.6
with:
branch: gh-pages
folder: docs
env:
BUILD_DIR: docs/
GH_PAT: ${{ secrets.GH_PAT }}

View File

@ -1,61 +0,0 @@
name: Scorecards supply-chain security
on:
# Only the default branch is supported.
branch_protection_rule:
schedule:
- cron: '39 20 * * 1'
push:
branches: [ "master" ]
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:
# Required when publishing results (badge / API / code scanning)
security-events: write
id-token: write
steps:
- name: "Checkout code"
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
# (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecards on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
# Publish the results for public repositories to enable scorecard badges. For more details, see
# https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories, `publish_results` will automatically be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
with:
sarif_file: results.sarif

View File

@ -1,237 +0,0 @@
name: "Tests"
on:
push:
pull_request:
# Allow manually triggering the workflow.
workflow_dispatch:
permissions: {}
jobs:
coding-standard:
runs-on: ubuntu-22.04
name: Coding standards
permissions:
contents: read # to fetch code (actions/checkout)
steps:
- name: Check out code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up PHP
uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0
with:
php-version: 'latest'
coverage: none
tools: cs2pr
# Install dependencies and handle caching in one go.
# @link https://github.com/marketplace/actions/install-php-dependencies-with-composer
- name: Install Composer dependencies
uses: "ramsey/composer-install@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: Check coding standards
id: phpcs
run: ./vendor/bin/phpcs -s --report-full --report-checkstyle=./phpcs-report.xml
- name: Show PHPCS results in PR
if: ${{ always() && steps.phpcs.outcome == 'failure' }}
run: cs2pr ./phpcs-report.xml
lint:
runs-on: ubuntu-22.04
strategy:
matrix:
php: ['5.5', '7.2', '8.0', '8.5']
experimental: [false]
include:
- 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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Install PHP
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@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 != 'nightly' }}
run: composer lint -- --checkstyle | cs2pr
- name: Lint against future parse errors (PHP nightly)
if: ${{ matrix.php == 'nightly' }}
run: composer lint
test:
needs: ['coding-standard', 'lint']
runs-on: ubuntu-22.04
strategy:
matrix:
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
extensions: ['optimal', 'minimal']
coverage: [false]
experimental: [false]
include:
# Run code coverage on high/low PHP.
- php: '5.5'
extensions: 'optimal'
coverage: true
experimental: false
- php: '5.5'
extensions: 'minimal'
coverage: true
experimental: false
- php: '8.5'
extensions: 'optimal'
coverage: true
experimental: false
- php: '8.5'
extensions: 'minimal'
coverage: true
experimental: false
# Experimental builds. These are allowed to fail.
- php: '8.6'
extensions: 'optimal'
coverage: false
experimental: true
- php: '8.6'
extensions: 'minimal'
coverage: false
experimental: true
name: "Test: PHP ${{ matrix.php }} - ${{ matrix.extensions }}"
continue-on-error: ${{ matrix.experimental }}
permissions:
contents: read # to fetch code (actions/checkout)
steps:
- name: Check out code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
# About the "extensions":
#
# In a "normal" test run, the "default" extension set for a PHP version is used
# and it is ensured that certain extensions will be available, no matter what.
#
# For the "minimal" test run, all extensions are disabled and then only
# a limited set of minimally required extensions are re-enabled.
# The minimal set is based on the required extensions from PHPUnit + PHPMailer combined
# + Curl for Composer.
# Whether Xdebug will be enabled depends on the code coverage settings.
#
# Also see:
# https://github.com/shivammathur/setup-php/?tab=readme-ov-file#heavy_plus_sign-php-extension-support
# https://github.com/shivammathur/setup-php/wiki
- name: Determine extensions to use
id: set_extensions
run: |
if [[ "${{ matrix.extensions }}" == "optimal" ]]; then
# Optimal.
echo 'EXT=imap, mbstring, openssl, intl, ctype, filter, hash' >> $GITHUB_OUTPUT
echo 'COMPOSER_OPTIONS=' >> $GITHUB_OUTPUT
else
# Minimal.
echo 'EXT=none, curl, dom, json, libxml, mbstring, tokenizer, xml, xmlwriter, ctype, filter, hash' >> $GITHUB_OUTPUT
echo 'COMPOSER_OPTIONS=--ignore-platform-req=ext-simplexml' >> $GITHUB_OUTPUT
fi
- name: Set up PHP
uses: shivammathur/setup-php@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=-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.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.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.
custom-cache-suffix: $(date -u "+%Y-%m")
# Install postfix and automatically retry if the install failed, which happens reguarly.
# @link https://github.com/marketplace/actions/retry-step
- name: Install postfix
uses: nick-invision/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
with:
timeout_minutes: 2
max_attempts: 3
retry_wait_seconds: 8
command: |
sudo apt-get install --fix-broken -y libsqlite3-0 postfix
sudo systemctl stop postfix.service
- name: Set up sendmail
run: |
smtp-sink -d "%d.%H.%M.%S" localhost:2500 1000 &
mkdir -p build/logs
sudo cp test/testbootstrap-dist.php test/testbootstrap.php
sudo chmod +x test/fakesendmail.sh
sudo mkdir -p /var/qmail/bin
sudo cp test/fakesendmail.sh /var/qmail/bin/sendmail
sudo cp test/fakesendmail.sh /usr/sbin/sendmail
- name: Run tests, no code coverage
if: ${{ matrix.coverage == false }}
run: ./vendor/bin/phpunit --no-coverage
- name: Run tests with code coverage
if: ${{ matrix.coverage == true }}
run: vendor/bin/phpunit
- name: Send coverage report to Codecov
if: ${{ success() && matrix.coverage == true && github.event.repository.fork == false }}
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
files: ./build/logs/clover.xml
fail_ci_if_error: true
verbose: true

14
.gitignore vendored
View File

@ -1,16 +1,6 @@
docs/*
!docs/README.md
docs/phpdoc/
test/message.txt
test/testbootstrap.php
test/*.pem
build/
vendor/
*.pem
composer.lock
.phpcs.xml
phpcs.xml
.phpcs-cache
/.rnd
test/PHPMailerTest.php*nonexistent_file.txt
test/*/PHPMailerTest.php*nonexistent_file.txt
phpunit.xml
/.phpunit.result.cache

View File

@ -1,41 +0,0 @@
<?php
/**
* This configuration will be read and overlaid on top of the
* default configuration. Command line arguments will be applied
* after this file is read.
*/
return [
// A list of directories that should be parsed for class and
// method information. After excluding the directories
// defined in exclude_analysis_directory_list, the remaining
// files will be statically analyzed for errors.
//
// Thus, both first-party and third-party code being used by
// your application should be included in this list.
'directory_list' => [
'src',
'vendor',
'examples'
],
// A directory list that defines files that will be excluded
// from static analysis, but whose class and method
// information should be included.
//
// Generally, you'll want to include the directories for
// third-party code (such as "vendor/") in this list.
//
// n.b.: If you'd like to parse but not analyze 3rd
// party code, directories containing that code
// should be added to the `directory_list` as
// to `exclude_analysis_directory_list`.
"exclude_analysis_directory_list" => [
'vendor/'
],
'skip_slow_php_options_warning' => true,
'exclude_file_regex' => '@^vendor/.*/(tests|Tests)/@',
];

132
.scrutinizer.yml Normal file
View File

@ -0,0 +1,132 @@
build:
environment:
php: '5.6.0'
before_commands:
- "composer install --prefer-source"
tools:
external_code_coverage:
enabled: true
timeout: 300
filter:
excluded_paths:
- 'docs/*'
- 'examples/*'
- 'extras/*'
- 'test/*'
- 'vendor/*'
php_code_coverage:
enabled: false
filter:
excluded_paths:
- 'docs/*'
- 'examples/*'
- 'extras/*'
- 'test/*'
- 'vendor/*'
php_code_sniffer:
enabled: true
config:
standard: PSR2
sniffs:
generic:
files:
one_class_per_file_sniff: false
filter:
excluded_paths:
- 'docs/*'
- 'examples/*'
- 'extras/*'
- 'test/*'
- 'vendor/*'
# Copy/Paste Detector
php_cpd:
enabled: true
excluded_dirs:
- docs
- examples
- extras
- test
- vendor
# PHP CS Fixer (http://http://cs.sensiolabs.org/).
php_cs_fixer:
enabled: true
config:
level: psr2
filter:
excluded_paths:
- 'docs/*'
- 'examples/*'
- 'extras/*'
- 'test/*'
- 'vendor/*'
# Analyzes the size and structure of a PHP project.
php_loc:
enabled: true
excluded_dirs:
- docs
- examples
- extras
- test
- vendor
# PHP Mess Detector (http://phpmd.org).
php_mess_detector:
enabled: true
config:
rulesets:
- codesize
- unusedcode
- naming
- design
naming_rules:
short_variable: { minimum: 2 }
filter:
excluded_paths:
- 'docs/*'
- 'examples/*'
- 'extras/*'
- 'test/*'
- 'vendor/*'
# Analyzes the size and structure of a PHP project.
php_pdepend:
enabled: true
excluded_dirs:
- docs
- examples
- extras
- test
- vendor
# Runs Scrutinizer's PHP Analyzer Tool
# https://scrutinizer-ci.com/docs/tools/php/php-analyzer/config_reference
php_analyzer:
enabled: true
config:
checkstyle:
enabled: true
naming:
enabled: true
property_name: ^[_a-zA-Z][a-zA-Z0-9_]*$ #Allow underscores & caps
method_name: ^(?:[_a-zA-Z]|__)[a-zA-Z0-9_]*$ #Allow underscores & caps
parameter_name: ^[a-z][a-zA-Z0-9_]*$ # Allow underscores
local_variable: ^[a-zA-Z][a-zA-Z0-9_]*$ #Allow underscores & caps
exception_name: ^[a-zA-Z][a-zA-Z0-9]*Exception$
isser_method_name: ^(?:[_a-zA-Z]|__)[a-zA-Z0-9]*$ #Allow underscores & caps
filter:
excluded_paths:
- 'docs/*'
- 'examples/*'
- 'extras/*'
- 'test/*'
- 'vendor/*'
# Security Advisory Checker
sensiolabs_security_checker: true

38
.travis.yml Normal file
View File

@ -0,0 +1,38 @@
language: php
php:
- 7.1
- 7.0
- 5.6
- 5.5
- 5.4
- 5.3
matrix:
include:
- php: hhvm
dist: trusty
before_install:
- sudo apt-get update -qq
- sudo apt-get install -y -qq postfix
install:
- composer install
before_script:
- sudo service postfix stop
- smtp-sink -d "%d.%H.%M.%S" localhost:2500 1000 &
- mkdir -p build/logs
- cd test
- cp testbootstrap-dist.php testbootstrap.php
- chmod +x fakesendmail.sh
- sudo mkdir -p /var/qmail/bin
- sudo cp fakesendmail.sh /var/qmail/bin/sendmail
- sudo cp fakesendmail.sh /usr/sbin/sendmail
- |
if [[ $TRAVIS_PHP_VERSION = "hhv"* ]]; then
echo 'sendmail_path = "/usr/sbin/sendmail -t -i "' >> /etc/hhvm/php.ini
else
echo 'sendmail_path = "/usr/sbin/sendmail -t -i "' > $(php --ini|grep -m 1 "ini files in:"|cut -d ":" -f 2)/sendmail.ini
fi
script:
- ../vendor/bin/phpunit --configuration ../travis.phpunit.xml.dist
after_script:
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover ../build/logs/clover.xml

View File

@ -1,46 +0,0 @@
GPL Cooperation Commitment
Version 1.0
Before filing or continuing to prosecute any legal proceeding or claim
(other than a Defensive Action) arising from termination of a Covered
License, we commit to extend to the person or entity ('you') accused
of violating the Covered License the following provisions regarding
cure and reinstatement, taken from GPL version 3. As used here, the
term 'this License' refers to the specific Covered License being
enforced.
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly
and finally terminates your license, and (b) permanently, if the
copyright holder fails to notify you of the violation by some
reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you
have received notice of violation of this License (for any work)
from that copyright holder, and you cure the violation prior to 30
days after your receipt of the notice.
We intend this Commitment to be irrevocable, and binding and
enforceable against us and assignees of or successors to our
copyrights.
Definitions
'Covered License' means the GNU General Public License, version 2
(GPLv2), the GNU Lesser General Public License, version 2.1
(LGPLv2.1), or the GNU Library General Public License, version 2
(LGPLv2), all as published by the Free Software Foundation.
'Defensive Action' means a legal proceeding or claim that We bring
against you in response to a prior proceeding or claim initiated by
you or your affiliate.
'We' means each contributor to this repository as of the date of
inclusion of this file, including subsidiaries of a corporate
contributor.
This work is available under a Creative Commons Attribution-ShareAlike
4.0 International license (https://creativecommons.org/licenses/by-sa/4.0/).

42
LICENSE
View File

@ -1,8 +1,8 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -10,7 +10,7 @@
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -55,7 +55,7 @@ modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
@ -111,8 +111,8 @@ modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
@ -146,7 +146,7 @@ such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
@ -158,7 +158,7 @@ Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
@ -216,7 +216,7 @@ instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
@ -267,7 +267,7 @@ Library will still fall under Section 6.)
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
@ -312,7 +312,7 @@ of these things:
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
e) verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
@ -329,7 +329,7 @@ restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
@ -370,7 +370,7 @@ subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
@ -422,7 +422,7 @@ conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
@ -432,7 +432,7 @@ decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
@ -455,8 +455,8 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
@ -485,7 +485,7 @@ convey the exclusion of warranty; and each file should have at least the
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
@ -499,4 +499,6 @@ necessary. Here is a sample; alter the names:
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
That's all there is to it!

49
PHPMailerAutoload.php Normal file
View File

@ -0,0 +1,49 @@
<?php
/**
* PHPMailer SPL autoloader.
* PHP Version 5
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailer SPL autoloader.
* @param string $classname The name of the class to load
*/
function PHPMailerAutoload($classname)
{
//Can't use __DIR__ as it's only in PHP 5.3+
$filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php';
if (is_readable($filename)) {
require $filename;
}
}
if (version_compare(PHP_VERSION, '5.1.2', '>=')) {
//SPL autoloading was introduced in PHP 5.1.2
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
spl_autoload_register('PHPMailerAutoload', true, true);
} else {
spl_autoload_register('PHPMailerAutoload');
}
} else {
/**
* Fall back to traditional autoload for old PHP versions
* @param string $classname The name of the class to load
*/
function __autoload($classname)
{
PHPMailerAutoload($classname);
}
}

218
README.md
View File

@ -1,232 +1,196 @@
[![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://supportukrainenow.org/)
![PHPMailer](https://raw.github.com/PHPMailer/PHPMailer/master/examples/images/phpmailer.png)
# PHPMailer A full-featured email creation and transfer class for PHP
# PHPMailer - A full-featured email creation and transfer class for PHP
[![Test status](https://github.com/PHPMailer/PHPMailer/workflows/Tests/badge.svg)](https://github.com/PHPMailer/PHPMailer/actions)
[![codecov.io](https://codecov.io/gh/PHPMailer/PHPMailer/branch/master/graph/badge.svg?token=iORZpwmYmM)](https://codecov.io/gh/PHPMailer/PHPMailer)
[![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer)
[![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer)
[![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer)
[![API Docs](https://github.com/phpmailer/phpmailer/workflows/Docs/badge.svg)](https://phpmailer.github.io/PHPMailer/)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/PHPMailer/PHPMailer/badge)](https://api.securityscorecards.dev/projects/github.com/PHPMailer/PHPMailer)
Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](https://travis-ci.org/PHPMailer/PHPMailer)
[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/badges/quality-score.png?s=3758e21d279becdf847a557a56a3ed16dfec9d5d)](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/)
[![Code Coverage](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/badges/coverage.png?s=3fe6ca5fe8cd2cdf96285756e42932f7ca256962)](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/)
[![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer) [![Latest Unstable Version](https://poser.pugx.org/phpmailer/phpmailer/v/unstable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer)
## Class Features
## Features
- Probably the world's most popular code for sending email from PHP!
- Used by many open-source projects: WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! and many more
- Integrated SMTP support send without a local mail server
- Send emails with multiple To, CC, BCC, and Reply-to addresses
- Integrated SMTP support - send without a local mail server
- Send emails with multiple TOs, CCs, BCCs and REPLY-TOs
- Multipart/alternative emails for mail clients that do not read HTML email
- Add attachments, including inline
- Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings
- Full UTF-8 support when using servers that support `SMTPUTF8`.
- Support for iCal events in multiparts and attachments
- SMTP authentication with `LOGIN`, `PLAIN`, `CRAM-MD5`, and `XOAUTH2` mechanisms over SMTPS and SMTP+STARTTLS transports
- Validates email addresses automatically
- Protects against header injection attacks
- Error messages in over 50 languages!
- SMTP authentication with LOGIN, PLAIN, NTLM, CRAM-MD5 and Google's XOAUTH2 mechanisms over SSL and TLS transports
- Error messages in 47 languages!
- DKIM and S/MIME signing support
- Compatible with PHP 5.5 and later, including PHP 8.5
- Namespaced to prevent name clashes
- Compatible with PHP 5.0 and later
- Much more!
## Why you might need it
Many PHP developers need to send email from their code. The only PHP function that supports this directly is [`mail()`](https://www.php.net/manual/en/function.mail.php). However, it does not provide any assistance for making use of popular features such as authentication, HTML messages, and attachments.
Formatting email correctly is surprisingly difficult. There are myriad overlapping (and conflicting) standards, requiring tight adherence to horribly complicated formatting and encoding rules the vast majority of code that you'll find online that uses the `mail()` function directly is just plain wrong, if not unsafe!
Many PHP developers utilize email in their code. The only PHP function that supports this is the `mail()` function. However, it does not provide any assistance for making use of popular features such as HTML-based emails and attachments.
The PHP `mail()` function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD, and macOS platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP client allows email sending on all platforms without needing a local mail server. Be aware though, that the `mail()` function should be avoided when possible; it's both faster and [safer](https://exploitbox.io/paper/Pwning-PHP-Mail-Function-For-Fun-And-RCE.html) to use SMTP to localhost.
Formatting email correctly is surprisingly difficult. There are myriad overlapping RFCs, requiring tight adherence to horribly complicated formatting and encoding rules - the vast majority of code that you'll find online that uses the `mail()` function directly is just plain wrong!
*Please* don't be tempted to do it yourself - if you don't use PHPMailer, there are many other excellent libraries that you should look at before rolling your own - try SwiftMailer, Zend_Mail, eZcomponents etc.
*Please* don't be tempted to do it yourself if you don't use PHPMailer, there are many other excellent libraries that
you should look at before rolling your own. Try [Symfony Mailer](https://symfony.com/doc/current/mailer.html), [Laminas/Mail](https://docs.laminas.dev/laminas-mail/), [ZetaComponents](https://github.com/zetacomponents/Mail), etc.
The PHP `mail()` function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD and OS X platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP implementation allows email sending on Windows platforms without a local mail server.
## License
This software is distributed under the [LGPL 2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) license, along with the [GPL Cooperation Commitment](https://gplcc.github.io/gplcc/). Please read [LICENSE](https://github.com/PHPMailer/PHPMailer/blob/master/LICENSE) for information on the software availability and distribution.
This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lgpl-2.1.html) license. Please read LICENSE for information on the
software availability and distribution.
## Installation & loading
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:
PHPMailer is available via [Composer/Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), so just add this line to your `composer.json` file:
```json
"phpmailer/phpmailer": "^7.0.0"
"phpmailer/phpmailer": "~5.2"
```
or run
or
```sh
composer require phpmailer/phpmailer
```
Note that the `vendor` folder and the `vendor/autoload.php` script are generated by Composer; they are not part of PHPMailer.
If you want to use the Gmail XOAUTH2 authentication class, you will also need to add a dependency on the `league/oauth2-google` package.
If you want to use XOAUTH2 authentication, you will also need to add a dependency on the `league/oauth2-client` and appropriate service adapters package in your `composer.json`, or take a look at
by @decomplexity's [SendOauth2 wrapper](https://github.com/decomplexity/SendOauth2), especially if you're using Microsoft services.
Alternatively, copy the contents of the PHPMailer folder into one of the `include_path` directories specified in your PHP configuration. If you don't speak git or just want a tarball, click the 'zip' button at the top of the page in GitHub.
Alternatively, if you're not using Composer, you
can [download PHPMailer as a zip file](https://github.com/PHPMailer/PHPMailer/archive/master.zip), (note that docs and examples are not included in the zip file), then copy the contents of the PHPMailer folder into one of the `include_path` directories specified in your PHP configuration and load each class file manually:
If you're not using composer's autoloader, PHPMailer provides an SPL-compatible autoloader, and that is the preferred way of loading the library - just `require '/path/to/PHPMailerAutoload.php';` and everything should work. The autoloader does not throw errors if it can't find classes so it prepends itself to the SPL list, allowing your own (or your framework's) autoloader to catch errors. SPL autoloading was introduced in PHP 5.1.0, so if you are using a version older than that you will need to require/include each class manually.
```php
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
PHPMailer does *not* declare a namespace because namespaces were only introduced in PHP 5.3.
require 'path/to/PHPMailer/src/Exception.php';
require 'path/to/PHPMailer/src/PHPMailer.php';
require 'path/to/PHPMailer/src/SMTP.php';
```
If you're not using the `SMTP` class explicitly (you're probably not), you don't need a `use` line for it. Even if you're not using exceptions, you do still need to load the `Exception` class as it is used internally.
## Legacy versions
PHPMailer 5.2 (which is compatible with PHP 5.0 — 7.0) is no longer supported, even for security updates. You will find the latest version of 5.2 in the [5.2-stable branch](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable). If you're using PHP 5.5 or later (which you should be), switch to the 6.x releases.
### Upgrading from 5.2
The biggest changes are that source files are now in the `src/` folder, and PHPMailer now declares the namespace `PHPMailer\PHPMailer`. This has several important effects [read the upgrade guide](https://github.com/PHPMailer/PHPMailer/tree/master/UPGRADING.md) for more details.
If you want to use Google's XOAUTH2 authentication mechanism, you need to be running at least PHP 5.4, and load the dependencies listed in `composer.json`.
### Minimal installation
While installing the entire package manually or with Composer is simple, convenient, and reliable, you may want to include only vital files in your project. At the very least you will need [src/PHPMailer.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/PHPMailer.php). If you're using SMTP, you'll need [src/SMTP.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/SMTP.php), and if you're using POP-before SMTP (*very* unlikely!), you'll need [src/POP3.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/POP3.php). You can skip the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder if you're not showing errors to users and can make do with English-only errors. If you're using XOAUTH2 you will need [src/OAuth.php](https://github.com/PHPMailer/PHPMailer/tree/master/src/OAuth.php) as well as the Composer dependencies for the services you wish to authenticate with. Really, it's much easier to use Composer!
While installing the entire package manually or with composer is simple, convenient and reliable, you may want to include only vital files in your project. At the very least you will need [class.phpmailer.php](https://github.com/PHPMailer/PHPMailer/tree/master/class.phpmailer.php). If you're using SMTP, you'll need [class.smtp.php](https://github.com/PHPMailer/PHPMailer/tree/master/class.smtp.php), and if you're using POP-before SMTP, you'll need [class.pop3.php](https://github.com/PHPMailer/PHPMailer/tree/master/class.pop3.php). For all of these, we recommend you use [the autoloader](https://github.com/PHPMailer/PHPMailer/tree/master/PHPMailerAutoload.php) too as otherwise you will either have to `require` all classes manually or use some other autoloader. You can skip the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder if you're not showing errors to users and can make do with English-only errors. You may need the additional classes in the [extras](extras/) folder if you are using those features, including NTLM authentication and ics generation. If you're using Google XOAUTH2 you will need `class.phpmaileroauth.php` and `class.oauth.php` classes too, as well as the composer dependencies.
## A Simple Example
```php
<?php
//Import PHPMailer classes into the global namespace
//These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require 'PHPMailerAutoload.php';
//Load Composer's autoloader (created by composer, not included with PHPMailer)
require 'vendor/autoload.php';
$mail = new PHPMailer;
//Create an instance; passing `true` enables exceptions
$mail = new PHPMailer(true);
//$mail->SMTPDebug = 3; // Enable verbose debug output
try {
//Server settings
$mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output
$mail->isSMTP(); //Send using SMTP
$mail->Host = 'smtp.example.com'; //Set the SMTP server to send through
$mail->SMTPAuth = true; //Enable SMTP authentication
$mail->Username = 'user@example.com'; //SMTP username
$mail->Password = 'secret'; //SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption
$mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp1.example.com;smtp2.example.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'user@example.com'; // SMTP username
$mail->Password = 'secret'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
//Recipients
$mail->setFrom('from@example.com', 'Mailer');
$mail->addAddress('joe@example.net', 'Joe User'); //Add a recipient
$mail->addAddress('ellen@example.com'); //Name is optional
$mail->addReplyTo('info@example.com', 'Information');
$mail->addCC('cc@example.com');
$mail->addBCC('bcc@example.com');
$mail->setFrom('from@example.com', 'Mailer');
$mail->addAddress('joe@example.net', 'Joe User'); // Add a recipient
$mail->addAddress('ellen@example.com'); // Name is optional
$mail->addReplyTo('info@example.com', 'Information');
$mail->addCC('cc@example.com');
$mail->addBCC('bcc@example.com');
//Attachments
$mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments
$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name
$mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
$mail->isHTML(true); // Set email format to HTML
//Content
$mail->isHTML(true); //Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
```
You'll find plenty to play with in the [examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) folder, which covers many common scenarios including sending through Gmail, building contact forms, sending to mailing lists, and more.
If you are re-using the instance (e.g. when sending to a mailing list), you may need to clear the recipient list to avoid sending duplicate messages. See [the mailing list example](https://github.com/PHPMailer/PHPMailer/blob/master/examples/mailing_list.phps) for further guidance.
You'll find plenty more to play with in the [examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) folder.
That's it. You should now be ready to use PHPMailer!
## Localization
PHPMailer defaults to English, but in the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder, you'll find many translations for PHPMailer error messages that you may encounter. Their filenames contain [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) language code for the translations, for example `fr` for French. To specify a language, you need to tell PHPMailer which one to use, like this:
PHPMailer defaults to English, but in the [language](https://github.com/PHPMailer/PHPMailer/tree/master/language/) folder you'll find numerous (46 at the time of writing!) translations for PHPMailer error messages that you may encounter. Their filenames contain [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code for the translations, for example `fr` for French. To specify a language, you need to tell PHPMailer which one to use, like this:
```php
//To load the French version
// To load the French version
$mail->setLanguage('fr', '/optional/path/to/language/directory/');
```
We welcome corrections and new languages if you're looking for corrections, run the [Language/TranslationCompletenessTest.php](https://github.com/PHPMailer/PHPMailer/blob/master/test/Language/TranslationCompletenessTest.php) script in the tests folder and it will show any missing translations.
We welcome corrections and new languages - if you're looking for corrections to do, run the [phpmailerLangTest.php](https://github.com/PHPMailer/PHPMailer/tree/master/test/phpmailerLangTest.php) script in the tests folder and it will show any missing translations.
## Documentation
Start reading at the [GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki). If you're having trouble, head for [the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting) as it's frequently updated.
Examples of how to use PHPMailer for common scenarios can be found in the [examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) folder. If you're looking for a good starting point, we recommend you start with [the Gmail example](https://github.com/PHPMailer/PHPMailer/tree/master/examples/gmail.phps).
To reduce PHPMailer's deployed code footprint, examples are not included if you load PHPMailer via Composer or via [GitHub's zip file download](https://github.com/PHPMailer/PHPMailer/archive/master.zip), so you'll need to either clone the git repository or use the above links to get to the examples directly.
There are tips and a troubleshooting guide in the [GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki). If you're having trouble, this should be the first place you look as it's the most frequently updated.
Complete generated API documentation is [available online](https://phpmailer.github.io/PHPMailer/).
Complete generated API documentation is [available online](http://phpmailer.github.io/PHPMailer/).
You can generate complete API-level documentation by running `phpdoc` in the top-level folder, and documentation will appear in the `docs` folder, though you'll need to have [PHPDocumentor](https://www.phpdoc.org) installed. You may find [the unit tests](https://github.com/PHPMailer/PHPMailer/blob/master/test/PHPMailer/PHPMailerTest.php) a good reference for how to do various operations such as encryption.
You'll find some basic user-level docs in the [docs](docs/) folder, and you can generate complete API-level documentation using the [generatedocs.sh](https://github.com/PHPMailer/PHPMailer/tree/master/docs/generatedocs.sh) shell script in the docs folder, though you'll need to install [PHPDocumentor](http://www.phpdoc.org) first. You may find [the unit tests](https://github.com/PHPMailer/PHPMailer/tree/master/test/phpmailerTest.php) a good source of how to do various operations such as encryption.
If the documentation doesn't cover what you need, search the [many questions on Stack Overflow](https://stackoverflow.com/questions/tagged/phpmailer), and before you ask a question about "SMTP Error: Could not connect to SMTP host.", [read the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting).
If the documentation doesn't cover what you need, search the [many questions on Stack Overflow](http://stackoverflow.com/questions/tagged/phpmailer), and before you ask a question about "SMTP Error: Could not connect to SMTP host.", [read the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting).
## Tests
[PHPMailer tests](https://github.com/PHPMailer/PHPMailer/tree/master/test/) use PHPUnit 9, with [a polyfill](https://github.com/Yoast/PHPUnit-Polyfills) to let 9-style tests run on older PHPUnit and PHP versions.
[![Test status](https://github.com/PHPMailer/PHPMailer/workflows/Tests/badge.svg)](https://github.com/PHPMailer/PHPMailer/actions)
There is a PHPUnit test script in the [test](https://github.com/PHPMailer/PHPMailer/tree/master/test/) folder.
Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](https://travis-ci.org/PHPMailer/PHPMailer)
If this isn't passing, is there something you can do to help?
## Security
Please disclose any vulnerabilities found responsibly report security issues to the maintainers privately.
See [SECURITY](https://github.com/PHPMailer/PHPMailer/tree/master/SECURITY.md) and [PHPMailer's security advisories on GitHub](https://github.com/PHPMailer/PHPMailer/security).
Please disclose any vulnerabilities found responsibly - report any security problems found to the maintainers privately.
PHPMailer versions prior to 5.2.22 (released January 9th 2017) have a local file disclosure vulnerability, [CVE-2017-5223](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2017-5223). If content passed into `msgHTML()` is sourced from unfiltered user input, relative paths can map to absolute local file paths and added as attachments. Also note that `addAttachment` (just like `file_get_contents`, `passthru`, `unlink`, etc) should not be passed user-sourced params either! Reported by Yongxiang Li of Asiasecurity.
PHPMailer versions prior to 5.2.20 (released December 28th 2016) are vulnerable to [CVE-2016-10045](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-10045) a remote code execution vulnerability, responsibly reported by [Dawid Golunski](https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10045-Vuln-Patch-Bypass.html), and patched by Paul Buonopane (@Zenexer).
PHPMailer versions prior to 5.2.18 (released December 2016) are vulnerable to [CVE-2016-10033](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-10033) a critical remote code execution vulnerability, responsibly reported by [Dawid Golunski](http://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html).
See [SECURITY](https://github.com/PHPMailer/PHPMailer/tree/master/SECURITY.md) for more detail on security issues.
## Contributing
Please submit bug reports, suggestions, and pull requests to the [GitHub issue tracker](https://github.com/PHPMailer/PHPMailer/issues).
We're particularly interested in fixing edge cases, expanding test coverage, and updating translations.
Please submit bug reports, suggestions and pull requests to the [GitHub issue tracker](https://github.com/PHPMailer/PHPMailer/issues).
If you found a mistake in the docs, or want to add something, go ahead and amend the wiki anyone can edit it.
We're particularly interested in fixing edge-cases, expanding test coverage and updating translations.
If you have git clones from prior to the move to the PHPMailer GitHub organisation, you'll need to update any remote URLs referencing the old GitHub location with a command like this from within your clone:
With the move to the PHPMailer GitHub organisation, you'll need to update any remote URLs referencing the old GitHub location with a command like this from within your clone:
```sh
git remote set-url upstream https://github.com/PHPMailer/PHPMailer.git
```
Please *don't* use the SourceForge or Google Code projects any more; they are obsolete and no longer maintained.
Please *don't* use the SourceForge or Google Code projects any more.
## Sponsorship
Development time and resources for PHPMailer are provided by [Smartmessages.net](https://info.smartmessages.net/), the world's only privacy-first email marketing system.
<a href="https://info.smartmessages.net/"><img src="https://www.smartmessages.net/img/smartmessages-logo.svg" width="550" alt="Smartmessages.net privacy-first email marketing logo"></a>
Development time and resources for PHPMailer are provided by [Smartmessages.net](https://info.smartmessages.net/), a powerful email marketing system.
Donations are very welcome, whether in beer 🍺, T-shirts 👕, or cold, hard cash 💰. Sponsorship through GitHub is a simple and convenient way to say "thank you" to PHPMailer's maintainers and contributors just click the "Sponsor" button [on the project page](https://github.com/PHPMailer/PHPMailer). If your company uses PHPMailer, consider taking part in Tidelift's enterprise support programme.
<a href="https://info.smartmessages.net/"><img src="https://www.smartmessages.net/img/smartmessages-logo.svg" width="250" height="28" alt="Smartmessages email marketing"></a>
## PHPMailer For Enterprise
Available as part of the Tidelift Subscription.
The maintainers of PHPMailer and thousands of other packages are working with Tidelift to deliver commercial
support and maintenance for the open-source packages you use to build your applications. Save time, reduce risk, and
improve code health, while paying the maintainers of the exact packages you
use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-phpmailer-phpmailer?utm_source=packagist-phpmailer-phpmailer&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
Other contributions are gladly received, whether in beer 🍺, T-shirts 👕, Amazon wishlist raids, or cold, hard cash 💰.
## Changelog
See [changelog](changelog.md).
## History
- PHPMailer was originally written in 2001 by Brent R. Matzelle as a [SourceForge project](https://sourceforge.net/projects/phpmailer/).
- [Marcus Bointon](https://github.com/Synchro) (`coolbru` on SF) and Andy Prevost (`codeworxtech`) took over the project in 2004.
- PHPMailer was originally written in 2001 by Brent R. Matzelle as a [SourceForge project](http://sourceforge.net/projects/phpmailer/).
- Marcus Bointon (coolbru on SF) and Andy Prevost (codeworxtech) took over the project in 2004.
- Became an Apache incubator project on Google Code in 2010, managed by Jim Jagielski.
- Marcus created [his fork on GitHub](https://github.com/Synchro/PHPMailer) in 2008.
- Marcus created his fork on [GitHub](https://github.com/Synchro/PHPMailer) in 2008.
- Jim and Marcus decide to join forces and use GitHub as the canonical and official repo for PHPMailer in 2013.
- PHPMailer moves to [the PHPMailer organisation](https://github.com/PHPMailer) on GitHub in 2013.
- PHPMailer moves to the [PHPMailer organisation](https://github.com/PHPMailer) on GitHub in 2013.
### What's changed since moving from SourceForge?
- Official successor to the SourceForge and Google Code projects.
- Test suite.
- Continuous integration with GitHub Actions.
- Continuous integration with Travis-CI.
- Composer support.
- Public development.
- Additional languages and language strings.
- CRAM-MD5 authentication support.
- Preserves full repo history of authors, commits, and branches from the original SourceForge project.
- Preserves full repo history of authors, commits and branches from the original SourceForge project.

View File

@ -1,25 +1,14 @@
# Security notices relating to PHPMailer
Please disclose any security issues or vulnerabilities found through [Tidelift's coordinated disclosure system](https://tidelift.com/security) or to the maintainers privately.
Please disclose any vulnerabilities found responsibly - report any security problems found to the maintainers privately.
PHPMailer 6.4.1 and earlier contain a vulnerability that can result in untrusted code being called (if such code is injected into the host project's scope by other means). If the `$patternselect` parameter to `validateAddress()` is set to `'php'` (the default, defined by `PHPMailer::$validator`), and the global namespace contains a function called `php`, it will be called in preference to the built-in validator of the same name. Mitigated in PHPMailer 6.5.0 by denying the use of simple strings as validator function names. Recorded as [CVE-2021-3603](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-3603). Reported by [Vikrant Singh Chauhan](mailto:vi@hackberry.xyz) via [huntr.dev](https://www.huntr.dev/).
PHPMailer versions 6.4.1 and earlier contain a possible remote code execution vulnerability through the `$lang_path` parameter of the `setLanguage()` method. If the `$lang_path` parameter is passed unfiltered from user input, it can be set to [a UNC path](https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats#unc-paths), and if an attacker is also able to persuade the server to load a file from that UNC path, a script file under their control may be executed. This vulnerability only applies to systems that resolve UNC paths, typically only Microsoft Windows.
PHPMailer 6.5.0 mitigates this by no longer treating translation files as PHP code, but by parsing their text content directly. This approach avoids the possibility of executing unknown code while retaining backward compatibility. This isn't ideal, so the current translation format is deprecated and will be replaced in the next major release. Recorded as [CVE-2021-34551](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-34551). Reported by [Jilin Diting Information Technology Co., Ltd](https://listensec.com) via Tidelift.
PHPMailer versions between 6.1.8 and 6.4.0 contain a regression of the earlier CVE-2018-19296 object injection vulnerability as a result of [a fix for Windows UNC paths in 6.1.8](https://github.com/PHPMailer/PHPMailer/commit/e2e07a355ee8ff36aba21d0242c5950c56e4c6f9). Recorded as [CVE-2020-36326](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-36326). Reported by Fariskhi Vidyan via Tidelift. 6.4.1 fixes this issue, and also enforces stricter checks for URL schemes in local path contexts.
PHPMailer versions 6.1.5 and earlier contain an output escaping bug that occurs in `Content-Type` and `Content-Disposition` when filenames passed into `addAttachment` and other methods that accept attachment names contain double quote characters, in contravention of RFC822 3.4.1. No specific vulnerability has been found relating to this, but it could allow file attachments to bypass attachment filters that are based on matching filename extensions. Recorded as [CVE-2020-13625](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2020-13625). Reported by Elar Lang of Clarified Security.
PHPMailer versions prior to 6.0.6 and 5.2.27 are vulnerable to an object injection attack by passing `phar://` paths into `addAttachment()` and other functions that may receive unfiltered local paths, possibly leading to RCE. Recorded as [CVE-2018-19296](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2018-19296). See [this article](https://knasmueller.net/5-answers-about-php-phar-exploitation) for more info on this type of vulnerability. Mitigated by blocking the use of paths containing URL-protocol style prefixes such as `phar://`. Reported by Sehun Oh of cyberone.kr.
PHPMailer versions prior to 5.2.24 (released July 26th 2017) have an XSS vulnerability in one of the code examples, [CVE-2017-11503](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2017-11503). The `code_generator.phps` example did not filter user input prior to output. This file is distributed with a `.phps` extension, so it is not normally executable unless it is explicitly renamed, and the file is not included when PHPMailer is loaded through composer, so it is safe by default. There was also an undisclosed potential XSS vulnerability in the default exception handler (unused by default). Patches for both issues kindly provided by Patrick Monnerat of the Fedora Project.
PHPMailer versions prior to 5.2.24 (released July 26th 2017) have an XSS vulnerability in one of the code examples, [CVE-2017-11503](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2017-11503). The `code_generator.phps` example did not filter user input prior to output. This file is distributed with a `.phps` extension, so it it not normally executable unless it is explicitly renamed, so it is safe by default. There was also an undisclosed potential XSS vulnerability in the default exception handler (unused by default). Patches for both issues kindly provided by Patrick Monnerat of the Fedora Project.
PHPMailer versions prior to 5.2.22 (released January 9th 2017) have a local file disclosure vulnerability, [CVE-2017-5223](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2017-5223). If content passed into `msgHTML()` is sourced from unfiltered user input, relative paths can map to absolute local file paths and added as attachments. Also note that `addAttachment` (just like `file_get_contents`, `passthru`, `unlink`, etc) should not be passed user-sourced params either! Reported by Yongxiang Li of Asiasecurity.
PHPMailer versions prior to 5.2.20 (released December 28th 2016) are vulnerable to [CVE-2016-10045](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-10045) a remote code execution vulnerability, responsibly reported by [Dawid Golunski](https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10045-Vuln-Patch-Bypass.html), and patched by Paul Buonopane (@Zenexer).
PHPMailer versions prior to 5.2.18 (released December 2016) are vulnerable to [CVE-2016-10033](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-10033) a remote code execution vulnerability, responsibly reported by [Dawid Golunski](https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html).
PHPMailer versions prior to 5.2.18 (released December 2016) are vulnerable to [CVE-2016-10033](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-10033) a remote code execution vulnerability, responsibly reported by [Dawid Golunski](http://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html).
PHPMailer versions prior to 5.2.14 (released November 2015) are vulnerable to [CVE-2015-8476](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-8476) an SMTP CRLF injection bug permitting arbitrary message sending.

View File

@ -1,48 +0,0 @@
# A short history of UTF-8 in email
## Background
For most of its existence, SMTP has been a 7-bit channel, only supporting US-ASCII characters. This has been a problem for many languages, especially those that use non-Latin scripts, and has led to the development of various workarounds.
The first major improvement, introduced in 1994 in [RFC 1652](https://www.rfc-editor.org/rfc/rfc1652) and extended in 2011 in [RFC 6152](https://www.rfc-editor.org/rfc/rfc6152), was the addition of the `8BITMIME` SMTP extension, which allowed raw 8-bit data to be included in message bodies sent over SMTP.
This allowed the message *contents* to contain 8-bit data, including things like UTF-8 text, even though the SMTP protocol itself was still firmly 7-bit. This worked by having the server switch to 8-bit after the headers, and then back to 7-bit after the completion of a `DATA` command.
From 1996, messages could support [RFC 2047 encoding](https://www.rfc-editor.org/rfc/rfc2047), which permitted inserting characters from any character set into header *values* (but not names), but only by encoding them in somewhat unreadable ways to allow them to survive passage through a 7-bit channel. An example with a subject of "Schrödinger's cat" would be:
```
Subject: =?utf-8?Q=Schr=C3=B6dinger=92s_Cat?=
```
Here the accented `ö` is encoded as `=C3=B6`, which is the UTF-8 encoding of the 2-byte character, and the whole thing is wrapped in `=?utf-8?Q?` to indicate that it uses the UTF-8 charset and `quoted-printable` encoding. This is a bit of a hack, and not very human-friendly, but it works.
Similarly, 8-bit message bodies could be encoded using the same `quoted-printable` and `base64` content transfer encoding (CTE) schemes, which preserved the 8-bit content while encoding it in a format that could survive transmission through a 7-bit channel.
Domain names were originally also stuck in a 7-bit world, actually even more constrained to only a subset of the US-ASCII character set. But of course, many people want to have domains in their own language/script. Internationalized domain name (IDN) permitted this, using yet another complex encoding scheme called punycode, defined for domain names in 2003 in [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492). This finally allowed the domain part (after the `@`) of email addresses to contain UTF-8, though it was actually an illusion preserved by email client applications. For example, an address of
`user@café.example.com` translates to
`user@xn--caf-dma.example.com` in punycode, rendering it mostly unreadable, but 7-bit friendly, and remaining compatible with email clients that don't know about IDN.
The one remaining part of email that could not handle UTF-8 is the local part of email addresses (the part before the `@`).
I've only mentioned UTF-8 here, but most of these approaches also allowed other character sets that were popular, such as [the ISO-8859 family](https://en.wikipedia.org/wiki/ISO/IEC_8859). However, UTF-8 solves so many problems that these other character sets are gradually falling out of favour, as UTF-8 can support all languages.
This patchwork of overlapping approaches has served us well, but we have to admit that it's a mess.
## SMTPUTF8
`SMTPUTF8` is another SMTP extension, defined in [RFC 6531](https://www.rfc-editor.org/rfc/rfc6531) in 2012. This essentially solves the whole problem, allowing the entire SMTP conversation — commands, headers, and message bodies — to be sent in raw, unencoded UTF-8.
But there's a problem with this approach: adoption. If you send a UTF-8 message to a recipient whose mail server doesn't support this format, the sender has to somehow downgrade the message to make it survive a transition to 7-bit. This is a hard problem to solve, especially since there is no way to make a 7-bit system support UTF-8 in the local parts of addresses. This downgrade problem is what held up the adoption of `SMTPUTF8` in PHPMailer for many years, but in that time the *de facto* approach has become to simply fail in that situation, and tell the recipient it's time they upgraded their mail server 😅.
The vast majority of large email providers (gmail, Yahoo, Microsoft, etc), mail servers (postfix, exim, IIS, etc), and mail clients (Apple Mail, Outlook, Thunderbird, etc) now all support SMTPUTF8, so the need for backward compatibility is no longer what it was.
## SMTPUTF8 in PHPMailer
Several other PHP email libraries have implemented a halfway solution to `SMTPUTF8`, adding only the ability to support UTF-8 in email addresses, not elsewhere in the protocol. I wanted PHPMailer to do it "the right way", and this has taken much longer. PHPMailer now supports UTF-8 everywhere, and does not need to use transfer or header encodings for UTF-8 text when connecting to an `SMTPUTF8`-capable mail server.
This support is handled automatically: if you add an email address that requires UTF-8, PHPMailer will use UTF-8 for everything. If not, it will fall back to 7-bit and encode the message as necessary.
The one place you will need to be careful is in the selection of the address validator. By default, PHPMailer uses PHP's built-in `filter_var` validator, which does not allow UTF-8 email addresses. When PHPMailer spots that you have submitted a UTF-8 address, but have not altered the default validator, it will automatically switch to using a UTF-8-compatible validator. As soon as you do this, any SMTP connection you make will *require* that the server you connect to supports `SMTPUTF8`. You can select this validator explicitly by setting `PHPMailer::$validator = 'eai'` (an acronym for Email Address Internationalization).
### Postfix gotcha
Postfix has supported `SMTPUTF8` for a long time, but it has a peculiarity that it does not always advertise that it does so. However, rather surprisingly, if you use UTF-8 in the conversation, it will work anyway.

View File

@ -1,125 +0,0 @@
# Upgrading from PHPMailer 5.2 to 6.0
PHPMailer 6.0 is a major update, breaking backward compatibility.
If you're in doubt about how you should be using PHPMailer 6, take a look at the examples as they have all been updated to work in a PHPMailer 6.0 style.
## PHP Version
PHPMailer 6.0 requires PHP 5.5 or later, and is fully compatible with PHP versions all the way up to 8.4. PHPMailer 5.2 supported PHP 5.0 and upwards, so if you need to run on a legacy PHP version, see the [PHPMailer 5.2-stable branch on Github](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable), but bear in mind that this branch is no longer maintained.
## Loading PHPMailer
The single biggest change will be in the way that you load PHPMailer. In earlier versions you may have done this:
```php
require 'PHPMailerAutoload.php';
```
or
```php
require 'class.phpmailer.php';
require 'class.smtp.php';
```
We recommend that you load PHPMailer via composer, using its standard autoloader, which you probably won't need to load if you're using it already, but in case you're not, you will need to do this instead:
```php
require 'vendor/autoload.php';
```
If you're not using composer, you can still load the classes manually, depending on what you're using:
```php
require 'src/PHPMailer.php';
require 'src/SMTP.php';
require 'src/Exception.php';
```
## Namespace
PHPMailer 6 uses a [namespace](https://www.php.net/manual/en/language.namespaces.rationale.php) of `PHPMailer\PHPMailer`, because it's the PHPMailer project within the PHPMailer organisation. You **must** import (with a `use` statement) classes you're using explicitly into your own namespace, or reference them absolutely in the global namespace - all the examples do this. This means the fully-qualified name of the main PHPMailer class is `PHPMailer\PHPMailer\PHPMailer`, which is a bit of a mouthful, but there's no harm in it! If you are using other PHPMailer classes explicitly (such as `SMTP` or `Exception`), you will need to import them into your namespace too.
For example you might create an instance like this:
```php
<?php
namespace MyProject;
use PHPMailer\PHPMailer\PHPMailer;
require 'vendor/autoload.php';
$mail = new PHPMailer;
...
```
or alternatively, using a fully qualified name:
```php
<?php
namespace MyProject;
require 'vendor/autoload.php';
$mail = new PHPMailer\PHPMailer\PHPMailer;
...
```
Note that `use` statements apply *only* to the file they appear in (they are local aliases), so if an included file contains `use` statements, it will not import the namespaced classes into the file you're including from.
## Namespaced exceptions
PHPMailer now uses its own namespaced `Exception` class, so if you were previously catching exceptions of type `phpmailerException` (or subclasses of that), you will need to update them to use the PHPMailer namespace, and make any existing `Exception` references use the global namespace, i.e. `\Exception`. If your original code was:
```php
try {
...
} catch (phpmailerException $e) {
echo $e->errorMessage();
} catch (Exception $e) {
echo $e->getMessage();
}
```
Convert it to:
```php
use PHPMailer\PHPMailer\Exception;
...
try {
...
} catch (Exception $e) {
echo $e->errorMessage();
} catch (\Exception $e) {
echo $e->getMessage();
}
```
## OAuth2 Support
The OAuth2 implementation has been completely redesigned using the [OAuth2 packages](https://oauth2-client.thephpleague.com) from the [League of extraordinary packages](https://thephpleague.com), providing support for many more OAuth services, and you'll need to update your code if you were using OAuth in 5.2. See [the examples](https://github.com/PHPMailer/PHPMailer/tree/master/examples) and documentation in the [PHPMailer wiki](https://github.com/PHPMailer/PHPMailer/wiki).
## Extras
Additional classes previously bundled in the `Extras` folder (such as htmlfilter and EasyPeasyICS) have been removed - use equivalent packages from [packagist.org](https://packagist.org) instead.
## Other upgrade changes
See the changelog for full details.
* File structure simplified, classes live in the `src/` folder
* Most statically called functions now use the `static` keyword instead of `self`, so it's possible to override static internal functions in subclasses, for example `validateAddress()`
* Complete RFC standardisation on CRLF (`\r\n`) line breaks by default:
* `PHPMailer::$LE` still exists, but all uses of it are changed to `static::$LE` for easier overriding. It may be changed to `\n` automatically when sending via `mail()` on UNIX-like OSs
* `PHPMailer::CRLF` line ending constant removed
* The length of the line break is no longer used in line length calculations
* Similar changes to line break handling in SMTP and POP3 classes
* All elements previously marked as deprecated have been removed:
* `PHPMailer->Version`
* `PHPMailer->ReturnPath`
* `PHPMailer->PluginDir`
* `PHPMailer->encodeQPphp()`
* `SMTP->CRLF`
* `SMTP->Version`
* `SMTP->SMTP_PORT`
* `POP3->CRLF`
* `POP3->Version`
* NTLM authentication has been removed - it never worked anyway!
* `PHPMailer->Workstation`
* `PHPMailer->Realm`
* `SMTP::authenticate` method signature changed
* `parseAddresses()` is now static
* `validateAddress()` is now called statically from `parseAddresses()`
* `idnSupported()` is now static and is called statically from `punyencodeAddress()`
* `PHPMailer->SingleToArray` is now protected

View File

@ -1 +1 @@
7.0.2
5.2.25

View File

@ -1,436 +1,14 @@
# PHPMailer Change Log
# ChangeLog
## 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
## 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.
## 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.
* Also support empty tokens.
* Avoid bogus static analyser deprecation warnings in `setFrom`.
* Make language loading entirely static, thanks to @SirLouen.
* Emit warnings when `parseAddresses()` is used without the IMAP extension.
* Handle `mb_decode_mimeheader` changes from PHP 8.3+.
* Deprecate the charset param to parseAddresses.
* Fix PHP 8.5 linting issue.
* Don't use `-t` switch when calling qmail.
* Checking for interrupted system calls now works in languages other than English.
* Add support for extracting gmail transaction IDs after sending.
* For consistency, the protected `ReplyTo` property has been changed to match the format used for other address arrays.
* Fix line length issues when using S/MIME signing.
* Pin action runners to exact versions to avoid unexpected upstream changes.
## Version 6.10.0 (April 24th, 2025)
* Add support for [RFC 6530 SMTPUTF8](https://www.rfc-editor.org/rfc/rfc6530), permitting use of UTF-8 Unicode characters everywhere, thanks to @arnt and ICANN. See `SMTPUTF8.md` for details.
* More reliable checking for multibyte support.
## Version 6.9.3 (November 22nd, 2024)
* Add support for the release version of PHP 8.4
* Add experimental support for PHP 8.5
* Use rfc-editor.org for all RFC docs links
## Version 6.9.2 (October 9th, 2024)
* Escape dots in SMTP transaction ID patterns
* Add link to [aboutmy.email](https://aboutmy.email) testing service in docs
* Add a more comprehensive example for using XOAUTH2 with gmail and Azure, thanks to @decomplexity
* Update Turkish, Spanish, Japanese, Russian, French translations
* Add Urdu & Kurdish (Sorani) translations
* Fix broken links in docs and comments, avoid http links, correct link to LGPL 2.1 license file
* Cleaner PSR-3 SMTP debug logging
* Bump GitHub action versions
* Fix error handler scope issue in POP3 and SMTP classes
* Numerous test improvements by @jrfnl
## Version 6.9.1 (November 25th, 2023)
* Finalise SendOauth2 example
## Version 6.9.0 (November 23rd, 2023)
* Add support for official release of PHP 8.3, add experimental support for PHP 8.4
* Add `clearCustomHeader` and `replaceCustomHeader` methods
* Add support for the XCLIENT SMTP extension with `setSMTPXclientAttribute` and `getSMTPXclientAttributes` methods
* Don't attempt opportunistic TLS when connecting to localhost
* Add package link and example showing how to use @decomplexity's SendOauth2 wrapper
* Update example to show a better way of using an SMTP subclass
* Avoid some more deprecation warnings
* Update Danish and Polish translations
* Add Bengali and Assamese translations
## Version 6.8.1 (August 29th, 2023)
* Don't reflect malformed DSNs in error messages to avert any risk of XSS
* Improve Simplified Chinese, Sinhalese, and Norwegian translations
* Don't use `setAccessible` in PHP >= 8.1 in tests
* Avoid a deprecation notice in PHP 8.3
* Fix link in readme
## Version 6.8.0 (March 6th, 2023)
* Add DSN parsing class, thanks to @voronkovich
* Fix some name edge cases, expand tests
* Add pattern for ZonMTA message IDs
* Improve Hindi translation
## Version 6.7.1 (December 8th, 2022)
* Add official support for PHP 8.2
* Add PHP 8.3 to test suite with "experimental" status
* Add ext-openssl to composer suggest list
* Bump development dependencies
## Version 6.7 (December 5th, 2022)
* Break out boundary definitions into a method (note that boundary format has also changed slightly)
* Remove MIME preamble to match popular client behaviour, may help with DKIM too
* Fix handling of trailing whitespace in simple DKIM canonicalisation
* Fix some possible POP3 auth issues, including a TCP hang (thanks to @czirkoszoltan)
* Add Azure XOAUTH2 example and docs (thanks to @greew)
* Preserve errors during disconnect
* Avoid some PHP 8.1 type issues
* Update CI to run on Ubuntu 22.04
## Version 6.6.5 (October 7th, 2022)
* Don't try to issue RSET if there has been a connection error
* Reject attempts to add folders as attachments
* Don't suppress earlier error messages on close()
* Handle Host === null better
* Update Danish and Polish translations
* Change recommendation for Microsoft OAuth package to thenetworg/oauth2-azure
* Bump some GitHub action versions
## Version 6.6.4 (August 22nd, 2022)
* Update Greek translation
* Add text/csv MIME type
* Fix DKIM when sending to anonymous group via mail()
* Improve docs around auth following gmail & MS deprecations
* Update GitHub action deps
* Add OpenSSF Scorecard security health metrics
## Version 6.6.3 (June 20th, 2022)
* Add an HTML form to the OAuth setup script
* Minor CS improvements
* Add Mongolian translation
* Remove bogus "ch" translation
## Version 6.6.2 (June 14th, 2022)
* Fix docs deployment GitHub action
* Updates to parallel-lint and console highlighter, thanks to @jrfnl
## Version 6.6.1 (June 14th, 2022) (unreleased)
* Don't clear errors on RSET, so they can still be obtained when using keepalive
* Bump some GitHub action versions
* Fix some tests
* 🇺🇦 Slava Ukraini!
## Version 6.6 (February 28th, 2022)
* Introduce interface for OAuth providers, making it easier to use OAuth libraries other than the League one, thanks to @pdscopes.
* Add more contextual information to TLS connection failure error messages, and throw exceptions on TLS connection errors, thanks to @miken32
## Version 6.5.4 (February 17th, 2022)
* If we can't use escaping functions, refuse to do unsafe things
* Avoid PHP 8.1 trim issue
* Add tests for XMailer
* Fix bug in use of CharSet property
* Fix bug in file upload example
* Update dev dependencies
## Version 6.5.3 (November 25th, 2021)
* Wrong commit tagged for the 6.5.2 release!
* Version file updated
## Version 6.5.2 (November 25th, 2021)
* Enable official support for PHP 8.1
* Enable experimental support for PHP 8.2
* Fix for PHP 5.6
* Fix for incorrect options for punyencoding IDNs
## Version 6.5.1 (August 18th, 2021)
* Provisional support for PHP 8.1
* Major overhaul of test suite
* Add codecov.io coverage reporting
* Prefer implicit TLS on port 465 as default encryption scheme in examples, as per RFC8314
* Fix potential noisy output from IMAP address parser
* Stricter checking of custom MessageID validity
* Replace invalid default From address
* Support fallback for languages, so a request for `pt_xx` will fall back to `pt` rather than the default `en`.
* Support multi-line RFC2047 addresses in parseAddresses
* Improved Japanese translation
Many thanks to @jrfnl for all her work.
## Version 6.5.0 (June 16th, 2021)
* **SECURITY** Fixes CVE-2021-34551, a complex RCE affecting Windows hosts. See [SECURITY.md](SECURITY.md) for details.
* The fix for this issue changes the way that language files are loaded. While they remain in the same PHP-like format, they are processed as plain text, and any code in them will not be run, including operations such as concatenation using the `.` operator.
* *Deprecation* The current translation file format using PHP arrays is now deprecated; the next major version will introduce a new format.
* **SECURITY** Fixes CVE-2021-3603 that may permit untrusted code to be run from an address validator. See [SECURITY.md](SECURITY.md) for details.
* The fix for this issue includes a minor BC break: callables injected into `validateAddress`, or indirectly through the `$validator` class property, may no longer be simple strings. If you want to inject your own validator, provide a closure instead of a function name.
* Haraka message ID strings are now recognised
## Version 6.4.1 (April 29th, 2021)
* **SECURITY** Fixes CVE-2020-36326, a regression of CVE-2018-19296 object injection introduced in 6.1.8, see SECURITY.md for details
* Reject more file paths that look like URLs, matching RFC3986 spec, blocking URLS using schemes such as `ssh2`
* Ensure method signature consistency in `doCallback` calls
* Ukrainian language update
* Add composer scripts for checking coding standards and running tests
## Version 6.4.0 (March 31st, 2021)
* Revert change that made the `mail()` and sendmail transports set the envelope sender if one isn't explicitly provided, as it causes problems described in <https://github.com/PHPMailer/PHPMailer/issues/2298>
* Check for mbstring extension before decoding addresss in `parseAddress`
* Add Serbian Latin translation (`sr_latn`)
* Enrol PHPMailer in Tidelift
## Version 6.3.0 (February 19th, 2021)
* Handle early connection errors such as 421 during connection and EHLO states
* Switch to GitHub Actions for CI
* Generate debug output for `mail()`, sendmail, and qmail transports. Enable using the same mechanism as for SMTP: set `SMTPDebug` > 0
* Make the `mail()` and sendmail transports set the envelope sender the same way as SMTP does, i.e. use whatever `From` is set to, only falling back to the `sendmail_from` php.ini setting if `From` is unset. This avoids errors from the `mail()` function if `Sender` is not set explicitly and php.ini is not configured. This is a minor functionality change, so bumps the minor version number.
* Extend `parseAddresses` to decode encoded names, improve tests
## Version 6.2.0
* PHP 8.0 compatibility, many thanks to @jrf_nl!
* Switch from PHP CS Fixer to PHP CodeSniffer for coding standards
* Create class constants for the debug levels in the POP3 class
* Improve French, Slovenian, and Ukrainian translations
* Improve file upload examples so file extensions are retained
* Resolve PHP 8 line break issues due to a very old PHP bug being fixed
* Avoid warnings when using old openssl functions
* Improve Travis-CI build configuration
## Version 6.1.8 (October 9th, 2020)
* Mark `ext-hash` as required in composer.json. This has long been required, but now it will cause an error at install time rather than runtime, making it easier to diagnose
* Make file upload examples safer
* Update links to SMTP testing servers
* Avoid errors when set_time_limit is disabled (you need better hosting!)
* Allow overriding auth settings for local tests; makes it easy to run tests using HELO
* Recover gracefully from errors during keepalive sessions
* Add AVIF MIME type mapping
* Prevent duplicate `To` headers in BCC-only messages when using `mail()`
* Avoid file function problems when attaching files from Windows UNC paths
* Improve German, Bahasa Indonesian, Filipino translations
* Add Javascript-based example
* Increased test coverage
## Version 6.1.7 (July 14th, 2020)
* Split SMTP connection into two separate methods
* Undo BC break in PHP versions 5.2.3 - 7.0.0 introduced in 6.1.2 when injecting callables for address validation and HTML to text conversion
* Save response to SMTP welcome banner as other responses are saved
* Retry stream_select if interrupted by a signal
## Version 6.1.6 (May 27th, 2020)
* **SECURITY** Fix insufficient output escaping bug in file attachment names. CVE-2020-13625. Reported by Elar Lang of Clarified Security.
* Correct Armenian ISO language code from `am` to `hy`, add mapping for fallback
* Use correct timeout property in debug output
## Version 6.1.5 (March 14th, 2020)
* Reject invalid custom headers that are empty or contain breaks
* Various fixes for DKIM issues, especially when using `mail()` transport
* Drop the `l=` length tag from DKIM signatures; it's a mild security risk
* Ensure CRLF is used explicitly when needed, rather than `static::$LE`
* Add a method for trimming header content consistently
* Some minor tweaks to resolve static analyser complaints
* Check that attachment files are readable both when adding *and* when sending
* Work around Outlook bug in mishandling MIME preamble
* Danish translation improvements
## Version 6.1.4 (December 10th, 2019)
* Clean up hostname handling
* Avoid IDN error on older PHP versions, prep for PHP 8.0
* Don't force RFC2047 folding unnecessarily
* Enable tests on full release of PHP 7.4
## Version 6.1.3 (November 21st, 2019)
* Fix an issue preventing injected debug handlers from working
* Fix an issue relating to connection timeout
* Add `SMTP::MAX_REPLY_LENGTH` constant
* Remove some dev dependencies; phpdoc no longer included
* Fix an issue where non-compliant servers returning bare codes caused an SMTP hang
## Version 6.1.2 (November 13th, 2019)
* Substantial revision of DKIM header generation
* Use shorter hashes for auto-generated CID values
* Fix format of content-id headers, and only use them for inline attachments
* Remove all use of XHTML
* Lots of coding standards cleanup
* API docs are now auto-updated via GitHub actions
* Fix header separation bug created in 6.1.1
* Fix misidentification of background attributes in SVG images in msgHTML
## Version 6.1.1 (September 27th 2019)
* Fix misordered version tag
## Version 6.1.0 (September 27th 2019)
* Multiple bug fixes for folding of long header lines, thanks to @caugner
* Add support for [RFC2387 child element content-type hint](https://www.rfc-editor.org/rfc/rfc2387#section-3.1) in `multipart/related` structures.
* Support for Ical event methods other than `REQUEST`, thanks to @puhr-mde
* Change header folding and param separation to use spaces instead of tabs
* Use ; to separate multiple MIME header params
* Add support for RFC3461 DSN messages
* IMAP example code fixed
* Use PHP temp streams instead of temp files
* Allow for longer SMTP error codes
* Updated Brazilian Portuguese translation
* Throw exceptions on invalid encoding values
* Add Afrikaans translation, thanks to @Donno191
* Updated Farsi/Persian translation
* Add PHP 7.4 to test config
* Remove some ambiguity about setting XMailer property
* Improve error checking in mailing list example
* Drop PHP 5.5 from CI config as it's no longer supported by Travis-CI
* Fix S/MIME signing
* Add constants for encryption type
* More consistent use of constants for encryption, charset, encoding
* Add PHPMailer logo images
## Version 6.0.7 (February 1st 2019)
* Include RedHat GPL Cooperation Commitment - see the `COMMITMENT` file for details.
* Don't exclude composer.json from git exports as it breaks composer updates in projects that use PHPMailer
* Updated Malay translation
* Fix language tests
## Version 6.0.6 (November 14th 2018)
* **SECURITY** Fix potential object injection vulnerability. Reported by Sehun Oh of cyberone.kr.
* Added Tagalog translation, thanks to @StoneArtz
* Added Malagache translation, thanks to @Hackinet
* Updated Serbian translation, fixed incorrect language code, thanks to @mmilanovic4
* Updated Arabic translations (@MicroDroid)
* Updated Hungarian translations
* Updated Dutch translations
* Updated Slovenian translation (@filips123)
* Updated Slovak translation (@pcmanik)
* Updated Italian translation (@sabas)
* Updated Norwegian translation (@aleskr)
* Updated Indonesian translation (@mylastof)
* Add constants for common values, such as `text/html` and `quoted-printable`, and use them
* Added support for copied headers in DKIM, helping with debugging, and an option to add extra headers to the DKIM signature. See DKIM_sign example for how to use them. Thanks to @gwi-mmuths.
* Add Campaign Monitor transaction ID pattern matcher
* Remove deprecated constant and ini values causing warnings in PHP 7.3, added PHP 7.3 build to Travis config.
* Expanded test coverage
## Version 5.2.27 (November 14th 2018)
* **SECURITY** Fix potential object injection vulnerability. Reported by Sehun Oh of cyberone.kr.
* Note that the 5.2 branch is now deprecated and will not receive security updates after 31st December 2018.
## Version 6.0.5 (March 27th 2018)
* Re-roll of 6.0.4 to fix missed version file entry. No code changes.
## Version 6.0.4 (March 27th 2018)
* Add some modern MIME types
* Add Hindi translation (thanks to @dextel2)
* Improve composer docs
* Fix generation of path to language files
## Version 6.0.3 (January 5th 2018)
* Correct DKIM canonicalization of line breaks for header & body - thanks to @themichaelhall
* Make dependence on ext-filter explicit in composer.json
## Version 6.0.2 (November 29th 2017)
* Don't make max line length depend on line break format
* Improve Travis-CI config - thanks to Filippo Tessarotto
* Match SendGrid transaction IDs
* `idnSupported()` now static, as previously documented
* Improve error messages for invalid addresses
* Improve Indonesian translation (thanks to @januridp)
* Improve Esperanto translation (thanks to @dknacht)
* Clean up git export ignore settings for production and zip bundles
* Update license doc
* Updated upgrading docs
* Clarify `addStringEmbeddedImage` docs
* Hide auth credentials in all but lowest-level debug output, prevents leakage in bug reports
* Code style cleanup
## Version 6.0.1 (September 14th 2017)
* Use shorter Message-ID headers (with more entropy) to avoid iCloud blackhole bug
* Switch to Symfony code style (though it's not well defined)
* CI builds now apply syntax & code style checks, so make your PRs tidy!
* CI code coverage only applied on latest version of PHP to speed up builds (thanks to @Slamdunk for these CI changes)
* Remove `composer.lock` - it's important that libraries break early; keeping it is for apps
* Rename test scripts to PSR-4 spec
* Make content-id values settable on attachments, not just embedded items
* Add SMTP transaction IDs to callbacks & allow for future expansion
* Expand test coverage
## Version 6.0 (August 28th 2017)
This is a major update that breaks backwards compatibility.
* **Requires PHP 5.5 or later**
* **Uses the `PHPMailer\PHPMailer` namespace**
* File structure simplified and PSR-4 compatible, classes live in the `src/` folder
* The custom autoloader has been removed: [**use composer**](https://getcomposer.org)!
* Classes & Exceptions renamed to make use of the namespace
* Most statically called functions now use the `static` keyword instead of `self`, so it's possible to override static internal functions in subclasses, for example `validateAddress()`
* Complete RFC standardisation on CRLF (`\r\n`) line breaks for SMTP by default:
* `PHPMailer:$LE` defaults to CRLF
* All uses of `PHPMailer::$LE` property converted to use `static::$LE` constant for consistency and ease of overriding
* Similar changes to line break handling in SMTP and POP3 classes.
* Line break format for `mail()` transport is set automatically.
* Warnings emitted for buggy `mail()` in PHP versions 7.0.0 - 7.0.16 and 7.1.0 - 7.1.2; either upgrade or switch to SMTP.
* Extensive reworking of XOAUTH2, adding support for Google, Yahoo and Microsoft providers, thanks to @sherryl4george
* Major cleanup of docs and examples
* All elements previously marked as deprecated have been removed:
* `PHPMailer->Version` (replaced with `VERSION` constant)
* `PHPMailer->ReturnPath`
* `PHPMailer->PluginDir`
* `PHPMailer->encodeQPphp()`
* `SMTP->CRLF` (replaced with `LE` constant)
* `SMTP->Version` (replaced with `VERSION` constant)
* `SMTP->SMTP_PORT` (replaced with `DEFAULT_PORT` constant)
* `POP3->CRLF` (replaced with `LE` constant)
* `POP3->Version` (replaced with `VERSION` constant)
* `POP3->POP3_PORT` (replaced with `DEFAULT_PORT` constant)
* `POP3->POP3_TIMEOUT` (replaced with `DEFAULT_TIMEOUT` constant)
* NTLM authentication has been removed - it never worked anyway!
* `PHPMailer->Workstation`
* `PHPMailer->Realm`
* `SingleTo` functionality is deprecated; this belongs at a higher level - PHPMailer is not a mailing list system.
* `SMTP::authenticate` method signature changed
* `parseAddresses()` is now static
* `validateAddress()` is now called statically from `parseAddresses()`
* `idnSupported()` is now static and is called statically from `punyencodeAddress()`
* `PHPMailer->SingleToArray` is now protected
* `fixEOL()` method removed - it duplicates `PHPMailer::normalizeBreaks()`, so use that instead
* Don't try to use an auth mechanism if it's not supported by the server
* Reorder automatic AUTH mechanism selector to try most secure method first
* `Extras` classes have been removed - use alternative packages from [packagist.org](https://packagist.org) instead
* Better handling of automatic transfer encoding switch in the presence of long lines
* Simplification of address validation - now uses PHP's `FILTER_VALIDATE_EMAIL` pattern by default, retains advanced options
* `Debugoutput` can accept a PSR-3 logger instance
* To reduce code footprint, the examples folder is no longer included in composer deployments or GitHub zip files
* Trap low-level errors in SMTP, reports via debug output
* More reliable folding of message headers
* Inject your own SMTP implementation via `setSMTPInstance()` instead of having to subclass and override `getSMTPInstance()`.
* Make obtaining SMTP transaction ID more reliable
* Better handling of unreliable PHP timeouts
* Made `SMTPDebug = 4` slightly less noisy
## Version 5.2.25 (August 28th 2017)
## Version 5.2.25 (August 2th 2917)
* Make obtaining SMTP transaction ID more reliable
* Add Bosnian translation
* This is the last official release in the legacy PHPMailer 5.2 series; there may be future security patches (which will be found in the [5.2-stable branch](https://github.com/PHPMailer/PHPMailer/tree/5.2-stable)), but no further non-security PRs or issues will be accepted. Migrate to PHPMailer 6.0.
## Version 5.2.24 (July 26th 2017)
* **SECURITY** Fix XSS vulnerability in one of the code examples, [CVE-2017-11503](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2017-11503). The `code_generator.phps` example did not filter user input prior to output. This file is distributed with a `.phps` extension, so it is not normally executable unless it is explicitly renamed, so it is safe by default. There was also an undisclosed potential XSS vulnerability in the default exception handler (unused by default). Patches for both issues kindly provided by Patrick Monnerat of the Fedora Project.
* **SECURITY** Fix XSS vulnerability in one of the code examples, [CVE-2017-11503](https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2017-11503). The `code_generator.phps` example did not filter user input prior to output. This file is distributed with a `.phps` extension, so it it not normally executable unless it is explicitly renamed, so it is safe by default. There was also an undisclosed potential XSS vulnerability in the default exception handler (unused by default). Patches for both issues kindly provided by Patrick Monnerat of the Fedora Project.
* Handle bare codes (an RFC contravention) in SMTP server responses
* Make message timestamps more dynamic - calculate the date separately for each message
* More thorough checks for reading attachments.
* Throw an exception when trying to send a message with an empty body caused by an internal error.
* Replaced all use of MD5 and SHA1 hash functions with SHA256.
* Now checks for invalid host strings when sending via SMTP.
* Include timestamps in HTML-format debug output
* Improve Turkish, Norwegian, Serbian, Brazilian Portuguese & simplified Chinese translations
* Correction of Serbian ISO language code from `sr` to `rs`
@ -853,10 +431,10 @@ All new documentation
* We have removed the /phpdoc from the downloads. All documentation is now on
the http://phpmailer.codeworxtech.com website.
## Version 2.2.1 (July 19, 2008)
## Version 2.2.1 () July 19 2008
* fixed line 1092 in class.smtp.php (my apologies, error on my part)
## Version 2.2 (July 15, 2008)
## Version 2.2 () July 15 2008
* Fixed redirect issue (display of UTF-8 in thank you redirect)
* fixed error in getResponse function declaration (class.pop3.php)
* PHPMailer now PHP6 compliant
@ -941,7 +519,7 @@ NOTE: will NOT work with PHP5 in E_STRICT error mode
## Version 1.73 (Sun, Jun 10 2005)
* Fixed denial of service bug: http://www.cybsec.com/vuln/PHPMailer-DOS.pdf
* Now has a total of 20 translations
* Fixed alt attachments bug: https://sourceforge.net/p/phpmailer/bugs/120/
* Fixed alt attachments bug: http://tinyurl.com/98u9k
## Version 1.72 (Wed, May 25 2004)
* Added Dutch, Swedish, Czech, Norwegian, and Turkish translations.
@ -1058,7 +636,7 @@ NOTE: will NOT work with PHP5 in E_STRICT error mode
## Version 1.19 (Thu, Jun 21 2001)
* Fixed MS Mail header bug
* Added fix for Bcc problem with mail(). *Does not work on Win32*
(See PHP bug report: https://bugs.php.net/bug.php?id=11616
(See PHP bug report: http://www.php.net/bugs.php?id=11616)
* mail() no longer passes a fifth parameter when not needed
## Version 1.15 (Fri, Jun 15 2001)

4042
class.phpmailer.php Normal file

File diff suppressed because it is too large Load Diff

197
class.phpmaileroauth.php Normal file
View File

@ -0,0 +1,197 @@
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.4
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailerOAuth - PHPMailer subclass adding OAuth support.
* @package PHPMailer
* @author @sherryl4george
* @author Marcus Bointon (@Synchro) <phpmailer@synchromedia.co.uk>
*/
class PHPMailerOAuth extends PHPMailer
{
/**
* The OAuth user's email address
* @var string
*/
public $oauthUserEmail = '';
/**
* The OAuth refresh token
* @var string
*/
public $oauthRefreshToken = '';
/**
* The OAuth client ID
* @var string
*/
public $oauthClientId = '';
/**
* The OAuth client secret
* @var string
*/
public $oauthClientSecret = '';
/**
* An instance of the PHPMailerOAuthGoogle class.
* @var PHPMailerOAuthGoogle
* @access protected
*/
protected $oauth = null;
/**
* Get a PHPMailerOAuthGoogle instance to use.
* @return PHPMailerOAuthGoogle
*/
public function getOAUTHInstance()
{
if (!is_object($this->oauth)) {
$this->oauth = new PHPMailerOAuthGoogle(
$this->oauthUserEmail,
$this->oauthClientSecret,
$this->oauthClientId,
$this->oauthRefreshToken
);
}
return $this->oauth;
}
/**
* Initiate a connection to an SMTP server.
* Overrides the original smtpConnect method to add support for OAuth.
* @param array $options An array of options compatible with stream_context_create()
* @uses SMTP
* @access public
* @return bool
* @throws phpmailerException
*/
public function smtpConnect($options = array())
{
if (is_null($this->smtp)) {
$this->smtp = $this->getSMTPInstance();
}
if (is_null($this->oauth)) {
$this->oauth = $this->getOAUTHInstance();
}
// Already connected?
if ($this->smtp->connected()) {
return true;
}
$this->smtp->setTimeout($this->Timeout);
$this->smtp->setDebugLevel($this->SMTPDebug);
$this->smtp->setDebugOutput($this->Debugoutput);
$this->smtp->setVerp($this->do_verp);
$hosts = explode(';', $this->Host);
$lastexception = null;
foreach ($hosts as $hostentry) {
$hostinfo = array();
if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
// Not a valid host entry
continue;
}
// $hostinfo[2]: optional ssl or tls prefix
// $hostinfo[3]: the hostname
// $hostinfo[4]: optional port number
// The host string prefix can temporarily override the current setting for SMTPSecure
// If it's not specified, the default value is used
$prefix = '';
$secure = $this->SMTPSecure;
$tls = ($this->SMTPSecure == 'tls');
if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) {
$prefix = 'ssl://';
$tls = false; // Can't have SSL and TLS at the same time
$secure = 'ssl';
} elseif ($hostinfo[2] == 'tls') {
$tls = true;
// tls doesn't use a prefix
$secure = 'tls';
}
//Do we need the OpenSSL extension?
$sslext = defined('OPENSSL_ALGO_SHA1');
if ('tls' === $secure or 'ssl' === $secure) {
//Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
if (!$sslext) {
throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL);
}
}
$host = $hostinfo[3];
$port = $this->Port;
$tport = (integer)$hostinfo[4];
if ($tport > 0 and $tport < 65536) {
$port = $tport;
}
if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
try {
if ($this->Helo) {
$hello = $this->Helo;
} else {
$hello = $this->serverHostname();
}
$this->smtp->hello($hello);
//Automatically enable TLS encryption if:
// * it's not disabled
// * we have openssl extension
// * we are not already using SSL
// * the server offers STARTTLS
if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) {
$tls = true;
}
if ($tls) {
if (!$this->smtp->startTLS()) {
throw new phpmailerException($this->lang('connect_host'));
}
// We must resend HELO after tls negotiation
$this->smtp->hello($hello);
}
if ($this->SMTPAuth) {
if (!$this->smtp->authenticate(
$this->Username,
$this->Password,
$this->AuthType,
$this->Realm,
$this->Workstation,
$this->oauth
)
) {
throw new phpmailerException($this->lang('authenticate'));
}
}
return true;
} catch (phpmailerException $exc) {
$lastexception = $exc;
$this->edebug($exc->getMessage());
// We must have connected, but then failed TLS or Auth, so close connection nicely
$this->smtp->quit();
}
}
}
// If we get here, all connection attempts have failed, so close connection hard
$this->smtp->close();
// As we've caught all exceptions, just report whatever the last one was
if ($this->exceptions and !is_null($lastexception)) {
throw $lastexception;
}
return false;
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.4
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailerOAuthGoogle - Wrapper for League OAuth2 Google provider.
* @package PHPMailer
* @author @sherryl4george
* @author Marcus Bointon (@Synchro) <phpmailer@synchromedia.co.uk>
* @link https://github.com/thephpleague/oauth2-client
*/
class PHPMailerOAuthGoogle
{
private $oauthUserEmail = '';
private $oauthRefreshToken = '';
private $oauthClientId = '';
private $oauthClientSecret = '';
/**
* @param string $UserEmail
* @param string $ClientSecret
* @param string $ClientId
* @param string $RefreshToken
*/
public function __construct(
$UserEmail,
$ClientSecret,
$ClientId,
$RefreshToken
) {
$this->oauthClientId = $ClientId;
$this->oauthClientSecret = $ClientSecret;
$this->oauthRefreshToken = $RefreshToken;
$this->oauthUserEmail = $UserEmail;
}
private function getProvider()
{
return new League\OAuth2\Client\Provider\Google([
'clientId' => $this->oauthClientId,
'clientSecret' => $this->oauthClientSecret
]);
}
private function getGrant()
{
return new \League\OAuth2\Client\Grant\RefreshToken();
}
private function getToken()
{
$provider = $this->getProvider();
$grant = $this->getGrant();
return $provider->getAccessToken($grant, ['refresh_token' => $this->oauthRefreshToken]);
}
public function getOauth64()
{
$token = $this->getToken();
return base64_encode("user=" . $this->oauthUserEmail . "\001auth=Bearer " . $token . "\001\001");
}
}

407
class.pop3.php Normal file
View File

@ -0,0 +1,407 @@
<?php
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* PHP Version 5
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
* Does not support APOP.
* @package PHPMailer
* @author Richard Davey (original author) <rich@corephp.co.uk>
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
*/
class POP3
{
/**
* The POP3 PHPMailer Version number.
* @var string
* @access public
*/
public $Version = '5.2.25';
/**
* Default POP3 port number.
* @var integer
* @access public
*/
public $POP3_PORT = 110;
/**
* Default timeout in seconds.
* @var integer
* @access public
*/
public $POP3_TIMEOUT = 30;
/**
* POP3 Carriage Return + Line Feed.
* @var string
* @access public
* @deprecated Use the constant instead
*/
public $CRLF = "\r\n";
/**
* Debug display level.
* Options: 0 = no, 1+ = yes
* @var integer
* @access public
*/
public $do_debug = 0;
/**
* POP3 mail server hostname.
* @var string
* @access public
*/
public $host;
/**
* POP3 port number.
* @var integer
* @access public
*/
public $port;
/**
* POP3 Timeout Value in seconds.
* @var integer
* @access public
*/
public $tval;
/**
* POP3 username
* @var string
* @access public
*/
public $username;
/**
* POP3 password.
* @var string
* @access public
*/
public $password;
/**
* Resource handle for the POP3 connection socket.
* @var resource
* @access protected
*/
protected $pop_conn;
/**
* Are we connected?
* @var boolean
* @access protected
*/
protected $connected = false;
/**
* Error container.
* @var array
* @access protected
*/
protected $errors = array();
/**
* Line break constant
*/
const CRLF = "\r\n";
/**
* Simple static wrapper for all-in-one POP before SMTP
* @param $host
* @param integer|boolean $port The port number to connect to
* @param integer|boolean $timeout The timeout value
* @param string $username
* @param string $password
* @param integer $debug_level
* @return boolean
*/
public static function popBeforeSmtp(
$host,
$port = false,
$timeout = false,
$username = '',
$password = '',
$debug_level = 0
) {
$pop = new POP3;
return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
}
/**
* Authenticate with a POP3 server.
* A connect, login, disconnect sequence
* appropriate for POP-before SMTP authorisation.
* @access public
* @param string $host The hostname to connect to
* @param integer|boolean $port The port number to connect to
* @param integer|boolean $timeout The timeout value
* @param string $username
* @param string $password
* @param integer $debug_level
* @return boolean
*/
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
{
$this->host = $host;
// If no port value provided, use default
if (false === $port) {
$this->port = $this->POP3_PORT;
} else {
$this->port = (integer)$port;
}
// If no timeout value provided, use default
if (false === $timeout) {
$this->tval = $this->POP3_TIMEOUT;
} else {
$this->tval = (integer)$timeout;
}
$this->do_debug = $debug_level;
$this->username = $username;
$this->password = $password;
// Reset the error log
$this->errors = array();
// connect
$result = $this->connect($this->host, $this->port, $this->tval);
if ($result) {
$login_result = $this->login($this->username, $this->password);
if ($login_result) {
$this->disconnect();
return true;
}
}
// We need to disconnect regardless of whether the login succeeded
$this->disconnect();
return false;
}
/**
* Connect to a POP3 server.
* @access public
* @param string $host
* @param integer|boolean $port
* @param integer $tval
* @return boolean
*/
public function connect($host, $port = false, $tval = 30)
{
// Are we already connected?
if ($this->connected) {
return true;
}
//On Windows this will raise a PHP Warning error if the hostname doesn't exist.
//Rather than suppress it with @fsockopen, capture it cleanly instead
set_error_handler(array($this, 'catchWarning'));
if (false === $port) {
$port = $this->POP3_PORT;
}
// connect to the POP3 server
$this->pop_conn = fsockopen(
$host, // POP3 Host
$port, // Port #
$errno, // Error Number
$errstr, // Error Message
$tval
); // Timeout (seconds)
// Restore the error handler
restore_error_handler();
// Did we connect?
if (false === $this->pop_conn) {
// It would appear not...
$this->setError(array(
'error' => "Failed to connect to server $host on port $port",
'errno' => $errno,
'errstr' => $errstr
));
return false;
}
// Increase the stream time-out
stream_set_timeout($this->pop_conn, $tval, 0);
// Get the POP3 server response
$pop3_response = $this->getResponse();
// Check for the +OK
if ($this->checkResponse($pop3_response)) {
// The connection is established and the POP3 server is talking
$this->connected = true;
return true;
}
return false;
}
/**
* Log in to the POP3 server.
* Does not support APOP (RFC 2828, 4949).
* @access public
* @param string $username
* @param string $password
* @return boolean
*/
public function login($username = '', $password = '')
{
if (!$this->connected) {
$this->setError('Not connected to POP3 server');
}
if (empty($username)) {
$username = $this->username;
}
if (empty($password)) {
$password = $this->password;
}
// Send the Username
$this->sendString("USER $username" . self::CRLF);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
// Send the Password
$this->sendString("PASS $password" . self::CRLF);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
return true;
}
}
return false;
}
/**
* Disconnect from the POP3 server.
* @access public
*/
public function disconnect()
{
$this->sendString('QUIT');
//The QUIT command may cause the daemon to exit, which will kill our connection
//So ignore errors here
try {
@fclose($this->pop_conn);
} catch (Exception $e) {
//Do nothing
};
}
/**
* Get a response from the POP3 server.
* $size is the maximum number of bytes to retrieve
* @param integer $size
* @return string
* @access protected
*/
protected function getResponse($size = 128)
{
$response = fgets($this->pop_conn, $size);
if ($this->do_debug >= 1) {
echo "Server -> Client: $response";
}
return $response;
}
/**
* Send raw data to the POP3 server.
* @param string $string
* @return integer
* @access protected
*/
protected function sendString($string)
{
if ($this->pop_conn) {
if ($this->do_debug >= 2) { //Show client messages when debug >= 2
echo "Client -> Server: $string";
}
return fwrite($this->pop_conn, $string, strlen($string));
}
return 0;
}
/**
* Checks the POP3 server response.
* Looks for for +OK or -ERR.
* @param string $string
* @return boolean
* @access protected
*/
protected function checkResponse($string)
{
if (substr($string, 0, 3) !== '+OK') {
$this->setError(array(
'error' => "Server reported an error: $string",
'errno' => 0,
'errstr' => ''
));
return false;
} else {
return true;
}
}
/**
* Add an error to the internal error store.
* Also display debug output if it's enabled.
* @param $error
* @access protected
*/
protected function setError($error)
{
$this->errors[] = $error;
if ($this->do_debug >= 1) {
echo '<pre>';
foreach ($this->errors as $error) {
print_r($error);
}
echo '</pre>';
}
}
/**
* Get an array of error messages, if any.
* @return array
*/
public function getErrors()
{
return $this->errors;
}
/**
* POP3 connection error handler.
* @param integer $errno
* @param string $errstr
* @param string $errfile
* @param integer $errline
* @access protected
*/
protected function catchWarning($errno, $errstr, $errfile, $errline)
{
$this->setError(array(
'error' => "Connecting to the POP3 server raised a PHP warning: ",
'errno' => $errno,
'errstr' => $errstr,
'errfile' => $errfile,
'errline' => $errline
));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -19,66 +19,43 @@
"name": "Brent R. Matzelle"
}
],
"funding": [
{
"url": "https://github.com/Synchro",
"type": "github"
}
],
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
},
"lock": false
},
"require": {
"php": ">=5.5.0",
"ext-ctype": "*",
"ext-filter": "*",
"ext-hash": "*"
"php": ">=5.0.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"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": "^10.0.0@dev",
"squizlabs/php_codesniffer": "^3.13.5",
"yoast/phpunit-polyfills": "^1.0.4"
"doctrine/annotations": "1.2.*",
"jms/serializer": "0.16.*",
"phpdocumentor/phpdocumentor": "2.*",
"phpunit/phpunit": "4.8.*",
"symfony/debug": "2.8.*",
"symfony/filesystem": "2.8.*",
"symfony/translation": "2.8.*",
"symfony/yaml": "2.8.*",
"zendframework/zend-cache": "2.5.1",
"zendframework/zend-config": "2.5.1",
"zendframework/zend-eventmanager": "2.5.1",
"zendframework/zend-filter": "2.5.1",
"zendframework/zend-i18n": "2.5.1",
"zendframework/zend-json": "2.5.1",
"zendframework/zend-math": "2.5.1",
"zendframework/zend-serializer": "2.5.*",
"zendframework/zend-servicemanager": "2.5.*",
"zendframework/zend-stdlib": "2.5.1"
},
"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",
"directorytree/imapengine": "For uploading sent messages via IMAP, see gmail example"
"league/oauth2-google": "Needed for Google XOAUTH2 authentication"
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"PHPMailer\\PHPMailer\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"PHPMailer\\Test\\": "test/"
}
},
"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": [
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . --show-deprecated -e php,phps --exclude vendor --exclude .git --exclude build"
"classmap": [
"class.phpmailer.php",
"class.phpmaileroauth.php",
"class.phpmaileroauthgoogle.php",
"class.smtp.php",
"class.pop3.php",
"extras/EasyPeasyICS.php",
"extras/ntlm_sasl_client.php"
]
}
},
"license": "LGPL-2.1"
}

3593
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
NEW CALLBACK FUNCTION:
======================
We have had requests for a method to process the results of sending emails
through PHPMailer. In this new release, we have implemented a callback
function that passes the results of each email sent (to, cc, and/or bcc).
We have provided an example that echos the results back to the screen. The
callback function can be used for any purpose. With minor modifications, the
callback function can be used to create CSV logs, post results to databases,
etc.
Please review the test.php script for the example.
It's pretty straight forward.
Enjoy!
Andy

55
docs/DomainKeys_notes.txt Normal file
View File

@ -0,0 +1,55 @@
CREATE DKIM KEYS and DNS Resource Record:
=========================================
To create DomainKeys Identified Mail keys, visit:
http://dkim.worxware.com/
... read the information, fill in the form, and download the ZIP file
containing the public key, private key, DNS Resource Record and instructions
to add to your DNS Zone Record, and the PHPMailer code to enable DKIM
digital signing.
/*** PROTECT YOUR PRIVATE & PUBLIC KEYS ***/
You need to protect your DKIM private and public keys from being viewed or
accessed. Add protection to your .htaccess file as in this example:
# secure htkeyprivate file
<Files .htkeyprivate>
order allow,deny
deny from all
</Files>
# secure htkeypublic file
<Files .htkeypublic>
order allow,deny
deny from all
</Files>
(the actual .htaccess additions are in the ZIP file sent back to you from
http://dkim.worxware.com/
A few notes on using DomainKey Identified Mail (DKIM):
You do not need to use PHPMailer to DKIM sign emails IF:
- you enable DomainKey support and add the DNS resource record
- you use your outbound mail server
If you are a third-party emailer that works on behalf of domain owners to
send their emails from your own server:
- you absolutely have to DKIM sign outbound emails
- the domain owner has to add the DNS resource record to match the
private key, public key, selector, identity, and domain that you create
- use caution with the "selector" ... at least one "selector" will already
exist in the DNS Zone Record of the domain at the domain owner's server
you need to ensure that the "selector" you use is unique
Note: since the IP address will not match the domain owner's DNS Zone record
you can be certain that email providers that validate based on DomainKey will
check the domain owner's DNS Zone record for your DNS resource record. Before
sending out emails on behalf of domain owners, ensure they have entered the
DNS resource record you provided them.
Enjoy!
Andy
PS. if you need additional information about DKIM, please see:
http://www.dkim.org/info/dkim-faq.html

View File

@ -0,0 +1,44 @@
#SMTP Debugging
If you are having problems connecting or sending emails through your SMTP server, the SMTP class can provide more information about the processing/errors taking place.
Use the debug functionality of the class to see what's going on in your connections. To do that, set the debug level in your script. For example:
```php
$mail->SMTPDebug = 2;
$mail->isSMTP(); // tell the class to use SMTP
$mail->SMTPAuth = true; // enable SMTP authentication
$mail->Port = 25; // set the SMTP port
$mail->Host = "mail.yourhost.com"; // SMTP server
$mail->Username = "name@yourhost.com"; // SMTP account username
$mail->Password = "your password"; // SMTP account password
```
##Debug levels
Setting the `SMTPDebug` property results in different amounts of output:
* `0`: Disable debugging (you can also leave this out completely, 0 is the default).
* `1`: Output messages sent by the client.
* `2`: as 1, plus responses received from the server (this is probably the most useful setting for debugging).
* `3`: as 2, plus more information about the initial connection.
* `4`: as 3, plus even lower-level information, very verbose.
You don't need to use levels above 2 unless you're having trouble connecting at all - it will just make output more verbose and more difficult to read.
Note that you will get no output until you call `send()`, because no SMTP conversation takes place until you do that.
##Debug output format
The form that the debug output taks is determined by the `Debugoutput` property. This has several options:
* `echo` Output plain-text as-is, appropriate for CLI
* `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
* `error_log` Output to error log as configured in php.ini
By default PHPMailer will use `echo` if run from a `cli` or `cli-server` SAPI, `html` otherwise. Alternatively, you can implement your own system by providing a callable expecting two parameters: a message string and the debug level:
$mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
You can of course make this more complex - for example your could capture all the output and store it in a database.
And finally, don't forget to disable debugging before going into production.

View File

@ -1,9 +0,0 @@
# PHPMailer Documentation
Generated documentation for PHPMailer is [available online](https://phpmailer.github.io/PHPMailer/), and is regenerated automatically whenever changes are made.
Pre-built PHPMailer API documentation is not provided in this repo, but you can generate it by running `phpdoc` in the top-level folder of this project, and documentation will be generated in this `docs` folder. You will need to have [phpDocumentor](https://www.phpdoc.org) installed. The configuration for phpdoc is in the [phpdoc.dist.xml file](https://github.com/PHPMailer/PHPMailer/blob/master/phpdoc.dist.xml).
Further help and information is available in [the PHPMailer README](https://github.com/PHPMailer/PHPMailer/blob/master/README.md), [the examples folder](https://github.com/PHPMailer/PHPMailer/tree/master/examples), and in [the GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki).
Fixes and additions to documentation are welcome - please submit pull requests or improve wiki pages.

128
docs/extending.html Normal file
View File

@ -0,0 +1,128 @@
<html>
<head>
<title>Examples using phpmailer</title>
</head>
<body>
<h2>Examples using PHPMailer</h2>
<h3>1. Advanced Example</h3>
<p>
This demonstrates sending multiple email messages with binary attachments
from a MySQL database using multipart/alternative messages.<p>
<pre>
require 'PHPMailerAutoload.php';
$mail = new PHPMailer();
$mail->setFrom('list@example.com', 'List manager');
$mail->Host = 'smtp1.example.com;smtp2.example.com';
$mail->Mailer = 'smtp';
@mysqli_connect('localhost','root','password');
@mysqli_select_db("my_company");
$query = "SELECT full_name, email, photo FROM employee";
$result = @mysqli_query($query);
while ($row = mysqli_fetch_assoc($result))
{
// HTML body
$body = "Hello &lt;font size=\"4\"&gt;" . $row['full_name'] . "&lt;/font&gt;, &lt;p&gt;";
$body .= "&lt;i&gt;Your&lt;/i&gt; personal photograph to this message.&lt;p&gt;";
$body .= "Sincerely, &lt;br&gt;";
$body .= "phpmailer List manager";
// Plain text body (for mail clients that cannot read HTML)
$text_body = 'Hello ' . $row['full_name'] . ", \n\n";
$text_body .= "Your personal photograph to this message.\n\n";
$text_body .= "Sincerely, \n";
$text_body .= 'phpmailer List manager';
$mail->Body = $body;
$mail->AltBody = $text_body;
$mail->addAddress($row['email'], $row['full_name']);
$mail->addStringAttachment($row['photo'], 'YourPhoto.jpg');
if(!$mail->send())
echo "There has been a mail error sending to " . $row['email'] . "&lt;br&gt;";
// Clear all addresses and attachments for next loop
$mail->clearAddresses();
$mail->clearAttachments();
}
</pre>
<p>
<h3>2. Extending PHPMailer</h3>
<p>
Extending classes with inheritance is one of the most
powerful features of object-oriented programming. It allows you to make changes to the
original class for your own personal use without hacking the original
classes, and it's very easy to do:
<p>
Here's a class that extends the phpmailer class and sets the defaults
for the particular site:<br>
PHP include file: my_phpmailer.php
<p>
<pre>
require 'PHPMailerAutoload.php';
class my_phpmailer extends PHPMailer {
// Set default variables for all new objects
public $From = 'from@example.com';
public $FromName = 'Mailer';
public $Host = 'smtp1.example.com;smtp2.example.com';
public $Mailer = 'smtp'; // Alternative to isSMTP()
public $WordWrap = 75;
// Replace the default debug output function
protected function edebug($msg) {
print('My Site Error');
print('Description:');
printf('%s', $msg);
exit;
}
//Extend the send function
public function send() {
$this->Subject = '[Yay for me!] '.$this->Subject;
return parent::send()
}
// Create an additional function
public function do_something($something) {
// Place your new code here
}
}
</pre>
<br>
Now here's a normal PHP page in the site, which will have all the defaults set above:<br>
<pre>
require 'my_phpmailer.php';
// Instantiate your new class
$mail = new my_phpmailer;
// Now you only need to add the necessary stuff
$mail->addAddress('josh@example.com', 'Josh Adams');
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the message body';
$mail->addAttachment('c:/temp/11-10-00.zip', 'new_name.zip'); // optional name
if(!$mail->send())
{
echo 'There was an error sending the message';
exit;
}
echo 'Message was sent successfully';
</pre>
</body>
</html>

28
docs/faq.html Normal file
View File

@ -0,0 +1,28 @@
<html>
<head>
<title>PHPMailer FAQ</title>
</head>
<body>
<h2>PHPMailer FAQ</h2>
<ul>
<li><strong>Q: I am concerned that using include files will take up too much
processing time on my computer. How can I make it run faster?</strong><br>
<strong>A:</strong> PHP by itself is fairly fast, but it recompiles scripts every time they are run, which takes up valuable
computer resources. You can bypass this by using an opcode cache which compiles
PHP code and store it in memory to reduce overhead immensely. <a href="http://www.php.net/apc/">APC
(Alternative PHP Cache)</a> is a free opcode cache extension in the PECL library.</li>
<li><strong>Q: Which mailer gives me the best performance?</strong><br>
<strong>A:</strong> On a single machine the <strong>sendmail (or Qmail)</strong> is fastest overall.
Next fastest is mail() to give you the best performance. Both do not have the overhead of SMTP.
If you do not have a local mail server (as is typical on Windows), SMTP is your only option.</li>
<li><strong>Q: When I try to attach a file with on my server I get a
"Could not find {file} on filesystem error". Why is this?</strong><br>
<strong>A:</strong> If you are using a Unix machine this is probably because the user
running your web server does not have read access to the directory in question. If you are using Windows,
then the problem is probably that you have used single backslashes to denote directories (\).
A single backslash has a special meaning to PHP so these are not
valid. Instead use double backslashes ("\\") or a single forward
slash ("/").</li>
</ul>
</body>
</html>

8
docs/generatedocs.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
# Regenerate PHPMailer documentation
# Run from within the docs folder
rm -rf phpdoc/*
phpdoc --directory .. --target ./phpdoc --ignore test/,examples/,extras/,test_script/,vendor/,language/ --sourcecode --force --title PHPMailer --template="clean"
# You can merge regenerated docs into a separate docs working copy without messing up the git status like so:
# rsync -a --delete --exclude ".git" --exclude "phpdoc-cache-*/" --exclude "README.md" phpdoc/ ../../phpmailer-docs
# After updating docs, push/PR them to the phpmailer gh-pages branch: https://github.com/PHPMailer/PHPMailer/tree/gh-pages

50
docs/pop3_article.txt Normal file
View File

@ -0,0 +1,50 @@
This is built for PHP Mailer 1.72 and was not tested with any previous version. It was developed under PHP 4.3.11 (E_ALL). It works under PHP 5 and 5.1 with E_ALL, but not in Strict mode due to var deprecation (but then neither does PHP Mailer either!). It follows the RFC 1939 standard explicitly and is fully commented.
With that noted, here is how to implement it:
I didn't want to modify the PHP Mailer classes at all, so you will have to include/require this class along with the base one. It can sit quite happily in the phpmailer directory.
When you need it, create your POP3 object
Right before I invoke PHP Mailer I activate the POP3 authorisation. POP3 before SMTP is a process whereby you login to your web hosts POP3 mail server BEFORE sending out any emails via SMTP. The POP3 logon 'verifies' your ability to send email by SMTP, which typically otherwise blocks you. On my web host (Pair Networks) a single POP3 logon is enough to 'verify' you for 90 minutes. Here is some sample PHP code that activates the POP3 logon and then sends an email via PHP Mailer:
<?php
$pop->authorise('pop3.example.com', 110, 30, 'mailer', 'password', 1);
$mail = new PHPMailer(); $mail->SMTPDebug = 2; $mail->isSMTP();
$mail->isHTML(false); $mail->Host = 'relay.example.com';
$mail->From = 'mailer@example.com';
$mail->FromName = 'Example Mailer';
$mail->Subject = 'My subject';
$mail->Body = 'Hello world';
$mail->addAddress('rich@corephp.co.uk', 'Richard Davey');
if (!$mail->send()) {
echo $mail->ErrorInfo;
}
?>
The PHP Mailer parts of this code should be obvious to anyone who has used PHP Mailer before. One thing to note - you almost certainly will not need to use SMTP Authentication *and* POP3 before SMTP together. The Authorisation method is a proxy method to all of the others within that class. There are connect, Logon and disconnect methods available, but I wrapped them in the single Authorisation one to make things easier.
The Parameters
The authorise parameters are as follows:
$pop->authorise('pop3.example.com', 110, 30, 'mailer', 'password', 1);
1. pop3.example.com - The POP3 Mail Server Name (hostname or IP address)
2. 110 - The POP3 Port on which to connect (default is usually 110, but check with your host)
3. 30 - A connection time-out value (in seconds)
4. mailer - The POP3 Username required to logon
5. password - The POP3 Password required to logon
6. 1 - The class debug level (0 = off, 1+ = debug output is echoed to the browser)
Final Comments + the Download
1) This class does not support APOP connections. This is only because I did not have an APOP server to test with, but if you'd like to see that added just contact me.
2) Opening and closing lots of POP3 connections can be quite a resource/network drain. If you need to send a whole batch of emails then just perform the authentication once at the start, and then loop through your mail sending script. Providing this process doesn't take longer than the verification period lasts on your POP3 server, you should be fine. With my host that period is 90 minutes, i.e. plenty of time.
3) If you have heavy requirements for this script (i.e. send a LOT of email on a frequent basis) then I would advise seeking out an alternative sending method (direct SMTP ideally). If this isn't possible then you could modify this class so the 'last authorised' date is recorded somewhere (MySQL, Flat file, etc) meaning you only open a new connection if the old one has expired, saving you precious overhead.
4) There are lots of other POP3 classes for PHP available. However most of them implement the full POP3 command set, where-as this one is purely for authentication, and much lighter as a result. However using any of the other POP3 classes to just logon to your server would have the same net result. At the end of the day, use whatever method you feel most comfortable with.
Download
My thanks to Chris Ryan for the inspiration (even if indirectly, via his SMTP class)

38
examples/DKIM.phps Normal file
View File

@ -0,0 +1,38 @@
<?php
/**
* This example shows how to use DKIM message authentication with PHPMailer.
* There's more to using DKIM than just this code - check out this article:
* @link https://yomotherboard.com/how-to-setup-email-server-dkim-keys/
* See also the DKIM code in the PHPMailer unit tests,
* which shows how to make a key pair from PHP.
*/
require '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer;
//Set who the message is to be sent from
$mail->setFrom('from@example.com', 'First Last');
//Set an alternative reply-to address
$mail->addReplyTo('replyto@example.com', 'First Last');
//Set who the message is to be sent to
$mail->addAddress('whoto@example.com', 'John Doe');
//Set the subject line
$mail->Subject = 'PHPMailer DKIM test';
//This should be the same as the domain of your From address
$mail->DKIM_domain = 'example.com';
//Path to your private key file
$mail->DKIM_private = 'dkim_private.pem';
//Set this to your own selector
$mail->DKIM_selector = 'phpmailer';
//If your private key has a passphrase, set it here
$mail->DKIM_passphrase = '';
//The identity you're signing as - usually your From address
$mail->DKIM_identity = $mail->From;
//send the message, check for errors
if (!$mail->send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent!";
}

View File

@ -1,81 +0,0 @@
<?php
/**
* This shows how to make a new public/private key pair suitable for use with DKIM.
* You should only need to do this once, and the public key (**not** the private key!)
* you generate should be inserted in your DNS matching the selector you want.
*
* You can also use the DKIM wizard here: https://www.sparkpost.com/resources/tools/dkim-wizard/
* but be aware that having your private key known anywhere outside your own server
* is a security risk, and it's easy enough to create your own on your own server.
*
* For security, any keys you create should not be accessible via your web site.
*
* 2048 bits is the recommended minimum key length - gmail won't accept less than 1024 bits.
* To test your DKIM config, use Sparkpost's DKIM tester:
* https://tools.sparkpost.com/dkim
*
* Note that you only need a *private* key to *send* a DKIM-signed message,
* but receivers need your *public* key in order to verify it.
*
* Your public key will need to be formatted appropriately for your DNS and
* inserted there using the selector you want to use.
*/
//Set these to match your domain and chosen DKIM selector
$domain = 'example.com';
$selector = 'phpmailer';
//Private key filename for this selector
$privatekeyfile = $selector . '_dkim_private.pem';
//Public key filename for this selector
$publickeyfile = $selector . '_dkim_public.pem';
if (file_exists($privatekeyfile)) {
echo "Using existing keys - if you want to generate new keys, delete old key files first.\n\n";
$privatekey = file_get_contents($privatekeyfile);
$publickey = file_get_contents($publickeyfile);
} else {
//Create a 2048-bit RSA key with an SHA256 digest
$pk = openssl_pkey_new(
[
'digest_alg' => 'sha256',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
]
);
//Save private key
openssl_pkey_export_to_file($pk, $privatekeyfile);
//Save public key
$pubKey = openssl_pkey_get_details($pk);
$publickey = $pubKey['key'];
file_put_contents($publickeyfile, $publickey);
$privatekey = file_get_contents($privatekeyfile);
}
echo "Private key (keep this private!):\n\n" . $privatekey;
echo "\n\nPublic key:\n\n" . $publickey;
//Prepare public key for DNS, e.g.
//phpmailer._domainkey.example.com IN TXT "v=DKIM1; h=sha256; t=s; p=" "MIIBIjANBg...oXlwIDAQAB"...
$dnskey = "$selector._domainkey.$domain IN TXT";
$dnsvalue = '"v=DKIM1; h=sha256; t=s; p=" ';
//Some DNS servers don't like ;(semi colon) chars unless backslash-escaped
$dnsvalue2 = '"v=DKIM1\; h=sha256\; t=s\; p=" ';
//Strip and split the key into smaller parts and format for DNS
//Many DNS systems don't like long TXT entries
//but are OK if it's split into 255-char chunks
//Remove PEM wrapper
$publickey = preg_replace('/^-+.*?-+$/m', '', $publickey);
//Strip line breaks
$publickey = str_replace(["\r", "\n"], '', $publickey);
//Split into chunks
$keyparts = str_split($publickey, 253); //Becomes 255 when quotes are included
//Quote each chunk
foreach ($keyparts as $keypart) {
$dnsvalue .= '"' . trim($keypart) . '" ';
$dnsvalue2 .= '"' . trim($keypart) . '" ';
}
echo "\n\nDNS key:\n\n" . trim($dnskey);
echo "\n\nDNS value:\n\n" . trim($dnsvalue);
echo "\n\nDNS value (with escaping):\n\n" . trim($dnsvalue2);

View File

@ -1,46 +0,0 @@
<?php
/**
* This example shows sending a DKIM-signed message with PHPMailer.
* More info about DKIM can be found here: https://www.dkim.org/info/dkim-faq.html
* There's more to using DKIM than just this code - check out this article:
* @see https://yomotherboard.com/how-to-setup-email-server-dkim-keys/
* See also the DKIM_gen_keys example code in the examples folder,
* which shows how to make a key pair from PHP.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/autoload.php';
//Usual setup
$mail = new PHPMailer();
$mail->setFrom('from@example.com', 'First Last');
$mail->addAddress('whoto@example.com', 'John Doe');
$mail->Subject = 'PHPMailer mail() test';
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
//This should be the same as the domain of your From address
$mail->DKIM_domain = 'example.com';
//See the DKIM_gen_keys.phps script for making a key pair -
//here we assume you've already done that.
//Path to your private key:
$mail->DKIM_private = 'dkim_private.pem';
//Set this to your own selector
$mail->DKIM_selector = 'phpmailer';
//Put your private key's passphrase in here if it has one
$mail->DKIM_passphrase = '';
//The identity you're signing as - usually your From address
$mail->DKIM_identity = $mail->From;
//Suppress listing signed header fields in signature, defaults to true for debugging purpose
$mail->DKIM_copyHeaderFields = false;
//Optionally you can add extra headers for signing to meet special requirements
$mail->DKIM_extraHeaders = ['List-Unsubscribe', 'List-Help'];
//When you send, the DKIM settings will be used to sign the message
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message sent!';
}

View File

@ -1,96 +0,0 @@
[![PHPMailer logo](images/phpmailer.png)](https://github.com/PHPMailer/PHPMailer)
# PHPMailer code examples
This folder contains a collection of examples of using [PHPMailer](https://github.com/PHPMailer/PHPMailer).
## About testing email sending
When working on email sending code you'll find yourself worrying about what might happen if all these test emails got sent to your mailing list. The solution is to use a fake mail server, one that acts just like the real thing, but just doesn't actually send anything out. Some offer web interfaces, feedback, logging, the ability to return specific error codes, all things that are useful for testing error handling, authentication etc. Here's a selection of mail testing tools you might like to try:
* [FakeEmail](https://github.com/tomwardill/FakeEmail), a Python-based fake mail server with a web interface.
* [smtp-sink](https://www.postfix.org/smtp-sink.1.html), part of the Postfix mail server, so you may have this installed already. This is used in the GitHub actions configuration to run PHPMailer's unit tests.
* [smtp4dev](https://github.com/rnwood/smtp4dev), a dummy SMTP server for Windows and Linux.
* [fakesendmail.sh](https://github.com/PHPMailer/PHPMailer/blob/master/test/fakesendmail.sh), part of PHPMailer's test setup, this is a shell script that emulates sendmail for testing 'mail' or 'sendmail' methods in PHPMailer.
* [HELO](https://usehelo.com), a very nice (commercial) mail server desktop app from BeyondCode, and [how to set it up for local testing](https://usehelo.com/blog/how-to-use-helo-with-phps-mail-function).
* [msglint](https://www.splitbrain.org/_static/msglint/), not a mail server, the IETF's MIME structure analyser checks the formatting of your messages.
* [MailHog](https://github.com/les-enovateurs/mailhog-examples), a Go-based email testing tool for developers with a web interface. You can use it with Docker and GitHub Actions to test your mails. The repository also contains a small part of PHPMailer's setup.
* [aboutmy.email](https://aboutmy.email), a service for evaluating your email config SPF, DKIM, DMARC, and compliance with list-unsubscribe, TLS, and many other settings.
Most of these examples use the `example.com` and `example.net` domains. These domains are reserved by IANA for illustrative purposes, as documented in [RFC 2606](https://www.rfc-editor.org/rfc/rfc2606). Don't use made-up domains like 'mydomain.com' or 'somedomain.com' in examples as someone, somewhere, probably owns them!
## Security note
Before running these examples in a web server, you'll need to rename them with '.php' extensions. They are supplied as '.phps' files which will usually be displayed with syntax highlighting by PHP instead of running them. This prevents potential security issues with running potential spam-gateway code if you happen to deploy these code examples on a live site - _please don't do that!_
Similarly, don't leave your passwords in these files as they will be visible to the world!
## [mail.phps](mail.phps)
This is a basic example which creates an email message from an external HTML file, creates a plain text body, sets various addresses, adds an attachment and sends the message. It uses PHP's built-in mail() function which is the simplest to use, but relies on the presence of a local mail server, something which is not usually available on Windows. If you find yourself in that situation, either install a local mail server, or use a remote one and send using SMTP instead.
## [simple_contact_form.phps](simple_contact_form.phps)
This is probably the most common reason for using PHPMailer - building a contact form. This example has a basic, unstyled form and also illustrates how to filter input data before using it, how to validate addresses, how to avoid being abused as a spam gateway, and how to address messages correctly so that you don't fail SPF checks.
## [exceptions.phps](exceptions.phps)
Like the mail example, but shows how to use PHPMailer's optional exceptions for error handling.
## [extending.phps](extending.phps)
This shows how to create a subclass of PHPMailer to customise its behaviour and simplify coding in your app.
## [smtp.phps](smtp.phps)
A simple example sending using SMTP with authentication.
## [smtp_no_auth.phps](smtp_no_auth.phps)
A simple example sending using SMTP without authentication.
## [send_file_upload.phps](send_file_upload.phps)
Lots of people want to do this... This is a simple form which accepts a file upload and emails it.
## [send_multiple_file_upload.phps](send_multiple_file_upload.phps)
A slightly more complex form that allows uploading multiple files at once and sends all of them as attachments to an email.
## [sendmail.phps](sendmail.phps)
A simple example using sendmail. Sendmail is a program (usually found on Linux/BSD, OS X and other UNIX-alikes) that can be used to submit messages to a local mail server without a lengthy SMTP conversation. It's probably the fastest sending mechanism, but lacks some error reporting features. There are sendmail emulators for most popular mail servers including postfix, qmail, exim etc.
## [gmail.phps](gmail.phps)
Submitting email via Google's Gmail service is a popular use of PHPMailer. It's much the same as normal SMTP sending, just with some specific settings, namely using TLS encryption, authentication is enabled, and it connects to the SMTP submission port 587 on the smtp.gmail.com host. This example does all that.
## [gmail_xoauth.phps](gmail_xoauth.phps)
Gmail now likes you to use XOAUTH2 for SMTP authentication. This is extremely laborious to set up, but once it's done you can use it repeatedly and will no longer need Gmail's ineptly-named "Allow less secure apps" setting enabled. [Read the guide in the wiki](https://github.com/PHPMailer/PHPMailer/wiki/Using-Gmail-with-XOAUTH2) for how to set it up.
## [pop_before_smtp.phps](pop_before_smtp.phps)
Back in the stone age, before effective SMTP authentication mechanisms were available, it was common for ISPs to use POP-before-SMTP authentication. As it implies, you authenticate using the POP3 protocol (an older protocol now mostly replaced by the far superior IMAP), and then the SMTP server will allow send access from your IP address for a short while, usually 5-15 minutes. PHPMailer includes a basic POP3 protocol client with just enough functionality to carry out this sequence - it's just like a normal SMTP conversation (without authentication), but connects via POP3 first.
## [mailing_list.phps](mailing_list.phps)
This is a somewhat naïve, but reasonably efficient example of sending similar emails to a list of different addresses. It sets up a PHPMailer instance using SMTP, then connects to a MySQL database to retrieve a list of recipients. The code loops over this list, sending email to each person using their info and marks them as sent in the database. It makes use of SMTP keepalive which saves reconnecting and re-authenticating between each message.
## [ssl_options.phps](ssl_options.phps)
PHP 5.6 introduced SSL certificate verification by default, and this applies to mail servers exactly as it does to web servers. Unfortunately, SSL misconfiguration in mail servers is quite common, so this caused a common problem: those that were previously using servers with bad configs suddenly found they stopped working when they upgraded PHP. PHPMailer provides a mechanism to disable SSL certificate verification as a workaround and this example shows how to do it. Bear in mind that this is **not** a good approach - the right way is to fix your mail server config!
## [smime_signed_mail.phps](smime_signed_mail.phps)
An example of how to sign messages using [S/MIME](https://en.wikipedia.org/wiki/S/MIME), ensuring that your data can't be tampered with in transit, and proves to recipients that it was you that sent it.
* * *
## [smtp_check.phps](smtp_check.phps)
This is an example showing how to use the SMTP class by itself (without PHPMailer) to check an SMTP connection.
## [smtp_low_memory.phps](smtp_low_memory.phps)
This demonstrates how to extend the SMTP class and make PHPMailer use it. In this case it's an effort to make the SMTP class use less memory when sending large attachments.
* * *

View File

@ -1,126 +0,0 @@
<?php
/**
* This example shows how to send via Microsoft Outlook's servers using XOAUTH2 authentication
* using the league/oauth2-client to provide the OAuth2 token.
* To use a different OAuth2 library create a wrapper class that implements OAuthTokenProvider and
* pass that wrapper class to PHPMailer::setOAuth().
*/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\OAuth;
//Alias the League Google OAuth2 provider class
use Greew\OAuth2\Client\Provider\Azure;
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
//Load dependencies from composer
//If this causes an error, run 'composer install'
require '../vendor/autoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
//SMTP::DEBUG_OFF = off (for production use)
//SMTP::DEBUG_CLIENT = client messages
//SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
//Set the hostname of the mail server
$mail->Host = 'smtp.office365.com';
//Set the SMTP port number:
// - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
// - 587 for SMTP+STARTTLS
$mail->Port = 587;
//Set the encryption mechanism to use:
// - SMTPS (implicit TLS on port 465) or
// - STARTTLS (explicit TLS on port 587)
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Set AuthType to use XOAUTH2
$mail->AuthType = 'XOAUTH2';
//Start Option 1: Use league/oauth2-client as OAuth2 token provider
//Fill in authentication details here
//Either the microsoft account owner, or the user that gave consent
$email = 'someone@somemicrosoftaccount.com';
$clientId = 'RANDOMCHARS-----duv1n2TS';
$clientSecret = 'RANDOMCHARS-----lGyjPcRtvP';
$tenantId = 'RANDOMCHARS-----HSFTAOIlagss';
//Obtained by configuring and running get_oauth_token.php
//after setting up an app in Google Developer Console.
$refreshToken = 'RANDOMCHARS-----DWxgOvPT003r-yFUV49TQYag7_Aod7y0';
//Create a new OAuth2 provider instance
$provider = new Azure(
[
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'tenantId' => $tenantId,
]
);
//Pass the OAuth provider instance to PHPMailer
$mail->setOAuth(
new OAuth(
[
'provider' => $provider,
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'refreshToken' => $refreshToken,
'userName' => $email,
]
)
);
//End Option 1
//Option 2: Another OAuth library as OAuth2 token provider
//Set up the other oauth library as per its documentation
//Then create the wrapper class that implementations OAuthTokenProvider
$oauthTokenProvider = new MyOAuthTokenProvider(/* Email, ClientId, ClientSecret, etc. */);
//Pass the implementation of OAuthTokenProvider to PHPMailer
$mail->setOAuth($oauthTokenProvider);
//End Option 2
//Set who the message is to be sent from
//For Outlook, this generally needs to be the same as the user you logged in as
$mail->setFrom($email, 'First Last');
//Set who the message is to be sent to
$mail->addAddress('someone@someserver.com', 'John Doe');
//Set the subject line
$mail->Subject = 'PHPMailer Outlook XOAUTH2 SMTP test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->CharSet = PHPMailer::CHARSET_UTF8;
$mail->msgHTML(file_get_contents('contentsutf8.html'), __DIR__);
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
$mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message sent!';
}

View File

@ -1,76 +0,0 @@
<?php
/**
* This example shows how to use a callback function from PHPMailer.
*/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require '../vendor/autoload.php';
/**
* Example PHPMailer callback function.
* This is a global function, but you can also pass a closure (or any other callable)
* to the `action_function` property.
*
* @param bool $result result of the send action
* @param array $to email address of the recipient
* @param array $cc cc email addresses
* @param array $bcc bcc email addresses
* @param string $subject the subject
* @param string $body the email body
*/
function callbackAction($result, $to, $cc, $bcc, $subject, $body)
{
echo "Message subject: \"$subject\"\n";
foreach ($to as $address) {
echo "Message to {$address[1]} <{$address[0]}>\n";
}
foreach ($cc as $address) {
echo "Message CC to {$address[1]} <{$address[0]}>\n";
}
foreach ($bcc as $toaddress) {
echo "Message BCC to {$toaddress[1]} <{$toaddress[0]}>\n";
}
if ($result) {
echo "Message sent successfully\n";
} else {
echo "Message send failed\n";
}
}
require_once '../vendor/autoload.php';
$mail = new PHPMailer();
try {
$mail->isMail();
$mail->setFrom('you@example.com', 'Your Name');
$mail->addAddress('jane@example.com', 'Jane Doe');
$mail->addCC('john@example.com', 'John Doe');
$mail->Subject = 'PHPMailer Test Subject';
$mail->msgHTML(file_get_contents('../examples/contents.html'));
//Optional - msgHTML will create an alternate automatically
$mail->AltBody = 'To view the message, please use an HTML compatible email viewer!';
$mail->addAttachment('images/phpmailer_mini.png');
$mail->action_function = 'callbackAction';
$mail->send();
} catch (Exception $e) {
echo $e->errorMessage();
}
//Alternative approach using a closure
try {
$mail->action_function = static function ($result, $to, $cc, $bcc, $subject, $body) {
if ($result) {
echo "Message sent successfully\n";
} else {
echo "Message send failed\n";
}
};
$mail->send();
} catch (Exception $e) {
echo $e->errorMessage();
}

View File

@ -0,0 +1,604 @@
<?php
/*
* A web form that both generates and uses PHPMailer code.
* revised, updated and corrected 27/02/2013
* by matt.sturdy@gmail.com
*/
require '../PHPMailerAutoload.php';
$CFG['smtp_debug'] = 2; //0 == off, 1 for client output, 2 for client and server
$CFG['smtp_debugoutput'] = 'html';
$CFG['smtp_server'] = 'localhost';
$CFG['smtp_port'] = '25';
$CFG['smtp_authenticate'] = false;
$CFG['smtp_username'] = 'name@example.com';
$CFG['smtp_password'] = 'yourpassword';
$CFG['smtp_secure'] = 'None';
$from_name = (isset($_POST['From_Name'])) ? $_POST['From_Name'] : '';
$from_email = (isset($_POST['From_Email'])) ? $_POST['From_Email'] : '';
$to_name = (isset($_POST['To_Name'])) ? $_POST['To_Name'] : '';
$to_email = (isset($_POST['To_Email'])) ? $_POST['To_Email'] : '';
$cc_email = (isset($_POST['cc_Email'])) ? $_POST['cc_Email'] : '';
$bcc_email = (isset($_POST['bcc_Email'])) ? $_POST['bcc_Email'] : '';
$subject = (isset($_POST['Subject'])) ? $_POST['Subject'] : '';
$message = (isset($_POST['Message'])) ? $_POST['Message'] : '';
$test_type = (isset($_POST['test_type'])) ? $_POST['test_type'] : 'smtp';
$smtp_debug = (isset($_POST['smtp_debug'])) ? $_POST['smtp_debug'] : $CFG['smtp_debug'];
$smtp_server = (isset($_POST['smtp_server'])) ? $_POST['smtp_server'] : $CFG['smtp_server'];
$smtp_port = (isset($_POST['smtp_port'])) ? $_POST['smtp_port'] : $CFG['smtp_port'];
$smtp_secure = strtolower((isset($_POST['smtp_secure'])) ? $_POST['smtp_secure'] : $CFG['smtp_secure']);
$smtp_authenticate = (isset($_POST['smtp_authenticate'])) ?
$_POST['smtp_authenticate'] : $CFG['smtp_authenticate'];
$authenticate_password = (isset($_POST['authenticate_password'])) ?
$_POST['authenticate_password'] : $CFG['smtp_password'];
$authenticate_username = (isset($_POST['authenticate_username'])) ?
$_POST['authenticate_username'] : $CFG['smtp_username'];
// storing all status output from the script to be shown to the user later
$results_messages = array();
// $example_code represents the "final code" that we're using, and will
// be shown to the user at the end.
$example_code = "\nrequire_once '../PHPMailerAutoload.php';";
$example_code .= "\n\n\$results_messages = array();";
$mail = new PHPMailer(true); //PHPMailer instance with exceptions enabled
$mail->CharSet = 'utf-8';
ini_set('default_charset', 'UTF-8');
$mail->Debugoutput = $CFG['smtp_debugoutput'];
$example_code .= "\n\n\$mail = new PHPMailer(true);";
$example_code .= "\n\$mail->CharSet = 'utf-8';";
$example_code .= "\nini_set('default_charset', 'UTF-8');";
class phpmailerAppException extends phpmailerException
{
}
$example_code .= "\n\nclass phpmailerAppException extends phpmailerException {}";
$example_code .= "\n\ntry {";
// Convert a string to its JavaScript representation.
function JSString($s) {
static $from = array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"');
static $to = array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\\"');
return is_null($s)? 'null': '"' . str_replace($from, $to, "$s") . '"';
}
try {
if (isset($_POST["submit"]) && $_POST['submit'] == "Submit") {
$to = $to_email;
if (!PHPMailer::validateAddress($to)) {
throw new phpmailerAppException("Email address " . $to . " is invalid -- aborting!");
}
$example_code .= "\n\$to = '" . addslashes($to_email) . "';";
$example_code .= "\nif(!PHPMailer::validateAddress(\$to)) {";
$example_code .= "\n throw new phpmailerAppException(\"Email address \" . " .
"\$to . \" is invalid -- aborting!\");";
$example_code .= "\n}";
switch ($test_type) {
case 'smtp':
$mail->isSMTP(); // telling the class to use SMTP
$mail->SMTPDebug = (integer)$smtp_debug;
$mail->Host = $smtp_server; // SMTP server
$mail->Port = (integer)$smtp_port; // set the SMTP port
if ($smtp_secure) {
$mail->SMTPSecure = strtolower($smtp_secure);
}
$mail->SMTPAuth = array_key_exists('smtp_authenticate', $_POST); // enable SMTP authentication?
if (array_key_exists('smtp_authenticate', $_POST)) {
$mail->Username = $authenticate_username; // SMTP account username
$mail->Password = $authenticate_password; // SMTP account password
}
$example_code .= "\n\$mail->isSMTP();";
$example_code .= "\n\$mail->SMTPDebug = " . (integer) $smtp_debug . ";";
$example_code .= "\n\$mail->Host = \"" . addslashes($smtp_server) . "\";";
$example_code .= "\n\$mail->Port = \"" . addslashes($smtp_port) . "\";";
$example_code .= "\n\$mail->SMTPSecure = \"" . addslashes(strtolower($smtp_secure)) . "\";";
$example_code .= "\n\$mail->SMTPAuth = " . (array_key_exists(
'smtp_authenticate',
$_POST
) ? 'true' : 'false') . ";";
if (array_key_exists('smtp_authenticate', $_POST)) {
$example_code .= "\n\$mail->Username = \"" . addslashes($authenticate_username) . "\";";
$example_code .= "\n\$mail->Password = \"" . addslashes($authenticate_password) . "\";";
}
break;
case 'mail':
$mail->isMail(); // telling the class to use PHP's mail()
$example_code .= "\n\$mail->isMail();";
break;
case 'sendmail':
$mail->isSendmail(); // telling the class to use Sendmail
$example_code .= "\n\$mail->isSendmail();";
break;
case 'qmail':
$mail->isQmail(); // telling the class to use Qmail
$example_code .= "\n\$mail->isQmail();";
break;
default:
throw new phpmailerAppException('Invalid test_type provided');
}
try {
if ($_POST['From_Name'] != '') {
$mail->addReplyTo($from_email, $from_name);
$mail->setFrom($from_email, $from_name);
$example_code .= "\n\$mail->addReplyTo(\"" .
addslashes($from_email) . "\", \"" . addslashes($from_name) . "\");";
$example_code .= "\n\$mail->setFrom(\"" .
addslashes($from_email) . "\", \"" . addslashes($from_name) . "\");";
} else {
$mail->addReplyTo($from_email);
$mail->setFrom($from_email, $from_email);
$example_code .= "\n\$mail->addReplyTo(\"" . addslashes($from_email) . "\");";
$example_code .= "\n\$mail->setFrom(\"" .
addslashes($from_email) . "\", \"" . addslashes($from_email) . "\");";
}
if ($_POST['To_Name'] != '') {
$mail->addAddress($to, $to_name);
$example_code .= "\n\$mail->addAddress(\"$to\", \"" . addslashes($to_name) . "\");";
} else {
$mail->addAddress($to);
$example_code .= "\n\$mail->addAddress(\"$to\");";
}
if ($_POST['bcc_Email'] != '') {
$indiBCC = explode(" ", $bcc_email);
foreach ($indiBCC as $key => $value) {
$mail->addBCC($value);
$example_code .= "\n\$mail->addBCC(\"" . addslashes($value) . "\");";
}
}
if ($_POST['cc_Email'] != '') {
$indiCC = explode(" ", $cc_Email);
foreach ($indiCC as $key => $value) {
$mail->addCC($value);
$example_code .= "\n\$mail->addCC(\"" . addslashes($value) . "\");";
}
}
} catch (phpmailerException $e) { //Catch all kinds of bad addressing
throw new phpmailerAppException($e->getMessage());
}
$mail->Subject = $subject . ' (PHPMailer test using ' . strtoupper($test_type) . ')';
$example_code .= "\n\$mail->Subject = \"" . addslashes($subject) .
' (PHPMailer test using ' . addslashes(strtoupper($test_type)) . ')";';
if ($_POST['Message'] == '') {
$body = file_get_contents('contents.html');
} else {
$body = $message;
}
$example_code .= "\n\$body = <<<'EOT'\n$body\nEOT;";
$mail->WordWrap = 78; // set word wrap to the RFC2822 limit
$mail->msgHTML($body, dirname(__FILE__), true); //Create message bodies and embed images
$example_code .= "\n\$mail->WordWrap = 78;";
$example_code .= "\n\$mail->msgHTML(\$body, dirname(__FILE__), true); //Create message bodies and embed images";
$mail->addAttachment('images/phpmailer_mini.png', 'phpmailer_mini.png'); // optional name
$mail->addAttachment('images/phpmailer.png', 'phpmailer.png'); // optional name
$example_code .= "\n\$mail->addAttachment('images/phpmailer_mini.png'," .
"'phpmailer_mini.png'); // optional name";
$example_code .= "\n\$mail->addAttachment('images/phpmailer.png', 'phpmailer.png'); // optional name";
$example_code .= "\n\ntry {";
$example_code .= "\n \$mail->send();";
$example_code .= "\n \$results_messages[] = \"Message has been sent using " .
addslashes(strtoupper($test_type)) . "\";";
$example_code .= "\n}";
$example_code .= "\ncatch (phpmailerException \$e) {";
$example_code .= "\n throw new phpmailerAppException('Unable to send to: ' . \$to. ': '.\$e->getMessage());";
$example_code .= "\n}";
try {
$mail->send();
$results_messages[] = "Message has been sent using " . strtoupper($test_type);
} catch (phpmailerException $e) {
throw new phpmailerAppException("Unable to send to: " . $to . ': ' . $e->getMessage());
}
}
} catch (phpmailerAppException $e) {
$results_messages[] = $e->errorMessage();
}
$example_code .= "\n}";
$example_code .= "\ncatch (phpmailerAppException \$e) {";
$example_code .= "\n \$results_messages[] = \$e->errorMessage();";
$example_code .= "\n}";
$example_code .= "\n\nif (count(\$results_messages) > 0) {";
$example_code .= "\n echo \"<h2>Run results</h2>\\n\";";
$example_code .= "\n echo \"<ul>\\n\";";
$example_code .= "\nforeach (\$results_messages as \$result) {";
$example_code .= "\n echo \"<li>\$result</li>\\n\";";
$example_code .= "\n}";
$example_code .= "\necho \"</ul>\\n\";";
$example_code .= "\n}";
?><!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PHPMailer Test Page</title>
<script type="text/javascript" src="scripts/shCore.js"></script>
<script type="text/javascript" src="scripts/shBrushPhp.js"></script>
<link type="text/css" rel="stylesheet" href="styles/shCore.css">
<link type="text/css" rel="stylesheet" href="styles/shThemeDefault.css">
<style>
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 1em;
padding: 1em;
}
table {
margin: 0 auto;
border-spacing: 0;
border-collapse: collapse;
}
table.column {
border-collapse: collapse;
background-color: #FFFFFF;
padding: 0.5em;
width: 35em;
}
td {
font-size: 1em;
padding: 0.1em 0.25em;
-moz-border-radius: 1em;
-webkit-border-radius: 1em;
border-radius: 1em;
}
td.colleft {
text-align: right;
width: 35%;
}
td.colrite {
text-align: left;
width: 65%;
}
fieldset {
padding: 1em 1em 1em 1em;
margin: 0 2em;
border-radius: 1.5em;
-webkit-border-radius: 1em;
-moz-border-radius: 1em;
}
fieldset.inner {
width: 40%;
}
fieldset:hover, tr:hover {
background-color: #fafafa;
}
legend {
font-weight: bold;
font-size: 1.1em;
}
div.column-left {
float: left;
width: 45em;
height: 31em;
}
div.column-right {
display: inline;
width: 45em;
max-height: 31em;
}
input.radio {
float: left;
}
div.radio {
padding: 0.2em;
}
</style>
<script>
SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
SyntaxHighlighter.all();
function startAgain() {
var post_params = {
"From_Name": <?php echo JSString($from_name); ?>,
"From_Email": <?php echo JSString($from_email); ?>,
"To_Name": <?php echo JSString($to_name); ?>,
"To_Email": <?php echo JSString($to_email); ?>,
"cc_Email": <?php echo JSString($cc_email); ?>,
"bcc_Email": <?php echo JSString($bcc_email); ?>,
"Subject": <?php echo JSString($subject); ?>,
"Message": <?php echo JSString($message); ?>,
"test_type": <?php echo JSString($test_type); ?>,
"smtp_debug": <?php echo JSString($smtp_debug); ?>,
"smtp_server": <?php echo JSString($smtp_server); ?>,
"smtp_port": <?php echo JSString($smtp_port); ?>,
"smtp_secure": <?php echo JSString($smtp_secure); ?>,
"smtp_authenticate": <?php echo JSString($smtp_authenticate); ?>,
"authenticate_username": <?php echo JSString($authenticate_username); ?>,
"authenticate_password": <?php echo JSString($authenticate_password); ?>
};
var resetForm = document.createElement("form");
resetForm.setAttribute("method", "POST");
resetForm.setAttribute("path", "index.php");
for (var k in post_params) {
var h = document.createElement("input");
h.setAttribute("type", "hidden");
h.setAttribute("name", k);
h.setAttribute("value", post_params[k]);
resetForm.appendChild(h);
}
document.body.appendChild(resetForm);
resetForm.submit();
}
function showHideDiv(test, element_id) {
var ops = {"smtp-options-table": "smtp"};
if (test == ops[element_id]) {
document.getElementById(element_id).style.display = "block";
} else {
document.getElementById(element_id).style.display = "none";
}
}
</script>
</head>
<body>
<?php
if (version_compare(PHP_VERSION, '5.0.0', '<')) {
echo 'Current PHP version: ' . phpversion() . "<br>";
echo exit("ERROR: Wrong PHP version. Must be PHP 5 or above.");
}
if (count($results_messages) > 0) {
echo '<h2>Run results</h2>';
echo '<ul>';
foreach ($results_messages as $result) {
echo "<li>$result</li>";
}
echo '</ul>';
}
if (isset($_POST["submit"]) && $_POST["submit"] == "Submit") {
echo "<button type=\"submit\" onclick=\"startAgain();\">Start Over</button><br>\n";
echo "<br><span>Script:</span>\n";
echo "<pre class=\"brush: php;\">\n";
echo htmlentities($example_code);
echo "\n</pre>\n";
echo "\n<hr style=\"margin: 3em;\">\n";
}
?>
<form method="POST" enctype="multipart/form-data">
<div>
<div class="column-left">
<fieldset>
<legend>Mail Details</legend>
<table border="1" class="column">
<tr>
<td class="colleft">
<label for="From_Name"><strong>From</strong> Name</label>
</td>
<td class="colrite">
<input type="text" id="From_Name" name="From_Name" value="<?php echo htmlentities($from_name); ?>"
style="width:95%;" autofocus placeholder="Your Name">
</td>
</tr>
<tr>
<td class="colleft">
<label for="From_Email"><strong>From</strong> Email Address</label>
</td>
<td class="colrite">
<input type="text" id="From_Email" name="From_Email" value="<?php echo htmlentities($from_email); ?>"
style="width:95%;" required placeholder="Your.Email@example.com">
</td>
</tr>
<tr>
<td class="colleft">
<label for="To_Name"><strong>To</strong> Name</label>
</td>
<td class="colrite">
<input type="text" id="To_Name" name="To_Name" value="<?php echo htmlentities($to_name); ?>"
style="width:95%;" placeholder="Recipient's Name">
</td>
</tr>
<tr>
<td class="colleft">
<label for="To_Email"><strong>To</strong> Email Address</label>
</td>
<td class="colrite">
<input type="text" id="To_Email" name="To_Email" value="<?php echo htmlentities($to_email); ?>"
style="width:95%;" required placeholder="Recipients.Email@example.com">
</td>
</tr>
<tr>
<td class="colleft">
<label for="cc_Email"><strong>CC Recipients</strong><br>
<small>(separate with commas)</small>
</label>
</td>
<td class="colrite">
<input type="text" id="cc_Email" name="cc_Email" value="<?php echo htmlentities($cc_email); ?>"
style="width:95%;" placeholder="cc1@example.com, cc2@example.com">
</td>
</tr>
<tr>
<td class="colleft">
<label for="bcc_Email"><strong>BCC Recipients</strong><br>
<small>(separate with commas)</small>
</label>
</td>
<td class="colrite">
<input type="text" id="bcc_Email" name="bcc_Email" value="<?php echo htmlentities($bcc_email); ?>"
style="width:95%;" placeholder="bcc1@example.com, bcc2@example.com">
</td>
</tr>
<tr>
<td class="colleft">
<label for="Subject"><strong>Subject</strong></label>
</td>
<td class="colrite">
<input type="text" name="Subject" id="Subject" value="<?php echo htmlentities($subject); ?>"
style="width:95%;" placeholder="Email Subject">
</td>
</tr>
<tr>
<td class="colleft">
<label for="Message"><strong>Message</strong><br>
<small>If blank, will use content.html</small>
</label>
</td>
<td class="colrite">
<textarea name="Message" id="Message" style="width:95%;height:5em;"
placeholder="Body of your email"><?php echo htmlentities($message); ?></textarea>
</td>
</tr>
</table>
<div style="margin:1em 0;">Test will include two attachments.</div>
</fieldset>
</div>
<div class="column-right">
<fieldset class="inner"> <!-- SELECT TYPE OF MAIL -->
<legend>Mail Test Specs</legend>
<table border="1" class="column">
<tr>
<td class="colleft">Test Type</td>
<td class="colrite">
<div class="radio">
<label for="radio-mail">Mail()</label>
<input class="radio" type="radio" name="test_type" value="mail" id="radio-mail"
onclick="showHideDiv(this.value, 'smtp-options-table');"
<?php echo ($test_type == 'mail') ? 'checked' : ''; ?>
required>
</div>
<div class="radio">
<label for="radio-sendmail">Sendmail</label>
<input class="radio" type="radio" name="test_type" value="sendmail" id="radio-sendmail"
onclick="showHideDiv(this.value, 'smtp-options-table');"
<?php echo ($test_type == 'sendmail') ? 'checked' : ''; ?>
required>
</div>
<div class="radio">
<label for="radio-qmail">Qmail</label>
<input class="radio" type="radio" name="test_type" value="qmail" id="radio-qmail"
onclick="showHideDiv(this.value, 'smtp-options-table');"
<?php echo ($test_type == 'qmail') ? 'checked' : ''; ?>
required>
</div>
<div class="radio">
<label for="radio-smtp">SMTP</label>
<input class="radio" type="radio" name="test_type" value="smtp" id="radio-smtp"
onclick="showHideDiv(this.value, 'smtp-options-table');"
<?php echo ($test_type == 'smtp') ? 'checked' : ''; ?>
required>
</div>
</td>
</tr>
</table>
<div id="smtp-options-table" style="margin:1em 0 0 0;
<?php if ($test_type != 'smtp') {
echo "display: none;";
} ?>">
<span style="margin:1.25em 0; display:block;"><strong>SMTP Specific Options:</strong></span>
<table border="1" class="column">
<tr>
<td class="colleft"><label for="smtp_debug">SMTP Debug ?</label></td>
<td class="colrite">
<select size="1" id="smtp_debug" name="smtp_debug">
<option <?php echo ($smtp_debug == '0') ? 'selected' : ''; ?> value="0">
0 - Disabled
</option>
<option <?php echo ($smtp_debug == '1') ? 'selected' : ''; ?> value="1">
1 - Client messages
</option>
<option <?php echo ($smtp_debug == '2') ? 'selected' : ''; ?> value="2">
2 - Client and server messages
</option>
</select>
</td>
</tr>
<tr>
<td class="colleft"><label for="smtp_server">SMTP Server</label></td>
<td class="colrite">
<input type="text" id="smtp_server" name="smtp_server"
value="<?php echo htmlentities($smtp_server); ?>" style="width:95%;"
placeholder="smtp.server.com">
</td>
</tr>
<tr>
<td class="colleft" style="width: 5em;"><label for="smtp_port">SMTP Port</label></td>
<td class="colrite">
<input type="text" name="smtp_port" id="smtp_port" size="3"
value="<?php echo htmlentities($smtp_port); ?>" placeholder="Port">
</td>
</tr>
<tr>
<td class="colleft"><label for="smtp_secure">SMTP Security</label></td>
<td>
<select size="1" name="smtp_secure" id="smtp_secure">
<option <?php echo ($smtp_secure == 'none') ? 'selected' : '' ?>>None</option>
<option <?php echo ($smtp_secure == 'tls') ? 'selected' : '' ?>>TLS</option>
<option <?php echo ($smtp_secure == 'ssl') ? 'selected' : '' ?>>SSL</option>
</select>
</td>
</tr>
<tr>
<td class="colleft"><label for="smtp-authenticate">SMTP Authenticate?</label></td>
<td class="colrite">
<input type="checkbox" id="smtp-authenticate"
name="smtp_authenticate"
<?php if ($smtp_authenticate != '') {
echo "checked";
} ?>
value="true">
</td>
</tr>
<tr>
<td class="colleft"><label for="authenticate_username">Authenticate Username</label></td>
<td class="colrite">
<input type="text" id="authenticate_username" name="authenticate_username"
value="<?php echo htmlentities($authenticate_username); ?>" style="width:95%;"
placeholder="SMTP Server Username">
</td>
</tr>
<tr>
<td class="colleft"><label for="authenticate_password">Authenticate Password</label></td>
<td class="colrite">
<input type="password" name="authenticate_password" id="authenticate_password"
value="<?php echo htmlentities($authenticate_password); ?>" style="width:95%;"
placeholder="SMTP Server Password">
</td>
</tr>
</table>
</div>
</fieldset>
</div>
<br style="clear:both;">
<div style="margin-left:2em; margin-bottom:5em; float:left;">
<div style="margin-bottom: 1em; ">
<input type="submit" value="Submit" name="submit">
</div>
<?php echo 'Current PHP version: ' . phpversion(); ?>
</div>
</div>
</form>
</body>
</html>

View File

@ -1,146 +0,0 @@
<?php
/**
* This example shows how to handle a simple contact form safely.
*/
//Import PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
//Don't run this unless we're handling a form submission
if (array_key_exists('email', $_POST)) {
date_default_timezone_set('Etc/UTC');
require '../vendor/autoload.php';
$isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
//Create a new PHPMailer instance
$mail = new PHPMailer();
//Send using SMTP to localhost (faster and safer than using mail()) requires a local mail server
//See other examples for how to use a remote server such as gmail
$mail->isSMTP();
$mail->Host = 'localhost';
$mail->Port = 25;
//Use a fixed address in your own domain as the from address
//**DO NOT** use the submitter's address here as it will be forgery
//and will cause your messages to fail SPF checks
$mail->setFrom('from@example.com', 'First Last');
//Choose who the message should be sent to
//You don't have to use a <select> like in this example, you can simply use a fixed address
//the important thing is *not* to trust an email address submitted from the form directly,
//as an attacker can substitute their own and try to use your form to send spam
$addresses = [
'sales' => 'sales@example.com',
'support' => 'support@example.com',
'accounts' => 'accounts@example.com',
];
//Validate address selection before trying to use it
if (array_key_exists('dept', $_POST) && array_key_exists($_POST['dept'], $addresses)) {
$mail->addAddress($addresses[$_POST['dept']]);
} else {
//Fall back to a fixed address if dept selection is invalid or missing
$mail->addAddress('support@example.com');
}
//Put the submitter's address in a reply-to header
//This will fail if the address provided is invalid,
//in which case we should ignore the whole request
if ($mail->addReplyTo($_POST['email'], $_POST['name'])) {
$mail->Subject = 'PHPMailer contact form';
//Keep it simple - don't use HTML
$mail->isHTML(false);
//Build a simple message body
$mail->Body = <<<EOT
Email: {$_POST['email']}
Name: {$_POST['name']}
Message: {$_POST['message']}
EOT;
//Send the message, check for errors
if (!$mail->send()) {
//The reason for failing to send will be in $mail->ErrorInfo
//but it's unsafe to display errors directly to users - process the error, log it on your server.
if ($isAjax) {
http_response_code(500);
}
$response = [
"status" => false,
"message" => 'Sorry, something went wrong. Please try again later.'
];
} else {
$response = [
"status" => true,
"message" => 'Message sent! Thanks for contacting us.'
];
}
} else {
$response = [
"status" => false,
"message" => 'Invalid email address, message ignored.'
];
}
if ($isAjax) {
header('Content-type:application/json;charset=utf-8');
echo json_encode($response);
exit();
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Contact form</title>
</head>
<body>
<h1>Contact us</h1>
<h2 id="status-message"><?php if (isset($response)) {
echo $response['message'];
}?></h2>
<form method="POST" id="contact-form">
<label for="name">Name: <input type="text" name="name" id="name"></label><br>
<label for="email">Email address: <input type="email" name="email" id="email"></label><br>
<label for="message">Message: <textarea name="message" id="message" rows="8" cols="20"></textarea></label><br>
<label for="dept">Send query to department:</label>
<select name="dept" id="dept">
<option value="sales">Sales</option>
<option value="support" selected>Technical support</option>
<option value="accounts">Accounts</option>
</select><br>
<input type="submit" value="Send">
</form>
<script type="application/javascript">
const form = document.getElementById("contact-form")
function email(data) {
const message = document.getElementById("status-message")
fetch("", {
method: "POST",
body: data,
headers: {
'X-Requested-With' : 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(response => {message.innerHTML = response.message})
.catch(error => {
error.json().then(response => {
message.innerHTML = response.message
})
})
}
const submitEvent = form.addEventListener("submit", (event) => {
event.preventDefault();
const formData = new FormData(form);
email(formData);
})
</script>
</body>
</html>

View File

@ -1,23 +1,19 @@
<?php
/**
* This example shows how to handle a simple contact form safely.
* This example shows how to handle a simple contact form.
*/
//Import PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
$msg = '';
//Don't run this unless we're handling a form submission
if (array_key_exists('email', $_POST)) {
date_default_timezone_set('Etc/UTC');
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
//Send using SMTP to localhost (faster and safer than using mail()) requires a local mail server
//See other examples for how to use a remote server such as gmail
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP - requires a local mail server
//Faster and safer than using mail()
$mail->isSMTP();
$mail->Host = 'localhost';
$mail->Port = 25;
@ -26,22 +22,8 @@ if (array_key_exists('email', $_POST)) {
//**DO NOT** use the submitter's address here as it will be forgery
//and will cause your messages to fail SPF checks
$mail->setFrom('from@example.com', 'First Last');
//Choose who the message should be sent to
//You don't have to use a <select> like in this example, you can simply use a fixed address
//the important thing is *not* to trust an email address submitted from the form directly,
//as an attacker can substitute their own and try to use your form to send spam
$addresses = [
'sales' => 'sales@example.com',
'support' => 'support@example.com',
'accounts' => 'accounts@example.com',
];
//Validate address selection before trying to use it
if (array_key_exists('dept', $_POST) && array_key_exists($_POST['dept'], $addresses)) {
$mail->addAddress($addresses[$_POST['dept']]);
} else {
//Fall back to a fixed address if dept selection is invalid or missing
$mail->addAddress('support@example.com');
}
//Send the message to yourself, or whoever should receive contact for submissions
$mail->addAddress('whoto@example.com', 'John Doe');
//Put the submitter's address in a reply-to header
//This will fail if the address provided is invalid,
//in which case we should ignore the whole request
@ -58,7 +40,7 @@ EOT;
//Send the message, check for errors
if (!$mail->send()) {
//The reason for failing to send will be in $mail->ErrorInfo
//but it's unsafe to display errors directly to users - process the error, log it on your server.
//but you shouldn't display errors to users - process the error, log it on your server.
$msg = 'Sorry, something went wrong. Please try again later.';
} else {
$msg = 'Message sent! Thanks for contacting us.';
@ -83,12 +65,6 @@ EOT;
<label for="name">Name: <input type="text" name="name" id="name"></label><br>
<label for="email">Email address: <input type="email" name="email" id="email"></label><br>
<label for="message">Message: <textarea name="message" id="message" rows="8" cols="20"></textarea></label><br>
<label for="dept">Send query to department:</label>
<select name="dept" id="dept">
<option value="sales">Sales</option>
<option value="support" selected>Technical support</option>
<option value="accounts">Accounts</option>
</select><br>
<input type="submit" value="Send">
</form>
</body>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>PHPMailer Test</title>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PHPMailer Test</title>
@ -10,14 +10,12 @@
<div align="center">
<a href="https://github.com/PHPMailer/PHPMailer/"><img src="images/phpmailer.png" height="90" width="340" alt="PHPMailer rocks"></a>
</div>
<p>This example uses <strong>HTML</strong> with the UTF-8 Unicode charset.</p>
<p>This example uses <strong>HTML</strong>.</p>
<p>Chinese text: 郵件內容為空</p>
<p>Russian text: Пустое тело сообщения</p>
<p>Armenian text: Հաղորդագրությունը դատարկ է</p>
<p>Czech text: Prázdné tělo zprávy</p>
<p>Emoji: <span style="font-size: 48px">😂 🦄 💥 📤 📧</span></p>
<p>Image data URL (base64)<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="#"></p>
<p>Image data URL (URL-encoded)<img src="data:image/gif,GIF89a%01%00%01%00%00%00%00%21%F9%04%01%0A%00%01%00%2C%00%00%00%00%01%00%01%00%00%02%02L%01%00%3B" alt="#"></p>
</div>
</body>
</html>

View File

@ -1,14 +1,9 @@
<?php
/**
* This example shows how to make use of PHPMailer's exceptions for error handling.
*/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
//Passing true to the constructor enables the use of exceptions for error handling
@ -24,7 +19,7 @@ try {
$mail->Subject = 'PHPMailer Exceptions test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//and convert the HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
@ -32,9 +27,9 @@ try {
//send the message
//Note that we don't need check the response from this because it will throw an exception if it has trouble
$mail->send();
echo 'Message sent!';
} catch (Exception $e) {
echo "Message sent!";
} catch (phpmailerException $e) {
echo $e->errorMessage(); //Pretty error messages from PHPMailer
} catch (\Exception $e) { //The leading slash means the Global PHP Exception class will be caught
} catch (Exception $e) {
echo $e->getMessage(); //Boring error messages from anything else!
}

View File

@ -1,72 +0,0 @@
<?php
/**
* This example shows how to extend PHPMailer to simplify your coding.
* If PHPMailer doesn't do something the way you want it to, or your code
* contains too much boilerplate, don't edit the library files,
* create a subclass instead and customise that.
* That way all your changes will be retained when PHPMailer is updated.
*/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require '../vendor/autoload.php';
/**
* Use PHPMailer as a base class and extend it
*/
class MyPHPMailer extends PHPMailer
{
/**
* myPHPMailer constructor.
*
* @param bool|null $exceptions
* @param string $body A default HTML message body
*/
public function __construct($exceptions, $body = '')
{
//Don't forget to do this or other things may not be set correctly!
parent::__construct($exceptions);
//Set a default 'From' address
$this->setFrom('joe@example.com', 'Joe User');
//Send via SMTP
$this->isSMTP();
//Equivalent to setting `Host`, `Port` and `SMTPSecure` all at once
$this->Host = 'tls://smtp.example.com:587';
//Set an HTML and plain-text body, import relative image references
$this->msgHTML($body, './images/');
//Show debug output
$this->SMTPDebug = SMTP::DEBUG_SERVER;
//Inject a new debug output handler
$this->Debugoutput = static function ($str, $level) {
echo "Debug level $level; message: $str\n";
};
}
//Extend the send function
public function send()
{
$this->Subject = '[Yay for me!] ' . $this->Subject;
$r = parent::send();
echo 'I sent a message with subject ' . $this->Subject;
return $r;
}
}
//Now creating and sending a message becomes simpler when you use this class in your app code
try {
//Instantiate your new class, making use of the new `$body` parameter
$mail = new myPHPMailer(true, '<strong>This is the message body</strong>');
//Now you only need to set things that are different from the defaults you defined
$mail->addAddress('jane@example.com', 'Jane User');
$mail->Subject = 'Here is the subject';
$mail->addAttachment(__FILE__, 'myPHPMailer.php');
$mail->send(); //No need to check for errors - the exception handler will do it
} catch (Exception $e) {
//Note that this is catching the PHPMailer Exception class, not the global \Exception type!
echo 'Caught a ' . get_class($e) . ': ' . $e->getMessage();
}

View File

@ -1,63 +1,55 @@
<?php
/**
* This example shows settings to use when sending via Google's Gmail servers.
* This uses traditional id & password authentication - look at the gmail_xoauth.phps
* example to see how to use XOAUTH2.
* The IMAP section shows how to save this message to the 'Sent Mail' folder using IMAP commands.
*/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
//SMTP::DEBUG_OFF = off (for production use)
//SMTP::DEBUG_CLIENT = client messages
//SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2;
//Ask for HTML-friendly debug output
$mail->Debugoutput = 'html';
//Set the hostname of the mail server
$mail->Host = 'smtp.gmail.com';
//Use `$mail->Host = gethostbyname('smtp.gmail.com');`
//if your network does not support SMTP over IPv6,
//though this may cause issues with TLS
// use
// $mail->Host = gethostbyname('smtp.gmail.com');
// if your network does not support SMTP over IPv6
//Set the SMTP port number:
// - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
// - 587 for SMTP+STARTTLS
$mail->Port = 465;
//Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
$mail->Port = 587;
//Set the encryption mechanism to use:
// - SMTPS (implicit TLS on port 465) or
// - STARTTLS (explicit TLS on port 587)
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
//Set the encryption system to use - ssl (deprecated) or tls
$mail->SMTPSecure = 'tls';
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Username to use for SMTP authentication - use full email address for gmail
$mail->Username = 'username@gmail.com';
$mail->Username = "username@gmail.com";
//Password to use for SMTP authentication
$mail->Password = 'yourpassword';
$mail->Password = "yourpassword";
//Set who the message is to be sent from
//Note that with gmail you can only use your account address (same as `Username`)
//or predefined aliases that you have configured within your account.
//Do not use user-submitted addresses in here
$mail->setFrom('from@example.com', 'First Last');
//Set an alternative reply-to address
//This is a good place to put user-submitted addresses
$mail->addReplyTo('replyto@example.com', 'First Last');
//Set who the message is to be sent to
@ -68,7 +60,7 @@ $mail->Subject = 'PHPMailer GMail SMTP test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
@ -78,29 +70,30 @@ $mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo 'Message sent!';
echo "Message sent!";
//Section 2: IMAP
//Uncomment these to save your message in the 'Sent Mail' folder.
#save_mail($mail->getSentMIMEMessage());
#if (save_mail($mail)) {
# echo "Message saved!";
#}
}
//Section 2: IMAP
//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)
{
$mailbox = new \DirectoryTree\ImapEngine\Mailbox([
'host' => 'imap.gmail.com',
'port' => 993,
'encryption' => 'ssl',
'username' => 'user@example.com',
'password' => 'password',
]);
//IMAP commands requires the PHP IMAP Extension, found at: https://php.net/manual/en/imap.setup.php
//Function to call which uses the PHP imap_*() functions to save messages: https://php.net/manual/en/book.imap.php
//You can use imap_getmailboxes($imapStream, '/imap/ssl') to get a list of available folders or labels, this can
//be useful if you are trying to get this working on a non-Gmail IMAP server.
function save_mail($mail) {
//You can change 'Sent Mail' to any other folder or tag
$path = "{imap.gmail.com:993/imap/ssl}[Gmail]/Sent Mail";
// Find the "sent" messages folder yours may have a different name.
$folder = $mailbox->folders()->find('Sent Mail');
//Tell your server to open an IMAP connection using the same username and password as you used for SMTP
$imapStream = imap_open($path, $mail->Username, $mail->Password);
$folder->messages()->append($message);
$result = imap_append($imapStream, $path, $mail->getSentMIMEMessage());
imap_close($imapStream);
return $result;
}

View File

@ -1,121 +1,85 @@
<?php
/**
* This example shows how to send via Google's Gmail servers using XOAUTH2 authentication
* using the league/oauth2-client to provide the OAuth2 token.
* To use a different OAuth2 library create a wrapper class that implements OAuthTokenProvider and
* pass that wrapper class to PHPMailer::setOAuth().
* This example shows settings to use when sending via Google's Gmail servers.
*/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\OAuth;
//Alias the League Google OAuth2 provider class
use League\OAuth2\Client\Provider\Google;
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
require '../PHPMailerAutoload.php';
//Load dependencies from composer
//If this causes an error, run 'composer install'
require '../vendor/autoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
$mail = new PHPMailerOAuth;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
//SMTP::DEBUG_OFF = off (for production use)
//SMTP::DEBUG_CLIENT = client messages
//SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 0;
//Ask for HTML-friendly debug output
$mail->Debugoutput = 'html';
//Set the hostname of the mail server
$mail->Host = 'smtp.gmail.com';
//Set the SMTP port number:
// - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
// - 587 for SMTP+STARTTLS
$mail->Port = 465;
//Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
$mail->Port = 587;
//Set the encryption mechanism to use:
// - SMTPS (implicit TLS on port 465) or
// - STARTTLS (explicit TLS on port 587)
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
//Set the encryption system to use - ssl (deprecated) or tls
$mail->SMTPSecure = 'tls';
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Set AuthType to use XOAUTH2
//Set AuthType
$mail->AuthType = 'XOAUTH2';
//Start Option 1: Use league/oauth2-client as OAuth2 token provider
//Fill in authentication details here
//Either the gmail account owner, or the user that gave consent
$email = 'someone@gmail.com';
$clientId = 'RANDOMCHARS-----duv1n2.apps.googleusercontent.com';
$clientSecret = 'RANDOMCHARS-----lGyjPcRtvP';
//User Email to use for SMTP authentication - user who gave consent to our app
$mail->oauthUserEmail = "from@gmail.com";
//Obtained by configuring and running get_oauth_token.php
//after setting up an app in Google Developer Console.
$refreshToken = 'RANDOMCHARS-----DWxgOvPT003r-yFUV49TQYag7_Aod7y0';
//Obtained From Google Developer Console
$mail->oauthClientId = "RANDOMCHARS-----duv1n2.apps.googleusercontent.com";
//Create a new OAuth2 provider instance
$provider = new Google(
[
'clientId' => $clientId,
'clientSecret' => $clientSecret,
]
);
//Obtained From Google Developer Console
$mail->oauthClientSecret = "RANDOMCHARS-----lGyjPcRtvP";
//Pass the OAuth provider instance to PHPMailer
$mail->setOAuth(
new OAuth(
[
'provider' => $provider,
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'refreshToken' => $refreshToken,
'userName' => $email,
]
)
);
//End Option 1
//Option 2: Another OAuth library as OAuth2 token provider
//Set up the other oauth library as per its documentation
//Then create the wrapper class that implements OAuthTokenProvider
$oauthTokenProvider = new MyOAuthTokenProvider(/* Email, ClientId, ClientSecret, etc. */);
//Pass the implementation of OAuthTokenProvider to PHPMailer
$mail->setOAuth($oauthTokenProvider);
//End Option 2
//Obtained By running get_oauth_token.php after setting up APP in Google Developer Console.
//Set Redirect URI in Developer Console as [https/http]://<yourdomain>/<folder>/get_oauth_token.php
// eg: http://localhost/phpmail/get_oauth_token.php
$mail->oauthRefreshToken = "RANDOMCHARS-----DWxgOvPT003r-yFUV49TQYag7_Aod7y0";
//Set who the message is to be sent from
//For gmail, this generally needs to be the same as the user you logged in as
$mail->setFrom($email, 'First Last');
$mail->setFrom('from@example.com', 'First Last');
//Set who the message is to be sent to
$mail->addAddress('someone@gmail.com', 'John Doe');
$mail->addAddress('whoto@example.com', 'John Doe');
//Set the subject line
$mail->Subject = 'PHPMailer GMail XOAUTH2 SMTP test';
$mail->Subject = 'PHPMailer GMail SMTP test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->CharSet = PHPMailer::CHARSET_UTF8;
$mail->msgHTML(file_get_contents('contentsutf8.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
$mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo 'Message sent!';
echo "Message sent!";
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,209 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 1280 640" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g id="Background" transform="matrix(8.70744,5.33177e-16,-5.33177e-16,-4.35372,-4208.74,2147.69)">
<path d="M630.351,346.3L483.35,346.3L483.35,493.301L630.351,493.301L630.351,346.3L630.351,346.3Z" style="fill:rgb(51,51,51);fill-rule:nonzero;"/>
</g>
<g id="PHPMailer" transform="matrix(0.986688,0,0,0.986688,12.9314,1.29196)">
<g transform="matrix(1.14074,0,0,1,-76.5738,0)">
<g id="path68" transform="matrix(2.14981,0,0,-2.46335,-776.134,1230.68)">
<path d="M614.574,416.832L584.18,445.184L584.18,381.999L644.963,381.999L644.963,445.181L614.574,416.832Z" style="fill:rgb(248,203,102);fill-rule:nonzero;"/>
</g>
<g id="path74" transform="matrix(2.14981,0,0,-2.56665,-776.135,1278.22)">
<path d="M644.989,460.2L584.155,460.2L614.574,432.967L644.989,460.2Z" style="fill:rgb(248,203,102);fill-rule:nonzero;"/>
</g>
</g>
<g>
<g transform="matrix(260.4,0,0,280,52.6877,289.686)">
<path d="M0.488,-0.47C0.488,-0.441 0.484,-0.412 0.476,-0.385C0.468,-0.357 0.455,-0.333 0.439,-0.312C0.422,-0.29 0.4,-0.274 0.374,-0.261C0.348,-0.248 0.318,-0.242 0.282,-0.242L0.173,-0.242L0.173,0L0.055,0L0.055,-0.688L0.277,-0.688C0.314,-0.688 0.345,-0.683 0.371,-0.672C0.398,-0.662 0.419,-0.647 0.437,-0.627C0.454,-0.608 0.467,-0.585 0.476,-0.559C0.484,-0.532 0.488,-0.502 0.488,-0.47ZM0.369,-0.468C0.369,-0.503 0.36,-0.53 0.343,-0.549C0.326,-0.567 0.299,-0.576 0.264,-0.576L0.173,-0.576L0.173,-0.353L0.268,-0.353C0.285,-0.353 0.3,-0.356 0.313,-0.361C0.326,-0.367 0.336,-0.375 0.345,-0.385C0.353,-0.395 0.359,-0.407 0.363,-0.421C0.367,-0.435 0.369,-0.451 0.369,-0.468Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(260.4,0,0,280,184.157,289.686)">
<path d="M0.38,0L0.38,-0.273L0.173,-0.273L0.173,0L0.055,0L0.055,-0.688L0.173,-0.688L0.173,-0.382L0.38,-0.382L0.38,-0.688L0.498,-0.688L0.498,0L0.38,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(260.4,0,0,280,327.324,289.686)">
<path d="M0.488,-0.47C0.488,-0.441 0.484,-0.412 0.476,-0.385C0.468,-0.357 0.455,-0.333 0.439,-0.312C0.422,-0.29 0.4,-0.274 0.374,-0.261C0.348,-0.248 0.318,-0.242 0.282,-0.242L0.173,-0.242L0.173,0L0.055,0L0.055,-0.688L0.277,-0.688C0.314,-0.688 0.345,-0.683 0.371,-0.672C0.398,-0.662 0.419,-0.647 0.437,-0.627C0.454,-0.608 0.467,-0.585 0.476,-0.559C0.484,-0.532 0.488,-0.502 0.488,-0.47ZM0.369,-0.468C0.369,-0.503 0.36,-0.53 0.343,-0.549C0.326,-0.567 0.299,-0.576 0.264,-0.576L0.173,-0.576L0.173,-0.353L0.268,-0.353C0.285,-0.353 0.3,-0.356 0.313,-0.361C0.326,-0.367 0.336,-0.375 0.345,-0.385C0.353,-0.395 0.359,-0.407 0.363,-0.421C0.367,-0.435 0.369,-0.451 0.369,-0.468Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
</g>
<g>
<g transform="matrix(260.4,0,0,280,640.738,289.686)">
<path d="M0.453,0L0.352,-0.161L0.128,-0.161L0.128,0L0.021,0L0.021,-0.688L0.128,-0.688L0.57,0L0.453,0ZM0.282,-0.27L0.128,-0.515L0.128,-0.27L0.282,-0.27Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(260.4,0,0,280,787.905,289.686)">
<rect x="0.055" y="-0.688" width="0.119" height="0.688" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(260.4,0,0,280,816.346,289.686)">
<path d="M0.124,0L0.124,-0.688L0.242,-0.688L0.242,-0.111L0.499,-0.111L0.499,0L0.124,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(260.4,0,0,280,936.864,289.686)">
<path d="M0.089,0L0.089,-0.688L0.483,-0.688L0.483,-0.577L0.207,-0.577L0.207,-0.382L0.459,-0.382L0.459,-0.271L0.207,-0.271L0.207,-0.111L0.499,-0.111L0.499,0L0.089,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(233.533,0,0,280,1069.8,289.686)">
<path d="M0.442,0L0.312,-0.261L0.173,-0.261L0.173,0L0.055,0L0.055,-0.688L0.336,-0.688C0.372,-0.688 0.402,-0.683 0.429,-0.674C0.455,-0.664 0.477,-0.65 0.495,-0.633C0.512,-0.615 0.525,-0.593 0.534,-0.568C0.543,-0.543 0.547,-0.514 0.547,-0.483C0.547,-0.457 0.544,-0.434 0.538,-0.412C0.531,-0.391 0.523,-0.372 0.512,-0.355C0.501,-0.339 0.487,-0.325 0.472,-0.314C0.457,-0.302 0.44,-0.294 0.422,-0.289L0.575,0L0.442,0ZM0.428,-0.477C0.428,-0.511 0.419,-0.535 0.401,-0.552C0.383,-0.568 0.357,-0.576 0.324,-0.576L0.173,-0.576L0.173,-0.373L0.327,-0.373C0.345,-0.373 0.36,-0.376 0.373,-0.381C0.385,-0.386 0.396,-0.393 0.404,-0.402C0.412,-0.411 0.418,-0.422 0.422,-0.435C0.426,-0.448 0.428,-0.462 0.428,-0.477Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
</g>
</g>
<g transform="matrix(1,0,0,1,73.8296,353)">
<g transform="matrix(41,0,0,41,0,29.709)">
<path d="M0.352,-0.612L0.352,0L0.259,0L0.259,-0.612L0.022,-0.612L0.022,-0.688L0.588,-0.688L0.588,-0.612L0.352,-0.612Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,25.0444,29.709)">
<path d="M0.155,-0.438C0.165,-0.456 0.175,-0.471 0.187,-0.484C0.198,-0.496 0.21,-0.507 0.224,-0.515C0.238,-0.523 0.253,-0.529 0.269,-0.532C0.285,-0.536 0.304,-0.538 0.324,-0.538C0.358,-0.538 0.385,-0.534 0.407,-0.524C0.429,-0.515 0.446,-0.503 0.458,-0.486C0.471,-0.47 0.479,-0.45 0.484,-0.427C0.489,-0.404 0.491,-0.379 0.491,-0.352L0.491,0L0.403,0L0.403,-0.335C0.403,-0.357 0.401,-0.377 0.399,-0.394C0.396,-0.411 0.391,-0.425 0.383,-0.436C0.375,-0.448 0.364,-0.456 0.35,-0.462C0.335,-0.467 0.317,-0.47 0.294,-0.47C0.273,-0.47 0.254,-0.466 0.238,-0.459C0.221,-0.451 0.206,-0.441 0.195,-0.427C0.183,-0.414 0.174,-0.397 0.167,-0.377C0.16,-0.358 0.157,-0.336 0.157,-0.312L0.157,0L0.069,0L0.069,-0.725L0.157,-0.725L0.157,-0.536C0.157,-0.525 0.157,-0.515 0.157,-0.504C0.156,-0.493 0.156,-0.483 0.156,-0.474C0.155,-0.465 0.155,-0.457 0.154,-0.451C0.154,-0.445 0.154,-0.44 0.153,-0.438L0.155,-0.438Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,47.8467,29.709)">
<path d="M0.135,-0.246C0.135,-0.218 0.138,-0.192 0.143,-0.169C0.149,-0.146 0.158,-0.126 0.17,-0.109C0.182,-0.092 0.197,-0.079 0.215,-0.07C0.234,-0.061 0.256,-0.056 0.282,-0.056C0.32,-0.056 0.351,-0.064 0.374,-0.079C0.397,-0.094 0.412,-0.114 0.42,-0.137L0.498,-0.115C0.492,-0.101 0.484,-0.086 0.474,-0.071C0.464,-0.056 0.451,-0.043 0.435,-0.031C0.418,-0.019 0.397,-0.009 0.372,-0.002C0.347,0.006 0.317,0.01 0.282,0.01C0.204,0.01 0.145,-0.014 0.104,-0.06C0.063,-0.107 0.042,-0.176 0.042,-0.268C0.042,-0.317 0.049,-0.359 0.061,-0.393C0.073,-0.428 0.09,-0.456 0.112,-0.477C0.133,-0.499 0.158,-0.514 0.187,-0.524C0.216,-0.533 0.246,-0.538 0.279,-0.538C0.323,-0.538 0.36,-0.531 0.39,-0.517C0.42,-0.502 0.444,-0.483 0.462,-0.457C0.48,-0.432 0.493,-0.402 0.5,-0.368C0.508,-0.334 0.512,-0.297 0.512,-0.257L0.512,-0.246L0.135,-0.246ZM0.421,-0.313C0.416,-0.369 0.402,-0.409 0.378,-0.435C0.355,-0.46 0.321,-0.473 0.277,-0.473C0.263,-0.473 0.247,-0.471 0.231,-0.466C0.215,-0.461 0.2,-0.453 0.187,-0.441C0.173,-0.429 0.161,-0.413 0.152,-0.392C0.142,-0.371 0.137,-0.345 0.136,-0.313L0.421,-0.313Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,82.04,29.709)">
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,109.387,29.709)">
<path d="M0.547,0L0.547,-0.319L0.175,-0.319L0.175,0L0.082,0L0.082,-0.688L0.175,-0.688L0.175,-0.397L0.547,-0.397L0.547,-0.688L0.641,-0.688L0.641,0L0.547,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,138.996,29.709)">
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,176.993,29.709)">
<path d="M0.135,-0.246C0.135,-0.218 0.138,-0.192 0.143,-0.169C0.149,-0.146 0.158,-0.126 0.17,-0.109C0.182,-0.092 0.197,-0.079 0.215,-0.07C0.234,-0.061 0.256,-0.056 0.282,-0.056C0.32,-0.056 0.351,-0.064 0.374,-0.079C0.397,-0.094 0.412,-0.114 0.42,-0.137L0.498,-0.115C0.492,-0.101 0.484,-0.086 0.474,-0.071C0.464,-0.056 0.451,-0.043 0.435,-0.031C0.418,-0.019 0.397,-0.009 0.372,-0.002C0.347,0.006 0.317,0.01 0.282,0.01C0.204,0.01 0.145,-0.014 0.104,-0.06C0.063,-0.107 0.042,-0.176 0.042,-0.268C0.042,-0.317 0.049,-0.359 0.061,-0.393C0.073,-0.428 0.09,-0.456 0.112,-0.477C0.133,-0.499 0.158,-0.514 0.187,-0.524C0.216,-0.533 0.246,-0.538 0.279,-0.538C0.323,-0.538 0.36,-0.531 0.39,-0.517C0.42,-0.502 0.444,-0.483 0.462,-0.457C0.48,-0.432 0.493,-0.402 0.5,-0.368C0.508,-0.334 0.512,-0.297 0.512,-0.257L0.512,-0.246L0.135,-0.246ZM0.421,-0.313C0.416,-0.369 0.402,-0.409 0.378,-0.435C0.355,-0.46 0.321,-0.473 0.277,-0.473C0.263,-0.473 0.247,-0.471 0.231,-0.466C0.215,-0.461 0.2,-0.453 0.187,-0.441C0.173,-0.429 0.161,-0.413 0.152,-0.392C0.142,-0.371 0.137,-0.345 0.136,-0.313L0.421,-0.313Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,199.795,29.709)">
<path d="M0.375,0L0.375,-0.335C0.375,-0.361 0.373,-0.382 0.37,-0.399C0.367,-0.417 0.361,-0.431 0.354,-0.441C0.346,-0.452 0.336,-0.459 0.324,-0.464C0.311,-0.468 0.296,-0.47 0.278,-0.47C0.26,-0.47 0.243,-0.467 0.228,-0.459C0.213,-0.452 0.2,-0.441 0.19,-0.427C0.179,-0.414 0.171,-0.397 0.165,-0.376C0.16,-0.356 0.157,-0.333 0.157,-0.306L0.157,0L0.069,0L0.069,-0.416C0.069,-0.427 0.069,-0.438 0.069,-0.45C0.069,-0.463 0.069,-0.474 0.068,-0.485C0.068,-0.496 0.068,-0.505 0.067,-0.513C0.067,-0.521 0.067,-0.526 0.066,-0.528L0.149,-0.528C0.15,-0.527 0.15,-0.522 0.15,-0.515C0.151,-0.508 0.151,-0.5 0.152,-0.49C0.152,-0.481 0.153,-0.472 0.153,-0.462C0.153,-0.453 0.153,-0.444 0.153,-0.438L0.155,-0.438C0.163,-0.453 0.171,-0.467 0.18,-0.479C0.189,-0.492 0.2,-0.502 0.212,-0.511C0.224,-0.52 0.238,-0.526 0.254,-0.531C0.27,-0.536 0.288,-0.538 0.309,-0.538C0.349,-0.538 0.381,-0.53 0.404,-0.514C0.427,-0.498 0.444,-0.473 0.453,-0.438L0.454,-0.438C0.462,-0.453 0.471,-0.467 0.48,-0.479C0.49,-0.492 0.502,-0.502 0.515,-0.511C0.528,-0.52 0.542,-0.526 0.559,-0.531C0.575,-0.536 0.593,-0.538 0.614,-0.538C0.641,-0.538 0.664,-0.535 0.683,-0.527C0.703,-0.52 0.719,-0.509 0.731,-0.494C0.743,-0.479 0.752,-0.46 0.758,-0.436C0.764,-0.413 0.767,-0.385 0.767,-0.352L0.767,0L0.68,0L0.68,-0.335C0.68,-0.361 0.679,-0.382 0.675,-0.399C0.672,-0.417 0.667,-0.431 0.659,-0.441C0.651,-0.452 0.641,-0.459 0.629,-0.464C0.617,-0.468 0.601,-0.47 0.583,-0.47C0.565,-0.47 0.548,-0.467 0.533,-0.46C0.518,-0.453 0.505,-0.442 0.495,-0.429C0.484,-0.415 0.476,-0.398 0.47,-0.377C0.465,-0.357 0.462,-0.333 0.462,-0.306L0.462,0L0.375,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,233.948,29.709)">
<path d="M0.202,0.01C0.149,0.01 0.109,-0.004 0.083,-0.032C0.056,-0.06 0.042,-0.099 0.042,-0.147C0.042,-0.182 0.049,-0.211 0.062,-0.233C0.075,-0.255 0.093,-0.273 0.114,-0.286C0.135,-0.298 0.16,-0.307 0.187,-0.312C0.214,-0.317 0.242,-0.32 0.271,-0.32L0.389,-0.322L0.389,-0.351C0.389,-0.373 0.387,-0.391 0.382,-0.407C0.378,-0.422 0.371,-0.434 0.361,-0.444C0.352,-0.453 0.34,-0.46 0.326,-0.465C0.312,-0.469 0.295,-0.471 0.276,-0.471C0.259,-0.471 0.244,-0.47 0.23,-0.468C0.216,-0.465 0.204,-0.461 0.194,-0.454C0.184,-0.448 0.176,-0.439 0.17,-0.428C0.164,-0.418 0.16,-0.404 0.158,-0.387L0.066,-0.396C0.069,-0.416 0.075,-0.435 0.084,-0.453C0.094,-0.47 0.107,-0.485 0.123,-0.498C0.14,-0.511 0.161,-0.521 0.186,-0.528C0.212,-0.535 0.242,-0.538 0.278,-0.538C0.344,-0.538 0.394,-0.523 0.428,-0.492C0.461,-0.462 0.478,-0.418 0.478,-0.36L0.478,-0.133C0.478,-0.107 0.481,-0.087 0.488,-0.074C0.495,-0.061 0.508,-0.054 0.527,-0.054C0.532,-0.054 0.537,-0.055 0.542,-0.055C0.547,-0.056 0.552,-0.057 0.556,-0.058L0.556,-0.003C0.545,0 0.534,0.002 0.523,0.003C0.512,0.004 0.501,0.005 0.488,0.005C0.472,0.005 0.457,0.003 0.446,-0.002C0.434,-0.006 0.424,-0.013 0.417,-0.022C0.409,-0.031 0.403,-0.042 0.399,-0.055C0.396,-0.068 0.393,-0.083 0.392,-0.101L0.389,-0.101C0.38,-0.084 0.369,-0.069 0.358,-0.055C0.347,-0.042 0.334,-0.03 0.319,-0.02C0.304,-0.011 0.287,-0.003 0.268,0.002C0.249,0.007 0.227,0.01 0.202,0.01ZM0.222,-0.056C0.25,-0.056 0.275,-0.061 0.296,-0.072C0.317,-0.082 0.334,-0.095 0.348,-0.111C0.362,-0.127 0.372,-0.144 0.379,-0.163C0.386,-0.182 0.389,-0.2 0.389,-0.217L0.389,-0.261L0.293,-0.259C0.271,-0.258 0.251,-0.257 0.232,-0.254C0.212,-0.251 0.195,-0.246 0.181,-0.238C0.166,-0.23 0.154,-0.218 0.146,-0.204C0.137,-0.189 0.133,-0.17 0.133,-0.146C0.133,-0.117 0.141,-0.095 0.156,-0.08C0.171,-0.064 0.194,-0.056 0.222,-0.056Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,256.75,29.709)">
<path d="M0.067,-0.641L0.067,-0.725L0.155,-0.725L0.155,-0.641L0.067,-0.641ZM0.067,0L0.067,-0.528L0.155,-0.528L0.155,0L0.067,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,265.859,29.709)">
<rect x="0.067" y="-0.725" width="0.088" height="0.725" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,286.359,29.709)">
<path d="M0.134,-0.267C0.134,-0.236 0.136,-0.208 0.141,-0.183C0.145,-0.158 0.153,-0.136 0.163,-0.117C0.174,-0.099 0.187,-0.085 0.204,-0.075C0.221,-0.065 0.243,-0.06 0.268,-0.06C0.299,-0.06 0.325,-0.068 0.346,-0.085C0.367,-0.102 0.38,-0.128 0.385,-0.163L0.474,-0.157C0.471,-0.135 0.464,-0.114 0.455,-0.094C0.445,-0.074 0.432,-0.056 0.415,-0.041C0.398,-0.026 0.378,-0.013 0.354,-0.004C0.329,0.005 0.302,0.01 0.27,0.01C0.229,0.01 0.194,0.003 0.165,-0.011C0.136,-0.025 0.112,-0.045 0.094,-0.069C0.076,-0.094 0.063,-0.123 0.055,-0.156C0.047,-0.189 0.042,-0.226 0.042,-0.265C0.042,-0.3 0.045,-0.331 0.051,-0.359C0.057,-0.386 0.065,-0.41 0.076,-0.43C0.087,-0.45 0.099,-0.467 0.113,-0.481C0.128,-0.495 0.143,-0.506 0.16,-0.514C0.177,-0.523 0.194,-0.529 0.213,-0.532C0.231,-0.536 0.25,-0.538 0.269,-0.538C0.299,-0.538 0.325,-0.534 0.348,-0.526C0.371,-0.518 0.391,-0.507 0.408,-0.492C0.425,-0.478 0.438,-0.462 0.449,-0.442C0.459,-0.423 0.466,-0.403 0.471,-0.38L0.38,-0.374C0.376,-0.403 0.364,-0.426 0.346,-0.443C0.327,-0.461 0.301,-0.469 0.267,-0.469C0.242,-0.469 0.221,-0.465 0.204,-0.457C0.187,-0.448 0.174,-0.436 0.163,-0.419C0.153,-0.402 0.145,-0.381 0.141,-0.356C0.136,-0.331 0.134,-0.301 0.134,-0.267Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,306.859,29.709)">
<rect x="0.067" y="-0.725" width="0.088" height="0.725" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,315.968,29.709)">
<path d="M0.202,0.01C0.149,0.01 0.109,-0.004 0.083,-0.032C0.056,-0.06 0.042,-0.099 0.042,-0.147C0.042,-0.182 0.049,-0.211 0.062,-0.233C0.075,-0.255 0.093,-0.273 0.114,-0.286C0.135,-0.298 0.16,-0.307 0.187,-0.312C0.214,-0.317 0.242,-0.32 0.271,-0.32L0.389,-0.322L0.389,-0.351C0.389,-0.373 0.387,-0.391 0.382,-0.407C0.378,-0.422 0.371,-0.434 0.361,-0.444C0.352,-0.453 0.34,-0.46 0.326,-0.465C0.312,-0.469 0.295,-0.471 0.276,-0.471C0.259,-0.471 0.244,-0.47 0.23,-0.468C0.216,-0.465 0.204,-0.461 0.194,-0.454C0.184,-0.448 0.176,-0.439 0.17,-0.428C0.164,-0.418 0.16,-0.404 0.158,-0.387L0.066,-0.396C0.069,-0.416 0.075,-0.435 0.084,-0.453C0.094,-0.47 0.107,-0.485 0.123,-0.498C0.14,-0.511 0.161,-0.521 0.186,-0.528C0.212,-0.535 0.242,-0.538 0.278,-0.538C0.344,-0.538 0.394,-0.523 0.428,-0.492C0.461,-0.462 0.478,-0.418 0.478,-0.36L0.478,-0.133C0.478,-0.107 0.481,-0.087 0.488,-0.074C0.495,-0.061 0.508,-0.054 0.527,-0.054C0.532,-0.054 0.537,-0.055 0.542,-0.055C0.547,-0.056 0.552,-0.057 0.556,-0.058L0.556,-0.003C0.545,0 0.534,0.002 0.523,0.003C0.512,0.004 0.501,0.005 0.488,0.005C0.472,0.005 0.457,0.003 0.446,-0.002C0.434,-0.006 0.424,-0.013 0.417,-0.022C0.409,-0.031 0.403,-0.042 0.399,-0.055C0.396,-0.068 0.393,-0.083 0.392,-0.101L0.389,-0.101C0.38,-0.084 0.369,-0.069 0.358,-0.055C0.347,-0.042 0.334,-0.03 0.319,-0.02C0.304,-0.011 0.287,-0.003 0.268,0.002C0.249,0.007 0.227,0.01 0.202,0.01ZM0.222,-0.056C0.25,-0.056 0.275,-0.061 0.296,-0.072C0.317,-0.082 0.334,-0.095 0.348,-0.111C0.362,-0.127 0.372,-0.144 0.379,-0.163C0.386,-0.182 0.389,-0.2 0.389,-0.217L0.389,-0.261L0.293,-0.259C0.271,-0.258 0.251,-0.257 0.232,-0.254C0.212,-0.251 0.195,-0.246 0.181,-0.238C0.166,-0.23 0.154,-0.218 0.146,-0.204C0.137,-0.189 0.133,-0.17 0.133,-0.146C0.133,-0.117 0.141,-0.095 0.156,-0.08C0.171,-0.064 0.194,-0.056 0.222,-0.056Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,338.771,29.709)">
<path d="M0.464,-0.146C0.464,-0.121 0.459,-0.099 0.449,-0.08C0.44,-0.06 0.426,-0.044 0.408,-0.031C0.389,-0.018 0.367,-0.008 0.341,-0.001C0.314,0.006 0.284,0.01 0.25,0.01C0.219,0.01 0.191,0.007 0.167,0.003C0.142,-0.002 0.121,-0.01 0.102,-0.02C0.083,-0.03 0.068,-0.044 0.055,-0.061C0.043,-0.078 0.034,-0.099 0.028,-0.124L0.105,-0.139C0.113,-0.111 0.128,-0.09 0.152,-0.077C0.175,-0.064 0.208,-0.057 0.25,-0.057C0.268,-0.057 0.286,-0.058 0.302,-0.061C0.317,-0.064 0.331,-0.068 0.342,-0.074C0.354,-0.081 0.363,-0.089 0.369,-0.1C0.375,-0.11 0.378,-0.124 0.378,-0.139C0.378,-0.155 0.375,-0.168 0.367,-0.178C0.36,-0.189 0.349,-0.197 0.336,-0.204C0.323,-0.211 0.306,-0.217 0.287,-0.222C0.268,-0.227 0.247,-0.233 0.225,-0.239C0.203,-0.244 0.182,-0.25 0.162,-0.257C0.141,-0.264 0.122,-0.273 0.105,-0.284C0.088,-0.296 0.075,-0.31 0.064,-0.326C0.054,-0.343 0.049,-0.364 0.049,-0.389C0.049,-0.437 0.066,-0.474 0.1,-0.499C0.135,-0.524 0.185,-0.537 0.25,-0.537C0.309,-0.537 0.355,-0.526 0.389,-0.506C0.424,-0.485 0.445,-0.452 0.455,-0.407L0.375,-0.397C0.373,-0.411 0.367,-0.423 0.359,-0.432C0.352,-0.441 0.342,-0.449 0.331,-0.454C0.32,-0.46 0.308,-0.464 0.294,-0.467C0.28,-0.469 0.265,-0.47 0.25,-0.47C0.211,-0.47 0.181,-0.464 0.163,-0.452C0.144,-0.44 0.134,-0.422 0.134,-0.397C0.134,-0.383 0.138,-0.371 0.145,-0.362C0.152,-0.353 0.162,-0.345 0.174,-0.339C0.187,-0.332 0.202,-0.327 0.219,-0.322C0.237,-0.317 0.256,-0.312 0.277,-0.307C0.291,-0.304 0.306,-0.3 0.32,-0.296C0.335,-0.292 0.349,-0.287 0.363,-0.281C0.377,-0.275 0.39,-0.269 0.402,-0.261C0.414,-0.253 0.425,-0.244 0.434,-0.233C0.443,-0.223 0.45,-0.21 0.456,-0.196C0.461,-0.181 0.464,-0.165 0.464,-0.146Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,359.271,29.709)">
<path d="M0.464,-0.146C0.464,-0.121 0.459,-0.099 0.449,-0.08C0.44,-0.06 0.426,-0.044 0.408,-0.031C0.389,-0.018 0.367,-0.008 0.341,-0.001C0.314,0.006 0.284,0.01 0.25,0.01C0.219,0.01 0.191,0.007 0.167,0.003C0.142,-0.002 0.121,-0.01 0.102,-0.02C0.083,-0.03 0.068,-0.044 0.055,-0.061C0.043,-0.078 0.034,-0.099 0.028,-0.124L0.105,-0.139C0.113,-0.111 0.128,-0.09 0.152,-0.077C0.175,-0.064 0.208,-0.057 0.25,-0.057C0.268,-0.057 0.286,-0.058 0.302,-0.061C0.317,-0.064 0.331,-0.068 0.342,-0.074C0.354,-0.081 0.363,-0.089 0.369,-0.1C0.375,-0.11 0.378,-0.124 0.378,-0.139C0.378,-0.155 0.375,-0.168 0.367,-0.178C0.36,-0.189 0.349,-0.197 0.336,-0.204C0.323,-0.211 0.306,-0.217 0.287,-0.222C0.268,-0.227 0.247,-0.233 0.225,-0.239C0.203,-0.244 0.182,-0.25 0.162,-0.257C0.141,-0.264 0.122,-0.273 0.105,-0.284C0.088,-0.296 0.075,-0.31 0.064,-0.326C0.054,-0.343 0.049,-0.364 0.049,-0.389C0.049,-0.437 0.066,-0.474 0.1,-0.499C0.135,-0.524 0.185,-0.537 0.25,-0.537C0.309,-0.537 0.355,-0.526 0.389,-0.506C0.424,-0.485 0.445,-0.452 0.455,-0.407L0.375,-0.397C0.373,-0.411 0.367,-0.423 0.359,-0.432C0.352,-0.441 0.342,-0.449 0.331,-0.454C0.32,-0.46 0.308,-0.464 0.294,-0.467C0.28,-0.469 0.265,-0.47 0.25,-0.47C0.211,-0.47 0.181,-0.464 0.163,-0.452C0.144,-0.44 0.134,-0.422 0.134,-0.397C0.134,-0.383 0.138,-0.371 0.145,-0.362C0.152,-0.353 0.162,-0.345 0.174,-0.339C0.187,-0.332 0.202,-0.327 0.219,-0.322C0.237,-0.317 0.256,-0.312 0.277,-0.307C0.291,-0.304 0.306,-0.3 0.32,-0.296C0.335,-0.292 0.349,-0.287 0.363,-0.281C0.377,-0.275 0.39,-0.269 0.402,-0.261C0.414,-0.253 0.425,-0.244 0.434,-0.233C0.443,-0.223 0.45,-0.21 0.456,-0.196C0.461,-0.181 0.464,-0.165 0.464,-0.146Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,391.162,29.709)">
<path d="M0.155,-0.438C0.165,-0.456 0.175,-0.471 0.187,-0.484C0.198,-0.496 0.21,-0.507 0.224,-0.515C0.238,-0.523 0.253,-0.529 0.269,-0.532C0.285,-0.536 0.304,-0.538 0.324,-0.538C0.358,-0.538 0.385,-0.534 0.407,-0.524C0.429,-0.515 0.446,-0.503 0.458,-0.486C0.471,-0.47 0.479,-0.45 0.484,-0.427C0.489,-0.404 0.491,-0.379 0.491,-0.352L0.491,0L0.403,0L0.403,-0.335C0.403,-0.357 0.401,-0.377 0.399,-0.394C0.396,-0.411 0.391,-0.425 0.383,-0.436C0.375,-0.448 0.364,-0.456 0.35,-0.462C0.335,-0.467 0.317,-0.47 0.294,-0.47C0.273,-0.47 0.254,-0.466 0.238,-0.459C0.221,-0.451 0.206,-0.441 0.195,-0.427C0.183,-0.414 0.174,-0.397 0.167,-0.377C0.16,-0.358 0.157,-0.336 0.157,-0.312L0.157,0L0.069,0L0.069,-0.725L0.157,-0.725L0.157,-0.536C0.157,-0.525 0.157,-0.515 0.157,-0.504C0.156,-0.493 0.156,-0.483 0.156,-0.474C0.155,-0.465 0.155,-0.457 0.154,-0.451C0.154,-0.445 0.154,-0.44 0.153,-0.438L0.155,-0.438Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,413.964,29.709)">
<path d="M0.271,-0.004C0.257,0 0.244,0.003 0.23,0.005C0.216,0.007 0.2,0.008 0.182,0.008C0.111,0.008 0.076,-0.032 0.076,-0.112L0.076,-0.464L0.015,-0.464L0.015,-0.528L0.08,-0.528L0.105,-0.646L0.164,-0.646L0.164,-0.528L0.262,-0.528L0.262,-0.464L0.164,-0.464L0.164,-0.131C0.164,-0.105 0.168,-0.088 0.177,-0.077C0.185,-0.067 0.199,-0.062 0.22,-0.062C0.228,-0.062 0.236,-0.063 0.244,-0.064C0.252,-0.065 0.261,-0.067 0.271,-0.069L0.271,-0.004Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,425.355,29.709)">
<path d="M0.271,-0.004C0.257,0 0.244,0.003 0.23,0.005C0.216,0.007 0.2,0.008 0.182,0.008C0.111,0.008 0.076,-0.032 0.076,-0.112L0.076,-0.464L0.015,-0.464L0.015,-0.528L0.08,-0.528L0.105,-0.646L0.164,-0.646L0.164,-0.528L0.262,-0.528L0.262,-0.464L0.164,-0.464L0.164,-0.131C0.164,-0.105 0.168,-0.088 0.177,-0.077C0.185,-0.067 0.199,-0.062 0.22,-0.062C0.228,-0.062 0.236,-0.063 0.244,-0.064C0.252,-0.065 0.261,-0.067 0.271,-0.069L0.271,-0.004Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,436.746,29.709)">
<path d="M0.514,-0.267C0.514,-0.227 0.511,-0.19 0.504,-0.156C0.498,-0.122 0.487,-0.093 0.472,-0.068C0.457,-0.044 0.437,-0.025 0.412,-0.011C0.387,0.003 0.356,0.01 0.32,0.01C0.282,0.01 0.249,0.003 0.221,-0.012C0.192,-0.026 0.171,-0.049 0.156,-0.082L0.153,-0.082C0.154,-0.081 0.154,-0.078 0.154,-0.073C0.154,-0.068 0.154,-0.062 0.155,-0.054C0.155,-0.046 0.155,-0.037 0.155,-0.028C0.155,-0.018 0.155,-0.008 0.155,0.001L0.155,0.208L0.067,0.208L0.067,-0.42C0.067,-0.433 0.067,-0.445 0.067,-0.457C0.067,-0.469 0.067,-0.479 0.066,-0.489C0.066,-0.499 0.066,-0.507 0.065,-0.514C0.065,-0.521 0.065,-0.525 0.064,-0.528L0.149,-0.528C0.15,-0.527 0.15,-0.524 0.151,-0.518C0.151,-0.512 0.152,-0.505 0.152,-0.497C0.153,-0.489 0.153,-0.48 0.154,-0.47C0.154,-0.461 0.154,-0.452 0.154,-0.443L0.156,-0.443C0.164,-0.46 0.174,-0.475 0.184,-0.487C0.194,-0.498 0.206,-0.508 0.22,-0.516C0.233,-0.524 0.248,-0.529 0.264,-0.532C0.281,-0.536 0.299,-0.538 0.32,-0.538C0.356,-0.538 0.387,-0.531 0.412,-0.518C0.437,-0.505 0.457,-0.487 0.472,-0.463C0.487,-0.44 0.498,-0.411 0.504,-0.378C0.511,-0.344 0.514,-0.307 0.514,-0.267ZM0.422,-0.265C0.422,-0.297 0.42,-0.326 0.416,-0.352C0.412,-0.377 0.405,-0.398 0.396,-0.416C0.386,-0.434 0.373,-0.447 0.357,-0.456C0.341,-0.465 0.321,-0.47 0.297,-0.47C0.278,-0.47 0.259,-0.467 0.242,-0.461C0.225,-0.456 0.21,-0.445 0.197,-0.43C0.184,-0.414 0.174,-0.392 0.167,-0.365C0.159,-0.337 0.155,-0.302 0.155,-0.258C0.155,-0.22 0.158,-0.189 0.165,-0.163C0.171,-0.137 0.18,-0.116 0.192,-0.1C0.204,-0.084 0.218,-0.073 0.236,-0.066C0.253,-0.059 0.274,-0.055 0.296,-0.055C0.321,-0.055 0.341,-0.06 0.357,-0.069C0.373,-0.079 0.386,-0.092 0.396,-0.11C0.405,-0.128 0.412,-0.15 0.416,-0.176C0.42,-0.202 0.422,-0.231 0.422,-0.265Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,459.548,29.709)">
<path d="M0.464,-0.146C0.464,-0.121 0.459,-0.099 0.449,-0.08C0.44,-0.06 0.426,-0.044 0.408,-0.031C0.389,-0.018 0.367,-0.008 0.341,-0.001C0.314,0.006 0.284,0.01 0.25,0.01C0.219,0.01 0.191,0.007 0.167,0.003C0.142,-0.002 0.121,-0.01 0.102,-0.02C0.083,-0.03 0.068,-0.044 0.055,-0.061C0.043,-0.078 0.034,-0.099 0.028,-0.124L0.105,-0.139C0.113,-0.111 0.128,-0.09 0.152,-0.077C0.175,-0.064 0.208,-0.057 0.25,-0.057C0.268,-0.057 0.286,-0.058 0.302,-0.061C0.317,-0.064 0.331,-0.068 0.342,-0.074C0.354,-0.081 0.363,-0.089 0.369,-0.1C0.375,-0.11 0.378,-0.124 0.378,-0.139C0.378,-0.155 0.375,-0.168 0.367,-0.178C0.36,-0.189 0.349,-0.197 0.336,-0.204C0.323,-0.211 0.306,-0.217 0.287,-0.222C0.268,-0.227 0.247,-0.233 0.225,-0.239C0.203,-0.244 0.182,-0.25 0.162,-0.257C0.141,-0.264 0.122,-0.273 0.105,-0.284C0.088,-0.296 0.075,-0.31 0.064,-0.326C0.054,-0.343 0.049,-0.364 0.049,-0.389C0.049,-0.437 0.066,-0.474 0.1,-0.499C0.135,-0.524 0.185,-0.537 0.25,-0.537C0.309,-0.537 0.355,-0.526 0.389,-0.506C0.424,-0.485 0.445,-0.452 0.455,-0.407L0.375,-0.397C0.373,-0.411 0.367,-0.423 0.359,-0.432C0.352,-0.441 0.342,-0.449 0.331,-0.454C0.32,-0.46 0.308,-0.464 0.294,-0.467C0.28,-0.469 0.265,-0.47 0.25,-0.47C0.211,-0.47 0.181,-0.464 0.163,-0.452C0.144,-0.44 0.134,-0.422 0.134,-0.397C0.134,-0.383 0.138,-0.371 0.145,-0.362C0.152,-0.353 0.162,-0.345 0.174,-0.339C0.187,-0.332 0.202,-0.327 0.219,-0.322C0.237,-0.317 0.256,-0.312 0.277,-0.307C0.291,-0.304 0.306,-0.3 0.32,-0.296C0.335,-0.292 0.349,-0.287 0.363,-0.281C0.377,-0.275 0.39,-0.269 0.402,-0.261C0.414,-0.253 0.425,-0.244 0.434,-0.233C0.443,-0.223 0.45,-0.21 0.456,-0.196C0.461,-0.181 0.464,-0.165 0.464,-0.146Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,480.048,29.709)">
<path d="M0.091,-0.427L0.091,-0.528L0.187,-0.528L0.187,-0.427L0.091,-0.427ZM0.091,0L0.091,-0.101L0.187,-0.101L0.187,0L0.091,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,491.439,29.709)">
<path d="M0,0.01L0.201,-0.725L0.278,-0.725L0.079,0.01L0,0.01Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,502.831,29.709)">
<path d="M0,0.01L0.201,-0.725L0.278,-0.725L0.079,0.01L0,0.01Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,514.222,29.709)">
<path d="M0.268,0.208C0.237,0.208 0.21,0.204 0.187,0.198C0.164,0.192 0.144,0.183 0.127,0.172C0.11,0.16 0.097,0.146 0.086,0.13C0.076,0.114 0.069,0.097 0.064,0.077L0.152,0.064C0.158,0.089 0.171,0.108 0.191,0.121C0.211,0.134 0.237,0.141 0.27,0.141C0.29,0.141 0.308,0.138 0.324,0.132C0.34,0.127 0.354,0.118 0.366,0.106C0.377,0.094 0.386,0.078 0.392,0.058C0.398,0.039 0.401,0.015 0.401,-0.013L0.401,-0.098L0.4,-0.098C0.394,-0.085 0.386,-0.072 0.376,-0.06C0.367,-0.048 0.355,-0.037 0.341,-0.027C0.327,-0.018 0.311,-0.01 0.293,-0.005C0.275,0.001 0.254,0.004 0.23,0.004C0.197,0.004 0.168,-0.002 0.144,-0.013C0.12,-0.024 0.101,-0.041 0.086,-0.063C0.071,-0.086 0.059,-0.114 0.052,-0.147C0.045,-0.181 0.042,-0.219 0.042,-0.263C0.042,-0.306 0.045,-0.344 0.052,-0.377C0.059,-0.411 0.071,-0.44 0.087,-0.464C0.102,-0.487 0.123,-0.505 0.148,-0.518C0.173,-0.53 0.204,-0.537 0.24,-0.537C0.278,-0.537 0.31,-0.528 0.338,-0.511C0.365,-0.494 0.386,-0.47 0.401,-0.438L0.402,-0.438C0.402,-0.446 0.403,-0.455 0.403,-0.465C0.404,-0.475 0.404,-0.485 0.405,-0.494C0.405,-0.503 0.406,-0.511 0.406,-0.517C0.407,-0.524 0.408,-0.527 0.408,-0.528L0.492,-0.528C0.491,-0.525 0.491,-0.52 0.491,-0.513C0.49,-0.506 0.49,-0.498 0.49,-0.488C0.489,-0.479 0.489,-0.468 0.489,-0.456C0.489,-0.444 0.489,-0.432 0.489,-0.419L0.489,-0.015C0.489,0.059 0.471,0.114 0.434,0.152C0.398,0.189 0.342,0.208 0.268,0.208ZM0.401,-0.264C0.401,-0.301 0.397,-0.332 0.389,-0.359C0.381,-0.385 0.371,-0.406 0.358,-0.423C0.345,-0.439 0.33,-0.452 0.313,-0.459C0.296,-0.467 0.279,-0.471 0.262,-0.471C0.239,-0.471 0.22,-0.467 0.204,-0.459C0.188,-0.452 0.174,-0.439 0.164,-0.423C0.153,-0.406 0.145,-0.384 0.14,-0.358C0.135,-0.332 0.133,-0.301 0.133,-0.264C0.133,-0.226 0.135,-0.194 0.14,-0.168C0.145,-0.142 0.153,-0.121 0.164,-0.105C0.174,-0.09 0.187,-0.078 0.203,-0.071C0.219,-0.064 0.238,-0.061 0.26,-0.061C0.278,-0.061 0.295,-0.065 0.312,-0.072C0.329,-0.08 0.344,-0.092 0.357,-0.108C0.37,-0.124 0.381,-0.145 0.389,-0.171C0.397,-0.197 0.401,-0.228 0.401,-0.264Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,537.024,29.709)">
<path d="M0.067,-0.641L0.067,-0.725L0.155,-0.725L0.155,-0.641L0.067,-0.641ZM0.067,0L0.067,-0.528L0.155,-0.528L0.155,0L0.067,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,546.133,29.709)">
<path d="M0.271,-0.004C0.257,0 0.244,0.003 0.23,0.005C0.216,0.007 0.2,0.008 0.182,0.008C0.111,0.008 0.076,-0.032 0.076,-0.112L0.076,-0.464L0.015,-0.464L0.015,-0.528L0.08,-0.528L0.105,-0.646L0.164,-0.646L0.164,-0.528L0.262,-0.528L0.262,-0.464L0.164,-0.464L0.164,-0.131C0.164,-0.105 0.168,-0.088 0.177,-0.077C0.185,-0.067 0.199,-0.062 0.22,-0.062C0.228,-0.062 0.236,-0.063 0.244,-0.064C0.252,-0.065 0.261,-0.067 0.271,-0.069L0.271,-0.004Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,557.524,29.709)">
<path d="M0.155,-0.438C0.165,-0.456 0.175,-0.471 0.187,-0.484C0.198,-0.496 0.21,-0.507 0.224,-0.515C0.238,-0.523 0.253,-0.529 0.269,-0.532C0.285,-0.536 0.304,-0.538 0.324,-0.538C0.358,-0.538 0.385,-0.534 0.407,-0.524C0.429,-0.515 0.446,-0.503 0.458,-0.486C0.471,-0.47 0.479,-0.45 0.484,-0.427C0.489,-0.404 0.491,-0.379 0.491,-0.352L0.491,0L0.403,0L0.403,-0.335C0.403,-0.357 0.401,-0.377 0.399,-0.394C0.396,-0.411 0.391,-0.425 0.383,-0.436C0.375,-0.448 0.364,-0.456 0.35,-0.462C0.335,-0.467 0.317,-0.47 0.294,-0.47C0.273,-0.47 0.254,-0.466 0.238,-0.459C0.221,-0.451 0.206,-0.441 0.195,-0.427C0.183,-0.414 0.174,-0.397 0.167,-0.377C0.16,-0.358 0.157,-0.336 0.157,-0.312L0.157,0L0.069,0L0.069,-0.725L0.157,-0.725L0.157,-0.536C0.157,-0.525 0.157,-0.515 0.157,-0.504C0.156,-0.493 0.156,-0.483 0.156,-0.474C0.155,-0.465 0.155,-0.457 0.154,-0.451C0.154,-0.445 0.154,-0.44 0.153,-0.438L0.155,-0.438Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,580.326,29.709)">
<path d="M0.153,-0.528L0.153,-0.193C0.153,-0.168 0.155,-0.146 0.159,-0.129C0.163,-0.112 0.169,-0.098 0.177,-0.087C0.186,-0.077 0.197,-0.069 0.211,-0.065C0.225,-0.06 0.242,-0.058 0.262,-0.058C0.283,-0.058 0.302,-0.062 0.319,-0.069C0.335,-0.076 0.35,-0.087 0.362,-0.101C0.373,-0.115 0.383,-0.132 0.389,-0.152C0.396,-0.172 0.399,-0.196 0.399,-0.222L0.399,-0.528L0.487,-0.528L0.487,-0.113C0.487,-0.102 0.487,-0.09 0.487,-0.078C0.487,-0.066 0.487,-0.054 0.488,-0.043C0.488,-0.032 0.488,-0.023 0.489,-0.015C0.489,-0.007 0.489,-0.002 0.49,0L0.407,0C0.406,-0.002 0.406,-0.006 0.406,-0.013C0.405,-0.02 0.405,-0.029 0.405,-0.038C0.404,-0.047 0.404,-0.057 0.403,-0.066C0.403,-0.076 0.403,-0.084 0.403,-0.09L0.401,-0.09C0.393,-0.075 0.384,-0.061 0.374,-0.049C0.363,-0.036 0.352,-0.026 0.338,-0.017C0.325,-0.009 0.31,-0.002 0.292,0.003C0.275,0.007 0.255,0.01 0.232,0.01C0.203,0.01 0.178,0.006 0.157,-0.001C0.136,-0.008 0.118,-0.019 0.104,-0.034C0.091,-0.049 0.081,-0.068 0.074,-0.092C0.068,-0.115 0.065,-0.143 0.065,-0.176L0.065,-0.528L0.153,-0.528Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,603.128,29.709)">
<path d="M0.514,-0.267C0.514,-0.082 0.449,0.01 0.32,0.01C0.28,0.01 0.247,0.003 0.22,-0.012C0.193,-0.026 0.172,-0.05 0.155,-0.082L0.154,-0.082C0.154,-0.074 0.154,-0.065 0.154,-0.056C0.153,-0.047 0.153,-0.038 0.152,-0.03C0.152,-0.022 0.151,-0.016 0.151,-0.01C0.15,-0.005 0.15,-0.001 0.149,0L0.064,0C0.065,-0.003 0.065,-0.008 0.065,-0.015C0.066,-0.022 0.066,-0.03 0.066,-0.04C0.067,-0.05 0.067,-0.061 0.067,-0.072C0.067,-0.084 0.067,-0.096 0.067,-0.109L0.067,-0.725L0.155,-0.725L0.155,-0.518C0.155,-0.508 0.155,-0.499 0.155,-0.49C0.155,-0.481 0.155,-0.473 0.154,-0.466C0.154,-0.458 0.154,-0.451 0.153,-0.443L0.155,-0.443C0.172,-0.477 0.193,-0.501 0.22,-0.516C0.247,-0.531 0.28,-0.538 0.32,-0.538C0.387,-0.538 0.436,-0.516 0.467,-0.471C0.498,-0.426 0.514,-0.358 0.514,-0.267ZM0.422,-0.264C0.422,-0.3 0.42,-0.331 0.415,-0.357C0.41,-0.383 0.403,-0.405 0.393,-0.422C0.383,-0.438 0.37,-0.451 0.354,-0.458C0.339,-0.466 0.32,-0.47 0.297,-0.47C0.274,-0.47 0.254,-0.466 0.236,-0.459C0.218,-0.451 0.204,-0.439 0.192,-0.423C0.18,-0.406 0.171,-0.384 0.165,-0.357C0.158,-0.33 0.155,-0.297 0.155,-0.258C0.155,-0.221 0.158,-0.189 0.165,-0.163C0.171,-0.137 0.18,-0.116 0.192,-0.1C0.204,-0.084 0.218,-0.073 0.236,-0.066C0.253,-0.059 0.274,-0.055 0.296,-0.055C0.318,-0.055 0.336,-0.059 0.352,-0.066C0.368,-0.074 0.381,-0.086 0.391,-0.103C0.402,-0.119 0.409,-0.141 0.414,-0.167C0.419,-0.194 0.422,-0.226 0.422,-0.264Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,625.931,29.709)">
<rect x="0.091" y="-0.107" width="0.095" height="0.107" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,637.322,29.709)">
<path d="M0.134,-0.267C0.134,-0.236 0.136,-0.208 0.141,-0.183C0.145,-0.158 0.153,-0.136 0.163,-0.117C0.174,-0.099 0.187,-0.085 0.204,-0.075C0.221,-0.065 0.243,-0.06 0.268,-0.06C0.299,-0.06 0.325,-0.068 0.346,-0.085C0.367,-0.102 0.38,-0.128 0.385,-0.163L0.474,-0.157C0.471,-0.135 0.464,-0.114 0.455,-0.094C0.445,-0.074 0.432,-0.056 0.415,-0.041C0.398,-0.026 0.378,-0.013 0.354,-0.004C0.329,0.005 0.302,0.01 0.27,0.01C0.229,0.01 0.194,0.003 0.165,-0.011C0.136,-0.025 0.112,-0.045 0.094,-0.069C0.076,-0.094 0.063,-0.123 0.055,-0.156C0.047,-0.189 0.042,-0.226 0.042,-0.265C0.042,-0.3 0.045,-0.331 0.051,-0.359C0.057,-0.386 0.065,-0.41 0.076,-0.43C0.087,-0.45 0.099,-0.467 0.113,-0.481C0.128,-0.495 0.143,-0.506 0.16,-0.514C0.177,-0.523 0.194,-0.529 0.213,-0.532C0.231,-0.536 0.25,-0.538 0.269,-0.538C0.299,-0.538 0.325,-0.534 0.348,-0.526C0.371,-0.518 0.391,-0.507 0.408,-0.492C0.425,-0.478 0.438,-0.462 0.449,-0.442C0.459,-0.423 0.466,-0.403 0.471,-0.38L0.38,-0.374C0.376,-0.403 0.364,-0.426 0.346,-0.443C0.327,-0.461 0.301,-0.469 0.267,-0.469C0.242,-0.469 0.221,-0.465 0.204,-0.457C0.187,-0.448 0.174,-0.436 0.163,-0.419C0.153,-0.402 0.145,-0.381 0.141,-0.356C0.136,-0.331 0.134,-0.301 0.134,-0.267Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,657.822,29.709)">
<path d="M0.514,-0.265C0.514,-0.172 0.494,-0.103 0.453,-0.058C0.412,-0.013 0.353,0.01 0.276,0.01C0.239,0.01 0.206,0.004 0.177,-0.007C0.148,-0.018 0.124,-0.035 0.104,-0.058C0.084,-0.08 0.068,-0.109 0.058,-0.143C0.047,-0.178 0.042,-0.218 0.042,-0.265C0.042,-0.447 0.121,-0.538 0.279,-0.538C0.32,-0.538 0.355,-0.532 0.385,-0.521C0.415,-0.51 0.439,-0.493 0.458,-0.47C0.477,-0.447 0.491,-0.418 0.5,-0.384C0.51,-0.35 0.514,-0.31 0.514,-0.265ZM0.422,-0.265C0.422,-0.306 0.419,-0.34 0.412,-0.366C0.406,-0.393 0.397,-0.414 0.385,-0.43C0.372,-0.446 0.357,-0.457 0.34,-0.464C0.322,-0.47 0.302,-0.473 0.28,-0.473C0.258,-0.473 0.238,-0.47 0.219,-0.463C0.201,-0.456 0.186,-0.445 0.173,-0.429C0.161,-0.413 0.151,-0.391 0.144,-0.365C0.138,-0.338 0.134,-0.305 0.134,-0.265C0.134,-0.224 0.138,-0.19 0.145,-0.163C0.152,-0.136 0.162,-0.115 0.175,-0.099C0.187,-0.083 0.202,-0.071 0.219,-0.065C0.236,-0.058 0.255,-0.055 0.275,-0.055C0.297,-0.055 0.318,-0.058 0.336,-0.065C0.354,-0.071 0.37,-0.082 0.382,-0.098C0.395,-0.114 0.405,-0.136 0.412,-0.163C0.418,-0.19 0.422,-0.224 0.422,-0.265Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,680.624,29.709)">
<path d="M0.375,0L0.375,-0.335C0.375,-0.361 0.373,-0.382 0.37,-0.399C0.367,-0.417 0.361,-0.431 0.354,-0.441C0.346,-0.452 0.336,-0.459 0.324,-0.464C0.311,-0.468 0.296,-0.47 0.278,-0.47C0.26,-0.47 0.243,-0.467 0.228,-0.459C0.213,-0.452 0.2,-0.441 0.19,-0.427C0.179,-0.414 0.171,-0.397 0.165,-0.376C0.16,-0.356 0.157,-0.333 0.157,-0.306L0.157,0L0.069,0L0.069,-0.416C0.069,-0.427 0.069,-0.438 0.069,-0.45C0.069,-0.463 0.069,-0.474 0.068,-0.485C0.068,-0.496 0.068,-0.505 0.067,-0.513C0.067,-0.521 0.067,-0.526 0.066,-0.528L0.149,-0.528C0.15,-0.527 0.15,-0.522 0.15,-0.515C0.151,-0.508 0.151,-0.5 0.152,-0.49C0.152,-0.481 0.153,-0.472 0.153,-0.462C0.153,-0.453 0.153,-0.444 0.153,-0.438L0.155,-0.438C0.163,-0.453 0.171,-0.467 0.18,-0.479C0.189,-0.492 0.2,-0.502 0.212,-0.511C0.224,-0.52 0.238,-0.526 0.254,-0.531C0.27,-0.536 0.288,-0.538 0.309,-0.538C0.349,-0.538 0.381,-0.53 0.404,-0.514C0.427,-0.498 0.444,-0.473 0.453,-0.438L0.454,-0.438C0.462,-0.453 0.471,-0.467 0.48,-0.479C0.49,-0.492 0.502,-0.502 0.515,-0.511C0.528,-0.52 0.542,-0.526 0.559,-0.531C0.575,-0.536 0.593,-0.538 0.614,-0.538C0.641,-0.538 0.664,-0.535 0.683,-0.527C0.703,-0.52 0.719,-0.509 0.731,-0.494C0.743,-0.479 0.752,-0.46 0.758,-0.436C0.764,-0.413 0.767,-0.385 0.767,-0.352L0.767,0L0.68,0L0.68,-0.335C0.68,-0.361 0.679,-0.382 0.675,-0.399C0.672,-0.417 0.667,-0.431 0.659,-0.441C0.651,-0.452 0.641,-0.459 0.629,-0.464C0.617,-0.468 0.601,-0.47 0.583,-0.47C0.565,-0.47 0.548,-0.467 0.533,-0.46C0.518,-0.453 0.505,-0.442 0.495,-0.429C0.484,-0.415 0.476,-0.398 0.47,-0.377C0.465,-0.357 0.462,-0.333 0.462,-0.306L0.462,0L0.375,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,714.777,29.709)">
<path d="M0,0.01L0.201,-0.725L0.278,-0.725L0.079,0.01L0,0.01Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,726.168,29.709)">
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,753.515,29.709)">
<path d="M0.547,0L0.547,-0.319L0.175,-0.319L0.175,0L0.082,0L0.082,-0.688L0.175,-0.688L0.175,-0.397L0.547,-0.397L0.547,-0.688L0.641,-0.688L0.641,0L0.547,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,783.124,29.709)">
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,810.471,29.709)">
<path d="M0.667,0L0.667,-0.459C0.667,-0.476 0.667,-0.493 0.667,-0.51C0.668,-0.527 0.668,-0.543 0.669,-0.557C0.67,-0.574 0.67,-0.59 0.671,-0.605C0.667,-0.589 0.662,-0.572 0.657,-0.556C0.653,-0.542 0.648,-0.527 0.643,-0.511C0.638,-0.496 0.633,-0.481 0.628,-0.469L0.451,0L0.385,0L0.205,-0.469C0.203,-0.474 0.201,-0.479 0.199,-0.486L0.185,-0.529C0.182,-0.537 0.18,-0.544 0.178,-0.552C0.172,-0.569 0.167,-0.587 0.162,-0.605C0.162,-0.587 0.162,-0.569 0.163,-0.551C0.164,-0.536 0.164,-0.52 0.165,-0.503C0.165,-0.486 0.165,-0.472 0.165,-0.459L0.165,0L0.082,0L0.082,-0.688L0.205,-0.688L0.388,-0.211C0.39,-0.204 0.393,-0.196 0.396,-0.186C0.399,-0.176 0.402,-0.165 0.405,-0.154C0.408,-0.144 0.411,-0.133 0.413,-0.124C0.416,-0.114 0.417,-0.107 0.418,-0.102C0.419,-0.107 0.421,-0.114 0.424,-0.124C0.426,-0.134 0.429,-0.144 0.433,-0.155C0.436,-0.166 0.44,-0.176 0.443,-0.186C0.446,-0.196 0.449,-0.204 0.452,-0.211L0.631,-0.688L0.751,-0.688L0.751,0L0.667,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,844.624,29.709)">
<path d="M0.202,0.01C0.149,0.01 0.109,-0.004 0.083,-0.032C0.056,-0.06 0.042,-0.099 0.042,-0.147C0.042,-0.182 0.049,-0.211 0.062,-0.233C0.075,-0.255 0.093,-0.273 0.114,-0.286C0.135,-0.298 0.16,-0.307 0.187,-0.312C0.214,-0.317 0.242,-0.32 0.271,-0.32L0.389,-0.322L0.389,-0.351C0.389,-0.373 0.387,-0.391 0.382,-0.407C0.378,-0.422 0.371,-0.434 0.361,-0.444C0.352,-0.453 0.34,-0.46 0.326,-0.465C0.312,-0.469 0.295,-0.471 0.276,-0.471C0.259,-0.471 0.244,-0.47 0.23,-0.468C0.216,-0.465 0.204,-0.461 0.194,-0.454C0.184,-0.448 0.176,-0.439 0.17,-0.428C0.164,-0.418 0.16,-0.404 0.158,-0.387L0.066,-0.396C0.069,-0.416 0.075,-0.435 0.084,-0.453C0.094,-0.47 0.107,-0.485 0.123,-0.498C0.14,-0.511 0.161,-0.521 0.186,-0.528C0.212,-0.535 0.242,-0.538 0.278,-0.538C0.344,-0.538 0.394,-0.523 0.428,-0.492C0.461,-0.462 0.478,-0.418 0.478,-0.36L0.478,-0.133C0.478,-0.107 0.481,-0.087 0.488,-0.074C0.495,-0.061 0.508,-0.054 0.527,-0.054C0.532,-0.054 0.537,-0.055 0.542,-0.055C0.547,-0.056 0.552,-0.057 0.556,-0.058L0.556,-0.003C0.545,0 0.534,0.002 0.523,0.003C0.512,0.004 0.501,0.005 0.488,0.005C0.472,0.005 0.457,0.003 0.446,-0.002C0.434,-0.006 0.424,-0.013 0.417,-0.022C0.409,-0.031 0.403,-0.042 0.399,-0.055C0.396,-0.068 0.393,-0.083 0.392,-0.101L0.389,-0.101C0.38,-0.084 0.369,-0.069 0.358,-0.055C0.347,-0.042 0.334,-0.03 0.319,-0.02C0.304,-0.011 0.287,-0.003 0.268,0.002C0.249,0.007 0.227,0.01 0.202,0.01ZM0.222,-0.056C0.25,-0.056 0.275,-0.061 0.296,-0.072C0.317,-0.082 0.334,-0.095 0.348,-0.111C0.362,-0.127 0.372,-0.144 0.379,-0.163C0.386,-0.182 0.389,-0.2 0.389,-0.217L0.389,-0.261L0.293,-0.259C0.271,-0.258 0.251,-0.257 0.232,-0.254C0.212,-0.251 0.195,-0.246 0.181,-0.238C0.166,-0.23 0.154,-0.218 0.146,-0.204C0.137,-0.189 0.133,-0.17 0.133,-0.146C0.133,-0.117 0.141,-0.095 0.156,-0.08C0.171,-0.064 0.194,-0.056 0.222,-0.056Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,867.426,29.709)">
<path d="M0.067,-0.641L0.067,-0.725L0.155,-0.725L0.155,-0.641L0.067,-0.641ZM0.067,0L0.067,-0.528L0.155,-0.528L0.155,0L0.067,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,876.535,29.709)">
<rect x="0.067" y="-0.725" width="0.088" height="0.725" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,885.644,29.709)">
<path d="M0.135,-0.246C0.135,-0.218 0.138,-0.192 0.143,-0.169C0.149,-0.146 0.158,-0.126 0.17,-0.109C0.182,-0.092 0.197,-0.079 0.215,-0.07C0.234,-0.061 0.256,-0.056 0.282,-0.056C0.32,-0.056 0.351,-0.064 0.374,-0.079C0.397,-0.094 0.412,-0.114 0.42,-0.137L0.498,-0.115C0.492,-0.101 0.484,-0.086 0.474,-0.071C0.464,-0.056 0.451,-0.043 0.435,-0.031C0.418,-0.019 0.397,-0.009 0.372,-0.002C0.347,0.006 0.317,0.01 0.282,0.01C0.204,0.01 0.145,-0.014 0.104,-0.06C0.063,-0.107 0.042,-0.176 0.042,-0.268C0.042,-0.317 0.049,-0.359 0.061,-0.393C0.073,-0.428 0.09,-0.456 0.112,-0.477C0.133,-0.499 0.158,-0.514 0.187,-0.524C0.216,-0.533 0.246,-0.538 0.279,-0.538C0.323,-0.538 0.36,-0.531 0.39,-0.517C0.42,-0.502 0.444,-0.483 0.462,-0.457C0.48,-0.432 0.493,-0.402 0.5,-0.368C0.508,-0.334 0.512,-0.297 0.512,-0.257L0.512,-0.246L0.135,-0.246ZM0.421,-0.313C0.416,-0.369 0.402,-0.409 0.378,-0.435C0.355,-0.46 0.321,-0.473 0.277,-0.473C0.263,-0.473 0.247,-0.471 0.231,-0.466C0.215,-0.461 0.2,-0.453 0.187,-0.441C0.173,-0.429 0.161,-0.413 0.152,-0.392C0.142,-0.371 0.137,-0.345 0.136,-0.313L0.421,-0.313Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,908.446,29.709)">
<path d="M0.069,0L0.069,-0.405C0.069,-0.416 0.069,-0.428 0.069,-0.439C0.069,-0.451 0.069,-0.462 0.068,-0.473C0.068,-0.483 0.068,-0.493 0.067,-0.503C0.067,-0.512 0.067,-0.521 0.066,-0.528L0.149,-0.528L0.152,-0.473C0.153,-0.463 0.153,-0.453 0.153,-0.444C0.153,-0.435 0.153,-0.427 0.153,-0.42L0.155,-0.42C0.161,-0.441 0.168,-0.458 0.175,-0.473C0.182,-0.488 0.19,-0.5 0.2,-0.51C0.209,-0.519 0.22,-0.526 0.233,-0.531C0.246,-0.536 0.262,-0.538 0.281,-0.538C0.288,-0.538 0.295,-0.538 0.301,-0.536C0.308,-0.535 0.313,-0.534 0.316,-0.533L0.316,-0.453C0.311,-0.454 0.304,-0.455 0.296,-0.456C0.288,-0.457 0.279,-0.458 0.27,-0.458C0.249,-0.458 0.232,-0.453 0.218,-0.444C0.204,-0.435 0.192,-0.422 0.183,-0.406C0.174,-0.39 0.168,-0.371 0.164,-0.348C0.159,-0.326 0.157,-0.302 0.157,-0.275L0.157,0L0.069,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,922.1,29.709)">
<path d="M0,0.01L0.201,-0.725L0.278,-0.725L0.079,0.01L0,0.01Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,933.491,29.709)">
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,960.837,29.709)">
<path d="M0.547,0L0.547,-0.319L0.175,-0.319L0.175,0L0.082,0L0.082,-0.688L0.175,-0.688L0.175,-0.397L0.547,-0.397L0.547,-0.688L0.641,-0.688L0.641,0L0.547,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,990.446,29.709)">
<path d="M0.614,-0.481C0.614,-0.451 0.609,-0.423 0.599,-0.397C0.589,-0.371 0.575,-0.349 0.555,-0.33C0.535,-0.311 0.511,-0.296 0.481,-0.285C0.451,-0.274 0.417,-0.268 0.377,-0.268L0.175,-0.268L0.175,0L0.082,0L0.082,-0.688L0.372,-0.688C0.412,-0.688 0.448,-0.683 0.478,-0.673C0.508,-0.663 0.534,-0.649 0.554,-0.631C0.574,-0.613 0.589,-0.591 0.599,-0.566C0.609,-0.54 0.614,-0.512 0.614,-0.481ZM0.521,-0.48C0.521,-0.524 0.507,-0.557 0.48,-0.579C0.454,-0.602 0.414,-0.613 0.36,-0.613L0.175,-0.613L0.175,-0.342L0.364,-0.342C0.418,-0.342 0.457,-0.354 0.483,-0.377C0.508,-0.401 0.521,-0.435 0.521,-0.48Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,1017.79,29.709)">
<path d="M0.667,0L0.667,-0.459C0.667,-0.476 0.667,-0.493 0.667,-0.51C0.668,-0.527 0.668,-0.543 0.669,-0.557C0.67,-0.574 0.67,-0.59 0.671,-0.605C0.667,-0.589 0.662,-0.572 0.657,-0.556C0.653,-0.542 0.648,-0.527 0.643,-0.511C0.638,-0.496 0.633,-0.481 0.628,-0.469L0.451,0L0.385,0L0.205,-0.469C0.203,-0.474 0.201,-0.479 0.199,-0.486L0.185,-0.529C0.182,-0.537 0.18,-0.544 0.178,-0.552C0.172,-0.569 0.167,-0.587 0.162,-0.605C0.162,-0.587 0.162,-0.569 0.163,-0.551C0.164,-0.536 0.164,-0.52 0.165,-0.503C0.165,-0.486 0.165,-0.472 0.165,-0.459L0.165,0L0.082,0L0.082,-0.688L0.205,-0.688L0.388,-0.211C0.39,-0.204 0.393,-0.196 0.396,-0.186C0.399,-0.176 0.402,-0.165 0.405,-0.154C0.408,-0.144 0.411,-0.133 0.413,-0.124C0.416,-0.114 0.417,-0.107 0.418,-0.102C0.419,-0.107 0.421,-0.114 0.424,-0.124C0.426,-0.134 0.429,-0.144 0.433,-0.155C0.436,-0.166 0.44,-0.176 0.443,-0.186C0.446,-0.196 0.449,-0.204 0.452,-0.211L0.631,-0.688L0.751,-0.688L0.751,0L0.667,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,1051.95,29.709)">
<path d="M0.202,0.01C0.149,0.01 0.109,-0.004 0.083,-0.032C0.056,-0.06 0.042,-0.099 0.042,-0.147C0.042,-0.182 0.049,-0.211 0.062,-0.233C0.075,-0.255 0.093,-0.273 0.114,-0.286C0.135,-0.298 0.16,-0.307 0.187,-0.312C0.214,-0.317 0.242,-0.32 0.271,-0.32L0.389,-0.322L0.389,-0.351C0.389,-0.373 0.387,-0.391 0.382,-0.407C0.378,-0.422 0.371,-0.434 0.361,-0.444C0.352,-0.453 0.34,-0.46 0.326,-0.465C0.312,-0.469 0.295,-0.471 0.276,-0.471C0.259,-0.471 0.244,-0.47 0.23,-0.468C0.216,-0.465 0.204,-0.461 0.194,-0.454C0.184,-0.448 0.176,-0.439 0.17,-0.428C0.164,-0.418 0.16,-0.404 0.158,-0.387L0.066,-0.396C0.069,-0.416 0.075,-0.435 0.084,-0.453C0.094,-0.47 0.107,-0.485 0.123,-0.498C0.14,-0.511 0.161,-0.521 0.186,-0.528C0.212,-0.535 0.242,-0.538 0.278,-0.538C0.344,-0.538 0.394,-0.523 0.428,-0.492C0.461,-0.462 0.478,-0.418 0.478,-0.36L0.478,-0.133C0.478,-0.107 0.481,-0.087 0.488,-0.074C0.495,-0.061 0.508,-0.054 0.527,-0.054C0.532,-0.054 0.537,-0.055 0.542,-0.055C0.547,-0.056 0.552,-0.057 0.556,-0.058L0.556,-0.003C0.545,0 0.534,0.002 0.523,0.003C0.512,0.004 0.501,0.005 0.488,0.005C0.472,0.005 0.457,0.003 0.446,-0.002C0.434,-0.006 0.424,-0.013 0.417,-0.022C0.409,-0.031 0.403,-0.042 0.399,-0.055C0.396,-0.068 0.393,-0.083 0.392,-0.101L0.389,-0.101C0.38,-0.084 0.369,-0.069 0.358,-0.055C0.347,-0.042 0.334,-0.03 0.319,-0.02C0.304,-0.011 0.287,-0.003 0.268,0.002C0.249,0.007 0.227,0.01 0.202,0.01ZM0.222,-0.056C0.25,-0.056 0.275,-0.061 0.296,-0.072C0.317,-0.082 0.334,-0.095 0.348,-0.111C0.362,-0.127 0.372,-0.144 0.379,-0.163C0.386,-0.182 0.389,-0.2 0.389,-0.217L0.389,-0.261L0.293,-0.259C0.271,-0.258 0.251,-0.257 0.232,-0.254C0.212,-0.251 0.195,-0.246 0.181,-0.238C0.166,-0.23 0.154,-0.218 0.146,-0.204C0.137,-0.189 0.133,-0.17 0.133,-0.146C0.133,-0.117 0.141,-0.095 0.156,-0.08C0.171,-0.064 0.194,-0.056 0.222,-0.056Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,1074.75,29.709)">
<path d="M0.067,-0.641L0.067,-0.725L0.155,-0.725L0.155,-0.641L0.067,-0.641ZM0.067,0L0.067,-0.528L0.155,-0.528L0.155,0L0.067,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,1083.86,29.709)">
<rect x="0.067" y="-0.725" width="0.088" height="0.725" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,1092.97,29.709)">
<path d="M0.135,-0.246C0.135,-0.218 0.138,-0.192 0.143,-0.169C0.149,-0.146 0.158,-0.126 0.17,-0.109C0.182,-0.092 0.197,-0.079 0.215,-0.07C0.234,-0.061 0.256,-0.056 0.282,-0.056C0.32,-0.056 0.351,-0.064 0.374,-0.079C0.397,-0.094 0.412,-0.114 0.42,-0.137L0.498,-0.115C0.492,-0.101 0.484,-0.086 0.474,-0.071C0.464,-0.056 0.451,-0.043 0.435,-0.031C0.418,-0.019 0.397,-0.009 0.372,-0.002C0.347,0.006 0.317,0.01 0.282,0.01C0.204,0.01 0.145,-0.014 0.104,-0.06C0.063,-0.107 0.042,-0.176 0.042,-0.268C0.042,-0.317 0.049,-0.359 0.061,-0.393C0.073,-0.428 0.09,-0.456 0.112,-0.477C0.133,-0.499 0.158,-0.514 0.187,-0.524C0.216,-0.533 0.246,-0.538 0.279,-0.538C0.323,-0.538 0.36,-0.531 0.39,-0.517C0.42,-0.502 0.444,-0.483 0.462,-0.457C0.48,-0.432 0.493,-0.402 0.5,-0.368C0.508,-0.334 0.512,-0.297 0.512,-0.257L0.512,-0.246L0.135,-0.246ZM0.421,-0.313C0.416,-0.369 0.402,-0.409 0.378,-0.435C0.355,-0.46 0.321,-0.473 0.277,-0.473C0.263,-0.473 0.247,-0.471 0.231,-0.466C0.215,-0.461 0.2,-0.453 0.187,-0.441C0.173,-0.429 0.161,-0.413 0.152,-0.392C0.142,-0.371 0.137,-0.345 0.136,-0.313L0.421,-0.313Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
<g transform="matrix(41,0,0,41,1115.77,29.709)">
<path d="M0.069,0L0.069,-0.405C0.069,-0.416 0.069,-0.428 0.069,-0.439C0.069,-0.451 0.069,-0.462 0.068,-0.473C0.068,-0.483 0.068,-0.493 0.067,-0.503C0.067,-0.512 0.067,-0.521 0.066,-0.528L0.149,-0.528L0.152,-0.473C0.153,-0.463 0.153,-0.453 0.153,-0.444C0.153,-0.435 0.153,-0.427 0.153,-0.42L0.155,-0.42C0.161,-0.441 0.168,-0.458 0.175,-0.473C0.182,-0.488 0.19,-0.5 0.2,-0.51C0.209,-0.519 0.22,-0.526 0.233,-0.531C0.246,-0.536 0.262,-0.538 0.281,-0.538C0.288,-0.538 0.295,-0.538 0.301,-0.536C0.308,-0.535 0.313,-0.534 0.316,-0.533L0.316,-0.453C0.311,-0.454 0.304,-0.455 0.296,-0.456C0.288,-0.457 0.279,-0.458 0.27,-0.458C0.249,-0.458 0.232,-0.453 0.218,-0.444C0.204,-0.435 0.192,-0.422 0.183,-0.406C0.174,-0.39 0.168,-0.371 0.164,-0.348C0.159,-0.326 0.157,-0.302 0.157,-0.275L0.157,0L0.069,0Z" style="fill:rgb(255,254,254);fill-rule:nonzero;"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 53 KiB

48
examples/index.html Normal file
View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>PHPMailer Examples</title>
</head>
<body>
<h1>PHPMailer code examples<a href="https://github.com/PHPMailer/PHPMailer"><img src="images/phpmailer.png" style="float:right; border:0;" alt="PHPMailer logo"></a></h1>
<p>This folder contains a collection of examples of using <a href="https://github.com/PHPMailer/PHPMailer">PHPMailer</a>.</p>
<h2>About testing email sending</h2>
<p>When working on email sending code you'll find yourself worrying about what might happen if all these test emails got sent to your mailing list. The solution is to use a fake mail server, one that acts just like the real thing, but just doesn't actually send anything out. Some offer web interfaces, feedback, logging, the ability to return specific error codes, all things that are useful for testing error handling, authentication etc. Here's a selection of mail testing tools you might like to try:</p>
<ul>
<li><a href="https://github.com/Nilhcem/FakeSMTP">FakeSMTP</a>, a Java desktop app with the ability to show an SMTP log and save messages to a folder. </li>
<li><a href="https://github.com/isotoma/FakeEmail">FakeEmail</a>, a Python-based fake mail server with a web interface.</li>
<li><a href="http://www.postfix.org/smtp-sink.1.html">smtp-sink</a>, part of the Postfix mail server, so you probably already have this installed. This is used in the Travis-CI configuration to run PHPMailer's unit tests.</li>
<li><a href="http://smtp4dev.codeplex.com">smtp4dev</a>, a dummy SMTP server for Windows.</li>
<li><a href="https://github.com/PHPMailer/PHPMailer/blob/master/test/fakesendmail.sh">fakesendmail.sh</a>, part of PHPMailer's test setup, this is a shell script that emulates sendmail for testing 'mail' or 'sendmail' methods in PHPMailer.</li>
<li><a href="http://tools.ietf.org/tools/msglint/">msglint</a>, not a mail server, the IETF's MIME structure analyser checks the formatting of your messages.</li>
</ul>
<div style="padding: 8px; color: #333333; background-color: #dc8b92">
<h2>Security note</h2>
<p>Before running these examples you'll need to rename them with '.php' extensions. They are supplied as '.phps' files which will usually be displayed with syntax highlighting by PHP instead of running them. This prevents potential security issues with running potential spam-gateway code if you happen to deploy these code examples on a live site - <em>please don't do that!</em> Similarly, don't leave your passwords in these files as they will be visible to the world!</p>
</div>
<h2><a href="code_generator.phps">code_generator.phps</a></h2>
<p>This script is a simple code generator - fill in the form and hit submit, and it will use when you entered to email you a message, and will also generate PHP code using your settings that you can copy and paste to use in your own apps. If you need to get going quickly, this is probably the best place to start.</p>
<h2><a href="mail.phps">mail.phps</a></h2>
<p>This script is a basic example which creates an email message from an external HTML file, creates a plain text body, sets various addresses, adds an attachment and sends the message. It uses PHP's built-in mail() function which is the simplest to use, but relies on the presence of a local mail server, something which is not usually available on Windows. If you find yourself in that situation, either install a local mail server, or use a remote one and send using SMTP instead.</p>
<h2><a href="exceptions.phps">exceptions.phps</a></h2>
<p>The same as the mail example, but shows how to use PHPMailer's optional exceptions for error handling.</p>
<h2><a href="smtp.phps">smtp.phps</a></h2>
<p>A simple example sending using SMTP with authentication.</p>
<h2><a href="smtp_no_auth.phps">smtp_no_auth.phps</a></h2>
<p>A simple example sending using SMTP without authentication.</p>
<h2><a href="sendmail.phps">sendmail.phps</a></h2>
<p>A simple example using sendmail. Sendmail is a program (usually found on Linux/BSD, OS X and other UNIX-alikes) that can be used to submit messages to a local mail server without a lengthy SMTP conversation. It's probably the fastest sending mechanism, but lacks some error reporting features. There are sendmail emulators for most popular mail servers including postfix, qmail, exim etc.</p>
<h2><a href="gmail.phps">gmail.phps</a></h2>
<p>Submitting email via Google's Gmail service is a popular use of PHPMailer. It's much the same as normal SMTP sending, just with some specific settings, namely using TLS encryption, authentication is enabled, and it connects to the SMTP submission port 587 on the smtp.gmail.com host. This example does all that.</p>
<h2><a href="pop_before_smtp.phps">pop_before_smtp.phps</a></h2>
<p>Before effective SMTP authentication mechanisms were available, it was common for ISPs to use POP-before-SMTP authentication. As it implies, you authenticate using the POP3 protocol (an older protocol now mostly replaced by the far superior IMAP), and then the SMTP server will allow send access from your IP address for a short while, usually 5-15 minutes. PHPMailer includes a POP3 protocol client, so it can carry out this sequence - it's just like a normal SMTP conversation (without authentication), but connects via POP first.</p>
<h2><a href="mailing_list.phps">mailing_list.phps</a></h2>
<p>This is a somewhat naïve example of sending similar emails to a list of different addresses. It sets up a PHPMailer instance using SMTP, then connects to a MySQL database to retrieve a list of recipients. The code loops over this list, sending email to each person using their info and marks them as sent in the database. It makes use of SMTP keepalive which saves reconnecting and re-authenticating between each message.</p>
<hr>
<h2><a href="smtp_check.phps">smtp_check.phps</a></h2>
<p>This is an example showing how to use the SMTP class by itself (without PHPMailer) to check an SMTP connection.</p>
<hr>
<p>Most of these examples use the 'example.com' domain. This domain is reserved by IANA for illustrative purposes, as documented in <a href="http://tools.ietf.org/html/rfc2606">RFC 2606</a>. Don't use made-up domains like 'mydomain.com' or 'somedomain.com' in examples as someone, somewhere, probably owns them!</p>
</body>
</html>

View File

@ -1,16 +1,12 @@
<?php
/**
* This example shows sending a message using PHP's mail() function.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
$mail = new PHPMailer;
//Set who the message is to be sent from
$mail->setFrom('from@example.com', 'First Last');
//Set an alternative reply-to address
@ -21,7 +17,7 @@ $mail->addAddress('whoto@example.com', 'John Doe');
$mail->Subject = 'PHPMailer mail() test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
@ -29,7 +25,7 @@ $mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo 'Message sent!';
echo "Message sent!";
}

View File

@ -1,38 +1,26 @@
<?php
/**
* This example shows how to send a message to a whole list of recipients efficiently.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
error_reporting(E_ALL);
error_reporting(E_STRICT | E_ALL);
date_default_timezone_set('Etc/UTC');
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Passing `true` enables PHPMailer exceptions
$mail = new PHPMailer(true);
$mail = new PHPMailer;
$body = file_get_contents('contents.html');
$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->SMTPAuth = true;
$mail->SMTPKeepAlive = true; //SMTP connection will not close after each email sent, reduces SMTP overhead
$mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent, reduces SMTP overhead
$mail->Port = 25;
$mail->Username = 'yourname@example.com';
$mail->Password = 'yourpassword';
$mail->setFrom('list@example.com', 'List manager');
$mail->addReplyTo('list@example.com', 'List manager');
$mail->addCustomHeader(
'List-Unsubscribe',
'<mailto:unsubscribes@example.com>, <https://www.example.com/unsubscribe.php>'
);
$mail->Subject = 'PHPMailer Simple database mailing list test';
$mail->Subject = "PHPMailer Simple database mailing list test";
//Same body for all messages, so set this before the sending loop
//If you generate a different body for each recipient (e.g. you're using a templating system),
@ -45,52 +33,27 @@ $mail->AltBody = 'To view the message, please use an HTML compatible email viewe
//You'll need to alter this to match your database
$mysql = mysqli_connect('localhost', 'username', 'password');
mysqli_select_db($mysql, 'mydb');
$result = mysqli_query($mysql, 'SELECT full_name, email, photo FROM mailinglist WHERE sent = FALSE');
$result = mysqli_query($mysql, 'SELECT full_name, email, photo FROM mailinglist WHERE sent = false');
foreach ($result as $row) {
try {
$mail->addAddress($row['email'], $row['full_name']);
} catch (Exception $e) {
printf(
'Invalid address skipped: %s<br>',
htmlspecialchars($row['email'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401)
);
continue;
}
foreach ($result as $row) { //This iterator syntax only works in PHP 5.4+
$mail->addAddress($row['email'], $row['full_name']);
if (!empty($row['photo'])) {
//Assumes the image data is stored in the DB
$mail->addStringAttachment($row['photo'], 'YourPhoto.jpg');
$mail->addStringAttachment($row['photo'], 'YourPhoto.jpg'); //Assumes the image data is stored in the DB
}
$mail->replaceCustomHeader(
'List-Unsubscribe',
'<mailto:unsubscribes@example.com>, <https://www.example.com/unsubscribe.php?email=' .
rawurlencode($row['email']) . '>'
);
try {
$mail->send();
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)
);
if (!$mail->send()) {
echo "Mailer Error (" . str_replace("@", "&#64;", $row["email"]) . ') ' . $mail->ErrorInfo . '<br />';
break; //Abandon sending
} else {
echo "Message sent to :" . $row['full_name'] . ' (' . str_replace("@", "&#64;", $row['email']) . ')<br />';
//Mark it as sent in the DB
mysqli_query(
$mysql,
"UPDATE mailinglist SET sent = TRUE WHERE email = '" .
"UPDATE mailinglist SET sent = true WHERE email = '" .
mysqli_real_escape_string($mysql, $row['email']) . "'"
);
} catch (Exception $e) {
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();
}
//Clear all addresses and attachments for the next iteration
// Clear all addresses and attachments for next loop
$mail->clearAddresses();
$mail->clearAttachments();
}

View File

@ -1,20 +1,12 @@
<?php
/**
* This example shows how to use POP-before-SMTP for authentication.
* POP-before-SMTP is a very old technology that is hardly used any more.
*/
//Import PHPMailer classes into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\POP3;
use PHPMailer\PHPMailer\SMTP;
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Authenticate via POP3.
//After this you should be allowed to submit messages over SMTP for a few minutes.
//After this you should be allowed to submit messages over SMTP for a while.
//Only applies if your host supports POP-before-SMTP.
$pop = POP3::popBeforeSmtp('pop3.example.com', 110, 30, 'username', 'password', 1);
@ -24,12 +16,14 @@ $mail = new PHPMailer(true);
try {
$mail->isSMTP();
//Enable SMTP debugging
//SMTP::DEBUG_OFF = off (for production use)
//SMTP::DEBUG_CLIENT = client messages
//SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2;
//Ask for HTML-friendly debug output
$mail->Debugoutput = 'html';
//Set the hostname of the mail server
$mail->Host = 'mail.example.com';
$mail->Host = "mail.example.com";
//Set the SMTP port number - likely to be 25, 465 or 587
$mail->Port = 25;
//Whether to use SMTP authentication
@ -44,7 +38,7 @@ try {
$mail->Subject = 'PHPMailer POP-before-SMTP test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//and convert the HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
@ -52,9 +46,9 @@ try {
//send the message
//Note that we don't need check the response from this because it will throw an exception if it has trouble
$mail->send();
echo 'Message sent!';
} catch (Exception $e) {
echo "Message sent!";
} catch (phpmailerException $e) {
echo $e->errorMessage(); //Pretty error messages from PHPMailer
} catch (\Exception $e) {
} catch (Exception $e) {
echo $e->getMessage(); //Boring error messages from anything else!
}

664
examples/scripts/XRegExp.js Normal file
View File

@ -0,0 +1,664 @@
// XRegExp 1.5.1
// (c) 2007-2012 Steven Levithan
// MIT License
// <http://xregexp.com>
// Provides an augmented, extensible, cross-browser implementation of regular expressions,
// including support for additional syntax, flags, and methods
var XRegExp;
if (XRegExp) {
// Avoid running twice, since that would break references to native globals
throw Error("can't load XRegExp twice in the same frame");
}
// Run within an anonymous function to protect variables and avoid new globals
(function (undefined) {
//---------------------------------
// Constructor
//---------------------------------
// Accepts a pattern and flags; returns a new, extended `RegExp` object. Differs from a native
// regular expression in that additional syntax and flags are supported and cross-browser
// syntax inconsistencies are ameliorated. `XRegExp(/regex/)` clones an existing regex and
// converts to type XRegExp
XRegExp = function (pattern, flags) {
var output = [],
currScope = XRegExp.OUTSIDE_CLASS,
pos = 0,
context, tokenResult, match, chr, regex;
if (XRegExp.isRegExp(pattern)) {
if (flags !== undefined)
throw TypeError("can't supply flags when constructing one RegExp from another");
return clone(pattern);
}
// Tokens become part of the regex construction process, so protect against infinite
// recursion when an XRegExp is constructed within a token handler or trigger
if (isInsideConstructor)
throw Error("can't call the XRegExp constructor within token definition functions");
flags = flags || "";
context = { // `this` object for custom tokens
hasNamedCapture: false,
captureNames: [],
hasFlag: function (flag) {return flags.indexOf(flag) > -1;},
setFlag: function (flag) {flags += flag;}
};
while (pos < pattern.length) {
// Check for custom tokens at the current position
tokenResult = runTokens(pattern, pos, currScope, context);
if (tokenResult) {
output.push(tokenResult.output);
pos += (tokenResult.match[0].length || 1);
} else {
// Check for native multicharacter metasequences (excluding character classes) at
// the current position
if (match = nativ.exec.call(nativeTokens[currScope], pattern.slice(pos))) {
output.push(match[0]);
pos += match[0].length;
} else {
chr = pattern.charAt(pos);
if (chr === "[")
currScope = XRegExp.INSIDE_CLASS;
else if (chr === "]")
currScope = XRegExp.OUTSIDE_CLASS;
// Advance position one character
output.push(chr);
pos++;
}
}
}
regex = RegExp(output.join(""), nativ.replace.call(flags, flagClip, ""));
regex._xregexp = {
source: pattern,
captureNames: context.hasNamedCapture ? context.captureNames : null
};
return regex;
};
//---------------------------------
// Public properties
//---------------------------------
XRegExp.version = "1.5.1";
// Token scope bitflags
XRegExp.INSIDE_CLASS = 1;
XRegExp.OUTSIDE_CLASS = 2;
//---------------------------------
// Private variables
//---------------------------------
var replacementToken = /\$(?:(\d\d?|[$&`'])|{([$\w]+)})/g,
flagClip = /[^gimy]+|([\s\S])(?=[\s\S]*\1)/g, // Nonnative and duplicate flags
quantifier = /^(?:[?*+]|{\d+(?:,\d*)?})\??/,
isInsideConstructor = false,
tokens = [],
// Copy native globals for reference ("native" is an ES3 reserved keyword)
nativ = {
exec: RegExp.prototype.exec,
test: RegExp.prototype.test,
match: String.prototype.match,
replace: String.prototype.replace,
split: String.prototype.split
},
compliantExecNpcg = nativ.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups
compliantLastIndexIncrement = function () {
var x = /^/g;
nativ.test.call(x, "");
return !x.lastIndex;
}(),
hasNativeY = RegExp.prototype.sticky !== undefined,
nativeTokens = {};
// `nativeTokens` match native multicharacter metasequences only (including deprecated octals,
// excluding character classes)
nativeTokens[XRegExp.INSIDE_CLASS] = /^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/;
nativeTokens[XRegExp.OUTSIDE_CLASS] = /^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/;
//---------------------------------
// Public methods
//---------------------------------
// Lets you extend or change XRegExp syntax and create custom flags. This is used internally by
// the XRegExp library and can be used to create XRegExp plugins. This function is intended for
// users with advanced knowledge of JavaScript's regular expression syntax and behavior. It can
// be disabled by `XRegExp.freezeTokens`
XRegExp.addToken = function (regex, handler, scope, trigger) {
tokens.push({
pattern: clone(regex, "g" + (hasNativeY ? "y" : "")),
handler: handler,
scope: scope || XRegExp.OUTSIDE_CLASS,
trigger: trigger || null
});
};
// Accepts a pattern and flags; returns an extended `RegExp` object. If the pattern and flag
// combination has previously been cached, the cached copy is returned; otherwise the newly
// created regex is cached
XRegExp.cache = function (pattern, flags) {
var key = pattern + "/" + (flags || "");
return XRegExp.cache[key] || (XRegExp.cache[key] = XRegExp(pattern, flags));
};
// Accepts a `RegExp` instance; returns a copy with the `/g` flag set. The copy has a fresh
// `lastIndex` (set to zero). If you want to copy a regex without forcing the `global`
// property, use `XRegExp(regex)`. Do not use `RegExp(regex)` because it will not preserve
// special properties required for named capture
XRegExp.copyAsGlobal = function (regex) {
return clone(regex, "g");
};
// Accepts a string; returns the string with regex metacharacters escaped. The returned string
// can safely be used at any point within a regex to match the provided literal string. Escaped
// characters are [ ] { } ( ) * + ? - . , \ ^ $ | # and whitespace
XRegExp.escape = function (str) {
return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};
// Accepts a string to search, regex to search with, position to start the search within the
// string (default: 0), and an optional Boolean indicating whether matches must start at-or-
// after the position or at the specified position only. This function ignores the `lastIndex`
// of the provided regex in its own handling, but updates the property for compatibility
XRegExp.execAt = function (str, regex, pos, anchored) {
var r2 = clone(regex, "g" + ((anchored && hasNativeY) ? "y" : "")),
match;
r2.lastIndex = pos = pos || 0;
match = r2.exec(str); // Run the altered `exec` (required for `lastIndex` fix, etc.)
if (anchored && match && match.index !== pos)
match = null;
if (regex.global)
regex.lastIndex = match ? r2.lastIndex : 0;
return match;
};
// Breaks the unrestorable link to XRegExp's private list of tokens, thereby preventing
// syntax and flag changes. Should be run after XRegExp and any plugins are loaded
XRegExp.freezeTokens = function () {
XRegExp.addToken = function () {
throw Error("can't run addToken after freezeTokens");
};
};
// Accepts any value; returns a Boolean indicating whether the argument is a `RegExp` object.
// Note that this is also `true` for regex literals and regexes created by the `XRegExp`
// constructor. This works correctly for variables created in another frame, when `instanceof`
// and `constructor` checks would fail to work as intended
XRegExp.isRegExp = function (o) {
return Object.prototype.toString.call(o) === "[object RegExp]";
};
// Executes `callback` once per match within `str`. Provides a simpler and cleaner way to
// iterate over regex matches compared to the traditional approaches of subverting
// `String.prototype.replace` or repeatedly calling `exec` within a `while` loop
XRegExp.iterate = function (str, regex, callback, context) {
var r2 = clone(regex, "g"),
i = -1, match;
while (match = r2.exec(str)) { // Run the altered `exec` (required for `lastIndex` fix, etc.)
if (regex.global)
regex.lastIndex = r2.lastIndex; // Doing this to follow expectations if `lastIndex` is checked within `callback`
callback.call(context, match, ++i, str, regex);
if (r2.lastIndex === match.index)
r2.lastIndex++;
}
if (regex.global)
regex.lastIndex = 0;
};
// Accepts a string and an array of regexes; returns the result of using each successive regex
// to search within the matches of the previous regex. The array of regexes can also contain
// objects with `regex` and `backref` properties, in which case the named or numbered back-
// references specified are passed forward to the next regex or returned. E.g.:
// var xregexpImgFileNames = XRegExp.matchChain(html, [
// {regex: /<img\b([^>]+)>/i, backref: 1}, // <img> tag attributes
// {regex: XRegExp('(?ix) \\s src=" (?<src> [^"]+ )'), backref: "src"}, // src attribute values
// {regex: XRegExp("^http://xregexp\\.com(/[^#?]+)", "i"), backref: 1}, // xregexp.com paths
// /[^\/]+$/ // filenames (strip directory paths)
// ]);
XRegExp.matchChain = function (str, chain) {
return function recurseChain (values, level) {
var item = chain[level].regex ? chain[level] : {regex: chain[level]},
regex = clone(item.regex, "g"),
matches = [], i;
for (i = 0; i < values.length; i++) {
XRegExp.iterate(values[i], regex, function (match) {
matches.push(item.backref ? (match[item.backref] || "") : match[0]);
});
}
return ((level === chain.length - 1) || !matches.length) ?
matches : recurseChain(matches, level + 1);
}([str], 0);
};
//---------------------------------
// New RegExp prototype methods
//---------------------------------
// Accepts a context object and arguments array; returns the result of calling `exec` with the
// first value in the arguments array. the context is ignored but is accepted for congruity
// with `Function.prototype.apply`
RegExp.prototype.apply = function (context, args) {
return this.exec(args[0]);
};
// Accepts a context object and string; returns the result of calling `exec` with the provided
// string. the context is ignored but is accepted for congruity with `Function.prototype.call`
RegExp.prototype.call = function (context, str) {
return this.exec(str);
};
//---------------------------------
// Overridden native methods
//---------------------------------
// Adds named capture support (with backreferences returned as `result.name`), and fixes two
// cross-browser issues per ES3:
// - Captured values for nonparticipating capturing groups should be returned as `undefined`,
// rather than the empty string.
// - `lastIndex` should not be incremented after zero-length matches.
RegExp.prototype.exec = function (str) {
var match, name, r2, origLastIndex;
if (!this.global)
origLastIndex = this.lastIndex;
match = nativ.exec.apply(this, arguments);
if (match) {
// Fix browsers whose `exec` methods don't consistently return `undefined` for
// nonparticipating capturing groups
if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
r2 = RegExp(this.source, nativ.replace.call(getNativeFlags(this), "g", ""));
// Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed
// matching due to characters outside the match
nativ.replace.call((str + "").slice(match.index), r2, function () {
for (var i = 1; i < arguments.length - 2; i++) {
if (arguments[i] === undefined)
match[i] = undefined;
}
});
}
// Attach named capture properties
if (this._xregexp && this._xregexp.captureNames) {
for (var i = 1; i < match.length; i++) {
name = this._xregexp.captureNames[i - 1];
if (name)
match[name] = match[i];
}
}
// Fix browsers that increment `lastIndex` after zero-length matches
if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))
this.lastIndex--;
}
if (!this.global)
this.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows)
return match;
};
// Fix browser bugs in native method
RegExp.prototype.test = function (str) {
// Use the native `exec` to skip some processing overhead, even though the altered
// `exec` would take care of the `lastIndex` fixes
var match, origLastIndex;
if (!this.global)
origLastIndex = this.lastIndex;
match = nativ.exec.call(this, str);
// Fix browsers that increment `lastIndex` after zero-length matches
if (match && !compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))
this.lastIndex--;
if (!this.global)
this.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows)
return !!match;
};
// Adds named capture support and fixes browser bugs in native method
String.prototype.match = function (regex) {
if (!XRegExp.isRegExp(regex))
regex = RegExp(regex); // Native `RegExp`
if (regex.global) {
var result = nativ.match.apply(this, arguments);
regex.lastIndex = 0; // Fix IE bug
return result;
}
return regex.exec(this); // Run the altered `exec`
};
// Adds support for `${n}` tokens for named and numbered backreferences in replacement text,
// and provides named backreferences to replacement functions as `arguments[0].name`. Also
// fixes cross-browser differences in replacement text syntax when performing a replacement
// using a nonregex search value, and the value of replacement regexes' `lastIndex` property
// during replacement iterations. Note that this doesn't support SpiderMonkey's proprietary
// third (`flags`) parameter
String.prototype.replace = function (search, replacement) {
var isRegex = XRegExp.isRegExp(search),
captureNames, result, str, origLastIndex;
// There are too many combinations of search/replacement types/values and browser bugs that
// preclude passing to native `replace`, so don't try
//if (...)
// return nativ.replace.apply(this, arguments);
if (isRegex) {
if (search._xregexp)
captureNames = search._xregexp.captureNames; // Array or `null`
if (!search.global)
origLastIndex = search.lastIndex;
} else {
search = search + ""; // Type conversion
}
if (Object.prototype.toString.call(replacement) === "[object Function]") {
result = nativ.replace.call(this + "", search, function () {
if (captureNames) {
// Change the `arguments[0]` string primitive to a String object which can store properties
arguments[0] = new String(arguments[0]);
// Store named backreferences on `arguments[0]`
for (var i = 0; i < captureNames.length; i++) {
if (captureNames[i])
arguments[0][captureNames[i]] = arguments[i + 1];
}
}
// Update `lastIndex` before calling `replacement` (fix browsers)
if (isRegex && search.global)
search.lastIndex = arguments[arguments.length - 2] + arguments[0].length;
return replacement.apply(null, arguments);
});
} else {
str = this + ""; // Type conversion, so `args[args.length - 1]` will be a string (given nonstring `this`)
result = nativ.replace.call(str, search, function () {
var args = arguments; // Keep this function's `arguments` available through closure
return nativ.replace.call(replacement + "", replacementToken, function ($0, $1, $2) {
// Numbered backreference (without delimiters) or special variable
if ($1) {
switch ($1) {
case "$": return "$";
case "&": return args[0];
case "`": return args[args.length - 1].slice(0, args[args.length - 2]);
case "'": return args[args.length - 1].slice(args[args.length - 2] + args[0].length);
// Numbered backreference
default:
// What does "$10" mean?
// - Backreference 10, if 10 or more capturing groups exist
// - Backreference 1 followed by "0", if 1-9 capturing groups exist
// - Otherwise, it's the string "$10"
// Also note:
// - Backreferences cannot be more than two digits (enforced by `replacementToken`)
// - "$01" is equivalent to "$1" if a capturing group exists, otherwise it's the string "$01"
// - There is no "$0" token ("$&" is the entire match)
var literalNumbers = "";
$1 = +$1; // Type conversion; drop leading zero
if (!$1) // `$1` was "0" or "00"
return $0;
while ($1 > args.length - 3) {
literalNumbers = String.prototype.slice.call($1, -1) + literalNumbers;
$1 = Math.floor($1 / 10); // Drop the last digit
}
return ($1 ? args[$1] || "" : "$") + literalNumbers;
}
// Named backreference or delimited numbered backreference
} else {
// What does "${n}" mean?
// - Backreference to numbered capture n. Two differences from "$n":
// - n can be more than two digits
// - Backreference 0 is allowed, and is the entire match
// - Backreference to named capture n, if it exists and is not a number overridden by numbered capture
// - Otherwise, it's the string "${n}"
var n = +$2; // Type conversion; drop leading zeros
if (n <= args.length - 3)
return args[n];
n = captureNames ? indexOf(captureNames, $2) : -1;
return n > -1 ? args[n + 1] : $0;
}
});
});
}
if (isRegex) {
if (search.global)
search.lastIndex = 0; // Fix IE, Safari bug (last tested IE 9.0.5, Safari 5.1.2 on Windows)
else
search.lastIndex = origLastIndex; // Fix IE, Opera bug (last tested IE 9.0.5, Opera 11.61 on Windows)
}
return result;
};
// A consistent cross-browser, ES3 compliant `split`
String.prototype.split = function (s /* separator */, limit) {
// If separator `s` is not a regex, use the native `split`
if (!XRegExp.isRegExp(s))
return nativ.split.apply(this, arguments);
var str = this + "", // Type conversion
output = [],
lastLastIndex = 0,
match, lastLength;
// Behavior for `limit`: if it's...
// - `undefined`: No limit
// - `NaN` or zero: Return an empty array
// - A positive number: Use `Math.floor(limit)`
// - A negative number: No limit
// - Other: Type-convert, then use the above rules
if (limit === undefined || +limit < 0) {
limit = Infinity;
} else {
limit = Math.floor(+limit);
if (!limit)
return [];
}
// This is required if not `s.global`, and it avoids needing to set `s.lastIndex` to zero
// and restore it to its original value when we're done using the regex
s = XRegExp.copyAsGlobal(s);
while (match = s.exec(str)) { // Run the altered `exec` (required for `lastIndex` fix, etc.)
if (s.lastIndex > lastLastIndex) {
output.push(str.slice(lastLastIndex, match.index));
if (match.length > 1 && match.index < str.length)
Array.prototype.push.apply(output, match.slice(1));
lastLength = match[0].length;
lastLastIndex = s.lastIndex;
if (output.length >= limit)
break;
}
if (s.lastIndex === match.index)
s.lastIndex++;
}
if (lastLastIndex === str.length) {
if (!nativ.test.call(s, "") || lastLength)
output.push("");
} else {
output.push(str.slice(lastLastIndex));
}
return output.length > limit ? output.slice(0, limit) : output;
};
//---------------------------------
// Private helper functions
//---------------------------------
// Supporting function for `XRegExp`, `XRegExp.copyAsGlobal`, etc. Returns a copy of a `RegExp`
// instance with a fresh `lastIndex` (set to zero), preserving properties required for named
// capture. Also allows adding new flags in the process of copying the regex
function clone (regex, additionalFlags) {
if (!XRegExp.isRegExp(regex))
throw TypeError("type RegExp expected");
var x = regex._xregexp;
regex = XRegExp(regex.source, getNativeFlags(regex) + (additionalFlags || ""));
if (x) {
regex._xregexp = {
source: x.source,
captureNames: x.captureNames ? x.captureNames.slice(0) : null
};
}
return regex;
}
function getNativeFlags (regex) {
return (regex.global ? "g" : "") +
(regex.ignoreCase ? "i" : "") +
(regex.multiline ? "m" : "") +
(regex.extended ? "x" : "") + // Proposed for ES4; included in AS3
(regex.sticky ? "y" : "");
}
function runTokens (pattern, index, scope, context) {
var i = tokens.length,
result, match, t;
// Protect against constructing XRegExps within token handler and trigger functions
isInsideConstructor = true;
// Must reset `isInsideConstructor`, even if a `trigger` or `handler` throws
try {
while (i--) { // Run in reverse order
t = tokens[i];
if ((scope & t.scope) && (!t.trigger || t.trigger.call(context))) {
t.pattern.lastIndex = index;
match = t.pattern.exec(pattern); // Running the altered `exec` here allows use of named backreferences, etc.
if (match && match.index === index) {
result = {
output: t.handler.call(context, match, scope),
match: match
};
break;
}
}
}
} catch (err) {
throw err;
} finally {
isInsideConstructor = false;
}
return result;
}
function indexOf (array, item, from) {
if (Array.prototype.indexOf) // Use the native array method if available
return array.indexOf(item, from);
for (var i = from || 0; i < array.length; i++) {
if (array[i] === item)
return i;
}
return -1;
}
//---------------------------------
// Built-in tokens
//---------------------------------
// Augment XRegExp's regular expression syntax and flags. Note that when adding tokens, the
// third (`scope`) argument defaults to `XRegExp.OUTSIDE_CLASS`
// Comment pattern: (?# )
XRegExp.addToken(
/\(\?#[^)]*\)/,
function (match) {
// Keep tokens separated unless the following token is a quantifier
return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ? "" : "(?:)";
}
);
// Capturing group (match the opening parenthesis only).
// Required for support of named capturing groups
XRegExp.addToken(
/\((?!\?)/,
function () {
this.captureNames.push(null);
return "(";
}
);
// Named capturing group (match the opening delimiter only): (?<name>
XRegExp.addToken(
/\(\?<([$\w]+)>/,
function (match) {
this.captureNames.push(match[1]);
this.hasNamedCapture = true;
return "(";
}
);
// Named backreference: \k<name>
XRegExp.addToken(
/\\k<([\w$]+)>/,
function (match) {
var index = indexOf(this.captureNames, match[1]);
// Keep backreferences separate from subsequent literal numbers. Preserve back-
// references to named groups that are undefined at this point as literal strings
return index > -1 ?
"\\" + (index + 1) + (isNaN(match.input.charAt(match.index + match[0].length)) ? "" : "(?:)") :
match[0];
}
);
// Empty character class: [] or [^]
XRegExp.addToken(
/\[\^?]/,
function (match) {
// For cross-browser compatibility with ES3, convert [] to \b\B and [^] to [\s\S].
// (?!) should work like \b\B, but is unreliable in Firefox
return match[0] === "[]" ? "\\b\\B" : "[\\s\\S]";
}
);
// Mode modifier at the start of the pattern only, with any combination of flags imsx: (?imsx)
// Does not support x(?i), (?-i), (?i-m), (?i: ), (?i)(?m), etc.
XRegExp.addToken(
/^\(\?([imsx]+)\)/,
function (match) {
this.setFlag(match[1]);
return "";
}
);
// Whitespace and comments, in free-spacing (aka extended) mode only
XRegExp.addToken(
/(?:\s+|#.*)+/,
function (match) {
// Keep tokens separated unless the following token is a quantifier
return nativ.test.call(quantifier, match.input.slice(match.index + match[0].length)) ? "" : "(?:)";
},
XRegExp.OUTSIDE_CLASS,
function () {return this.hasFlag("x");}
);
// Dot, in dotall (aka singleline) mode only
XRegExp.addToken(
/\./,
function () {return "[\\s\\S]";},
XRegExp.OUTSIDE_CLASS,
function () {return this.hasFlag("s");}
);
//---------------------------------
// Backward compatibility
//---------------------------------
// Uncomment the following block for compatibility with XRegExp 1.0-1.2:
/*
XRegExp.matchWithinChain = XRegExp.matchChain;
RegExp.prototype.addFlags = function (s) {return clone(this, s);};
RegExp.prototype.execAll = function (s) {var r = []; XRegExp.iterate(s, this, function (m) {r.push(m);}); return r;};
RegExp.prototype.forEachExec = function (s, f, c) {return XRegExp.iterate(s, this, f, c);};
RegExp.prototype.validate = function (s) {var r = RegExp("^(?:" + this.source + ")$(?!\\s)", getNativeFlags(this)); if (this.global) this.lastIndex = 0; return s.search(r) === 0;};
*/
})();

View File

@ -0,0 +1,122 @@
(function() {
var sh = SyntaxHighlighter;
/**
* Provides functionality to dynamically load only the brushes that a needed to render the current page.
*
* There are two syntaxes that autoload understands. For example:
*
* SyntaxHighlighter.autoloader(
* [ 'applescript', 'Scripts/shBrushAppleScript.js' ],
* [ 'actionscript3', 'as3', 'Scripts/shBrushAS3.js' ]
* );
*
* or a more easily comprehendable one:
*
* SyntaxHighlighter.autoloader(
* 'applescript Scripts/shBrushAppleScript.js',
* 'actionscript3 as3 Scripts/shBrushAS3.js'
* );
*/
sh.autoloader = function()
{
var list = arguments,
elements = sh.findElements(),
brushes = {},
scripts = {},
all = SyntaxHighlighter.all,
allCalled = false,
allParams = null,
i
;
SyntaxHighlighter.all = function(params)
{
allParams = params;
allCalled = true;
};
function addBrush(aliases, url)
{
for (var i = 0; i < aliases.length; i++)
brushes[aliases[i]] = url;
};
function getAliases(item)
{
return item.pop
? item
: item.split(/\s+/)
;
}
// create table of aliases and script urls
for (i = 0; i < list.length; i++)
{
var aliases = getAliases(list[i]),
url = aliases.pop()
;
addBrush(aliases, url);
}
// dynamically add <script /> tags to the document body
for (i = 0; i < elements.length; i++)
{
var url = brushes[elements[i].params.brush];
if(url && scripts[url] === undefined)
{
if(elements[i].params['html-script'] === 'true')
{
if(scripts[brushes['xml']] === undefined) {
loadScript(brushes['xml']);
scripts[url] = false;
}
}
scripts[url] = false;
loadScript(url);
}
}
function loadScript(url)
{
var script = document.createElement('script'),
done = false
;
script.src = url;
script.type = 'text/javascript';
script.language = 'javascript';
script.onload = script.onreadystatechange = function()
{
if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete'))
{
done = true;
scripts[url] = true;
checkAll();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
script.parentNode.removeChild(script);
}
};
// sync way of adding script tags to the page
document.body.appendChild(script);
};
function checkAll()
{
for(var url in scripts)
if (scripts[url] == false)
return;
if (allCalled)
SyntaxHighlighter.highlight(allParams);
};
};
})();

72
examples/scripts/shBrushPhp.js vendored Normal file
View File

@ -0,0 +1,72 @@
;(function()
{
// CommonJS
SyntaxHighlighter = SyntaxHighlighter || (typeof require !== 'undefined'? require('shCore').SyntaxHighlighter : null);
function Brush()
{
var funcs = 'abs acos acosh addcslashes addslashes ' +
'array_change_key_case array_chunk array_combine array_count_values array_diff '+
'array_diff_assoc array_diff_key array_diff_uassoc array_diff_ukey array_fill '+
'array_filter array_flip array_intersect array_intersect_assoc array_intersect_key '+
'array_intersect_uassoc array_intersect_ukey array_key_exists array_keys array_map '+
'array_merge array_merge_recursive array_multisort array_pad array_pop array_product '+
'array_push array_rand array_reduce array_reverse array_search array_shift '+
'array_slice array_splice array_sum array_udiff array_udiff_assoc '+
'array_udiff_uassoc array_uintersect array_uintersect_assoc '+
'array_uintersect_uassoc array_unique array_unshift array_values array_walk '+
'array_walk_recursive atan atan2 atanh base64_decode base64_encode base_convert '+
'basename bcadd bccomp bcdiv bcmod bcmul bindec bindtextdomain bzclose bzcompress '+
'bzdecompress bzerrno bzerror bzerrstr bzflush bzopen bzread bzwrite ceil chdir '+
'checkdate checkdnsrr chgrp chmod chop chown chr chroot chunk_split class_exists '+
'closedir closelog copy cos cosh count count_chars date decbin dechex decoct '+
'deg2rad delete ebcdic2ascii echo empty end ereg ereg_replace eregi eregi_replace error_log '+
'error_reporting escapeshellarg escapeshellcmd eval exec exit exp explode extension_loaded '+
'feof fflush fgetc fgetcsv fgets fgetss file_exists file_get_contents file_put_contents '+
'fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype '+
'floatval flock floor flush fmod fnmatch fopen fpassthru fprintf fputcsv fputs fread fscanf '+
'fseek fsockopen fstat ftell ftok getallheaders getcwd getdate getenv gethostbyaddr gethostbyname '+
'gethostbynamel getimagesize getlastmod getmxrr getmygid getmyinode getmypid getmyuid getopt '+
'getprotobyname getprotobynumber getrandmax getrusage getservbyname getservbyport gettext '+
'gettimeofday gettype glob gmdate gmmktime ini_alter ini_get ini_get_all ini_restore ini_set '+
'interface_exists intval ip2long is_a is_array is_bool is_callable is_dir is_double '+
'is_executable is_file is_finite is_float is_infinite is_int is_integer is_link is_long '+
'is_nan is_null is_numeric is_object is_readable is_real is_resource is_scalar is_soap_fault '+
'is_string is_subclass_of is_uploaded_file is_writable is_writeable mkdir mktime nl2br '+
'parse_ini_file parse_str parse_url passthru pathinfo print readlink realpath rewind rewinddir rmdir '+
'round str_ireplace str_pad str_repeat str_replace str_rot13 str_shuffle str_split '+
'str_word_count strcasecmp strchr strcmp strcoll strcspn strftime strip_tags stripcslashes '+
'stripos stripslashes stristr strlen strnatcasecmp strnatcmp strncasecmp strncmp strpbrk '+
'strpos strptime strrchr strrev strripos strrpos strspn strstr strtok strtolower strtotime '+
'strtoupper strtr strval substr substr_compare';
var keywords = 'abstract and array as break case catch cfunction class clone const continue declare default die do ' +
'else elseif enddeclare endfor endforeach endif endswitch endwhile extends final for foreach ' +
'function global goto if implements include include_once interface instanceof insteadof namespace new ' +
'old_function or private protected public return require require_once static switch ' +
'trait throw try use var while xor ';
var constants = '__FILE__ __LINE__ __METHOD__ __FUNCTION__ __CLASS__';
this.regexList = [
{ regex: SyntaxHighlighter.regexLib.singleLineCComments, css: 'comments' }, // one line comments
{ regex: SyntaxHighlighter.regexLib.multiLineCComments, css: 'comments' }, // multiline comments
{ regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' }, // double quoted strings
{ regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'string' }, // single quoted strings
{ regex: /\$\w+/g, css: 'variable' }, // variables
{ regex: new RegExp(this.getKeywords(funcs), 'gmi'), css: 'functions' }, // common functions
{ regex: new RegExp(this.getKeywords(constants), 'gmi'), css: 'constants' }, // constants
{ regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword' } // keyword
];
this.forHtmlScript(SyntaxHighlighter.regexLib.phpScriptTags);
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['php'];
SyntaxHighlighter.brushes.Php = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();

1
examples/scripts/shCore.js vendored Normal file

File diff suppressed because one or more lines are too long

140
examples/scripts/shLegacy.js vendored Normal file
View File

@ -0,0 +1,140 @@
var dp = {
SyntaxHighlighter : {}
};
dp.SyntaxHighlighter = {
parseParams: function(
input,
showGutter,
showControls,
collapseAll,
firstLine,
showColumns
)
{
function getValue(list, name)
{
var regex = new XRegExp('^' + name + '\\[(?<value>\\w+)\\]$', 'gi'),
match = null
;
for (var i = 0; i < list.length; i++)
if ((match = regex.exec(list[i])) != null)
return match.value;
return null;
}
function defaultValue(value, def)
{
return value != null ? value : def;
}
function asString(value)
{
return value != null ? value.toString() : null;
}
var parts = input.split(':'),
brushName = parts[0],
options = {},
straight = { 'true' : true },
reverse = { 'true' : false },
defaults = SyntaxHighlighter.defaults
;
for (var i in parts)
options[parts[i]] = 'true';
showGutter = asString(defaultValue(showGutter, defaults.gutter));
showControls = asString(defaultValue(showControls, defaults.toolbar));
collapseAll = asString(defaultValue(collapseAll, defaults.collapse));
showColumns = asString(defaultValue(showColumns, defaults.ruler));
firstLine = asString(defaultValue(firstLine, defaults['first-line']));
return {
brush : brushName,
gutter : defaultValue(reverse[options.nogutter], showGutter),
toolbar : defaultValue(reverse[options.nocontrols], showControls),
collapse : defaultValue(straight[options.collapse], collapseAll),
// ruler : defaultValue(straight[options.showcolumns], showColumns),
'first-line' : defaultValue(getValue(parts, 'firstline'), firstLine)
};
},
HighlightAll: function(
name,
showGutter /* optional */,
showControls /* optional */,
collapseAll /* optional */,
firstLine /* optional */,
showColumns /* optional */
)
{
function findValue()
{
var a = arguments;
for (var i = 0; i < a.length; i++)
{
if (a[i] === null)
continue;
if (typeof(a[i]) == 'string' && a[i] != '')
return a[i] + '';
if (typeof(a[i]) == 'object' && a[i].value != '')
return a[i].value + '';
}
return null;
}
function findTagsByName(list, name, tagName)
{
var tags = document.getElementsByTagName(tagName);
for (var i = 0; i < tags.length; i++)
if (tags[i].getAttribute('name') == name)
list.push(tags[i]);
}
var elements = [],
highlighter = null,
registered = {},
propertyName = 'innerHTML'
;
// for some reason IE doesn't find <pre/> by name, however it does see them just fine by tag name...
findTagsByName(elements, name, 'pre');
findTagsByName(elements, name, 'textarea');
if (elements.length === 0)
return;
for (var i = 0; i < elements.length; i++)
{
var element = elements[i],
params = findValue(
element.attributes['class'], element.className,
element.attributes['language'], element.language
),
language = ''
;
if (params === null)
continue;
params = dp.SyntaxHighlighter.parseParams(
params,
showGutter,
showControls,
collapseAll,
firstLine,
showColumns
);
SyntaxHighlighter.highlight(params, element);
}
}
};

View File

@ -1,40 +1,29 @@
<?php
/**
* PHPMailer simple file upload and send example.
* PHPMailer simple file upload and send example
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/autoload.php';
$msg = '';
if (array_key_exists('userfile', $_FILES)) {
//First handle the upload
//Don't trust provided filename - same goes for MIME types
//See https://www.php.net/manual/en/features.file-upload.php#114004 for more thorough upload validation
//Extract an extension from the provided filename
$ext = PHPMailer::mb_pathinfo($_FILES['userfile']['name'], PATHINFO_EXTENSION);
//Define a safe location to move the uploaded file to, preserving the extension
$uploadfile = tempnam(sys_get_temp_dir(), hash('sha256', $_FILES['userfile']['name'])) . '.' . $ext;
// First handle the upload
// Don't trust provided filename - same goes for MIME types
// See http://php.net/manual/en/features.file-upload.php#114004 for more thorough upload validation
$uploadfile = tempnam(sys_get_temp_dir(), sha1($_FILES['userfile']['name']));
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
//Upload handled successfully
//Now create a message
$mail = new PHPMailer();
// Upload handled successfully
// Now create a message
// This should be somewhere in your include_path
require '../PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->setFrom('from@example.com', 'First Last');
$mail->addAddress('whoto@example.com', 'John Doe');
$mail->Subject = 'PHPMailer file sender';
$mail->Body = 'My message body';
//Attach the uploaded file
if (!$mail->addAttachment($uploadfile, 'My uploaded file')) {
$msg .= 'Failed to attach file ' . $_FILES['userfile']['name'];
}
// Attach the uploaded file
$mail->addAttachment($uploadfile, 'My uploaded file');
if (!$mail->send()) {
$msg .= 'Mailer Error: ' . $mail->ErrorInfo;
$msg .= "Mailer Error: " . $mail->ErrorInfo;
} else {
$msg .= 'Message sent!';
$msg .= "Message sent!";
}
} else {
$msg .= 'Failed to move file to ' . $uploadfile;
@ -42,7 +31,7 @@ if (array_key_exists('userfile', $_FILES)) {
}
?>
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PHPMailer Upload</title>
@ -54,7 +43,7 @@ if (array_key_exists('userfile', $_FILES)) {
<input type="submit" value="Send File">
</form>
<?php } else {
echo htmlspecialchars($msg, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401);
echo $msg;
} ?>
</body>
</html>
</html>

View File

@ -1,46 +1,37 @@
<?php
/**
* PHPMailer multiple files upload and send example
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/autoload.php';
$msg = '';
if (array_key_exists('userfile', $_FILES)) {
//Create a message
$mail = new PHPMailer();
// Create a message
// This should be somewhere in your include_path
require '../PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->setFrom('from@example.com', 'First Last');
$mail->addAddress('whoto@example.com', 'John Doe');
$mail->Subject = 'PHPMailer file sender';
$mail->Body = 'My message body';
//Attach multiple files one by one
for ($ct = 0, $ctMax = count($_FILES['userfile']['tmp_name']); $ct < $ctMax; $ct++) {
//Extract an extension from the provided filename
$ext = PHPMailer::mb_pathinfo($_FILES['userfile']['name'][$ct], PATHINFO_EXTENSION);
//Define a safe location to move the uploaded file to, preserving the extension
$uploadfile = tempnam(sys_get_temp_dir(), hash('sha256', $_FILES['userfile']['name'][$ct])) . '.' . $ext;
for ($ct = 0; $ct < count($_FILES['userfile']['tmp_name']); $ct++) {
$uploadfile = tempnam(sys_get_temp_dir(), sha1($_FILES['userfile']['name'][$ct]));
$filename = $_FILES['userfile']['name'][$ct];
if (move_uploaded_file($_FILES['userfile']['tmp_name'][$ct], $uploadfile)) {
if (!$mail->addAttachment($uploadfile, $filename)) {
$msg .= 'Failed to attach file ' . $filename;
}
$mail->addAttachment($uploadfile, $filename);
} else {
$msg .= 'Failed to move file to ' . $uploadfile;
}
}
if (!$mail->send()) {
$msg .= 'Mailer Error: ' . $mail->ErrorInfo;
$msg .= "Mailer Error: " . $mail->ErrorInfo;
} else {
$msg .= 'Message sent!';
$msg .= "Message sent!";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PHPMailer Upload</title>
@ -54,7 +45,7 @@ if (array_key_exists('userfile', $_FILES)) {
<input type="submit" value="Send Files">
</form>
<?php } else {
echo htmlspecialchars($msg, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401);
echo $msg;
} ?>
</body>
</html>

View File

@ -1,17 +1,13 @@
<?php
/**
* This example shows sending a message using a local sendmail binary.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
//Set PHPMailer to use the sendmail transport
$mail = new PHPMailer;
// Set PHPMailer to use the sendmail transport
$mail->isSendmail();
//Set who the message is to be sent from
$mail->setFrom('from@example.com', 'First Last');
@ -23,7 +19,7 @@ $mail->addAddress('whoto@example.com', 'John Doe');
$mail->Subject = 'PHPMailer sendmail test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
@ -31,7 +27,7 @@ $mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo 'Message sent!';
echo "Message sent!";
}

View File

@ -1,100 +0,0 @@
<?php
/**
* The SendOauth2 wrapper supports OAuth2 and Basic authorization/authentication for
* Microsoft 365 Exchange email and Google Gmail. Both TheLeague's Google provider + client
* and Google's 'official' GoogleAPI client are supported. The wrapper supports any authentication
* mechanism provided by these systems: authorization_code grant and client_credentials grant
* (aka Google 'service accounts'), client secrets and X.509 certificates, $_SESSION 'state'
* and PKCE code exchanges, and creation on the fly of GoogleAPI's .json credentials files.
* Appropriate scopes (client permissions) and 'provider' overrides are added automatically.
*
* The wrapper is installed with Composer from the decomplexity/SendOauth2 repo; see its README.
*
* The wrapper can also be invoked using fewer (or even no) arguments; this is for those websites
* that use PHPMailer in several places. See the repo for details.
*/
// Import PHPMailer classes
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
// Import SendOauth2B class
use decomplexity\SendOauth2\SendOauth2B;
// Uncomment the next two lines to display PHP errors
// error_reporting(E_ALL);
// ini_set("display_errors", 1);
// Load Composer's autoloader
require 'vendor/autoload.php';
// Set timezone for SMTP
date_default_timezone_set('Etc/UTC');
// Create an instance; passing `true` enables exceptions
$mail = new PHPMailer(true);
try {
// Server settings
$mail->isSMTP(); // Use SMTP
$mail->SMTPDebug = SMTP::DEBUG_OFF; // Set DEBUG_LOWLEVEL for SMTP diagnostics
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable implicit TLS encryption
$mail->Port = 587; // TCP port; MSFT doesn't like 465
$mail->AuthType = 'XOAUTH2'; // Set AuthType to use XOAUTH2 ('LOGIN' for Basic auth)
// Sender and recipients
$mail->setFrom('from@example.com', 'Mailer'); // 'Header' From address with optional sender name
$mail->addAddress('joe@example.net', 'Joe User'); // Add a To: recipient
/**
* Authenticate
* Note that any ClientCertificatePrivateKey should include the -----BEGIN PRIVATE KEY----- and
* -----END PRIVATE KEY-----
*/
$oauthTokenProvider = new SendOauth2B(
[
'mail' => $mail, // PHPMailer instance
'clientId' => 'long string', // for Google service account, Unique ID
'clientSecret' => 'long string', // or null if using a certificate
'clientCertificatePrivateKey' => 'ultra long string', // or null if using a clientSecret
'clientCertificateThumbprint' => 'long string', // or null if using a clientSecret
'serviceProvider' => 'Microsoft', // literal: also 'Google' or 'GoogleAPI'
'authTypeSetting' => $mail->AuthType, // is set above - or insert here as 'XOAUTH2'
'mailSMTPAddress' => 'me@mydomain.com', // Envelope/mailFrom/reverse-path From address
'refreshToken' => 'very long string', // null if grantType is 'client_credentials'
'grantType' => 'authorization_code', // or 'client_credentials'
'tenant' => 'long string', // MSFT tenant GUID. Null for Gmail
'hostedDomain' => 'mydomain.com', // Any Google (and optional). Null for MSFT
'projectID' => 'string', // GoogleAPI only. Else null
'serviceAccountName' => 'string', // GoogleAPI service account only. Else null
'impersonate' => 'you@mydomain.com', // Google API service account only. Else null
// default to 'mailSMTPAddress', must be
// a Google Wspace email adddress, not @gmail
'gmailXoauth2Credentials' => 'your credentials.json', // File name - defaults to:
// gmail-xoauth2-credentials.json
'writeGmailCredentialsFile' => 'yes' or 'no', // Defaults to 'yes'; meaning the
// credentials json is dynamically created
]
);
$mail->setOAuth($oauthTokenProvider); // Pass OAuthTokenProvider to PHPMailer
$mail->Host = 'smtp.office365.com'; // Set SMTP server (smtp.gmail.com for Gmail)
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo 'Message could not be sent. Mailer Error: ' . htmlspecialchars($mail->ErrorInfo, ENT_QUOTES);
}

View File

@ -1,40 +1,36 @@
<?php
/**
* This PHPMailer example shows S/MIME signing a message and then sending.
*
* This example shows signing a message and then sending it via the mail() function of PHP.
*
* Before you can sign the mail certificates are needed.
*
*
* STEP 1 - Creating a certificate:
* You can either use a self-signed certificate, pay for a signed one,
* or use free alternatives such as StartSSL, Comodo etc.
* Check out this link for more providers: https://kb.mozillazine.org/Getting_an_SMIME_certificate
* You can either use a self signed certificate, pay for a signed one or use free alternatives such as StartSSL/Comodo etc.
* Check out this link for more providers: http://kb.mozillazine.org/Getting_an_SMIME_certificate
* In this example I am using Comodo.
* The form is directly available via https://secure.comodo.com/products/frontpage?area=SecureEmailCertificate
* Fill it out and you'll get an email with a link to download your certificate.
* Usually the certificate will be directly installed into your browser (FireFox/Chrome).
*
*
*
* STEP 2 - Exporting the certificate
* This is specific to your browser, however, most browsers will give you the option
* to export your recently added certificate in PKCS12 (.pfx)
* This is specific to your browser, however, most browsers will give you the option to export your recently added certificate in PKCS12 (.pfx)
* Include your private key if you are asked for it.
* Set up a password to protect your exported file.
*
*
* STEP 3 - Splitting the .pfx into a private key and the certificate.
* I use openssl for this. You only need two commands. In my case the certificate file is called 'exported-cert.pfx'
* To create the private key do the following:
*
* openssl pkcs12 -in exported-cert.pfx -nocerts -out cert.key
*
*
* Of course the way you name your file (-out) is up to you.
* You will be asked for a password for the Import password. This is the password you
* set while exporting the certificate into the pfx file.
* You will be asked for a password for the Import password. This is the password you just set while exporting the certificate into the pfx file.
* Afterwards, you can password protect your private key (recommended)
* Also make sure to set the permissions to a minimum level and suitable for your application.
* To create the certificate file use the following command:
*
*
* openssl pkcs12 -in exported-cert.pfx -clcerts -nokeys -out cert.crt
*
* Again, the way you name your certificate is up to you. You will be also asked for the Import Password.
@ -48,17 +44,13 @@
* STEP 3 - Code
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
//Set who the message is to be sent from
//IMPORTANT: This must match the email address of your certificate.
//Although the certificate will be valid, an error will be thrown since it cannot be verified
//that the sender and the signer are the same person.
//Although the certificate will be valid, an error will be thrown since it cannot be verified that the sender and the signer are the same person.
$mail->setFrom('from@example.com', 'First Last');
//Set an alternative reply-to address
$mail->addReplyTo('replyto@example.com', 'First Last');
@ -68,7 +60,7 @@ $mail->addAddress('whoto@example.com', 'John Doe');
$mail->Subject = 'PHPMailer mail() test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//Convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
@ -78,22 +70,20 @@ $mail->addAttachment('images/phpmailer_mini.png');
$mail->sign(
'/path/to/cert.crt', //The location of your certificate file
'/path/to/cert.key', //The location of your private key file
//The password you protected your private key with (not the Import Password!
//May be empty but the parameter must not be omitted!
'yourSecretPrivateKeyPassword',
'yourSecretPrivateKeyPassword', //The password you protected your private key with (not the Import Password! may be empty but parameter must not be omitted!)
'/path/to/certchain.pem' //The location of your chain file
);
//Send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo 'Message sent!';
echo "Message sent!";
}
/*
/**
* REMARKS:
* If your email client does not support S/MIME it will most likely just show an attachment smime.p7s,
* which is the signature contained in the email.
* Other clients, such as Thunderbird support S/MIME natively and will validate the signature
* automatically and report the result in some way.
* If your email client does not support S/MIME it will most likely just show an attachment smime.p7s which is the signature contained in the email.
* Other clients, such as Thunderbird support S/MIME natively and will validate the signature automatically and report the result in some way.
*/
?>

View File

@ -1,102 +0,0 @@
<?php
/**
* PHPMailer simple contact form example.
* If you want to accept and send uploads in your form, look at the send_file_upload example.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/autoload.php';
if (array_key_exists('email', $_POST)) {
$err = false;
$msg = '';
$email = '';
//Apply some basic validation and filtering to the subject
if (array_key_exists('subject', $_POST)) {
$subject = substr(strip_tags($_POST['subject']), 0, 255);
} else {
$subject = 'No subject given';
}
//Apply some basic validation and filtering to the query
if (array_key_exists('query', $_POST)) {
//Limit length and strip HTML tags
$query = substr(strip_tags($_POST['query']), 0, 16384);
} else {
$query = '';
$msg = 'No query provided!';
$err = true;
}
//Apply some basic validation and filtering to the name
if (array_key_exists('name', $_POST)) {
//Limit length and strip HTML tags
$name = substr(strip_tags($_POST['name']), 0, 255);
} else {
$name = '';
}
//Validate to address
//Never allow arbitrary input for the 'to' address as it will turn your form into a spam gateway!
//Substitute appropriate addresses from your own domain, or simply use a single, fixed address
if (array_key_exists('to', $_POST) && in_array($_POST['to'], ['sales', 'support', 'accounts'], true)) {
$to = $_POST['to'] . '@example.com';
} else {
$to = 'support@example.com';
}
//Make sure the address they provided is valid before trying to use it
if (PHPMailer::validateAddress($_POST['email'])) {
$email = $_POST['email'];
} else {
$msg .= 'Error: invalid email address provided';
$err = true;
}
if (!$err) {
$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = 'localhost';
$mail->Port = 25;
$mail->CharSet = PHPMailer::CHARSET_UTF8;
//It's important not to use the submitter's address as the from address as it's forgery,
//which will cause your messages to fail SPF checks.
//Use an address in your own domain as the from address, put the submitter's address in a reply-to
$mail->setFrom('contact@example.com', (empty($name) ? 'Contact form' : $name));
$mail->addAddress($to);
$mail->addReplyTo($email, $name);
$mail->Subject = 'Contact form: ' . $subject;
$mail->Body = "Contact form submission\n\n" . $query;
if (!$mail->send()) {
$msg .= 'Mailer Error: ' . $mail->ErrorInfo;
} else {
$msg .= 'Message sent!';
}
}
} ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PHPMailer Contact Form</title>
</head>
<body>
<h1>Contact us</h1>
<?php if (empty($msg)) { ?>
<form method="post">
<label for="to">Send to:</label>
<select name="to" id="to">
<option value="sales">Sales</option>
<option value="support" selected="selected">Support</option>
<option value="accounts">Accounts</option>
</select><br>
<label for="subject">Subject: <input type="text" name="subject" id="subject" maxlength="255"></label><br>
<label for="name">Your name: <input type="text" name="name" id="name" maxlength="255"></label><br>
<label for="email">Your email address: <input type="email" name="email" id="email" maxlength="255"></label><br>
<label for="query">Your question:</label><br>
<textarea cols="30" rows="8" name="query" id="query" placeholder="Your question"></textarea><br>
<input type="submit" value="Submit">
</form>
<?php } else {
echo $msg;
} ?>
</body>
</html>

View File

@ -1,38 +1,35 @@
<?php
/**
* This example shows making an SMTP connection with authentication.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
//SMTP::DEBUG_OFF = off (for production use)
//SMTP::DEBUG_CLIENT = client messages
//SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2;
//Ask for HTML-friendly debug output
$mail->Debugoutput = 'html';
//Set the hostname of the mail server
$mail->Host = 'mail.example.com';
$mail->Host = "mail.example.com";
//Set the SMTP port number - likely to be 25, 465 or 587
$mail->Port = 25;
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Username to use for SMTP authentication
$mail->Username = 'yourname@example.com';
$mail->Username = "yourname@example.com";
//Password to use for SMTP authentication
$mail->Password = 'yourpassword';
$mail->Password = "yourpassword";
//Set who the message is to be sent from
$mail->setFrom('from@example.com', 'First Last');
//Set an alternative reply-to address
@ -43,20 +40,15 @@ $mail->addAddress('whoto@example.com', 'John Doe');
$mail->Subject = 'PHPMailer SMTP test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
$mail->addAttachment('images/phpmailer_mini.png');
//SMTP XCLIENT attributes can be passed with setSMTPXclientAttribute method
//$mail->setSMTPXclientAttribute('LOGIN', 'yourname@example.com');
//$mail->setSMTPXclientAttribute('ADDR', '10.10.10.10');
//$mail->setSMTPXclientAttribute('HELO', 'test.example.com');
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo 'Message sent!';
echo "Message sent!";
}

View File

@ -1,22 +1,17 @@
<?php
/**
* This uses the SMTP class alone to check that a connection can be made to an SMTP server,
* authenticate, then disconnect
*/
//Import the PHPMailer SMTP class into the global namespace
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require '../vendor/autoload.php';
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
require '../PHPMailerAutoload.php';
//Create a new SMTP instance
$smtp = new SMTP();
$smtp = new SMTP;
//Enable connection-level debug output
$smtp->do_debug = SMTP::DEBUG_CONNECTION;
@ -48,7 +43,7 @@ try {
//If server supports authentication, do it (even if no encryption)
if (is_array($e) && array_key_exists('AUTH', $e)) {
if ($smtp->authenticate('username', 'password')) {
echo 'Connected ok!';
echo "Connected ok!";
} else {
throw new Exception('Authentication failed: ' . $smtp->getError()['error']);
}
@ -57,4 +52,4 @@ try {
echo 'SMTP error: ' . $e->getMessage(), "\n";
}
//Whatever happened, close the connection.
$smtp->quit();
$smtp->quit(true);

View File

@ -1,117 +0,0 @@
<?php
/**
* SMTP low memory example.
*/
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
/**
* This class demonstrates sending an already-built RFC822 message via SMTP
* by extending PHPMailer's SMTP class.
* It uses less memory than PHPMailer's usual approach because it keeps
* the message as a single string rather than splitting its lines into
* an array, which can consume very large amounts of memory if you have
* large attachments. The downside is that it's somewhat slower.
* This is mainly of academic interest, but shows how you can change how
* core classes work without having to alter the library itself.
*/
class SMTPLowMemory extends SMTP
{
public function data($msg_data)
{
//This will use the standard timelimit
if (!$this->sendCommand('DATA', 'DATA', 354)) {
return false;
}
/* The server is ready to accept data!
* According to rfc821 we should not send more than 1000 characters on a single line (including the LE)
* so we will break the data up into lines by \r and/or \n then if needed we will break each of those into
* smaller lines to fit within the limit.
* We will also look for lines that start with a '.' and prepend an additional '.' (which does not count
* towards the line-length limit), in order to implement the "dot stuffing" required by RFC5321 sections:
* https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.2
* https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1.6.
*/
//Normalize line breaks
$msg_data = str_replace(["\r\n", "\r"], "\n", $msg_data);
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
* of the first line (':' separated) does not contain a space then it _should_ be a header and we will
* process all lines before a blank line as headers.
*/
$firstline = substr($msg_data, 0, strcspn($msg_data, "\n", 0));
$field = substr($firstline, 0, strpos($firstline, ':'));
$in_headers = false;
if (!empty($field) && strpos($field, ' ') === false) {
$in_headers = true;
}
$offset = 0;
$len = strlen($msg_data);
while ($offset < $len) {
//Get position of next line break
$linelen = strcspn($msg_data, "\n", $offset);
//Get the next line
$line = substr($msg_data, $offset, $linelen);
//Remember where we have got to
$offset += ($linelen + 1);
$lines_out = [];
if ($in_headers && $line === '') {
$in_headers = false;
}
//We need to break this line up into several smaller lines
//This is a small micro-optimisation: isset($str[$len]) is equivalent to (strlen($str) > $len)
while (isset($line[self::MAX_LINE_LENGTH])) {
//Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on
//so as to avoid breaking in the middle of a word
$pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' ');
//Deliberately matches both false and 0
if (!$pos) {
//No nice break found, add a hard break
$pos = self::MAX_LINE_LENGTH - 1;
$lines_out[] = substr($line, 0, $pos);
$line = substr($line, $pos);
} else {
//Break at the found point
$lines_out[] = substr($line, 0, $pos);
//Move along by the amount we dealt with
$line = substr($line, $pos + 1);
}
//If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1
if ($in_headers) {
$line = "\t" . $line;
}
}
$lines_out[] = $line;
//Send the lines to the server
foreach ($lines_out as $line_out) {
//RFC2821 section 4.5.2
if (!empty($line_out) && $line_out[0] === '.') {
$line_out = '.' . $line_out;
}
$this->client_send($line_out . self::LE);
}
}
//Message data has been sent, complete the command
//Increase timelimit for end of DATA command
$savetimelimit = $this->Timelimit;
$this->Timelimit *= 2;
$result = $this->sendCommand('DATA END', '.', 250);
//Restore timelimit
$this->Timelimit = $savetimelimit;
return $result;
}
}
//To make PHPMailer use our custom SMTP class, we need to give it an instance
$mail = new PHPMailer(true);
$mail->setSMTPInstance(new SMTPLowMemory());
//Now carry on as normal

View File

@ -1,34 +1,31 @@
<?php
/**
* This example shows making an SMTP connection without using authentication.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
require '../vendor/autoload.php';
require_once '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
//SMTP::DEBUG_OFF = off (for production use)
//SMTP::DEBUG_CLIENT = client messages
//SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2;
//Ask for HTML-friendly debug output
$mail->Debugoutput = 'html';
//Set the hostname of the mail server
$mail->Host = 'mail.example.com';
$mail->Host = "mail.example.com";
//Set the SMTP port number - likely to be 25, 465 or 587
$mail->Port = 25;
//We don't need to set this as it's the default value
//$mail->SMTPAuth = false;
//Whether to use SMTP authentication
$mail->SMTPAuth = false;
//Set who the message is to be sent from
$mail->setFrom('from@example.com', 'First Last');
//Set an alternative reply-to address
@ -39,7 +36,7 @@ $mail->addAddress('whoto@example.com', 'John Doe');
$mail->Subject = 'PHPMailer SMTP without auth test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
//Attach an image file
@ -47,7 +44,7 @@ $mail->addAttachment('images/phpmailer_mini.png');
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo 'Message sent!';
echo "Message sent!";
}

View File

@ -1,64 +1,57 @@
<?php
/**
* This example shows settings to use when sending over SMTP with TLS and custom connection options.
*/
//Import the PHPMailer class into the global namespace
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
require '../vendor/autoload.php';
require '../PHPMailerAutoload.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging
//SMTP::DEBUG_OFF = off (for production use)
//SMTP::DEBUG_CLIENT = client messages
//SMTP::DEBUG_SERVER = client and server messages
$mail->SMTPDebug = SMTP::DEBUG_CONNECTION;
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2;
//Ask for HTML-friendly debug output
$mail->Debugoutput = 'html';
//Set the hostname of the mail server
$mail->Host = 'smtp.example.com';
//Set the SMTP port number:
// - 465 for SMTP with implicit TLS, a.k.a. RFC8314 SMTPS or
// - 587 for SMTP+STARTTLS
$mail->Port = 465;
//Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
$mail->Port = 587;
//Set the encryption mechanism to use:
// - SMTPS (implicit TLS on port 465) or
// - STARTTLS (explicit TLS on port 587)
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
//Set the encryption system to use - ssl (deprecated) or tls
$mail->SMTPSecure = 'tls';
//Custom connection options
//Note that these settings are INSECURE
$mail->SMTPOptions = array(
'ssl' => [
'verify_peer' => true,
$mail->SMTPOptions = array (
'ssl' => array(
'verify_peer' => true,
'verify_depth' => 3,
'allow_self_signed' => true,
'peer_name' => 'smtp.example.com',
'cafile' => '/etc/ssl/ca_cert.pem',
],
)
);
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Username to use for SMTP authentication - use full email address for gmail
$mail->Username = 'username@example.com';
$mail->Username = "username@example.com";
//Password to use for SMTP authentication
$mail->Password = 'yourpassword';
$mail->Password = "yourpassword";
//Set who the message is to be sent from
$mail->setFrom('from@example.com', 'First Last');
@ -71,11 +64,11 @@ $mail->Subject = 'PHPMailer SMTP options test';
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Send the message, check for errors
//send the message, check for errors
if (!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo;
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo 'Message sent!';
echo "Message sent!";
}

View File

@ -0,0 +1,46 @@
.syntaxhighlighter a,.syntaxhighlighter div,.syntaxhighlighter code,.syntaxhighlighter table,.syntaxhighlighter table td,.syntaxhighlighter table tr,.syntaxhighlighter table tbody,.syntaxhighlighter table thead,.syntaxhighlighter table caption,.syntaxhighlighter textarea{-moz-border-radius:0 0 0 0 !important;-webkit-border-radius:0 0 0 0 !important;background:none !important;border:0 !important;bottom:auto !important;float:none !important;height:auto !important;left:auto !important;line-height:1.1em !important;margin:0 !important;outline:0 !important;overflow:visible !important;padding:0 !important;position:static !important;right:auto !important;text-align:left !important;top:auto !important;vertical-align:baseline !important;width:auto !important;box-sizing:content-box !important;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace !important;font-weight:normal !important;font-style:normal !important;font-size:1em !important;min-height:inherit !important;min-height:auto !important;}
.syntaxhighlighter{width:100% !important;margin:1em 0 1em 0 !important;position:relative !important;overflow:auto !important;font-size:1em !important;}
.syntaxhighlighter.source{overflow:hidden !important;}
.syntaxhighlighter .bold{font-weight:bold !important;}
.syntaxhighlighter .italic{font-style:italic !important;}
.syntaxhighlighter .line{white-space:pre !important;}
.syntaxhighlighter table{width:100% !important;}
.syntaxhighlighter table caption{text-align:left !important;padding:.5em 0 0.5em 1em !important;}
.syntaxhighlighter table td.code{width:100% !important;}
.syntaxhighlighter table td.code .container{position:relative !important;}
.syntaxhighlighter table td.code .container textarea{box-sizing:border-box !important;position:absolute !important;left:0 !important;top:0 !important;width:100% !important;height:100% !important;border:none !important;background:white !important;padding-left:1em !important;overflow:hidden !important;white-space:pre !important;}
.syntaxhighlighter table td.gutter .line{text-align:right !important;padding:0 0.5em 0 1em !important;}
.syntaxhighlighter table td.code .line{padding:0 1em !important;}
.syntaxhighlighter.nogutter td.code .container textarea,.syntaxhighlighter.nogutter td.code .line{padding-left:0em !important;}
.syntaxhighlighter.show{display:block !important;}
.syntaxhighlighter.collapsed table{display:none !important;}
.syntaxhighlighter.collapsed .toolbar{padding:0.1em 0.8em 0em 0.8em !important;font-size:1em !important;position:static !important;width:auto !important;height:auto !important;}
.syntaxhighlighter.collapsed .toolbar span{display:inline !important;margin-right:1em !important;}
.syntaxhighlighter.collapsed .toolbar span a{padding:0 !important;display:none !important;}
.syntaxhighlighter.collapsed .toolbar span a.expandSource{display:inline !important;}
.syntaxhighlighter .toolbar{position:absolute !important;right:1px !important;top:1px !important;width:11px !important;height:11px !important;font-size:10px !important;z-index:10 !important;}
.syntaxhighlighter .toolbar span.title{display:inline !important;}
.syntaxhighlighter .toolbar a{display:block !important;text-align:center !important;text-decoration:none !important;padding-top:1px !important;}
.syntaxhighlighter .toolbar a.expandSource{display:none !important;}
.syntaxhighlighter.ie{font-size:.9em !important;padding:1px 0 1px 0 !important;}
.syntaxhighlighter.ie .toolbar{line-height:8px !important;}
.syntaxhighlighter.ie .toolbar a{padding-top:0px !important;}
.syntaxhighlighter.printing .line.alt1 .content,.syntaxhighlighter.printing .line.alt2 .content,.syntaxhighlighter.printing .line.highlighted .number,.syntaxhighlighter.printing .line.highlighted.alt1 .content,.syntaxhighlighter.printing .line.highlighted.alt2 .content{background:none !important;}
.syntaxhighlighter.printing .line .number{color:#bbbbbb !important;}
.syntaxhighlighter.printing .line .content{color:black !important;}
.syntaxhighlighter.printing .toolbar{display:none !important;}
.syntaxhighlighter.printing a{text-decoration:none !important;}
.syntaxhighlighter.printing .plain,.syntaxhighlighter.printing .plain a{color:black !important;}
.syntaxhighlighter.printing .comments,.syntaxhighlighter.printing .comments a{color:#008200 !important;}
.syntaxhighlighter.printing .string,.syntaxhighlighter.printing .string a{color:blue !important;}
.syntaxhighlighter.printing .keyword{color:#006699 !important;font-weight:bold !important;}
.syntaxhighlighter.printing .preprocessor{color:gray !important;}
.syntaxhighlighter.printing .variable{color:#aa7700 !important;}
.syntaxhighlighter.printing .value{color:#009900 !important;}
.syntaxhighlighter.printing .functions{color:#ff1493 !important;}
.syntaxhighlighter.printing .constants{color:#0066cc !important;}
.syntaxhighlighter.printing .script{font-weight:bold !important;}
.syntaxhighlighter.printing .color1,.syntaxhighlighter.printing .color1 a{color:gray !important;}
.syntaxhighlighter.printing .color2,.syntaxhighlighter.printing .color2 a{color:#ff1493 !important;}
.syntaxhighlighter.printing .color3,.syntaxhighlighter.printing .color3 a{color:red !important;}
.syntaxhighlighter.printing .break,.syntaxhighlighter.printing .break a{color:black !important;}

View File

@ -0,0 +1,77 @@
.syntaxhighlighter a,.syntaxhighlighter div,.syntaxhighlighter code,.syntaxhighlighter table,.syntaxhighlighter table td,.syntaxhighlighter table tr,.syntaxhighlighter table tbody,.syntaxhighlighter table thead,.syntaxhighlighter table caption,.syntaxhighlighter textarea{-moz-border-radius:0 0 0 0 !important;-webkit-border-radius:0 0 0 0 !important;background:none !important;border:0 !important;bottom:auto !important;float:none !important;height:auto !important;left:auto !important;line-height:1.1em !important;margin:0 !important;outline:0 !important;overflow:visible !important;padding:0 !important;position:static !important;right:auto !important;text-align:left !important;top:auto !important;vertical-align:baseline !important;width:auto !important;box-sizing:content-box !important;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace !important;font-weight:normal !important;font-style:normal !important;font-size:1em !important;min-height:inherit !important;min-height:auto !important;}
.syntaxhighlighter{width:100% !important;margin:1em 0 1em 0 !important;position:relative !important;overflow:auto !important;font-size:1em !important;}
.syntaxhighlighter.source{overflow:hidden !important;}
.syntaxhighlighter .bold{font-weight:bold !important;}
.syntaxhighlighter .italic{font-style:italic !important;}
.syntaxhighlighter .line{white-space:pre !important;}
.syntaxhighlighter table{width:100% !important;}
.syntaxhighlighter table caption{text-align:left !important;padding:.5em 0 0.5em 1em !important;}
.syntaxhighlighter table td.code{width:100% !important;}
.syntaxhighlighter table td.code .container{position:relative !important;}
.syntaxhighlighter table td.code .container textarea{box-sizing:border-box !important;position:absolute !important;left:0 !important;top:0 !important;width:100% !important;height:100% !important;border:none !important;background:white !important;padding-left:1em !important;overflow:hidden !important;white-space:pre !important;}
.syntaxhighlighter table td.gutter .line{text-align:right !important;padding:0 0.5em 0 1em !important;}
.syntaxhighlighter table td.code .line{padding:0 1em !important;}
.syntaxhighlighter.nogutter td.code .container textarea,.syntaxhighlighter.nogutter td.code .line{padding-left:0em !important;}
.syntaxhighlighter.show{display:block !important;}
.syntaxhighlighter.collapsed table{display:none !important;}
.syntaxhighlighter.collapsed .toolbar{padding:0.1em 0.8em 0em 0.8em !important;font-size:1em !important;position:static !important;width:auto !important;height:auto !important;}
.syntaxhighlighter.collapsed .toolbar span{display:inline !important;margin-right:1em !important;}
.syntaxhighlighter.collapsed .toolbar span a{padding:0 !important;display:none !important;}
.syntaxhighlighter.collapsed .toolbar span a.expandSource{display:inline !important;}
.syntaxhighlighter .toolbar{position:absolute !important;right:1px !important;top:1px !important;width:11px !important;height:11px !important;font-size:10px !important;z-index:10 !important;}
.syntaxhighlighter .toolbar span.title{display:inline !important;}
.syntaxhighlighter .toolbar a{display:block !important;text-align:center !important;text-decoration:none !important;padding-top:1px !important;}
.syntaxhighlighter .toolbar a.expandSource{display:none !important;}
.syntaxhighlighter.ie{font-size:.9em !important;padding:1px 0 1px 0 !important;}
.syntaxhighlighter.ie .toolbar{line-height:8px !important;}
.syntaxhighlighter.ie .toolbar a{padding-top:0px !important;}
.syntaxhighlighter.printing .line.alt1 .content,.syntaxhighlighter.printing .line.alt2 .content,.syntaxhighlighter.printing .line.highlighted .number,.syntaxhighlighter.printing .line.highlighted.alt1 .content,.syntaxhighlighter.printing .line.highlighted.alt2 .content{background:none !important;}
.syntaxhighlighter.printing .line .number{color:#bbbbbb !important;}
.syntaxhighlighter.printing .line .content{color:black !important;}
.syntaxhighlighter.printing .toolbar{display:none !important;}
.syntaxhighlighter.printing a{text-decoration:none !important;}
.syntaxhighlighter.printing .plain,.syntaxhighlighter.printing .plain a{color:black !important;}
.syntaxhighlighter.printing .comments,.syntaxhighlighter.printing .comments a{color:#008200 !important;}
.syntaxhighlighter.printing .string,.syntaxhighlighter.printing .string a{color:blue !important;}
.syntaxhighlighter.printing .keyword{color:#006699 !important;font-weight:bold !important;}
.syntaxhighlighter.printing .preprocessor{color:gray !important;}
.syntaxhighlighter.printing .variable{color:#aa7700 !important;}
.syntaxhighlighter.printing .value{color:#009900 !important;}
.syntaxhighlighter.printing .functions{color:#ff1493 !important;}
.syntaxhighlighter.printing .constants{color:#0066cc !important;}
.syntaxhighlighter.printing .script{font-weight:bold !important;}
.syntaxhighlighter.printing .color1,.syntaxhighlighter.printing .color1 a{color:gray !important;}
.syntaxhighlighter.printing .color2,.syntaxhighlighter.printing .color2 a{color:#ff1493 !important;}
.syntaxhighlighter.printing .color3,.syntaxhighlighter.printing .color3 a{color:red !important;}
.syntaxhighlighter.printing .break,.syntaxhighlighter.printing .break a{color:black !important;}
.syntaxhighlighter{background-color:white !important;}
.syntaxhighlighter .line.alt1{background-color:white !important;}
.syntaxhighlighter .line.alt2{background-color:white !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#e0e0e0 !important;}
.syntaxhighlighter .line.highlighted.number{color:black !important;}
.syntaxhighlighter table caption{color:black !important;}
.syntaxhighlighter .gutter{color:#afafaf !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #6ce26c !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#6ce26c !important;color:white !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:blue !important;background:white !important;border:1px solid #6ce26c !important;}
.syntaxhighlighter.collapsed .toolbar a{color:blue !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:red !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#6ce26c !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:black !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:black !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#008200 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:blue !important;}
.syntaxhighlighter .keyword{color:#006699 !important;}
.syntaxhighlighter .preprocessor{color:gray !important;}
.syntaxhighlighter .variable{color:#aa7700 !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#ff1493 !important;}
.syntaxhighlighter .constants{color:#0066cc !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#006699 !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:gray !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#ff1493 !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:red !important;}
.syntaxhighlighter .keyword{font-weight:bold !important;}

View File

@ -0,0 +1,78 @@
.syntaxhighlighter a,.syntaxhighlighter div,.syntaxhighlighter code,.syntaxhighlighter table,.syntaxhighlighter table td,.syntaxhighlighter table tr,.syntaxhighlighter table tbody,.syntaxhighlighter table thead,.syntaxhighlighter table caption,.syntaxhighlighter textarea{-moz-border-radius:0 0 0 0 !important;-webkit-border-radius:0 0 0 0 !important;background:none !important;border:0 !important;bottom:auto !important;float:none !important;height:auto !important;left:auto !important;line-height:1.1em !important;margin:0 !important;outline:0 !important;overflow:visible !important;padding:0 !important;position:static !important;right:auto !important;text-align:left !important;top:auto !important;vertical-align:baseline !important;width:auto !important;box-sizing:content-box !important;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace !important;font-weight:normal !important;font-style:normal !important;font-size:1em !important;min-height:inherit !important;min-height:auto !important;}
.syntaxhighlighter{width:100% !important;margin:1em 0 1em 0 !important;position:relative !important;overflow:auto !important;font-size:1em !important;}
.syntaxhighlighter.source{overflow:hidden !important;}
.syntaxhighlighter .bold{font-weight:bold !important;}
.syntaxhighlighter .italic{font-style:italic !important;}
.syntaxhighlighter .line{white-space:pre !important;}
.syntaxhighlighter table{width:100% !important;}
.syntaxhighlighter table caption{text-align:left !important;padding:.5em 0 0.5em 1em !important;}
.syntaxhighlighter table td.code{width:100% !important;}
.syntaxhighlighter table td.code .container{position:relative !important;}
.syntaxhighlighter table td.code .container textarea{box-sizing:border-box !important;position:absolute !important;left:0 !important;top:0 !important;width:100% !important;height:100% !important;border:none !important;background:white !important;padding-left:1em !important;overflow:hidden !important;white-space:pre !important;}
.syntaxhighlighter table td.gutter .line{text-align:right !important;padding:0 0.5em 0 1em !important;}
.syntaxhighlighter table td.code .line{padding:0 1em !important;}
.syntaxhighlighter.nogutter td.code .container textarea,.syntaxhighlighter.nogutter td.code .line{padding-left:0em !important;}
.syntaxhighlighter.show{display:block !important;}
.syntaxhighlighter.collapsed table{display:none !important;}
.syntaxhighlighter.collapsed .toolbar{padding:0.1em 0.8em 0em 0.8em !important;font-size:1em !important;position:static !important;width:auto !important;height:auto !important;}
.syntaxhighlighter.collapsed .toolbar span{display:inline !important;margin-right:1em !important;}
.syntaxhighlighter.collapsed .toolbar span a{padding:0 !important;display:none !important;}
.syntaxhighlighter.collapsed .toolbar span a.expandSource{display:inline !important;}
.syntaxhighlighter .toolbar{position:absolute !important;right:1px !important;top:1px !important;width:11px !important;height:11px !important;font-size:10px !important;z-index:10 !important;}
.syntaxhighlighter .toolbar span.title{display:inline !important;}
.syntaxhighlighter .toolbar a{display:block !important;text-align:center !important;text-decoration:none !important;padding-top:1px !important;}
.syntaxhighlighter .toolbar a.expandSource{display:none !important;}
.syntaxhighlighter.ie{font-size:.9em !important;padding:1px 0 1px 0 !important;}
.syntaxhighlighter.ie .toolbar{line-height:8px !important;}
.syntaxhighlighter.ie .toolbar a{padding-top:0px !important;}
.syntaxhighlighter.printing .line.alt1 .content,.syntaxhighlighter.printing .line.alt2 .content,.syntaxhighlighter.printing .line.highlighted .number,.syntaxhighlighter.printing .line.highlighted.alt1 .content,.syntaxhighlighter.printing .line.highlighted.alt2 .content{background:none !important;}
.syntaxhighlighter.printing .line .number{color:#bbbbbb !important;}
.syntaxhighlighter.printing .line .content{color:black !important;}
.syntaxhighlighter.printing .toolbar{display:none !important;}
.syntaxhighlighter.printing a{text-decoration:none !important;}
.syntaxhighlighter.printing .plain,.syntaxhighlighter.printing .plain a{color:black !important;}
.syntaxhighlighter.printing .comments,.syntaxhighlighter.printing .comments a{color:#008200 !important;}
.syntaxhighlighter.printing .string,.syntaxhighlighter.printing .string a{color:blue !important;}
.syntaxhighlighter.printing .keyword{color:#006699 !important;font-weight:bold !important;}
.syntaxhighlighter.printing .preprocessor{color:gray !important;}
.syntaxhighlighter.printing .variable{color:#aa7700 !important;}
.syntaxhighlighter.printing .value{color:#009900 !important;}
.syntaxhighlighter.printing .functions{color:#ff1493 !important;}
.syntaxhighlighter.printing .constants{color:#0066cc !important;}
.syntaxhighlighter.printing .script{font-weight:bold !important;}
.syntaxhighlighter.printing .color1,.syntaxhighlighter.printing .color1 a{color:gray !important;}
.syntaxhighlighter.printing .color2,.syntaxhighlighter.printing .color2 a{color:#ff1493 !important;}
.syntaxhighlighter.printing .color3,.syntaxhighlighter.printing .color3 a{color:red !important;}
.syntaxhighlighter.printing .break,.syntaxhighlighter.printing .break a{color:black !important;}
.syntaxhighlighter{background-color:#0a2b1d !important;}
.syntaxhighlighter .line.alt1{background-color:#0a2b1d !important;}
.syntaxhighlighter .line.alt2{background-color:#0a2b1d !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#233729 !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:#f8f8f8 !important;}
.syntaxhighlighter .gutter{color:#497958 !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #41a83e !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#41a83e !important;color:#0a2b1d !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#96dd3b !important;background:black !important;border:1px solid #41a83e !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#96dd3b !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:white !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#41a83e !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:#ffe862 !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:#f8f8f8 !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#336442 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#9df39f !important;}
.syntaxhighlighter .keyword{color:#96dd3b !important;}
.syntaxhighlighter .preprocessor{color:#91bb9e !important;}
.syntaxhighlighter .variable{color:#ffaa3e !important;}
.syntaxhighlighter .value{color:#f7e741 !important;}
.syntaxhighlighter .functions{color:#ffaa3e !important;}
.syntaxhighlighter .constants{color:#e0e8ff !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#96dd3b !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#eb939a !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#91bb9e !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#edef7d !important;}
.syntaxhighlighter .comments{font-style:italic !important;}
.syntaxhighlighter .keyword{font-weight:bold !important;}

View File

@ -0,0 +1,80 @@
.syntaxhighlighter a,.syntaxhighlighter div,.syntaxhighlighter code,.syntaxhighlighter table,.syntaxhighlighter table td,.syntaxhighlighter table tr,.syntaxhighlighter table tbody,.syntaxhighlighter table thead,.syntaxhighlighter table caption,.syntaxhighlighter textarea{-moz-border-radius:0 0 0 0 !important;-webkit-border-radius:0 0 0 0 !important;background:none !important;border:0 !important;bottom:auto !important;float:none !important;height:auto !important;left:auto !important;line-height:1.1em !important;margin:0 !important;outline:0 !important;overflow:visible !important;padding:0 !important;position:static !important;right:auto !important;text-align:left !important;top:auto !important;vertical-align:baseline !important;width:auto !important;box-sizing:content-box !important;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace !important;font-weight:normal !important;font-style:normal !important;font-size:1em !important;min-height:inherit !important;min-height:auto !important;}
.syntaxhighlighter{width:100% !important;margin:1em 0 1em 0 !important;position:relative !important;overflow:auto !important;font-size:1em !important;}
.syntaxhighlighter.source{overflow:hidden !important;}
.syntaxhighlighter .bold{font-weight:bold !important;}
.syntaxhighlighter .italic{font-style:italic !important;}
.syntaxhighlighter .line{white-space:pre !important;}
.syntaxhighlighter table{width:100% !important;}
.syntaxhighlighter table caption{text-align:left !important;padding:.5em 0 0.5em 1em !important;}
.syntaxhighlighter table td.code{width:100% !important;}
.syntaxhighlighter table td.code .container{position:relative !important;}
.syntaxhighlighter table td.code .container textarea{box-sizing:border-box !important;position:absolute !important;left:0 !important;top:0 !important;width:100% !important;height:100% !important;border:none !important;background:white !important;padding-left:1em !important;overflow:hidden !important;white-space:pre !important;}
.syntaxhighlighter table td.gutter .line{text-align:right !important;padding:0 0.5em 0 1em !important;}
.syntaxhighlighter table td.code .line{padding:0 1em !important;}
.syntaxhighlighter.nogutter td.code .container textarea,.syntaxhighlighter.nogutter td.code .line{padding-left:0em !important;}
.syntaxhighlighter.show{display:block !important;}
.syntaxhighlighter.collapsed table{display:none !important;}
.syntaxhighlighter.collapsed .toolbar{padding:0.1em 0.8em 0em 0.8em !important;font-size:1em !important;position:static !important;width:auto !important;height:auto !important;}
.syntaxhighlighter.collapsed .toolbar span{display:inline !important;margin-right:1em !important;}
.syntaxhighlighter.collapsed .toolbar span a{padding:0 !important;display:none !important;}
.syntaxhighlighter.collapsed .toolbar span a.expandSource{display:inline !important;}
.syntaxhighlighter .toolbar{position:absolute !important;right:1px !important;top:1px !important;width:11px !important;height:11px !important;font-size:10px !important;z-index:10 !important;}
.syntaxhighlighter .toolbar span.title{display:inline !important;}
.syntaxhighlighter .toolbar a{display:block !important;text-align:center !important;text-decoration:none !important;padding-top:1px !important;}
.syntaxhighlighter .toolbar a.expandSource{display:none !important;}
.syntaxhighlighter.ie{font-size:.9em !important;padding:1px 0 1px 0 !important;}
.syntaxhighlighter.ie .toolbar{line-height:8px !important;}
.syntaxhighlighter.ie .toolbar a{padding-top:0px !important;}
.syntaxhighlighter.printing .line.alt1 .content,.syntaxhighlighter.printing .line.alt2 .content,.syntaxhighlighter.printing .line.highlighted .number,.syntaxhighlighter.printing .line.highlighted.alt1 .content,.syntaxhighlighter.printing .line.highlighted.alt2 .content{background:none !important;}
.syntaxhighlighter.printing .line .number{color:#bbbbbb !important;}
.syntaxhighlighter.printing .line .content{color:black !important;}
.syntaxhighlighter.printing .toolbar{display:none !important;}
.syntaxhighlighter.printing a{text-decoration:none !important;}
.syntaxhighlighter.printing .plain,.syntaxhighlighter.printing .plain a{color:black !important;}
.syntaxhighlighter.printing .comments,.syntaxhighlighter.printing .comments a{color:#008200 !important;}
.syntaxhighlighter.printing .string,.syntaxhighlighter.printing .string a{color:blue !important;}
.syntaxhighlighter.printing .keyword{color:#006699 !important;font-weight:bold !important;}
.syntaxhighlighter.printing .preprocessor{color:gray !important;}
.syntaxhighlighter.printing .variable{color:#aa7700 !important;}
.syntaxhighlighter.printing .value{color:#009900 !important;}
.syntaxhighlighter.printing .functions{color:#ff1493 !important;}
.syntaxhighlighter.printing .constants{color:#0066cc !important;}
.syntaxhighlighter.printing .script{font-weight:bold !important;}
.syntaxhighlighter.printing .color1,.syntaxhighlighter.printing .color1 a{color:gray !important;}
.syntaxhighlighter.printing .color2,.syntaxhighlighter.printing .color2 a{color:#ff1493 !important;}
.syntaxhighlighter.printing .color3,.syntaxhighlighter.printing .color3 a{color:red !important;}
.syntaxhighlighter.printing .break,.syntaxhighlighter.printing .break a{color:black !important;}
.syntaxhighlighter{background-color:white !important;}
.syntaxhighlighter .line.alt1{background-color:white !important;}
.syntaxhighlighter .line.alt2{background-color:white !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#c3defe !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:black !important;}
.syntaxhighlighter .gutter{color:#787878 !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #d4d0c8 !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#d4d0c8 !important;color:white !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#3f5fbf !important;background:white !important;border:1px solid #d4d0c8 !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#3f5fbf !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#aa7700 !important;}
.syntaxhighlighter .toolbar{color:#a0a0a0 !important;background:#d4d0c8 !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:#a0a0a0 !important;}
.syntaxhighlighter .toolbar a:hover{color:red !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:black !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#3f5fbf !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#2a00ff !important;}
.syntaxhighlighter .keyword{color:#7f0055 !important;}
.syntaxhighlighter .preprocessor{color:#646464 !important;}
.syntaxhighlighter .variable{color:#aa7700 !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#ff1493 !important;}
.syntaxhighlighter .constants{color:#0066cc !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#7f0055 !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:gray !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#ff1493 !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:red !important;}
.syntaxhighlighter .keyword{font-weight:bold !important;}
.syntaxhighlighter .xml .keyword{color:#3f7f7f !important;font-weight:normal !important;}
.syntaxhighlighter .xml .color1,.syntaxhighlighter .xml .color1 a{color:#7f007f !important;}
.syntaxhighlighter .xml .string{font-style:italic !important;color:#2a00ff !important;}

View File

@ -0,0 +1,76 @@
.syntaxhighlighter a,.syntaxhighlighter div,.syntaxhighlighter code,.syntaxhighlighter table,.syntaxhighlighter table td,.syntaxhighlighter table tr,.syntaxhighlighter table tbody,.syntaxhighlighter table thead,.syntaxhighlighter table caption,.syntaxhighlighter textarea{-moz-border-radius:0 0 0 0 !important;-webkit-border-radius:0 0 0 0 !important;background:none !important;border:0 !important;bottom:auto !important;float:none !important;height:auto !important;left:auto !important;line-height:1.1em !important;margin:0 !important;outline:0 !important;overflow:visible !important;padding:0 !important;position:static !important;right:auto !important;text-align:left !important;top:auto !important;vertical-align:baseline !important;width:auto !important;box-sizing:content-box !important;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace !important;font-weight:normal !important;font-style:normal !important;font-size:1em !important;min-height:inherit !important;min-height:auto !important;}
.syntaxhighlighter{width:100% !important;margin:1em 0 1em 0 !important;position:relative !important;overflow:auto !important;font-size:1em !important;}
.syntaxhighlighter.source{overflow:hidden !important;}
.syntaxhighlighter .bold{font-weight:bold !important;}
.syntaxhighlighter .italic{font-style:italic !important;}
.syntaxhighlighter .line{white-space:pre !important;}
.syntaxhighlighter table{width:100% !important;}
.syntaxhighlighter table caption{text-align:left !important;padding:.5em 0 0.5em 1em !important;}
.syntaxhighlighter table td.code{width:100% !important;}
.syntaxhighlighter table td.code .container{position:relative !important;}
.syntaxhighlighter table td.code .container textarea{box-sizing:border-box !important;position:absolute !important;left:0 !important;top:0 !important;width:100% !important;height:100% !important;border:none !important;background:white !important;padding-left:1em !important;overflow:hidden !important;white-space:pre !important;}
.syntaxhighlighter table td.gutter .line{text-align:right !important;padding:0 0.5em 0 1em !important;}
.syntaxhighlighter table td.code .line{padding:0 1em !important;}
.syntaxhighlighter.nogutter td.code .container textarea,.syntaxhighlighter.nogutter td.code .line{padding-left:0em !important;}
.syntaxhighlighter.show{display:block !important;}
.syntaxhighlighter.collapsed table{display:none !important;}
.syntaxhighlighter.collapsed .toolbar{padding:0.1em 0.8em 0em 0.8em !important;font-size:1em !important;position:static !important;width:auto !important;height:auto !important;}
.syntaxhighlighter.collapsed .toolbar span{display:inline !important;margin-right:1em !important;}
.syntaxhighlighter.collapsed .toolbar span a{padding:0 !important;display:none !important;}
.syntaxhighlighter.collapsed .toolbar span a.expandSource{display:inline !important;}
.syntaxhighlighter .toolbar{position:absolute !important;right:1px !important;top:1px !important;width:11px !important;height:11px !important;font-size:10px !important;z-index:10 !important;}
.syntaxhighlighter .toolbar span.title{display:inline !important;}
.syntaxhighlighter .toolbar a{display:block !important;text-align:center !important;text-decoration:none !important;padding-top:1px !important;}
.syntaxhighlighter .toolbar a.expandSource{display:none !important;}
.syntaxhighlighter.ie{font-size:.9em !important;padding:1px 0 1px 0 !important;}
.syntaxhighlighter.ie .toolbar{line-height:8px !important;}
.syntaxhighlighter.ie .toolbar a{padding-top:0px !important;}
.syntaxhighlighter.printing .line.alt1 .content,.syntaxhighlighter.printing .line.alt2 .content,.syntaxhighlighter.printing .line.highlighted .number,.syntaxhighlighter.printing .line.highlighted.alt1 .content,.syntaxhighlighter.printing .line.highlighted.alt2 .content{background:none !important;}
.syntaxhighlighter.printing .line .number{color:#bbbbbb !important;}
.syntaxhighlighter.printing .line .content{color:black !important;}
.syntaxhighlighter.printing .toolbar{display:none !important;}
.syntaxhighlighter.printing a{text-decoration:none !important;}
.syntaxhighlighter.printing .plain,.syntaxhighlighter.printing .plain a{color:black !important;}
.syntaxhighlighter.printing .comments,.syntaxhighlighter.printing .comments a{color:#008200 !important;}
.syntaxhighlighter.printing .string,.syntaxhighlighter.printing .string a{color:blue !important;}
.syntaxhighlighter.printing .keyword{color:#006699 !important;font-weight:bold !important;}
.syntaxhighlighter.printing .preprocessor{color:gray !important;}
.syntaxhighlighter.printing .variable{color:#aa7700 !important;}
.syntaxhighlighter.printing .value{color:#009900 !important;}
.syntaxhighlighter.printing .functions{color:#ff1493 !important;}
.syntaxhighlighter.printing .constants{color:#0066cc !important;}
.syntaxhighlighter.printing .script{font-weight:bold !important;}
.syntaxhighlighter.printing .color1,.syntaxhighlighter.printing .color1 a{color:gray !important;}
.syntaxhighlighter.printing .color2,.syntaxhighlighter.printing .color2 a{color:#ff1493 !important;}
.syntaxhighlighter.printing .color3,.syntaxhighlighter.printing .color3 a{color:red !important;}
.syntaxhighlighter.printing .break,.syntaxhighlighter.printing .break a{color:black !important;}
.syntaxhighlighter{background-color:black !important;}
.syntaxhighlighter .line.alt1{background-color:black !important;}
.syntaxhighlighter .line.alt2{background-color:black !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#2a3133 !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:#d3d3d3 !important;}
.syntaxhighlighter .gutter{color:#d3d3d3 !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #990000 !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#990000 !important;color:black !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#ebdb8d !important;background:black !important;border:1px solid #990000 !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#ebdb8d !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#ff7d27 !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#990000 !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:#9ccff4 !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:#d3d3d3 !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#ff7d27 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#ff9e7b !important;}
.syntaxhighlighter .keyword{color:aqua !important;}
.syntaxhighlighter .preprocessor{color:#aec4de !important;}
.syntaxhighlighter .variable{color:#ffaa3e !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#81cef9 !important;}
.syntaxhighlighter .constants{color:#ff9e7b !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:aqua !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#ebdb8d !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#ff7d27 !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#aec4de !important;}

View File

@ -0,0 +1,77 @@
.syntaxhighlighter a,.syntaxhighlighter div,.syntaxhighlighter code,.syntaxhighlighter table,.syntaxhighlighter table td,.syntaxhighlighter table tr,.syntaxhighlighter table tbody,.syntaxhighlighter table thead,.syntaxhighlighter table caption,.syntaxhighlighter textarea{-moz-border-radius:0 0 0 0 !important;-webkit-border-radius:0 0 0 0 !important;background:none !important;border:0 !important;bottom:auto !important;float:none !important;height:auto !important;left:auto !important;line-height:1.1em !important;margin:0 !important;outline:0 !important;overflow:visible !important;padding:0 !important;position:static !important;right:auto !important;text-align:left !important;top:auto !important;vertical-align:baseline !important;width:auto !important;box-sizing:content-box !important;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace !important;font-weight:normal !important;font-style:normal !important;font-size:1em !important;min-height:inherit !important;min-height:auto !important;}
.syntaxhighlighter{width:100% !important;margin:1em 0 1em 0 !important;position:relative !important;overflow:auto !important;font-size:1em !important;}
.syntaxhighlighter.source{overflow:hidden !important;}
.syntaxhighlighter .bold{font-weight:bold !important;}
.syntaxhighlighter .italic{font-style:italic !important;}
.syntaxhighlighter .line{white-space:pre !important;}
.syntaxhighlighter table{width:100% !important;}
.syntaxhighlighter table caption{text-align:left !important;padding:.5em 0 0.5em 1em !important;}
.syntaxhighlighter table td.code{width:100% !important;}
.syntaxhighlighter table td.code .container{position:relative !important;}
.syntaxhighlighter table td.code .container textarea{box-sizing:border-box !important;position:absolute !important;left:0 !important;top:0 !important;width:100% !important;height:100% !important;border:none !important;background:white !important;padding-left:1em !important;overflow:hidden !important;white-space:pre !important;}
.syntaxhighlighter table td.gutter .line{text-align:right !important;padding:0 0.5em 0 1em !important;}
.syntaxhighlighter table td.code .line{padding:0 1em !important;}
.syntaxhighlighter.nogutter td.code .container textarea,.syntaxhighlighter.nogutter td.code .line{padding-left:0em !important;}
.syntaxhighlighter.show{display:block !important;}
.syntaxhighlighter.collapsed table{display:none !important;}
.syntaxhighlighter.collapsed .toolbar{padding:0.1em 0.8em 0em 0.8em !important;font-size:1em !important;position:static !important;width:auto !important;height:auto !important;}
.syntaxhighlighter.collapsed .toolbar span{display:inline !important;margin-right:1em !important;}
.syntaxhighlighter.collapsed .toolbar span a{padding:0 !important;display:none !important;}
.syntaxhighlighter.collapsed .toolbar span a.expandSource{display:inline !important;}
.syntaxhighlighter .toolbar{position:absolute !important;right:1px !important;top:1px !important;width:11px !important;height:11px !important;font-size:10px !important;z-index:10 !important;}
.syntaxhighlighter .toolbar span.title{display:inline !important;}
.syntaxhighlighter .toolbar a{display:block !important;text-align:center !important;text-decoration:none !important;padding-top:1px !important;}
.syntaxhighlighter .toolbar a.expandSource{display:none !important;}
.syntaxhighlighter.ie{font-size:.9em !important;padding:1px 0 1px 0 !important;}
.syntaxhighlighter.ie .toolbar{line-height:8px !important;}
.syntaxhighlighter.ie .toolbar a{padding-top:0px !important;}
.syntaxhighlighter.printing .line.alt1 .content,.syntaxhighlighter.printing .line.alt2 .content,.syntaxhighlighter.printing .line.highlighted .number,.syntaxhighlighter.printing .line.highlighted.alt1 .content,.syntaxhighlighter.printing .line.highlighted.alt2 .content{background:none !important;}
.syntaxhighlighter.printing .line .number{color:#bbbbbb !important;}
.syntaxhighlighter.printing .line .content{color:black !important;}
.syntaxhighlighter.printing .toolbar{display:none !important;}
.syntaxhighlighter.printing a{text-decoration:none !important;}
.syntaxhighlighter.printing .plain,.syntaxhighlighter.printing .plain a{color:black !important;}
.syntaxhighlighter.printing .comments,.syntaxhighlighter.printing .comments a{color:#008200 !important;}
.syntaxhighlighter.printing .string,.syntaxhighlighter.printing .string a{color:blue !important;}
.syntaxhighlighter.printing .keyword{color:#006699 !important;font-weight:bold !important;}
.syntaxhighlighter.printing .preprocessor{color:gray !important;}
.syntaxhighlighter.printing .variable{color:#aa7700 !important;}
.syntaxhighlighter.printing .value{color:#009900 !important;}
.syntaxhighlighter.printing .functions{color:#ff1493 !important;}
.syntaxhighlighter.printing .constants{color:#0066cc !important;}
.syntaxhighlighter.printing .script{font-weight:bold !important;}
.syntaxhighlighter.printing .color1,.syntaxhighlighter.printing .color1 a{color:gray !important;}
.syntaxhighlighter.printing .color2,.syntaxhighlighter.printing .color2 a{color:#ff1493 !important;}
.syntaxhighlighter.printing .color3,.syntaxhighlighter.printing .color3 a{color:red !important;}
.syntaxhighlighter.printing .break,.syntaxhighlighter.printing .break a{color:black !important;}
.syntaxhighlighter{background-color:#121212 !important;}
.syntaxhighlighter .line.alt1{background-color:#121212 !important;}
.syntaxhighlighter .line.alt2{background-color:#121212 !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#2c2c29 !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:white !important;}
.syntaxhighlighter .gutter{color:#afafaf !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #3185b9 !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#3185b9 !important;color:#121212 !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#3185b9 !important;background:black !important;border:1px solid #3185b9 !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#3185b9 !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#d01d33 !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#3185b9 !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:#96daff !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:white !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#696854 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#e3e658 !important;}
.syntaxhighlighter .keyword{color:#d01d33 !important;}
.syntaxhighlighter .preprocessor{color:#435a5f !important;}
.syntaxhighlighter .variable{color:#898989 !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#aaaaaa !important;}
.syntaxhighlighter .constants{color:#96daff !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#d01d33 !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#ffc074 !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#4a8cdb !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#96daff !important;}
.syntaxhighlighter .functions{font-weight:bold !important;}

View File

@ -0,0 +1,76 @@
.syntaxhighlighter a,.syntaxhighlighter div,.syntaxhighlighter code,.syntaxhighlighter table,.syntaxhighlighter table td,.syntaxhighlighter table tr,.syntaxhighlighter table tbody,.syntaxhighlighter table thead,.syntaxhighlighter table caption,.syntaxhighlighter textarea{-moz-border-radius:0 0 0 0 !important;-webkit-border-radius:0 0 0 0 !important;background:none !important;border:0 !important;bottom:auto !important;float:none !important;height:auto !important;left:auto !important;line-height:1.1em !important;margin:0 !important;outline:0 !important;overflow:visible !important;padding:0 !important;position:static !important;right:auto !important;text-align:left !important;top:auto !important;vertical-align:baseline !important;width:auto !important;box-sizing:content-box !important;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace !important;font-weight:normal !important;font-style:normal !important;font-size:1em !important;min-height:inherit !important;min-height:auto !important;}
.syntaxhighlighter{width:100% !important;margin:1em 0 1em 0 !important;position:relative !important;overflow:auto !important;font-size:1em !important;}
.syntaxhighlighter.source{overflow:hidden !important;}
.syntaxhighlighter .bold{font-weight:bold !important;}
.syntaxhighlighter .italic{font-style:italic !important;}
.syntaxhighlighter .line{white-space:pre !important;}
.syntaxhighlighter table{width:100% !important;}
.syntaxhighlighter table caption{text-align:left !important;padding:.5em 0 0.5em 1em !important;}
.syntaxhighlighter table td.code{width:100% !important;}
.syntaxhighlighter table td.code .container{position:relative !important;}
.syntaxhighlighter table td.code .container textarea{box-sizing:border-box !important;position:absolute !important;left:0 !important;top:0 !important;width:100% !important;height:100% !important;border:none !important;background:white !important;padding-left:1em !important;overflow:hidden !important;white-space:pre !important;}
.syntaxhighlighter table td.gutter .line{text-align:right !important;padding:0 0.5em 0 1em !important;}
.syntaxhighlighter table td.code .line{padding:0 1em !important;}
.syntaxhighlighter.nogutter td.code .container textarea,.syntaxhighlighter.nogutter td.code .line{padding-left:0em !important;}
.syntaxhighlighter.show{display:block !important;}
.syntaxhighlighter.collapsed table{display:none !important;}
.syntaxhighlighter.collapsed .toolbar{padding:0.1em 0.8em 0em 0.8em !important;font-size:1em !important;position:static !important;width:auto !important;height:auto !important;}
.syntaxhighlighter.collapsed .toolbar span{display:inline !important;margin-right:1em !important;}
.syntaxhighlighter.collapsed .toolbar span a{padding:0 !important;display:none !important;}
.syntaxhighlighter.collapsed .toolbar span a.expandSource{display:inline !important;}
.syntaxhighlighter .toolbar{position:absolute !important;right:1px !important;top:1px !important;width:11px !important;height:11px !important;font-size:10px !important;z-index:10 !important;}
.syntaxhighlighter .toolbar span.title{display:inline !important;}
.syntaxhighlighter .toolbar a{display:block !important;text-align:center !important;text-decoration:none !important;padding-top:1px !important;}
.syntaxhighlighter .toolbar a.expandSource{display:none !important;}
.syntaxhighlighter.ie{font-size:.9em !important;padding:1px 0 1px 0 !important;}
.syntaxhighlighter.ie .toolbar{line-height:8px !important;}
.syntaxhighlighter.ie .toolbar a{padding-top:0px !important;}
.syntaxhighlighter.printing .line.alt1 .content,.syntaxhighlighter.printing .line.alt2 .content,.syntaxhighlighter.printing .line.highlighted .number,.syntaxhighlighter.printing .line.highlighted.alt1 .content,.syntaxhighlighter.printing .line.highlighted.alt2 .content{background:none !important;}
.syntaxhighlighter.printing .line .number{color:#bbbbbb !important;}
.syntaxhighlighter.printing .line .content{color:black !important;}
.syntaxhighlighter.printing .toolbar{display:none !important;}
.syntaxhighlighter.printing a{text-decoration:none !important;}
.syntaxhighlighter.printing .plain,.syntaxhighlighter.printing .plain a{color:black !important;}
.syntaxhighlighter.printing .comments,.syntaxhighlighter.printing .comments a{color:#008200 !important;}
.syntaxhighlighter.printing .string,.syntaxhighlighter.printing .string a{color:blue !important;}
.syntaxhighlighter.printing .keyword{color:#006699 !important;font-weight:bold !important;}
.syntaxhighlighter.printing .preprocessor{color:gray !important;}
.syntaxhighlighter.printing .variable{color:#aa7700 !important;}
.syntaxhighlighter.printing .value{color:#009900 !important;}
.syntaxhighlighter.printing .functions{color:#ff1493 !important;}
.syntaxhighlighter.printing .constants{color:#0066cc !important;}
.syntaxhighlighter.printing .script{font-weight:bold !important;}
.syntaxhighlighter.printing .color1,.syntaxhighlighter.printing .color1 a{color:gray !important;}
.syntaxhighlighter.printing .color2,.syntaxhighlighter.printing .color2 a{color:#ff1493 !important;}
.syntaxhighlighter.printing .color3,.syntaxhighlighter.printing .color3 a{color:red !important;}
.syntaxhighlighter.printing .break,.syntaxhighlighter.printing .break a{color:black !important;}
.syntaxhighlighter{background-color:#222222 !important;}
.syntaxhighlighter .line.alt1{background-color:#222222 !important;}
.syntaxhighlighter .line.alt2{background-color:#222222 !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#253e5a !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:lime !important;}
.syntaxhighlighter .gutter{color:#38566f !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #435a5f !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#435a5f !important;color:#222222 !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#428bdd !important;background:black !important;border:1px solid #435a5f !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#428bdd !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:lime !important;}
.syntaxhighlighter .toolbar{color:#aaaaff !important;background:#435a5f !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:#aaaaff !important;}
.syntaxhighlighter .toolbar a:hover{color:#9ccff4 !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:lime !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#428bdd !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:lime !important;}
.syntaxhighlighter .keyword{color:#aaaaff !important;}
.syntaxhighlighter .preprocessor{color:#8aa6c1 !important;}
.syntaxhighlighter .variable{color:aqua !important;}
.syntaxhighlighter .value{color:#f7e741 !important;}
.syntaxhighlighter .functions{color:#ff8000 !important;}
.syntaxhighlighter .constants{color:yellow !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#aaaaff !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:red !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:yellow !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#ffaa3e !important;}

View File

@ -0,0 +1,76 @@
.syntaxhighlighter a,.syntaxhighlighter div,.syntaxhighlighter code,.syntaxhighlighter table,.syntaxhighlighter table td,.syntaxhighlighter table tr,.syntaxhighlighter table tbody,.syntaxhighlighter table thead,.syntaxhighlighter table caption,.syntaxhighlighter textarea{-moz-border-radius:0 0 0 0 !important;-webkit-border-radius:0 0 0 0 !important;background:none !important;border:0 !important;bottom:auto !important;float:none !important;height:auto !important;left:auto !important;line-height:1.1em !important;margin:0 !important;outline:0 !important;overflow:visible !important;padding:0 !important;position:static !important;right:auto !important;text-align:left !important;top:auto !important;vertical-align:baseline !important;width:auto !important;box-sizing:content-box !important;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace !important;font-weight:normal !important;font-style:normal !important;font-size:1em !important;min-height:inherit !important;min-height:auto !important;}
.syntaxhighlighter{width:100% !important;margin:1em 0 1em 0 !important;position:relative !important;overflow:auto !important;font-size:1em !important;}
.syntaxhighlighter.source{overflow:hidden !important;}
.syntaxhighlighter .bold{font-weight:bold !important;}
.syntaxhighlighter .italic{font-style:italic !important;}
.syntaxhighlighter .line{white-space:pre !important;}
.syntaxhighlighter table{width:100% !important;}
.syntaxhighlighter table caption{text-align:left !important;padding:.5em 0 0.5em 1em !important;}
.syntaxhighlighter table td.code{width:100% !important;}
.syntaxhighlighter table td.code .container{position:relative !important;}
.syntaxhighlighter table td.code .container textarea{box-sizing:border-box !important;position:absolute !important;left:0 !important;top:0 !important;width:100% !important;height:100% !important;border:none !important;background:white !important;padding-left:1em !important;overflow:hidden !important;white-space:pre !important;}
.syntaxhighlighter table td.gutter .line{text-align:right !important;padding:0 0.5em 0 1em !important;}
.syntaxhighlighter table td.code .line{padding:0 1em !important;}
.syntaxhighlighter.nogutter td.code .container textarea,.syntaxhighlighter.nogutter td.code .line{padding-left:0em !important;}
.syntaxhighlighter.show{display:block !important;}
.syntaxhighlighter.collapsed table{display:none !important;}
.syntaxhighlighter.collapsed .toolbar{padding:0.1em 0.8em 0em 0.8em !important;font-size:1em !important;position:static !important;width:auto !important;height:auto !important;}
.syntaxhighlighter.collapsed .toolbar span{display:inline !important;margin-right:1em !important;}
.syntaxhighlighter.collapsed .toolbar span a{padding:0 !important;display:none !important;}
.syntaxhighlighter.collapsed .toolbar span a.expandSource{display:inline !important;}
.syntaxhighlighter .toolbar{position:absolute !important;right:1px !important;top:1px !important;width:11px !important;height:11px !important;font-size:10px !important;z-index:10 !important;}
.syntaxhighlighter .toolbar span.title{display:inline !important;}
.syntaxhighlighter .toolbar a{display:block !important;text-align:center !important;text-decoration:none !important;padding-top:1px !important;}
.syntaxhighlighter .toolbar a.expandSource{display:none !important;}
.syntaxhighlighter.ie{font-size:.9em !important;padding:1px 0 1px 0 !important;}
.syntaxhighlighter.ie .toolbar{line-height:8px !important;}
.syntaxhighlighter.ie .toolbar a{padding-top:0px !important;}
.syntaxhighlighter.printing .line.alt1 .content,.syntaxhighlighter.printing .line.alt2 .content,.syntaxhighlighter.printing .line.highlighted .number,.syntaxhighlighter.printing .line.highlighted.alt1 .content,.syntaxhighlighter.printing .line.highlighted.alt2 .content{background:none !important;}
.syntaxhighlighter.printing .line .number{color:#bbbbbb !important;}
.syntaxhighlighter.printing .line .content{color:black !important;}
.syntaxhighlighter.printing .toolbar{display:none !important;}
.syntaxhighlighter.printing a{text-decoration:none !important;}
.syntaxhighlighter.printing .plain,.syntaxhighlighter.printing .plain a{color:black !important;}
.syntaxhighlighter.printing .comments,.syntaxhighlighter.printing .comments a{color:#008200 !important;}
.syntaxhighlighter.printing .string,.syntaxhighlighter.printing .string a{color:blue !important;}
.syntaxhighlighter.printing .keyword{color:#006699 !important;font-weight:bold !important;}
.syntaxhighlighter.printing .preprocessor{color:gray !important;}
.syntaxhighlighter.printing .variable{color:#aa7700 !important;}
.syntaxhighlighter.printing .value{color:#009900 !important;}
.syntaxhighlighter.printing .functions{color:#ff1493 !important;}
.syntaxhighlighter.printing .constants{color:#0066cc !important;}
.syntaxhighlighter.printing .script{font-weight:bold !important;}
.syntaxhighlighter.printing .color1,.syntaxhighlighter.printing .color1 a{color:gray !important;}
.syntaxhighlighter.printing .color2,.syntaxhighlighter.printing .color2 a{color:#ff1493 !important;}
.syntaxhighlighter.printing .color3,.syntaxhighlighter.printing .color3 a{color:red !important;}
.syntaxhighlighter.printing .break,.syntaxhighlighter.printing .break a{color:black !important;}
.syntaxhighlighter{background-color:#0f192a !important;}
.syntaxhighlighter .line.alt1{background-color:#0f192a !important;}
.syntaxhighlighter .line.alt2{background-color:#0f192a !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#253e5a !important;}
.syntaxhighlighter .line.highlighted.number{color:#38566f !important;}
.syntaxhighlighter table caption{color:#d1edff !important;}
.syntaxhighlighter .gutter{color:#afafaf !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #435a5f !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#435a5f !important;color:#0f192a !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#428bdd !important;background:black !important;border:1px solid #435a5f !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#428bdd !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#1dc116 !important;}
.syntaxhighlighter .toolbar{color:#d1edff !important;background:#435a5f !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:#d1edff !important;}
.syntaxhighlighter .toolbar a:hover{color:#8aa6c1 !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:#d1edff !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#428bdd !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#1dc116 !important;}
.syntaxhighlighter .keyword{color:#b43d3d !important;}
.syntaxhighlighter .preprocessor{color:#8aa6c1 !important;}
.syntaxhighlighter .variable{color:#ffaa3e !important;}
.syntaxhighlighter .value{color:#f7e741 !important;}
.syntaxhighlighter .functions{color:#ffaa3e !important;}
.syntaxhighlighter .constants{color:#e0e8ff !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#b43d3d !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#f8bb00 !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:white !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#ffaa3e !important;}

View File

@ -0,0 +1,76 @@
.syntaxhighlighter a,.syntaxhighlighter div,.syntaxhighlighter code,.syntaxhighlighter table,.syntaxhighlighter table td,.syntaxhighlighter table tr,.syntaxhighlighter table tbody,.syntaxhighlighter table thead,.syntaxhighlighter table caption,.syntaxhighlighter textarea{-moz-border-radius:0 0 0 0 !important;-webkit-border-radius:0 0 0 0 !important;background:none !important;border:0 !important;bottom:auto !important;float:none !important;height:auto !important;left:auto !important;line-height:1.1em !important;margin:0 !important;outline:0 !important;overflow:visible !important;padding:0 !important;position:static !important;right:auto !important;text-align:left !important;top:auto !important;vertical-align:baseline !important;width:auto !important;box-sizing:content-box !important;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace !important;font-weight:normal !important;font-style:normal !important;font-size:1em !important;min-height:inherit !important;min-height:auto !important;}
.syntaxhighlighter{width:100% !important;margin:1em 0 1em 0 !important;position:relative !important;overflow:auto !important;font-size:1em !important;}
.syntaxhighlighter.source{overflow:hidden !important;}
.syntaxhighlighter .bold{font-weight:bold !important;}
.syntaxhighlighter .italic{font-style:italic !important;}
.syntaxhighlighter .line{white-space:pre !important;}
.syntaxhighlighter table{width:100% !important;}
.syntaxhighlighter table caption{text-align:left !important;padding:.5em 0 0.5em 1em !important;}
.syntaxhighlighter table td.code{width:100% !important;}
.syntaxhighlighter table td.code .container{position:relative !important;}
.syntaxhighlighter table td.code .container textarea{box-sizing:border-box !important;position:absolute !important;left:0 !important;top:0 !important;width:100% !important;height:100% !important;border:none !important;background:white !important;padding-left:1em !important;overflow:hidden !important;white-space:pre !important;}
.syntaxhighlighter table td.gutter .line{text-align:right !important;padding:0 0.5em 0 1em !important;}
.syntaxhighlighter table td.code .line{padding:0 1em !important;}
.syntaxhighlighter.nogutter td.code .container textarea,.syntaxhighlighter.nogutter td.code .line{padding-left:0em !important;}
.syntaxhighlighter.show{display:block !important;}
.syntaxhighlighter.collapsed table{display:none !important;}
.syntaxhighlighter.collapsed .toolbar{padding:0.1em 0.8em 0em 0.8em !important;font-size:1em !important;position:static !important;width:auto !important;height:auto !important;}
.syntaxhighlighter.collapsed .toolbar span{display:inline !important;margin-right:1em !important;}
.syntaxhighlighter.collapsed .toolbar span a{padding:0 !important;display:none !important;}
.syntaxhighlighter.collapsed .toolbar span a.expandSource{display:inline !important;}
.syntaxhighlighter .toolbar{position:absolute !important;right:1px !important;top:1px !important;width:11px !important;height:11px !important;font-size:10px !important;z-index:10 !important;}
.syntaxhighlighter .toolbar span.title{display:inline !important;}
.syntaxhighlighter .toolbar a{display:block !important;text-align:center !important;text-decoration:none !important;padding-top:1px !important;}
.syntaxhighlighter .toolbar a.expandSource{display:none !important;}
.syntaxhighlighter.ie{font-size:.9em !important;padding:1px 0 1px 0 !important;}
.syntaxhighlighter.ie .toolbar{line-height:8px !important;}
.syntaxhighlighter.ie .toolbar a{padding-top:0px !important;}
.syntaxhighlighter.printing .line.alt1 .content,.syntaxhighlighter.printing .line.alt2 .content,.syntaxhighlighter.printing .line.highlighted .number,.syntaxhighlighter.printing .line.highlighted.alt1 .content,.syntaxhighlighter.printing .line.highlighted.alt2 .content{background:none !important;}
.syntaxhighlighter.printing .line .number{color:#bbbbbb !important;}
.syntaxhighlighter.printing .line .content{color:black !important;}
.syntaxhighlighter.printing .toolbar{display:none !important;}
.syntaxhighlighter.printing a{text-decoration:none !important;}
.syntaxhighlighter.printing .plain,.syntaxhighlighter.printing .plain a{color:black !important;}
.syntaxhighlighter.printing .comments,.syntaxhighlighter.printing .comments a{color:#008200 !important;}
.syntaxhighlighter.printing .string,.syntaxhighlighter.printing .string a{color:blue !important;}
.syntaxhighlighter.printing .keyword{color:#006699 !important;font-weight:bold !important;}
.syntaxhighlighter.printing .preprocessor{color:gray !important;}
.syntaxhighlighter.printing .variable{color:#aa7700 !important;}
.syntaxhighlighter.printing .value{color:#009900 !important;}
.syntaxhighlighter.printing .functions{color:#ff1493 !important;}
.syntaxhighlighter.printing .constants{color:#0066cc !important;}
.syntaxhighlighter.printing .script{font-weight:bold !important;}
.syntaxhighlighter.printing .color1,.syntaxhighlighter.printing .color1 a{color:gray !important;}
.syntaxhighlighter.printing .color2,.syntaxhighlighter.printing .color2 a{color:#ff1493 !important;}
.syntaxhighlighter.printing .color3,.syntaxhighlighter.printing .color3 a{color:red !important;}
.syntaxhighlighter.printing .break,.syntaxhighlighter.printing .break a{color:black !important;}
.syntaxhighlighter{background-color:#1b2426 !important;}
.syntaxhighlighter .line.alt1{background-color:#1b2426 !important;}
.syntaxhighlighter .line.alt2{background-color:#1b2426 !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#323e41 !important;}
.syntaxhighlighter .line.highlighted.number{color:#b9bdb6 !important;}
.syntaxhighlighter table caption{color:#b9bdb6 !important;}
.syntaxhighlighter .gutter{color:#afafaf !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #435a5f !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#435a5f !important;color:#1b2426 !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#5ba1cf !important;background:black !important;border:1px solid #435a5f !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#5ba1cf !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#5ce638 !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#435a5f !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:#e0e8ff !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:#b9bdb6 !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#878a85 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#5ce638 !important;}
.syntaxhighlighter .keyword{color:#5ba1cf !important;}
.syntaxhighlighter .preprocessor{color:#435a5f !important;}
.syntaxhighlighter .variable{color:#ffaa3e !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#ffaa3e !important;}
.syntaxhighlighter .constants{color:#e0e8ff !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#5ba1cf !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#e0e8ff !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:white !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#ffaa3e !important;}

View File

@ -0,0 +1,21 @@
.syntaxhighlighter.applescript{background:white;font-size:1em;color:black;}
.syntaxhighlighter.applescript div,.syntaxhighlighter.applescript code{font:1em/1.25 Verdana,sans-serif !important;}
.syntaxhighlighter.applescript .code .line{overflow:hidden !important;}
.syntaxhighlighter.applescript .code .line.highlighted{background:#b5d5ff !important;}
.syntaxhighlighter.applescript .color1{color:#000000 !important;}
.syntaxhighlighter.applescript .color2{color:#000000 !important;}
.syntaxhighlighter.applescript .color3{color:#000000 !important;font-weight:bold !important;}
.syntaxhighlighter.applescript .keyword{color:#000000 !important;font-weight:bold !important;}
.syntaxhighlighter.applescript .color4{color:#0000ff !important;font-style:italic !important;}
.syntaxhighlighter.applescript .comments{color:#4c4d4d !important;}
.syntaxhighlighter.applescript .plain{color:#408000 !important;}
.syntaxhighlighter.applescript .string{color:#000000 !important;}
.syntaxhighlighter.applescript .commandNames{color:#0000ff !important;font-weight:bold !important;}
.syntaxhighlighter.applescript .parameterNames{color:#0000ff !important;}
.syntaxhighlighter.applescript .classes{color:#0000ff !important;font-style:italic !important;}
.syntaxhighlighter.applescript .properties{color:#6c04d4 !important;}
.syntaxhighlighter.applescript .enumeratedValues{color:#4a1e7f !important;}
.syntaxhighlighter.applescript .additionCommandNames{color:#0016b0 !important;font-weight:bold !important;}
.syntaxhighlighter.applescript .additionParameterNames{color:#0016b0 !important;}
.syntaxhighlighter.applescript .additionClasses{color:#0016b0 !important;font-style:italic !important;}
.syntaxhighlighter.applescript .spaces{display:inline-block;height:0 !important;font-size:1.75em !important;line-height:0 !important;}

View File

@ -0,0 +1,31 @@
.syntaxhighlighter{background-color:white !important;}
.syntaxhighlighter .line.alt1{background-color:white !important;}
.syntaxhighlighter .line.alt2{background-color:white !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#e0e0e0 !important;}
.syntaxhighlighter .line.highlighted.number{color:black !important;}
.syntaxhighlighter table caption{color:black !important;}
.syntaxhighlighter .gutter{color:#afafaf !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #6ce26c !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#6ce26c !important;color:white !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:blue !important;background:white !important;border:1px solid #6ce26c !important;}
.syntaxhighlighter.collapsed .toolbar a{color:blue !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:red !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#6ce26c !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:black !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:black !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#008200 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:blue !important;}
.syntaxhighlighter .keyword{color:#006699 !important;}
.syntaxhighlighter .preprocessor{color:gray !important;}
.syntaxhighlighter .variable{color:#aa7700 !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#ff1493 !important;}
.syntaxhighlighter .constants{color:#0066cc !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#006699 !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:gray !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#ff1493 !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:red !important;}
.syntaxhighlighter .keyword{font-weight:bold !important;}

View File

@ -0,0 +1,32 @@
.syntaxhighlighter{background-color:#0a2b1d !important;}
.syntaxhighlighter .line.alt1{background-color:#0a2b1d !important;}
.syntaxhighlighter .line.alt2{background-color:#0a2b1d !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#233729 !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:#f8f8f8 !important;}
.syntaxhighlighter .gutter{color:#497958 !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #41a83e !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#41a83e !important;color:#0a2b1d !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#96dd3b !important;background:black !important;border:1px solid #41a83e !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#96dd3b !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:white !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#41a83e !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:#ffe862 !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:#f8f8f8 !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#336442 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#9df39f !important;}
.syntaxhighlighter .keyword{color:#96dd3b !important;}
.syntaxhighlighter .preprocessor{color:#91bb9e !important;}
.syntaxhighlighter .variable{color:#ffaa3e !important;}
.syntaxhighlighter .value{color:#f7e741 !important;}
.syntaxhighlighter .functions{color:#ffaa3e !important;}
.syntaxhighlighter .constants{color:#e0e8ff !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#96dd3b !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#eb939a !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#91bb9e !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#edef7d !important;}
.syntaxhighlighter .comments{font-style:italic !important;}
.syntaxhighlighter .keyword{font-weight:bold !important;}

View File

@ -0,0 +1,34 @@
.syntaxhighlighter{background-color:white !important;}
.syntaxhighlighter .line.alt1{background-color:white !important;}
.syntaxhighlighter .line.alt2{background-color:white !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#c3defe !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:black !important;}
.syntaxhighlighter .gutter{color:#787878 !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #d4d0c8 !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#d4d0c8 !important;color:white !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#3f5fbf !important;background:white !important;border:1px solid #d4d0c8 !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#3f5fbf !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#aa7700 !important;}
.syntaxhighlighter .toolbar{color:#a0a0a0 !important;background:#d4d0c8 !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:#a0a0a0 !important;}
.syntaxhighlighter .toolbar a:hover{color:red !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:black !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#3f5fbf !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#2a00ff !important;}
.syntaxhighlighter .keyword{color:#7f0055 !important;}
.syntaxhighlighter .preprocessor{color:#646464 !important;}
.syntaxhighlighter .variable{color:#aa7700 !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#ff1493 !important;}
.syntaxhighlighter .constants{color:#0066cc !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#7f0055 !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:gray !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#ff1493 !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:red !important;}
.syntaxhighlighter .keyword{font-weight:bold !important;}
.syntaxhighlighter .xml .keyword{color:#3f7f7f !important;font-weight:normal !important;}
.syntaxhighlighter .xml .color1,.syntaxhighlighter .xml .color1 a{color:#7f007f !important;}
.syntaxhighlighter .xml .string{font-style:italic !important;color:#2a00ff !important;}

View File

@ -0,0 +1,30 @@
.syntaxhighlighter{background-color:black !important;}
.syntaxhighlighter .line.alt1{background-color:black !important;}
.syntaxhighlighter .line.alt2{background-color:black !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#2a3133 !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:#d3d3d3 !important;}
.syntaxhighlighter .gutter{color:#d3d3d3 !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #990000 !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#990000 !important;color:black !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#ebdb8d !important;background:black !important;border:1px solid #990000 !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#ebdb8d !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#ff7d27 !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#990000 !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:#9ccff4 !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:#d3d3d3 !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#ff7d27 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#ff9e7b !important;}
.syntaxhighlighter .keyword{color:aqua !important;}
.syntaxhighlighter .preprocessor{color:#aec4de !important;}
.syntaxhighlighter .variable{color:#ffaa3e !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#81cef9 !important;}
.syntaxhighlighter .constants{color:#ff9e7b !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:aqua !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#ebdb8d !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#ff7d27 !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#aec4de !important;}

View File

@ -0,0 +1,31 @@
.syntaxhighlighter{background-color:#121212 !important;}
.syntaxhighlighter .line.alt1{background-color:#121212 !important;}
.syntaxhighlighter .line.alt2{background-color:#121212 !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#2c2c29 !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:white !important;}
.syntaxhighlighter .gutter{color:#afafaf !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #3185b9 !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#3185b9 !important;color:#121212 !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#3185b9 !important;background:black !important;border:1px solid #3185b9 !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#3185b9 !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#d01d33 !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#3185b9 !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:#96daff !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:white !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#696854 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#e3e658 !important;}
.syntaxhighlighter .keyword{color:#d01d33 !important;}
.syntaxhighlighter .preprocessor{color:#435a5f !important;}
.syntaxhighlighter .variable{color:#898989 !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#aaaaaa !important;}
.syntaxhighlighter .constants{color:#96daff !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#d01d33 !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#ffc074 !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#4a8cdb !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#96daff !important;}
.syntaxhighlighter .functions{font-weight:bold !important;}

View File

@ -0,0 +1,30 @@
.syntaxhighlighter{background-color:#222222 !important;}
.syntaxhighlighter .line.alt1{background-color:#222222 !important;}
.syntaxhighlighter .line.alt2{background-color:#222222 !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#253e5a !important;}
.syntaxhighlighter .line.highlighted.number{color:white !important;}
.syntaxhighlighter table caption{color:lime !important;}
.syntaxhighlighter .gutter{color:#38566f !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #435a5f !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#435a5f !important;color:#222222 !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#428bdd !important;background:black !important;border:1px solid #435a5f !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#428bdd !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:lime !important;}
.syntaxhighlighter .toolbar{color:#aaaaff !important;background:#435a5f !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:#aaaaff !important;}
.syntaxhighlighter .toolbar a:hover{color:#9ccff4 !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:lime !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#428bdd !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:lime !important;}
.syntaxhighlighter .keyword{color:#aaaaff !important;}
.syntaxhighlighter .preprocessor{color:#8aa6c1 !important;}
.syntaxhighlighter .variable{color:aqua !important;}
.syntaxhighlighter .value{color:#f7e741 !important;}
.syntaxhighlighter .functions{color:#ff8000 !important;}
.syntaxhighlighter .constants{color:yellow !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#aaaaff !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:red !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:yellow !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#ffaa3e !important;}

View File

@ -0,0 +1,30 @@
.syntaxhighlighter{background-color:#0f192a !important;}
.syntaxhighlighter .line.alt1{background-color:#0f192a !important;}
.syntaxhighlighter .line.alt2{background-color:#0f192a !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#253e5a !important;}
.syntaxhighlighter .line.highlighted.number{color:#38566f !important;}
.syntaxhighlighter table caption{color:#d1edff !important;}
.syntaxhighlighter .gutter{color:#afafaf !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #435a5f !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#435a5f !important;color:#0f192a !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#428bdd !important;background:black !important;border:1px solid #435a5f !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#428bdd !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#1dc116 !important;}
.syntaxhighlighter .toolbar{color:#d1edff !important;background:#435a5f !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:#d1edff !important;}
.syntaxhighlighter .toolbar a:hover{color:#8aa6c1 !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:#d1edff !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#428bdd !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#1dc116 !important;}
.syntaxhighlighter .keyword{color:#b43d3d !important;}
.syntaxhighlighter .preprocessor{color:#8aa6c1 !important;}
.syntaxhighlighter .variable{color:#ffaa3e !important;}
.syntaxhighlighter .value{color:#f7e741 !important;}
.syntaxhighlighter .functions{color:#ffaa3e !important;}
.syntaxhighlighter .constants{color:#e0e8ff !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#b43d3d !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#f8bb00 !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:white !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#ffaa3e !important;}

View File

@ -0,0 +1,30 @@
.syntaxhighlighter{background-color:#1b2426 !important;}
.syntaxhighlighter .line.alt1{background-color:#1b2426 !important;}
.syntaxhighlighter .line.alt2{background-color:#1b2426 !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#323e41 !important;}
.syntaxhighlighter .line.highlighted.number{color:#b9bdb6 !important;}
.syntaxhighlighter table caption{color:#b9bdb6 !important;}
.syntaxhighlighter .gutter{color:#afafaf !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #435a5f !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#435a5f !important;color:#1b2426 !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:#5ba1cf !important;background:black !important;border:1px solid #435a5f !important;}
.syntaxhighlighter.collapsed .toolbar a{color:#5ba1cf !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:#5ce638 !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#435a5f !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:#e0e8ff !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:#b9bdb6 !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#878a85 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#5ce638 !important;}
.syntaxhighlighter .keyword{color:#5ba1cf !important;}
.syntaxhighlighter .preprocessor{color:#435a5f !important;}
.syntaxhighlighter .variable{color:#ffaa3e !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#ffaa3e !important;}
.syntaxhighlighter .constants{color:#e0e8ff !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#5ba1cf !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:#e0e8ff !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:white !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:#ffaa3e !important;}

View File

@ -0,0 +1,31 @@
.syntaxhighlighter{background-color:white !important;}
.syntaxhighlighter .line.alt1{background-color:white !important;}
.syntaxhighlighter .line.alt2{background-color:white !important;}
.syntaxhighlighter .line.highlighted.alt1,.syntaxhighlighter .line.highlighted.alt2{background-color:#e0e0e0 !important;}
.syntaxhighlighter .line.highlighted.number{color:black !important;}
.syntaxhighlighter table caption{color:black !important;}
.syntaxhighlighter .gutter{color:#afafaf !important;}
.syntaxhighlighter .gutter .line{border-right:3px solid #6ce26c !important;}
.syntaxhighlighter .gutter .line.highlighted{background-color:#6ce26c !important;color:white !important;}
.syntaxhighlighter.printing .line .content{border:none !important;}
.syntaxhighlighter.collapsed{overflow:visible !important;}
.syntaxhighlighter.collapsed .toolbar{color:blue !important;background:white !important;border:1px solid #6ce26c !important;}
.syntaxhighlighter.collapsed .toolbar a{color:blue !important;}
.syntaxhighlighter.collapsed .toolbar a:hover{color:red !important;}
.syntaxhighlighter .toolbar{color:white !important;background:#6ce26c !important;border:none !important;}
.syntaxhighlighter .toolbar a{color:white !important;}
.syntaxhighlighter .toolbar a:hover{color:black !important;}
.syntaxhighlighter .plain,.syntaxhighlighter .plain a{color:black !important;}
.syntaxhighlighter .comments,.syntaxhighlighter .comments a{color:#008200 !important;}
.syntaxhighlighter .string,.syntaxhighlighter .string a{color:#d11010 !important;}
.syntaxhighlighter .keyword{color:#006699 !important;}
.syntaxhighlighter .preprocessor{color:gray !important;}
.syntaxhighlighter .variable{color:#aa7700 !important;}
.syntaxhighlighter .value{color:#009900 !important;}
.syntaxhighlighter .functions{color:#ff1493 !important;}
.syntaxhighlighter .constants{color:#0066cc !important;}
.syntaxhighlighter .script{font-weight:bold !important;color:#006699 !important;background-color:none !important;}
.syntaxhighlighter .color1,.syntaxhighlighter .color1 a{color:gray !important;}
.syntaxhighlighter .color2,.syntaxhighlighter .color2 a{color:#ff1493 !important;}
.syntaxhighlighter .color3,.syntaxhighlighter .color3 a{color:red !important;}
.syntaxhighlighter .keyword{font-weight:bold !important;}

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

148
extras/EasyPeasyICS.php Normal file
View File

@ -0,0 +1,148 @@
<?php
/**
* EasyPeasyICS Simple ICS/vCal data generator.
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
* @author Manuel Reinhard <manu@sprain.ch>
*
* Built with inspiration from
* http://stackoverflow.com/questions/1463480/how-can-i-use-php-to-dynamically-publish-an-ical-file-to-be-read-by-google-calend/1464355#1464355
* History:
* 2010/12/17 - Manuel Reinhard - when it all started
* 2014 PHPMailer project becomes maintainer
*/
/**
* Class EasyPeasyICS.
* Simple ICS data generator
* @package phpmailer
* @subpackage easypeasyics
*/
class EasyPeasyICS
{
/**
* The name of the calendar
* @var string
*/
protected $calendarName;
/**
* The array of events to add to this calendar
* @var array
*/
protected $events = array();
/**
* Constructor
* @param string $calendarName
*/
public function __construct($calendarName = "")
{
$this->calendarName = $calendarName;
}
/**
* Add an event to this calendar.
* @param string $start The start date and time as a unix timestamp
* @param string $end The end date and time as a unix timestamp
* @param string $summary A summary or title for the event
* @param string $description A description of the event
* @param string $url A URL for the event
* @param string $uid A unique identifier for the event - generated automatically if not provided
* @return array An array of event details, including any generated UID
*/
public function addEvent($start, $end, $summary = '', $description = '', $url = '', $uid = '')
{
if (empty($uid)) {
$uid = md5(uniqid(mt_rand(), true)) . '@EasyPeasyICS';
}
$event = array(
'start' => gmdate('Ymd', $start) . 'T' . gmdate('His', $start) . 'Z',
'end' => gmdate('Ymd', $end) . 'T' . gmdate('His', $end) . 'Z',
'summary' => $summary,
'description' => $description,
'url' => $url,
'uid' => $uid
);
$this->events[] = $event;
return $event;
}
/**
* @return array Get the array of events.
*/
public function getEvents()
{
return $this->events;
}
/**
* Clear all events.
*/
public function clearEvents()
{
$this->events = array();
}
/**
* Get the name of the calendar.
* @return string
*/
public function getName()
{
return $this->calendarName;
}
/**
* Set the name of the calendar.
* @param $name
*/
public function setName($name)
{
$this->calendarName = $name;
}
/**
* Render and optionally output a vcal string.
* @param bool $output Whether to output the calendar data directly (the default).
* @return string The complete rendered vlal
*/
public function render($output = true)
{
//Add header
$ics = 'BEGIN:VCALENDAR
METHOD:PUBLISH
VERSION:2.0
X-WR-CALNAME:' . $this->calendarName . '
PRODID:-//hacksw/handcal//NONSGML v1.0//EN';
//Add events
foreach ($this->events as $event) {
$ics .= '
BEGIN:VEVENT
UID:' . $event['uid'] . '
DTSTAMP:' . gmdate('Ymd') . 'T' . gmdate('His') . 'Z
DTSTART:' . $event['start'] . '
DTEND:' . $event['end'] . '
SUMMARY:' . str_replace("\n", "\\n", $event['summary']) . '
DESCRIPTION:' . str_replace("\n", "\\n", $event['description']) . '
URL;VALUE=URI:' . $event['url'] . '
END:VEVENT';
}
//Add footer
$ics .= '
END:VCALENDAR';
if ($output) {
//Output
$filename = $this->calendarName;
//Filename needs quoting if it contains spaces
if (strpos($filename, ' ') !== false) {
$filename = '"'.$filename.'"';
}
header('Content-type: text/calendar; charset=utf-8');
header('Content-Disposition: inline; filename=' . $filename . '.ics');
echo $ics;
}
return $ics;
}
}

Some files were not shown because too many files have changed in this diff Show More