/**
  * 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;
 }