/** * Process a specific item from the queue * * @param FUE_Sending_Queue_Item $queue_item A row from wp_followup_email_orders * @return bool|WP_Error TRUE if the email was sent or a WP_Error object if an error occured */ public function send_queue_item($queue_item) { $wpdb = Follow_Up_Emails::instance()->wpdb; // if a queue item doesn't have an email_id, it needs to have either a // subscription_notification or daily_summary meta key if (empty($queue_item->email_id)) { if (isset($queue_item->meta['subscription_notification']) || isset($queue_item->meta['daily_summary'])) { return $this->send_adhoc_email($queue_item); } else { // invalid queue item. delete! Follow_Up_Emails::instance()->scheduler->delete_item($queue_item->id); return new WP_Error('fue_queue_error', __('Queue item deleted because no email was assigned to it', 'follow_up_emails')); } } // only process unsent email orders if ($queue_item->is_sent != 0) { return new WP_Error('fue_queue_error', __('Queue item has already been sent', 'follow_up_emails')); } $email = new FUE_Email($queue_item->email_id); // make sure that the email is not disabled if ($email->status != FUE_Email::STATUS_ACTIVE && $email->type != 'manual') { return new WP_Error('fue_queue_error', __('Could not send email because it is not active', 'follow_up_emails')); } // set local variables $this->email = $email; $this->queue = $queue_item; // email cannot be active and have an empty message if (empty($email->message)) { // set the status to inactive $email->update_status(FUE_Email::STATUS_INACTIVE); return new WP_Error('fue_queue_error', __('Cannot send emails without a message. Email has been deactivated', 'follow_up_emails')); } // if the queue item is cron locked, reschedule to avoid duplicate emails being sent if (FUE_Sending_Scheduler::is_queue_item_locked($queue_item)) { FUE_Sending_Scheduler::reschedule_queue_item($queue_item); return new WP_Error('fue_queue_notice', __('This email is locked due to a previous attempt in sending the email. Sending has been rescheduled to avoid duplicate emails.', 'follow_up_emails')); } // place a cron lock to prevent duplicates FUE_Sending_Scheduler::lock_email_queue($queue_item); $email_data = $this->get_email_data($queue_item, $email); // remove from queue if the user chose to not receive emails // non-order related emails if ($queue_item->user_id > 0 && $queue_item->order_id == 0 && fue_user_opted_out($queue_item->user_id)) { Follow_Up_Emails::instance()->scheduler->delete_item($queue_item->id); return new WP_Error('fue_queue_notice', __('The customer opted out of recieving non-order related emails. Email has been deleted.', 'follow_up_emails')); } // do not send if the recipient's email is on the excludes list if (fue_is_email_excluded($email_data['email_to']) || $queue_item->order_id > 0 && fue_is_email_excluded($email_data['email_to'], 0, $queue_item->order_id)) { do_action('fue_email_excluded', $email_data['email_to'], $queue_item->id); Follow_Up_Emails::instance()->scheduler->delete_item($queue_item->id); return new WP_Error('fue_queue_notice', __('The customer is on the "Exclude Emails" list. Email deleted.', 'follow_up_emails')); } // allow other extensions to "skip" sending this email $skip = apply_filters('fue_skip_email_sending', false, $email, $queue_item); if ($skip) { return new WP_Error('fue_queue_notice', __('An add-on has marked this email to be skipped.', 'follow_up_emails')); } $email_data['subject'] = apply_filters('fue_email_subject', $email_data['subject'], $email, $queue_item); $email_data['message'] = apply_filters('fue_email_message', $email_data['message'], $email, $queue_item); $email_data = $this->process_variable_replacements($email_data); // hook to variable replacement $email_data['subject'] = apply_filters('fue_send_email_subject', $email_data['subject'], $queue_item); $email_data['message'] = apply_filters('fue_send_email_message', $email_data['message'], $queue_item); $email_data['message'] = $this->process_link_variables($email_data, $queue_item, $email); $headers = apply_filters('fue_email_headers', array($this->get_bcc_header(), $this->get_reply_to_header()), $email, $queue_item); add_filter('wp_mail_from', array($this, 'get_wp_email_from'), 20); add_filter('wp_mail_from_name', array($this, 'get_wp_email_from_name'), 20); // send the email do_action('fue_before_email_send', $email_data['subject'], $email_data['message'], $headers, $queue_item); // Decode html entities to UTF-8 (http://php.net/html_entity_decode#104617) if (function_exists('mb_convert_encoding')) { $email_data['subject'] = preg_replace_callback("/(&#[0-9]+;)/", array($this, 'convert_encoding'), $email_data['subject']); } // apply the email template if (!empty($email->template)) { $email_data['message'] = $email->apply_template($email_data['message']); } // allow plugins to take care of the sending // plugins that override the sending must return TRUE to stop FUE from sending this queue item $sent = apply_filters('fue_send_queue_item', false, $queue_item, $email_data, $headers); // return if an error occured if (is_wp_error($sent)) { return $sent; } if (!$sent) { $email_data = apply_filters('fue_before_sending_email', $email_data, $email, $queue_item); self::mail($email_data['email_to'], $email_data['subject'], $email_data['message'], $headers); } do_action('fue_after_email_sent', $email_data['subject'], $email_data['message'], $headers, $queue_item); $this->log_sent_email($email_data); // increment usage count fue_update_email(array('id' => $email->id, 'usage_count' => $email->usage_count + 1)); // update the email order $now = get_date_from_gmt(date('Y-m-d H:i:s'), 'Y-m-d H:i:s'); $wpdb->update($wpdb->prefix . 'followup_email_orders', array('is_sent' => 1, 'date_sent' => $now, 'email_trigger' => $email->get_trigger_string()), array('id' => $queue_item->id)); do_action('fue_email_order_sent', $queue_item->id); do_action('fue_email_sent_details', $queue_item, $queue_item->user_id, $email, $email_data['email_to'], $email_data['cname'], $email->get_trigger_string()); // remove queue lock FUE_Sending_Scheduler::remove_queue_item_lock($queue_item); // if this is a 'date' email and there are no more unsent emails // of the same kind in the queue, archive it self::maybe_archive_email($email); return true; }