| 1 |
<?php |
| 2 |
/** |
| 3 |
* Email Actions |
| 4 |
* |
| 5 |
* @package WPbot_Automator |
| 6 |
*/ |
| 7 |
|
| 8 |
namespace WPbot_Automator\Actions; |
| 9 |
|
| 10 |
if ( ! defined( 'ABSPATH' ) ) { |
| 11 |
exit; |
| 12 |
} |
| 13 |
|
| 14 |
/** |
| 15 |
* Class Email_Actions |
| 16 |
*/ |
| 17 |
class Email_Actions extends Action { |
| 18 |
|
| 19 |
/** |
| 20 |
* Constructor |
| 21 |
*/ |
| 22 |
public function __construct() { |
| 23 |
$this->id = 'mail'; |
| 24 |
$this->group = __( 'Mail', 'wpbot-automator' ); |
| 25 |
} |
| 26 |
|
| 27 |
/** |
| 28 |
* Execute the action |
| 29 |
* |
| 30 |
* @param array $action_data Configuration for this action from the workflow. |
| 31 |
* @param array $trigger_data Data passed from the trigger. |
| 32 |
* @return bool|array |
| 33 |
*/ |
| 34 |
public function execute( $action_data, $trigger_data ) { |
| 35 |
$action_id = isset( $action_data['actionId'] ) ? $action_data['actionId'] : ''; |
| 36 |
|
| 37 |
if ( empty( $action_id ) ) { |
| 38 |
return false; |
| 39 |
} |
| 40 |
|
| 41 |
switch ( $action_id ) { |
| 42 |
case 'send_email': |
| 43 |
return $this->send_email( $action_data, $trigger_data ); |
| 44 |
default: |
| 45 |
return false; |
| 46 |
} |
| 47 |
} |
| 48 |
|
| 49 |
/** |
| 50 |
* Send an email |
| 51 |
*/ |
| 52 |
private function send_email( $config, $trigger_data ) { |
| 53 |
global $wpdb; |
| 54 |
$config_values = isset( $config['config'] ) ? $config['config'] : array(); |
| 55 |
|
| 56 |
$to = isset( $config_values['to_email'] ) ? $this->parse_tokens( $config_values['to_email'], $trigger_data ) : ''; |
| 57 |
$subject = isset( $config_values['subject'] ) ? $this->parse_tokens( $config_values['subject'], $trigger_data ) : ''; |
| 58 |
$body = isset( $config_values['body'] ) ? $this->parse_tokens( $config_values['body'], $trigger_data ) : ''; |
| 59 |
$template_id = isset( $config_values['template_id'] ) ? absint( $config_values['template_id'] ) : 0; |
| 60 |
$from_email = isset( $config_values['from_email'] ) ? $this->parse_tokens( $config_values['from_email'], $trigger_data ) : get_option( 'admin_email' ); |
| 61 |
$from_name = isset( $config_values['from_name'] ) ? $this->parse_tokens( $config_values['from_name'], $trigger_data ) : get_option( 'blogname' ); |
| 62 |
$cc = isset( $config_values['cc_email'] ) ? $this->parse_tokens( $config_values['cc_email'], $trigger_data ) : ''; |
| 63 |
$bcc = isset( $config_values['bcc_email'] ) ? $this->parse_tokens( $config_values['bcc_email'], $trigger_data ) : ''; |
| 64 |
$reply_to = isset( $config_values['reply_to'] ) ? $this->parse_tokens( $config_values['reply_to'], $trigger_data ) : ''; |
| 65 |
$is_html = isset( $config_values['is_html'] ) ? (bool) $config_values['is_html'] : true; |
| 66 |
|
| 67 |
$from_email = sanitize_email( $from_email ); |
| 68 |
if ( ! is_email( $from_email ) ) { |
| 69 |
$from_email = get_option( 'admin_email' ); |
| 70 |
} |
| 71 |
$reply_to = sanitize_email( $reply_to ); |
| 72 |
if ( ! is_email( $reply_to ) ) { |
| 73 |
$reply_to = ''; |
| 74 |
} |
| 75 |
|
| 76 |
// If a template is selected, use it instead of the manual body. |
| 77 |
if ( ! empty( $template_id ) ) { |
| 78 |
$table = \WPbot_Automator\Core\Database::get_email_templates_table(); |
| 79 |
$template = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table} WHERE id = %d", $template_id ), ARRAY_A ); |
| 80 |
if ( $template && ! empty( $template['body_html'] ) ) { |
| 81 |
$body = $template['body_html']; |
| 82 |
$is_html = true; // Templates are always HTML. |
| 83 |
} |
| 84 |
} |
| 85 |
|
| 86 |
if ( empty( $to ) || empty( $subject ) || empty( $body ) ) { |
| 87 |
return array( |
| 88 |
'success' => false, |
| 89 |
'message' => 'To, Subject, and Body (or Template) are required.', |
| 90 |
); |
| 91 |
} |
| 92 |
|
| 93 |
// Parse tokens. |
| 94 |
$to = $this->parse_tokens( $to, $trigger_data ); |
| 95 |
$subject = $this->parse_tokens( $subject, $trigger_data ); |
| 96 |
$body = $this->parse_tokens( $body, $trigger_data ); |
| 97 |
$cc = $this->parse_tokens( $cc, $trigger_data ); |
| 98 |
$bcc = $this->parse_tokens( $bcc, $trigger_data ); |
| 99 |
$reply_to = $this->parse_tokens( $reply_to, $trigger_data ); |
| 100 |
|
| 101 |
$to_list = $this->sanitize_email_list( $to ); |
| 102 |
if ( empty( $to_list ) ) { |
| 103 |
return array( |
| 104 |
'success' => false, |
| 105 |
'message' => sprintf( 'Invalid or missing "To" email address: "%s".', esc_html( $to ) ), |
| 106 |
); |
| 107 |
} |
| 108 |
$to = 1 === count( $to_list ) ? reset( $to_list ) : $to_list; |
| 109 |
|
| 110 |
$cc_list = $this->sanitize_email_list( $cc ); |
| 111 |
$bcc_list = $this->sanitize_email_list( $bcc ); |
| 112 |
|
| 113 |
$headers = array(); |
| 114 |
|
| 115 |
// Set Content-Type |
| 116 |
if ( $is_html ) { |
| 117 |
$headers[] = 'Content-Type: text/html; charset=UTF-8'; |
| 118 |
} else { |
| 119 |
$headers[] = 'Content-Type: text/plain; charset=UTF-8'; |
| 120 |
} |
| 121 |
|
| 122 |
// Set From |
| 123 |
$headers[] = 'From: ' . $from_name . ' <' . $from_email . '>'; |
| 124 |
|
| 125 |
// Set Reply-To |
| 126 |
if ( ! empty( $reply_to ) && $reply_to !== $from_email ) { |
| 127 |
$headers[] = 'Reply-To: ' . $reply_to; |
| 128 |
} |
| 129 |
|
| 130 |
// Set CC |
| 131 |
if ( ! empty( $cc_list ) ) { |
| 132 |
$headers[] = 'Cc: ' . implode( ', ', $cc_list ); |
| 133 |
} |
| 134 |
|
| 135 |
// Set BCC |
| 136 |
if ( ! empty( $bcc_list ) ) { |
| 137 |
$headers[] = 'Bcc: ' . implode( ', ', $bcc_list ); |
| 138 |
} |
| 139 |
|
| 140 |
// Convert headers to string for better compatibility with logging plugins. |
| 141 |
$headers_str = implode( "\r\n", $headers ); |
| 142 |
|
| 143 |
$sent = wp_mail( $to, $subject, $body, $headers ); |
| 144 |
|
| 145 |
if ( ! $sent ) { |
| 146 |
//error_log( sprintf( 'WPbot Automator - send_email failed. to=%s from=%s reply_to=%s headers=%s', is_array( $to ) ? implode( ',', $to ) : $to, $from_email, $reply_to, wp_json_encode( $headers ) ) ); |
| 147 |
} |
| 148 |
|
| 149 |
if ( $sent ) { |
| 150 |
return array( |
| 151 |
'success' => true, |
| 152 |
'message' => 'Email sent successfully.', |
| 153 |
); |
| 154 |
} |
| 155 |
|
| 156 |
return array( |
| 157 |
'success' => false, |
| 158 |
'message' => 'Failed to send email.', |
| 159 |
); |
| 160 |
} |
| 161 |
|
| 162 |
/** |
| 163 |
* Sanitize a list of email addresses. |
| 164 |
* |
| 165 |
* @param string|array $emails Emails string or array. |
| 166 |
* @return array |
| 167 |
*/ |
| 168 |
private function sanitize_email_list( $emails ) { |
| 169 |
if ( is_array( $emails ) ) { |
| 170 |
$emails = implode( ',', $emails ); |
| 171 |
} |
| 172 |
|
| 173 |
if ( ! is_string( $emails ) ) { |
| 174 |
return array(); |
| 175 |
} |
| 176 |
|
| 177 |
$parts = preg_split( '/[;,\s]+/', $emails, -1, PREG_SPLIT_NO_EMPTY ); |
| 178 |
$result = array(); |
| 179 |
foreach ( $parts as $email ) { |
| 180 |
$email = sanitize_email( $email ); |
| 181 |
if ( is_email( $email ) ) { |
| 182 |
$result[] = $email; |
| 183 |
} |
| 184 |
} |
| 185 |
|
| 186 |
return array_unique( $result ); |
| 187 |
} |
| 188 |
} |
| 189 |
|