Provides a clean and simple way to configure the WordPress-bundled PHPMailer library, allowing you to quickly get started sending mail through a local or cloud based service of your choice

Overview

WP PHPMailer

CircleCI Packagist Version WordPress Plugin Rating PHP from Packagist WordPress Plugin: Tested WP Version Packagist Downloads WordPress Plugin Downloads GitHub License Hire Itineris Twitter Follow @itineris_ltd Twitter Follow @TangRufus

WP PHPMailer provides a clean and simple way to configure the WordPress-bundled PHPMailer library, allowing you to quickly get started sending mail through a local or cloud based service of your choice.

Goal

Although WordPress bundles the PHPMailer library which allow you sending mail through a local or cloud based service of your choice, different cloud based service requires different configuration. Worse still, most services provide multiple ways for setting them up. For instance: which SendGrid SMTP port provides the highest level of security, 25, 587, 2525 or 465?

WP PHPMailer uses the WordPress-bundled PHPMailer library:

  • so you offload the responsibility of updating bundled libraries from plugin authors to WordPress core team and contributors
    • at the time of writing, the official SendGrid plugin's vendor folder hasn't been updated in 2.5 years

WP PHPMailer believes in convention over configuration, we pick the best configuration for each service:

  • so you don't waste time going through the documents
  • so you don't have to figure out which port and protocol to use
  • so you don't miss any security configuration, e.g: SMTPAuth, SMTPSecure, etc
  • so you only have to provide minimum information
    • take SendGrid for example, only SendGrid API key (with "Mail Send" permission only) is required

WP PHPMailer believes a plugin should "do one thing and do it well":

Usage

Pick one driver and define its required constants in wp-config.php.

Mailhog

define('WP_PHPMAILER_DRIVER', 'mailhog');

Mailtrap

define('WP_PHPMAILER_DRIVER', 'mailtrap');

define('MAILTRAP_USERNAME', 'your-mailtrap-username');
define('MAILTRAP_PASSWORD', 'your-mailtrap-password');

SendGrid

define('WP_PHPMAILER_DRIVER', 'sendgrid');

define('SENDGRID_API_KEY', 'your-sendgrid-api-key');

// Optional. Useful if you have email authentication configurated.
define('SENDGRID_FROM_ADDRESS', '[email protected]');
define('SENDGRID_FROM_NAME', 'John Doe');
define('SENDGRID_FROM_AUTO', true);

Custom Driver

Step 1. Define Your Driver

class MyCustomDriver implements DriverInterface
{
    public static function makeConfig(ConstantRepository $constantRepo): ConfigInterface
    {
        $config = new Config();

        $config->set('auth', true);
        $config->set('host', 'smtp.custom.test');
        $config->set('port', 587);
        $config->set('protocol', 'tls');

        $config->set(
            'username',
            $constantRepo->getRequired('MY_CUSTOM_USERNAME')
        );

        $config->set(
            'password',
            $constantRepo->getRequired('MY_CUSTOM_PASSWORD')
        );

        $config->set(
            'fromAddress',
            $constantRepo->get('MY_CUSTOM_FROM_ADDRESS')
        );
        $config->set(
            'fromName',
            $constantRepo->get('MY_CUSTOM_FROM_NAME')
        );
        $config->set(
            'fromAuto',
            $constantRepo->get('MY_CUSTOM_FROM_AUTO')
        );

        return $config;
    }
}

Step 2. Register Your Driver

add_filter('wp_phpmailer_drivers', function (array $drivers): array {
    $drivers['my-custom-driver'] = MyCustomDriver::class;

    return $drivers;
});

Step 3. Define Constants

// wp-config.php

define('WP_PHPMAILER_DRIVER', 'my-custom-driver');

define('MY_CUSTOM_USERNAME', 'xxx');
define('MY_CUSTOM_PASSWORD', 'xxx');

// Optional.
define('MY_CUSTOM_FROM_ADDRESS', 'xxx');
define('MY_CUSTOM_FROM_NAME', 'xxx');
define('MY_CUSTOM_FROM_AUTO', true);

Filters

wp_phpmailer_driver

$driver = (string) apply_filters('wp_phpmailer_driver', string $wpPhpmailerDriver))

Filters the WP_PHPMAILER_DRIVER constant.

Parameters:

  • $wpPhpmailerDriver
    • (string) the value of WP_PHPMAILER_DRIVER constant

wp_phpmailer_drivers

$drivers = (array) apply_filters('wp_phpmailer_drivers', array $drivers)

Filters the available drivers array.

Parameters:

  • $drivers
    • (array) the available drivers array

Example:

add_filter('wp_phpmailer_drivers', function (array $drivers): array {
   $drivers['my-custom-driver'] = MyCustomDriver::class;

   return $drivers;
});

wp_phpmailer_config_mappings

$mappings = (array) apply_filters('wp_phpmailer_config_mappings', array $mapings)

Filters the whitelisted PHPMailer configuration (property names) array. 'fromAddress', 'fromName', 'fromAuto' are special. Do not add them in mappings!

Parameters:

  • $mapings
    • (array) the whitelisted PHPMailer configuration (property names)

Example:

add_filter('wp_phpmailer_config_mappings', function (array $mappings): array {
    $mappings['xxx'] = 'yyy';

    return $mappings;
});

// The above filter results in:
add_action( 'phpmailer_init', function (PHPMailer $phpmailer) {
    // $this->config comes from `DriverInterface::makeConfig`.
    $phpmailer->xxx = $this->config->get('yyy');
});

Minimum Requirements

  • PHP v7.2
  • WordPress v5.5

Installation

Composer (Recommended)

composer require itinerisltd/wp-phpmailer

wordpress.org (WP CLI)

wp plugin install wp-phpmailer

wordpress.org

Download from https://wordpress.org/plugins/wp-phpmailer Then, install wp-phpmailer.zip as usual.

Build from Source (Not Recommended)

# Make sure you use the same PHP version as remote servers.
# Building inside docker images is recommended.
php -v

# Checkout source code
git clone https://github.com/ItinerisLtd/wp-phpmailer.git
cd wp-phpmailer
git checkout <the-tag-or-the-branch-or-the-commit>

# Build the zip file
composer release:build

Then, install release/wp-phpmailer.zip as usual.

Common Errors

NotFoundException - Driver 'xxx' not found, acceptable values are: aaa, bbb, ccc

Reason: Driver is not found or not defined.

Troubleshooting:

  • Ensure PHP constant is WP_PHPMAILER_DRIVER is correct
  • Ensure filter wp_phpmailer_driver is functioning correctly

FAQ

Where is the settings page?

There is no settings page.

All configurations are done by PHP constants and WordPress filters.

Will you add a settings page?

No.

We have seen countless vulnerabilities related to user inputs. Mail settings don't change often and should be configured by a developer. Therefore, WP PHPMailer decided to use PHP constants instead of storing options in WordPress database.

However, if you must, you can use filters to override this behavior.

What PHPMailer version bundled?

This plugin reuse the PHPMailer class bundled with WordPress core.

Thus, you have to keep WordPress core up to date to receive security patches.

Is it a must to use SMTP?

No.

While you can make your own non-SMTP drivers, all default drivers are using SMTP. Pull requests are welcomed.

Will you add support for older PHP versions?

Never! This plugin will only work on actively supported PHP versions.

Don't use it on end of life or security fixes only PHP versions.

It looks awesome. Where can I find more goodies like this?

Where can I give reviews?

Thanks! Glad you like it. It's important to let my boss knows somebody is using this project. Please consider:

Testing

composer test
composer phpstan:analyse
composer style:check

Pull requests without tests will not be accepted!

Feedback

Please provide feedback! We want to make this library useful in as many projects as possible. Please submit an issue and point out what you do and don't like, or fork the project and make suggestions. No issue is too small.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

WP PHPMailer is a Itineris Limited project created by Tang Rufus.

Special thanks to Brandon whose WP SMTP inspired this project.

Full list of contributors can be found here.

License

WP PHPMailer is released under the MIT License.

Comments
  • Bump guzzlehttp/psr7 from 1.8.2 to 1.8.5

    Bump guzzlehttp/psr7 from 1.8.2 to 1.8.5

    Bumps guzzlehttp/psr7 from 1.8.2 to 1.8.5.

    Release notes

    Sourced from guzzlehttp/psr7's releases.

    1.8.5

    See change log for changes.

    1.8.4

    See change log for changes.

    1.8.3

    See change log for changes.

    Changelog

    Sourced from guzzlehttp/psr7's changelog.

    1.8.5 - 2022-03-20

    Fixed

    • Correct header value validation

    1.8.4 - 2022-03-20

    Fixed

    • Validate header values properly

    1.8.3 - 2021-10-05

    Fixed

    • Return null in caching stream size if remote size is null
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 4
  • Adds generic SMTP driver

    Adds generic SMTP driver

    This is such a useful and streight forward SMTP implementation. Thanks a lot for the package. However I stumpled over it again and wondered another time, why there is no simple SMTP driver one can use with any SMTP compatible service. So I added one for my own and I am sure that this will be useful for others, too.

    Thanks and kind regards,

    Philipp

    Closes #508

    opened by ouun 4
  • Bump itinerisltd/itineris-wp-coding-standards from 0.4.0 to 0.4.1

    Bump itinerisltd/itineris-wp-coding-standards from 0.4.0 to 0.4.1

    Bumps itinerisltd/itineris-wp-coding-standards from 0.4.0 to 0.4.1.

    Changelog

    Sourced from itinerisltd/itineris-wp-coding-standards's changelog.

    0.4.1 (2022-09-01)

    Full Changelog

    Merged pull requests:

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 2
  • Bump mockery/mockery from 1.3.4 to 1.3.5

    Bump mockery/mockery from 1.3.4 to 1.3.5

    Bumps mockery/mockery from 1.3.4 to 1.3.5.

    Release notes

    Sourced from mockery/mockery's releases.

    1.3.5

    • Fix auto-generated return values with union types #1143
    • Adds support for tentative types #1130
    • Fixes for PHP 8.1 Support (#1130 and #1140)
    Changelog

    Sourced from mockery/mockery's changelog.

    1.3.5 (2021-09-13)

    • Fix auto-generated return values with union types #1143
    • Adds support for tentative types #1130
    • Fixes for PHP 8.1 Support (#1130 and #1140)
    Commits
    • 472fa8c Adds a couple of notes
    • 553ad47 Merge pull request #1143 from GrahamCampbell/13-fix-union-return
    • b2b3b0e Fix auto-generated return values with union types
    • 6be9039 Merge pull request #1140 from GrahamCampbell/php81-fixes
    • 2bbc2b1 Update .gitattributes
    • 9ee64d6 More fixes for PHP 8.1 and setup CI again
    • 0a999ca Merge pull request #1130 from jrmajor/tentative-types
    • 3b543da Add support for tentative return types
    • f12df93 Skip Serializable test on PHP 8.1
    • cd96b3e Fix passing null to non-nullable parameter
    • See full diff in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 2
  • Bump symfony/finder from 4.4.13 to 4.4.14

    Bump symfony/finder from 4.4.13 to 4.4.14

    Bumps symfony/finder from 4.4.13 to 4.4.14.

    Release notes

    Sourced from symfony/finder's releases.

    v4.4.14

    Changelog (https://github.com/symfony/finder/compare/v4.4.13...v4.4.14)

    • no changes
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.

    If all status checks pass Dependabot will automatically merge this pull request during working hours.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot badge me will comment on this PR with code to add a "Dependabot enabled" badge to your readme

    Additionally, you can set the following in the .dependabot/config.yml file in this repo:

    • Update frequency
    • Automerge options (never/patch/minor, and dev/runtime dependencies)
    • Out-of-range updates (receive only lockfile updates, if desired)
    • Security updates (receive only security updates, if desired)
    dependencies 
    opened by dependabot-preview[bot] 2
  • Bump roots/wordpress from 5.4.2 to 5.5

    Bump roots/wordpress from 5.4.2 to 5.5

    Bumps roots/wordpress from 5.4.2 to 5.5.

    Commits
    • 537fd93 Tag 5.5
    • e9cf4f9 WordPress 5.5
    • abd91fb Help/About: Final adjustments to the 5.5 About page.
    • c5dca80 Post WordPress 5.5 RC 3 version bump.
    • 9c1800d WordPress 5.5 RC 3.
    • 5028fdb Options, Meta APIs: Update the docs around default metadata values.
    • f2656fe Bundled Themes: Bump theme versions ahead of WordPress 5.5.
    • fa8f759 Editor: update packages.
    • d5c3cd0 I18N: Fix typo in a screen reader text string on the About page.
    • d5b7889 I18N: Fix typo in a string in rest_validate_value_from_schema().
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.

    If all status checks pass Dependabot will automatically merge this pull request during working hours.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot badge me will comment on this PR with code to add a "Dependabot enabled" badge to your readme

    Additionally, you can set the following in the .dependabot/config.yml file in this repo:

    • Update frequency
    • Automerge options (never/patch/minor, and dev/runtime dependencies)
    • Out-of-range updates (receive only lockfile updates, if desired)
    • Security updates (receive only security updates, if desired)
    dependencies 
    opened by dependabot-preview[bot] 2
  • Bump wp-coding-standards/wpcs from 2.1.1 to 2.2.0

    Bump wp-coding-standards/wpcs from 2.1.1 to 2.2.0

    Bumps wp-coding-standards/wpcs from 2.1.1 to 2.2.0.

    Release notes

    Sourced from wp-coding-standards/wpcs's releases.

    2.2.0

    Note: The repository has moved. The new URL is https://github.com/WordPress/WordPress-Coding-Standards. The move does not affect the package name for Packagist. This remains the same: wp-coding-standards/wpcs.

    Added

    • New WordPress.DateTime.CurrentTimeTimestamp sniff to the WordPress-Core ruleset, which checks against the use of the WP native current_time() function to retrieve a timestamp as this won't be a real timestamp. Includes an auto-fixer.
    • New WordPress.DateTime.RestrictedFunctions sniff to the WordPress-Core ruleset, which checks for the use of certain date/time related functions. Initially this sniff forbids the use of the PHP native date_default_timezone_set() and date() functions.
    • New WordPress.PHP.DisallowShortTernary sniff to the WordPress-Core ruleset, which, as the name implies, disallows the use of short ternaries.
    • New WordPress.CodeAnalysis.EscapedNotTranslated sniff to the WordPress-Extra ruleset which will warn when a text string is escaped for output, but not being translated, while the arguments passed to the function call give the impression that translation is intended.
    • New WordPress.NamingConventions.ValidPostTypeSlug sniff to the WordPress-Extra ruleset which will examine calls to register_post_type() and throw errors when an invalid post type slug is used.
    • Generic.Arrays.DisallowShortArraySyntax to the WordPress-Core ruleset.
    • WordPress.NamingConventions.PrefixAllGlobals: the PHP prefix has been added to the prefix blacklist as it is reserved by PHP itself.
    • The wp_sanitize_redirect() function to the sanitizingFunctions list used by the WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput and WordPress.Security.EscapeOutput sniffs.
    • The sanitize_key() and the highlight_string() functions to the escapingFunctions list used by the WordPress.Security.EscapeOutput sniff.
    • The RECOVERY_MODE_COOKIE constant to the list of WP Core constants which may be defined by plugins and themes and therefore don't need to be prefixed (WordPress.NamingConventions.PrefixAllGlobals).
    • $content_width, $plugin, $mu_plugin and $network_plugin to the list of WP globals which is used by both the WordPress.Variables.GlobalVariables and the WordPress.NamingConventions.PrefixAllGlobals sniffs.
    • Sniff::is_short_list() utility method to determine whether a short array open/close token actually represents a PHP 7.1+ short list.
    • Sniff::find_list_open_close() utility method to find the opener and closer for list() constructs, including short lists.
    • Sniff::get_list_variables() utility method which will retrieve an array with the token pointers to the variables which are being assigned to in a list() construct. Includes support for short lists.
    • Sniff::is_function_deprecated() static utility method to determine whether a declared function has been marked as deprecated in the function DocBlock.
    • End-user documentation to the following existing sniffs: WordPress.Arrays.ArrayIndentation, WordPress.Arrays.ArrayKeySpacingRestrictions, WordPress.Arrays.MultipleStatementAlignment, WordPress.Classes.ClassInstantiation, WordPress.NamingConventions.ValidHookName, WordPress.PHP.IniSet, WordPress.Security.SafeRedirect, WordPress.WhiteSpace.CastStructureSpacing, WordPress.WhiteSpace.DisallowInlineTabs, WordPress.WhiteSpace.PrecisionAlignment, WordPress.WP.CronInterval, WordPress.WP.DeprecatedClasses, WordPress.WP.DeprecatedFunctions, WordPress.WP.DeprecatedParameters, WordPress.WP.DeprecatedParameterValues, WordPress.WP.EnqueuedResources, WordPress.WP.PostsPerPage. This documentation can be exposed via the PHP_CodeSniffer --generator=... command-line argument.

    Changed

    • The default value for minimum_supported_wp_version, as used by a number of sniffs detecting usage of deprecated WP features, has been updated to 5.0.
    • The WordPress.Arrays.ArrayKeySpacingRestrictions sniff has two new error codes: TooMuchSpaceBeforeKey and TooMuchSpaceAfterKey. Both auto-fixable. The sniff will now check that there is exactly one space on the inside of the square brackets around the array key for non-string, non-numeric array keys. Previously, it only checked that there was whitespace, not how much whitespace.
    • WordPress.Arrays.ArrayKeySpacingRestrictions: the fixers have been made more efficient and less fixer-conflict prone.
    • WordPress.NamingConventions.PrefixAllGlobals: plugin/theme prefixes should be at least three characters long. A new ShortPrefixPassed error has been added for when the prefix passed does not comply with this rule.
    • WordPress.WhiteSpace.CastStructureSpacing now allows for no whitespace before a cast when the cast is preceded by the spread ... operator. This pre-empts a fixer conflict for when the spacing around the spread operator will start to get checked.
    • The WordPress.WP.DeprecatedClasses sniff will now detect classes deprecated in WP 4.9 and WP 5.3.
    • The WordPress.WP.DeprecatedFunctions sniff will now detect functions deprecated in WP 5.3.
    • WordPress.NamingConventions.ValidHookName now has "cleaner" error messages and higher precision for the line on which an error is thrown.
    • WordPress.Security.EscapeOutput: if an error refers to array access via a variable, the array index key will now be included in the error message.
    • The processing of the WordPress ruleset by PHP_CodeSniffer will now be faster.
    • Various minor code tweaks and clean up.
    • Various minor documentation fixes.
    • Documentation: updated the repo URL in all relevant places.

    Deprecated

    • The WordPress.WP.TimezoneChange sniff. Use the WordPress.DateTime.RestrictedFunctions instead. The deprecated sniff will be removed in WPCS 3.0.0.

    Fixed

    • All sniffs in the WordPress.Arrays category will no longer treat short lists as if they were a short array.
    • The WordPress.NamingConventions.ValidFunctionName and the WordPress.NamingConventions.PrefixAllGlobals sniff will now ignore functions marked as @deprecated.
    • Both the WordPress.NamingConventions.PrefixAllGlobals sniff as well as the WordPress.WP.GlobalVariablesOverride sniff have been updated to recognize variables being declared via (long/short) list() constructs and handle them correctly.
    • Both the WordPress.NamingConventions.PrefixAllGlobals sniff as well as the WordPress.WP.GlobalVariablesOverride sniff will now take a limited list of WP global variables which are intended to be overwritten by plugins/themes into account. Initially this list contains the $content_width and the $wp_cockneyreplace variables.
    • WordPress.NamingConventions.ValidHookName: will no longer examine a string array access index key as if it were a part of the hook name.
    ... (truncated)
    Changelog

    Sourced from wp-coding-standards/wpcs's changelog.

    [2.2.0] - 2019-11-11

    Note: The repository has moved. The new URL is https://github.com/WordPress/WordPress-Coding-Standards. The move does not affect the package name for Packagist. This remains the same: wp-coding-standards/wpcs.

    Added

    • New WordPress.DateTime.CurrentTimeTimestamp sniff to the WordPress-Core ruleset, which checks against the use of the WP native current_time() function to retrieve a timestamp as this won't be a real timestamp. Includes an auto-fixer.
    • New WordPress.DateTime.RestrictedFunctions sniff to the WordPress-Core ruleset, which checks for the use of certain date/time related functions. Initially this sniff forbids the use of the PHP native date_default_timezone_set() and date() functions.
    • New WordPress.PHP.DisallowShortTernary sniff to the WordPress-Core ruleset, which, as the name implies, disallows the use of short ternaries.
    • New WordPress.CodeAnalysis.EscapedNotTranslated sniff to the WordPress-Extra ruleset which will warn when a text string is escaped for output, but not being translated, while the arguments passed to the function call give the impression that translation is intended.
    • New WordPress.NamingConventions.ValidPostTypeSlug sniff to the WordPress-Extra ruleset which will examine calls to register_post_type() and throw errors when an invalid post type slug is used.
    • Generic.Arrays.DisallowShortArraySyntax to the WordPress-Core ruleset.
    • WordPress.NamingConventions.PrefixAllGlobals: the PHP prefix has been added to the prefix blacklist as it is reserved by PHP itself.
    • The wp_sanitize_redirect() function to the sanitizingFunctions list used by the WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput and WordPress.Security.EscapeOutput sniffs.
    • The sanitize_key() and the highlight_string() functions to the escapingFunctions list used by the WordPress.Security.EscapeOutput sniff.
    • The RECOVERY_MODE_COOKIE constant to the list of WP Core constants which may be defined by plugins and themes and therefore don't need to be prefixed (WordPress.NamingConventions.PrefixAllGlobals).
    • $content_width, $plugin, $mu_plugin and $network_plugin to the list of WP globals which is used by both the WordPress.Variables.GlobalVariables and the WordPress.NamingConventions.PrefixAllGlobals sniffs.
    • Sniff::is_short_list() utility method to determine whether a short array open/close token actually represents a PHP 7.1+ short list.
    • Sniff::find_list_open_close() utility method to find the opener and closer for list() constructs, including short lists.
    • Sniff::get_list_variables() utility method which will retrieve an array with the token pointers to the variables which are being assigned to in a list() construct. Includes support for short lists.
    • Sniff::is_function_deprecated() static utility method to determine whether a declared function has been marked as deprecated in the function DocBlock.
    • End-user documentation to the following existing sniffs: WordPress.Arrays.ArrayIndentation, WordPress.Arrays.ArrayKeySpacingRestrictions, WordPress.Arrays.MultipleStatementAlignment, WordPress.Classes.ClassInstantiation, WordPress.NamingConventions.ValidHookName, WordPress.PHP.IniSet, WordPress.Security.SafeRedirect, WordPress.WhiteSpace.CastStructureSpacing, WordPress.WhiteSpace.DisallowInlineTabs, WordPress.WhiteSpace.PrecisionAlignment, WordPress.WP.CronInterval, WordPress.WP.DeprecatedClasses, WordPress.WP.DeprecatedFunctions, WordPress.WP.DeprecatedParameters, WordPress.WP.DeprecatedParameterValues, WordPress.WP.EnqueuedResources, WordPress.WP.PostsPerPage. This documentation can be exposed via the PHP_CodeSniffer --generator=... command-line argument.

    Changed

    • The default value for minimum_supported_wp_version, as used by a number of sniffs detecting usage of deprecated WP features, has been updated to 5.0.
    • The WordPress.Arrays.ArrayKeySpacingRestrictions sniff has two new error codes: TooMuchSpaceBeforeKey and TooMuchSpaceAfterKey. Both auto-fixable. The sniff will now check that there is exactly one space on the inside of the square brackets around the array key for non-string, non-numeric array keys. Previously, it only checked that there was whitespace, not how much whitespace.
    • WordPress.Arrays.ArrayKeySpacingRestrictions: the fixers have been made more efficient and less fixer-conflict prone.
    • WordPress.NamingConventions.PrefixAllGlobals: plugin/theme prefixes should be at least three characters long. A new ShortPrefixPassed error has been added for when the prefix passed does not comply with this rule.
    • WordPress.WhiteSpace.CastStructureSpacing now allows for no whitespace before a cast when the cast is preceded by the spread ... operator. This pre-empts a fixer conflict for when the spacing around the spread operator will start to get checked.
    • The WordPress.WP.DeprecatedClasses sniff will now detect classes deprecated in WP 4.9 and WP 5.3.
    • The WordPress.WP.DeprecatedFunctions sniff will now detect functions deprecated in WP 5.3.
    • WordPress.NamingConventions.ValidHookName now has "cleaner" error messages and higher precision for the line on which an error is thrown.
    • WordPress.Security.EscapeOutput: if an error refers to array access via a variable, the array index key will now be included in the error message.
    • The processing of the WordPress ruleset by PHP_CodeSniffer will now be faster.
    • Various minor code tweaks and clean up.
    • Various minor documentation fixes.
    • Documentation: updated the repo URL in all relevant places.

    Deprecated

    • The WordPress.WP.TimezoneChange sniff. Use the WordPress.DateTime.RestrictedFunctions instead. The deprecated sniff will be removed in WPCS 3.0.0.

    Fixed

    • All sniffs in the WordPress.Arrays category will no longer treat short lists as if they were a short array.
    • The WordPress.NamingConventions.ValidFunctionName and the WordPress.NamingConventions.PrefixAllGlobals sniff will now ignore functions marked as @deprecated.
    • Both the WordPress.NamingConventions.PrefixAllGlobals sniff as well as the WordPress.WP.GlobalVariablesOverride sniff have been updated to recognize variables being declared via (long/short) list() constructs and handle them correctly.
    • Both the WordPress.NamingConventions.PrefixAllGlobals sniff as well as the WordPress.WP.GlobalVariablesOverride sniff will now take a limited list of WP global variables which are intended to be overwritten by plugins/themes into account. Initially this list contains the $content_width and the $wp_cockneyreplace variables.
    ... (truncated)
    Commits
    • f90e869 Merge pull request #1828 from WordPress/develop
    • d45f5e5 Merge pull request #1833 from WordPress/feature/changelog-2.2.0
    • e004a3e Changelog for WPCS 2.2.0
    • 84033ee Adds WP.Security.SafeRedirect documentation. (#1826)
    • e105835 Merge pull request #1824 from NielsdeBlaauw/1722-WordPress.WP.EnqueuedResources
    • 31b8d9b Various minor documentation fixes (#1831)
    • 9bd5f9c Adds documentation for WordPress.WP.EnqueuedResources.
    • a2a32d1 Various minor documentation fixes
    • e7560d1 Ini_set: add documentation (#1730)
    • ed52f7d Merge pull request #1732 from WordPress/docs/posts-per-page
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.

    If all status checks pass Dependabot will automatically merge this pull request.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot badge me will comment on this PR with code to add a "Dependabot enabled" badge to your readme

    Additionally, you can set the following in the .dependabot/config.yml file in this repo:

    • Update frequency
    • Automerge options (never/patch/minor, and dev/runtime dependencies)
    • Out-of-range updates (receive only lockfile updates, if desired)
    • Security updates (receive only security updates, if desired)
    dependencies 
    opened by dependabot-preview[bot] 2
  • Update itinerisltd/itineris-wp-coding-standards requirement from ^0.2.3 to ^0.3.1

    Update itinerisltd/itineris-wp-coding-standards requirement from ^0.2.3 to ^0.3.1

    Updates the requirements on itinerisltd/itineris-wp-coding-standards to permit the latest version.

    Changelog

    Sourced from itinerisltd/itineris-wp-coding-standards's changelog.

    0.3.1 (2019-10-15)

    Full Changelog

    Merged pull requests:

    0.3.0 (2019-07-11)

    Full Changelog

    Merged pull requests:

    0.2.3 (2019-03-20)

    Full Changelog

    Merged pull requests:

    0.2.2 (2019-02-19)

    Full Changelog

    Merged pull requests:

    0.2.1 (2019-02-18)

    Full Changelog

    Merged pull requests:

    0.2.0 (2019-01-28)

    Full Changelog

    Merged pull requests:

    ... (truncated)
    Commits

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.

    If all status checks pass Dependabot will automatically merge this pull request.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot badge me will comment on this PR with code to add a "Dependabot enabled" badge to your readme

    Additionally, you can set the following in the .dependabot/config.yml file in this repo:

    • Update frequency
    • Automerge options (never/patch/minor, and dev/runtime dependencies)
    • Out-of-range updates (receive only lockfile updates, if desired)
    • Security updates (receive only security updates, if desired)
    dependencies 
    opened by dependabot-preview[bot] 2
  • Update itinerisltd/itineris-wp-coding-standards requirement from ^0.2.3 to ^0.3.0

    Update itinerisltd/itineris-wp-coding-standards requirement from ^0.2.3 to ^0.3.0

    Updates the requirements on itinerisltd/itineris-wp-coding-standards to permit the latest version.

    Changelog

    Sourced from itinerisltd/itineris-wp-coding-standards's changelog.

    0.3.0 (2019-07-11)

    Full Changelog

    Merged pull requests:

    • Update to wp-coding-standards/wpcs:^2.1; Ditch automattic/vipwpcs #18 (TangRufus)

    0.2.3 (2019-03-20)

    Full Changelog

    Merged pull requests:

    0.2.2 (2019-02-19)

    Full Changelog

    Merged pull requests:

    0.2.1 (2019-02-18)

    Full Changelog

    Merged pull requests:

    0.2.0 (2019-01-28)

    Full Changelog

    Merged pull requests:

    0.1.0 (2018-10-18)

    Merged pull requests:

    ... (truncated)
    Commits
    • 9d74c6b Merge branch 'version-bump'
    • 4b1ab3c Version bump 0.3.0
    • 9f0d866 Merge branch 'composer-update'
    • b3862fb Update to wp-coding-standards/wpcs:^2.1; Ditch automattic/vipwpcs
    • See full diff in compare view

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.

    If all status checks pass Dependabot will automatically merge this pull request.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot ignore this [patch|minor|major] version will close this PR and stop Dependabot creating any more for this minor/major version (unless you reopen the PR or upgrade to it). To ignore the version in this PR you can just close it
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot badge me will comment on this PR with code to add a "Dependabot enabled" badge to your readme

    Additionally, you can set the following in the .dependabot/config.yml file in this repo:

    • Update frequency (including time of day and day of week)
    • Automerge options (never/patch/minor, and dev/runtime dependencies)
    • Pull request limits (per update run and/or open at any time)
    • Out-of-range updates (receive only lockfile updates, if desired)
    • Security updates (receive only security updates, if desired)

    Finally, you can contact us by mentioning @dependabot.

    dependencies 
    opened by dependabot-preview[bot] 2
  • Bump mockery/mockery from 1.3.5 to 1.3.6

    Bump mockery/mockery from 1.3.5 to 1.3.6

    Bumps mockery/mockery from 1.3.5 to 1.3.6.

    Release notes

    Sourced from mockery/mockery's releases.

    1.3.6

    PHP 8.2 | Fix "Use of "parent" in callables is deprecated" notice #1169

    Changelog

    Sourced from mockery/mockery's changelog.

    1.3.6 (2022-09-07)

    • PHP 8.2 | Fix "Use of "parent" in callables is deprecated" notice #1169

    1.5.1 (2022-09-07)

    • [PHP 8.2] Various tests: explicitly declare properties #1170
    • [PHP 8.2] Fix "Use of "parent" in callables is deprecated" notice #1169
    • [PHP 8.1] Support intersection types #1164
    • Handle final __toString methods #1162

    1.5.0 (2022-01-20)

    • Override default call count expectations via expects() #1146
    • Mock methods with static return types #1157
    • Mock methods with mixed return type #1156
    • Mock classes with new in initializers on PHP 8.1 #1160
    • Removes redundant PHPUnitConstraint #1158

    1.4.4 (2021-09-13)

    • Fixes auto-generated return values #1144
    • Adds support for tentative types #1130
    • Fixes for PHP 8.1 Support (#1130 and #1140)
    • Add method that allows defining a set of arguments the mock should yield #1133
    • Added option to configure default matchers for objects \Mockery::getConfiguration()->setDefaultMatcher($class, $matcherClass) #1120
    Commits
    • dc206df Adds note to changelog
    • a60f28f Merge pull request #1169 from jrfnl/feature/1168-fix-php-8.2-error-callables
    • f09b080 PHP 8.2: fix "Use of "parent" in callables is deprecated" notice
    • See full diff in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 1
  • Bump phpstan/phpstan-strict-rules from 0.12.10 to 0.12.11

    Bump phpstan/phpstan-strict-rules from 0.12.10 to 0.12.11

    Bumps phpstan/phpstan-strict-rules from 0.12.10 to 0.12.11.

    Release notes

    Sourced from phpstan/phpstan-strict-rules's releases.

    0.12.11

    • 2b72e8e - Set reportMaybesInPropertyPhpDocTypes: true
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 1
Owner
Itineris Limited
We’re a full-service digital marketing agency that partners with ambitious clients to help them grow
Itineris Limited
A Laravel package to check if you can send e-mail through a given mailserver in name of a given e-mail address

A Laravel package to check if you can send e-mail through a given mailserver in name of a given e-mail address Mail spf checker A Laravel package to c

Dieter Coopman 102 Sep 20, 2022
A ready-to-use PHP script for sending Emails with an HTML Template will use a Gmail account as the sender and you will not need any email server. Powered by PHPMailer.

Gmail Email Sender by PHP A ready-to-use PHP script for sending Emails with an HTML Template will use a Gmail account as the sender and you will not n

Max Base 3 Aug 28, 2022
A mail driver to quickly preview mail

A mail driver to quickly preview mail This package can display a small overlay whenever a mail is sent. The overlay contains a link to the mail that w

Spatie 1k Sep 23, 2022
This application (class) does the sending of emails used in the phpmailer library

emailsender - PHP Notification library via email using phpMailer This library has the function of sending email using the phpmailer library. Doing thi

Lucas Alcantara Rodrigues Volpati 1 Feb 9, 2022
Bounce Mail Handler for PHP | This is a "reboot" of PHPMailer-BMH from WorxWare.

PHP 7.0+ Support Composer & PSR-0 Support PHPUnit testing via Travis CI (TODO: more tests needed) PHP-Quality testing via SensioLabsInsight (TODO: mor

Lars Moelleken 41 Mar 25, 2022
Mail sending module for Mezzio and Laminas MVC with support for file attachment and template email composition

This module provides an easy and flexible way to send emails from Mezzio and Laminas MVC applications (formerly known as Zend Expressive and Zend MVC). It allows you to pre-configure emails and transports, and then send those emails at runtime.

null 82 Jan 16, 2022
A simplified SMPP client lib for sending or receiving smses through SMPP v3.4.

PHP-based SMPP client lib This is a simplified SMPP client lib for sending or receiving smses through SMPP v3.4. In addition to the client, this lib a

Qranio.com 2 Jul 26, 2022
PHPMailer – A full-featured email creation and transfer class for PHP

PHPMailer – A full-featured email creation and transfer class for PHP Features Probably the world's most popular code for sending email from PHP! Used

PHPMailer 18.7k Sep 26, 2022
PHPMailer-VerficationCode App

the App PHPMailer-VerficationCode App Steps To use it: install Xampp or Wampp Server copy and extlact the cloned project into htdocs in xammp Import .

Dominique Rwema Bagirishya 13 Jul 21, 2022
CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very usefull when you're sending emails.

CssToInlineStyles class Installation CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline style

Tijs Verkoyen 5.6k Sep 21, 2022
PostfixAdmin - web based virtual user administration interface for Postfix mail servers

PostfixAdmin An open source, web based interface for managing domains/mailboxes/aliases etc on a Postfix based mail server.

PostfixAdmin 714 Sep 24, 2022
The classic email sending library for PHP

PHPMailer – A full-featured email creation and transfer class for PHP Features Probably the world's most popular code for sending email from PHP! Used

PHPMailer 18.7k Sep 30, 2022
An AngularJS / Laravel app - Keyword Based Email forwarder | read/write emails through IMAP

@MailTree Simple mail forwarder. Based on the specific email body/subject keywords forward mails to the list of predefined users. Install Imap Install

Dren Kajmakchi 4 Aug 21, 2018
:envelope: E-Mail Address Validator (syntax, dns, trash, typo)

✉️ E-Mail Address Validator for PHP Warning The best way to validate an e-mail address is still to send a duplicate opt-in-mail, when the user clicks

Lars Moelleken 39 Jul 28, 2022
The Mailer component helps sending emails

Mailer Component The Mailer component helps sending emails. Getting Started $ composer require symfony/mailer use Symfony\Component\Mailer\Transport;

Symfony 1.1k Sep 29, 2022
Laravel Mail Credentials switcher for Budget Laravel Applications

Laravel Mail Switcher Laravel Mail Credentials Switcher is a library which helps you to: Manage your Mail Service Credentials Configure the Laravel's

(Seth) Phat Tran 28 Aug 6, 2022
Laravel Mail Catcher Driver

Laravel Mail Catcher Driver This package include a new mailbase driver which will catch all the sent emails and save it to the database. It then expos

Tauqeer Liaqat 94 Aug 30, 2022
💌 Mail app for Nextcloud

Nextcloud Mail ?? A mail app for Nextcloud Why is this so awesome? ?? Integration with other Nextcloud apps! Currently Contacts, Calendar & Files – mo

Nextcloud 666 Sep 22, 2022
Sending Email via Microsoft Exchange Web Services made Easy!

Send Mail via Exchange Web Services! Sending Email via Microsoft Exchange Web Services (EWS) made easy! Installation Install via Composer composer req

Raju Rayhan 19 Jul 19, 2022