PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.14
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.14
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
fluentform / app / Services / FormBuilder / Notifications / EmailNotification.php

EmailNotification.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.14, at app/Services/FormBuilder/Notifications/EmailNotification.php

447 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Services\FormBuilder\Notifications;
4
5 defined('ABSPATH') || die;
6
7 use FluentForm\Framework\Helpers\ArrayHelper;
8 use FluentForm\Framework\Foundation\Application;
9 use FluentForm\App\Modules\Form\FormFieldsParser;
10 use FluentForm\App\Services\Emogrifier\Emogrifier;
11
12 class EmailNotification
13 {
14 /**
15 * FluentForm\Framework\Foundation\Application
16 *
17 * @var $app
18 */
19 protected $app = null;
20
21 /**
22 * Biuld the instance of this class
23 *
24 * @param \FluentForm\Framework\Foundation\Application $app
25 *
26 * @return $this
27 */
28 public function __construct(Application $app)
29 {
30 $this->app = $app;
31 }
32
33 /**
34 * Send the email notification
35 *
36 * @param array $notification [Notification settings from form meta]
37 * @param array $submittedData [User submitted form data]
38 * @param \StdClass $form [The form object from database]
39 *
40 * @return bool
41 */
42 public function notify($notification, $submittedData, $form, $entryId = false)
43 {
44 $isSendAsPlain = 'yes' == ArrayHelper::get($notification, 'asPlainText');
45
46 $isSendAsPlain= apply_filters_deprecated(
47 'fluentform_send_plain_html_email',
48 [
49 $isSendAsPlain,
50 $form,
51 $notification,
52 ],
53 FLUENTFORM_FRAMEWORK_UPGRADE,
54 'fluentform/send_plain_html_email',
55 'Use fluentform/send_plain_html_email instead of fluentform_send_plain_html_email.'
56 );
57
58 $isSendAsPlain = apply_filters('fluentform/send_plain_html_email', $isSendAsPlain, $form, $notification);
59
60 $emailBody = $notification['message'];
61
62 $emailBody = apply_filters_deprecated(
63 'fluentform_submission_message_parse',
64 [
65 $emailBody,
66 $entryId,
67 $submittedData,
68 $form,
69 ],
70 FLUENTFORM_FRAMEWORK_UPGRADE,
71 'fluentform/submission_message_parse',
72 'Use fluentform/submission_message_parse instead of fluentform_submission_message_parse.'
73 );
74
75 $emailBody = apply_filters('fluentform/submission_message_parse', $emailBody, $entryId, $submittedData, $form);
76
77 $notification['parsed_message'] = $emailBody;
78
79 if (! $isSendAsPlain) {
80 $emailBody = $this->getEmailWithTemplate($emailBody, $form, $notification);
81 }
82
83 $sendAddresses = $this->getSendAddresses($notification, $submittedData);
84 $notification['subject'] = apply_filters_deprecated(
85 'fluentform_email_subject',
86 [
87 $notification['subject'],
88 $notification,
89 $submittedData,
90 $form,
91 ],
92 FLUENTFORM_FRAMEWORK_UPGRADE,
93 'fluentform/email_subject',
94 'Use fluentform/email_subject instead of fluentform_email_subject.'
95 );
96
97 $subject = apply_filters('fluentform/email_subject', $notification['subject'], $notification, $submittedData, $form);
98
99 if (! $sendAddresses || ! $subject) {
100 if ($entryId) {
101 do_action('fluentform/log_data', [
102 'parent_source_id' => $form->id,
103 'source_type' => 'submission_item',
104 'source_id' => $entryId,
105 'component' => 'EmailNotification',
106 'status' => 'error',
107 'title' => 'Email sending skipped',
108 'description' => "Email skipped to send because email/subject may not valid.<br />Subject: {$notification['subject']}. <br/>Email: " . $sendAddresses,
109 ]);
110 }
111 return null;
112 }
113
114 $headers = $this->getHeaders($notification, $isSendAsPlain);
115 $notificationAttachments = isset($notification['attachments']) ? $notification['attachments'] : [];
116 $notificationAttachments = apply_filters_deprecated(
117 'fluentform_filter_email_attachments',
118 [
119 $notificationAttachments,
120 $notification,
121 $form,
122 $submittedData,
123 ],
124 FLUENTFORM_FRAMEWORK_UPGRADE,
125 'fluentform/filter_email_attachments',
126 'Use fluentform/filter_email_attachments instead of fluentform_filter_email_attachments.'
127 );
128 $attachments = $this->app->applyFilters(
129 'fluentform/filter_email_attachments',
130 $notificationAttachments,
131 $notification,
132 $form,
133 $submittedData
134 );
135
136 $emailBody = apply_filters_deprecated(
137 'fluentform_email_body',
138 [
139 $emailBody,
140 $notification,
141 $submittedData,
142 $form,
143 ],
144 FLUENTFORM_FRAMEWORK_UPGRADE,
145 'fluentform/email_body',
146 'Use fluentform/email_body instead of fluentform_email_body.'
147 );
148
149 $emailBody = apply_filters('fluentform/email_body', $emailBody, $notification, $submittedData, $form);
150
151 if ($entryId) {
152 /*
153 * Inline email logger. It will work fine hopefully
154 */
155 add_action('wp_mail_failed', function ($error) use ($notification, $form, $entryId) {
156 $failedMailSubject = ArrayHelper::get($error->error_data, 'wp_mail_failed.subject');
157 if ($failedMailSubject == $notification['subject']) {
158 $reason = $error->get_error_message();
159 do_action('fluentform/log_data', [
160 'parent_source_id' => $form->id,
161 'source_type' => 'submission_item',
162 'source_id' => $entryId,
163 'component' => 'EmailNotification',
164 'status' => 'failed',
165 'title' => 'Email sending failed',
166 'description' => "Email Notification failed to sent.<br />Subject: {$notification['subject']}. <br/>Reason: " . $reason,
167 ]);
168 }
169 }, 10, 1);
170 }
171
172 $sendAddresses = apply_filters_deprecated(
173 'fluentform_email_to',
174 [
175 $sendAddresses,
176 $notification,
177 $submittedData,
178 $form,
179 ],
180 FLUENTFORM_FRAMEWORK_UPGRADE,
181 'fluentform/email_to',
182 'Use fluentform/email_to instead of fluentform_email_to.'
183 );
184
185 $emailTo = apply_filters('fluentform/email_to', $sendAddresses, $notification, $submittedData, $form);
186 if (is_array($emailTo)) {
187 $emailTo = implode(', ', $emailTo);
188 }
189 do_action('fluentform/log_data', [
190 'parent_source_id' => $form->id,
191 'source_type' => 'submission_item',
192 'source_id' => $entryId,
193 'component' => 'EmailNotification',
194 'status' => 'info',
195 'title' => 'Email sending initiated',
196 'description' => 'Email Notification broadcasted to ' . $emailTo . ".<br />Subject: {$subject}",
197 ]);
198
199 return $this->broadCast([
200 'email' => $emailTo,
201 'subject' => $subject,
202 'body' => $emailBody,
203 'headers' => $headers,
204 'attachments' => $attachments,
205 ]);
206 }
207
208 private function broadCast($data)
209 {
210 $sendEmail = explode(',', $data['email']);
211 if (count($sendEmail) > 1) {
212 $data['email'] = $sendEmail;
213 }
214
215 return wp_mail(
216 $data['email'],
217 $data['subject'],
218 $data['body'],
219 $data['headers'],
220 $data['attachments']
221 );
222 }
223
224 /**
225 * Get email addresses
226 *
227 * @param array $notification [Notification settings from form meta]
228 * @param array $submittedData [User submitted form data]
229 *
230 * @return string $sendAddresses [Email address or addresses as comma separated string]
231 */
232 private function getSendAddresses($notification, $submittedData)
233 {
234 $sendAddresses = ArrayHelper::get($notification, 'sendTo.email');
235
236 if ('field' == ArrayHelper::get($notification, 'sendTo.type') && ! empty($notification['sendTo']['field'])) {
237 $sendAddresses = ArrayHelper::get($submittedData, $notification['sendTo']['field'], '');
238 if (!is_email($sendAddresses)) {
239 return '';
240 }
241 }
242
243 if ('routing' != ArrayHelper::get($notification, 'sendTo.type')) {
244 return $sendAddresses;
245 }
246
247 $routings = ArrayHelper::get($notification, 'sendTo.routing');
248 $validAddresses = [];
249 foreach ($routings as $routing) {
250 $emailAddresses = ArrayHelper::get($routing, 'input_value');
251
252 if (!$emailAddresses || trim($emailAddresses) === '') {
253 continue;
254 }
255 $emailAddresses = array_map('trim', explode(',', $emailAddresses));
256 $emailAddresses = array_filter($emailAddresses, function ($email) {
257 return is_email($email);
258 });
259 $condition = [
260 'conditionals' => [
261 'status' => true,
262 'type' => 'any',
263 'conditions' => [
264 $routing,
265 ],
266 ],
267 ];
268 if (\FluentForm\App\Services\ConditionAssesor::evaluate($condition, $submittedData)) {
269 $validAddresses = array_merge($validAddresses, $emailAddresses);
270 }
271 }
272 return implode(',', $validAddresses);
273 }
274
275 /**
276 * Resolve a form's input keys and their admin labels.
277 *
278 * @param $formId
279 *
280 * @return array
281 *
282 * @todo: Implement Caching mechanism so we don't have to parse these things for every request
283 */
284 private function getFormInputsAndLabels($form)
285 {
286 $formInputs = FormFieldsParser::getInputs($form);
287
288 $inputLabels = FormFieldsParser::getAdminLabels($form, $formInputs);
289
290 return [
291 'inputs' => $formInputs,
292 'labels' => $inputLabels,
293 ];
294 }
295
296 public function getEmailWithTemplate($emailBody, $form, $notification)
297 {
298 $originalEmailBody = $emailBody;
299 $emailHeader = '';
300 $emailHeader = apply_filters_deprecated(
301 'fluentform_email_header',
302 [
303 $emailHeader,
304 $form,
305 $notification,
306 ],
307 FLUENTFORM_FRAMEWORK_UPGRADE,
308 'fluentform/email_header',
309 'Use fluentform/email_header instead of fluentform_email_header.'
310 );
311 $emailHeader = apply_filters('fluentform/email_header', $emailHeader, $form, $notification);
312
313 $emailFooter = '';
314 $emailFooter = apply_filters_deprecated(
315 'fluentform_email_footer',
316 [
317 $emailFooter,
318 $form,
319 $notification,
320 ],
321 FLUENTFORM_FRAMEWORK_UPGRADE,
322 'fluentform/email_footer',
323 'Use fluentform/email_footer instead of fluentform_email_footer.'
324 );
325 $emailFooter = apply_filters('fluentform/email_footer', $emailFooter, $form, $notification);
326
327 if (empty($emailHeader)) {
328 $emailHeader = wpFluentForm('view')->make('email.template.header', [
329 'form' => $form,
330 'notification' => $notification,
331 ]);
332 }
333
334 if (empty($emailFooter)) {
335 $emailFooter = wpFluentForm('view')->make('email.template.footer', [
336 'form' => $form,
337 'notification' => $notification,
338 'footerText' => $this->getFooterText($form, $notification),
339 ]);
340 }
341
342 $css = wpFluentForm('view')->make('email.template.styles');
343 $css = apply_filters_deprecated(
344 'fluentform_email_styles',
345 [
346 $css,
347 $form,
348 $notification,
349 ],
350 FLUENTFORM_FRAMEWORK_UPGRADE,
351 'fluentform/email_styles',
352 'Use fluentform/email_styles instead of fluentform_email_styles.'
353 );
354 $css = apply_filters('fluentform/email_styles', $css, $form, $notification);
355 $emailBody = $emailHeader . $emailBody . $emailFooter;
356
357 ob_start();
358 try {
359 // apply CSS styles inline for picky email clients
360 $emogrifier = new Emogrifier($emailBody, $css);
361 $emailBody = $emogrifier->emogrify();
362 } catch (\Exception $e) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement -- Emogrifier failed (malformed HTML/CSS); keep the un-inlined body.
363 }
364 $maybeError = ob_get_clean();
365
366 if ($maybeError) {
367 return $originalEmailBody;
368 }
369
370 return $emailBody;
371 }
372
373 private function getFooterText($form, $notification)
374 {
375 $option = get_option('_fluentform_global_form_settings');
376 if ($option && ! empty($option['misc']['email_footer_text'])) {
377 $footerText = $option['misc']['email_footer_text'];
378 } else {
379 $footerText = '&copy; ' . get_bloginfo('name', 'display') . '.';
380 }
381
382 $footerText = apply_filters_deprecated(
383 'fluentform_email_template_footer_text',
384 [
385 $footerText,
386 $form,
387 $notification,
388 ],
389 FLUENTFORM_FRAMEWORK_UPGRADE,
390 'fluentform/email_template_footer_text',
391 'Use fluentform/email_template_footer_text instead of fluentform_email_header.'
392 );
393 return apply_filters('fluentform/email_template_footer_text', $footerText, $form, $notification);
394 }
395
396 public function getHeaders($notification, $isSendAsPlain = false)
397 {
398 $headers = [
399 'Content-Type: text/html; charset=utf-8',
400 ];
401
402 $fromEmail = $notification['fromEmail'];
403
404 if (!is_string($fromEmail) || ! is_email($fromEmail)) {
405 $fromEmail = false;
406 }
407
408 if ($notification['fromName'] && $fromEmail) {
409 $headers[] = "From: {$notification['fromName']} <{$fromEmail}>";
410 } elseif ($fromEmail) {
411 $headers[] = "From: <{$fromEmail}>";
412 }
413
414 if (! empty($notification['bcc'])) {
415 $bccEmail = $notification['bcc'];
416 $headers[] = 'bcc: ' . $bccEmail;
417 }
418
419 if (! empty($notification['cc'])) {
420 $ccEmail = $notification['cc'];
421 $headers[] = 'cc: ' . $ccEmail;
422 }
423
424 if ($notification['replyTo'] && is_email($notification['replyTo'])) {
425 $headers[] = 'Reply-To: <' . $notification['replyTo'] . '>';
426 }
427
428 $headers = apply_filters_deprecated(
429 'fluenttform_email_header',
430 [
431 $headers,
432 $notification,
433 ],
434 FLUENTFORM_FRAMEWORK_UPGRADE,
435 'fluentform/email_template_header',
436 'Use fluentform/email_template_header instead of fluenttform_email_header.'
437 );
438 $headers = $this->app->applyFilters(
439 'fluentform/email_template_header',
440 $headers,
441 $notification
442 );
443
444 return $headers;
445 }
446 }
447