FluentSMTP – WP Mail SMTP, Amazon SES, SendGrid, MailGun and Any SMTP Connector Plugin - Version 2.0.2

Version Description

(Date: September 21, 2021) = * Fixed Scheduled Database Cleanup * Improvement on wp_mail loading and sending emails * Pepipost Driver Improvement * SendGrid Driver Improvement * SendinBlue Drive Improvement

Download this release

Release Info

Developer techjewel
Plugin Icon FluentSMTP – WP Mail SMTP, Amazon SES, SendGrid, MailGun and Any SMTP Connector Plugin
Version 2.0.2
Comparing to
See all releases

Code changes from version 2.0.1 to 2.0.2

app/Bindings.php CHANGED
@@ -13,6 +13,7 @@ $singletons = [
13
  'gmail' => 'FluentMail\App\Services\Mailer\Providers\Gmail\Handler',
14
  'outlook' => 'FluentMail\App\Services\Mailer\Providers\Outlook\Handler',
15
  'postmark' => 'FluentMail\App\Services\Mailer\Providers\Postmark\Handler',
 
16
  ];
17
 
18
  foreach ($singletons as $key => $className) {
13
  'gmail' => 'FluentMail\App\Services\Mailer\Providers\Gmail\Handler',
14
  'outlook' => 'FluentMail\App\Services\Mailer\Providers\Outlook\Handler',
15
  'postmark' => 'FluentMail\App\Services\Mailer\Providers\Postmark\Handler',
16
+ // 'elasticmail' => 'FluentMail\App\Services\Mailer\Providers\ElasticMail\Handler',
17
  ];
18
 
19
  foreach ($singletons as $key => $className) {
app/Functions/helpers.php CHANGED
@@ -26,46 +26,6 @@ if (!function_exists('fluentMailAssetUrl')) {
26
  }
27
  }
28
 
29
- if (!function_exists('dd')) {
30
- function dd()
31
- {
32
- foreach (func_get_args() as $arg) {
33
- echo "<pre>";
34
- print_r($arg);
35
- echo "</pre>";
36
- }
37
- die;
38
- }
39
- }
40
-
41
- if (!function_exists('ddd')) {
42
- function ddd($data)
43
- {
44
- foreach (func_get_args() as $arg) {
45
- echo "<pre>";
46
- print_r($arg);
47
- echo "</pre>";
48
- }
49
- }
50
- }
51
-
52
- if (!function_exists('fluentMailWpParseArgs')) {
53
- function fluentMailWpParseArgs($args, $defaults = [])
54
- {
55
- $newArgs = (array)$defaults;
56
-
57
- foreach ($args as $key => $value) {
58
- if (is_array($value) && isset($newArgs[$key])) {
59
- $newArgs[$key] = fluentMailWpParseArgs($value, $newArgs[$key]);
60
- } else {
61
- $newArgs[$key] = $value;
62
- }
63
- }
64
-
65
- return $newArgs;
66
- }
67
- }
68
-
69
  if (!function_exists('fluentMailIsListedSenderEmail')) {
70
  function fluentMailIsListedSenderEmail($email)
71
  {
@@ -201,3 +161,423 @@ if (!function_exists('fluentMailSesConnection')) {
201
  }
202
  }
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
  }
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  if (!function_exists('fluentMailIsListedSenderEmail')) {
30
  function fluentMailIsListedSenderEmail($email)
31
  {
161
  }
162
  }
163
 
164
+ if(!function_exists('fluentMail_wp_mail')) {
165
+ function fluentMail_wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {
166
+ // Compact the input, apply the filters, and extract them back out.
167
+ /**
168
+ * Filters the wp_mail() arguments.
169
+ *
170
+ * @since 2.2.0
171
+ *
172
+ * @param array $args A compacted array of wp_mail() arguments, including the "to" email,
173
+ * subject, message, headers, and attachments values.
174
+ */
175
+ $atts = apply_filters(
176
+ 'wp_mail', compact('to', 'subject', 'message', 'headers', 'attachments')
177
+ );
178
+
179
+ /**
180
+ * Filters whether to preempt sending an email.
181
+ *
182
+ * Returning a non-null value will short-circuit {@see wp_mail()}, returning
183
+ * that value instead. A boolean return value should be used to indicate whether
184
+ * the email was successfully sent.
185
+ *
186
+ * @since 5.7.0
187
+ *
188
+ * @param null|bool $return Short-circuit return value.
189
+ * @param array $atts {
190
+ * Array of the `wp_mail()` arguments.
191
+ *
192
+ * @type string|string[] $to Array or comma-separated list of email addresses to send message.
193
+ * @type string $subject Email subject.
194
+ * @type string $message Message contents.
195
+ * @type string|string[] $headers Additional headers.
196
+ * @type string|string[] $attachments Paths to files to attach.
197
+ * }
198
+ */
199
+ $pre_wp_mail = apply_filters( 'pre_wp_mail', null, $atts );
200
+
201
+ if ( null !== $pre_wp_mail ) {
202
+ return $pre_wp_mail;
203
+ }
204
+
205
+
206
+ if ( isset( $atts['to'] ) ) {
207
+ $to = $atts['to'];
208
+ }
209
+
210
+ if ( ! is_array( $to ) ) {
211
+ $to = explode( ',', $to );
212
+ }
213
+
214
+ if ( isset( $atts['subject'] ) ) {
215
+ $subject = $atts['subject'];
216
+ }
217
+
218
+ if ( isset( $atts['message'] ) ) {
219
+ $message = $atts['message'];
220
+ }
221
+
222
+ if ( isset( $atts['headers'] ) ) {
223
+ $headers = $atts['headers'];
224
+ }
225
+
226
+ if ( isset( $atts['attachments'] ) ) {
227
+ $attachments = $atts['attachments'];
228
+ }
229
+
230
+ if ( ! is_array( $attachments ) ) {
231
+ $attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
232
+ }
233
+
234
+ global $phpmailer;
235
+
236
+ // (Re)create it, if it's gone missing.
237
+ if ( ! ( $phpmailer instanceof PHPMailer\PHPMailer\PHPMailer ) ) {
238
+ require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
239
+ require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
240
+ require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
241
+ $phpmailer = new PHPMailer\PHPMailer\PHPMailer( true );
242
+
243
+ $phpmailer::$validator = static function ( $email ) {
244
+ return (bool) is_email( $email );
245
+ };
246
+ }
247
+
248
+ if (($class = get_class($phpmailer)) != 'PHPMailer\PHPMailer\PHPMailer') {
249
+ do_action(
250
+ 'wp_mail_failed',
251
+ new WP_Error(
252
+ 400,
253
+ "Oops! PHPMailer is modified by $class."
254
+ )
255
+ );
256
+ }
257
+
258
+ // Headers.
259
+ $cc = array();
260
+ $bcc = array();
261
+ $reply_to = array();
262
+
263
+ if ( empty( $headers ) ) {
264
+ $headers = array();
265
+ } else {
266
+ if ( ! is_array( $headers ) ) {
267
+ // Explode the headers out, so this function can take
268
+ // both string headers and an array of headers.
269
+ $tempheaders = explode( "\n", str_replace( "\r\n", "\n", $headers ) );
270
+ } else {
271
+ $tempheaders = $headers;
272
+ }
273
+ $headers = array();
274
+
275
+ // If it's actually got contents.
276
+ if ( ! empty( $tempheaders ) ) {
277
+ // Iterate through the raw headers.
278
+ foreach ( (array) $tempheaders as $header ) {
279
+ if ( strpos( $header, ':' ) === false ) {
280
+ if ( false !== stripos( $header, 'boundary=' ) ) {
281
+ $parts = preg_split( '/boundary=/i', trim( $header ) );
282
+ $boundary = trim( str_replace( array( "'", '"' ), '', $parts[1] ) );
283
+ }
284
+ continue;
285
+ }
286
+ // Explode them out.
287
+ list( $name, $content ) = explode( ':', trim( $header ), 2 );
288
+
289
+ // Cleanup crew.
290
+ $name = trim( $name );
291
+ $content = trim( $content );
292
+
293
+ switch ( strtolower( $name ) ) {
294
+ // Mainly for legacy -- process a "From:" header if it's there.
295
+ case 'from':
296
+ $bracket_pos = strpos( $content, '<' );
297
+ if ( false !== $bracket_pos ) {
298
+ // Text before the bracketed email is the "From" name.
299
+ if ( $bracket_pos > 0 ) {
300
+ $from_name = substr( $content, 0, $bracket_pos - 1 );
301
+ $from_name = str_replace( '"', '', $from_name );
302
+ $from_name = trim( $from_name );
303
+ }
304
+
305
+ $from_email = substr( $content, $bracket_pos + 1 );
306
+ $from_email = str_replace( '>', '', $from_email );
307
+ $from_email = trim( $from_email );
308
+
309
+ // Avoid setting an empty $from_email.
310
+ } elseif ( '' !== trim( $content ) ) {
311
+ $from_email = trim( $content );
312
+ }
313
+ break;
314
+ case 'content-type':
315
+ if ( strpos( $content, ';' ) !== false ) {
316
+ list( $type, $charset_content ) = explode( ';', $content );
317
+ $content_type = trim( $type );
318
+ if ( false !== stripos( $charset_content, 'charset=' ) ) {
319
+ $charset = trim( str_replace( array( 'charset=', '"' ), '', $charset_content ) );
320
+ } elseif ( false !== stripos( $charset_content, 'boundary=' ) ) {
321
+ $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset_content ) );
322
+ $charset = '';
323
+ }
324
+
325
+ // Avoid setting an empty $content_type.
326
+ } elseif ( '' !== trim( $content ) ) {
327
+ $content_type = trim( $content );
328
+ }
329
+ break;
330
+ case 'cc':
331
+ $cc = array_merge( (array) $cc, explode( ',', $content ) );
332
+ break;
333
+ case 'bcc':
334
+ $bcc = array_merge( (array) $bcc, explode( ',', $content ) );
335
+ break;
336
+ case 'reply-to':
337
+ $reply_to = array_merge( (array) $reply_to, explode( ',', $content ) );
338
+ break;
339
+ default:
340
+ // Add it to our grand headers array.
341
+ $headers[ trim( $name ) ] = trim( $content );
342
+ break;
343
+ }
344
+ }
345
+ }
346
+ }
347
+
348
+ // Empty out the values that may be set.
349
+ $phpmailer->clearAllRecipients();
350
+ $phpmailer->clearAttachments();
351
+ $phpmailer->clearCustomHeaders();
352
+ $phpmailer->clearReplyTos();
353
+
354
+
355
+ /*
356
+ * If we don't have an email from the input headers, default to wordpress@$sitename
357
+ * Some hosts will block outgoing mail from this address if it doesn't exist,
358
+ * but there's no easy alternative. Defaulting to admin_email might appear to be
359
+ * another option, but some hosts may refuse to relay mail from an unknown domain.
360
+ * See https://core.trac.wordpress.org/ticket/5007.
361
+ */
362
+ $defaultConnection = false;
363
+ if ( ! isset( $from_email ) ) {
364
+ $defaultConnection = fluentMailDefaultConnection();
365
+
366
+ if (!empty($defaultConnection['sender_email'])) {
367
+ $from_email = $defaultConnection['sender_email'];
368
+ } else {
369
+ // Get the site domain and get rid of www.
370
+ $sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
371
+ if ( 'www.' === substr( $sitename, 0, 4 ) ) {
372
+ $sitename = substr( $sitename, 4 );
373
+ }
374
+ $from_email = 'wordpress@' . $sitename;
375
+ }
376
+ }
377
+
378
+ // Set "From" name and email.
379
+ // If we don't have a name from the input headers.
380
+ if ( ! isset( $from_name ) ) {
381
+ if($defaultConnection && !empty($defaultConnection['sender_name'])) {
382
+ $from_name = $defaultConnection['sender_name'];
383
+ } else {
384
+ $provider = fluentMailGetProvider($from_email);
385
+ if ($provider && !empty($provider->getSetting('sender_name'))) {
386
+ $from_name = $provider->getSetting('sender_name');
387
+ } else {
388
+ $from_name = 'WordPress';
389
+ }
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Filters the email address to send from.
395
+ *
396
+ * @since 2.2.0
397
+ *
398
+ * @param string $from_email Email address to send from.
399
+ */
400
+ $from_email = apply_filters('wp_mail_from', $from_email);
401
+
402
+ /**
403
+ * Filters the name to associate with the "from" email address.
404
+ *
405
+ * @since 2.3.0
406
+ *
407
+ * @param string $from_name Name associated with the "from" email address.
408
+ */
409
+ $from_name = apply_filters('wp_mail_from_name', $from_name);
410
+
411
+ try {
412
+ $phpmailer->setFrom( $from_email, $from_name, false );
413
+ } catch ( PHPMailer\PHPMailer\Exception $e ) {
414
+ $mail_error_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
415
+ $mail_error_data['phpmailer_exception_code'] = $e->getCode();
416
+
417
+ /** This filter is documented in wp-includes/pluggable.php */
418
+ do_action(
419
+ 'wp_mail_failed',
420
+ new WP_Error(
421
+ 'wp_mail_failed',
422
+ $e->getMessage(),
423
+ $mail_error_data
424
+ )
425
+ );
426
+
427
+ return false;
428
+ }
429
+
430
+ // Set mail's subject and body.
431
+ $phpmailer->Subject = $subject;
432
+ $phpmailer->Body = $message;
433
+
434
+ // Set destination addresses, using appropriate methods for handling addresses.
435
+ $address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' );
436
+
437
+ foreach ( $address_headers as $address_header => $addresses ) {
438
+ if ( empty( $addresses ) ) {
439
+ continue;
440
+ }
441
+
442
+ foreach ( (array) $addresses as $address ) {
443
+ try {
444
+ // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>".
445
+ $recipient_name = '';
446
+
447
+ if ( preg_match( '/(.*)<(.+)>/', $address, $matches ) ) {
448
+ if ( count( $matches ) == 3 ) {
449
+ $recipient_name = $matches[1];
450
+ $address = $matches[2];
451
+ }
452
+ }
453
+
454
+ switch ( $address_header ) {
455
+ case 'to':
456
+ $phpmailer->addAddress( $address, $recipient_name );
457
+ break;
458
+ case 'cc':
459
+ $phpmailer->addCc( $address, $recipient_name );
460
+ break;
461
+ case 'bcc':
462
+ $phpmailer->addBcc( $address, $recipient_name );
463
+ break;
464
+ case 'reply_to':
465
+ $phpmailer->addReplyTo( $address, $recipient_name );
466
+ break;
467
+ }
468
+ } catch ( PHPMailer\PHPMailer\Exception $e ) {
469
+ continue;
470
+ }
471
+ }
472
+ }
473
+
474
+ // Set to use PHP's mail().
475
+ $phpmailer->isMail();
476
+
477
+ // Set Content-Type and charset.
478
+
479
+ // If we don't have a content-type from the input headers.
480
+ if ( ! isset( $content_type ) ) {
481
+ $content_type = 'text/plain';
482
+ }
483
+
484
+ /**
485
+ * Filters the wp_mail() content type.
486
+ *
487
+ * @since 2.3.0
488
+ *
489
+ * @param string $content_type Default wp_mail() content type.
490
+ */
491
+ $content_type = apply_filters( 'wp_mail_content_type', $content_type );
492
+
493
+ $phpmailer->ContentType = $content_type;
494
+
495
+ // Set whether it's plaintext, depending on $content_type.
496
+ if ( 'text/html' === $content_type ) {
497
+ $phpmailer->isHTML( true );
498
+ }
499
+
500
+ // If we don't have a charset from the input headers.
501
+ if ( ! isset( $charset ) ) {
502
+ $charset = get_bloginfo( 'charset' );
503
+ }
504
+
505
+ /**
506
+ * Filters the default wp_mail() charset.
507
+ *
508
+ * @since 2.3.0
509
+ *
510
+ * @param string $charset Default email charset.
511
+ */
512
+ $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
513
+
514
+ // Set custom headers.
515
+ if ( ! empty( $headers ) ) {
516
+ foreach ( (array) $headers as $name => $content ) {
517
+ // Only add custom headers not added automatically by PHPMailer.
518
+ if ( ! in_array( $name, array( 'MIME-Version', 'X-Mailer' ), true ) ) {
519
+ try {
520
+ $phpmailer->addCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
521
+ } catch ( PHPMailer\PHPMailer\Exception $e ) {
522
+ continue;
523
+ }
524
+ }
525
+ }
526
+
527
+ if ( false !== stripos( $content_type, 'multipart' ) && ! empty( $boundary ) ) {
528
+ $phpmailer->addCustomHeader( sprintf( 'Content-Type: %s; boundary="%s"', $content_type, $boundary ) );
529
+ }
530
+ }
531
+
532
+ if ( ! empty( $attachments ) ) {
533
+ foreach ( $attachments as $attachment ) {
534
+ try {
535
+ $phpmailer->addAttachment( $attachment );
536
+ } catch ( PHPMailer\PHPMailer\Exception $e ) {
537
+ continue;
538
+ }
539
+ }
540
+ }
541
+
542
+ /**
543
+ * Fires after PHPMailer is initialized.
544
+ *
545
+ * @since 2.2.0
546
+ *
547
+ * @param PHPMailer $phpmailer The PHPMailer instance (passed by reference).
548
+ */
549
+ do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) );
550
+
551
+
552
+ // Send!
553
+ try {
554
+ // Trap the fluentSMTPMail mailer here
555
+ $phpmailer = new FluentMail\App\Services\Mailer\FluentPHPMailer($phpmailer);
556
+ return $phpmailer->send();
557
+
558
+ } catch ( PHPMailer\PHPMailer\Exception $e ) {
559
+
560
+ $mail_error_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
561
+ $mail_error_data['phpmailer_exception_code'] = $e->getCode();
562
+
563
+ /**
564
+ * Fires after a PHPMailer\PHPMailer\Exception is caught.
565
+ *
566
+ * @since 4.4.0
567
+ *
568
+ * @param WP_Error $error A WP_Error object with the PHPMailer\PHPMailer\Exception message, and an array
569
+ * containing the mail recipient, subject, message, headers, and attachments.
570
+ */
571
+ do_action(
572
+ 'wp_mail_failed',
573
+ new WP_Error(
574
+ 'wp_mail_failed',
575
+ $e->getMessage(),
576
+ $mail_error_data
577
+ )
578
+ );
579
+
580
+ return false;
581
+ }
582
+ }
583
+ }
app/Functions/pluggable.php DELETED
@@ -1,474 +0,0 @@
1
- <?php
2
-
3
- if (! function_exists( 'wp_mail' ) ) :
4
- /**
5
- * Sends an email, similar to PHP's mail function.
6
- *
7
- * A true return value does not automatically mean that the user received the
8
- * email successfully. It just only means that the method used was able to
9
- * process the request without any errors.
10
- *
11
- * The default content type is `text/plain` which does not allow using HTML.
12
- * However, you can set the content type of the email by using the
13
- * {@see 'wp_mail_content_type'} filter.
14
- *
15
- * The default charset is based on the charset used on the blog. The charset can
16
- * be set using the {@see 'wp_mail_charset'} filter.
17
- *
18
- * @since 1.2.1
19
- *
20
- * @global PHPMailer\PHPMailer\PHPMailer $phpmailer
21
- *
22
- * @param string|array $to Array or comma-separated list of email addresses to send message.
23
- * @param string $subject Email subject
24
- * @param string $message Message contents
25
- * @param string|array $headers Optional. Additional headers.
26
- * @param string|array $attachments Optional. Files to attach.
27
- * @return bool Whether the email contents were sent successfully.
28
- */
29
- function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {
30
- // Compact the input, apply the filters, and extract them back out.
31
-
32
- /**
33
- * Filters the wp_mail() arguments.
34
- *
35
- * @since 2.2.0
36
- *
37
- * @param array $args A compacted array of wp_mail() arguments, including the "to" email,
38
- * subject, message, headers, and attachments values.
39
- */
40
- $atts = apply_filters(
41
- 'wp_mail', compact('to', 'subject', 'message', 'headers', 'attachments')
42
- );
43
-
44
- /**
45
- * Filters whether to preempt sending an email.
46
- *
47
- * Returning a non-null value will short-circuit {@see wp_mail()}, returning
48
- * that value instead. A boolean return value should be used to indicate whether
49
- * the email was successfully sent.
50
- *
51
- * @since 5.7.0
52
- *
53
- * @param null|bool $return Short-circuit return value.
54
- * @param array $atts {
55
- * Array of the `wp_mail()` arguments.
56
- *
57
- * @type string|string[] $to Array or comma-separated list of email addresses to send message.
58
- * @type string $subject Email subject.
59
- * @type string $message Message contents.
60
- * @type string|string[] $headers Additional headers.
61
- * @type string|string[] $attachments Paths to files to attach.
62
- * }
63
- */
64
- $pre_wp_mail = apply_filters( 'pre_wp_mail', null, $atts );
65
-
66
- if ( null !== $pre_wp_mail ) {
67
- return $pre_wp_mail;
68
- }
69
-
70
-
71
- if ( isset( $atts['to'] ) ) {
72
- $to = $atts['to'];
73
- }
74
-
75
- if ( ! is_array( $to ) ) {
76
- $to = explode( ',', $to );
77
- }
78
-
79
- if ( isset( $atts['subject'] ) ) {
80
- $subject = $atts['subject'];
81
- }
82
-
83
- if ( isset( $atts['message'] ) ) {
84
- $message = $atts['message'];
85
- }
86
-
87
- if ( isset( $atts['headers'] ) ) {
88
- $headers = $atts['headers'];
89
- }
90
-
91
- if ( isset( $atts['attachments'] ) ) {
92
- $attachments = $atts['attachments'];
93
- }
94
-
95
- if ( ! is_array( $attachments ) ) {
96
- $attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
97
- }
98
-
99
- global $phpmailer;
100
-
101
- // (Re)create it, if it's gone missing.
102
- if ( ! ( $phpmailer instanceof PHPMailer\PHPMailer\PHPMailer ) ) {
103
- require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
104
- require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
105
- require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
106
- $phpmailer = new PHPMailer\PHPMailer\PHPMailer( true );
107
-
108
- $phpmailer::$validator = static function ( $email ) {
109
- return (bool) is_email( $email );
110
- };
111
- }
112
-
113
- if (($class = get_class($phpmailer)) != 'PHPMailer\PHPMailer\PHPMailer') {
114
- do_action(
115
- 'wp_mail_failed',
116
- new WP_Error(
117
- 400,
118
- "Oops! PHPMailer is modified by $class."
119
- )
120
- );
121
- }
122
-
123
- // Headers.
124
- $cc = array();
125
- $bcc = array();
126
- $reply_to = array();
127
-
128
- if ( empty( $headers ) ) {
129
- $headers = array();
130
- } else {
131
- if ( ! is_array( $headers ) ) {
132
- // Explode the headers out, so this function can take
133
- // both string headers and an array of headers.
134
- $tempheaders = explode( "\n", str_replace( "\r\n", "\n", $headers ) );
135
- } else {
136
- $tempheaders = $headers;
137
- }
138
- $headers = array();
139
-
140
- // If it's actually got contents.
141
- if ( ! empty( $tempheaders ) ) {
142
- // Iterate through the raw headers.
143
- foreach ( (array) $tempheaders as $header ) {
144
- if ( strpos( $header, ':' ) === false ) {
145
- if ( false !== stripos( $header, 'boundary=' ) ) {
146
- $parts = preg_split( '/boundary=/i', trim( $header ) );
147
- $boundary = trim( str_replace( array( "'", '"' ), '', $parts[1] ) );
148
- }
149
- continue;
150
- }
151
- // Explode them out.
152
- list( $name, $content ) = explode( ':', trim( $header ), 2 );
153
-
154
- // Cleanup crew.
155
- $name = trim( $name );
156
- $content = trim( $content );
157
-
158
- switch ( strtolower( $name ) ) {
159
- // Mainly for legacy -- process a "From:" header if it's there.
160
- case 'from':
161
- $bracket_pos = strpos( $content, '<' );
162
- if ( false !== $bracket_pos ) {
163
- // Text before the bracketed email is the "From" name.
164
- if ( $bracket_pos > 0 ) {
165
- $from_name = substr( $content, 0, $bracket_pos - 1 );
166
- $from_name = str_replace( '"', '', $from_name );
167
- $from_name = trim( $from_name );
168
- }
169
-
170
- $from_email = substr( $content, $bracket_pos + 1 );
171
- $from_email = str_replace( '>', '', $from_email );
172
- $from_email = trim( $from_email );
173
-
174
- // Avoid setting an empty $from_email.
175
- } elseif ( '' !== trim( $content ) ) {
176
- $from_email = trim( $content );
177
- }
178
- break;
179
- case 'content-type':
180
- if ( strpos( $content, ';' ) !== false ) {
181
- list( $type, $charset_content ) = explode( ';', $content );
182
- $content_type = trim( $type );
183
- if ( false !== stripos( $charset_content, 'charset=' ) ) {
184
- $charset = trim( str_replace( array( 'charset=', '"' ), '', $charset_content ) );
185
- } elseif ( false !== stripos( $charset_content, 'boundary=' ) ) {
186
- $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset_content ) );
187
- $charset = '';
188
- }
189
-
190
- // Avoid setting an empty $content_type.
191
- } elseif ( '' !== trim( $content ) ) {
192
- $content_type = trim( $content );
193
- }
194
- break;
195
- case 'cc':
196
- $cc = array_merge( (array) $cc, explode( ',', $content ) );
197
- break;
198
- case 'bcc':
199
- $bcc = array_merge( (array) $bcc, explode( ',', $content ) );
200
- break;
201
- case 'reply-to':
202
- $reply_to = array_merge( (array) $reply_to, explode( ',', $content ) );
203
- break;
204
- default:
205
- // Add it to our grand headers array.
206
- $headers[ trim( $name ) ] = trim( $content );
207
- break;
208
- }
209
- }
210
- }
211
- }
212
-
213
- // Empty out the values that may be set.
214
- $phpmailer->clearAllRecipients();
215
- $phpmailer->clearAttachments();
216
- $phpmailer->clearCustomHeaders();
217
- $phpmailer->clearReplyTos();
218
-
219
-
220
- /*
221
- * If we don't have an email from the input headers, default to wordpress@$sitename
222
- * Some hosts will block outgoing mail from this address if it doesn't exist,
223
- * but there's no easy alternative. Defaulting to admin_email might appear to be
224
- * another option, but some hosts may refuse to relay mail from an unknown domain.
225
- * See https://core.trac.wordpress.org/ticket/5007.
226
- */
227
- $defaultConnection = false;
228
- if ( ! isset( $from_email ) ) {
229
- $defaultConnection = fluentMailDefaultConnection();
230
-
231
- if (!empty($defaultConnection['sender_email'])) {
232
- $from_email = $defaultConnection['sender_email'];
233
- } else {
234
- // Get the site domain and get rid of www.
235
- $sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
236
- if ( 'www.' === substr( $sitename, 0, 4 ) ) {
237
- $sitename = substr( $sitename, 4 );
238
- }
239
- $from_email = 'wordpress@' . $sitename;
240
- }
241
- }
242
-
243
- // Set "From" name and email.
244
- // If we don't have a name from the input headers.
245
- if ( ! isset( $from_name ) ) {
246
- if($defaultConnection && !empty($defaultConnection['sender_name'])) {
247
- $from_name = $defaultConnection['sender_name'];
248
- } else {
249
- $provider = fluentMailGetProvider($from_email);
250
- if ($provider && !empty($provider->getSetting('sender_name'))) {
251
- $from_name = $provider->getSetting('sender_name');
252
- } else {
253
- $from_name = 'WordPress';
254
- }
255
- }
256
- }
257
-
258
- /**
259
- * Filters the email address to send from.
260
- *
261
- * @since 2.2.0
262
- *
263
- * @param string $from_email Email address to send from.
264
- */
265
- $from_email = apply_filters('wp_mail_from', $from_email);
266
-
267
- /**
268
- * Filters the name to associate with the "from" email address.
269
- *
270
- * @since 2.3.0
271
- *
272
- * @param string $from_name Name associated with the "from" email address.
273
- */
274
- $from_name = apply_filters('wp_mail_from_name', $from_name);
275
-
276
- try {
277
- $phpmailer->setFrom( $from_email, $from_name, false );
278
- } catch ( PHPMailer\PHPMailer\Exception $e ) {
279
- $mail_error_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
280
- $mail_error_data['phpmailer_exception_code'] = $e->getCode();
281
-
282
- /** This filter is documented in wp-includes/pluggable.php */
283
- do_action(
284
- 'wp_mail_failed',
285
- new WP_Error(
286
- 'wp_mail_failed',
287
- $e->getMessage(),
288
- $mail_error_data
289
- )
290
- );
291
-
292
- return false;
293
- }
294
-
295
- // Set mail's subject and body.
296
- $phpmailer->Subject = $subject;
297
- $phpmailer->Body = $message;
298
-
299
- // Set destination addresses, using appropriate methods for handling addresses.
300
- $address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' );
301
-
302
- foreach ( $address_headers as $address_header => $addresses ) {
303
- if ( empty( $addresses ) ) {
304
- continue;
305
- }
306
-
307
- foreach ( (array) $addresses as $address ) {
308
- try {
309
- // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>".
310
- $recipient_name = '';
311
-
312
- if ( preg_match( '/(.*)<(.+)>/', $address, $matches ) ) {
313
- if ( count( $matches ) == 3 ) {
314
- $recipient_name = $matches[1];
315
- $address = $matches[2];
316
- }
317
- }
318
-
319
- switch ( $address_header ) {
320
- case 'to':
321
- $phpmailer->addAddress( $address, $recipient_name );
322
- break;
323
- case 'cc':
324
- $phpmailer->addCc( $address, $recipient_name );
325
- break;
326
- case 'bcc':
327
- $phpmailer->addBcc( $address, $recipient_name );
328
- break;
329
- case 'reply_to':
330
- $phpmailer->addReplyTo( $address, $recipient_name );
331
- break;
332
- }
333
- } catch ( PHPMailer\PHPMailer\Exception $e ) {
334
- continue;
335
- }
336
- }
337
- }
338
-
339
- // Set to use PHP's mail().
340
- $phpmailer->isMail();
341
-
342
- // Set Content-Type and charset.
343
-
344
- // If we don't have a content-type from the input headers.
345
- if ( ! isset( $content_type ) ) {
346
- $content_type = 'text/plain';
347
- }
348
-
349
- /**
350
- * Filters the wp_mail() content type.
351
- *
352
- * @since 2.3.0
353
- *
354
- * @param string $content_type Default wp_mail() content type.
355
- */
356
- $content_type = apply_filters( 'wp_mail_content_type', $content_type );
357
-
358
- $phpmailer->ContentType = $content_type;
359
-
360
- // Set whether it's plaintext, depending on $content_type.
361
- if ( 'text/html' === $content_type ) {
362
- $phpmailer->isHTML( true );
363
- }
364
-
365
- // If we don't have a charset from the input headers.
366
- if ( ! isset( $charset ) ) {
367
- $charset = get_bloginfo( 'charset' );
368
- }
369
-
370
- /**
371
- * Filters the default wp_mail() charset.
372
- *
373
- * @since 2.3.0
374
- *
375
- * @param string $charset Default email charset.
376
- */
377
- $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
378
-
379
- // Set custom headers.
380
- if ( ! empty( $headers ) ) {
381
- foreach ( (array) $headers as $name => $content ) {
382
- // Only add custom headers not added automatically by PHPMailer.
383
- if ( ! in_array( $name, array( 'MIME-Version', 'X-Mailer' ), true ) ) {
384
- try {
385
- $phpmailer->addCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
386
- } catch ( PHPMailer\PHPMailer\Exception $e ) {
387
- continue;
388
- }
389
- }
390
- }
391
-
392
- if ( false !== stripos( $content_type, 'multipart' ) && ! empty( $boundary ) ) {
393
- $phpmailer->addCustomHeader( sprintf( 'Content-Type: %s; boundary="%s"', $content_type, $boundary ) );
394
- }
395
- }
396
-
397
- if ( ! empty( $attachments ) ) {
398
- foreach ( $attachments as $attachment ) {
399
- try {
400
- $phpmailer->addAttachment( $attachment );
401
- } catch ( PHPMailer\PHPMailer\Exception $e ) {
402
- continue;
403
- }
404
- }
405
- }
406
-
407
- /**
408
- * Fires after PHPMailer is initialized.
409
- *
410
- * @since 2.2.0
411
- *
412
- * @param PHPMailer $phpmailer The PHPMailer instance (passed by reference).
413
- */
414
- do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) );
415
-
416
-
417
- // Send!
418
- try {
419
- // Trap the fluentSMTPMail mailer here
420
- $phpmailer = new FluentMail\App\Services\Mailer\FluentPHPMailer($phpmailer);
421
- return $phpmailer->send();
422
-
423
- } catch ( PHPMailer\PHPMailer\Exception $e ) {
424
-
425
- $mail_error_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
426
- $mail_error_data['phpmailer_exception_code'] = $e->getCode();
427
-
428
- /**
429
- * Fires after a PHPMailer\PHPMailer\Exception is caught.
430
- *
431
- * @since 4.4.0
432
- *
433
- * @param WP_Error $error A WP_Error object with the PHPMailer\PHPMailer\Exception message, and an array
434
- * containing the mail recipient, subject, message, headers, and attachments.
435
- */
436
- do_action(
437
- 'wp_mail_failed',
438
- new WP_Error(
439
- 'wp_mail_failed',
440
- $e->getMessage(),
441
- $mail_error_data
442
- )
443
- );
444
-
445
- return false;
446
- }
447
- }
448
- else:
449
- if (! (defined( 'DOING_AJAX' ) && DOING_AJAX) ):
450
- add_action('admin_notices', function() {
451
- if(!current_user_can('manage_options')) {
452
- return;
453
- }
454
- $details = new ReflectionFunction('wp_mail');
455
- $hints = $details->getFileName() . ':' . $details->getStartLine();
456
- ?>
457
- <div class="notice notice-warning is-dismissible">
458
- <p>
459
- <?php
460
- echo sprintf(
461
- __('The <strong>FluentSMTP</strong> plugin depends on
462
- <a target="_blank" href="%1s">wp_mail</a> pluggable function and
463
- plugin is not able to extend it. Please check if another plugin is using this and disable it for <strong>FluentSMTP</strong> to work!',
464
- 'fluent-smtp'), 'https://developer.wordpress.org/reference/functions/wp_mail/'
465
- );
466
- ?>
467
- </p>
468
- <p style="color: red;"><?php _e('Possible Conflict: ', 'fluent-smtp'); ?><?php echo $hints;?></p>
469
- </div>
470
- <?php
471
- });
472
- endif;
473
- endif;
474
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/Models/Logger.php CHANGED
@@ -392,10 +392,8 @@ class Logger extends Model
392
  {
393
  try {
394
 
395
- $date = date('Y-m-d', current_time('timestamp') - $days * DAY_IN_SECONDS);
396
-
397
- $query = "DELETE FROM {$this->table} WHERE `created_at` < $date";
398
-
399
  return $this->db->query($query);
400
 
401
  } catch (Exception $e) {
392
  {
393
  try {
394
 
395
+ $date = date('Y-m-d H:i:s', current_time('timestamp') - $days * DAY_IN_SECONDS);
396
+ $query = $this->db->prepare("DELETE FROM %s WHERE `created_at` < %s", $this->table, $date);
 
 
397
  return $this->db->query($query);
398
 
399
  } catch (Exception $e) {
app/Services/Mailer/Providers/ElasticMail/Handler.php ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FluentMail\App\Services\Mailer\Providers\ElasticMail;
4
+
5
+ use FluentMail\Includes\Support\Arr;
6
+ use FluentMail\App\Services\Mailer\BaseHandler;
7
+
8
+ class Handler extends BaseHandler
9
+ {
10
+ use ValidatorTrait;
11
+
12
+ protected $emailSentCode = 200;
13
+
14
+ protected $url = 'https://api.postmarkapp.com/email';
15
+
16
+ public function send()
17
+ {
18
+ if ($this->preSend() && $this->phpMailer->preSend()) {
19
+ return $this->postSend();
20
+ }
21
+
22
+ return $this->handleResponse(new \WP_Error(423, 'Something went wrong!', []));
23
+ }
24
+
25
+ public function postSend()
26
+ {
27
+ $body = [
28
+ 'From' => $this->getParam('from'),
29
+ 'To' => $this->getTo(),
30
+ 'Subject' => $this->getSubject(),
31
+ 'MessageStream' => $this->getSetting('message_stream', 'outbound')
32
+ ];
33
+
34
+ if ($replyTo = $this->getReplyTo()) {
35
+ $body['ReplyTo'] = $replyTo;
36
+ }
37
+
38
+ if ($bcc = $this->getBlindCarbonCopy()) {
39
+ $body['Bcc'] = $bcc;
40
+ }
41
+
42
+ if ($cc = $this->getCarbonCopy()) {
43
+ $body['Cc'] = $cc;
44
+ }
45
+
46
+ if ($this->getHeader('content-type') == 'text/html') {
47
+ $body['HtmlBody'] = $this->getParam('message');
48
+
49
+ if ($this->getSetting('track_opens') == 'yes') {
50
+ $body['TrackOpens'] = true;
51
+ }
52
+
53
+ if ($this->getSetting('track_links') == 'yes') {
54
+ $body['TrackLinks'] = 'HtmlOnly';
55
+ }
56
+
57
+ } else {
58
+ $body['TextBody'] = $this->getParam('message');
59
+ }
60
+
61
+ if (!empty($this->getParam('attachments'))) {
62
+ $body['Attachments'] = $this->getAttachments();
63
+ }
64
+
65
+ // Handle apostrophes in email address From names by escaping them for the Postmark API.
66
+ $from_regex = "/(\"From\": \"[a-zA-Z\\d]+)*[\\\\]{2,}'/";
67
+
68
+ $args = array(
69
+ 'headers' => $this->getRequestHeaders(),
70
+ 'body' => preg_replace($from_regex, "'", wp_json_encode($body), 1),
71
+ );
72
+
73
+ $response = wp_remote_post($this->url, $args);
74
+
75
+ if (is_wp_error($response)) {
76
+ $returnResponse = new \WP_Error($response->get_error_code(), $response->get_error_message(), $response->get_error_messages());
77
+ } else {
78
+ $responseBody = wp_remote_retrieve_body($response);
79
+ $responseCode = wp_remote_retrieve_response_code($response);
80
+
81
+ $isOKCode = $responseCode == $this->emailSentCode;
82
+
83
+ $responseBody = \json_decode($responseBody, true);
84
+
85
+ if ($isOKCode) {
86
+ $returnResponse = [
87
+ 'id' => Arr::get($responseBody, 'MessageID'),
88
+ 'message' => Arr::get($responseBody, 'Message')
89
+ ];
90
+ } else {
91
+ $returnResponse = new \WP_Error($responseCode, Arr::get($responseBody, 'Message', 'Unknown Error'), $responseBody);
92
+ }
93
+ }
94
+
95
+ $this->response = $returnResponse;
96
+
97
+ return $this->handleResponse($this->response);
98
+ }
99
+
100
+ public function setSettings($settings)
101
+ {
102
+ if ($settings['key_store'] == 'wp_config') {
103
+ $settings['api_key'] = defined('FLUENTMAIL_ELASTICMAIL_API_KEY') ? FLUENTMAIL_ELASTICMAIL_API_KEY : '';
104
+ }
105
+
106
+ $this->settings = $settings;
107
+ return $this;
108
+ }
109
+
110
+ protected function getReplyTo()
111
+ {
112
+ if ($replyTo = $this->getParam('headers.reply-to')) {
113
+ $replyTo = reset($replyTo);
114
+ return $replyTo['email'];
115
+ }
116
+ }
117
+
118
+ protected function getTo()
119
+ {
120
+ return $this->getRecipients($this->getParam('to'));
121
+ }
122
+
123
+ protected function getCarbonCopy()
124
+ {
125
+ return $this->getRecipients($this->getParam('headers.cc'));
126
+ }
127
+
128
+ protected function getBlindCarbonCopy()
129
+ {
130
+ return $this->getRecipients($this->getParam('headers.bcc'));
131
+ }
132
+
133
+ protected function getRecipients($recipients)
134
+ {
135
+ $array = array_map(function ($recipient) {
136
+ return isset($recipient['name'])
137
+ ? $recipient['name'] . ' <' . $recipient['email'] . '>'
138
+ : $recipient['email'];
139
+ }, $recipients);
140
+
141
+ return implode(', ', $array);
142
+ }
143
+
144
+ protected function getAttachments()
145
+ {
146
+ $data = [];
147
+
148
+ foreach ($this->getParam('attachments') as $attachment) {
149
+ $file = false;
150
+
151
+ try {
152
+ if (is_file($attachment[0]) && is_readable($attachment[0])) {
153
+ $fileName = basename($attachment[0]);
154
+ $file = file_get_contents($attachment[0]);
155
+ }
156
+ } catch (\Exception $e) {
157
+ $file = false;
158
+ }
159
+
160
+ if ($file === false) {
161
+ continue;
162
+ }
163
+
164
+ $data[] = [
165
+ 'Name' => $fileName,
166
+ 'Content' => base64_encode($file),
167
+ 'ContentType' => $this->determineMimeContentRype($attachment[0])
168
+ ];
169
+ }
170
+
171
+ return $data;
172
+ }
173
+
174
+ protected function getRequestHeaders()
175
+ {
176
+ return [
177
+ 'Accept' => 'application/json',
178
+ 'Content-Type' => 'application/json',
179
+ 'X-Postmark-Server-Token' => $this->getSetting('api_key'),
180
+ ];
181
+ }
182
+
183
+ protected function determineMimeContentRype($filename)
184
+ {
185
+ if (function_exists('mime_content_type')) {
186
+ return mime_content_type($filename);
187
+ } elseif (function_exists('finfo_open')) {
188
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
189
+ $mime_type = finfo_file($finfo, $filename);
190
+ finfo_close($finfo);
191
+ return $mime_type;
192
+ } else {
193
+ return 'application/octet-stream';
194
+ }
195
+ }
196
+ }
app/Services/Mailer/Providers/ElasticMail/ValidatorTrait.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FluentMail\App\Services\Mailer\Providers\ElasticMail;
4
+
5
+ use FluentMail\Includes\Support\Arr;
6
+ use FluentMail\App\Services\Mailer\ValidatorTrait as BaseValidatorTrait;
7
+
8
+ trait ValidatorTrait
9
+ {
10
+ use BaseValidatorTrait;
11
+
12
+ public function validateProviderInformation($connection)
13
+ {
14
+ $errors = [];
15
+
16
+ $keyStoreType = $connection['key_store'];
17
+
18
+ if($keyStoreType == 'db') {
19
+ if (! Arr::get($connection, 'api_key')) {
20
+ $errors['api_key']['required'] = __('Api key is required.', 'fluent-smtp');
21
+ }
22
+ } else if($keyStoreType == 'wp_config') {
23
+ if(!defined('FLUENTMAIL_ELASTICMAIL_API_KEY') || !FLUENTMAIL_ELASTICMAIL_API_KEY) {
24
+ $errors['api_key']['required'] = __('Please define FLUENTMAIL_ELASTICMAIL_API_KEY in wp-config.php file.', 'fluent-smtp');
25
+ }
26
+ }
27
+
28
+ if ($errors) {
29
+ $this->throwValidationException($errors);
30
+ }
31
+ }
32
+ }
app/Services/Mailer/Providers/Gmail/Handler.php CHANGED
@@ -57,7 +57,6 @@ class Handler extends BaseHandler
57
  $googleClient = $this->getApiClient($data);
58
  $googleService = new \Google_Service_Gmail($googleClient);
59
 
60
-
61
  $result = array();
62
  try {
63
  $googleClient->setDefer(true);
57
  $googleClient = $this->getApiClient($data);
58
  $googleService = new \Google_Service_Gmail($googleClient);
59
 
 
60
  $result = array();
61
  try {
62
  $googleClient->setDefer(true);
app/Services/Mailer/Providers/PepiPost/Handler.php CHANGED
@@ -189,9 +189,7 @@ class Handler extends BaseHandler
189
 
190
  protected function getCustomEmailHeaders()
191
  {
192
- return [
193
- 'X-Mailer' => 'FluentMail - PepiPost'
194
- ];
195
  }
196
 
197
  protected function getRequestHeaders()
189
 
190
  protected function getCustomEmailHeaders()
191
  {
192
+ return [];
 
 
193
  }
194
 
195
  protected function getRequestHeaders()
app/Services/Mailer/Providers/SendGrid/Handler.php CHANGED
@@ -32,8 +32,7 @@ class Handler extends BaseHandler
32
  'from' => $this->getFrom(),
33
  'personalizations' => $this->getRecipients(),
34
  'subject' => $this->getSubject(),
35
- 'content' => $this->getBody(),
36
- 'headers' => $this->getCustomEmailHeaders()
37
  ];
38
 
39
  if ($replyTo = $this->getReplyTo()) {
@@ -95,7 +94,6 @@ class Handler extends BaseHandler
95
  if ($replyTo = $this->getParam('headers.reply-to')) {
96
  return reset($replyTo);
97
  }
98
-
99
  }
100
 
101
  protected function getRecipients()
@@ -183,9 +181,7 @@ class Handler extends BaseHandler
183
 
184
  protected function getCustomEmailHeaders()
185
  {
186
- return [
187
- 'X-Mailer' => 'FluentMail - SendGrid'
188
- ];
189
  }
190
 
191
  protected function getRequestHeaders()
32
  'from' => $this->getFrom(),
33
  'personalizations' => $this->getRecipients(),
34
  'subject' => $this->getSubject(),
35
+ 'content' => $this->getBody()
 
36
  ];
37
 
38
  if ($replyTo = $this->getReplyTo()) {
94
  if ($replyTo = $this->getParam('headers.reply-to')) {
95
  return reset($replyTo);
96
  }
 
97
  }
98
 
99
  protected function getRecipients()
181
 
182
  protected function getCustomEmailHeaders()
183
  {
184
+ return [];
 
 
185
  }
186
 
187
  protected function getRequestHeaders()
app/Services/Mailer/Providers/SendInBlue/Handler.php CHANGED
@@ -39,10 +39,16 @@ class Handler extends BaseHandler
39
  $body = [
40
  'sender' => $this->getFrom(),
41
  'subject' => $this->getSubject(),
42
- 'htmlContent' => $this->getBody(),
43
- 'headers' => $this->getCustomEmailHeaders()
44
  ];
45
 
 
 
 
 
 
 
 
46
  if ($replyTo = $this->getReplyTo()) {
47
  $body['replyTo'] = $replyTo;
48
  }
@@ -177,15 +183,12 @@ class Handler extends BaseHandler
177
 
178
  protected function getCustomEmailHeaders()
179
  {
180
- return [
181
- 'X-Mailer' => 'FluentMail - SendInBlue'
182
- ];
183
  }
184
 
185
  protected function getRequestHeaders()
186
  {
187
  return [
188
- 'X-Mailer' => 'FluentMail-SendInBlue',
189
  'Api-Key' => $this->getSetting('api_key'),
190
  'Content-Type' => 'application/json',
191
  'Accept' => 'application/json'
39
  $body = [
40
  'sender' => $this->getFrom(),
41
  'subject' => $this->getSubject(),
42
+ 'htmlContent' => $this->getBody()
 
43
  ];
44
 
45
+ $contentType = $this->getParam('headers.content-type');
46
+
47
+ if($contentType == 'text/plain') {
48
+ $body['textContent'] = $this->getBody();
49
+ unset($body['htmlContent']);
50
+ }
51
+
52
  if ($replyTo = $this->getReplyTo()) {
53
  $body['replyTo'] = $replyTo;
54
  }
183
 
184
  protected function getCustomEmailHeaders()
185
  {
186
+ return [];
 
 
187
  }
188
 
189
  protected function getRequestHeaders()
190
  {
191
  return [
 
192
  'Api-Key' => $this->getSetting('api_key'),
193
  'Content-Type' => 'application/json',
194
  'Accept' => 'application/json'
app/Services/Mailer/Providers/config.php CHANGED
@@ -4,7 +4,7 @@ return [
4
  'connections' => [],
5
  'mappings' => [],
6
  'providers' => [
7
- 'smtp' => [
8
  'key' => 'smtp',
9
  'title' => __('SMTP', 'fluent-smtp'),
10
  'image' => fluentMailAssetUrl('images/smtp.svg'),
@@ -28,7 +28,7 @@ return [
28
  ],
29
  'note' => '<a href="https://fluentsmtp.com/docs/set-up-fluent-smtp-with-any-host-or-mailer/">Read the documentation</a> for how to configure any SMTP with FluentSMTP.'
30
  ],
31
- 'ses' => [
32
  'key' => 'ses',
33
  'title' => __('Amazon SES', 'fluent-smtp'),
34
  'image' => fluentMailAssetUrl('images/amazon.png'),
@@ -69,7 +69,7 @@ return [
69
  ],
70
  'note' => '<a href="https://fluentsmtp.com/docs/set-up-amazon-ses-in-fluent-smtp/">Read the documentation</a> for how to configure Amazon SES with FluentSMTP.'
71
  ],
72
- 'mailgun' => [
73
  'key' => 'mailgun',
74
  'title' => __('Mailgun', 'fluent-smtp'),
75
  'image' => fluentMailAssetUrl('images/mailgun.svg'),
@@ -86,7 +86,7 @@ return [
86
  ],
87
  'note' => '<a href="https://fluentsmtp.com/docs/configure-mailgun-in-fluent-smtp-to-send-emails/">Read the documentation</a> for how to configure Mailgun with FluentSMTP.'
88
  ],
89
- 'sendgrid' => [
90
  'key' => 'sendgrid',
91
  'title' => __('SendGrid', 'fluent-smtp'),
92
  'image' => fluentMailAssetUrl('images/sendgrid.svg'),
@@ -100,7 +100,7 @@ return [
100
  ],
101
  'note' => '<a href="https://fluentsmtp.com/docs/set-up-the-sendgrid-driver-in-fluent-smtp/">Read the documentation</a> for how to configure sendgrid with FluentSMTP.'
102
  ],
103
- 'sendinblue' => [
104
  'key' => 'sendinblue',
105
  'title' => __('Sendinblue', 'fluent-smtp'),
106
  'image' => fluentMailAssetUrl('images/sendinblue.svg'),
@@ -114,7 +114,7 @@ return [
114
  ],
115
  'note' => '<a href="https://fluentsmtp.com/docs/setting-up-sendinblue-mailer-in-fluent-smtp/">Read the documentation</a> for how to configure Sendinblue with FluentSMTP.'
116
  ],
117
- 'sparkpost' => [
118
  'key' => 'sparkpost',
119
  'title' => __('SparkPost', 'fluent-smtp'),
120
  'image' => fluentMailAssetUrl('images/sparkpost.png'),
@@ -128,7 +128,7 @@ return [
128
  ],
129
  'note' => '<a href="https://fluentsmtp.com/docs/configure-sparkpost-in-fluent-smtp-to-send-emails/">Read the documentation</a> for how to configure SparkPost with FluentSMTP.'
130
  ],
131
- 'pepipost' => [
132
  'key' => 'pepipost',
133
  'title' => __('Pepipost', 'fluent-smtp'),
134
  'image' => fluentMailAssetUrl('images/pepipost-logo.png'),
@@ -142,7 +142,7 @@ return [
142
  ],
143
  'note' => '<a href="https://fluentsmtp.com/docs/set-up-the-pepipost-mailer-in-fluent-smtp/">Read the documentation</a> for how to configure Pepipost with FluentSMTP.'
144
  ],
145
- 'postmark' => [
146
  'key' => 'postmark',
147
  'title' => __('Postmark', 'fluent-smtp'),
148
  'image' => fluentMailAssetUrl('images/postmark.svg'),
@@ -159,7 +159,22 @@ return [
159
  ],
160
  'note' => '<a href="https://fluentsmtp.com/docs/configure-postmark-in-fluent-smtp-to-send-emails/">Read the documentation</a> for how to configure Postmark with FluentSMTP.'
161
  ],
162
- 'gmail' => [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  'key' => 'gmail',
164
  'title' => __('Gmail/Google Workspace', 'fluent-smtp'),
165
  'image' => fluentMailAssetUrl('images/gmail-logo.png'),
@@ -178,7 +193,7 @@ return [
178
  ],
179
  'note' => __('Gmail/Google Workspace is not recommended for sending mass marketing emails.', 'fluent-smtp')
180
  ],
181
- 'outlook' => [
182
  'key' => 'outlook',
183
  'title' => __('Outlook/Office365', 'fluent-smtp'),
184
  'image' => fluentMailAssetUrl('images/microsoft.svg'),
@@ -197,7 +212,7 @@ return [
197
  ],
198
  'note' => __('Outlook/Office365 is not recommended for sending mass marketing emails.', 'fluent-smtp')
199
  ],
200
- 'default' => [
201
  'key' => 'default',
202
  'title' => __('PHP Mail', 'fluent-smtp'),
203
  'image' => fluentMailAssetUrl('images/default.svg'),
4
  'connections' => [],
5
  'mappings' => [],
6
  'providers' => [
7
+ 'smtp' => [
8
  'key' => 'smtp',
9
  'title' => __('SMTP', 'fluent-smtp'),
10
  'image' => fluentMailAssetUrl('images/smtp.svg'),
28
  ],
29
  'note' => '<a href="https://fluentsmtp.com/docs/set-up-fluent-smtp-with-any-host-or-mailer/">Read the documentation</a> for how to configure any SMTP with FluentSMTP.'
30
  ],
31
+ 'ses' => [
32
  'key' => 'ses',
33
  'title' => __('Amazon SES', 'fluent-smtp'),
34
  'image' => fluentMailAssetUrl('images/amazon.png'),
69
  ],
70
  'note' => '<a href="https://fluentsmtp.com/docs/set-up-amazon-ses-in-fluent-smtp/">Read the documentation</a> for how to configure Amazon SES with FluentSMTP.'
71
  ],
72
+ 'mailgun' => [
73
  'key' => 'mailgun',
74
  'title' => __('Mailgun', 'fluent-smtp'),
75
  'image' => fluentMailAssetUrl('images/mailgun.svg'),
86
  ],
87
  'note' => '<a href="https://fluentsmtp.com/docs/configure-mailgun-in-fluent-smtp-to-send-emails/">Read the documentation</a> for how to configure Mailgun with FluentSMTP.'
88
  ],
89
+ 'sendgrid' => [
90
  'key' => 'sendgrid',
91
  'title' => __('SendGrid', 'fluent-smtp'),
92
  'image' => fluentMailAssetUrl('images/sendgrid.svg'),
100
  ],
101
  'note' => '<a href="https://fluentsmtp.com/docs/set-up-the-sendgrid-driver-in-fluent-smtp/">Read the documentation</a> for how to configure sendgrid with FluentSMTP.'
102
  ],
103
+ 'sendinblue' => [
104
  'key' => 'sendinblue',
105
  'title' => __('Sendinblue', 'fluent-smtp'),
106
  'image' => fluentMailAssetUrl('images/sendinblue.svg'),
114
  ],
115
  'note' => '<a href="https://fluentsmtp.com/docs/setting-up-sendinblue-mailer-in-fluent-smtp/">Read the documentation</a> for how to configure Sendinblue with FluentSMTP.'
116
  ],
117
+ 'sparkpost' => [
118
  'key' => 'sparkpost',
119
  'title' => __('SparkPost', 'fluent-smtp'),
120
  'image' => fluentMailAssetUrl('images/sparkpost.png'),
128
  ],
129
  'note' => '<a href="https://fluentsmtp.com/docs/configure-sparkpost-in-fluent-smtp-to-send-emails/">Read the documentation</a> for how to configure SparkPost with FluentSMTP.'
130
  ],
131
+ 'pepipost' => [
132
  'key' => 'pepipost',
133
  'title' => __('Pepipost', 'fluent-smtp'),
134
  'image' => fluentMailAssetUrl('images/pepipost-logo.png'),
142
  ],
143
  'note' => '<a href="https://fluentsmtp.com/docs/set-up-the-pepipost-mailer-in-fluent-smtp/">Read the documentation</a> for how to configure Pepipost with FluentSMTP.'
144
  ],
145
+ 'postmark' => [
146
  'key' => 'postmark',
147
  'title' => __('Postmark', 'fluent-smtp'),
148
  'image' => fluentMailAssetUrl('images/postmark.svg'),
159
  ],
160
  'note' => '<a href="https://fluentsmtp.com/docs/configure-postmark-in-fluent-smtp-to-send-emails/">Read the documentation</a> for how to configure Postmark with FluentSMTP.'
161
  ],
162
+ // 'elasticmail' => [
163
+ // 'key' => 'elasticmail',
164
+ // 'title' => __('Elastic Mail', 'fluent-smtp'),
165
+ // 'image' => fluentMailAssetUrl('images/elastic_mail.svg'),
166
+ // 'provider' => 'ElasticMail',
167
+ // 'options' => [
168
+ // 'sender_name' => '',
169
+ // 'sender_email' => '',
170
+ // 'force_from_name' => 'no',
171
+ // 'api_key' => '',
172
+ // 'mail_type' => 'transactional',
173
+ // 'key_store' => 'db'
174
+ // ],
175
+ // 'note' => '<a href="https://fluentsmtp.com/docs/set-up-the-elastic-mail-driver-in-fluent-smtp/">Read the documentation</a> for how to configure sendgrid with FluentSMTP.'
176
+ // ],
177
+ 'gmail' => [
178
  'key' => 'gmail',
179
  'title' => __('Gmail/Google Workspace', 'fluent-smtp'),
180
  'image' => fluentMailAssetUrl('images/gmail-logo.png'),
193
  ],
194
  'note' => __('Gmail/Google Workspace is not recommended for sending mass marketing emails.', 'fluent-smtp')
195
  ],
196
+ 'outlook' => [
197
  'key' => 'outlook',
198
  'title' => __('Outlook/Office365', 'fluent-smtp'),
199
  'image' => fluentMailAssetUrl('images/microsoft.svg'),
212
  ],
213
  'note' => __('Outlook/Office365 is not recommended for sending mass marketing emails.', 'fluent-smtp')
214
  ],
215
+ 'default' => [
216
  'key' => 'default',
217
  'title' => __('PHP Mail', 'fluent-smtp'),
218
  'image' => fluentMailAssetUrl('images/default.svg'),
assets/admin/js/fluent-mail-admin-app.js CHANGED
@@ -1 +1 @@
1
- (()=>{var t={7757:(t,e,n)=>{t.exports=n(5666)},8552:(t,e,n)=>{var r=n(852)(n(5639),"DataView");t.exports=r},1989:(t,e,n)=>{var r=n(1789),o=n(401),s=n(7667),i=n(1327),a=n(1866);function l(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}l.prototype.clear=r,l.prototype.delete=o,l.prototype.get=s,l.prototype.has=i,l.prototype.set=a,t.exports=l},8407:(t,e,n)=>{var r=n(7040),o=n(4125),s=n(2117),i=n(7529),a=n(4705);function l(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}l.prototype.clear=r,l.prototype.delete=o,l.prototype.get=s,l.prototype.has=i,l.prototype.set=a,t.exports=l},7071:(t,e,n)=>{var r=n(852)(n(5639),"Map");t.exports=r},3369:(t,e,n)=>{var r=n(4785),o=n(1285),s=n(6e3),i=n(9916),a=n(5265);function l(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}l.prototype.clear=r,l.prototype.delete=o,l.prototype.get=s,l.prototype.has=i,l.prototype.set=a,t.exports=l},3818:(t,e,n)=>{var r=n(852)(n(5639),"Promise");t.exports=r},8525:(t,e,n)=>{var r=n(852)(n(5639),"Set");t.exports=r},8668:(t,e,n)=>{var r=n(3369),o=n(619),s=n(2385);function i(t){var e=-1,n=null==t?0:t.length;for(this.__data__=new r;++e<n;)this.add(t[e])}i.prototype.add=i.prototype.push=o,i.prototype.has=s,t.exports=i},6384:(t,e,n)=>{var r=n(8407),o=n(7465),s=n(3779),i=n(7599),a=n(4758),l=n(4309);function c(t){var e=this.__data__=new r(t);this.size=e.size}c.prototype.clear=o,c.prototype.delete=s,c.prototype.get=i,c.prototype.has=a,c.prototype.set=l,t.exports=c},2705:(t,e,n)=>{var r=n(5639).Symbol;t.exports=r},1149:(t,e,n)=>{var r=n(5639).Uint8Array;t.exports=r},577:(t,e,n)=>{var r=n(852)(n(5639),"WeakMap");t.exports=r},7412:t=>{t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length;++n<r&&!1!==e(t[n],n,t););return t}},4963:t=>{t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length,o=0,s=[];++n<r;){var i=t[n];e(i,n,t)&&(s[o++]=i)}return s}},4636:(t,e,n)=>{var r=n(2545),o=n(5694),s=n(1469),i=n(4144),a=n(5776),l=n(6719),c=Object.prototype.hasOwnProperty;t.exports=function(t,e){var n=s(t),u=!n&&o(t),p=!n&&!u&&i(t),f=!n&&!u&&!p&&l(t),_=n||