PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 4.3.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v4.3.0
0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / src / Processor.php
wp-mail-smtp / src Last commit date
Admin 1 year ago Compatibility 1 year ago Helpers 1 year ago Providers 1 year ago Queue 1 year ago Reports 1 year ago Tasks 1 year ago UsageTracking 1 year ago AbstractConnection.php 1 year ago Conflicts.php 1 year ago Connect.php 1 year ago Connection.php 1 year ago ConnectionInterface.php 1 year ago ConnectionsManager.php 1 year ago Core.php 1 year ago DBRepair.php 1 year ago Debug.php 1 year ago Geo.php 1 year ago MailCatcher.php 1 year ago MailCatcherInterface.php 1 year ago MailCatcherTrait.php 1 year ago MailCatcherV6.php 1 year ago Migration.php 1 year ago MigrationAbstract.php 1 year ago Migrations.php 1 year ago OptimizedEmailSending.php 1 year ago Options.php 1 year ago Processor.php 1 year ago SiteHealth.php 1 year ago Upgrade.php 1 year ago Uploads.php 1 year ago WP.php 1 year ago WPMailArgs.php 1 year ago WPMailInitiator.php 1 year ago
Processor.php
530 lines
1 <?php
2
3 namespace WPMailSMTP;
4
5 /**
6 * Class Processor modifies the behaviour of wp_mail() function.
7 *
8 * @since 1.0.0
9 */
10 class Processor {
11
12 /**
13 * This attribute will hold the "original" WP from email address passed to the wp_mail_from filter,
14 * that is not equal to the default email address.
15 *
16 * It should hold an email address set via the wp_mail_from filter, before we might overwrite it.
17 *
18 * @since 2.1.0
19 *
20 * @var string
21 */
22 protected $wp_mail_from;
23
24 /**
25 * Connections manager.
26 *
27 * @since 3.7.0
28 *
29 * @var ConnectionsManager
30 */
31 private $connections_manager;
32
33 /**
34 * This attribute will hold the arguments passed to the `wp_mail` function.
35 *
36 * @since 4.0.0
37 *
38 * @var array
39 */
40 private $original_wp_mail_args;
41
42 /**
43 * This attribute will hold the arguments passed to the `wp_mail` function and filtered via `wp_mail` filter.
44 *
45 * @since 4.0.0
46 *
47 * @var array
48 */
49 private $filtered_wp_mail_args;
50
51 /**
52 * This attribute will hold the From address filtered via the `wp_mail_from` filter.
53 *
54 * @since 4.0.0
55 *
56 * @var string
57 */
58 private $filtered_from_email;
59
60 /**
61 * This attribute will hold the From name filtered via the `wp_mail_from_name` filter.
62 *
63 * @since 4.0.0
64 *
65 * @var string
66 */
67 private $filtered_from_name;
68
69 /**
70 * Class constructor.
71 *
72 * @since 3.7.0
73 *
74 * @param ConnectionsManager $connections_manager Connections manager.
75 */
76 public function __construct( $connections_manager = null ) {
77
78 if ( is_null( $connections_manager ) ) {
79 $this->connections_manager = wp_mail_smtp()->get_connections_manager();
80 } else {
81 $this->connections_manager = $connections_manager;
82 }
83 }
84
85 /**
86 * Assign all hooks to proper places.
87 *
88 * @since 1.0.0
89 */
90 public function hooks() {
91
92 add_action( 'phpmailer_init', array( $this, 'phpmailer_init' ) );
93
94 // High priority number tries to ensure our plugin code executes last and respects previous hooks, if not forced.
95 add_filter( 'wp_mail_from', array( $this, 'filter_mail_from_email' ), PHP_INT_MAX );
96 add_filter( 'wp_mail_from_name', array( $this, 'filter_mail_from_name' ), PHP_INT_MAX );
97
98 add_action( 'wp_mail', [ $this, 'capture_early_wp_mail_filter_call' ], - PHP_INT_MAX );
99 add_action( 'wp_mail', [ $this, 'capture_late_wp_mail_filter_call' ], PHP_INT_MAX );
100 }
101
102 /**
103 * Redefine certain PHPMailer options with our custom ones.
104 *
105 * @since 1.0.0
106 *
107 * @param \PHPMailer $phpmailer It's passed by reference, so no need to return anything.
108 */
109 public function phpmailer_init( $phpmailer ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
110
111 $connection = $this->connections_manager->get_mail_connection();
112 $connection_options = $connection->get_options();
113 $mailer = $connection->get_mailer_slug();
114
115 // Check that mailer is not blank, and if mailer=smtp, host is not blank.
116 if (
117 ! $mailer ||
118 ( 'smtp' === $mailer && ! $connection_options->get( 'smtp', 'host' ) )
119 ) {
120 return;
121 }
122
123 // If the mailer is pepipost, make sure we have a username and password.
124 if (
125 'pepipost' === $mailer &&
126 ( ! $connection_options->get( 'pepipost', 'user' ) && ! $connection_options->get( 'pepipost', 'pass' ) )
127 ) {
128 return;
129 }
130
131 // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
132
133 // Set the mailer type as per config above, this overrides the already called isMail method.
134 // It's basically always 'smtp'.
135 $phpmailer->Mailer = $mailer;
136
137 // Set the Sender (return-path) if required.
138 if ( $connection_options->get( 'mail', 'return_path' ) ) {
139 $phpmailer->Sender = $phpmailer->From;
140 }
141
142 // Set the SMTPSecure value, if set to none, leave this blank. Possible values: 'ssl', 'tls', ''.
143 if ( 'none' === $connection_options->get( $mailer, 'encryption' ) ) {
144 $phpmailer->SMTPSecure = '';
145 } else {
146 $phpmailer->SMTPSecure = $connection_options->get( $mailer, 'encryption' );
147 }
148
149 // Check if user has disabled SMTPAutoTLS.
150 if ( $connection_options->get( $mailer, 'encryption' ) !== 'tls' && ! $connection_options->get( $mailer, 'autotls' ) ) {
151 $phpmailer->SMTPAutoTLS = false;
152 }
153
154 // Check if original WP from email can be set as the reply_to attribute.
155 if ( $this->allow_setting_original_from_email_to_reply_to( $phpmailer->getReplyToAddresses(), $mailer ) ) {
156 $phpmailer->addReplyTo( $this->wp_mail_from );
157 }
158
159 // If we're sending via SMTP, set the host.
160 if ( 'smtp' === $mailer ) {
161 // Set the other options.
162 $phpmailer->Host = $connection_options->get( $mailer, 'host' );
163 $phpmailer->Port = $connection_options->get( $mailer, 'port' );
164
165 // If we're using smtp auth, set the username & password.
166 if ( $connection_options->get( $mailer, 'auth' ) ) {
167 $phpmailer->SMTPAuth = true;
168 $phpmailer->Username = $connection_options->get( $mailer, 'user' );
169 $phpmailer->Password = $connection_options->get( $mailer, 'pass' );
170 }
171 } elseif ( 'pepipost' === $mailer ) {
172 // Set the Pepipost settings for BC.
173 $phpmailer->Mailer = 'smtp';
174 $phpmailer->Host = 'smtp.pepipost.com';
175 $phpmailer->Port = $connection_options->get( $mailer, 'port' );
176 $phpmailer->SMTPSecure = $connection_options->get( $mailer, 'encryption' ) === 'none' ? '' : $connection_options->get( $mailer, 'encryption' );
177 $phpmailer->SMTPAuth = true;
178 $phpmailer->Username = $connection_options->get( $mailer, 'user' );
179 $phpmailer->Password = $connection_options->get( $mailer, 'pass' );
180 }
181
182 $phpmailer->Timeout = 30;
183 // phpcs:enable
184
185 // Maybe set default reply-to header.
186 $this->set_default_reply_to( $phpmailer );
187
188 // You can add your own options here.
189 // See the phpmailer documentation for more info: https://github.com/PHPMailer/PHPMailer/tree/5.2-stable.
190 /* @noinspection PhpUnusedLocalVariableInspection It's passed by reference. */
191 $phpmailer = apply_filters( 'wp_mail_smtp_custom_options', $phpmailer );
192 }
193
194 /**
195 * Check if it's allowed to set the original WP from email to the reply_to field.
196 *
197 * @since 2.1.0
198 *
199 * @param array $reply_to Array of currently set reply to emails.
200 * @param string $mailer The slug of current mailer.
201 *
202 * @return bool
203 */
204 protected function allow_setting_original_from_email_to_reply_to( $reply_to, $mailer ) {
205
206 $connection = $this->connections_manager->get_mail_connection();
207 $connection_options = $connection->get_options();
208 $forced = $connection_options->get( 'mail', 'from_email_force' );
209 $from_email = $connection_options->get( 'mail', 'from_email' );
210
211 if ( ! empty( $reply_to ) || empty( $this->wp_mail_from ) ) {
212 return false;
213 }
214
215 if ( in_array( $mailer, [ 'zoho' ], true ) ) {
216 $sender = $connection_options->get( $mailer, 'user_details' );
217 $from_email = ! empty( $sender['email'] ) ? $sender['email'] : '';
218 $forced = true;
219 }
220
221 if (
222 $from_email === $this->wp_mail_from ||
223 ! $forced
224 ) {
225 return false;
226 }
227
228 return true;
229 }
230
231 /**
232 * This method will be called every time 'smtp' and 'mail' mailers will be used to send emails.
233 *
234 * @since 1.3.0
235 * @since 1.5.0 Added a do_action() to be able to hook into.
236 *
237 * @param bool $is_sent If the email was sent.
238 * @param array $to To email address.
239 * @param array $cc CC email addresses.
240 * @param array $bcc BCC email addresses.
241 * @param string $subject The email subject.
242 * @param string $body The email body.
243 * @param string $from The from email address.
244 */
245 public static function send_callback( $is_sent, $to, $cc, $bcc, $subject, $body, $from ) {
246
247 if ( ! $is_sent ) {
248 // Add mailer to the beginning and save to display later.
249 Debug::set(
250 'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( wp_mail_smtp()->get_connections_manager()->get_mail_connection()->get_mailer_slug() )->get_title() ) . "\r\n" .
251 'PHPMailer was able to connect to SMTP server but failed while trying to send an email.'
252 );
253 } else {
254 Debug::clear();
255 }
256
257 do_action( 'wp_mail_smtp_mailcatcher_smtp_send_after', $is_sent, $to, $cc, $bcc, $subject, $body, $from );
258 }
259
260 /**
261 * Validate the email address.
262 *
263 * @since 3.6.0
264 *
265 * @param string $email The email address.
266 *
267 * @return boolean True if email address is valid, false on failure.
268 */
269 public static function is_email_callback( $email ) {
270
271 return (bool) is_email( $email );
272 }
273
274 /**
275 * Modify the email address that is used for sending emails.
276 *
277 * @since 1.0.0
278 * @since 1.3.0 Forcing email rewrite if option is selected.
279 * @since 1.7.0 Default email may be empty, so pay attention to that as well.
280 *
281 * @param string $wp_email The email address passed by the filter.
282 *
283 * @return string
284 */
285 public function filter_mail_from_email( $wp_email ) {
286
287 // Save the original from address.
288 $this->filtered_from_email = filter_var( $wp_email, FILTER_VALIDATE_EMAIL );
289
290 $connection = $this->connections_manager->get_mail_connection();
291 $connection_options = $connection->get_options();
292 $forced = $connection_options->get( 'mail', 'from_email_force' );
293 $from_email = $connection_options->get( 'mail', 'from_email' );
294 $def_email = WP::get_default_email();
295
296 // Save the "original" set WP email from address for later use.
297 if ( $wp_email !== $def_email ) {
298 $this->wp_mail_from = filter_var( $wp_email, FILTER_VALIDATE_EMAIL );
299 }
300
301 // Return FROM EMAIL if forced in settings.
302 if ( $forced && ! empty( $from_email ) ) {
303 return $from_email;
304 }
305
306 // If the FROM EMAIL is not the default, return it unchanged.
307 if ( ! empty( $def_email ) && $wp_email !== $def_email ) {
308 return $wp_email;
309 }
310
311 return ! empty( $from_email ) ? $from_email : $wp_email;
312 }
313
314 /**
315 * Modify the sender name that is used for sending emails.
316 *
317 * @since 1.0.0
318 * @since 1.3.0 Forcing name rewrite if option is selected.
319 *
320 * @param string $name The from name passed through the filter.
321 *
322 * @return string
323 */
324 public function filter_mail_from_name( $name ) {
325
326 // Save the original from name.
327 $this->filtered_from_name = $name;
328
329 $connection = $this->connections_manager->get_mail_connection();
330 $connection_options = $connection->get_options();
331 $force = $connection_options->get( 'mail', 'from_name_force' );
332
333 // If the FROM NAME is not the default and not forced, return it unchanged.
334 if ( ! $force && $name !== $this->get_default_name() ) {
335 return $name;
336 }
337
338 $name = $connection_options->get( 'mail', 'from_name' );
339
340 return $name;
341 }
342
343 /**
344 * Get the default email address based on domain name.
345 *
346 * @since 1.0.0
347 * @since 1.7.0 May return an empty string.
348 *
349 * @return string Empty string when we aren't able to get the site domain (CLI, misconfigured server etc).
350 */
351 public function get_default_email() {
352
353 $server_name = Geo::get_site_domain();
354
355 if ( empty( $server_name ) ) {
356 return '';
357 }
358
359 // Get rid of www.
360 $sitename = strtolower( $server_name );
361 if ( substr( $sitename, 0, 4 ) === 'www.' ) {
362 $sitename = substr( $sitename, 4 );
363 }
364
365 return 'wordpress@' . $sitename;
366 }
367
368 /**
369 * Get the default email FROM NAME generated by WordPress.
370 *
371 * @since 1.3.0
372 *
373 * @return string
374 */
375 public function get_default_name() {
376 return 'WordPress';
377 }
378
379 /**
380 * Get or create the phpmailer.
381 *
382 * @since 1.9.0
383 *
384 * @return MailCatcherInterface
385 */
386 public function get_phpmailer() {
387
388 global $phpmailer;
389
390 // Make sure the PHPMailer class has been instantiated.
391 if ( ! is_object( $phpmailer ) || ! is_a( $phpmailer, 'PHPMailer' ) ) {
392 $phpmailer = wp_mail_smtp()->generate_mail_catcher( true ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
393 }
394
395 return $phpmailer;
396 }
397
398 /**
399 * Set the default reply_to header, if:
400 * - no other reply_to headers are already set and,
401 * - the default reply_to address filter `wp_mail_smtp_processor_default_reply_to_addresses` is configured.
402 *
403 * @since 2.1.1
404 *
405 * @param MailCatcherInterface $phpmailer The PHPMailer object.
406 */
407 private function set_default_reply_to( $phpmailer ) {
408
409 if ( ! empty( $phpmailer->getReplyToAddresses() ) ) {
410 return;
411 }
412
413 $default_reply_to_emails = apply_filters( 'wp_mail_smtp_processor_set_default_reply_to', '' );
414
415 if ( empty( $default_reply_to_emails ) ) {
416 return;
417 }
418
419 foreach ( explode( ',', $default_reply_to_emails ) as $email ) {
420 $email = trim( $email );
421
422 if ( filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
423 $phpmailer->addReplyTo( $email );
424 }
425 }
426 }
427
428 /**
429 * Capture `wp_mail` filter call on earliest priority.
430 *
431 * Currently used to capture the original `wp_mail` arguments before they are filtered.
432 *
433 * @since 4.0.0
434 *
435 * @param array $args The original `wp_mail` arguments.
436 *
437 * @return array
438 */
439 public function capture_early_wp_mail_filter_call( $args ) {
440
441 $this->original_wp_mail_args = $args;
442
443 return $args;
444 }
445
446 /**
447 * Capture `wp_mail` filter call on latest priority.
448 *
449 * Currently used to capture the `wp_mail` arguments after they are filtered
450 * and capture `wp_mail` function call.
451 *
452 * @since 4.0.0
453 *
454 * @param array $args The filtered `wp_mail` arguments.
455 *
456 * @return array
457 */
458 public function capture_late_wp_mail_filter_call( $args ) {
459
460 $this->filtered_wp_mail_args = $args;
461
462 $this->capture_wp_mail_call();
463
464 return $args;
465 }
466
467 /**
468 * Capture `wp_mail` function call.
469 *
470 * @since 4.0.0
471 */
472 private function capture_wp_mail_call() {
473
474 /**
475 * Fires on `wp_mail` function call.
476 *
477 * @since 4.0.0
478 */
479 do_action( 'wp_mail_smtp_processor_capture_wp_mail_call' );
480 }
481
482 /**
483 * Get the original `wp_mail` arguments.
484 *
485 * @since 4.0.0
486 *
487 * @return array
488 */
489 public function get_original_wp_mail_args() {
490
491 return $this->original_wp_mail_args;
492 }
493
494 /**
495 * Get the filtered `wp_mail` arguments.
496 *
497 * @since 4.0.0
498 *
499 * @return array
500 */
501 public function get_filtered_wp_mail_args() {
502
503 return $this->filtered_wp_mail_args;
504 }
505
506 /**
507 * Get the filtered `wp_mail_from` value.
508 *
509 * @since 4.0.0
510 *
511 * @return string
512 */
513 public function get_filtered_from_email() {
514
515 return $this->filtered_from_email;
516 }
517
518 /**
519 * Get the filtered `wp_mail_from_name` value.
520 *
521 * @since 4.0.0
522 *
523 * @return string
524 */
525 public function get_filtered_from_name() {
526
527 return $this->filtered_from_name;
528 }
529 }
530