PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 4.9.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v4.9.0
4.9.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 / Queue / Email.php
wp-mail-smtp / src / Queue Last commit date
Attachments.php 6 days ago Email.php 6 days ago Migration.php 6 days ago Queue.php 6 days ago
Email.php
609 lines
1 <?php
2
3 namespace WPMailSMTP\Queue;
4
5 use WPMailSMTP\WP;
6 use DateTime;
7 use DateTimeZone;
8 use Exception;
9
10 /**
11 * Class Email.
12 *
13 * @since 4.0.0
14 */
15 class Email {
16
17 /**
18 * This email is enqueued.
19 *
20 * @since 4.0.0
21 */
22 const STATUS_QUEUED = 0;
23
24 /**
25 * This email is being processed.
26 *
27 * @since 4.0.0
28 */
29 const STATUS_PROCESSING = 1;
30
31 /**
32 * This email has been processed.
33 *
34 * @since 4.0.0
35 */
36 const STATUS_PROCESSED = 2;
37
38 /**
39 * ID of the email.
40 *
41 * @since 4.0.0
42 *
43 * @var int
44 */
45 private $id = 0;
46
47 /**
48 * Serialized WPMailInitiator state of this email.
49 *
50 * @since 4.0.0
51 *
52 * @var array
53 */
54 private $initiator_state = [];
55
56 /**
57 * Serialized arguments of this email's original wp_mail call.
58 *
59 * @since 4.0.0
60 *
61 * @var array
62 */
63 private $wp_mail_args = [];
64
65 /**
66 * Serialized connection data of this email.
67 *
68 * @since 4.0.0
69 *
70 * @var array
71 */
72 private $connection_data = [];
73
74 /**
75 * Serialized MailCatcher state of this email.
76 *
77 * @since 4.0.0
78 *
79 * @var array
80 */
81 private $mailer_state = [];
82
83 /**
84 * Status of this email.
85 *
86 * @since 4.0.0
87 *
88 * @var int
89 */
90 private $status = 0;
91
92 /**
93 * Date and time this email was enqueued at.
94 *
95 * @since 4.0.0
96 *
97 * @var DateTime
98 */
99 private $date_enqueued;
100
101 /**
102 * Date and time this email was processed at.
103 *
104 * @since 4.0.0
105 *
106 * @var DateTime
107 */
108 private $date_processed;
109
110 /**
111 * Email constructor.
112 *
113 * @since 4.0.0
114 */
115 public function __construct() {
116
117 $this->date_enqueued = new DateTime( 'now', new DateTimeZone( 'UTC' ) );
118 }
119
120 /**
121 * Get a list of allowed statuses.
122 *
123 * @since 4.0.0
124 *
125 * @return array
126 */
127 public static function get_statuses() {
128
129 return [
130 self::STATUS_QUEUED,
131 self::STATUS_PROCESSING,
132 self::STATUS_PROCESSED,
133 ];
134 }
135
136 /**
137 * Construct an email from an array of data.
138 *
139 * @since 4.0.0
140 *
141 * @param object $data Database row object.
142 *
143 * @throws Exception If supplied data is missing or malformed.
144 *
145 * @return Email
146 */
147 public static function from_data( $data ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
148
149 if ( is_null( $data ) ) {
150 throw new Exception( esc_html__( 'Record not found in DB', 'wp-mail-smtp' ) );
151 }
152
153 if (
154 ! is_object( $data ) ||
155 ! property_exists( $data, 'data' ) ||
156 ! isset(
157 $data->id,
158 $data->status,
159 $data->date_enqueued
160 )
161 ) {
162 throw new Exception( esc_html__( 'Invalid record format', 'wp-mail-smtp' ) );
163 }
164
165 // Data can be null if email has been anonymized.
166 // Only check for valid JSON if data isn't null.
167 if ( ! is_null( $data->data ) && ! WP::is_json( $data->data ) ) {
168 throw new Exception(
169 sprintf(
170 /* translators: %1$s - JSON error message. */
171 esc_html__( 'Data JSON decoding error: %1$s', 'wp-mail-smtp' ),
172 esc_html( json_last_error_msg() )
173 )
174 );
175 }
176
177 $email = new Email();
178 $email_data = is_null( $data->data ) ? [] : json_decode( $data->data, true );
179 $email_data = wp_parse_args(
180 $email_data,
181 [
182 'initiator_state' => [],
183 'wp_mail_args' => [],
184 'connection_data' => [],
185 'mailer_state' => [],
186 ]
187 );
188
189 $email->id = (int) $data->id;
190 $email->initiator_state = $email_data['initiator_state'];
191 $email->wp_mail_args = $email_data['wp_mail_args'];
192 $email->connection_data = $email_data['connection_data'];
193 $email->mailer_state = $email_data['mailer_state'];
194 $email->status = (int) $data->status;
195 $email->date_enqueued = $email->get_datetime( $data->date_enqueued );
196
197 if ( isset( $data->date_processed ) ) {
198 $email->date_processed = $email->get_datetime( $data->date_processed );
199 }
200
201 return $email;
202 }
203
204 /**
205 * Get this email's ID.
206 *
207 * @since 4.0.0
208 *
209 * @return int
210 */
211 public function get_id() {
212
213 return (int) $this->id;
214 }
215
216 /**
217 * Get this email's status.
218 *
219 * @since 4.0.0
220 *
221 * @return int
222 */
223 public function get_status() {
224
225 return $this->status;
226 }
227
228 /**
229 * Set this email's status.
230 *
231 * @since 4.0.0
232 *
233 * @param int $status Email status.
234 *
235 * @return Email
236 */
237 public function set_status( $status ) {
238
239 $status = (int) $status;
240
241 if ( ! in_array( $status, self::get_statuses(), true ) ) {
242 $status = self::STATUS_QUEUED;
243 }
244
245 $this->status = $status;
246
247 return $this;
248 }
249
250 /**
251 * Get this email's `wp_mail` call arguments.
252 *
253 * @since 4.0.0
254 *
255 * @return array
256 */
257 public function get_wp_mail_args() {
258
259 return $this->wp_mail_args;
260 }
261
262 /**
263 * Set this email's `wp_mail` call arguments.
264 *
265 * @since 4.0.0
266 *
267 * @param array $args Array of arguments.
268 *
269 * @return Email
270 */
271 public function set_wp_mail_args( $args ) {
272
273 $args = wp_parse_args(
274 $args,
275 [
276 'headers' => '',
277 'attachments' => [],
278 ]
279 );
280
281 $this->wp_mail_args = $args;
282
283 return $this;
284 }
285
286 /**
287 * Get this email's MailCatcher state.
288 *
289 * @since 4.0.0
290 *
291 * @return array
292 */
293 public function get_connection_data() {
294
295 return $this->connection_data;
296 }
297
298 /**
299 * Set this email's connection data.
300 *
301 * @since 4.0.0
302 *
303 * @param array $data Connection data.
304 *
305 * @return Email
306 */
307 public function set_connection_data( $data ) {
308
309 $this->connection_data = wp_parse_args(
310 $data,
311 [
312 'from_email' => '',
313 'from_name' => '',
314 ]
315 );
316
317 return $this;
318 }
319
320 /**
321 * Get this email's MailCatcher state.
322 *
323 * @since 4.0.0
324 *
325 * @return array
326 */
327 public function get_mailer_state() {
328
329 return $this->mailer_state;
330 }
331
332 /**
333 * Set this email's MailCatcher state.
334 *
335 * @since 4.0.0
336 *
337 * @param array $state MailCatcher state.
338 *
339 * @return Email
340 */
341 public function set_mailer_state( $state ) {
342
343 $this->mailer_state = wp_parse_args(
344 $state,
345 [
346 'CharSet' => '',
347 'ContentType' => '',
348 'Encoding' => '',
349 'CustomHeader' => '',
350 'Subject' => '',
351 'Body' => '',
352 'AltBody' => '',
353 'ReplyTo' => '',
354 'to' => '',
355 'cc' => '',
356 'bcc' => '',
357 'attachment' => '',
358 ]
359 );
360
361 return $this;
362 }
363
364 /**
365 * Get this email's WPMailInitiator state.
366 *
367 * @since 4.0.0
368 *
369 * @return array
370 */
371 public function get_initiator_state() {
372
373 return $this->initiator_state;
374 }
375
376 /**
377 * Set this email's WPMailInitiator state.
378 *
379 * @since 4.0.0
380 *
381 * @param array $state MailCatcher state.
382 *
383 * @return Email
384 */
385 public function set_initiator_state( $state ) {
386
387 $this->initiator_state = wp_parse_args(
388 $state,
389 [
390 'file' => '',
391 'line' => '',
392 'backtrace' => '',
393 ]
394 );
395
396 return $this;
397 }
398
399 /**
400 * Get the date and time this email
401 * was enqueued at.
402 *
403 * @since 4.0.0
404 *
405 * @return DateTime
406 */
407 public function get_date_enqueued() {
408
409 return $this->date_enqueued;
410 }
411
412 /**
413 * Set the date and time this email
414 * was enqueued at.
415 *
416 * @since 4.0.0
417 *
418 * @param DateTime $datetime Date and time of enqueueing.
419 *
420 * @return Email
421 */
422 public function set_date_enqueued( $datetime ) {
423
424 $this->date_enqueued = $this->get_datetime( $datetime );
425
426 return $this;
427 }
428
429 /**
430 * Get the date and time this email
431 * was processed at.
432 *
433 * @since 4.0.0
434 *
435 * @return DateTime
436 */
437 public function get_date_processed() {
438
439 return $this->date_processed;
440 }
441
442 /**
443 * Set the date and time this email
444 * was processed at.
445 *
446 * @since 4.0.0
447 *
448 * @param DateTime $datetime Date and time of processing.
449 *
450 * @return Email
451 */
452 public function set_date_processed( $datetime ) {
453
454 $this->date_processed = $this->get_datetime( $datetime );
455
456 return $this;
457 }
458
459 /**
460 * Convert a database string to a DateTime
461 * object, if necessary.
462 *
463 * @since 4.0.0
464 *
465 * @param string $datetime Date and time.
466 *
467 * @return DateTime
468 */
469 private function get_datetime( $datetime ) {
470
471 if ( ! is_a( $datetime, DateTime::class ) ) {
472 // Validate the date. Time is ignored.
473 $mm = substr( $datetime, 5, 2 );
474 $jj = substr( $datetime, 8, 2 );
475 $aa = substr( $datetime, 0, 4 );
476
477 $valid_date = wp_checkdate( $mm, $jj, $aa, $datetime );
478 $timezone = new DateTimeZone( 'UTC' );
479
480 if ( $valid_date ) {
481 $datetime = DateTime::createFromFormat( WP::datetime_mysql_format(), $datetime, $timezone );
482 } else {
483 $datetime = new DateTime( 'now', $timezone );
484 }
485 }
486
487 return $datetime;
488 }
489
490 /**
491 * Erase any potentially sensitive data.
492 *
493 * @since 4.0.0
494 *
495 * @return @return Email
496 */
497 public function anonymize() {
498
499 $this->initiator_state = null;
500 $this->wp_mail_args = null;
501 $this->connection_data = null;
502 $this->mailer_state = null;
503
504 return $this;
505 }
506
507 /**
508 * Save a new or modified email in DB.
509 *
510 * @since 4.0.0
511 *
512 * @throws Exception If data can't be encoded,
513 * or a database error occurred.
514 *
515 * @return int New or updated email ID.
516 */
517 public function save() {
518
519 global $wpdb;
520
521 $table = Queue::get_table_name();
522 $data = [
523 'initiator_state' => $this->initiator_state,
524 'wp_mail_args' => $this->wp_mail_args,
525 'connection_data' => $this->connection_data,
526 'mailer_state' => $this->mailer_state,
527 ];
528
529 $data = array_filter( $data );
530
531 if ( ! empty( $data ) ) {
532 $data = wp_json_encode(
533 [
534 'initiator_state' => $this->initiator_state,
535 'wp_mail_args' => $this->wp_mail_args,
536 'connection_data' => $this->connection_data,
537 'mailer_state' => $this->mailer_state,
538 ]
539 );
540
541 if ( $data === false ) {
542 throw new Exception(
543 sprintf(
544 /* translators: %1$s - JSON error message. */
545 esc_html__( 'Data JSON encoding error: %1$s', 'wp-mail-smtp' ),
546 esc_html( json_last_error_msg() )
547 )
548 );
549 }
550 } else {
551 $data = null;
552 }
553
554 if ( (bool) $this->get_id() ) {
555 // Update the existing DB table record.
556 $result = $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
557 $table,
558 [
559 'data' => $data,
560 'status' => $this->status,
561 'date_processed' => $this->get_date_processed()->format( WP::datetime_mysql_format() ),
562 ],
563 [
564 'id' => $this->get_id(),
565 ],
566 [
567 '%s', // data.
568 '%s', // status.
569 '%s', // date_processed.
570 ],
571 [
572 '%d',
573 ]
574 );
575
576 $email_id = $this->get_id();
577 } else {
578 // Create a new DB table record.
579 $result = $wpdb->insert(
580 $table,
581 [
582 'data' => $data,
583 'status' => $this->status,
584 'date_enqueued' => $this->get_date_enqueued()->format( WP::datetime_mysql_format() ),
585 ],
586 [
587 '%s', // data.
588 '%s', // status.
589 '%s', // date_enqueued.
590 ]
591 );
592
593 $email_id = $wpdb->insert_id;
594 }
595
596 if ( $result === false ) {
597 throw new Exception(
598 sprintf(
599 /* translators: %1$s - Database error message. */
600 esc_html__( 'Insert/update SQL query error: %1$s', 'wp-mail-smtp' ),
601 esc_html( $wpdb->last_error )
602 )
603 );
604 }
605
606 return (int) $email_id;
607 }
608 }
609