<?php include('../functions.php');?>
<?php include('../login/auth.php');?>
<?php include('../helpers/PHPMailerAutoload.php');?>
<?php include('../helpers/short.php');?>
<?php include('../helpers/preferences.php');?>
<?php include('../helpers/integrations/zapier/triggers/functions.php');?>
<?php include('../helpers/integrations/rules.php');?>
<?php include('../helpers/subscription.php');?>
<?php

function parse_id_list($val)
{
	$val = trim($val);
	if($val=='' || $val=='0') return '0';

	$ids = array();
	$vals = explode(',', $val);
	foreach($vals as $id)
	{
		$id = trim($id);
		if($id==='' || !ctype_digit($id)) return false;

		$id = (int)$id;
		if($id > 0) $ids[$id] = $id;
	}

	if(count($ids)==0) return '0';
	return implode(',', $ids);
}

function sendy_campaign_send_lock_name($campaign_id)
{
	return 'sendy_campaign_send_'.(int)$campaign_id;
}

function sendy_acquire_campaign_send_lock($campaign_id)
{
	global $mysqli;

	$lock_name = mysqli_real_escape_string($mysqli, sendy_campaign_send_lock_name($campaign_id));
	$r = mysqli_query($mysqli, 'SELECT GET_LOCK("'.$lock_name.'", 0) AS lock_status');
	if(!$r) return false;

	$row = mysqli_fetch_array($r);
	return isset($row['lock_status']) && (int)$row['lock_status'] === 1;
}

function sendy_release_campaign_send_lock($campaign_id)
{
	global $mysqli;

	$lock_name = mysqli_real_escape_string($mysqli, sendy_campaign_send_lock_name($campaign_id));
	mysqli_query($mysqli, 'DO RELEASE_LOCK("'.$lock_name.'")');
}

function sendy_get_list_custom_fields($list_id, &$custom_fields_cache)
{
	global $mysqli;

	$list_id = (int)$list_id;
	if(!isset($custom_fields_cache[$list_id]))
	{
		$custom_fields_cache[$list_id] = '';
		$q = 'SELECT custom_fields FROM lists WHERE id = '.$list_id;
		$r = mysqli_query($mysqli, $q);
		if ($r)
		{
		    while($row = mysqli_fetch_array($r)) $custom_fields_cache[$list_id] = $row['custom_fields'];
		}
	}

	return $custom_fields_cache[$list_id];
}

function sendy_apply_fallback_tags($content, $name, $custom_values, $subscriber_list, &$custom_fields_cache)
{
	preg_match_all('/\[([^\]]+),\s*fallback=/i', $content, $matches_var, PREG_PATTERN_ORDER);
	preg_match_all('/,\s*fallback=([^\]]*)\]/i', $content, $matches_val, PREG_PATTERN_ORDER);
	preg_match_all('/(\[[^\]]+,\s*fallback=[^\]]*\])/i', $content, $matches_all, PREG_PATTERN_ORDER);
	$matches_var = $matches_var[1];
	$matches_val = $matches_val[1];
	$matches_all = $matches_all[1];

	for($i=0;$i<count($matches_var);$i++)
	{
		$field = $matches_var[$i];
		$fallback = $matches_val[$i];
		$tag = $matches_all[$i];

		if($field=='Name')
		{
			$content = str_replace($tag, $name=='' ? $fallback : $name, $content);
		}
		else if($custom_values=='')
		{
			$content = str_replace($tag, $fallback, $content);
		}
		else
		{
			$custom_fields = sendy_get_list_custom_fields($subscriber_list, $custom_fields_cache);
			$custom_fields_array = explode('%s%', $custom_fields);
			$custom_values_array = explode('%s%', $custom_values);
			$cf_count = count($custom_fields_array);
			$matched = false;

			for($j=0;$j<$cf_count;$j++)
			{
				$cf_array = explode(':', $custom_fields_array[$j]);
				$key = str_replace(' ', '', $cf_array[0]);

				if($field==$key)
				{
					$matched = true;
					$custom_value = isset($custom_values_array[$j]) ? $custom_values_array[$j] : '';
					if($custom_value=='')
						$content = str_replace($tag, $fallback, $content);
					else if(isset($cf_array[1]) && $cf_array[1]=='Date')
						$content = str_replace($tag, date("D, M d, Y", $custom_value), $content);
					else
						$content = str_replace($tag, $custom_value, $content);
				}
			}

			if(!$matched) $content = str_replace($tag, $fallback, $content);
		}
	}

	return $content;
}

//variables
$campaign_id = (int)mysqli_real_escape_string($mysqli, $_POST['campaign_id']);
$app = isset($_POST['app']) && is_numeric($_POST['app']) ? mysqli_real_escape_string($mysqli, (int)$_POST['app']) : exit;
$offset = isset($_POST['offset']) ? mysqli_real_escape_string($mysqli, $_POST['offset']) : '';
$cron = $_POST['cron'];
$email_list = isset($_POST['email_list']) && $_POST['email_list']!='' ? parse_id_list($_POST['email_list']): '0';
$email_list_excl = isset($_POST['email_list_exclude']) && $_POST['email_list_exclude']!='' ? parse_id_list($_POST['email_list_exclude']) : '0';
$email_lists_segs = isset($_POST['email_lists_segs']) && $_POST['email_lists_segs']!='' ? parse_id_list($_POST['email_lists_segs']) : '0';
$email_lists_segs_excl = isset($_POST['email_lists_segs_excl']) && $_POST['email_lists_segs_excl']!='' ? parse_id_list($_POST['email_lists_segs_excl']) : '0';
if($email_list===false || $email_list_excl===false || $email_lists_segs===false || $email_lists_segs_excl===false) exit;
$total_recipients = empty($_POST['total_recipients']) ? 0 : (int)trim($_POST['total_recipients']);
$time = time();

//get user details
$q = 'SELECT send_rate, timezone FROM login WHERE id = '.get_app_info('main_userID');
$r = mysqli_query($mysqli, $q);
if ($r)
{
    while($row = mysqli_fetch_array($r))
    {
		$send_rate = $row['send_rate'];
		$user_timezone = $row['timezone'];
    }
}

//get smtp settings
$q = 'SELECT app_name, smtp_host, smtp_port, smtp_ssl, smtp_username, smtp_password, allocated_quota, gdpr_only, custom_domain, custom_domain_protocol, custom_domain_enabled FROM apps WHERE id = '.$app.' AND userID = '.get_app_info('main_userID');
$r = mysqli_query($mysqli, $q);
if ($r && mysqli_num_rows($r) > 0)
{
    while($row = mysqli_fetch_array($r))
    {
		$app_name = $row['app_name'];
		$smtp_host = $row['smtp_host'];
		$smtp_port = $row['smtp_port'];
		$smtp_ssl = $row['smtp_ssl'];
		$smtp_username = $row['smtp_username'];
		$smtp_password = $row['smtp_password'];
		$allocated_quota = $row['allocated_quota'];
		$gdpr_line = $row['gdpr_only'] ? 'AND gdpr = 1 ' : '';
		$custom_domain = $row['custom_domain'];
		$custom_domain_protocol = $row['custom_domain_protocol'];
		$custom_domain_enabled = $row['custom_domain_enabled'];
		if($custom_domain!='' && $custom_domain_enabled)
		{
			$parse = parse_url(APP_PATH);
			$domain = $parse['host'];
			$protocol = $parse['scheme'];
			$app_path = str_replace($domain, $custom_domain, APP_PATH);
			$app_path = str_replace($protocol, $custom_domain_protocol, $app_path);
		}
		else $app_path = APP_PATH;
    }
}

//Format sent date and web version for Zapier and Rules
$sent_formatted = date("%a, %b %d, %Y, %I:%M%p", $time);
$web_version = $app_path.'/w/'.encrypt_val($campaign_id);

//Include main list query
$main_query = $email_list == 0 ? '' : 'subscribers.list in ('.$email_list.') ';

//Include segmentation query
$seg_query = $main_query != '' && $email_lists_segs != 0 ? 'OR ' : '';
$seg_query .= $email_lists_segs == 0 ? '' : '(subscribers_seg.seg_id IN ('.$email_lists_segs.')) ';
$include_query = $main_query.$seg_query;
if($include_query == '') $include_query = '0';

//Exclude list query
$exclude_query = $email_list_excl == 0 ? '' : 'NOT EXISTS (SELECT 1 FROM subscribers ex WHERE ex.email = subscribers.email AND ex.list IN ('.$email_list_excl.')) ';

//Exclude segmentation query
$exclude_seg_query = $exclude_query != '' && $email_lists_segs_excl != 0 ? 'AND ' : '';
$exclude_seg_query .= $email_lists_segs_excl == 0 ? '' : 'NOT EXISTS (SELECT 1 FROM subscribers exs INNER JOIN subscribers_seg exss ON (exs.id = exss.subscriber_id) WHERE exs.email = subscribers.email AND exss.seg_id IN ('.$email_lists_segs_excl.'))';

if(!$cron)
{
	if(!sendy_acquire_campaign_send_lock($campaign_id))
	{
		echo 'locked';
		exit;
	}
	register_shutdown_function('sendy_release_campaign_send_lock', $campaign_id);
}

//When an interrupted SES campaign is explicitly resumed, preserve the
//in-flight batch as delivered to avoid duplicate mail, then continue with
//the remaining confirmed-unsent recipients.
if($offset!='')
{
	$interrupted_result = mysqli_query($mysqli, 'SELECT send_status FROM campaigns WHERE id = '.$campaign_id.' AND userID = '.get_app_info('main_userID'));
	if($interrupted_result && $interrupted_row = mysqli_fetch_array($interrupted_result))
	{
		if($interrupted_row['send_status']=='interrupted')
		{
			mysqli_begin_transaction($mysqli);
			$in_flight_result = mysqli_query($mysqli, 'SELECT id FROM queue WHERE campaign_id = '.$campaign_id.' AND sent = 2 FOR UPDATE');
			$in_flight = $in_flight_result ? mysqli_num_rows($in_flight_result) : 0;
			$resolved = mysqli_query($mysqli, 'UPDATE queue SET sent = 1, query_str = NULL, http_headers = NULL WHERE campaign_id = '.$campaign_id.' AND sent = 2');
			$resumed = mysqli_query($mysqli, 'UPDATE campaigns SET recipients = LEAST(to_send, (SELECT COUNT(*) FROM queue WHERE campaign_id = '.$campaign_id.' AND sent = 1)), send_status = NULL, send_error = NULL WHERE id = '.$campaign_id.' AND userID = '.get_app_info('main_userID'));
			if(!$in_flight_result || !$resolved || !$resumed || !mysqli_commit($mysqli))
			{
				mysqli_rollback($mysqli);
				echo 'resume_failed';
				exit;
			}
			$offset += $in_flight;
		}
	}
}

//Check if monthly quota needs to be updated
$q = 'SELECT allocated_quota, current_quota FROM apps WHERE id = '.$app;
$r = mysqli_query($mysqli, $q);
if($r)
{
	while($row = mysqli_fetch_array($r))
	{
		$allocated_quota = $row['allocated_quota'];
		$current_quota = $row['current_quota'];
		$updated_quota = $current_quota + $total_recipients;
	}
}
//Update quota if a monthly limit was set
if($allocated_quota!=-1)
{
	//if so, update quota
	$q = 'UPDATE apps SET current_quota = '.$updated_quota.' WHERE id = '.$app;
	mysqli_query($mysqli, $q);
}

//if CRON is setup, schedule email to send in the next 5 mins
if($cron)
{
	$the_date = '0';
	$timezone = '0';

	//Get number of recipients to send to
	$to_send = $total_recipients;

	//schedule email to send in the next 5 mins
	$q = 'UPDATE campaigns SET sent = "'.$time.'", to_send = '.$to_send.', send_date = "'.$the_date.'", lists = "'.$email_list.'", lists_excl = "'.$email_list_excl.'", segs = "'.$email_lists_segs.'", segs_excl = "'.$email_lists_segs_excl.'", timezone = "'.$timezone.'" WHERE id = '.$campaign_id;
	$r = mysqli_query($mysqli, $q);
	if ($r)
	{
		echo 'cron_send';
		exit;
	}
}
else
{
	ignore_user_abort(true);
	header("Content-Length: 0");
	header("Connection: close");
	flush();
	echo true;
}

//check if user wants to continue sending to the rest of the recipients because sending was incomplete
if($offset!='')
{
	//get currently unsubscribed
	$uc = 'SELECT id FROM subscribers WHERE unsubscribed = 1 AND last_campaign = '.$campaign_id;
    $currently_unsubscribed = mysqli_num_rows(mysqli_query($mysqli, $uc));
    //get currently bounced
	$bc = 'SELECT id FROM subscribers WHERE bounced = 1 AND last_campaign = '.$campaign_id;
    $currently_bounced = mysqli_num_rows(mysqli_query($mysqli, $bc));
    //get currently complaint
	$cc = 'SELECT id FROM subscribers WHERE complaint = 1 AND last_campaign = '.$campaign_id;
    $currently_complaint = mysqli_num_rows(mysqli_query($mysqli, $cc));
	//calculate offset (offset should exclude currently unsubscribed, bounced or complaint)
	$the_offset = ' OFFSET '.($offset-($currently_unsubscribed+$currently_bounced+$currently_complaint));
	$email_list = isset($_POST['email_list']) ? parse_id_list($_POST['email_list']) : '0';
	if($email_list===false) exit;
}
else $the_offset = '';

//select campaign to send email
$q = 'SELECT from_name, from_email, reply_to, title, label, plain_text, html_text, query_string, to_send, recipients, opens_tracking, links_tracking, timezone FROM campaigns WHERE id = '.$campaign_id.' AND userID = '.get_app_info('main_userID');
$r = mysqli_query($mysqli, $q);
if ($r && mysqli_num_rows($r) > 0)
{
    while($row = mysqli_fetch_array($r))
    {
	    $timezone = $row['timezone'];
	$from_name = stripslashes($row['from_name']);
	$from_email = stripslashes($row['from_email']);
	$reply_to = stripslashes($row['reply_to']);
		$title = stripslashes($row['title']);
		$campaign_title = $row['label']=='' ? $title : stripslashes(htmlentities($row['label'],ENT_QUOTES,"UTF-8"));
		$plain_text = stripslashes($row['plain_text']);
		$html = stripslashes($row['html_text']);
		$query_string = stripslashes($row['query_string']);
		$to_send = stripslashes($row['to_send']);
		$current_recipient_count = $row['recipients'];
		$opens_tracking = $row['opens_tracking'];
		$links_tracking = $row['links_tracking'];
    }
}

//convert date tags
date_default_timezone_set($timezone!='' ? $timezone : $user_timezone);
$today = time();
$day_word = array(_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday'));
$month_word = array('', _('January'), _('February'), _('March'), _('April'), _('May'), _('June'), _('July'), _('August'), _('September'), _('October'), _('November'), _('December'));
$currentdaynumber = date('d', $today);
$currentday = $day_word[date('w', $today)];
$currentmonthnumber = date('m', $today);
$currentmonth = $currentmonthnumber==10 ? $month_word[$currentmonthnumber] : $month_word[str_replace('0', '', $currentmonthnumber)];
$currentyear = date('Y', $today);
$unconverted_date = array('[currentdaynumber]', '[currentday]', '[currentmonthnumber]', '[currentmonth]', '[currentyear]');
$converted_date = array($currentdaynumber, $currentday, $currentmonthnumber, $currentmonth, $currentyear);

//if sending campaign for the first time (not resend)
if($offset=='')
{
	//If links tracking is enabled, insert links into database
	if($links_tracking)
	{
		//Insert web version link
		if(strpos($html, '</webversion>')==true || strpos($html, '[webversion]')==true)
			mysqli_query($mysqli, 'INSERT INTO links (campaign_id, link) VALUES ('.$campaign_id.', "'.$app_path.'/w/'.encrypt_val($campaign_id).'")');

		//Insert reconsent link
		if(strpos($html, '[reconsent]')==true)
			mysqli_query($mysqli, 'INSERT INTO links (campaign_id, link) VALUES ('.$campaign_id.', "'.$app_path.'/r?c='.encrypt_val($campaign_id).'")');

		//Insert into links
		$links = array();
		//extract all links from HTML
		preg_match_all('/href=["\']([^"\']+)["\']/i', $html, $matches, PREG_PATTERN_ORDER);
		$matches = array_unique($matches[1]);
		foreach($matches as $var)
		{
			//If a query_string is set
			if($query_string!='' && substr($var, 0, 1)!="#")
			{
				$var_array = explode('#', $var, 2);
				$url_part_1 = $var_array[0];
				$url_part_2 = isset($var_array[1]) ? $var_array[1] : '';
				$anchor = strpos($var,'#') !== false ? '#' : '';
				if(strpos($var,'?') !== false) $var = $url_part_1.'&'.$query_string.$anchor.$url_part_2;
				else $var = $url_part_1.'?'.$query_string.$anchor.$url_part_2;
			}

			if(substr($var, 0, 1)!="#" && substr($var, 0, 6)!="mailto" && substr($var, 0, 3)!="ftp" && substr($var, 0, 3)!="tel" && substr($var, 0, 3)!="sms" && substr($var, 0, 13)!="[unsubscribe]" && substr($var, 0, 13)!="[preferences]" && substr($var, 0, 12)!="[webversion]" && substr($var, 0, 11)!="[reconsent]" && !strpos($var, 'fonts.googleapis.com') && !strpos($var, 'use.typekit.net') && !strpos($var, 'use.fontawesome.com'))
			{
				$var = str_replace($unconverted_date, $converted_date, $var);
			array_push($links, $var);
		    }
		}
		//extract unique links
		for($i=0;$i<count($links);$i++)
		{
		    $q = 'INSERT INTO links (campaign_id, link) VALUES ('.$campaign_id.', "'.$links[$i].'")';
		    $r = mysqli_query($mysqli, $q);
		    if ($r){}
		}
	}

	//Get and update number of recipients to send to
	$q2  = 'SELECT COUNT(DISTINCT subscribers.email) AS total FROM subscribers';
	$q2 .= $email_lists_segs==0 && $email_lists_segs_excl==0 ? ' ' : ' LEFT JOIN subscribers_seg ON (subscribers.id = subscribers_seg.subscriber_id) ';
	$q2 .= 'WHERE ('.$include_query.') ';
	$q2 .= $exclude_query != '' || $exclude_seg_query != '' ? 'AND ('.$exclude_query.$exclude_seg_query.') ' : '';
	$q2 .= 'AND subscribers.unsubscribed = 0 AND subscribers.bounced = 0 AND subscribers.complaint = 0 AND subscribers.confirmed = 1 '.$gdpr_line;
	$r2 = mysqli_query($mysqli, $q2);
	if ($r2)
	{
		$row = mysqli_fetch_array($r2);
		$to_send = (int)$row['total'];
		$q3 = 'UPDATE campaigns SET to_send = '.$to_send.', to_send_lists = "'.$email_list.'", sent = "'.$time.'", lists = "'.$email_list.'", lists_excl = "'.$email_list_excl.'", segs = "'.$email_lists_segs.'", segs_excl = "'.$email_lists_segs_excl.'", send_status = NULL, send_error = NULL WHERE id = '.$campaign_id;
		$r3 = mysqli_query($mysqli, $q3);
		if ($r3){}
	}
	else error_log("[Unable to calculate recipients to send]".mysqli_error($mysqli).': in '.__FILE__.' on line '.__LINE__);

	//Run rules
	$rules_data = array(
	    'trigger' => 'campaign_sending',
		'app_name' => $app_name,
	    'campaign_title' => $campaign_title,
	    'subject' => $title,
	    'from_name' => $from_name,
	    'from_email' => $from_email,
	    'reply_to' => $reply_to,
	    'sent' => $sent_formatted,
	    'no_of_recipients' => $to_send,
	    'webversion' => $web_version,
	    'brand_id' => $app,
	    'campaign_id' => $campaign_id,
	    'report_url' => "$app_path/report?i=$app&c=$campaign_id"
    );

    //Run rules
	run_rule($rules_data);
}
else
{
	//Reset timeout_check in case user clicks "Resume" button even though cron was used to send this campaign.
	//This should remove possibility of sending an email multiple times to the same recipient(s).
	mysqli_query($mysqli, 'UPDATE campaigns SET timeout_check = NULL WHERE id = '.$campaign_id.' AND userID = '.get_app_info('main_userID'));
}

//Replace links in newsletter and put tracking image
$q  = 'SELECT subscribers.id, subscribers.name, subscribers.email, subscribers.list, subscribers.custom_fields FROM subscribers
	   INNER JOIN (
	   SELECT MIN(subscribers.id) AS id FROM subscribers';
$q .= $email_lists_segs==0 && $email_lists_segs_excl==0 ? ' ' : ' LEFT JOIN subscribers_seg ON (subscribers.id = subscribers_seg.subscriber_id) ';
$q .= 'WHERE ('.$include_query.') ';
$q .= $exclude_query != '' || $exclude_seg_query != '' ? 'AND ('.$exclude_query.$exclude_seg_query.') ' : '';
$q .= 'AND subscribers.unsubscribed = 0 AND subscribers.bounced = 0 AND subscribers.complaint = 0 AND subscribers.confirmed = 1 '.$gdpr_line.'
	   AND userID = '.get_app_info('main_userID').'
	   GROUP BY subscribers.email) deduped_subscribers ON subscribers.id = deduped_subscribers.id
	   ORDER BY subscribers.id ASC
	   LIMIT 18446744073709551615'.$the_offset;

$campaign_links = array();
$q2 = 'SELECT id, link FROM links WHERE campaign_id = '.$campaign_id;
$r2 = mysqli_query($mysqli, $q2);
if ($r2 && mysqli_num_rows($r2) > 0)
{
    while($row2 = mysqli_fetch_array($r2)) $campaign_links[] = array('id' => $row2['id'], 'link' => $row2['link']);
}

$attachments = array();
$attachments_path = sendy_existing_uploads_path($app, 'attachments/'.$campaign_id, '../../uploads');
if(file_exists($attachments_path))
{
	foreach(glob($attachments_path.'/*') as $attachment)
	{
		if(file_exists($attachment)) $attachments[] = $attachment;
	}
}

$r = mysqli_query($mysqli, $q);
if ($r && mysqli_num_rows($r) > 0)
{
	$subscriber_id = '';
	$email = '';
	$subscriber_list = '';
	$custom_fields_cache = array();
	$sendy_stop_check_interval = 100;
	$sendy_recipient_loop_count = 0;
	$campaign_stopped = 0;
	$recipients_already_sent = 0;
	$title_treated = $title;

    while($row = mysqli_fetch_array($r))
    {
	//prevent execution timeout
	set_time_limit(0);

		//Check if 'stop campaign' is initiated
		$sendy_recipient_loop_count++;
		if($sendy_recipient_loop_count == 1 || $sendy_recipient_loop_count % $sendy_stop_check_interval == 0)
		{
			$qc = 'SELECT campaign_stopped, recipients FROM campaigns WHERE id = '.$campaign_id;
			$rc = mysqli_query($mysqli, $qc);
			if ($rc)
			{
				while($rowc = mysqli_fetch_array($rc))
				{
					$campaign_stopped = $rowc['campaign_stopped'];
					$recipients_already_sent = $rowc['recipients'];
				}
			}
			else
			{
				global $dbHost, $dbUser, $dbPass, $dbName, $dbPort;
				if(isset($dbPort)) $mysqli = new mysqli($dbHost, $dbUser, $dbPass, $dbName, $dbPort);
				else $mysqli = new mysqli($dbHost, $dbUser, $dbPass, $dbName);
				if(!$mysqli->connect_error)
					mysqli_query($mysqli, 'UPDATE campaigns SET send_status = "interrupted", send_error = "Sendy lost its database connection while checking the campaign stop status." WHERE id = '.$campaign_id);
				exit;
			}
		}

		//If so,
		if($campaign_stopped==1)
		{
			//sent timestamp
			$sent_formatted = date("D, M d, Y, h:iA", time());

			//Zapier Trigger 'new_campaign_sent' event
			zapier_trigger_new_campaign_sent($title_treated, $from_name, $from_email, $reply_to, $sent_formatted, $web_version, $app);

			//Run rules
			$rules_data = array(
				'trigger' => 'campaign_sent',
				'app_name' => $app_name,
				'campaign_title' => $campaign_title,
				'subject' => $title_treated,
				'from_name' => $from_name,
				'from_email' => $from_email,
				'reply_to' => $reply_to,
				'sent' => $sent_formatted,
				'no_of_recipients' => $recipients_already_sent,
				'webversion' => $web_version,
				'brand_id' => $app,
				'campaign_id' => $campaign_id,
				'report_url' => "$app_path/report?i=$app&c=$campaign_id"
			);

			//Run rules
			run_rule($rules_data);

			//Exit script to stop campaign from sending further
			exit;
		}

	$subscriber_id = $row['id'];
		$name = ucfirst(trim($row['name']));
		$email = trim($row['email']);
		$subscriber_list = $row['list'];
		$custom_values = $row['custom_fields'];

		$html_treated = str_replace($unconverted_date, $converted_date, $html);
		$plain_treated = str_replace($unconverted_date, $converted_date, $plain_text);
		$title_treated = str_replace($unconverted_date, $converted_date, $title);

		//replace new links on HTML code
		foreach($campaign_links as $campaign_link)
		{
			$linkID = $campaign_link['id'];
			if($query_string!='')
			{
				$link = (strpos($campaign_link['link'],'?'.$query_string) !== false) ? str_replace('?'.$query_string, '', $campaign_link['link']) : str_replace('&'.$query_string, '', $campaign_link['link']);
			}
			else $link = $campaign_link['link'];

			//If link tracking is enabled, replace links with trackable links
			if($links_tracking)
			{
				//replace new links on HTML code
				$html_treated = str_replace('href="'.$link.'"', 'href="'.$app_path.'/l/'.encrypt_val($subscriber_id).'/'.encrypt_val($linkID).'/'.encrypt_val($campaign_id).'"', $html_treated);
				$html_treated = str_replace('href=\''.$link.'\'', 'href="'.$app_path.'/l/'.encrypt_val($subscriber_id).'/'.encrypt_val($linkID).'/'.encrypt_val($campaign_id).'"', $html_treated);

				//replace new links on Plain Text code
				$plain_treated = str_replace($link, $app_path.'/l/'.encrypt_val($subscriber_id).'/'.encrypt_val($linkID).'/'.encrypt_val($campaign_id), $plain_treated);
		    }
		}

		//tags for subject
		$title_treated = sendy_apply_fallback_tags($title_treated, $name, $custom_values, $subscriber_list, $custom_fields_cache);

		//tags for HTML
		$html_treated = sendy_apply_fallback_tags($html_treated, $name, $custom_values, $subscriber_list, $custom_fields_cache);
		//tags for Plain text
		$plain_treated = sendy_apply_fallback_tags($plain_treated, $name, $custom_values, $subscriber_list, $custom_fields_cache);

		//set web version links
	$html_treated = str_replace('<webversion', '<a href="'.$app_path.'/w/'.encrypt_val($subscriber_id).'/'.encrypt_val($subscriber_list).'/'.encrypt_val($campaign_id).'" ', $html_treated);
	$html_treated = str_replace('</webversion>', '</a>', $html_treated);
	$html_treated = str_replace('[webversion]', $app_path.'/w/'.encrypt_val($subscriber_id).'/'.encrypt_val($subscriber_list).'/'.encrypt_val($campaign_id), $html_treated);
	$plain_treated = str_replace('[webversion]', $app_path.'/w/'.encrypt_val($subscriber_id).'/'.encrypt_val($subscriber_list).'/'.encrypt_val($campaign_id), $plain_treated);

	//set unsubscribe links
		if($smtp_host == 'smtp.elasticemail.com' && $smtp_port!='' && $smtp_username!='' && $smtp_password!='')
		{
			$html_treated = str_replace('<unsubscribe', '<a href="{unsubscribe}" ', $html_treated);
			$html_treated = str_replace('</unsubscribe>', '</a>', $html_treated);
			$html_treated = str_replace('[unsubscribe]', '{unsubscribe}', $html_treated);
			$plain_treated = str_replace('[unsubscribe]', '{unsubscribe}', $plain_treated);
		}
		else
		{
		$html_treated = str_replace('<unsubscribe', '<a href="'.$app_path.'/unsubscribe/'.encrypt_val($email).'/'.encrypt_val($subscriber_list).'/'.encrypt_val($campaign_id).'" ', $html_treated);
		$html_treated = str_replace('</unsubscribe>', '</a>', $html_treated);
		$html_treated = str_replace('[unsubscribe]', $app_path.'/unsubscribe/'.encrypt_val($email).'/'.encrypt_val($subscriber_list).'/'.encrypt_val($campaign_id), $html_treated);
		$plain_treated = str_replace('[unsubscribe]', $app_path.'/unsubscribe/'.encrypt_val($email).'/'.encrypt_val($subscriber_list).'/'.encrypt_val($campaign_id), $plain_treated);
		}

		list($html_treated, $plain_treated) = sendy_replace_preferences_tags($html_treated, $plain_treated, $app_path, $app, $email);

	//Name tag
		$html_treated = str_replace('[Name]', $name, $html_treated);
		$plain_treated = str_replace('[Name]', $name, $plain_treated);
		$title_treated = str_replace('[Name]', $name, $title_treated);

	//Email tag
		$html_treated = str_replace('[Email]', $email, $html_treated);
		$plain_treated = str_replace('[Email]', $email, $plain_treated);
		$title_treated = str_replace('[Email]', $email, $title_treated);

		//set reconsent links
	$html_treated = str_replace('[reconsent]', APP_PATH.'/r?e='.encrypt_val($email).'&a='.encrypt_val($app).'&w='.encrypt_val($subscriber_id).'/'.encrypt_val($subscriber_list).'/'.encrypt_val($campaign_id), $html_treated);
	$plain_treated = str_replace('[reconsent]', APP_PATH.'/r?e='.encrypt_val($email).'&a='.encrypt_val($app).'&w='.encrypt_val($subscriber_id).'/'.encrypt_val($subscriber_list).'/'.encrypt_val($campaign_id), $plain_treated);

	//If opens tracking is enabled, add 1 x 1 px tracking image
	if($opens_tracking)
	{
		//add tracking 1 by 1px image
			$html_treated .= '<img src="'.$app_path.'/t/'.encrypt_val($campaign_id).'/'.encrypt_val($subscriber_id).'" alt="" style="width:1px;height:1px;"/>';
		}

		//send email
		$mail = new PHPMailer();
		if($smtp_host!='' && $smtp_port!='' && $smtp_username!='' && $smtp_password!='')
		{
			$mail->IsSMTP();
			$mail->SMTPDebug = 0;
			$mail->SMTPAuth = true;
			$mail->SMTPSecure = $smtp_ssl;
			$mail->Host = $smtp_host;
			$mail->Port = $smtp_port;
			$mail->Username = $smtp_username;
			$mail->Password = $smtp_password;

			//If sending via ElasticEmail, send subscriber list ID to ElasticEmail so that we can retrieve it via their webhook later
			if($smtp_host == 'smtp.elasticemail.com' && $smtp_port!='' && $smtp_username!='' && $smtp_password!='')
				$mail->AddCustomHeader('X-ElasticEmail-Postback: '.encrypt_val($subscriber_list));
			//If sending via Sendgrid, send subscriber list ID to Sendgrid so that we can retrieve it via their webhook later
			else if($smtp_host == 'smtp.sendgrid.net' && $smtp_port!='' && $smtp_username!='' && $smtp_password!='')
			{
				$sgheaders = json_encode(array('category' => array(encrypt_val($subscriber_list))));
				$mail->AddCustomHeader('X-SMTPAPI: '.$sgheaders);
			}
			else if($smtp_host == 'in-v3.mailjet.com' && $smtp_port!='' && $smtp_username!='' && $smtp_password!='')
				$mail->AddCustomHeader('X-MJ-CustomID: '.encrypt_val($subscriber_list));
		}
		else if(get_app_info('s3_key')!='' && get_app_info('s3_secret')!='')
		{
			//if there is an attachment, don't use curl_multi
			if(count($attachments)>0)
				$mail->IsAmazonSES(false, $campaign_id, $subscriber_id, get_app_info('timezone'));
			//otherwise send with curl_multi
			else
				$mail->IsAmazonSES(true, $campaign_id, $subscriber_id, get_app_info('timezone'), $send_rate);
			$mail->AddAmazonSESKey(get_app_info('s3_key'), get_app_info('s3_secret'));
		}
		$mail->CharSet	  =	"UTF-8";
		$mail->From       = $from_email;
		$mail->FromName   = $from_name;
		$mail->Subject = $title_treated;
		$mail->AltBody = $plain_treated;
		$mail->Body = $html_treated;
		$mail->IsHTML(true);
		$mail->AddAddress($email, $name);
		$mail->AddReplyTo($reply_to, $from_name);
		$mail->AddCustomHeader('List-Unsubscribe-Post: List-Unsubscribe=One-Click');
		$mail->AddCustomHeader('List-Unsubscribe: <'.APP_PATH.'/unsubscribe/'.encrypt_val($email).'/'.encrypt_val($subscriber_list).'/'.encrypt_val($campaign_id).'>');
		$mail->AddCustomHeader('Precedence: Bulk');
		//check if attachments are available for this campaign to attach
		if(count($attachments)>0)
		{
			foreach($attachments as $attachment) $mail->AddAttachment($attachment);
		}
		$mail->Send();
		if(isset($GLOBALS['sendy_ses_fatal_error']) && $GLOBALS['sendy_ses_fatal_error']!='') exit;

		//increment recipient count if not using AWS or SMTP
		if((get_app_info('s3_key')=='' && get_app_info('s3_secret')=='') || ($smtp_host!='' && $smtp_port!='' && $smtp_username!='' && $smtp_password!=''))
		{
			//increment recipients number in campaigns table
			$q5 = 'UPDATE campaigns SET recipients = recipients+1 WHERE id = '.$campaign_id;
			mysqli_query($mysqli, $q5);

			//update last_campaign
			$q14 = 'UPDATE subscribers SET last_campaign = '.$campaign_id.' WHERE id = '.$subscriber_id;
			mysqli_query($mysqli, $q14);
		}
    }

    //====================== Send remaining in queue ======================//

    $q4 = 'SELECT id, query_str, http_headers, subscriber_id FROM queue FORCE INDEX (q_campaign_sent_id) WHERE campaign_id = '.$campaign_id.' AND sent = 0 ORDER BY id ASC';
    $r4 = mysqli_query($mysqli, $q4);
	    if ($r4 && mysqli_num_rows($r4) > 0)
	    {
		require_once('../helpers/class.amazonses.php');
		$ses_signer = new AmazonSES();
		$ses_signer->amazonSES_base_url = 'https://'.get_app_info('ses_endpoint');
		$ses_signer->aws_access_key_id = get_app_info('s3_key');
		$ses_signer->aws_secret_key = get_app_info('s3_secret');
		$ses_signer->Timezone = get_app_info('timezone');

	        while($row = mysqli_fetch_array($r4))
	        {
		$request_url = 'https://'.get_app_info('ses_endpoint');
			$queue_id = $row['id'];
			$query_str = stripslashes($row['query_str']);
			$http_headers = $ses_signer->make_required_http_headers_for_query_string($query_str);
			$subscriber_id = $row['subscriber_id'];

			$claim_result = mysqli_query($mysqli, 'UPDATE queue SET sent = 2 WHERE id = '.$queue_id.' AND sent = 0');
			if(!$claim_result || mysqli_affected_rows($mysqli) !== 1)
			{
				mysqli_query($mysqli, 'UPDATE campaigns SET send_status = "interrupted", send_error = "Unable to claim the remaining Amazon SES queue row." WHERE id = '.$campaign_id);
				break;
			}

		//Get server path
			$server_path_array = explode('includes/create/send-now.php', $_SERVER['SCRIPT_FILENAME']);
		    $server_path = $server_path_array[0];

		//send remaining in queue
	        $cr = curl_init();
	        curl_setopt($cr, CURLOPT_URL, $request_url);
		        curl_setopt($cr, CURLOPT_POST, $query_str);
		        curl_setopt($cr, CURLOPT_POSTFIELDS, $query_str);
	        curl_setopt($cr, CURLOPT_HTTPHEADER, $http_headers);
	        curl_setopt($cr, CURLOPT_HEADER, true);
	        curl_setopt($cr, CURLOPT_RETURNTRANSFER, true);
	        curl_setopt($cr, CURLOPT_SSL_VERIFYHOST, 2);
			curl_setopt($cr, CURLOPT_SSL_VERIFYPEER, 1);
			curl_setopt($cr, CURLOPT_CAINFO, $server_path.'certs/cacert.pem');

	        // Make the request and fetch response.
	        $response = curl_exec($cr);

	        //Get message ID from response
	        $messageIDArray = explode('<MessageId>', $response);
	        $messageIDArray2 = explode('</MessageId>', $messageIDArray[1]);
	        $messageID = $messageIDArray2[0];

	        $response_http_status_code = curl_getinfo($cr, CURLINFO_HTTP_CODE);

	        if ($response_http_status_code !== 200)
	        {
		        mysqli_query($mysqli, 'UPDATE queue SET sent = 0 WHERE id = '.$queue_id.' AND sent = 2');
		        $q7 = 'SELECT errors FROM campaigns WHERE id = '.$campaign_id;
		$r7 = mysqli_query($mysqli, $q7);
		if ($r7)
		{
		    while($row = mysqli_fetch_array($r7))
		    {
				$errors = $row['errors'];

				if($errors=='')
							$val = $subscriber_id.':'.$response_http_status_code;
						else
						{
							$errors .= ','.$subscriber_id.':'.$response_http_status_code;
							$val = $errors;
						}
		    }
		}

		        //update campaigns' errors column
		        $q6 = 'UPDATE campaigns SET errors = "'.$val.'" WHERE id = '.$campaign_id;
				mysqli_query($mysqli, $q6);
	        }
	        else
	        {
				mysqli_begin_transaction($mysqli);
				$q5 = 'UPDATE queue SET sent = 1, query_str = NULL, http_headers = NULL WHERE id = '.$queue_id.' AND sent = 2';
				$r5 = mysqli_query($mysqli, $q5);
				if(!$r5 || mysqli_affected_rows($mysqli) !== 1)
				{
					mysqli_rollback($mysqli);
					mysqli_query($mysqli, 'UPDATE campaigns SET send_status = "interrupted", send_error = "SES accepted a message, but Sendy could not record its queue acknowledgement." WHERE id = '.$campaign_id);
					break;
				}

				$q6 = 'UPDATE campaigns SET recipients = recipients+1 WHERE recipients < to_send AND id = '.$campaign_id;
				$r6 = mysqli_query($mysqli, $q6);

				//update messageID of subscriber
				$q14 = 'UPDATE subscribers SET messageID = "'.$messageID.'" WHERE id = '.$subscriber_id;
				$r14 = mysqli_query($mysqli, $q14);
				if(!$r6 || !$r14 || !mysqli_commit($mysqli))
				{
					mysqli_rollback($mysqli);
					mysqli_query($mysqli, 'UPDATE campaigns SET send_status = "interrupted", send_error = "SES accepted a message, but Sendy could not finish recording it." WHERE id = '.$campaign_id);
					break;
				}
	        }
        }
    }
    else
	{
		// Leave to_send unchanged. If no queue rows exist while recipients is
		// still below to_send, the campaign should remain resumable.
	}
    //======================= /Send remaining in queue ======================//
}
else
{
	// Leave to_send unchanged. Returning no subscriber rows should not turn a
	// partial send into a completed campaign.
}


//=========================== Post processing ===========================//
$q8 = 'SELECT recipients FROM campaigns where id = '.$campaign_id;
$r8 = mysqli_query($mysqli, $q8);
if ($r8) while($row = mysqli_fetch_array($r8)) $no_of_recipients = $row['recipients'];
if($no_of_recipients >= $to_send)
{
    //tags for subject to me
	preg_match_all('/\[([a-zA-Z0-9!#%^&*()+=$@._\-\:|\/?<>~`"\'\s]+),\s*fallback=/i', $title, $matches_var, PREG_PATTERN_ORDER);
	preg_match_all('/,\s*fallback=([a-zA-Z0-9!,#%^&*()+=$@._\-\:|\/?<>~`"\'\s]*)\]/i', $title, $matches_val, PREG_PATTERN_ORDER);
	preg_match_all('/(\[[a-zA-Z0-9!#%^&*()+=$@._\-\:|\/?<>~`"\'\s]+,\s*fallback=[a-zA-Z0-9!,#%^&*()+=$@._\-\:|\/?<>~`"\'\s]*\])/i', $title, $matches_all, PREG_PATTERN_ORDER);
	preg_match_all('/\[([^\]]+),\s*fallback=/i', $title, $matches_var, PREG_PATTERN_ORDER);
	preg_match_all('/,\s*fallback=([^\]]*)\]/i', $title, $matches_val, PREG_PATTERN_ORDER);
	preg_match_all('/(\[[^\]]+,\s*fallback=[^\]]*\])/i', $title, $matches_all, PREG_PATTERN_ORDER);
	$matches_var = $matches_var[1];
	$matches_val = $matches_val[1];
	$matches_all = $matches_all[1];
	for($i=0;$i<count($matches_var);$i++)
	{
		$field = $matches_var[$i];
		$fallback = $matches_val[$i];
		$tag = $matches_all[$i];
		//for each match, replace tag with fallback
		$title = str_replace($tag, $fallback, $title);
	}
	$title = str_replace('[Name]', $from_name, $title);
	$title = str_replace('[Email]', $from_email, $title);
	$title = str_replace($unconverted_date, $converted_date, $title);

	$q4 = 'UPDATE campaigns SET recipients = '.$to_send.', send_status = NULL, send_error = NULL WHERE id = '.$campaign_id.' AND userID = '.get_app_info('main_userID');
	mysqli_query($mysqli, $q4);

	$q9 = 'DELETE FROM queue WHERE campaign_id = '.$campaign_id;
	mysqli_query($mysqli, $q9);

	$q11 = 'SELECT errors, to_send_lists FROM campaigns WHERE id = '.$campaign_id;
	$r11 = mysqli_query($mysqli, $q11);
	if ($r11)
	{
		while($row = mysqli_fetch_array($r11))
		{
			$error_recipients_ids = $row['errors'];
			$tsl = $row['to_send_lists'];
		}

		if($error_recipients_ids=='')
		{
			$q10 = 'UPDATE subscribers SET bounce_soft = 0 WHERE list IN ('.$tsl.')';
			mysqli_query($mysqli, $q10);
		}
		else
		{
			$error_recipients_ids_array = explode(',', $error_recipients_ids);
			$eid_array = array();
			foreach($error_recipients_ids_array as $id_val)
			{
				$id_val_array = explode(':', $id_val);
				array_push($eid_array, $id_val_array[0]);
			}
			$error_recipients_ids = implode(',', $eid_array);
			$q10 = 'UPDATE subscribers SET bounce_soft = 0 WHERE list IN ('.$tsl.') AND id NOT IN ('.$error_recipients_ids.')';
			mysqli_query($mysqli, $q10);
		}
	}

	//sent timestamp
	$sent_formatted = date("D, M d, Y, h:iA", time());

	//Zapier Trigger 'new_campaign_sent' event
	zapier_trigger_new_campaign_sent($title, $from_name, $from_email, $reply_to, $sent_formatted, $web_version, $app);

	//Run rules
	$rules_data = array(
	    'trigger' => 'campaign_sent',
		'app_name' => $app_name,
	    'campaign_title' => $campaign_title,
	    'subject' => $title,
	    'from_name' => $from_name,
	    'from_email' => $from_email,
	    'reply_to' => $reply_to,
	    'sent' => $sent_formatted,
	    'no_of_recipients' => $no_of_recipients,
	    'webversion' => $web_version,
	    'brand_id' => $app,
	    'campaign_id' => $campaign_id,
	    'report_url' => "$app_path/report?i=$app&c=$campaign_id"
    );

    //Run rules
	run_rule($rules_data);

	//quit
	exit;
}

//========================== /Post processing ===========================//

?>
