<?php

include_once 'class.phpmailer.php';
include_once 'class.smtp.php';

include_once '../config.php';
include_once '../settings.php';
include_once '../utils.php';

class MailController {
    protected $default_params = array(
          'debug_level' => 1,
          'attachments' => array(),
      );

    function __construct() {
        //SMTP needs accurate times, and the PHP time zone MUST be set
        //This should be done in your php.ini, but this is how to do it if you don't have access to that
        date_default_timezone_set('Etc/UTC');
    }
    
    function isLocalRequest() {
        return $_SERVER['SERVER_ADDR'] == $_SERVER['REMOTE_ADDR']; 
    }
    
    public function run() {
        $method = $_SERVER['REQUEST_METHOD'];
        if ($method == "GET"){
          $this->doGet();
        } else if ($method == "POST") {
          $this->doPost();
        } else {
            error_log("request method '" . $method . "' is not supported");
        }
    }
    
    protected function doGet() {
    }
    
    // Example parameters: 
    // $params = array(
    //   'smtp_server' => 'smtp.qq.com',         //14.18.245.164
    //   'smtp_secure' => 'tls',                 //optional
    //   'smtp_port' => 465,                     //optional
    //   'smtp_user' => 'ivincentwang@qq.com',
    //   'smtp_pass' => "XXXXXXXXX",
    //   'from_addr' => 'ivincentwang@qq.com',
    //   'from_name' => 'Vincent Wang',
    //   'cc_addr' => 'vincent@easyio.com',      //optional
    //   'cc_name' => 'Vincent Wang',            //optional
    //   'to_addr' => 'linsong.qizi@gmail.com',
    //   'to_name' => 'Linsong Qizi',
    //   'subject' => 'PHPMailer GMail SMTP test',
    //   'content' => "hello test",
    //   'attachments' => array('composer.json', 'class.smtp.php') // optional
    // );
    // NOTE: if manul test in browser, need to comment out the local request
    // check below, otherwise, you will always be redirected
    protected function doPost() {
        if (!$this->isLocalRequest())
        {
            $url = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
            header('Location: ' . $url, 302)
            die();
        }

        $params = array_merge($this->default_params, $_POST);

        //validate input
        $required_keys = array('smtp_server', 'from_addr', 'to_addr', 'subject');
        foreach($required_keys as $key) {
          if (empty($params[$key])) {
            die("ERROR : missing parameter '" . $key . "'");
          }
        }
        
        if (!empty($params['attachments'])) {
          $attachments = explode(',', $params['attachments']);
          $params['attachments'] = $attachments;
        }

        $to_addrs = explode(',', $params['to_addr']);
        $params['to_addr'] = $to_addrs;

        if (!empty($params['to_name']))
        {
          $to_names = explode(',', $params['to_name']);
          $params['to_name'] = $to_names;
        }
        
        if (!empty($params['cc_addr']))
        {
          $cc_addrs = explode(',', $params['cc_addr']);
          $params['cc_addr'] = $cc_addrs;
        }
        
        if (!empty($params['cc_name']))
        {
          $cc_names = explode(',', $params['cc_name']);
          $params['cc_name'] = $cc_names;
        }
          
        $this->sendMail($params);
        exit();
    }
    
    protected function setupTlsTunnel($mail) {
      $conf = new INIFile;
      if ($conf->load("/mnt/tls_tunnel/tls_tunnel.conf")) {
        $conf->setValue(NULL, 'remote_host', $mail->Host);
        $conf->setValue(NULL, 'remote_port', $mail->Port);
        $mail->Host = $conf->value(NULL, 'local_host', '127.0.0.1');
        $mail->Port = intval($conf->value(NULL, 'local_port', '3333'));
        $conf->save();

        $pid = rtrim(file_get_contents("/var/run/tls_tunnel.pid"));
        execCmd('kill -HUP ' . $pid)
      }
    }

    protected function sendMail($params) {
        //Create a new PHPMailer instance
        $mail = new PHPMailer;

        //Tell PHPMailer to use SMTP
        $mail->isSMTP();

        //Enable SMTP debugging
        // 0 = off (for production use)
        // 1 = client messages
        // 2 = client and server messages
        $mail->SMTPDebug = $params['debug_level'];

        //Enable auto TLS or not, by default disable it
        if (!empty($params['auto_tls']))
          $mail->SMTPAutoTLS = ($params['auto_tls'] == 'true' || $params['auto_tls'] == '1');
        else
          $mail->SMTPAutoTLS = false;

        //Ask for HTML-friendly debug output
        $mail->Debugoutput = 'html';

        //Set the hostname of the mail server
        $mail->Host = $params['smtp_server'];
        // use
        // $mail->Host = gethostbyname('smtp.gmail.com');
        // if your network does not support SMTP over IPv6

        //Set the SMTP port number - 587 for authenticated TLS, a.k.a. RFC4409 SMTP submission
        if (!empty($params['smtp_port']))
          $mail->Port = $params['smtp_port'];

        //Set the encryption system to use - ssl (deprecated) or tls
        if (!empty($params['smtp_secure']))
        {
          $this->setupTlsTunnel($mail);
          // never set SMTPSecure 
          // $mail->SMTPSecure = $params['smtp_secure'];
        }

        //Whether to use SMTP authentication
        $mail->SMTPAuth = !empty($params['smtp_user']) && !empty($params['smtp_pass']);

        //Username to use for SMTP authentication - use full email address for gmail
        $mail->Username = $params['smtp_user'];

        //Password to use for SMTP authentication
        $mail->Password = $params['smtp_pass'];

        //Set who the message is to be sent from
        $mail->setFrom($params['from_addr'], $params['from_name']);

        //Set cc data
        if (!empty($params['cc_addr'])) {
          foreach($params['cc_addr'] as $index => $addr)
            $mail->addCC($addr, arrayGet($params['cc_name'], $index, ''));
        }

        //Set an alternative reply-to address
        $mail->addReplyTo($params['from_addr'], $params['from_name']);

        //Set who the message is to be sent to
        foreach($params['to_addr'] as $index => $addr) {
          $mail->addAddress($addr, arrayGet($params['to_name'], $index, ''));
        }

        //Set the subject line
        $mail->Subject = $params['subject'];

        //Read an HTML message body from an external file, convert referenced images to embedded,
        //convert HTML into a basic plain-text alternative body
        //$mail->sgHTML(file_get_contents('contents.html'), dirname(__FILE__));
        $mail->sgHTML($params['content']);
        $mail->Body = preg_replace('/\r\n/', '<br>', $mail->Body);

        //Add Attachments
        foreach($params['attachments'] as $path) {
          $path = trim($path, "\r\n\t ");
          //check if the path is relative path
          if (!startsWith($path, '/')) {
            $rootPath = $_SERVER['DOCUMENT_ROOT'];
            $path = build_file_path($rootPath, $path);
          }
          if (!file_exists($path)) {
            echo 'file "' . $path . '" does not exist, skip it ' . "\n";
            continue;
          }
          $mail->addAttachment($path);
        }

        //send the message, check for errors
        if (!$mail->send()) {
            echo "ERROR : " . $mail->ErrorInfo;
            http_response_code(503);
        } else {
            echo "SUCCESS";
        }
    }
}

$controller = new MailController();
$controller->run();

?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <eta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title><?php echo Config::$webPageTitle ?> Mail </title>

    <link rel="stylesheet" href="../../css/bootstrap.min.css" media="screen" />
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="page-header"><h1>Mail SMTP Server Settings</h1></div>

        <div class="alert alert-info">
          <p>To send email by mail_controller, you need to send it a POST request from the <strong>*SAME*</strong> host.</p>
        </div>

        <h3>Gmail SMTP Setting:</h3>
        <dl class='dl-horizontal'>
          <dt>SMTP Server: </dt>
          <dd>smtp.gmail.com</dd>
          <dt>SMTP Port:</dt>
          <dd><strong>5</strong> (for secure, recommended)</dd>
          <dd> (for nonsecure)</dd>
        </dl>
        <div class="alert alert-info">
          <h4>NOTE</h4>
          If you can not send email successfully by Gmail SMTP server, there are two things you need to check: 
          <ul>
            <li>Make sure the option 'Access for less secure apps' has been turned on. <strong><a href="https://support.google.com/accounts/answer/6010255?hl=en">Here</a></strong> is how to change it.</li>
            <li>If you enabled 2-Step-Verification, then you will need to generate an App password and use it instead of your password. <strong><a href="https://support.google.com/accounts/answer/185833">Here</a></strong> is how to do it.</li>
          </ul>
        </div>


        <h3>Yahoo! Mail SMTP Setting:</h3>
        <dl class='dl-horizontal'>
          <dt>SMTP Server: </dt>
          <dd>smtp.mail.yahoo.com</dd>
          <dt>SMTP Port:</dt>
          <dd><strong>5</strong> (for secure, recommended)</dd>
          <dd> (for nonsecure)</dd>
        </dl>
        <div class="alert alert-info">
          <h4>NOTE</h4>
          If you can not send email successfully by Yahoo! mail SMTP server, there are two things you need to check: 
          <ul>
            <li>If you don't enable 2-Step-Verification, then make sure the option 'Allow apps that use less secure sign in' has been turned on. <strong><a href="https://help.yahoo.com/kb/account/SLN27791.html">Here</a> </strong> is how to do it.</li>
            <li>If you enabled 2-Step-Verification, then you will need to generate an App password and use it as 'smtp_pass' instead of your password. <strong><a href="https://help.yahoo.com/kb/SLN15241.html">Here</a></strong> is how to do it.</li>
          </ul>
        </div>
      </div>
    </div>
  </body>
</html>