PluginProbe
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification / 5.8.0
Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification v5.8.0
5.8.0 5.8.1 5.7.0 5.6.2 5.6.3 5.6.1 5.6.0 5.5.0 5.4.0 5.3.2 5.3.1 5.1.6 5.1.5 trunk 2.1.5 2.11 2.12 2.13 2.15 3.0.0 3.0.1 3.0.2 3.0.3 3.0.5 3.0.51 All 41 releases
double-opt-in / src / Service / ConfirmationMailResender.php

ConfirmationMailResender.php in Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification 5.8.0, at src/Service/ConfirmationMailResender.php

129 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Re-sends the stored confirmation mail of an opt-in.
4 *
5 * @package Forge12\DoubleOptIn\Service
6 * @since 5.8.0
7 */
8
9 declare( strict_types=1 );
10
11 namespace Forge12\DoubleOptIn\Service;
12
13 use Forge12\DoubleOptIn\Repository\OptInRepositoryInterface;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * One implementation for every path that re-sends the confirmation mail:
21 * the admin REST route, the legacy admin AJAX button and, from Welle 2 on,
22 * the visitor asking for it again (addon-reminder).
23 *
24 * The mail is the one stored on the record (`mail_optin`), so the link in
25 * it is the original one. Subject and sender come from the current form
26 * settings, as before.
27 *
28 * Checks no capability: who may trigger a resend is the caller's business.
29 *
30 * @api
31 */
32 class ConfirmationMailResender {
33
34 /** @var OptInRepositoryInterface */
35 private $repository;
36
37 /** @var callable(int):array<string, mixed> */
38 private $formSettings;
39
40 /** @var DoiMailHeaders|null */
41 private $headers;
42
43 /**
44 * @param OptInRepositoryInterface $repository Opt-in storage.
45 * @param callable(int):array<string, mixed> $formSettings Form id → settings with
46 * `subject`, `sender`, `sender_name`.
47 * @param DoiMailHeaders|null $headers Marks the mail for `f12_doi_mail_headers`.
48 */
49 public function __construct( OptInRepositoryInterface $repository, callable $formSettings, ?DoiMailHeaders $headers = null ) {
50 $this->repository = $repository;
51 $this->formSettings = $formSettings;
52 $this->headers = $headers;
53 }
54
55 public function resend( int $optInId ): ResendResult {
56 $optIn = $optInId > 0 ? $this->repository->findById( $optInId ) : null;
57 if ( $optIn === null ) {
58 return ResendResult::refused( ResendResult::NOT_FOUND );
59 }
60 if ( $optIn->isConfirmed() ) {
61 return ResendResult::refused( ResendResult::CONFIRMED );
62 }
63 // A withdrawn consent is not asked for again behind the person's back.
64 if ( $optIn->isOptedOut() ) {
65 return ResendResult::refused( ResendResult::OPTED_OUT );
66 }
67
68 $stored = $optIn->getMailOptIn();
69 if ( $stored === '' ) {
70 return ResendResult::refused( ResendResult::NO_BODY );
71 }
72
73 $settings = (array) call_user_func( $this->formSettings, $optIn->getFormId() );
74 $to = $optIn->getEmail();
75 $body = $stored;
76 $subject = (string) ( $settings['subject'] ?? '' );
77 $from = self::from( (string) ( $settings['sender'] ?? '' ), (string) ( $settings['sender_name'] ?? '' ) );
78
79 // Older writers stored a structured payload instead of the body.
80 $payload = maybe_unserialize( $stored );
81 if ( is_array( $payload ) ) {
82 $to = (string) ( $payload['to'] ?? $to );
83 $body = (string) ( $payload['body'] ?? '' );
84 $subject = (string) ( $payload['subject'] ?? $subject );
85 $from = (string) ( $payload['from'] ?? $from );
86 }
87
88 if ( $body === '' ) {
89 return ResendResult::refused( ResendResult::NO_BODY );
90 }
91 if ( $to === '' ) {
92 return ResendResult::refused( ResendResult::NO_RECIPIENT );
93 }
94
95 $headers = array( 'Content-Type: text/html; charset=UTF-8' );
96 if ( $from !== '' ) {
97 $headers[] = 'From: ' . $from;
98 }
99
100 if ( $this->headers !== null ) {
101 $this->headers->expect( $optIn->getId(), $to, DoiMailHeaders::KIND_RESEND );
102 }
103
104 $sent = (bool) wp_mail(
105 $to,
106 $subject !== '' ? $subject : __( 'Please confirm your opt-in', 'double-opt-in' ),
107 $body,
108 $headers
109 );
110
111 if ( $this->headers !== null ) {
112 // A mail that never reached wp_mail's filter must not tag the next one.
113 $this->headers->forget();
114 }
115
116 // Record the outcome on the opt-in (OptInMailTracker).
117 do_action( 'f12_doi_optin_mail_result', $optIn->getId(), $sent, '' );
118
119 return $sent ? ResendResult::sent() : ResendResult::refused( ResendResult::SEND_FAILED );
120 }
121
122 private static function from( string $email, string $name ): string {
123 if ( $email === '' ) {
124 return '';
125 }
126 return $name !== '' ? $name . ' <' . $email . '>' : $email;
127 }
128 }
129