예제 #1
0
파일: cron.php 프로젝트: hungnv0789/vhtm
 /**
  * _ProcessJob
  * This method does the "setup work" for a split test campaign.
  *
  * If a job is passed in that hasn't been started before, it will set everything up:
  * - create a "queue" of recipients
  * - clean the queue (remove banned/duplicate recipients etc)
  * - set up stats for each newsletter in the split test campaign
  * - save stats for the user sending the campaign to take off credits etc
  *
  * If a job is passed in that has been set up before, it just loads the data up.
  *
  * Once it has done either of those, it gives the details to the Splittest_Send_API class
  * and then calls _ActionJob.
  * Based on what that returns, it will either mark the job as complete or not.
  *
  * If the job is a percentage split test send (send to first X % of a list/segment), then
  * it sets the appropriate flags etc to make sure we only send to that first X%.
  * If the job hasn't been set up before, it works out the limit and sets the details in the jobdetails
  * which are then saved in the database in case the job dies or is paused etc.
  *
  * If the job is a percentage split test send and it's time to send to the rest of the list/segment,
  * then it works out the "best" one to send and sets the appropriate variables for that to happen.
  *
  * @param Int $jobid The specific job id we're going to process.
  *
  * @uses _jobid
  * @uses StartJob
  * @uses PauseJob
  * @uses LoadJob
  * @uses GetUser
  * @uses GetJobQueue
  * @uses CreateQueue
  * @uses JobQueue
  * @uses GetSubscribersFromSegment
  * @uses GetSubscribers
  * @uses RemoveDuplicatesInQueue
  * @uses RemoveBannedEmails
  * @uses RemoveUnsubscribedEmails
  * @uses QueueSize
  * @uses _CalculateBestNewsletter
  * @uses _FinishJob
  * @uses _ActionJob
  * @uses _CalculateBestNewsletter
  *
  * @return Boolean Returns whether the job was processed or not. If a job could not be processed, it returns false. Otherwise it returns true.
  */
 private function _ProcessJob($jobid = 0)
 {
     if ($jobid <= 0) {
         return false;
     }
     $this->_jobid = $jobid;
     /**
      * Load the job, then start it.
      * We need to do this so when we call "StartJob" we can give it the splitid to "start" as well.
      */
     $jobinfo = $this->LoadJob($jobid);
     $jobdetails = $jobinfo['jobdetails'];
     /**
      * Need to load the split campaign
      * before starting the job
      * so if we're in "t"imeout mode,
      * we can look at the stats
      * We also need the weighting's from the split campaign
      * to work it out.
      */
     $this->splitcampaign_details = $this->_splittest_api->Load($jobdetails['splitid']);
     /**
      * If it's a "t"imeout, work out the best stat.
      */
     if ($jobinfo['jobstatus'] == 't') {
         $jobdetails['newsletters'] = $this->_CalculateBestNewsletter($jobdetails['Stats']);
         /**
          * Also need to kill off the "percentage_send_maximum" element
          * as this would cause the job to go into "timeout" mode again.
          */
         unset($jobdetails['percentage_send_maximum']);
     }
     if (!$this->StartJob($jobid, $jobdetails['splitid'])) {
         $this->PauseJob($jobid);
         return false;
     }
     // ----- "Login" to the system as the job's owner.
     $user = GetUser($jobinfo['ownerid']);
     IEM::userLogin($jobinfo['ownerid'], false);
     // -----
     $queueid = false;
     // if there's no queue, start one up.
     if (!($queueid = $this->GetJobQueue($jobid))) {
         /**
          * Randomize the newsletters
          * It's probably already been done but can't hurt to do it again.
          */
         shuffle($jobdetails['newsletters']);
         $sendqueue = $this->CreateQueue('splittest');
         $queueok = $this->JobQueue($jobid, $sendqueue);
         $send_criteria = $jobdetails['SendCriteria'];
         $queueinfo = array('queueid' => $sendqueue, 'queuetype' => 'splittest', 'ownerid' => $jobinfo['ownerid']);
         if (isset($jobdetails['Segments']) && is_array($jobdetails['Segments'])) {
             $this->_subscribers_api->GetSubscribersFromSegment($jobdetails['Segments'], false, $queueinfo, 'nosort');
         } else {
             $this->_subscribers_api->GetSubscribers($send_criteria, array(), false, $queueinfo, $sendqueue);
         }
         if (SENDSTUDIO_DATABASE_TYPE == 'pgsql') {
             $this->Db->OptimizeTable(SENDSTUDIO_TABLEPREFIX . "queues");
         }
         $this->_subscribers_api->RemoveDuplicatesInQueue($sendqueue, 'splittest', $jobdetails['Lists']);
         $this->_subscribers_api->RemoveBannedEmails($jobdetails['Lists'], $sendqueue, 'splittest');
         $this->_subscribers_api->RemoveUnsubscribedEmails($jobdetails['Lists'], $sendqueue, 'splittest');
         if (SENDSTUDIO_DATABASE_TYPE == 'pgsql') {
             $this->Db->OptimizeTable(SENDSTUDIO_TABLEPREFIX . "queues");
         }
         $jobdetails['SendSize'] = $this->_subscribers_api->QueueSize($sendqueue, 'splittest');
         $jobdetails['Stats'] = array();
         $jobdetails['SendQueue'] = $sendqueue;
         /**
          * Delete the old user stats allocations.
          * They were all allocated under one stat/job before so the user recorded their send info
          * so they couldn't set up split test sends and go over their send quota.
          *
          * Now, we need to re-allocate them per newsletter being sent.
          */
         $this->_stats_api->DeleteUserStats($jobinfo['ownerid'], $this->_jobid);
         $statids = array();
         foreach ($jobdetails['newsletters'] as $newsletterid) {
             $newsletterstats = $jobdetails;
             $newsletterstats['Job'] = $jobid;
             $newsletterstats['Queue'] = $sendqueue;
             $newsletterstats['SentBy'] = $queueinfo['ownerid'];
             $newsletterstats['SendType'] = 'splittest';
             $newsletterstats['Newsletter'] = $newsletterid;
             $newsletterstats['Lists'] = $jobdetails['sendingto']['Lists'];
             $newsletterstats['SendCriteria'] = $jobdetails['SendCriteria'];
             $statid = $this->_stats_api->SaveNewsletterStats($newsletterstats);
             $statids[] = $statid;
             $jobdetails['Stats'][$newsletterid] = $statid;
             $this->_stats_api->RecordUserStats($jobinfo['ownerid'], $this->_jobid, $jobdetails['SendSize'], $jobdetails['SendStartTime'], $statid);
         }
         $this->SaveSplitStats($jobdetails['splitid'], $this->_jobid, $statids);
         /**
          * If it's a percentage send,
          * work out the number of emails to send for the first percentage
          * It gets stored in the jobdetails array so it can be saved in the database.
          */
         if ($this->splitcampaign_details['splittype'] == 'percentage') {
             $max_to_email = ceil($this->splitcampaign_details['splitdetails']['percentage'] / 100 * $jobdetails['SendSize']);
             $jobdetails['percentage_send_maximum'] = $max_to_email;
         }
         /**
          * Save the job stat details.
          * Otherwise we could potentially end up with a 'start'ed queue but no stats.
          */
         $this->Set('jobdetails', $jobdetails);
         $this->UpdateJobDetails();
         /**
          * This is to process the 'queueid' later in the code.
          */
         $queueid = $sendqueue;
         // This will make sure that the credit warning emails are also being send out from splittest
         API_USERS::creditEvaluateWarnings($user->GetNewAPI());
     }
     $this->Db->OptimizeTable(SENDSTUDIO_TABLEPREFIX . "queues");
     $queuesize = $this->_subscribers_api->QueueSize($queueid, 'splittest');
     $this->_queueid = $queueid;
     /**
      * If there is a "percentage_send_maximum" variable in the jobdetails array,
      * we are sending to the first part of a 'percentage' split test.
      *
      * We have to send to the rest of the percentage maximum before we pause the job,
      * work out the "best" performing campaign and send to that.
      */
     if (isset($jobdetails['percentage_send_maximum'])) {
         $this->_percentage_send_maximum = (int) $jobdetails['percentage_send_maximum'];
     }
     /**
      * If the _percentage_send_maximum is 0, then "timeout" the job.
      * We must have hit "pause" right at the end of the initial send process or something.
      */
     if ($this->_percentage_send_maximum !== null && $this->_percentage_send_maximum <= 0) {
         $this->TimeoutJob($jobid, $this->splitcampaign_details['splitid'], $this->splitcampaign_details['splitdetails']['hoursafter']);
         IEM::userLogout();
         return true;
     }
     $this->Set('statids', $jobdetails['Stats']);
     $this->Set('jobdetails', $jobdetails);
     $this->Set('jobowner', $jobinfo['ownerid']);
     /**
      * There's nothing left? Just mark it as done.
      */
     if ($queuesize == 0) {
         $this->_FinishJob();
         IEM::userLogout();
         return true;
     }
     $finished = $this->_ActionJob($jobid, $queueid);
     if ($finished) {
         $this->_FinishJob();
     }
     IEM::userLogout();
     return true;
 }
예제 #2
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;
    }
예제 #3
0
파일: send.php 프로젝트: hungnv0789/vhtm
	/**
	* 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);
	}