From ddf20a5acb637a15a8661178f4dc9ccc5cf10380 Mon Sep 17 00:00:00 2001 From: Slava Abakumov Date: Thu, 9 Jul 2020 14:06:12 +0300 Subject: [PATCH] WP Mail SMTP 2.2.1 --- assets/languages/wp-mail-smtp.pot | 384 +++++++++++++++----------- gulpfile.js | 6 +- package.json | 2 +- readme.txt | 10 +- src/Admin/Area.php | 18 +- src/Admin/PageAbstract.php | 4 +- src/Admin/Pages/About.php | 30 +- src/Admin/Pages/Logs.php | 5 +- src/Admin/Pages/MiscTab.php | 15 +- src/Admin/Pages/SettingsTab.php | 65 ++++- src/Admin/Pages/TestTab.php | 6 +- src/Core.php | 120 +++++++- src/MailCatcher.php | 17 +- src/MailCatcherInterface.php | 33 +++ src/MailCatcherV6.php | 149 ++++++++++ src/Options.php | 4 +- src/Processor.php | 32 +-- src/Providers/Gmail/Auth.php | 60 +++- src/Providers/Gmail/Mailer.php | 43 ++- src/Providers/Gmail/Options.php | 17 ++ src/Providers/Loader.php | 13 +- src/Providers/MailerAbstract.php | 17 +- src/Providers/MailerInterface.php | 5 +- src/Providers/Mailgun/Mailer.php | 37 ++- src/Providers/PepipostAPI/Mailer.php | 394 +++++++++++++++------------ src/Providers/SMTPcom/Mailer.php | 5 +- src/Providers/Sendgrid/Mailer.php | 5 +- src/Providers/Sendinblue/Mailer.php | 26 +- src/SiteHealth.php | 102 ++++++- src/Tasks/Task.php | 2 +- src/WP.php | 59 ++++ uninstall.php | 188 +++++++++---- wp_mail_smtp.php | 4 +- 33 files changed, 1339 insertions(+), 538 deletions(-) create mode 100644 src/MailCatcherInterface.php create mode 100644 src/MailCatcherV6.php diff --git a/assets/languages/wp-mail-smtp.pot b/assets/languages/wp-mail-smtp.pot index 0c7ed27..e493502 100644 --- a/assets/languages/wp-mail-smtp.pot +++ b/assets/languages/wp-mail-smtp.pot @@ -1,13 +1,13 @@ msgid "" msgstr "" -"Project-Id-Version: WP Mail SMTP 2.1.1\n" +"Project-Id-Version: WP Mail SMTP 2.2.1\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wp-mail-smtp\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"POT-Creation-Date: 2020-06-08T15:05:17+03:00\n" +"POT-Creation-Date: 2020-07-09T12:48:03+03:00\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.4.0\n" "X-Domain: wp-mail-smtp\n" @@ -66,21 +66,21 @@ msgstr "" #: src/Admin/Area.php:220 #: src/Admin/Area.php:221 -#: src/Admin/Area.php:864 +#: src/Admin/Area.php:862 msgid "Settings" msgstr "" #: src/Admin/Area.php:228 #: src/Admin/Area.php:229 -#: src/Admin/Pages/About.php:627 -#: src/Admin/Pages/Logs.php:49 +#: src/Admin/Pages/About.php:651 +#: src/Admin/Pages/Logs.php:48 #: src/Admin/Pages/LogsTab.php:30 msgid "Email Log" msgstr "" #: src/Admin/Area.php:238 #: src/Admin/Area.php:239 -#: src/Admin/Pages/About.php:105 +#: src/Admin/Pages/About.php:106 msgid "About Us" msgstr "" @@ -100,274 +100,278 @@ msgstr "" msgid "

The Default (PHP) mailer is currently selected, but is not recommended because in most cases it does not resolve email delivery issues.

Please consider selecting and configuring one of the other mailers.

" msgstr "" -#: src/Admin/Area.php:312 -#: src/Admin/PageAbstract.php:81 +#: src/Admin/Area.php:310 +#: src/Admin/PageAbstract.php:83 msgid "Save Settings" msgstr "" -#: src/Admin/Area.php:313 +#: src/Admin/Area.php:311 msgid "Cancel" msgstr "" -#: src/Admin/Area.php:314 +#: src/Admin/Area.php:312 msgid "Warning icon" msgstr "" -#: src/Admin/Area.php:319 +#: src/Admin/Area.php:317 msgid "%name% is a PRO Feature" msgstr "" -#: src/Admin/Area.php:320 +#: src/Admin/Area.php:318 msgid "Upgrade to Pro" msgstr "" -#: src/Admin/Area.php:324 +#: src/Admin/Area.php:322 msgid "Bonus: WP Mail SMTP users get $50 off regular price,
applied at checkout." msgstr "" -#: src/Admin/Area.php:333 +#: src/Admin/Area.php:331 msgid "Already purchased?" msgstr "" -#: src/Admin/Area.php:400 -#: src/Admin/Area.php:407 -#: src/Admin/Pages/About.php:308 +#: src/Admin/Area.php:398 +#: src/Admin/Area.php:405 +#: src/Admin/Pages/About.php:332 msgid "Activate" msgstr "" -#: src/Admin/Area.php:401 -#: src/Admin/Pages/About.php:300 +#: src/Admin/Area.php:399 +#: src/Admin/Pages/About.php:324 msgid "Activated" msgstr "" -#: src/Admin/Area.php:402 -#: src/Admin/Pages/About.php:297 +#: src/Admin/Area.php:400 +#: src/Admin/Pages/About.php:321 msgid "Active" msgstr "" -#: src/Admin/Area.php:403 -#: src/Admin/Pages/About.php:305 +#: src/Admin/Area.php:401 +#: src/Admin/Pages/About.php:329 msgid "Inactive" msgstr "" -#: src/Admin/Area.php:404 +#: src/Admin/Area.php:402 msgid "Processing..." msgstr "" -#: src/Admin/Area.php:405 +#: src/Admin/Area.php:403 msgid "Could not install a plugin. Please download from WordPress.org and install manually." msgstr "" -#: src/Admin/Area.php:406 +#: src/Admin/Area.php:404 msgid "Install and Activate" msgstr "" -#: src/Admin/Area.php:408 +#: src/Admin/Area.php:406 msgid "Download" msgstr "" #. translators: %1$s - WP.org link; %2$s - same WP.org link. -#: src/Admin/Area.php:468 +#: src/Admin/Area.php:466 msgid "Please rate WP Mail SMTP ★★★★★ on WordPress.org to help us spread the word. Thank you from the WP Mail SMTP team!" msgstr "" -#: src/Admin/Area.php:805 +#: src/Admin/Area.php:803 msgid "WP Mail SMTP Pro related message was successfully dismissed." msgstr "" -#: src/Admin/Area.php:824 +#: src/Admin/Area.php:822 msgid "Educational notice for this mailer was successfully dismissed." msgstr "" -#: src/Admin/Area.php:863 +#: src/Admin/Area.php:861 msgid "Go to WP Mail SMTP Settings page" msgstr "" -#: src/Admin/Area.php:870 +#: src/Admin/Area.php:868 msgid "Go to WP Mail SMTP Lite vs Pro comparison page" msgstr "" -#: src/Admin/Area.php:871 +#: src/Admin/Area.php:869 msgid "Premium Support" msgstr "" #. translators: %s - plugin current license type. -#: src/Admin/Pages/About.php:98 -#: src/Admin/Pages/About.php:526 +#: src/Admin/Pages/About.php:99 +#: src/Admin/Pages/About.php:550 msgid "%s vs Pro" msgstr "" -#: src/Admin/Pages/About.php:170 +#: src/Admin/Pages/About.php:171 msgid "Hello and welcome to WP Mail SMTP, the easiest and most popular WordPress SMTP plugin. We build software that helps your site reliably deliver emails every time." msgstr "" -#: src/Admin/Pages/About.php:174 +#: src/Admin/Pages/About.php:175 msgid "Email deliverability has been a well-documented problem for all WordPress websites. However as WPForms grew, we became more aware of this painful issue that affects our users and the larger WordPress community. So we decided to solve this problem and make a solution that's beginner friendly." msgstr "" -#: src/Admin/Pages/About.php:177 +#: src/Admin/Pages/About.php:178 msgid "Our goal is to make reliable email deliverability easy for WordPress." msgstr "" #. translators: %1$s - WPForms URL, %2$s - WPBeginner URL, %3$s - OptinMonster URL, %4$s - MonsterInsights URL, %5$s - RafflePress URL -#: src/Admin/Pages/About.php:184 +#: src/Admin/Pages/About.php:185 msgid "WP Mail SMTP is brought to you by the same team that's behind the most user friendly WordPress forms, WPForms, the largest WordPress resource site, WPBeginner, the most popular lead-generation software, OptinMonster, the best WordPress analytics plugin, MonsterInsights, and the most powerful WordPress contest plugin, RafflePress." msgstr "" -#: src/Admin/Pages/About.php:202 +#: src/Admin/Pages/About.php:203 msgid "Yup, we know a thing or two about building awesome products that customers love." msgstr "" -#: src/Admin/Pages/About.php:208 +#: src/Admin/Pages/About.php:209 msgid "The WPForms Team photo" msgstr "" -#: src/Admin/Pages/About.php:210 +#: src/Admin/Pages/About.php:211 msgid "The WPForms Team" msgstr "" +#: src/Admin/Pages/About.php:260 +msgid "Plugin icon" +msgstr "" + #. translators: %s - status HTML text. -#: src/Admin/Pages/About.php:250 +#: src/Admin/Pages/About.php:274 msgid "Status: %s" msgstr "" -#: src/Admin/Pages/About.php:316 +#: src/Admin/Pages/About.php:340 msgid "Not Installed" msgstr "" -#: src/Admin/Pages/About.php:319 +#: src/Admin/Pages/About.php:343 msgid "Install Plugin" msgstr "" -#: src/Admin/Pages/About.php:340 +#: src/Admin/Pages/About.php:364 msgid "MonsterInsights" msgstr "" -#: src/Admin/Pages/About.php:341 -#: src/Admin/Pages/About.php:347 +#: src/Admin/Pages/About.php:365 +#: src/Admin/Pages/About.php:371 msgid "MonsterInsights makes it “effortless” to properly connect your WordPress site with Google Analytics, so you can start making data-driven decisions to grow your business." msgstr "" -#: src/Admin/Pages/About.php:346 +#: src/Admin/Pages/About.php:370 msgid "MonsterInsights Pro" msgstr "" -#: src/Admin/Pages/About.php:354 +#: src/Admin/Pages/About.php:378 msgid "OptinMonster" msgstr "" -#: src/Admin/Pages/About.php:355 +#: src/Admin/Pages/About.php:379 msgid "Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers." msgstr "" -#: src/Admin/Pages/About.php:361 +#: src/Admin/Pages/About.php:385 msgid "Contact Forms by WPForms" msgstr "" -#: src/Admin/Pages/About.php:362 -#: src/Admin/Pages/About.php:368 +#: src/Admin/Pages/About.php:386 +#: src/Admin/Pages/About.php:392 msgid "The best WordPress contact form plugin. Drag & Drop online form builder that helps you create beautiful contact forms with just a few clicks." msgstr "" -#: src/Admin/Pages/About.php:367 +#: src/Admin/Pages/About.php:391 msgid "WPForms Pro" msgstr "" -#: src/Admin/Pages/About.php:375 +#: src/Admin/Pages/About.php:399 msgid "RafflePress" msgstr "" -#: src/Admin/Pages/About.php:376 -#: src/Admin/Pages/About.php:382 +#: src/Admin/Pages/About.php:400 +#: src/Admin/Pages/About.php:406 msgid "Turn your visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with powerful viral giveaways & contests." msgstr "" -#: src/Admin/Pages/About.php:381 +#: src/Admin/Pages/About.php:405 msgid "RafflePress Pro" msgstr "" -#: src/Admin/Pages/About.php:401 +#: src/Admin/Pages/About.php:425 msgid "Could not activate the plugin. Please activate it from the Plugins page." msgstr "" -#: src/Admin/Pages/About.php:413 +#: src/Admin/Pages/About.php:437 msgid "Plugin activated." msgstr "" -#: src/Admin/Pages/About.php:430 +#: src/Admin/Pages/About.php:454 msgid "Could not install the plugin." msgstr "" -#: src/Admin/Pages/About.php:491 +#: src/Admin/Pages/About.php:515 msgid "Plugin installed & activated." msgstr "" -#: src/Admin/Pages/About.php:499 +#: src/Admin/Pages/About.php:523 msgid "Plugin installed." msgstr "" -#: src/Admin/Pages/About.php:534 +#: src/Admin/Pages/About.php:558 msgid "Get the most out of WP Mail SMTP by upgrading to Pro and unlocking all of the powerful features." msgstr "" -#: src/Admin/Pages/About.php:543 +#: src/Admin/Pages/About.php:567 msgid "Feature" msgstr "" -#: src/Admin/Pages/About.php:553 +#: src/Admin/Pages/About.php:577 msgid "Pro" msgstr "" -#: src/Admin/Pages/About.php:594 +#: src/Admin/Pages/About.php:618 msgid "Get WP Mail SMTP Pro Today and Unlock all of these Powerful Features" msgstr "" -#: src/Admin/Pages/About.php:601 +#: src/Admin/Pages/About.php:625 msgid "Bonus: WP Mail SMTP Lite users get $50 off regular price, automatically applied at checkout." msgstr "" -#: src/Admin/Pages/About.php:628 +#: src/Admin/Pages/About.php:652 #: src/Admin/Pages/ControlTab.php:27 msgid "Email Controls" msgstr "" -#: src/Admin/Pages/About.php:629 +#: src/Admin/Pages/About.php:653 msgid "Additional Mailers" msgstr "" -#: src/Admin/Pages/About.php:630 +#: src/Admin/Pages/About.php:654 msgid "Customer Support" msgstr "" -#: src/Admin/Pages/About.php:651 +#: src/Admin/Pages/About.php:675 msgid "Emails are not logged" msgstr "" -#: src/Admin/Pages/About.php:657 +#: src/Admin/Pages/About.php:681 msgid "Complete Email Log management inside WordPress" msgstr "" -#: src/Admin/Pages/About.php:665 +#: src/Admin/Pages/About.php:689 msgid "No controls over whether default WordPress emails are sent" msgstr "" -#: src/Admin/Pages/About.php:671 +#: src/Admin/Pages/About.php:695 msgid "Complete Email Controls management for most default WordPress emails" msgstr "" -#: src/Admin/Pages/About.php:679 +#: src/Admin/Pages/About.php:703 msgid "Only default list of mailers" msgstr "" -#: src/Admin/Pages/About.php:685 +#: src/Admin/Pages/About.php:709 msgid "Additional mailers: Microsoft Outlook (with Office365 support) and Amazon SES" msgstr "" -#: src/Admin/Pages/About.php:693 +#: src/Admin/Pages/About.php:717 msgid "Limited Support" msgstr "" -#: src/Admin/Pages/About.php:699 +#: src/Admin/Pages/About.php:723 msgid "Priority Support" msgstr "" @@ -520,194 +524,202 @@ msgstr "" msgid "Check this if you would like to remove ALL WP Mail SMTP data upon plugin deletion. All settings will be unrecoverable." msgstr "" -#: src/Admin/Pages/MiscTab.php:223 -#: src/Admin/Pages/SettingsTab.php:540 +#: src/Admin/Pages/MiscTab.php:234 +#: src/Admin/Pages/SettingsTab.php:583 msgid "Settings were successfully saved." msgstr "" -#: src/Admin/Pages/SettingsTab.php:36 +#: src/Admin/Pages/SettingsTab.php:37 msgid "General" msgstr "" -#: src/Admin/Pages/SettingsTab.php:64 +#: src/Admin/Pages/SettingsTab.php:67 msgid "License" msgstr "" -#: src/Admin/Pages/SettingsTab.php:67 +#: src/Admin/Pages/SettingsTab.php:70 msgid "Your license key provides access to updates and support." msgstr "" -#: src/Admin/Pages/SettingsTab.php:75 +#: src/Admin/Pages/SettingsTab.php:78 msgid "License Key" msgstr "" -#: src/Admin/Pages/SettingsTab.php:85 +#: src/Admin/Pages/SettingsTab.php:88 msgid "Mail" msgstr "" -#: src/Admin/Pages/SettingsTab.php:92 +#: src/Admin/Pages/SettingsTab.php:95 msgid "From Email" msgstr "" -#: src/Admin/Pages/SettingsTab.php:103 +#: src/Admin/Pages/SettingsTab.php:113 +msgid "Please first authorize the Gmail mailer below" +msgstr "" + +#: src/Admin/Pages/SettingsTab.php:127 msgid "The email address which emails are sent from." msgstr "" -#: src/Admin/Pages/SettingsTab.php:104 -msgid "If you using an email provider (Gmail, Yahoo, Outlook.com, etc) this should be your email address for that account." +#: src/Admin/Pages/SettingsTab.php:128 +msgid "If you're using an email provider (Yahoo, Outlook.com, etc) this should be your email address for that account." msgstr "" -#: src/Admin/Pages/SettingsTab.php:107 +#: src/Admin/Pages/SettingsTab.php:131 msgid "Please note that other plugins can change this, to prevent this use the setting below." msgstr "" -#: src/Admin/Pages/SettingsTab.php:119 +#: src/Admin/Pages/SettingsTab.php:149 msgid "Force From Email" msgstr "" -#: src/Admin/Pages/SettingsTab.php:124 +#: src/Admin/Pages/SettingsTab.php:156 msgid "Current provider will automatically force From Email to be the email address that you use to set up the connection below." msgstr "" -#: src/Admin/Pages/SettingsTab.php:128 +#: src/Admin/Pages/SettingsTab.php:158 +msgid "Gmail mailer will automatically force From Email to be the email address that you selected above." +msgstr "" + +#: src/Admin/Pages/SettingsTab.php:164 msgid "If checked, the From Email setting above will be used for all emails, ignoring values set by other plugins." msgstr "" -#: src/Admin/Pages/SettingsTab.php:138 +#: src/Admin/Pages/SettingsTab.php:174 msgid "From Name" msgstr "" -#: src/Admin/Pages/SettingsTab.php:149 +#: src/Admin/Pages/SettingsTab.php:185 msgid "The name which emails are sent from." msgstr "" -#: src/Admin/Pages/SettingsTab.php:161 +#: src/Admin/Pages/SettingsTab.php:197 msgid "Force From Name" msgstr "" -#: src/Admin/Pages/SettingsTab.php:166 +#: src/Admin/Pages/SettingsTab.php:202 msgid "Current provider doesn't support setting and forcing From Name. Emails will be sent on behalf of the account name used to setup the connection below." msgstr "" -#: src/Admin/Pages/SettingsTab.php:170 +#: src/Admin/Pages/SettingsTab.php:206 msgid "If checked, the From Name setting above will be used for all emails, ignoring values set by other plugins." msgstr "" -#: src/Admin/Pages/SettingsTab.php:179 +#: src/Admin/Pages/SettingsTab.php:215 msgid "Return Path" msgstr "" -#: src/Admin/Pages/SettingsTab.php:188 +#: src/Admin/Pages/SettingsTab.php:224 msgid "Set the return-path to match the From Email" msgstr "" -#: src/Admin/Pages/SettingsTab.php:192 +#: src/Admin/Pages/SettingsTab.php:228 msgid "Return Path indicates where non-delivery receipts - or bounce messages - are to be sent." msgstr "" -#: src/Admin/Pages/SettingsTab.php:193 +#: src/Admin/Pages/SettingsTab.php:229 msgid "If unchecked, bounce messages may be lost. Some providers may ignore this option." msgstr "" -#: src/Admin/Pages/SettingsTab.php:201 +#: src/Admin/Pages/SettingsTab.php:237 msgid "Mailer" msgstr "" -#: src/Admin/Pages/SettingsTab.php:242 +#: src/Admin/Pages/SettingsTab.php:278 msgid "Don't see what you're looking for?" msgstr "" -#: src/Admin/Pages/SettingsTab.php:244 +#: src/Admin/Pages/SettingsTab.php:280 msgid "Suggest a Mailer" msgstr "" -#: src/Admin/Pages/SettingsTab.php:272 +#: src/Admin/Pages/SettingsTab.php:308 msgid "Dismiss this notice" msgstr "" -#: src/Admin/Pages/SettingsTab.php:314 +#: src/Admin/Pages/SettingsTab.php:355 msgid "You're using WP Mail SMTP Lite - no license needed. Enjoy!" msgstr "" #. translators: %s - WPMailSMTP.com upgrade URL. -#: src/Admin/Pages/SettingsTab.php:320 +#: src/Admin/Pages/SettingsTab.php:361 msgid "To unlock more features consider upgrading to PRO." msgstr "" -#: src/Admin/Pages/SettingsTab.php:339 +#: src/Admin/Pages/SettingsTab.php:380 msgid "As a valued WP Mail SMTP Lite user you receive $50 off, automatically applied at checkout!" msgstr "" -#: src/Admin/Pages/SettingsTab.php:400 +#: src/Admin/Pages/SettingsTab.php:441 msgid "Get WP Mail SMTP Pro and Unlock all the Powerful Features" msgstr "" -#: src/Admin/Pages/SettingsTab.php:404 +#: src/Admin/Pages/SettingsTab.php:445 msgid "Thanks for being a loyal WP Mail SMTP user. Upgrade to WP Mail SMTP Pro to unlock more awesome features and experience why WP Mail SMTP is the most popular SMTP plugin." msgstr "" -#: src/Admin/Pages/SettingsTab.php:408 +#: src/Admin/Pages/SettingsTab.php:449 msgid "We know that you will truly love WP Mail SMTP. It's used by over 1,000,000 websites." msgstr "" -#: src/Admin/Pages/SettingsTab.php:411 +#: src/Admin/Pages/SettingsTab.php:452 msgid "Pro Features:" msgstr "" -#: src/Admin/Pages/SettingsTab.php:415 +#: src/Admin/Pages/SettingsTab.php:456 msgid "Manage Notifications - control which emails your site sends" msgstr "" -#: src/Admin/Pages/SettingsTab.php:416 +#: src/Admin/Pages/SettingsTab.php:457 msgid "Email Logging - keep track of every email sent from your site" msgstr "" -#: src/Admin/Pages/SettingsTab.php:417 +#: src/Admin/Pages/SettingsTab.php:458 msgid "Office 365 - send emails using your Office 365 account" msgstr "" -#: src/Admin/Pages/SettingsTab.php:418 +#: src/Admin/Pages/SettingsTab.php:459 msgid "Amazon SES - harness the power of AWS" msgstr "" -#: src/Admin/Pages/SettingsTab.php:419 +#: src/Admin/Pages/SettingsTab.php:460 msgid "Outlook.com - send emails using your Outlook.com account" msgstr "" -#: src/Admin/Pages/SettingsTab.php:420 +#: src/Admin/Pages/SettingsTab.php:461 msgid "Access to our world class support team" msgstr "" -#: src/Admin/Pages/SettingsTab.php:423 +#: src/Admin/Pages/SettingsTab.php:464 msgid "White Glove Setup - sit back and relax while we handle everything for you" msgstr "" -#: src/Admin/Pages/SettingsTab.php:424 +#: src/Admin/Pages/SettingsTab.php:465 msgid "Install WP Mail SMTP Pro plugin" msgstr "" -#: src/Admin/Pages/SettingsTab.php:425 +#: src/Admin/Pages/SettingsTab.php:466 msgid "Set up domain name verification (DNS)" msgstr "" -#: src/Admin/Pages/SettingsTab.php:426 +#: src/Admin/Pages/SettingsTab.php:467 msgid "Configure Mailgun service" msgstr "" -#: src/Admin/Pages/SettingsTab.php:427 +#: src/Admin/Pages/SettingsTab.php:468 msgid "Set up WP Mail SMTP Pro plugin" msgstr "" -#: src/Admin/Pages/SettingsTab.php:428 +#: src/Admin/Pages/SettingsTab.php:469 msgid "Test and verify email delivery" msgstr "" #. translators: %s - WPMailSMTP.com URL. -#: src/Admin/Pages/SettingsTab.php:436 +#: src/Admin/Pages/SettingsTab.php:477 msgid "Get WP Mail SMTP Pro Today and Unlock all the Powerful Features »" msgstr "" -#: src/Admin/Pages/SettingsTab.php:454 +#: src/Admin/Pages/SettingsTab.php:495 msgid "Bonus: WP Mail SMTP users get $50 off regular price, automatically applied at checkout." msgstr "" @@ -1324,35 +1336,35 @@ msgid "Heads up! WP Mail SMTP has detected %1$s is activated. Please deactivate msgstr "" #. translators: %1$s - WP Mail SMTP plugin name; %2$s - WPMailSMTP.com URL to a related doc. -#: src/Core.php:367 +#: src/Core.php:381 msgid "Your site is running an outdated version of PHP that is no longer supported and may cause issues with %1$s. Read more for additional information." msgstr "" -#: src/Core.php:381 +#: src/Core.php:395 msgid "Please Note: Support for PHP 5.5 will be discontinued in 2020. After this, if no further action is taken, WP Mail SMTP functionality will be disabled." msgstr "" #. translators: %s - plugin name and its version. -#: src/Core.php:415 +#: src/Core.php:429 msgid "EMAILING DISABLED: The %s is currently blocking all emails from being sent." msgstr "" #. translators: %1$s - constant name; %2$s - constant value. -#: src/Core.php:426 +#: src/Core.php:440 msgid "To send emails, change the value of the %1$s constant to %2$s." msgstr "" #. translators: %s - plugin Misc settings page URL. -#: src/Core.php:437 +#: src/Core.php:451 msgid "To send emails, go to plugin Misc settings and disable the \"Do Not Send\" option." msgstr "" #. translators: %s - plugin name and its version. -#: src/Core.php:469 +#: src/Core.php:482 msgid "EMAIL DELIVERY ERROR: the plugin %s logged this error during the last time it tried to send an email:" msgstr "" -#: src/Core.php:499 +#: src/Core.php:512 msgid "Consider running an email test after fixing it." msgstr "" @@ -1377,19 +1389,19 @@ msgstr "" msgid "We're sorry, the Amazon SES mailer is not available on your plan. Please upgrade to the PRO plan to unlock all these awesome features." msgstr "" -#: src/Providers/Gmail/Auth.php:170 +#: src/Providers/Gmail/Auth.php:182 msgid "There was an error while processing the Google authentication request. Please make sure that you have Client ID and Client Secret both valid and saved." msgstr "" -#: src/Providers/Gmail/Mailer.php:258 +#: src/Providers/Gmail/Mailer.php:255 msgid "Please re-grant Google app permissions!" msgstr "" -#: src/Providers/Gmail/Mailer.php:259 +#: src/Providers/Gmail/Mailer.php:256 msgid "Go to WP Mail SMTP plugin settings page. Click the “Remove Connection” button." msgstr "" -#: src/Providers/Gmail/Mailer.php:260 +#: src/Providers/Gmail/Mailer.php:257 msgid "Then click the “Allow plugin to send emails using your Google account” button and re-enable access." msgstr "" @@ -1447,11 +1459,16 @@ msgstr "" msgid "Connected as %s" msgstr "" -#: src/Providers/Gmail/Options.php:184 +#. translators: %s - URL to Google Gmail alias documentation page. +#: src/Providers/Gmail/Options.php:187 +msgid "If you want to use a different From Email address you can set-up a Google email alias. Follow these instructions and then select the From Email at the top of this page." +msgstr "" + +#: src/Providers/Gmail/Options.php:201 msgid "Removing the connection will give you an ability to redo the connection or link to another Google account." msgstr "" -#: src/Providers/Gmail/Options.php:192 +#: src/Providers/Gmail/Options.php:209 msgid "You need to save settings with Client ID and Client Secret before you can proceed." msgstr "" @@ -1463,6 +1480,18 @@ msgstr "" msgid "You currently have the native WordPress option selected. Please select any other Mailer option above to continue the setup." msgstr "" +#: src/Providers/Mailgun/Mailer.php:392 +msgid "Mailgun API request was successful, but it could not queue the email for delivery." +msgstr "" + +#: src/Providers/Mailgun/Mailer.php:393 +msgid "This could point to an incorrect Domain Name in the plugin settings." +msgstr "" + +#: src/Providers/Mailgun/Mailer.php:394 +msgid "Please check the WP Mail SMTP plugin settings and make sure the Mailgun Domain Name setting is correct." +msgstr "" + #: src/Providers/Mailgun/Options.php:25 msgid "Mailgun" msgstr "" @@ -1623,6 +1652,14 @@ msgstr "" msgid "Pepipost SMTP" msgstr "" +#: src/Providers/PepipostAPI/Mailer.php:339 +msgid "General error" +msgstr "" + +#: src/Providers/PepipostAPI/Mailer.php:340 +msgid "Error" +msgstr "" + #. translators: %1$s - URL to pepipost.com site. #: src/Providers/PepipostAPI/Options.php:31 msgid "Pepipost is a recommended transactional email service. Every month Pepipost delivers over 8 billion emails from 20,000+ customers. Their mission is to reliably send emails in the most efficient way and at the most disruptive pricing ever. Pepipost provides users 30,000 free emails the first 30 days." @@ -1708,11 +1745,11 @@ msgstr "" msgid "Use the SMTP details provided by your hosting provider or email service.

To see recommended settings for the popular services as well as troubleshooting tips, check out our SMTP documentation." msgstr "" -#: src/Providers/SMTPcom/Mailer.php:433 +#: src/Providers/SMTPcom/Mailer.php:434 msgid "Api Key:" msgstr "" -#: src/Providers/SMTPcom/Mailer.php:435 +#: src/Providers/SMTPcom/Mailer.php:436 msgid "Channel:" msgstr "" @@ -1760,54 +1797,89 @@ msgstr "" msgid "Is WP Mail SMTP mailer setup complete?" msgstr "" -#: src/SiteHealth.php:92 +#: src/SiteHealth.php:72 +msgid "Do WP Mail SMTP DB tables exist?" +msgstr "" + +#: src/SiteHealth.php:98 msgid "Version" msgstr "" -#: src/SiteHealth.php:96 +#: src/SiteHealth.php:102 msgid "License key type" msgstr "" -#: src/SiteHealth.php:100 +#: src/SiteHealth.php:106 msgid "Debug" msgstr "" -#: src/SiteHealth.php:101 +#: src/SiteHealth.php:107 msgid "No debug notices found." msgstr "" -#: src/SiteHealth.php:131 +#: src/SiteHealth.php:110 +msgid "DB tables" +msgstr "" + +#: src/SiteHealth.php:112 +msgid "No DB tables found." +msgstr "" + +#: src/SiteHealth.php:142 msgid "Current mailer" msgstr "" -#: src/SiteHealth.php:136 +#: src/SiteHealth.php:147 msgid "WP Mail SMTP mailer setup is complete" msgstr "" -#: src/SiteHealth.php:145 +#: src/SiteHealth.php:156 msgid "The WP Mail SMTP plugin mailer setup is complete. You can send a test email, to make sure it's working properly." msgstr "" -#: src/SiteHealth.php:150 +#: src/SiteHealth.php:161 msgid "Test email sending" msgstr "" -#: src/SiteHealth.php:158 +#: src/SiteHealth.php:169 msgid "You currently have the default mailer selected, which means that you haven’t set up SMTP yet." msgstr "" -#: src/SiteHealth.php:163 +#: src/SiteHealth.php:174 msgid "WP Mail SMTP mailer setup is incomplete" msgstr "" -#: src/SiteHealth.php:169 +#: src/SiteHealth.php:180 msgid "The WP Mail SMTP plugin mailer setup is incomplete. Please click on the link below to access plugin settings and configure the mailer." msgstr "" -#: src/SiteHealth.php:174 +#: src/SiteHealth.php:185 msgid "Configure mailer" msgstr "" +#: src/SiteHealth.php:202 +msgid "WP Mail SMTP DB tables are created" +msgstr "" + +#: src/SiteHealth.php:208 +msgid "WP Mail SMTP is using custom database tables for some of its features. In order to work properly, the custom tables should be created, and it looks like they exist in your database." +msgstr "" + +#: src/SiteHealth.php:216 +msgid "WP Mail SMTP DB tables check has failed" +msgstr "" + +#. translators: %s - the list of missing tables separated by comma. +#: src/SiteHealth.php:222 +msgid "Missing table: %s" +msgid_plural "Missing tables: %s" +msgstr[0] "" +msgstr[1] "" + +#: src/SiteHealth.php:225 +msgid "WP Mail SMTP is using custom database tables for some of its features. In order to work properly, the custom tables should be created, and it seems they are missing. Please try to re-install the WP Mail SMTP plugin. If this issue persists, please contact our support." +msgstr "" + #. translators: %1$s - date, \a\t - specially escaped "at", %2$s - time. #: src/WP.php:190 msgid "%1$s \\a\\t %2$s" diff --git a/gulpfile.js b/gulpfile.js index 508ecee..a9585bd 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -321,10 +321,10 @@ gulp.task( 'replace_ver', gulp.series( 'replace_plugin_file_ver', 'replace_since /** * Task: build. */ -gulp.task( 'build:lite', gulp.series( gulp.parallel( 'css', 'js', 'img', 'pot:lite' ), 'replace_ver', 'rename:lite', 'composer:lite', 'zip:lite' ) ); -gulp.task( 'build:pro', gulp.series( gulp.parallel( 'css', 'js', 'img', 'pot' ), 'replace_ver', 'rename:pro', 'composer:pro', 'zip:pro' ) ); +gulp.task( 'build:lite', gulp.series( gulp.parallel( 'css', 'js', 'img' ), 'replace_ver', 'pot:lite', 'rename:lite', 'composer:lite', 'zip:lite' ) ); +gulp.task( 'build:pro', gulp.series( gulp.parallel( 'css', 'js', 'img' ), 'replace_ver', 'pot', 'rename:pro', 'composer:pro', 'zip:pro' ) ); gulp.task( 'build:test', gulp.series( 'rename:lite', 'composer:lite', 'zip:lite', 'rename:pro', 'composer:pro', 'zip:pro' ) ); -gulp.task( 'build', gulp.series( gulp.parallel( 'css', 'js', 'img', 'pot' ), 'replace_ver', 'rename:lite', 'composer:lite', 'zip:lite', 'rename:pro', 'composer:pro', 'zip:pro' ) ); +gulp.task( 'build', gulp.series( gulp.parallel( 'css', 'js', 'img' ), 'replace_ver', 'pot', 'rename:lite', 'composer:lite', 'zip:lite', 'rename:pro', 'composer:pro', 'zip:pro' ) ); /** * Look out for relevant sass/js changes. diff --git a/package.json b/package.json index 974761c..204f375 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wp-mail-smtp", - "version": "2.1.1", + "version": "2.2.1", "description": "Reconfigures the wp_mail() function to improve WordPress emails deliverability.", "private": true, "repository": { diff --git a/readme.txt b/readme.txt index af20fb5..eb0001e 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: wpforms, jaredatch, smub, slaFFik Tags: smtp, wp mail smtp, wordpress smtp, gmail smtp, sendgrid smtp, mailgun smtp, mail, mailer, phpmailer, wp_mail, email, mailgun, sengrid, gmail, pepipost, sendinblue, wp smtp Requires at least: 4.9 Tested up to: 5.4 -Stable tag: 2.1.1 +Stable tag: 2.2.1 Requires PHP: 5.5.0 The most popular WordPress SMTP and PHP Mailer plugin. Trusted by over 1 million sites. @@ -229,6 +229,14 @@ By all means please contact us to discuss features or options you'd like to see == Changelog == += 2.2.1 - 2020-07-09 = +* Added: Gmail mailer now supports aliases. +* Added: Support both old PHPMailer v5 (WordPress <=5.4) and PHPMailer v6 (WordPress >=5.5). +* Changed: Pepipost mailer is now using the native API v5 instead of the SendGrid migration API. +* Fixed: Incorrect Mailgun Domain Name option was not showing an email delivery error. +* Fixed: Empty debug errors for the Sendinblue mailer are no more. +* Fixed: Properly compare From Email option value with a correct default email address from WP core. + = 2.1.1 - 2020-06-08 = * Changed: Remove current automatic default reply-to address and add WP filter `wp_mail_smtp_processor_set_default_reply_to` for setting default reply-to addresses. * Changed: Improve description for several options with links to an article about how to properly use constants. diff --git a/src/Admin/Area.php b/src/Admin/Area.php index 7c6f731..ed7260c 100644 --- a/src/Admin/Area.php +++ b/src/Admin/Area.php @@ -271,7 +271,7 @@ public function maybe_redirect_email_log_menu_to_email_log_settings_tab() { * @since 1.5.0 Added new assets for new pages. * @since 1.7.0 Added jQuery Confirm library css/js files. * - * @param string $hook + * @param string $hook Current hook. */ public function enqueue_assets( $hook ) { @@ -305,9 +305,7 @@ public function enqueue_assets( $hook ) { 'title' => esc_html__( 'Heads up!', 'wp-mail-smtp' ), 'content' => wp_kses( __( '

The Default (PHP) mailer is currently selected, but is not recommended because in most cases it does not resolve email delivery issues.

Please consider selecting and configuring one of the other mailers.

', 'wp-mail-smtp' ), - array( - 'p' => true, - ) + [ 'p' => [] ] ), 'save_button' => esc_html__( 'Save Settings', 'wp-mail-smtp' ), 'cancel_button' => esc_html__( 'Cancel', 'wp-mail-smtp' ), @@ -322,11 +320,11 @@ public function enqueue_assets( $hook ) { 'upgrade_bonus' => '

' . wp_kses( __( 'Bonus: WP Mail SMTP users get $50 off regular price,
applied at checkout.', 'wp-mail-smtp' ), - array( - 'strong' => true, - 'span' => true, - 'br' => true, - ) + [ + 'strong' => [], + 'span' => [], + 'br' => [], + ] ) . '

', 'upgrade_doc' => ' @@ -893,7 +891,7 @@ public function get_admin_page_url( $page = '' ) { return add_query_arg( 'page', $page, - admin_url( 'admin.php' ) + WP::admin_url( 'admin.php' ) ); } diff --git a/src/Admin/PageAbstract.php b/src/Admin/PageAbstract.php index b032331..f1cecc8 100644 --- a/src/Admin/PageAbstract.php +++ b/src/Admin/PageAbstract.php @@ -2,6 +2,8 @@ namespace WPMailSMTP\Admin; +use WPMailSMTP\WP; + /** * Class PageAbstract. * @@ -23,7 +25,7 @@ public function get_link() { add_query_arg( 'tab', $this->slug, - admin_url( 'admin.php?page=' . Area::SLUG ) + WP::admin_url( 'admin.php?page=' . Area::SLUG ) ) ); } diff --git a/src/Admin/Pages/About.php b/src/Admin/Pages/About.php index d078692..120e6eb 100644 --- a/src/Admin/Pages/About.php +++ b/src/Admin/Pages/About.php @@ -6,6 +6,7 @@ use WPMailSMTP\Admin\PageAbstract; use WPMailSMTP\Admin\PluginsInstallSkin; use WPMailSMTP\Admin\PluginsInstallUpgrader; +use WPMailSMTP\WP; /** * Class About to display a page with About Us and Versus content. @@ -42,7 +43,7 @@ public function get_link( $tab = '' ) { return add_query_arg( 'tab', $this->get_defined_tab( $tab ), - admin_url( 'admin.php?page=' . Area::SLUG . '-' . $this->slug ) + WP::admin_url( 'admin.php?page=' . Area::SLUG . '-' . $this->slug ) ); } @@ -214,6 +215,24 @@ protected function display_about() { + display_plugins(); + } + + /** + * Display the plugins section. + * + * @since 2.2.0 + */ + protected function display_plugins() { + ?> +
get_about_plugins_data( $plugin, true ) ); } + // Do not display a plugin which has to be installed and the user can't install it. + if ( ! current_user_can( 'install_plugins' ) && $data['status_class'] === 'status-download' ) { + continue; + } + ?>
- + <?php esc_attr_e( 'Plugin icon', 'wp-mail-smtp' ); ?>
@@ -430,7 +454,7 @@ public static function ajax_plugin_install() { $error = \esc_html__( 'Could not install the plugin.', 'wp-mail-smtp' ); // Check for permissions. - if ( ! \current_user_can( 'activate_plugins' ) ) { + if ( ! \current_user_can( 'install_plugins' ) ) { \wp_send_json_error( $error ); } diff --git a/src/Admin/Pages/Logs.php b/src/Admin/Pages/Logs.php index 9910f13..ed3690b 100644 --- a/src/Admin/Pages/Logs.php +++ b/src/Admin/Pages/Logs.php @@ -4,11 +4,10 @@ use WPMailSMTP\Admin\Area; use WPMailSMTP\Admin\PageAbstract; +use WPMailSMTP\WP; /** * Class Logs - * - * @since 1.5.0 */ class Logs extends PageAbstract { @@ -34,7 +33,7 @@ public function get_link() { return add_query_arg( 'tab', $this->slug, - admin_url( 'admin.php?page=' . Area::SLUG ) + WP::admin_url( 'admin.php?page=' . Area::SLUG ) ); } diff --git a/src/Admin/Pages/MiscTab.php b/src/Admin/Pages/MiscTab.php index 799253c..6e563b0 100644 --- a/src/Admin/Pages/MiscTab.php +++ b/src/Admin/Pages/MiscTab.php @@ -198,7 +198,12 @@ class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox wp-mail-smtp-c } /** - * @inheritdoc + * Process tab form submission ($_POST). + * + * @since 1.0.0 + * @since 2.2.0 Fixed checkbox saving and use the correct merge to prevent breaking other 'general' checkboxes. + * + * @param array $data Tab data specific for the plugin ($_POST). */ public function process_post( $data ) { @@ -207,14 +212,20 @@ public function process_post( $data ) { $options = new Options(); // Unchecked checkboxes doesn't exist in $_POST, so we need to ensure we actually have them in data to save. + if ( empty( $data['general']['do_not_send'] ) ) { + $data['general']['do_not_send'] = false; + } if ( empty( $data['general']['am_notifications_hidden'] ) ) { $data['general']['am_notifications_hidden'] = false; } + if ( empty( $data['general']['email_delivery_errors_hidden'] ) ) { + $data['general']['email_delivery_errors_hidden'] = false; + } if ( empty( $data['general']['uninstall'] ) ) { $data['general']['uninstall'] = false; } - $to_save = array_merge( $options->get_all(), $data ); + $to_save = Options::array_merge_recursive( $options->get_all(), $data ); // All the sanitization is done there. $options->set( $to_save ); diff --git a/src/Admin/Pages/SettingsTab.php b/src/Admin/Pages/SettingsTab.php index 0308160..feedf76 100644 --- a/src/Admin/Pages/SettingsTab.php +++ b/src/Admin/Pages/SettingsTab.php @@ -5,6 +5,7 @@ use WPMailSMTP\Admin\PageAbstract; use WPMailSMTP\Debug; use WPMailSMTP\Options; +use WPMailSMTP\Providers\Gmail\Auth; use WPMailSMTP\WP; /** @@ -58,6 +59,8 @@ public function display() {
wp_nonce_field(); ?> + +
@@ -92,16 +95,37 @@ public function display() {
- is_const_defined( 'mail', 'from_email' ) || ! empty( $disabled_email ) ? 'disabled' : ''; ?> - id="wp-mail-smtp-setting-from_email" spellcheck="false" - placeholder="get_processor()->get_default_email() ); ?>"> + + is_const_defined( 'mail', 'from_email' ) || ! empty( $disabled_email ) ? 'disabled' : ''; ?> + id="wp-mail-smtp-setting-from_email" spellcheck="false" + placeholder="get_processor()->get_default_email() ); ?>"> + + is_clients_saved() ? $gmail_auth->get_user_possible_send_from_addresses() : []; + ?> + + + + + + + +


- +

@@ -110,10 +134,16 @@ public function display() {


- get( 'mail', 'from_email_force' ) ); ?> - is_const_defined( 'mail', 'from_email_force' ) || ! empty( $disabled_email ) ? 'disabled' : ''; ?> - id="wp-mail-smtp-setting-from_email_force"> + + get( 'mail', 'from_email_force' ) ); ?> + is_const_defined( 'mail', 'from_email_force' ) || ! empty( $disabled_email ) ? 'disabled' : ''; ?> + id="wp-mail-smtp-setting-from_email_force"> + + +
+ + display_save_btn(); ?> @@ -525,6 +566,8 @@ public function process_post( $data ) { } } + $data = apply_filters( 'wp_mail_smtp_settings_tab_process_post', $data ); + // New gmail clients data will be added from new $data. $to_save = Options::array_merge_recursive( $old_opt, $data ); diff --git a/src/Admin/Pages/TestTab.php b/src/Admin/Pages/TestTab.php index b5faa67..eabc4ec 100644 --- a/src/Admin/Pages/TestTab.php +++ b/src/Admin/Pages/TestTab.php @@ -4,7 +4,7 @@ use WPMailSMTP\Conflicts; use WPMailSMTP\Debug; -use WPMailSMTP\MailCatcher; +use WPMailSMTP\MailCatcherInterface; use WPMailSMTP\Options; use WPMailSMTP\WP; use WPMailSMTP\Admin\PageAbstract; @@ -393,8 +393,8 @@ public static function set_test_html_content_type() { * * @since 1.0.0 * - * @param MailCatcher $phpmailer - * @param string $smtp_debug + * @param MailCatcherInterface $phpmailer The MailCatcher object. + * @param string $smtp_debug The SMTP debug message. * * @return string */ diff --git a/src/Core.php b/src/Core.php index 62ec474..7f5eedd 100644 --- a/src/Core.php +++ b/src/Core.php @@ -59,6 +59,10 @@ public function __construct() { if ( $this->is_not_loadable() ) { add_action( 'admin_notices', 'wp_mail_smtp_insecure_php_version_notice' ); + if ( WP::use_global_plugin_settings() ) { + add_action( 'network_admin_notices', 'wp_mail_smtp_insecure_php_version_notice' ); + } + return; } @@ -95,8 +99,13 @@ protected function is_not_loadable() { */ public function hooks() { + // Force from_email_force to always return true if current mailer is Gmail. + if ( ( new Options() )->get( 'mail', 'mailer' ) === 'gmail' ) { + add_filter( 'wp_mail_smtp_options_get', [ $this, 'gmail_mailer_get_from_email_force' ], 1, 3 ); + } + // Action Scheduler requires a special early loading procedure. - add_action( 'plugins_loaded', array( $this, 'load_action_scheduler' ), -10 ); + add_action( 'plugins_loaded', array( $this, 'load_action_scheduler' ), - 10 ); // Activation hook. register_activation_hook( WPMS_PLUGIN_FILE, array( $this, 'activate' ) ); @@ -148,6 +157,11 @@ public function init() { if ( current_user_can( 'manage_options' ) ) { add_action( 'admin_notices', array( '\WPMailSMTP\WP', 'display_admin_notices' ) ); add_action( 'admin_notices', array( $this, 'display_general_notices' ) ); + + if ( WP::use_global_plugin_settings() ) { + add_action( 'network_admin_notices', array( '\WPMailSMTP\WP', 'display_admin_notices' ) ); + add_action( 'network_admin_notices', array( $this, 'display_general_notices' ) ); + } } } @@ -455,7 +469,6 @@ public static function display_general_notices() { } if ( wp_mail_smtp()->get_admin()->is_error_delivery_notice_enabled() ) { - $notice = Debug::get_last(); if ( ! empty( $notice ) ) { @@ -556,7 +569,7 @@ public function detect_conflicts() { * * @since 1.0.0 * - * @return \WPMailSMTP\MailCatcher + * @return MailCatcherInterface */ public function replace_phpmailer() { @@ -573,11 +586,11 @@ public function replace_phpmailer() { * * @param null $obj PhpMailer object to override with own implementation. * - * @return \WPMailSMTP\MailCatcher + * @return MailCatcherInterface */ protected function replace_w_fake_phpmailer( &$obj = null ) { - $obj = new MailCatcher( true ); + $obj = $this->generate_mail_catcher( true ); return $obj; } @@ -725,7 +738,7 @@ public function is_white_labeled() { /** * Require the action scheduler in an early plugins_loaded hook (-10). * - * @see https://actionscheduler.org/usage/#load-order + * @see https://actionscheduler.org/usage/#load-order * * @since 2.1.0 */ @@ -733,4 +746,99 @@ public function load_action_scheduler() { require_once $this->plugin_path . '/vendor/woocommerce/action-scheduler/action-scheduler.php'; } + + /** + * Get the list of all custom DB tables that should be present in the DB. + * + * @since 2.1.2 + * + * @return array List of table names. + */ + public function get_custom_db_tables() { + + $tables = [ + \WPMailSMTP\Tasks\Meta::get_table_name(), + ]; + + return apply_filters( 'wp_mail_smtp_core_get_custom_db_tables', $tables ); + } + + /** + * Generate the correct MailCatcher object based on the PHPMailer version used in WP. + * + * Also conditionally require the needed class files. + * + * @see https://make.wordpress.org/core/2020/07/01/external-library-updates-in-wordpress-5-5-call-for-testing/ + * + * @since 2.2.0 + * + * @param bool $exceptions True if external exceptions should be thrown. + * + * @return MailCatcherInterface + */ + public function generate_mail_catcher( $exceptions = null ) { + + if ( version_compare( get_bloginfo( 'version' ), '5.5-alpha', '<' ) ) { + if ( ! class_exists( '\PHPMailer', false ) ) { + require_once ABSPATH . WPINC . '/class-phpmailer.php'; + } + + $mail_catcher = new MailCatcher( $exceptions ); + } else { + if ( ! class_exists( '\PHPMailer\PHPMailer\PHPMailer', false ) ) { + require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php'; + } + + if ( ! class_exists( '\PHPMailer\PHPMailer\Exception', false ) ) { + require_once ABSPATH . WPINC . '/PHPMailer/Exception.php'; + } + + if ( ! class_exists( '\PHPMailer\PHPMailer\SMTP', false ) ) { + require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php'; + } + + $mail_catcher = new MailCatcherV6( $exceptions ); + } + + return $mail_catcher; + } + + /** + * Check if the passed object is a valid PHPMailer object. + * + * @since 2.2.0 + * + * @param object $phpmailer A potential PHPMailer object to be tested. + * + * @return bool + */ + public function is_valid_phpmailer( $phpmailer ) { + + return $phpmailer instanceof MailCatcherInterface || + $phpmailer instanceof \PHPMailer || + $phpmailer instanceof \PHPMailer\PHPMailer\PHPMailer; + } + + /** + * Force the `mail.from_email_force` plugin option to always return true if the current saved mailer is Gmail. + * Alters the plugin options retrieving via the Options::get method. + * + * The gmail mailer check is performed when this filter is added. + * + * @since 2.2.0 + * + * @param mixed $value The value of the plugin option that is being retrieved via Options::get method. + * @param string $group The group of the plugin option that is being retrieved via Options::get method. + * @param string $key The key of the plugin option that is being retrieved via Options::get method. + * + * @return mixed + */ + public function gmail_mailer_get_from_email_force( $value, $group, $key ) { + + if ( $group === 'mail' && $key === 'from_email_force' ) { + $value = true; + } + + return $value; + } } diff --git a/src/MailCatcher.php b/src/MailCatcher.php index 9778fe7..4706646 100644 --- a/src/MailCatcher.php +++ b/src/MailCatcher.php @@ -13,7 +13,7 @@ * * @since 1.0.0 */ -class MailCatcher extends \PHPMailer { +class MailCatcher extends \PHPMailer implements MailCatcherInterface { /** * Callback Action function name. @@ -77,6 +77,9 @@ public function send() { $mail_mailer === 'pepipost' ) { try { + // Allow to hook early to catch any early failed emails. + do_action( 'wp_mail_smtp_mailcatcher_smtp_pre_send_before', $this ); + // Prepare all the headers. if ( ! $this->preSend() ) { return false; @@ -151,4 +154,16 @@ public function getCustomHeaders() { return $this->CustomHeader; } + + /** + * Get the PHPMailer line ending. + * + * @since 2.2.0 + * + * @return string + */ + public function get_line_ending() { + + return $this->LE; // phpcs:ignore + } } diff --git a/src/MailCatcherInterface.php b/src/MailCatcherInterface.php new file mode 100644 index 0000000..653c804 --- /dev/null +++ b/src/MailCatcherInterface.php @@ -0,0 +1,33 @@ +get( 'mail', 'mailer' ) ); + + $is_emailing_blocked = false; + + if ( wp_mail_smtp()->is_blocked() ) { + $is_emailing_blocked = true; + } + + // Always allow a test email - check for the specific header. + foreach ( (array) $this->getCustomHeaders() as $header ) { + if ( + ! empty( $header[0] ) && + ! empty( $header[1] ) && + $header[0] === 'X-Mailer-Type' && + trim( $header[1] ) === 'WPMailSMTP/Admin/Test' + ) { + $is_emailing_blocked = false; + } + }; + + // Do not send emails if admin desired that. + if ( $is_emailing_blocked ) { + return false; + } + + // Define a custom header, that will be used to identify the plugin and the mailer. + $this->XMailer = 'WPMailSMTP/Mailer/' . $mail_mailer . ' ' . WPMS_PLUGIN_VER; // phpcs:ignore + + // Use the default PHPMailer, as we inject our settings there for certain providers. + if ( + $mail_mailer === 'mail' || + $mail_mailer === 'smtp' || + $mail_mailer === 'pepipost' + ) { + try { + // Allow to hook early to catch any early failed emails. + do_action( 'wp_mail_smtp_mailcatcher_smtp_pre_send_before', $this ); + + // Prepare all the headers. + if ( ! $this->preSend() ) { + return false; + } + + // Allow to hook after all the preparation before the actual sending. + do_action( 'wp_mail_smtp_mailcatcher_smtp_send_before', $this ); + + return $this->postSend(); + } catch ( \PHPMailer\PHPMailer\Exception $e ) { + $this->mailHeader = ''; // phpcs:ignore + $this->setError( $e->getMessage() ); + + // Set the debug error, but not for default PHP mailer. + if ( $mail_mailer !== 'mail' ) { + Debug::set( + 'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( $mail_mailer )->get_title() ) . PHP_EOL . + $e->getMessage() + ); + } + + if ( $this->exceptions ) { + throw $e; + } + + return false; + } + } + + // We need this so that the PHPMailer class will correctly prepare all the headers. + $this->Mailer = 'mail'; // phpcs:ignore + + // Prepare everything (including the message) for sending. + if ( ! $this->preSend() ) { + return false; + } + + $mailer = wp_mail_smtp()->get_providers()->get_mailer( $mail_mailer, $this ); + + if ( ! $mailer ) { + return false; + } + + if ( ! $mailer->is_php_compatible() ) { + return false; + } + + /* + * Send the actual email. + * We reuse everything, that was preprocessed for usage in PHPMailer. + */ + $mailer->send(); + + $is_sent = $mailer->is_email_sent(); + + // Allow to perform any actions with the data. + do_action( 'wp_mail_smtp_mailcatcher_send_after', $mailer, $this ); + + return $is_sent; + } + + /** + * Get the PHPMailer line ending. + * + * @since 2.2.0 + * + * @return string + */ + public function get_line_ending() { + + return static::$LE; // phpcs:ignore + } +} diff --git a/src/Options.php b/src/Options.php index b39e191..555496a 100644 --- a/src/Options.php +++ b/src/Options.php @@ -170,9 +170,11 @@ public static function get_defaults() { * Retrieve all options of the plugin. * * @since 1.0.0 + * @since 2.2.0 Added the filter. */ protected function populate_options() { - $this->_options = get_option( self::META_KEY, array() ); + + $this->_options = apply_filters( 'wp_mail_smtp_populate_options', get_option( self::META_KEY, [] ) ); } /** diff --git a/src/Processor.php b/src/Processor.php index 9c99591..ce4c0a1 100644 --- a/src/Processor.php +++ b/src/Processor.php @@ -146,28 +146,19 @@ protected function allow_setting_original_from_email_to_reply_to( $reply_to, $ma $forced = $options->get( 'mail', 'from_email_force' ); $from_email = $options->get( 'mail', 'from_email' ); - if ( ! empty( $reply_to ) ) { + if ( ! empty( $reply_to ) || empty( $this->wp_mail_from ) ) { return false; } - if ( in_array( $mailer, array( 'gmail', 'outlook' ), true ) ) { + if ( $mailer === 'gmail' ) { $forced = true; - - switch ( $mailer ) { - case 'gmail': - $sender = wp_mail_smtp()->get_providers()->get_auth( 'gmail' )->get_user_info(); - break; - - case 'outlook': - $sender = $options->get( 'outlook', 'user_details' ); - break; - } - + } elseif ( $mailer === 'outlook' ) { + $sender = $options->get( 'outlook', 'user_details' ); $from_email = ! empty( $sender['email'] ) ? $sender['email'] : ''; + $forced = true; } if ( - empty( $this->wp_mail_from ) || $from_email === $this->wp_mail_from || ! $forced ) { @@ -213,7 +204,7 @@ public static function send_callback( $is_sent, $to, $cc, $bcc, $subject, $body, * @since 1.3.0 Forcing email rewrite if option is selected. * @since 1.7.0 Default email may be empty, so pay attention to that as well. * - * @param string $wp_email + * @param string $wp_email The email address passed by the filter. * * @return string */ @@ -222,11 +213,11 @@ public function filter_mail_from_email( $wp_email ) { $options = new Options(); $forced = $options->get( 'mail', 'from_email_force' ); $from_email = $options->get( 'mail', 'from_email' ); - $def_email = $this->get_default_email(); + $def_email = WP::get_default_email(); // Save the "original" set WP email from address for later use. if ( $wp_email !== $def_email ) { - $this->wp_mail_from = $wp_email; + $this->wp_mail_from = filter_var( $wp_email, FILTER_VALIDATE_EMAIL ); } // Return FROM EMAIL if forced in settings. @@ -308,7 +299,7 @@ public function get_default_name() { * * @since 1.9.0 * - * @return \WPMailSMTP\MailCatcher + * @return MailCatcherInterface */ public function get_phpmailer() { @@ -316,8 +307,7 @@ public function get_phpmailer() { // Make sure the PHPMailer class has been instantiated. if ( ! is_object( $phpmailer ) || ! is_a( $phpmailer, 'PHPMailer' ) ) { - require_once ABSPATH . WPINC . '/class-phpmailer.php'; - $phpmailer = new MailCatcher( true ); // phpcs:ignore + $phpmailer = wp_mail_smtp()->generate_mail_catcher( true ); // phpcs:ignore } return $phpmailer; @@ -330,7 +320,7 @@ public function get_phpmailer() { * * @since 2.1.1 * - * @param \PHPMailer $phpmailer The PHPMailer object. + * @param MailCatcherInterface $phpmailer The PHPMailer object. */ private function set_default_reply_to( $phpmailer ) { diff --git a/src/Providers/Gmail/Auth.php b/src/Providers/Gmail/Auth.php index f5f26ac..fb674e0 100644 --- a/src/Providers/Gmail/Auth.php +++ b/src/Providers/Gmail/Auth.php @@ -14,6 +14,15 @@ */ class Auth extends AuthAbstract { + /** + * List of all possible "from email" email addresses (aliases). + * + * @since 2.2.0 + * + * @var null|array + */ + private $aliases = null; + /** * Auth constructor. * @@ -47,12 +56,15 @@ public function __construct() { */ public static function get_plugin_auth_url() { - return add_query_arg( - array( - 'page' => Area::SLUG, - 'tab' => 'auth', - ), - admin_url( 'options-general.php' ) + return apply_filters( + 'wp_mail_smtp_gmail_get_plugin_auth_url', + add_query_arg( + array( + 'page' => Area::SLUG, + 'tab' => 'auth', + ), + admin_url( 'options-general.php' ) + ) ); } @@ -280,4 +292,40 @@ public function get_user_info() { return array( 'email' => $email ); } + + /** + * Get the registered email addresses that the user can use as the "from email". + * + * @since 2.2.0 + * + * @return array The list of possible from email addresses. + */ + public function get_user_possible_send_from_addresses() { + + if ( isset( $this->aliases ) ) { + return $this->aliases; + } + + $gmail = new \Google_Service_Gmail( $this->get_client() ); + + try { + $response = $gmail->users_settings_sendAs->listUsersSettingsSendAs( 'me' ); // phpcs:ignore + + // phpcs:disable + if ( isset( $response->sendAs ) ) { + $this->aliases = array_map( + function( $sendAsObject ) { + return $sendAsObject->sendAsEmail; + }, + $response->sendAs + ); + } + // phpcs:enable + + } catch ( \Exception $exception ) { + $this->aliases = []; + } + + return $this->aliases; + } } diff --git a/src/Providers/Gmail/Mailer.php b/src/Providers/Gmail/Mailer.php index 5fb87da..b3fcb23 100644 --- a/src/Providers/Gmail/Mailer.php +++ b/src/Providers/Gmail/Mailer.php @@ -3,7 +3,7 @@ namespace WPMailSMTP\Providers\Gmail; use WPMailSMTP\Debug; -use WPMailSMTP\MailCatcher; +use WPMailSMTP\MailCatcherInterface; use WPMailSMTP\Providers\MailerAbstract; /** @@ -37,10 +37,11 @@ class Mailer extends MailerAbstract { * * @since 1.0.0 * - * @param \WPMailSMTP\MailCatcher $phpmailer + * @param MailCatcherInterface $phpmailer The MailCatcher object. */ public function __construct( $phpmailer ) { - parent::__construct( $phpmailer ); + + parent::__construct( $phpmailer ); if ( ! $this->is_php_compatible() ) { return; @@ -52,14 +53,12 @@ public function __construct( $phpmailer ) { * * @since 1.2.0 * - * @param \WPMailSMTP\MailCatcher $phpmailer + * @param MailCatcherInterface $phpmailer The MailCatcher object. */ public function process_phpmailer( $phpmailer ) { - // Make sure that we have access to MailCatcher class methods. - if ( - ! $phpmailer instanceof MailCatcher && - ! $phpmailer instanceof \PHPMailer - ) { + + // Make sure that we have access to PHPMailer class methods. + if ( ! wp_mail_smtp()->is_valid_phpmailer( $phpmailer ) ) { return; } @@ -79,25 +78,23 @@ public function send() { $auth = new Auth(); $message = new \Google_Service_Gmail_Message(); - /* - * Right now Gmail doesn't allow to redefine From and Sender email headers. - * It always uses the email address that was used to connect to its API. - * With code below we are making sure that Email Log archive and single Email Log - * have the save value for From email header. - */ - $gmail_creds = $auth->get_user_info(); - - if ( ! empty( $gmail_creds['email'] ) ) { - $this->phpmailer->From = $gmail_creds['email']; - $this->phpmailer->Sender = $gmail_creds['email']; + // Set the authorized Gmail email address as the "from email" if the set email is not on the list of aliases. + $possible_from_emails = $auth->get_user_possible_send_from_addresses(); + + if ( ! in_array( $this->phpmailer->From, $possible_from_emails, true ) ) { + $user_info = $auth->get_user_info(); + + if ( ! empty( $user_info['email'] ) ) { + $this->phpmailer->From = $user_info['email']; + $this->phpmailer->Sender = $user_info['email']; + } } try { - // Prepare a message for sending. + // Prepare a message for sending if any changes happened above. $this->phpmailer->preSend(); - // Get the raw MIME email using MailCatcher data. - // We need here to make base64URL-safe string. + // Get the raw MIME email using MailCatcher data. We need to make base64URL-safe string. $base64 = str_replace( [ '+', '/', '=' ], [ '-', '_', '' ], diff --git a/src/Providers/Gmail/Options.php b/src/Providers/Gmail/Options.php index e001e65..791e8f7 100644 --- a/src/Providers/Gmail/Options.php +++ b/src/Providers/Gmail/Options.php @@ -180,6 +180,23 @@ protected function display_auth_setting_action() { } ?> +

+ Follow these instructions and then select the From Email at the top of this page.', 'wp-mail-smtp' ), + [ + 'a' => [ + 'href' => [], + 'rel' => [], + 'target' => [], + ], + ] + ), + 'https://support.google.com/a/answer/33327' + ); + ?> +

diff --git a/src/Providers/Loader.php b/src/Providers/Loader.php index 506af82..154c9fc 100644 --- a/src/Providers/Loader.php +++ b/src/Providers/Loader.php @@ -3,7 +3,7 @@ namespace WPMailSMTP\Providers; use WPMailSMTP\Debug; -use WPMailSMTP\MailCatcher; +use WPMailSMTP\MailCatcherInterface; use WPMailSMTP\Options; /** @@ -39,7 +39,7 @@ class Loader { /** * @since 1.0.0 * - * @var MailCatcher + * @var MailCatcherInterface */ private $phpmailer; @@ -132,17 +132,14 @@ public function get_options_all() { * * @since 1.0.0 * - * @param string $provider The provider name. - * @param MailCatcher|\PHPMailer $phpmailer The MailCatcher object. + * @param string $provider The provider name. + * @param MailCatcherInterface $phpmailer The MailCatcher object. * * @return MailerAbstract|null */ public function get_mailer( $provider, $phpmailer ) { - if ( - $phpmailer instanceof MailCatcher || - $phpmailer instanceof \PHPMailer - ) { + if ( wp_mail_smtp()->is_valid_phpmailer( $phpmailer ) ) { $this->phpmailer = $phpmailer; } diff --git a/src/Providers/MailerAbstract.php b/src/Providers/MailerAbstract.php index b0e2441..9d58402 100644 --- a/src/Providers/MailerAbstract.php +++ b/src/Providers/MailerAbstract.php @@ -4,7 +4,7 @@ use WPMailSMTP\Conflicts; use WPMailSMTP\Debug; -use WPMailSMTP\MailCatcher; +use WPMailSMTP\MailCatcherInterface; use WPMailSMTP\Options; use WPMailSMTP\WP; @@ -32,7 +32,7 @@ abstract class MailerAbstract implements MailerInterface { /** * @since 1.0.0 * - * @var MailCatcher + * @var MailCatcherInterface */ protected $phpmailer; /** @@ -74,9 +74,9 @@ abstract class MailerAbstract implements MailerInterface { * * @since 1.0.0 * - * @param MailCatcher $phpmailer + * @param MailCatcherInterface $phpmailer The MailCatcher object. */ - public function __construct( MailCatcher $phpmailer ) { + public function __construct( MailCatcherInterface $phpmailer ) { $this->options = new Options(); $this->mailer = $this->options->get( 'mail', 'mailer' ); @@ -94,15 +94,12 @@ public function __construct( MailCatcher $phpmailer ) { * * @since 1.0.0 * - * @param MailCatcher $phpmailer + * @param MailCatcherInterface $phpmailer The MailCatcher object. */ public function process_phpmailer( $phpmailer ) { - // Make sure that we have access to MailCatcher class methods. - if ( - ! $phpmailer instanceof MailCatcher && - ! $phpmailer instanceof \PHPMailer - ) { + // Make sure that we have access to PHPMailer class methods. + if ( ! wp_mail_smtp()->is_valid_phpmailer( $phpmailer ) ) { return; } diff --git a/src/Providers/MailerInterface.php b/src/Providers/MailerInterface.php index 922ae36..6205b4d 100644 --- a/src/Providers/MailerInterface.php +++ b/src/Providers/MailerInterface.php @@ -2,6 +2,9 @@ namespace WPMailSMTP\Providers; +use WPMailSMTP\MailCatcher; +use WPMailSMTP\MailCatcherV6; + /** * Interface MailerInterface. * @@ -77,7 +80,7 @@ public function get_debug_info(); * * @since 1.2.0 * - * @param \WPMailSMTP\MailCatcher $phpmailer + * @param MailCatcherInterface $phpmailer The MailCatcher object. */ public function process_phpmailer( $phpmailer ); } diff --git a/src/Providers/Mailgun/Mailer.php b/src/Providers/Mailgun/Mailer.php index ffa2767..cc28617 100644 --- a/src/Providers/Mailgun/Mailer.php +++ b/src/Providers/Mailgun/Mailer.php @@ -2,6 +2,7 @@ namespace WPMailSMTP\Providers\Mailgun; +use WPMailSMTP\Debug; use WPMailSMTP\Providers\MailerAbstract; use WPMailSMTP\WP; @@ -56,7 +57,7 @@ public function __construct( $phpmailer ) { // Default value should be defined before the parent class contructor fires. $this->url = self::API_BASE_US; - // We want to prefill everything from \WPMailSMTP\MailCatcher class, which extends \PHPMailer. + // We want to prefill everything from MailCatcher class, which extends PHPMailer. parent::__construct( $phpmailer ); // We have a special API URL to query in case of EU region. @@ -366,6 +367,40 @@ public function set_return_path( $email ) { ); } + /** + * Whether the email is sent or not. + * We basically check the response code from a request to provider. + * Might not be 100% correct, not guarantees that email is delivered. + * + * In Mailgun's case it looks like we have to check if the response body has the message ID. + * All successful API responses should have `id` key in the response body. + * + * @since 2.2.0 + * + * @return bool + */ + public function is_email_sent() { + + $is_sent = parent::is_email_sent(); + + if ( + $is_sent && + isset( $this->response['body'] ) && + ! array_key_exists( 'id', (array) $this->response['body'] ) + ) { + $message = 'Mailer: Mailgun' . PHP_EOL . + esc_html__( 'Mailgun API request was successful, but it could not queue the email for delivery.', 'wp-mail-smtp' ) . PHP_EOL . + esc_html__( 'This could point to an incorrect Domain Name in the plugin settings.', 'wp-mail-smtp' ) . PHP_EOL . + esc_html__( 'Please check the WP Mail SMTP plugin settings and make sure the Mailgun Domain Name setting is correct.', 'wp-mail-smtp' ); + + Debug::set( $message ); + + return false; + } + + return $is_sent; + } + /** * Get a Mailgun-specific response with a helpful error. * diff --git a/src/Providers/PepipostAPI/Mailer.php b/src/Providers/PepipostAPI/Mailer.php index b5b919b..9e562a4 100644 --- a/src/Providers/PepipostAPI/Mailer.php +++ b/src/Providers/PepipostAPI/Mailer.php @@ -2,14 +2,16 @@ namespace WPMailSMTP\Providers\PepipostAPI; +use WPMailSMTP\MailCatcherInterface; +use WPMailSMTP\Options as PluginOptions; use WPMailSMTP\Providers\MailerAbstract; use WPMailSMTP\WP; /** - * Class Mailer is basically a Sendgrid copy-paste, as Pepipost support SG migration. - * In the future we may rewrite the class to use the native Pepipost API. + * Pepipost API mailer. * - * @since 1.8.0 + * @since 1.8.0 Pepipost - SendGrid migration API. + * @since 2.2.0 Rewrote this class to use native Pepipost API. */ class Mailer extends MailerAbstract { @@ -26,24 +28,26 @@ class Mailer extends MailerAbstract { * URL to make an API request to. * * @since 1.8.0 + * @since 2.2.0 Changed the API url to Pepipost API v5. * * @var string */ - protected $url = 'https://sgapi.pepipost.com/v3/mail/send'; + protected $url = 'https://api.pepipost.com/v5/mail/send'; /** * Mailer constructor. * * @since 1.8.0 + * @since 2.2.0 Changed the API key header (API v5 changes). * - * @param \WPMailSMTP\MailCatcher $phpmailer + * @param MailCatcherInterface $phpmailer The MailCatcher instance. */ public function __construct( $phpmailer ) { - // We want to prefill everything from \WPMailSMTP\MailCatcher class, which extends \PHPMailer. + // We want to prefill everything from MailCatcher class, which extends PHPMailer. parent::__construct( $phpmailer ); - $this->set_header( 'Authorization', 'Bearer ' . $this->options->get( $this->mailer, 'api_key' ) ); + $this->set_header( 'api_key', $this->options->get( $this->mailer, 'api_key' ) ); $this->set_header( 'content-type', 'application/json' ); } @@ -67,6 +71,7 @@ public function get_body() { * Set the FROM header of the email. * * @since 1.8.0 + * @since 2.2.0 Changed the attribute names (API v5 changes). * * @param string $email From mail. * @param string $name From name. @@ -84,9 +89,9 @@ public function set_from( $email, $name = '' ) { } $this->set_body_param( - array( + [ 'from' => $from, - ) + ] ); } @@ -94,6 +99,7 @@ public function set_from( $email, $name = '' ) { * Set the names/emails of people who will receive the email. * * @since 1.8.0 + * @since 2.2.0 change the attribute names (API v5 changes). * * @param array $recipients List of recipients: cc/bcc/to. */ @@ -103,62 +109,29 @@ public function set_recipients( $recipients ) { return; } - // Allow for now only these recipient types. - $default = array( 'to', 'cc', 'bcc' ); - $data = array(); + $data = []; - foreach ( $recipients as $type => $emails ) { - if ( - ! in_array( $type, $default, true ) || - empty( $emails ) || - ! is_array( $emails ) - ) { - continue; - } - - $data[ $type ] = array(); - - // Iterate over all emails for each type. - // There might be multiple cc/to/bcc emails. - foreach ( $emails as $email ) { - $holder = array(); - $addr = isset( $email[0] ) ? $email[0] : false; - $name = isset( $email[1] ) ? $email[1] : false; - - if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) { - continue; - } - - $holder['email'] = $addr; - if ( ! empty( $name ) ) { - $holder['name'] = $name; - } - - array_push( $data[ $type ], $holder ); - } + if ( ! empty( $recipients['to'] ) ) { + $data['to'] = $this->prepare_list_of_to_emails( $recipients['to'] ); } - if ( ! empty( $data ) ) { - $this->set_body_param( - array( - 'personalizations' => array( $data ), - ) - ); + if ( ! empty( $recipients['cc'] ) ) { + $data['cc'] = $this->prepare_list_of_emails( $recipients['cc'] ); + } - if ( ! empty( $data['bcc'] ) ) { - // Only the 1st BCC email address, ignore the rest - is not supported by Pepipost. - $bcc['mail_settings']['bcc']['email'] = $data['bcc'][0]['email']; - $this->set_body_param( - $bcc - ); - } + if ( ! empty( $recipients['bcc'] ) ) { + $data['bcc'] = $this->prepare_list_of_emails( $recipients['bcc'] ); } + + $this->set_body_personalizations( $data ); } /** * Set the email content. + * Pepipost API only supports HTML emails, so we have to replace new lines in plain text emails with
. * * @since 1.8.0 + * @since 2.2.0 Change the way the content is prepared (API v5 changes). * * @param array|string $content Email content. */ @@ -168,117 +141,100 @@ public function set_content( $content ) { return; } - if ( is_array( $content ) ) { - - $default = array( 'text', 'html' ); - $data = array(); - - foreach ( $content as $type => $body ) { - if ( - ! in_array( $type, $default, true ) || - empty( $body ) - ) { - continue; - } - - $content_type = 'text/plain'; - $content_value = $body; + $html = ''; - if ( $type === 'html' ) { - $content_type = 'text/html'; - } else { - $content_value = nl2br( $content_value ); - } + if ( ! is_array( $content ) ) { + $html = $content; - $data[] = array( - 'type' => $content_type, - 'value' => $content_value, - ); + if ( $this->phpmailer->ContentType === 'text/plain' ) { + $html = nl2br( $html ); } - - $this->set_body_param( - array( - 'content' => $data, - ) - ); } else { - $data['type'] = 'text/html'; - $data['value'] = $content; - if ( $this->phpmailer->ContentType === 'text/plain' ) { - $data['type'] = 'text/plain'; - $data['value'] = nl2br( $data['value'] ); + if ( ! empty( $content['html'] ) ) { + $html = $content['html']; + } elseif ( ! empty( $content['text'] ) ) { + $html = nl2br( $content['text'] ); } - - $this->set_body_param( - array( - 'content' => array( $data ), - ) - ); } + + $this->set_body_param( + [ + 'content' => [ + [ + 'type' => 'html', + 'value' => $html, + ], + ], + ] + ); } /** - * Redefine the way custom headers are processed for this mailer - they should be in body. + * Redefine the way custom headers are processed for this mailer - they should be in body (personalizations). * * @since 1.8.0 + * @since 2.2.0 Change the way the headers are processed (API v5 changes). * - * @param array $headers + * @param array $headers The email headers to be applied. */ public function set_headers( $headers ) { + $valid_headers = []; + foreach ( $headers as $header ) { $name = isset( $header[0] ) ? $header[0] : false; $value = isset( $header[1] ) ? $header[1] : false; - $this->set_body_header( $name, $value ); + $valid_headers[ $name ] = WP::sanitize_value( $value ); } // Add custom PHPMailer-specific header. - $this->set_body_header( 'X-Mailer', 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER ); + $valid_headers['X-Mailer'] = WP::sanitize_value( 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER ); + + if ( ! empty( $valid_headers ) ) { + $this->set_body_personalizations( [ 'headers' => $valid_headers ] ); + } } /** - * This mailer supports email-related custom headers inside a body of the message. + * Pepipost API accepts an array of files content in body, so we will include all files and send. + * Doesn't handle exceeding the limits etc, as this will be reported by the API response. * * @since 1.8.0 + * @since 2.2.0 Change the way the attachments are processed (API v5 changes). * - * @param string $name - * @param string $value + * @param array $attachments The list of attachments data. */ - public function set_body_header( $name, $value ) { + public function set_attachments( $attachments ) { - $name = sanitize_text_field( $name ); - if ( empty( $name ) ) { + if ( empty( $attachments ) ) { return; } - $headers = isset( $this->body['headers'] ) ? (array) $this->body['headers'] : array(); - - $headers[ $name ] = WP::sanitize_value( $value ); + $data = $this->prepare_attachments( $attachments ); - $this->set_body_param( - array( - 'headers' => $headers, - ) - ); + if ( ! empty( $data ) ) { + $this->set_body_param( + [ + 'attachments' => $data, + ] + ); + } } /** - * Pepipost accepts an array of files content in body, so we will include all files and send. - * Doesn't handle exceeding the limits etc, as this is done and reported by SendGrid API. + * Prepare the attachments data for Pepipost API. * - * @since 1.8.0 + * @since 2.2.0 + * + * @param array $attachments Array of attachments. * - * @param array $attachments + * @return array */ - public function set_attachments( $attachments ) { - - if ( empty( $attachments ) ) { - return; - } + protected function prepare_attachments( $attachments ) { - $data = array(); + $data = []; foreach ( $attachments as $attachment ) { $file = false; @@ -291,8 +247,7 @@ public function set_attachments( $attachments ) { if ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) { $file = file_get_contents( $attachment[0] ); // phpcs:ignore } - } - catch ( \Exception $e ) { + } catch ( \Exception $e ) { $file = false; } @@ -300,27 +255,21 @@ public function set_attachments( $attachments ) { continue; } - $data[] = array( - 'content' => base64_encode( $file ), - 'type' => $attachment[4], - 'filename' => $attachment[2], - 'disposition' => $attachment[6], - ); + $data[] = [ + 'content' => base64_encode( $file ), // phpcs:ignore + 'name' => $attachment[2], + ]; } - if ( ! empty( $data ) ) { - $this->set_body_param( - array( - 'attachments' => $data, - ) - ); - } + return $data; } /** * Set the reply-to property of the email. + * Pepipost API only supports one reply_to email, so we take the first one and discard the rest. * * @since 1.8.0 + * @since 2.2.0 Change the way the reply_to is processed (API v5 changes). * * @param array $reply_to Name/email for reply-to feature. */ @@ -330,54 +279,44 @@ public function set_reply_to( $reply_to ) { return; } - $data = array(); + $email_array = array_shift( $reply_to ); - foreach ( $reply_to as $key => $emails ) { - if ( - empty( $emails ) || - ! is_array( $emails ) - ) { - continue; - } - - $addr = isset( $emails[0] ) ? $emails[0] : false; - $name = isset( $emails[1] ) ? $emails[1] : false; + if ( empty( $email_array[0] ) ) { + return; + } - if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) { - continue; - } + $email = $email_array[0]; - $data['email'] = $addr; - if ( ! empty( $name ) ) { - $data['name'] = $name; - } + if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) { + return; } - if ( ! empty( $data ) ) { + if ( ! empty( $email ) ) { $this->set_body_param( - array( - 'reply_to' => $data, - ) + [ + 'reply_to' => $email, + ] ); } } /** - * Pepipost doesn't support sender or return_path params. + * Pepipost API doesn't support sender or return_path params. * So we do nothing. * * @since 1.8.0 * - * @param string $from_email + * @param string $from_email The from email address. */ public function set_return_path( $from_email ) {} /** * Get a Pepipost-specific response with a helpful error. * - * @see https://developers.pepipost.com/migration-api/new-subpage/errorcodes + * @see https://developers.pepipost.com/email-api/email-api/sendemail#responses * * @since 1.8.0 + * @since 2.2.0 Change the way the response error message is processed (API v5 changes). * * @return string */ @@ -385,27 +324,26 @@ protected function get_response_error() { $body = (array) wp_remote_retrieve_body( $this->response ); - $error_text = array(); - - if ( ! empty( $body['errors'] ) ) { - foreach ( $body['errors'] as $error ) { - if ( property_exists( $error, 'message' ) ) { - // Prepare additional information from SendGrid API. - $extra = ''; - if ( property_exists( $error, 'field' ) && ! empty( $error->field ) ) { - $extra .= $error->field . '; '; - } - if ( property_exists( $error, 'help' ) && ! empty( $error->help ) ) { - $extra .= $error->help; - } - - // Assign both the main message and perhaps extra information, if exists. - $error_text[] = $error->message . ( ! empty( $extra ) ? ' - ' . $extra : '' ); - } + $error = ! empty( $body['error'] ) ? $body['error'] : ''; + $info = ! empty( $body['info'] ) ? $body['info'] : ''; + $message = ''; + + if ( is_string( $error ) ) { + $message = $error . ( ( ! empty( $info ) ) ? ' - ' . $info : '' ); + } elseif ( is_array( $error ) ) { + $message = ''; + + foreach ( $error as $item ) { + $message .= sprintf( + '%1$s (%2$s - %3$s)', + ! empty( $item->description ) ? $item->description : esc_html__( 'General error', 'wp-mail-smtp' ), + ! empty( $item->message ) ? $item->message : esc_html__( 'Error', 'wp-mail-smtp' ), + ! empty( $item->field ) ? $item->field : '' + ) . PHP_EOL; } } - return implode( '
', array_map( 'esc_textarea', $error_text ) ); + return $message; } /** @@ -440,4 +378,98 @@ public function is_mailer_complete() { return false; } + + /** + * A special set method for Pepipost API "personalizations" attribute. + * We are sending one email at a time, so we should set just the first + * personalization item. + * + * Mainly used in set_headers and set_recipients. + * + * @see https://developers.pepipost.com/email-api/email-api/sendemail + * + * @since 2.2.0 + * + * @param array $data The personalizations array of data (array of arrays). + */ + private function set_body_personalizations( $data ) { + + if ( empty( $data ) ) { + return; + } + + if ( ! empty( $this->body['personalizations'][0] ) ) { + $this->body['personalizations'][0] = PluginOptions::array_merge_recursive( + $this->body['personalizations'][0], + $data + ); + } else { + $this->set_body_param( + [ + 'personalizations' => [ + $data, + ], + ] + ); + } + } + + /** + * Prepare list of emails by filtering valid emails first. + * + * @since 2.2.0 + * + * @param array $items A 2D array of email and name pair items (0 = email, 1 = name). + * + * @return array 2D array with 'email' keys. + */ + private function prepare_list_of_emails( $items ) { + + $valid_emails = array_filter( + array_column( $items, 0 ), + function ( $email ) { + return filter_var( $email, FILTER_VALIDATE_EMAIL ); + } + ); + + return array_map( + function( $email ) { + return [ 'email' => $email ]; + }, + $valid_emails + ); + } + + /** + * Prepare list of TO emails by filtering valid emails first + * and returning array of arrays (email, name). + * + * @since 2.2.0 + * + * @param array $items A 2D array of email and name pair items (0 = email, 1 = name). + * + * @return array 2D array with 'email' and optional 'name' attributes. + */ + private function prepare_list_of_to_emails( $items ) { + + $data = []; + + foreach ( $items as $item ) { + $email = filter_var( $item[0], FILTER_VALIDATE_EMAIL ); + + if ( empty( $email ) ) { + continue; + } + + $pair['email'] = $email; + + if ( ! empty( $item[1] ) ) { + $pair['name'] = $item[1]; + } + + $data[] = $pair; + } + + return $data; + } } diff --git a/src/Providers/SMTPcom/Mailer.php b/src/Providers/SMTPcom/Mailer.php index 29f81e3..f5c1b2c 100644 --- a/src/Providers/SMTPcom/Mailer.php +++ b/src/Providers/SMTPcom/Mailer.php @@ -2,6 +2,7 @@ namespace WPMailSMTP\Providers\SMTPcom; +use WPMailSMTP\MailCatcherInterface; use WPMailSMTP\Providers\MailerAbstract; use WPMailSMTP\WP; @@ -37,11 +38,11 @@ class Mailer extends MailerAbstract { * * @since 2.0.0 * - * @param \WPMailSMTP\MailCatcher $phpmailer + * @param MailCatcherInterface $phpmailer The MailCatcher object. */ public function __construct( $phpmailer ) { - // We want to prefill everything from \WPMailSMTP\MailCatcher class, which extends \PHPMailer. + // We want to prefill everything from MailCatcher class, which extends PHPMailer. parent::__construct( $phpmailer ); // Set mailer specific headers. diff --git a/src/Providers/Sendgrid/Mailer.php b/src/Providers/Sendgrid/Mailer.php index b4b48a9..d0fe364 100644 --- a/src/Providers/Sendgrid/Mailer.php +++ b/src/Providers/Sendgrid/Mailer.php @@ -2,6 +2,7 @@ namespace WPMailSMTP\Providers\Sendgrid; +use WPMailSMTP\MailCatcherInterface; use WPMailSMTP\Providers\MailerAbstract; use WPMailSMTP\WP; @@ -35,11 +36,11 @@ class Mailer extends MailerAbstract { * * @since 1.0.0 * - * @param \WPMailSMTP\MailCatcher $phpmailer + * @param MailCatcherInterface $phpmailer The MailCatcher object. */ public function __construct( $phpmailer ) { - // We want to prefill everything from \WPMailSMTP\MailCatcher class, which extends \PHPMailer. + // We want to prefill everything from MailCatcher class, which extends PHPMailer. parent::__construct( $phpmailer ); $this->set_header( 'Authorization', 'Bearer ' . $this->options->get( $this->mailer, 'api_key' ) ); diff --git a/src/Providers/Sendinblue/Mailer.php b/src/Providers/Sendinblue/Mailer.php index 861caa5..501d7a0 100644 --- a/src/Providers/Sendinblue/Mailer.php +++ b/src/Providers/Sendinblue/Mailer.php @@ -3,6 +3,7 @@ namespace WPMailSMTP\Providers\Sendinblue; use WPMailSMTP\Debug; +use WPMailSMTP\MailCatcherInterface; use WPMailSMTP\Providers\MailerAbstract; use WPMailSMTP\WP; @@ -50,7 +51,7 @@ class Mailer extends MailerAbstract { * * @since 1.6.0 * - * @param \WPMailSMTP\MailCatcher $phpmailer + * @param MailCatcherInterface $phpmailer The MailCatcher object. */ public function __construct( $phpmailer ) { @@ -305,21 +306,18 @@ public function send() { $response = $api->get_smtp_client()->sendTransacEmail( $this->get_body() ); $this->process_response( $response ); - } - catch ( \SendinBlue\Client\ApiException $e ) { + } catch ( \SendinBlue\Client\ApiException $e ) { $error = json_decode( $e->getResponseBody() ); - if ( json_last_error() === JSON_ERROR_NONE ) { - Debug::set( - 'Mailer: Sendinblue' . "\r\n" . - '[' . sanitize_key( $error->code ) . ']: ' . esc_html( $error->message ) - ); + + if ( json_last_error() === JSON_ERROR_NONE && ! empty( $error ) ) { + $message = '[' . sanitize_key( $error->code ) . ']: ' . esc_html( $error->message ); + } else { + $message = $e->getMessage(); } - } - catch ( \Exception $e ) { - Debug::set( - 'Mailer: Sendinblue' . "\r\n" . - $e->getMessage() - ); + + Debug::set( 'Mailer: Sendinblue' . PHP_EOL . $message ); + } catch ( \Exception $e ) { + Debug::set( 'Mailer: Sendinblue' . PHP_EOL . $e->getMessage() ); return; } diff --git a/src/SiteHealth.php b/src/SiteHealth.php index 0cf5ab0..3b07638 100644 --- a/src/SiteHealth.php +++ b/src/SiteHealth.php @@ -68,6 +68,11 @@ public function register_site_status_tests( $tests ) { 'test' => array( $this, 'mailer_setup_complete_test' ), ); + $tests['direct']['wp_mail_smtp_db_tables_exist'] = array( + 'label' => esc_html__( 'Do WP Mail SMTP DB tables exist?', 'wp-mail-smtp' ), + 'test' => [ $this, 'db_tables_test' ], + ); + return $tests; } @@ -84,24 +89,30 @@ public function register_site_status_tests( $tests ) { public function register_debug_information( $debug_info ) { $debug_notices = Debug::get(); + $db_tables = $this->get_db_tables( 'existing' ); - $debug_info[ self::DEBUG_INFO_SLUG ] = array( + $debug_info[ self::DEBUG_INFO_SLUG ] = [ 'label' => $this->get_label(), - 'fields' => array( - 'version' => array( + 'fields' => [ + 'version' => [ 'label' => esc_html__( 'Version', 'wp-mail-smtp' ), 'value' => WPMS_PLUGIN_VER, - ), - 'license_key_type' => array( + ], + 'license_key_type' => [ 'label' => esc_html__( 'License key type', 'wp-mail-smtp' ), 'value' => wp_mail_smtp()->get_license_type(), - ), - 'debug' => array( + ], + 'debug' => [ 'label' => esc_html__( 'Debug', 'wp-mail-smtp' ), 'value' => ! empty( $debug_notices ) ? implode( '. ', $debug_notices ) : esc_html__( 'No debug notices found.', 'wp-mail-smtp' ), - ), - ), - ); + ], + 'db_tables' => [ + 'label' => esc_html__( 'DB tables', 'wp-mail-smtp' ), + 'value' => ! empty( $db_tables ) ? + implode( ', ', $db_tables ) : esc_html__( 'No DB tables found.', 'wp-mail-smtp' ), + ], + ], + ]; return $debug_info; } @@ -177,4 +188,75 @@ public function mailer_setup_complete_test() { return $result; } + + /** + * Perform the test for checking if all custom plugin DB tables exist. + * + * @since 2.1.2 + * + * @return array + */ + public function db_tables_test() { + + $result = array( + 'label' => esc_html__( 'WP Mail SMTP DB tables are created', 'wp-mail-smtp' ), + 'status' => 'good', + 'badge' => array( + 'label' => $this->get_label(), + 'color' => self::BADGE_COLOR, + ), + 'description' => esc_html__( 'WP Mail SMTP is using custom database tables for some of its features. In order to work properly, the custom tables should be created, and it looks like they exist in your database.', 'wp-mail-smtp' ), + 'actions' => '', + 'test' => 'wp_mail_smtp_db_tables_exist', + ); + + $missing_tables = $this->get_db_tables( 'missing' ); + + if ( ! empty( $missing_tables ) ) { + $result['label'] = esc_html__( 'WP Mail SMTP DB tables check has failed', 'wp-mail-smtp' ); + $result['status'] = 'critical'; + $result['badge']['color'] = 'red'; + $result['description'] = sprintf( + '

%s

%s

', + sprintf( /* translators: %s - the list of missing tables separated by comma. */ + esc_html( _n( 'Missing table: %s', 'Missing tables: %s', count( $missing_tables ), 'wp-mail-smtp' ) ), + esc_html( implode( ', ', $missing_tables ) ) + ), + esc_html__( 'WP Mail SMTP is using custom database tables for some of its features. In order to work properly, the custom tables should be created, and it seems they are missing. Please try to re-install the WP Mail SMTP plugin. If this issue persists, please contact our support.', 'wp-mail-smtp' ) + ); + } + + return $result; + } + + /** + * Check DB: + * - if any required plugin DB table is missing, + * - which of the required plugin DB tables exist. + * + * @since 2.1.2 + * + * @param string $check Which type of tables to return: 'missing' or 'existing'. + * + * @return array Missing or existing tables. + */ + private function get_db_tables( $check = 'missing' ) { + + global $wpdb; + + $tables = wp_mail_smtp()->get_custom_db_tables(); + + $missing_tables = []; + $existing_tables = []; + + foreach ( $tables as $table ) { + if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ) !== $table ) { // phpcs:ignore + $missing_tables[] = $table; + } else { + $existing_tables[] = $table; + } + } + + return ( $check === 'existing' ) ? $existing_tables : $missing_tables; + } } diff --git a/src/Tasks/Task.php b/src/Tasks/Task.php index ed39ce7..bd95fd2 100644 --- a/src/Tasks/Task.php +++ b/src/Tasks/Task.php @@ -195,7 +195,7 @@ public function register() { $this->meta_id = $task_meta->add( [ 'action' => $this->action, - 'data' => $this->params, + 'data' => isset( $this->params ) ? $this->params : [], ] ); diff --git a/src/WP.php b/src/WP.php index 1b4e153..b2f68c2 100644 --- a/src/WP.php +++ b/src/WP.php @@ -238,4 +238,63 @@ public static function sanitize_value( $value ) { return $filtered; } + + /** + * Get default email address. + * + * This is the same code as used in WP core for getting the default email address. + * + * @see https://github.com/WordPress/WordPress/blob/master/wp-includes/pluggable.php#L332 + * + * @since 2.2.0 + * + * @return string + */ + public static function get_default_email() { + + $sitename = strtolower( $_SERVER['SERVER_NAME'] ); // phpcs:ignore + + if ( 'www.' === substr( $sitename, 0, 4 ) ) { + $sitename = substr( $sitename, 4 ); + } + + return 'wordpress@' . $sitename; + } + + /** + * Wrapper for the WP `admin_url` method that should be used in the plugin. + * + * We can filter into it, to maybe call `network_admin_url` for multisite support. + * + * @since 2.2.0 + * + * @param string $path Optional path relative to the admin URL. + * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). + * 'http' or 'https' can be passed to force those schemes. + * + * @return string Admin URL link with optional path appended. + */ + public static function admin_url( $path = '', $scheme = 'admin' ) { + + return apply_filters( 'wp_mail_smtp_admin_url', \admin_url( $path, $scheme ), $path, $scheme ); + } + + /** + * Check if the global plugin option in a multisite should be used. + * If the global plugin option "multisite" is set and true. + * + * @since 2.2.0 + * + * @return bool + */ + public static function use_global_plugin_settings() { + + if ( ! is_multisite() ) { + return false; + } + + $main_site_options = get_blog_option( get_main_site_id(), Options::META_KEY, [] ); + + return ! empty( $main_site_options['general']['network_wide'] ); + } } diff --git a/uninstall.php b/uninstall.php index 43fc412..3953be4 100644 --- a/uninstall.php +++ b/uninstall.php @@ -12,17 +12,14 @@ // Load plugin file. require_once 'wp_mail_smtp.php'; +require_once dirname( __FILE__ ) . '/vendor/woocommerce/action-scheduler/action-scheduler.php'; -// Confirm user has decided to remove all data, otherwise stop. -$settings = get_option( 'wp_mail_smtp', array() ); -if ( empty( $settings['general']['uninstall'] ) ) { - return; -} +global $wpdb; /* * Remove Legacy options. */ -$options = array( +$options = [ '_amn_smtp_last_checked', 'pepipost_ssl', 'pepipost_port', @@ -38,62 +35,145 @@ 'mailer', 'mail_from_name', 'mail_from', -); +]; -foreach ( $options as $option ) { - delete_option( $option ); -} +/** + * Remove AM announcement posts. + */ +$am_announcement_params = [ + 'post_type' => [ 'amn_smtp' ], + 'post_status' => 'any', + 'numberposts' => - 1, + 'fields' => 'ids', +]; -global $wpdb; +// WP MS uninstall process. +if ( is_multisite() ) { + $main_site_settings = get_blog_option( get_main_site_id(), 'wp_mail_smtp', [] ); + $network_wide = ! empty( $main_site_settings['general']['network_wide'] ); + $network_uninstall = ! empty( $main_site_settings['general']['uninstall'] ); -// Delete plugin settings. -$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'wp\_mail\_smtp%'" ); + $sites = get_sites(); -// Delete plugin user meta. -$wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE 'wp\_mail\_smtp\_%'" ); + foreach ( $sites as $site ) { + $settings = get_blog_option( $site->blog_id, 'wp_mail_smtp', [] ); -// Remove any transients we've left behind. -$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_transient\_wp\_mail\_smtp\_%'" ); -$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_site\_transient\_wp\_mail\_smtp\_%'" ); -$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_transient\_timeout\_wp\_mail\_smtp\_%'" ); -$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_site\_transient\_timeout\_wp\_mail\_smtp\_%'" ); + // Confirm network site admin has decided to remove all data, otherwise skip. + if ( + ( $network_wide && ! $network_uninstall ) || + ( ! $network_wide && empty( $settings['general']['uninstall'] ) ) + ) { + continue; + } -/* - * Remove product announcements. - */ -$announcements = get_posts( - array( - 'post_type' => array( 'amn_smtp' ), - 'post_status' => 'any', - 'numberposts' => - 1, - 'fields' => 'ids', - ) -); -if ( ! empty( $announcements ) ) { - foreach ( $announcements as $announcement ) { - wp_delete_post( $announcement, true ); + /* + * Delete network site plugin options. + */ + foreach ( $options as $option ) { + delete_blog_option( $site->blog_id, $option ); + } + + // Switch to the current network site. + switch_to_blog( $site->blog_id ); + + // Delete plugin settings. + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'wp\_mail\_smtp%'" ); // phpcs:ignore WordPress.DB + + // Delete plugin user meta. + $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE 'wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB + + // Remove any transients we've left behind. + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_transient\_wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_site\_transient\_wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_transient\_timeout\_wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_site\_transient\_timeout\_wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB + + /* + * Delete network site product announcements. + */ + $announcements = get_posts( $am_announcement_params ); + + if ( ! empty( $announcements ) ) { + foreach ( $announcements as $announcement ) { + wp_delete_post( $announcement, true ); + } + } + + /* + * Delete network site Logs for Pro plugin only. + */ + if ( + function_exists( 'wp_mail_smtp' ) && + is_readable( wp_mail_smtp()->plugin_path . '/src/Pro/Pro.php' ) + ) { + $table = \WPMailSMTP\Pro\Emails\Logs\Logs::get_table_name(); + $wpdb->query( "DROP TABLE IF EXISTS $table;" ); // phpcs:ignore WordPress.DB + } + + /* + * Drop all Action Scheduler data and unschedule all plugin ActionScheduler actions. + */ + ( new \WPMailSMTP\Tasks\Tasks() )->cancel_all(); + + $meta_table = \WPMailSMTP\Tasks\Meta::get_table_name(); + $wpdb->query( "DROP TABLE IF EXISTS $meta_table;" ); // phpcs:ignore WordPress.DB + + // Restore the current network site back to the original one. + restore_current_blog(); } -} +} else { // Non WP MS uninstall process (for normal WP installs). -/* - * Logs for Pro plugin only. - */ -if ( - function_exists( 'wp_mail_smtp' ) && - is_readable( wp_mail_smtp()->plugin_path . '/src/Pro/Pro.php' ) -) { - // DB table. - $logs_table = \WPMailSMTP\Pro\Emails\Logs\Logs::get_table_name(); - $wpdb->query( "DROP TABLE IF EXISTS $logs_table;" ); // phpcs:ignore WordPress.DB -} + // Confirm user has decided to remove all data, otherwise stop. + $settings = get_option( 'wp_mail_smtp', [] ); + if ( empty( $settings['general']['uninstall'] ) ) { + return; + } -/* - * Drop all Action Scheduler data. - */ -require_once dirname( __FILE__ ) . '/vendor/woocommerce/action-scheduler/action-scheduler.php'; + /* + * Delete plugin options. + */ + foreach ( $options as $option ) { + delete_option( $option ); + } + + // Delete plugin settings. + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'wp\_mail\_smtp%'" ); // phpcs:ignore WordPress.DB + + // Delete plugin user meta. + $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE 'wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB -// Unschedule all plugin ActionScheduler actions. -( new \WPMailSMTP\Tasks\Tasks() )->cancel_all(); + // Remove any transients we've left behind. + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_transient\_wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_site\_transient\_wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_transient\_timeout\_wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB + $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_site\_transient\_timeout\_wp\_mail\_smtp\_%'" ); // phpcs:ignore WordPress.DB + + /* + * Remove product announcements. + */ + $announcements = get_posts( $am_announcement_params ); + if ( ! empty( $announcements ) ) { + foreach ( $announcements as $announcement ) { + wp_delete_post( $announcement, true ); + } + } -$meta_table = \WPMailSMTP\Tasks\Meta::get_table_name(); -$wpdb->query( "DROP TABLE IF EXISTS $meta_table;" ); // phpcs:ignore WordPress.DB + /* + * Logs for Pro plugin only. + */ + if ( + function_exists( 'wp_mail_smtp' ) && + is_readable( wp_mail_smtp()->plugin_path . '/src/Pro/Pro.php' ) + ) { + $table = \WPMailSMTP\Pro\Emails\Logs\Logs::get_table_name(); + $wpdb->query( "DROP TABLE IF EXISTS $table;" ); // phpcs:ignore WordPress.DB + } + + /* + * Drop all Action Scheduler data and unschedule all plugin ActionScheduler actions. + */ + ( new \WPMailSMTP\Tasks\Tasks() )->cancel_all(); + + $meta_table = \WPMailSMTP\Tasks\Meta::get_table_name(); + $wpdb->query( "DROP TABLE IF EXISTS $meta_table;" ); // phpcs:ignore WordPress.DB +} diff --git a/wp_mail_smtp.php b/wp_mail_smtp.php index b6f5926..230943f 100644 --- a/wp_mail_smtp.php +++ b/wp_mail_smtp.php @@ -1,7 +1,7 @@ wp_mail() function to use Gmail/Mailgun/SendGrid/SMTP instead of the default mail() and creates an options page to manage the settings. * Author: WPForms @@ -203,7 +203,7 @@ function wp_mail_smtp_insecure_php_version_notice() { } if ( ! defined( 'WPMS_PLUGIN_VER' ) ) { - define( 'WPMS_PLUGIN_VER', '2.1.1' ); + define( 'WPMS_PLUGIN_VER', '2.2.1' ); } if ( ! defined( 'WPMS_PHP_VER' ) ) { define( 'WPMS_PHP_VER', '5.5.0' );