Пример #1
0
    /**
     * ProcessJob
     * Does most of the work setting up the job (creates the queue, removes duplicates and so on) to run. Once the job has been set up ready to run, it 'Actions' the job, then marks it as 'finished'.
     *
     * @param Int $jobid The job to run.
     *
     * @see Email_API
     * @see Subscriber_API
     * @see Lists_API
     * @see newsletter_api
     * @see GetUser
     * @see StartJob
     * @see GetJobQueue
     * @see CreateQueue
     * @see JobQueue
     * @see Subscribers_API::GetSubscribers
     * @see RemoveDuplicatesInQueue
     * @see RemoveBannedEmails
     * @see ActionJob
     * @see FinishJob
     *
     * @return Boolean Returns false if the job can't be started. Otherwise runs the job and returns true.
     */
    function ProcessJob($jobid=0) {
        if (!$this->StartJob($jobid)) {
            $this->PauseJob($jobid);
            $this->jobstatus = 'p';
            trigger_error("Unable to start send job {$jobid}");
            return false;
        }

        $user = GetUser($this->jobowner);
        IEM::userLogin($this->jobowner, false);

        $queueid = false;

        // if there's no queue, start one up.
        if (!$queueid = $this->GetJobQueue($jobid)) {
            $sendqueue = $this->CreateQueue('send');
            $queueok = $this->JobQueue($jobid, $sendqueue);
            $send_criteria = $this->jobdetails['SendCriteria'];

            $original_queuesize = $this->jobdetails['SendSize'];

            $queueinfo = array('queueid' => $sendqueue, 'queuetype' => 'send', 'ownerid' => $this->jobowner);

            if (isset($this->jobdetails['Segments']) && is_array($this->jobdetails['Segments'])) {
                $this->Subscriber_API->GetSubscribersFromSegment($this->jobdetails['Segments'], false, $queueinfo, 'nosort');
            } else {
                $this->Subscriber_API->GetSubscribers($send_criteria, array(), false, $queueinfo, $sendqueue);
            }

            $this->Subscriber_API->RemoveDuplicatesInQueue($sendqueue, 'send', $this->jobdetails['Lists']);

            $this->Subscriber_API->RemoveBannedEmails($this->jobdetails['Lists'], $sendqueue, 'send');

            $this->Subscriber_API->RemoveUnsubscribedEmails($this->jobdetails['Lists'], $sendqueue, 'send');

            $queueid = $sendqueue;

            $newsletterstats = $this->jobdetails;
            $newsletterstats['Job'] = $jobid;
            $newsletterstats['Queue'] = $sendqueue;
            $newsletterstats['SentBy'] = $queueinfo['ownerid'];

            $real_queuesize = $this->Subscriber_API->QueueSize($queueid, 'send');

            $newsletterstats['SendSize'] = $real_queuesize;

            $statid = $this->Stats_API->SaveNewsletterStats($newsletterstats);

            /**
             * Process tracker request where because cron was not enabled, we need to parse the option straight away
             * @todo Result for the call to module_Tracker::ParseOptionsForAllTracker() is not being processed and being ignored
             */
            $tempAPIFile = dirname(__FILE__) . '/module_trackerfactory.php';
            if (is_file($tempAPIFile)) {
                require_once($tempAPIFile);
                $temp = array_merge($this->jobdetails, array('statid' => $statid,
                    'stattype' => 'newsletter',
                    'newsletterid' => $this->jobdetails['Newsletter']));

                $status = module_Tracker::ParseOptionsForAllTracker($temp);
            }
            /**
             * -----
             */
            /**
             * So we can link user stats to send stats, we need to update it.
             */
            $this->Stats_API->UpdateUserStats($queueinfo['ownerid'], $jobid, $statid);

            /**
             * The 'queuesize' in the stats_users table is updated by MarkNewsletterFinished in send.php
             * so we don't need to worry about it while setting up the send.
             * That takes into account whether some recipients were skipped because a html-only email was sent etc.
             */
            /**
             * We re-check the user stats in case a bunch of subscribers have joined, or the user has done something like:
             * - create a list
             * - added a few subscribers
             * - scheduled a send
             * - added more subscribers
             */
            $check_stats = $this->Stats_API->ReCheckUserStats($user, $original_queuesize, $real_queuesize, AdjustTime());

            list($ok_to_send, $not_ok_to_send_reason) = $check_stats;
            if (!$ok_to_send) {
                trigger_error(__CLASS__ . '::' . __METHOD__ . " -- " . GetLang($not_ok_to_send_reason), E_USER_WARNING);
                $this->PauseJob($jobid);
                $this->UnapproveJob($jobid);
                IEM::userLogout();
                return false;
            }

            API_USERS::creditEvaluateWarnings($user->GetNewAPI());
        }

        $this->statid = $this->LoadStats($jobid);
        if (empty($this->statid)) {
            trigger_error(__CLASS__ . '::' . __METHOD__ . " -- Cannot find statid. Previous preliminary job process did not get finalized (either CRON died, or it hasn't finished processing the job). Ignoring this job: jobid {$jobid}.", E_USER_NOTICE);
            IEM::userLogout();
            return false;
        }

        $queuesize = $this->Subscriber_API->QueueSize($queueid, 'send');

        // used by send.php::CleanUp
        $this->queuesize = $this->jobdetails['SendSize'];

        /**
         * There's nothing left? Just mark it as done.
         */
        if ($queuesize == 0) {
            $this->jobstatus = 'c';
            $this->FinishJob($jobid);
            IEM::userLogout();
            return true;
        }

        $finished = $this->ActionJob($jobid, $queueid);

        if ($finished) {
            $this->jobstatus = 'c';
            $this->FinishJob($jobid);
        }

        IEM::userLogout();
        return true;
    }
Пример #2
0
	/**
	* Process
	* This works out where you are up to in the send process and takes the appropriate action. Most is passed off to other methods in this class for processing and displaying the right forms.
	*
	* @return Void Doesn't return anything.
	*/
	function Process()
	{
		$action = (isset($_GET['Action'])) ? strtolower($_GET['Action']) : null;
		$user = IEM::userGetCurrent();
		$access = $user->HasAccess('Newsletters', 'send');

		$popup = (in_array($action, $this->PopupWindows)) ? true : false;
		$this->PrintHeader($popup);

		if (!$access) {
			$this->DenyAccess();
			return;
		}

		if ($action == 'processpaging') {
			$this->SetPerPage($_GET['PerPageDisplay']);
			$action = '';
		}

		switch ($action) {
			case 'viewsenderrors':
				$job = (isset($_GET['Job'])) ? (int)$_GET['Job'] : 0;
				if (!$this->CanAccessJobs($job)) {
					$this->DenyAccess();
					return;
				}
				echo $this->PrintSendFailureReport($job);
			break;

			case 'view_report':
				$queueid = IEM::sessionGet('ReportQueue');

				$report_type = (isset($_GET['ReportType'])) ? strtolower($_GET['ReportType']) : null;
				switch ($report_type) {
					case '1':
						$GLOBALS['Heading'] = GetLang('SendProblem_Report_Subscriber_Problem_Heading');
						$GLOBALS['Intro'] = GetLang('SendProblem_Report_Subscriber_Problem_Intro');
					break;

					case '10':
						$GLOBALS['Heading'] = GetLang('SendProblem_Report_Email_Problem_Heading');
						$GLOBALS['Intro'] = GetLang('SendProblem_Report_Email_Problem_Intro');
					break;

					case '20':
						$GLOBALS['Heading'] = GetLang('SendProblem_Report_MailServer_Problem_Heading');
						$GLOBALS['Intro'] = GetLang('SendProblem_Report_MailServer_Problem_Intro');
					break;

					case '30':
						$GLOBALS['Heading'] = GetLang('SendProblem_Report_SMTPMailServer_Problem_Heading');
						$GLOBALS['Intro'] = GetLang('SendProblem_Report_SMTPMailServer_Problem_Intro');
					break;

					default:
						$GLOBALS['Heading'] = GetLang('SendProblem_Report_Invalid_Heading');
						$GLOBALS['Intro'] = GetLang('SendProblem_Report_Invalid_Intro');
						$GLOBALS['EmailList'] = GetLang('SendProblem_InvalidReportURL');
						$this->ParseTemplate('SendProblem_Report_Results_View');
					break 2;
				}

				$api = $this->GetApi('Subscribers');

				$email_list = '';
				$problem_email_addresses = $api->GetUnsentSubscribers($queueid, $report_type);
				foreach ($problem_email_addresses as $emailaddress) {
					$email_list .= htmlspecialchars($emailaddress, ENT_QUOTES, SENDSTUDIO_CHARSET) . "\n";
				}
				$GLOBALS['EmailList'] = $email_list;
				$this->ParseTemplate('SendProblem_Report_Results_View');

			break;


			case 'pausesend':
				$job = (int)$_GET['Job'];
				if (!$this->CanAccessJobs($job)) {
					$this->DenyAccess();
					return;
				}

				$api = $this->GetApi('Jobs');
				$paused = $api->PauseJob($job);
				if ($paused) {
					$GLOBALS['Message'] = $this->PrintSuccess('Send_Paused_Success');
				} else {
					$GLOBALS['Error'] = GetLang('Send_Paused_Failure');
					$GLOBALS['Message'] = $this->ParseTemplate('ErrorMsg', true, false);
				}
				$this->ParseTemplate('Send_Step5_Paused');
			break;

			case 'sendfinished':
				$job = (int)$_GET['Job'];
				if (!$this->CanAccessJobs($job)) {
					$this->DenyAccess();
					return;
				}

				$send_details = IEM::sessionGet('SendDetails');

				$statsapi = $this->GetApi('Stats');

				$statsapi->MarkNewsletterFinished($send_details['StatID'], $send_details['SendSize']);

				$timetaken = $send_details['SendEndTime'] - $send_details['SendStartTime'];
				$timedifference = $this->TimeDifference($timetaken);

				$GLOBALS['SendReport_Intro'] = sprintf(GetLang('SendReport_Intro'), $timedifference);

				$sendreport = '';
				if ($send_details['EmailResults']['success'] > 0) {
					if ($send_details['EmailResults']['success'] == 1) {
						$sendreport .= $this->PrintSuccess('SendReport_Success_One');
					} else {
						$sendreport .= $this->PrintSuccess('SendReport_Success_Many', $this->FormatNumber($send_details['EmailResults']['success']));
					}
				}

				$this->PrintSendFailureReport($job, $sendreport);

				$api = $this->GetApi('Jobs');
				$api->FinishJob($job);
				$api->ClearQueue($send_details['SendQueue'], 'send');
			break;

			case 'send':
				IEM::sessionRemove('ApproveJob');
				API_USERS::creditEvaluateWarnings($user->GetNewAPI());

				$jobid = (int)$_GET['Job'];

				if (!$this->CanAccessJobs($jobid)) {
					$this->DenyAccess();
					return;
				}

				$subscriberApi = $this->GetApi('Subscribers');

				$jobApi = $this->GetApi('Jobs');

				if (!isset($_GET['Started'])) {
					$jobApi->StartJob($jobid);
				}

				$sendqueue = $jobApi->GetJobQueue($jobid);

				$send_api = $this->GetApi('Send');

				$job = $jobApi->LoadJob($jobid);

				$send_api->Set('statid', $send_api->LoadStats($jobid));

				$send_api->Set('jobdetails', $job['jobdetails']);
				$send_api->Set('jobowner', $job['ownerid']);

				if (isset($_GET['Resend'])) {
					// this function handles moving everyone onto the 'live' queue etc so we don't need to worry about any of that.
					$send_api->ResendJob_Setup($jobid);
				}

				$queuesize = $jobApi->QueueSize($sendqueue, 'send');

				$send_details = IEM::sessionGet('SendDetails');

				$send_details['SendQueue'] = $sendqueue;

				$timenow = AdjustTime(0, true, null, true);

				$timediff = ($timenow - $send_details['SendStartTime']);

				$time_so_far = $this->TimeDifference($timediff);

				$num_left_to_send = $send_details['SendSize'] - $queuesize;

				if ($num_left_to_send > 0) {
					$timeunits = $timediff / ($num_left_to_send);
					$timediff = ($timeunits * $queuesize);
				} else {
					$timediff = 0;
				}
				$timewaiting = $this->TimeDifference($timediff);

				$GLOBALS['SendTimeSoFar'] = sprintf(GetLang('Send_TimeSoFar'), $time_so_far);
				$GLOBALS['SendTimeLeft'] = sprintf(GetLang('Send_TimeLeft'), $timewaiting);

				if ($queuesize <= 0) {
					$email = $this->GetApi('Email');
					if (SENDSTUDIO_SAFE_MODE) {
						$email->Set('imagedir', TEMP_DIRECTORY . '/send');
					} else {
						$email->Set('imagedir', TEMP_DIRECTORY . '/send.' . $jobid . '.' . $sendqueue);
					}
					$email->CleanupImages();

					$send_details['SendEndTime'] = AdjustTime(0, true, null, true);
					IEM::sessionSet('SendDetails', $send_details);

					$GLOBALS['Send_NumberLeft'] = GetLang('SendFinished');
					$this->ParseTemplate('Send_Step5');
					?>
						<script>
							window.opener.focus();
							window.opener.document.location = 'index.php?Page=Send&Action=SendFinished&Job=<?php echo $jobid; ?>&r=<?php echo time(); ?>';
							window.close();
						</script>
					<?php
					break;
				}

				if ($queuesize == 1) {
					$GLOBALS['Send_NumberLeft'] = GetLang('Send_NumberLeft_One');
				} else {
					$GLOBALS['Send_NumberLeft'] = sprintf(GetLang('Send_NumberLeft_Many'), $this->FormatNumber($queuesize));
				}

				if ($num_left_to_send == 1) {
					$GLOBALS['Send_NumberAlreadySent'] = GetLang('Send_NumberSent_One');
				} else {
					$GLOBALS['Send_NumberAlreadySent'] = sprintf(GetLang('Send_NumberSent_Many'), $this->FormatNumber($num_left_to_send));
				}

				$send_api->SetupJob($jobid, $sendqueue);

				$recipients = $send_api->FetchFromQueue($sendqueue, 'send', 1, 1);

				$send_api->SetupDynamicContentFields($recipients);

				$send_api->SetupCustomFields($recipients);

				$sent_ok = false;

				foreach ($recipients as $p => $recipientid) {
					$send_results = $send_api->SendToRecipient($recipientid, $sendqueue);

					// save the info in the session, then see if we need to pause between each email.
					if ($send_results['success'] > 0) {
						$sent_ok = true;
						$send_details['EmailResults']['success']++;
					} else {
						$send_details['EmailResults']['failure']++;
					}
					$send_details['EmailResults']['total']++;
					IEM::sessionSet('SendDetails', $send_details);
				}

				$GLOBALS['JobID'] = $jobid;

				$template = $this->ParseTemplate('Send_Step5', true);
				$template .= $this->PrintFooter(true, true);
				echo $template;

				// we should only need to pause if we successfully sent.
				if ($sent_ok) {
					$send_api->Pause();
				}
				exit;
			break;

			case 'step4':
				$newsletter_chosen = $_POST['newsletter'];
				if ($newsletter_chosen == 0) {
					$this->SelectNewsletter(GetLang('Send_Step4_ChooseNewsletter'));
					break;
				}

				if (!$this->CanAccessNewsletter($newsletter_chosen)) {
					$this->DenyAccess();
					break;
				}

				$send_details = IEM::sessionGet('SendDetails');

				$send_details['Multipart'] = (isset($_POST['sendmultipart'])) ? 1 : 0;
				$send_details['TrackOpens'] = (isset($_POST['trackopens'])) ? 1 : 0;
				$send_details['TrackLinks'] = (isset($_POST['tracklinks'])) ? 1 : 0;
				$send_details['EmbedImages'] = (isset($_POST['embedimages'])) ? 1 : 0;
				$send_details['Newsletter'] = $_POST['newsletter'];
				$send_details['SendFromName'] = $_POST['sendfromname'];
				$send_details['SendFromEmail'] = $_POST['sendfromemail'];
				$send_details['ReplyToEmail'] = (isset($_POST['replytoemail'])) ? $_POST['replytoemail'] : $send_details['SendFromEmail'];
				$send_details['BounceEmail'] = (isset($_POST['bounceemail'])) ? $_POST['bounceemail'] : $send_details['SendFromEmail'];

				$newsletterapi = $this->GetApi('Newsletters');
				$newsletterapi->Load($send_details['Newsletter']);
				$archive = $newsletterapi->Archive();
				if(empty($archive)) {
					$GLOBALS['Messages'] = $this->PrintWarning('SendNewsletterArchive_DeactivatedWarning');
				}

				$to_firstname = false;
				if (isset($_POST['to_firstname']) && (int)$_POST['to_firstname'] > 0) {
					$to_firstname = (int)$_POST['to_firstname'];
				}

				$send_details['To_FirstName'] = $to_firstname;

				$to_lastname = false;
				if (isset($_POST['to_lastname']) && (int)$_POST['to_lastname'] > 0) {
					$to_lastname = (int)$_POST['to_lastname'];
				}

				$send_details['To_LastName'] = $to_lastname;

				$send_details['Charset'] = SENDSTUDIO_CHARSET;

				$send_details['NotifyOwner'] = (isset($_POST['notifyowner'])) ? 1 : 0;

				$send_details['SendStartTime'] = AdjustTime(0, true, null, true);

				$send_details['EmailResults']['success'] = 0;
				$send_details['EmailResults']['total'] = 0;
				$send_details['EmailResults']['failure'] = 0;

				$jobapi = $this->GetApi('Jobs');

				$scheduletime = AdjustTime(0, true, null, true);

				$statsapi = $this->GetApi('Stats');

				IEM::sessionSet('SendDetails', $send_details);

				$subscriber_count = $send_details['SendSize'];

				$approved = $user->Get('userid');

				$newslettername = '';
				$newsletterApi = $this->GetApi('Newsletters');
				$newsletterApi->Load($send_details['Newsletter']);
				$newslettername = $newsletterApi->Get('name');
				$newslettersubject = $newsletterApi->Get('subject');

				$newsletter_size = 0;
				$html_size = utf8_strlen($newsletterApi->Get('htmlbody'));
				$text_size = utf8_strlen($newsletterApi->Get('textbody'));

				// if you are sending multipart, then put both parts together to work out an approximate size.
				if ($send_details['Multipart']) {
					$newsletter_size += $html_size + $text_size;
				} else {
					// if you are not sending multipart, then try to work out the html part (as a guide for maximum size).
					if ($html_size > 0) {
						$newsletter_size += $html_size;
					} else {
						$newsletter_size += $text_size;
					}
				}

				$attachments = $this->GetAttachments('newsletters', $send_details['Newsletter'], true);
				if (isset($attachments['filelist'])) {
					foreach ($attachments['filelist'] as $p => $attachment) {
						$file = $attachments['path'] . '/' . $attachment;
						// base64 encoding adds about 30% overhead so we need to add it here.
						$newsletter_size += 1.3 * filesize($file);
					}
				}

				$email_api = $this->GetApi('Email');

				$problem_images = array();

				// we'll do a quick check for the images in the html content to make sure they all work.
				$email_api->Set('EmbedImages', true);
				$email_api->AddBody('html', $newsletterApi->Get('htmlbody'));
				$images = $email_api->GetImages();
				if (is_array($images) && !empty($images)) {
					$max_image_count = $this->max_image_count;

					$counter = 0;
					$total_image_size = 0;
					$image_exceed_threshold = (count($images) > $max_image_count);

					foreach ($images as $md5 => $image_url) {
						list($img, $error) = $email_api->GetImage($image_url);
						$image_size = 1.3 * strlen($img);
						if ($img) {
							if ($send_details['EmbedImages']) {
								// base64 encoding adds about 30% overhead so we need to add it here.
								$newsletter_size += $image_size;
							}
						} else {
							$problem_images[] = array('img' => $image_url, 'error' => $error);
						}

						// Images exceed "max image count" threshold....
						// We will need to do something about it so that the application doesn't timeout
						if ($image_exceed_threshold) {
							$total_image_size += $image_size;

							if (++$counter >= $max_image_count) {
								$temp = sprintf(GetLang('CannotVerifyAllImages_ExceedThreshold'), $max_image_count);
								$temp .= sprintf(GetLang('CannotVerifyAllImages_OnlyThresholdImagesVerified'), $max_image_count);

								$problem_images[] = $temp;
								if ($send_details['EmbedImages']) {
									$problem_images[] = sprintf(GetLang('CannotVerifyAllImages_SendSizeEstimated'));

									$average_image_size = ($total_image_size / $max_image_count);
									$total_image_count = count($images);
									$newsletter_size += abs($average_image_size * ($total_image_count - $max_image_count));
								}
								break;
							}
						}
					}
				}

				$img_warning = '';

				if (!empty($problem_images)) {
					foreach ($problem_images as $problem_details) {
						if (is_array($problem_images)) {
							$img_warning .= sprintf(GetLang('UnableToLoadImage'), $problem_details['img'], $problem_details['img'], $problem_details['error']);
						} else {
							$img_warning .= "- {$problem_details}<br/>";
						}
					}
				}

				if ($img_warning) {
					if ($send_details['EmbedImages']) {
						$warning_var = 'UnableToLoadImage_Newsletter_List_Embed';
					} else {
						$warning_var = 'UnableToLoadImage_Newsletter_List';
					}
					$GLOBALS['ImageWarning'] = $this->PrintWarning($warning_var, $img_warning);
				}

				if (SENDSTUDIO_EMAILSIZE_MAXIMUM > 0) {
					if ($newsletter_size >= (SENDSTUDIO_EMAILSIZE_MAXIMUM*1024)) {
						$this->SelectNewsletter(sprintf(GetLang('Newsletter_Size_Over_EmailSize_Maximum'), $this->EasySize(SENDSTUDIO_EMAILSIZE_MAXIMUM*1024, 0)));
						break;
					}
				}

				if (($subcount = IEM::sessionGet('SendSize_Many_Extra', false)) === false) {
					$subcount = $subscriber_count;
				}

				$GLOBALS['ApproximateSendSize'] = sprintf(GetLang('Newsletter_SendSize_Approximate'), $this->EasySize($newsletter_size, 0), $this->EasySize($newsletter_size * $subcount, 1));

				if (SENDSTUDIO_EMAILSIZE_WARNING > 0) {
					if ($newsletter_size > (SENDSTUDIO_EMAILSIZE_WARNING*1024)) {
						$GLOBALS['EmailSizeWarning'] = $this->PrintWarning('Newsletter_Size_Over_EmailSize_Warning_Send', $this->EasySize((SENDSTUDIO_EMAILSIZE_WARNING*1024), 0));
					}
				}

				if (SENDSTUDIO_CRON_ENABLED && SENDSTUDIO_CRON_SEND > 0) {
					$sendtime = $_POST['sendtime'];

					if (isset($_POST['sendimmediately']) && $_POST['sendimmediately'] == '1') {
						/*
						* Set the date/time to now if sendimmediately was ticked
						*/
						$time_now = AdjustTime(0, true, null, true);
						$sendtime = AdjustTime($time_now, false, 'h:iA');
						$_POST['datetime']['year'] = AdjustTime($time_now,false,'Y');
						$_POST['datetime']['month'] = AdjustTime($time_now,false,'n');
						$_POST['datetime']['day'] = AdjustTime($time_now,false,'j');
					}

					/*
					* the sendtime is in this format:
					* hr:minAM
					* so we need to look at the character positions rather than exploding on the separator.
					*/
					$hr = substr($sendtime, 0, 2);
					$minute = substr($sendtime, 3, 2);
					$ampm = substr($sendtime, -2);

					if (strtolower($ampm) == 'pm') {
						if ($hr != 12) {
							$hr = $hr + 12;
						}
					}

					if (strtolower($ampm) == 'am' && $hr == 12) {
						$hr = 0;
					}

					if ($hr > 23) {
						$hr = $hr - 24;
					}

					$check_schedule_time = AdjustTime(array($hr, $minute, 0, (int)$_POST['datetime']['month'], (int)$_POST['datetime']['day'], (int)$_POST['datetime']['year']), true);

					$five_mins_ago = $statsapi->GetServerTime() - (5*60);

					if ($check_schedule_time < $five_mins_ago) {
						$this->SelectNewsletter(GetLang('Send_Step4_CannotSendInPast'));
						break;
					}

					$send_criteria = $send_details['SendCriteria'];

					$server_schedule_time = array($hr, $minute, 0, (int)$_POST['datetime']['month'], (int)$_POST['datetime']['day'], (int)$_POST['datetime']['year']);

					$scheduletime = AdjustTime($server_schedule_time, true);
					
					/**
					* Since we're using scheduled sending, we need to check user stats for when this is scheduled to send.
					*/
					$check_stats = $statsapi->CheckUserStats($user, $subscriber_count, $scheduletime);

					list($ok_to_send, $not_ok_to_send_reason) = $check_stats;

					if (!$ok_to_send) {
						echo $this->PrintError($not_ok_to_send_reason);
						// Please refer to Mitch about why I comment this out
						//$this->FilterRecipients($send_details['Lists'], GetLang($not_ok_to_send_reason));
						break;
					}

					$send_details['SendStartTime'] = $scheduletime;

					/**
					 * Store required tracker variables in send details
					 */
					if (check($this, 'mailTrack', true)) {
						if ($this->GetApi('module_TrackerFactory', false)) {
							$list = module_Tracker::GetRequestOptionNamesForAllTracker();
							foreach ($list as $each) {
								if (isset($_POST[$each])) {
									$send_details[$each] = $_POST[$each];
								}
							}
						}
					}
					
				}

				/**
				* see if they have hit refresh on this last step.
				* if they have, then there will already be an approvejob session variable.
				*
				* If there is one there already, clean it up.
				* Give the user back their email credits and delete the stats etc.
				*/
				$job_already_started = IEM::sessionGet('ApproveJob');

				if ($job_already_started) {

					$send_size = IEM::sessionGet('JobSendSize');

					$statsapi = $this->GetApi('Stats');
					$jobapi = $this->GetApi('Jobs');
					// we need to start the job
					// then get the queue
					// then we can get the stats
					// so a user can get their credits back
					// if they cancel a send before doing anything.
					$jobapi->StartJob($job_already_started);
					$queueid = $jobapi->GetJobQueue($job_already_started);

					$statid = $statsapi->GetStatsByQueue($queueid);

					$statsapi->Delete($statid, 'n');
					$jobapi->PauseJob($job_already_started);
					$jobapi->Delete($job_already_started);

					IEM::sessionRemove('JobSendSize');
					IEM::sessionRemove('ApproveJob');
				}

				$jobcreated = $jobapi->Create('send', $scheduletime, $user->userid, $send_details, 'newsletter', $send_details['Newsletter'], $send_details['Lists'], $approved);

				IEM::sessionSet('ApproveJob', $jobcreated);

				IEM::sessionSet('JobSendSize', $subscriber_count);

				// if we're not using scheduled sending, create the queue and start 'er up!
				if (!SENDSTUDIO_CRON_ENABLED || SENDSTUDIO_CRON_SEND <= 0) {
					/**
					* Record the user stats for this send.
					* We have to do it here so you can't schedule multiple sends and then it records everything.
					*/
					$statsapi->RecordUserStats($user->userid, $jobcreated, $subscriber_count, $scheduletime);
					
					$subscriberApi = $this->GetApi('Subscribers');

					$sendqueue = $subscriberApi->CreateQueue('Send');

					$jobapi->StartJob($jobcreated);

					$queuedok = $jobapi->JobQueue($jobcreated, $sendqueue);

					$send_criteria = $send_details['SendCriteria'];

					$queueinfo = array('queueid' => $sendqueue, 'queuetype' => 'send', 'ownerid' => $user->userid);

					if (isset($send_details['Segments']) && is_array($send_details['Segments'])) {
						$subscriberApi->GetSubscribersFromSegment($send_details['Segments'], false, $queueinfo, 'nosort');
					} else {
						$subscriberApi->GetSubscribers($send_criteria, array(), false, $queueinfo, $user->userid);
					}

					if (SENDSTUDIO_DATABASE_TYPE == 'pgsql') {
						$subscriberApi->Db->OptimizeTable(SENDSTUDIO_TABLEPREFIX . "queues");
					}

					$subscriberApi->RemoveDuplicatesInQueue($sendqueue, 'send', $send_details['Lists']);

					$subscriberApi->RemoveBannedEmails($send_details['Lists'], $sendqueue, 'send');

					$subscriberApi->RemoveUnsubscribedEmails($send_details['Lists'], $sendqueue, 'send');

					if (SENDSTUDIO_DATABASE_TYPE == 'pgsql') {
						$subscriberApi->Db->OptimizeTable(SENDSTUDIO_TABLEPREFIX . "queues");
					}

					$send_details['SendSize'] = $subscriberApi->QueueSize($sendqueue, 'send');

					$newsletterstats = $send_details;
					$newsletterstats['Job'] = $jobcreated;
					$newsletterstats['Queue'] = $sendqueue;
					$newsletterstats['SentBy'] = $queueinfo['ownerid'];

					$statid = $statsapi->SaveNewsletterStats($newsletterstats);

					/**
					 * Process tracker request hwere because cron was not enabled
					 * @todo Result for the call to module_Tracker::ParseOptionsForAllTracker() is not being processed and being ignored
					 */
					if (check($this, 'TrackAllLinks', true)) {
						if ($this->GetApi('module_TrackerFactory', false)) {
							$temp = array_merge($_POST, array(	'statid'		=> $statid,
																'stattype'		=> 'newsletter',
																'newsletterid'	=> $send_details['Newsletter']));

							$status = module_Tracker::ParseOptionsForAllTracker($temp);
						}
					}

					$send_details['StatID'] = $statid;

					/**
					* So we can link user stats to send stats, we need to update it.
					*/
					$statsapi->UpdateUserStats($user->userid, $jobcreated, $statid);

					$jobapi->PauseJob($jobcreated);

					IEM::sessionSet('SendDetails', $send_details);

					$GLOBALS['JobID'] = $jobcreated;
				}

				$listdetails = array();
				$listApi = $this->GetApi('Lists');
				foreach ($send_details['Lists'] as $l => $listid) {
					$listApi->Load($listid);
					$listdetails[] = $listApi->Get('name');
				}
				$listnames = implode(', ', $listdetails);

				$GLOBALS['Send_NewsletterName'] = sprintf(GetLang('Send_NewsletterName'), htmlspecialchars($newslettername, ENT_QUOTES, SENDSTUDIO_CHARSET));
				$GLOBALS['Send_NewsletterSubject'] = sprintf(GetLang('Send_NewsletterSubject'), htmlspecialchars($newslettersubject, ENT_QUOTES, SENDSTUDIO_CHARSET));

				$GLOBALS['Send_SubscriberList'] = sprintf(GetLang('Send_SubscriberList'), htmlspecialchars($listnames, ENT_QUOTES, SENDSTUDIO_CHARSET));

				$last_sent_details = $newsletterApi->GetLastSent($send_details['Newsletter']);

				$last_sent = $last_sent_details['starttime'];
				if ($last_sent <= 0 && $send_details['SendSize'] > 5) {
					$GLOBALS['SentToTestListWarning'] = $this->PrintWarning('SendToTestListWarning');
				}

				$SendInfo = IEM::sessionGet('SendInfoDetails');

				if (SENDSTUDIO_CRON_ENABLED && SENDSTUDIO_CRON_SEND > 0) {
					/**
					* Record the user stats for this send.
					* We have to do it here so you can't schedule multiple sends and then it records everything.
					*/
					$statsapi->RecordUserStats($user->userid, $jobcreated, $subscriber_count, $scheduletime);
					
					$GLOBALS['Send_ScheduleTime'] = sprintf(GetLang('JobScheduled'), $this->PrintTime($scheduletime));
					$GLOBALS['Send_TotalRecipients'] = sprintf(GetLang('Send_TotalRecipients_Cron'), $this->FormatNumber($SendInfo['Count']));

					$this->ParseTemplate('Send_Step4_Cron');
					break;
				}

				$GLOBALS['Send_TotalRecipients'] = sprintf(GetLang('Send_TotalRecipients'), $this->FormatNumber($newsletterApi->QueueSize($sendqueue, 'send')));

				$this->ParseTemplate('Send_Step4');
			break;

			case 'step3':
				$this->Step3();
			break;

			case 'step2':
				$filteringOption = 0;
				$lists = array();
				$segments = array();

				if (isset($_POST['ShowFilteringOptions'])) {
					$filteringOption = intval($_POST['ShowFilteringOptions']);
					if ($filteringOption != 0) {
						$user->SetSettings('ShowFilteringOptions', $filteringOption);
					}
				}

				if ($filteringOption == 3 && !$user->HasAccess('Segments', 'Send')) {
					$filteringOption = 1;
				}

				switch ($filteringOption) {
					// This is when a list is selected
					case 1:
					case 2:
						if (isset($_POST['lists'])) {
							$lists = $_POST['lists'];
						}
					break;

					// This is when a segment is selected
					case 3:
						if (isset($_POST['segments']) && is_array($_POST['segments'])) {
							$segments = $_POST['segments'];
						}
					break;

					// A list/segment can be selected using "GET" request
					default:
						if (isset($_GET['list'])) {
							$lists = array((int)$_GET['list']);
							$filteringOption = 1;
							$user->SetSettings('ShowFilteringOptions', 1);
						} elseif (isset($_GET['segment'])) {
							$segments = array(intval($_GET['segment']));
							$filteringOption = 3;
							$user->SetSettings('ShowFilteringOptions', 3);
						}
					break;

				}

				if ($filteringOption == 1 || $filteringOption == 2) {
					if (empty($lists)) {
						$GLOBALS['Error'] = GetLang('Send_Step1_ChooseListToSendTo');
						$GLOBALS['Message'] = $this->ParseTemplate('ErrorMsg', true, false);
						$this->ChooseList('Send', 'step2', false);
						break;
					}

					if (!$user->Admin()) {
						$availabeLists = $user->GetLists();

						if (is_array($availabeLists)) {
							$availabeLists = array_keys($availabeLists);
						} else {
							$this->ChooseList('Send', 'step2', false);
							break;
						}

						$intersects = array_intersect($lists, $availabeLists);
						if (count($lists) != count($intersects)) {
							$this->ChooseList('Send', 'step2', false);
							break;
						}
					}
				}

				if ($filteringOption == 1) {
					$this->FilterRecipients($lists);
				} elseif ($filteringOption == 2) {
					$send_details = IEM::sessionGet('SendDetails');

					$send_details['Lists'] = $lists;
					$send_details['SendCriteria'] = array('Confirmed' => 1);
					$send_details['SendSize'] = null;
					$send_details['BackStep'] = 1;

					IEM::sessionSet('SendDetails', $send_details);

					$this->Step3();
				} else {
					if (empty($segments)) {
						$GLOBALS['Error'] = GetLang('Send_Step1_ChooseSegmentToSendTo');
						$GLOBALS['Message'] = $this->ParseTemplate('ErrorMsg', true, false);
						$this->ChooseList('Send', 'step2', false);
						break;
					}

					if (!$user->Admin()) {
						$availableSegments = $user->GetSegmentList();

						if (!empty($availableSegments)) {
							$availableSegments = array_keys($availableSegments);
						}

						foreach ($segments as $segment) {
							if (!in_array($segment, $availableSegments)) {
								$this->DenyAccess();
								exit();
							}
						}
					}

					$send_details = IEM::sessionGet('SendDetails');

					$send_details['Lists'] = null;
					$send_details['SendCriteria'] = array();
					$send_details['SendSize'] = null;
					$send_details['Segments'] = $segments;

					IEM::sessionSet('SendDetails', $send_details);

					$this->Step3();
				}
			break;

			case 'resumesend':
				$this->ResumeSend();
			break;

			case 'resend':
				$this->ResendJob();
			break;

			default:
				IEM::sessionRemove('SendDetails');

				$id = (isset($_GET['id'])) ? (int)$_GET['id'] : 0;
				if (!$this->CanAccessNewsletter($id)) {
					$id = 0;
				}

				$senddetails['NewsletterChosen'] = $id;

				IEM::sessionSet('SendDetails', $senddetails);

				$newsletterapi = $this->GetApi('Newsletters');

				$newsletterowner = ($user->Admin() ? 0 : $user->userid);

				$newsletters = $newsletterapi->GetLiveNewsletters($newsletterowner);
				if (empty($newsletters)) {
					$all_newsletters = $newsletterapi->GetNewsletters($newsletterowner, array(), true);
					if ($all_newsletters < 1) {
						if ($user->HasAccess('Newsletters', 'Create')) {
							$GLOBALS['Message'] = $this->PrintSuccess('NoNewsletters', GetLang('NoNewsletters_HasAccess'));

							$GLOBALS['Newsletters_AddButton'] = $this->ParseTemplate('Newsletter_Create_Button', true, false);

						} else {
							$GLOBALS['Message'] = $this->PrintSuccess('NoNewsletters', '');
						}
					} else {
						if ($user->HasAccess('Newsletters', 'Approve')) {
							$GLOBALS['Message'] = $this->PrintSuccess('NoLiveNewsletters', GetLang('NoLiveNewsletters_HasAccess'));
						} else {
							$GLOBALS['Message'] = $this->PrintSuccess('NoLiveNewsletters', '');
						}
					}
					$this->ParseTemplate('Newsletters_Send_Empty');
					break;
				}
				$this->ChooseList('Send', 'step2', false);
			break;
		}
		$this->PrintFooter($popup);
	}