app = $app; } /** * Send the email notification * @param array $notification [Notification settings from form meta] * @param array $submittedData [User submitted form data] * @param \StdClass $form [The form object from database] * @return bool */ public function notify($notification, $submittedData, $form, $entryId = false) { $isSendAsPlain = ArrayHelper::get($notification, 'asPlainText') == 'yes'; $isSendAsPlain = apply_filters('fluenform_send_plain_html_email', $isSendAsPlain, $form, $notification); $emailBody = $notification['message']; $emailBody = apply_filters('fluentform_submission_message_parse', $emailBody, $entryId, $submittedData, $form); $notification['parsed_message'] = $emailBody; if (!$isSendAsPlain) { $emailBody = $this->getEmailWithTemplate($emailBody, $form, $notification); } $sendAddresses = $this->getSendAddresses($notification, $submittedData); $subject = apply_filters('fluentform_email_subject', $notification['subject'], $notification, $submittedData, $form); if (!$sendAddresses || !$subject) { do_action('ff_log_data', [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $entryId, 'component' => 'EmailNotification', 'status' => 'error', 'title' => 'Email sending skipped', 'description' => "Email skipped to send because email/subject may not valid.
Subject: {$notification['subject']}.
Email: " . implode(', ', $sendAddresses), ]); return false; } $headers = $this->getHeaders($notification, $isSendAsPlain); $attachments = $this->app->applyFilters( 'fluentform_filter_email_attachments', isset($notification['attachments']) ? $notification['attachments'] : [], $notification, $form, $submittedData ); $emailBody = apply_filters('fluentform_email_body', $emailBody, $notification, $submittedData, $form); if ($entryId) { /* * Inline email logger. It will work fine hopefully */ add_action('wp_mail_failed', function ($error) use ($notification, $form, $entryId) { $failedMailSubject = ArrayHelper::get($error->error_data, 'wp_mail_failed.subject'); if ($failedMailSubject == $notification['subject']) { $reason = $error->get_error_message(); do_action('ff_log_data', [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $entryId, 'component' => 'EmailNotification', 'status' => 'failed', 'title' => 'Email sending failed', 'description' => "Email Notification failed to sent.
Subject: {$notification['subject']}.
Reason: " . $reason, ]); } }, 10, 1); } $result = false; foreach ($sendAddresses as $address) { do_action('ff_log_data', [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $entryId, 'component' => 'EmailNotification', 'status' => 'info', 'title' => 'Email sending initiated', 'description' => "Email Notification broadcasted to " . $address . ".
Subject: {$subject}", ]); $emailTo = apply_filters('fluentform_email_to', $address, $notification, $submittedData, $form); $result = $this->broadCast([ 'email' => $emailTo, 'subject' => $subject, 'body' => $emailBody, 'headers' => $headers, 'attachments' => $attachments ]); } return $result; } private function broadCast($data) { $sendEmail = explode(',', $data['email']); if (count($sendEmail) > 1) { $data['email'] = $sendEmail; } return wp_mail( $data['email'], $data['subject'], $data['body'], $data['headers'], $data['attachments'] ); } private function getSendAddresses($notification, $submittedData) { $sendAddresses = [ ArrayHelper::get($notification, 'sendTo.email') ]; if (ArrayHelper::get($notification, 'sendTo.type') == 'field' && !empty($notification['sendTo']['field'])) { $sendAddresses = [ ArrayHelper::get($submittedData, $notification['sendTo']['field']) ]; $sendAddresses = array_filter($sendAddresses, 'is_email'); } if (ArrayHelper::get($notification, 'sendTo.type') != 'routing') { return $sendAddresses; } $routings = ArrayHelper::get($notification, 'sendTo.routing'); $validAddresses = []; foreach ($routings as $routing) { $inputValue = ArrayHelper::get($routing, 'input_value'); if(!$inputValue || !is_email($inputValue)) { continue; } $condition = [ 'conditionals' => [ 'status' => true, 'type' => 'any', 'conditions' => [ $routing ] ] ]; if (\FluentForm\App\Services\ConditionAssesor::evaluate($condition, $submittedData)) { $validAddresses[] = $inputValue; } } return $validAddresses; } /** * @param $formId * @return array * @todo: Implement Caching mechanism so we don't have to parse these things for every request */ private function getFormInputsAndLabels($form) { $formInputs = FormFieldsParser::getInputs($form); $inputLabels = FormFieldsParser::getAdminLabels($form, $formInputs); return [ 'inputs' => $formInputs, 'labels' => $inputLabels ]; } public function getEmailWithTemplate($emailBody, $form, $notification) { $originalEmailBody = $emailBody; $emailHeader = apply_filters('fluentform_email_header', '', $form, $notification); $emailFooter = apply_filters('fluentform_email_footer', '', $form, $notification); if (empty($emailHeader)) { $emailHeader = View::make('email.template.header', array( 'form' => $form, 'notification' => $notification )); } if (empty($emailFooter)) { $emailFooter = View::make('email.template.footer', array( 'form' => $form, 'notification' => $notification, 'footerText' => $this->getFooterText($form, $notification) )); } $css = View::make('email.template.styles'); $css = apply_filters('fluentform_email_styles', $css, $form, $notification); $emailBody = $emailHeader . $emailBody . $emailFooter; ob_start(); try { // apply CSS styles inline for picky email clients $emogrifier = new Emogrifier($emailBody, $css); $emailBody = $emogrifier->emogrify(); } catch (\Exception $e) { } $maybeError = ob_get_clean(); if ($maybeError) { return $originalEmailBody; } return $emailBody; } private function getFooterText($form, $notification) { $option = get_option('_fluentform_global_form_settings'); if ($option && !empty($option['misc']['email_footer_text'])) { $footerText = $option['misc']['email_footer_text']; } else { $footerText = '© ' . get_bloginfo('name', 'display') . '.'; } return apply_filters('fluentform_email_template_footer_text', $footerText, $form, $notification); } private function getHeaders($notification, $isSendAsPlain = false) { $headers = [ 'Content-Type: text/html; charset=utf-8' ]; $fromEmail = $notification['fromEmail']; if (!is_email($fromEmail)) { $fromEmail = false; } if ($notification['fromName'] && $fromEmail) { $headers[] = "From: {$notification['fromName']} <{$fromEmail}>"; } elseif ($fromEmail) { $headers[] = "From: <{$fromEmail}>"; } if (!empty($notification['bcc'])) { $bccEmail = $notification['bcc']; $headers[] = 'bcc: ' . $bccEmail; } if (!empty($notification['cc'])) { $ccEmail = $notification['cc']; $headers[] = 'cc: ' . $ccEmail; } if ($notification['replyTo'] && is_email($notification['replyTo'])) { $headers[] = "Reply-To: <" . $notification['replyTo'] . ">"; } $headers = $this->app->applyFilters( 'fluenttform_email_header', $headers, $notification ); return $headers; } }