PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.9.2
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.9.2
4.9.2 4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Framework / Mails / MailSender.php
wp-staging / Framework / Mails Last commit date
Report 3 months ago MailSender.php 1 year ago
MailSender.php
249 lines
1 <?php
2
3 namespace WPStaging\Framework\Mails;
4
5 use WPStaging\Notifications\Notifications;
6 use WPStaging\Framework\Facades\Sanitize;
7
8 use function WPStaging\functions\debug_log;
9
10 /**
11 * Class MailSender
12 * This class is responsible for sending email notifications during WPStaging jobs by white-listing all plugins for our internal use
13 * The wpstg_action parameter is set to bypass_optimizer to bypass the optimizer and allow the email to be sent.
14 * @package WPStaging\Framework\Mails
15 */
16 class MailSender
17 {
18 /**
19 * @var string
20 */
21 const TRANSIENT_EMAIL_NOTIFICATION_ACCESS_TOKEN = 'wpstg_email_notification_access_token';
22
23 /**
24 * @var Notifications
25 */
26 protected $notifications;
27
28 /**
29 * @var array
30 */
31 protected $attachments;
32
33 /**
34 * @var string
35 */
36 protected $recipient;
37
38 /**
39 * @var bool
40 */
41 protected $addFooter;
42
43 /**
44 * @var Sanitize
45 */
46 protected $sanitize;
47
48 /**
49 * @param Notifications $notifications
50 * @param Sanitize $sanitize
51 */
52 public function __construct(Notifications $notifications, Sanitize $sanitize)
53 {
54 $this->notifications = $notifications;
55 $this->attachments = [];
56 $this->recipient = get_option(Notifications::OPTION_BACKUP_SCHEDULE_REPORT_EMAIL);
57 $this->addFooter = false;
58 $this->sanitize = $sanitize;
59 }
60
61 /**
62 * @param array $attachments
63 * @return void
64 */
65 public function setAttachments(array $attachments)
66 {
67 $this->attachments = $attachments;
68 }
69
70 /**
71 * @param string $recipient
72 * @return void
73 */
74 public function setRecipient(string $recipient)
75 {
76 $this->recipient = $recipient;
77 }
78
79 /**
80 * @param bool $addFooter
81 * @return void
82 */
83 public function setAddFooter(bool $addFooter)
84 {
85 $this->addFooter = $addFooter;
86 }
87
88 /**
89 * This function sends a request to the server to send an email notification even if the optimizer is enabled by whitelisting all plugins for our internal use
90 * The wpstg_action parameter is set to bypass_optimizer to bypass the optimizer and allow the email to be sent.
91 * @param string $subject
92 * @param string $body
93 * @param array $details
94 * @return bool
95 */
96 public function sendRequestForEmailNotification(string $subject, string $body, array $details = []): bool
97 {
98 if (empty($subject) || empty($body)) {
99 debug_log('Email subject or body is empty', 'error');
100 return false;
101 }
102
103 $accessToken = wp_generate_password(64, false);
104 set_transient(self::TRANSIENT_EMAIL_NOTIFICATION_ACCESS_TOKEN, $accessToken, 10);
105
106 $attachments = $this->prepareAttachments();
107
108 $response = wp_remote_post(
109 admin_url('admin-ajax.php'),
110 [
111 'timeout' => 15,
112 'sslverify' => false,
113 'body' => [
114 'action' => 'wpstg_send_mail_notification',
115 'wpstg_action' => 'bypass_optimizer',
116 'access_token' => $accessToken,
117 'subject' => $subject,
118 'body' => $body,
119 'recipient' => $this->recipient,
120 'attachments' => implode(',', $attachments),
121 'footer' => $this->addFooter,
122 'details' => $details,
123 ],
124 ]
125 );
126
127 if (is_wp_error($response)) {
128 debug_log($response->get_error_message(), 'error');
129 return false;
130 }
131
132 if (wp_remote_retrieve_response_code($response) !== 200) {
133 debug_log('Failed to send email notification', 'error');
134 return false;
135 }
136
137 $responseBody = wp_remote_retrieve_body($response);
138 if (empty($responseBody)) {
139 debug_log('Empty response body', 'error');
140 return false;
141 }
142
143 $responseBody = json_decode($responseBody, true);
144 if (empty($responseBody['success'])) {
145 return false;
146 }
147
148 return $responseBody['success'];
149 }
150
151 /**
152 * This method is called when the wpstg_send_mail_notification action is triggered
153 * It sends an email notification to the report email address
154 * @return void
155 */
156 public function ajaxSendEmailNotification()
157 {
158 $accessToken = isset($_POST['access_token']) ? sanitize_text_field($_POST['access_token']) : '';
159 if (empty($accessToken) || get_transient(self::TRANSIENT_EMAIL_NOTIFICATION_ACCESS_TOKEN) !== $accessToken) {
160 debug_log('Invalid/Missing access token', 'error');
161 wp_send_json_error();
162 }
163
164 delete_transient(self::TRANSIENT_EMAIL_NOTIFICATION_ACCESS_TOKEN);
165
166 $subject = isset($_POST['subject']) ? sanitize_text_field($_POST['subject']) : '';
167 $body = isset($_POST['body']) ? wp_kses_post($_POST['body']) : '';
168 $footer = isset($_POST['footer']) ? (bool)$_POST['footer'] : true;
169 $details = isset($_POST['details']) ? $this->sanitize->sanitizeArray($_POST['details']) : [];
170 if (empty($subject) || empty($body)) {
171 debug_log('Email subject or body is empty', 'error');
172 wp_send_json_error();
173 }
174
175 if (empty($_POST['recipient']) || !filter_var($_POST['recipient'], FILTER_VALIDATE_EMAIL)) {
176 debug_log('Report email is not set or invalid', 'error');
177 wp_send_json_error();
178 }
179
180 $attachments = $this->getPreparedAttachments();
181 $result = false;
182 try {
183 if (get_option(Notifications::OPTION_SEND_EMAIL_AS_HTML, false) === 'true') {
184 $result = $this->notifications->sendEmailAsHTML(sanitize_email($_POST['recipient']), $subject, $body, '', $details, $attachments);
185 } else {
186 $result = $this->notifications->sendEmail(sanitize_email($_POST['recipient']), $subject, $body, '', $attachments, $footer);
187 }
188
189 $this->cleanupAttachments($attachments);
190
191 if (!$result) {
192 wp_send_json_error();
193 }
194 } catch (\Exception $error) {
195 debug_log($error->getMessage(), 'error');
196 wp_send_json_error();
197 }
198
199 wp_send_json_success();
200 }
201
202 private function prepareAttachments(): array
203 {
204 $attachments = [];
205 foreach ($this->attachments as $attachment) {
206 if (!file_exists($attachment)) {
207 continue;
208 }
209
210 $attachments[] = $attachment;
211 }
212
213 return $attachments;
214 }
215
216 private function getPreparedAttachments(): array
217 {
218 $attachments = isset($_POST['attachments']) ? sanitize_text_field($_POST['attachments']) : '';
219 if (empty($attachments)) {
220 return [];
221 }
222
223 $this->attachments = explode(',', $attachments);
224 $attachments = [];
225 foreach ($this->attachments as $attachment) {
226 if (!file_exists($attachment)) {
227 continue;
228 }
229
230 $attachments[] = $attachment;
231 }
232
233 return $attachments;
234 }
235
236 /**
237 * @param array $attachments
238 * @return void
239 */
240 private function cleanupAttachments(array $attachments)
241 {
242 foreach ($attachments as $attachment) {
243 if (file_exists($attachment)) {
244 unlink($attachment);
245 }
246 }
247 }
248 }
249