<?php

class ASPMailLogic extends SOY2LogicBase{
	
	var $mail_from = "soycms_admin@soycms.net";
	
	var $mails = array(
    	"password" => array(
    		"title" => "【SOY CMS beta】パスワードのご案内"
    	),
    	"register" => array(
    		"title" => "【SOY CMS beta】 登録完了のご案内"
    	),
    	"activation" => array(
    		"title" => "【SOY CMS beta】 登録確認のご案内"
    	)
    );
    
    /**
     * 登録確認メールの送信
     */
    function sendActivationMail(ASPUser $user,CertificationQueue $queue){
    	list($title,$body) = $this->getMail("activation");
    	
    	$body = $this->replace("terms_url",$this->getTermUrl(),$body);	
    	$body = $this->replace("name",$user->getLastName()." ".$user->getFirstName(),$body);
    	$body = $this->replace("activation_url",
    			SOY2PageController::createLink("RegistCode",true).
				"?email=".rawurlencode($user->getEmail()).
				"&register_code=".rawurlencode($queue->getRegisterCode()),
				$body);
		$body = $this->replace("mail",$user->getEmail(),$body);
		$body = $this->replace("register_code",$queue->getRegisterCode(),$body);
    	
    	$this->send($this->mail_from,$user->getEmail(),$title,$body);
    }
    
    /**
     * パスワード確認メールの送信
     */
    function sendPasswordMail(ASPUser $user,$newPassword){
		list($title,$body) = $this->getMail("password");
    	
    	$body = $this->replace("name",$user->getLastName()." ".$user->getFirstName(),$body);
    	$body = $this->replace("password",$newPassword,$body);
    			
    	$this->send($this->mail_from,$user->getEmail(),$title,$body);	
    }
    
    /**
     * 登録完了メールの送信
     */
    function sendRegisterMail(ASPUser $user,$siteUrl){
		list($title,$body) = $this->getMail("register");
    	
    	$body = $this->replace("terms_url",$this->getTermUrl(),$body);	
    	$body = $this->replace("name",$user->getLastName()." ".$user->getFirstName(),$body);
    	$body = $this->replace("site_url",$siteUrl,$body);
    	
    	$this->send($this->mail_from,$user->getEmail(),$title,$body);
    }
    
    /**
     * メール本文を取得
     * @return array(title,body)
     */
    function getMail($key){
    	$this->mails[$key]["body"] = file_get_contents(dirname(__FILE__)."/mail/mail_".$key.".txt");
    	return array($this->mails[$key]["title"],$this->mails[$key]["body"]);
    }
    
    /**
     * 規約のURL
     */
    function getTermUrl(){
    	return "http://soycms.net/product/license/";
    }
    
    /**
     * メール本文の置換
     */
    function replace($key,$replace,$mail){
    	return str_replace('$$'.strtoupper($key).'$$',$replace,$mail);
    }
    
    /**
     * メールを送信する
     */
    function send($from,$to,$title,$body){
    	MailUtil::encoding("ISO-2022-JP");
		MailUtil::send($from,$to,$title,$body,array("Date"=>date("r")));
    }
}

class MailUtil{
	
	var $SERVER_NAME = "s318.xrea.com";
	var $USER_NAME = "soycms_admin@soycms.net";
	var $USER_PASSWORD = "WXitunILXUbn";
	
	private $popConnect = null;
	private $smtpConnect = null;
	private $counter = 0;
	
	var $connected = false;
	var $encoding = 'utf-8';
	var $_encoding = 'utf-8';
	var $header = array();
	
	private function MailUtil(){}
	
	private function &getInstance() {
		static $singleton_ ;
		if( !$singleton_ )
			$singleton_ = new MailUtil() ;
		return $singleton_ ;
	}
	
	function __destruct(){
		$this->disconnect();
	}
	
	public static function encoding($bodyEncoding){
		
		$sender = MailUtil::getInstance();
		$sender->encoding = $bodyEncoding;
		$sender->_encoding = $bodyEncoding;
	}
	
	public static function switchMailServer($server){
		$sender = MailUtil::getInstance();
		$sender->SERVER_NAME = $server;
	}
	
    public static function send($from,$sendTo,$title,$body,$header = array()){ 	
    	
    	$sender = MailUtil::getInstance();
    	
    	//カンマ、セミコロンでの区切り
    	$sendTo = str_replace(array("\r","\n"), "", $sendTo);//改行削除
    	$sendTo = str_replace(";", ",", $sendTo);
    	$array = split(",",$sendTo);
    	$array = array_diff($array, array(''));	//空を削除
    	$array = array_unique($array);				//重複を削除
		
		$sender->header = $header;
		
    	foreach($array as $sendMailAddress){
    		
    		if(!MailUtil::checkEmailValidity($sendMailAddress)){
    			continue;
    		}
	    	
	    	for($i=0; $i<3; $i++){
	    	
		    	try{
	    			$sender->sendMail($from,$sendMailAddress,$title,$body);
	    			break;
		    	}catch(Exception $e){
		    		if($i==2){
		    			throw $e; 
		    		}
		    	}	    		
	    	}    		
    	}    
    }
    
    function sendMail($from,$sendTo,$title,$body){
    	
    	if($this->connected == false){
    		$this->auth();
    		   		
    		$this->connect();
    		$this->connected = true;
    		$this->counter = 0;
    		
    	}
		
		$this->chengeEncoding($sendTo);
    	
		// .だけの行は..に置換、改行コードをCRLFに統一（一度LFに統一しているのは正規表現で修飾子mを使うため）
		$body = str_replace(array("\r\n", "\r"), "\n", $body);  // CRLF, CR -> LF
		$body = preg_replace('/^\\.$/m','..', $body);          // .        -> ..
		$body = str_replace("\n", "\r\n", $body);                // LF       -> CRLF

    	$title = str_replace(array("\r","\n"), "", $title);//改行削除
    	$title = $this->convertTitle($title);
    	
    	$this->smtpCommand("MAIL FROM:<$from>");
		
		while(true){
			$str = $this->getSmtpResponse();
			if(preg_match("/Ok/i",$str)){
				break;
			}
			if(substr($str,0,3)!="250"){
				throw new Exception("Failed: MAIL FROM");
			}
			
		}
		
		$this->smtpCommand("RCPT TO:<$sendTo>");
		
		while(true){
			$str = $this->getSmtpResponse();
			if(preg_match("/Ok/i",$str)){
				break;
			}
			
			if(substr($str,0,3)!="250"){
				throw new Exception("Failed: RCPT TO".$str);
			}
			
		}
				
		$this->smtpCommand("DATA");
		
		while(true){
			$str = $this->getSmtpResponse();
			
			if(preg_match("/354/i",$str)){
				break;
			}
			
			if(substr($str,0,3)!="250"){
				throw new Exception("Failed: MAIL FROM");
			}
			
		}
		
		if(!in_array("Subject",$this->header))$this->data("Subject: ".$title);
		if(!in_array("From",$this->header))$this->data("From: $from");
		if(!in_array("To",$this->header))$this->data("To: $sendTo");
		if(!in_array("Content-Type",$this->header))$this->data("Content-Type: text/plain; charset=\"".$this->encoding."\"");
		
		foreach($this->header as $key => $value){
			$this->data($key.": ".$value);
		}
		
		$this->data("");
		$this->data("$body");
		
		$this->smtpCommand(".");
			
		$this->counter++;
    	
    	if($this->counter >= 100){
    		$this->disconnect();
    		$this->connected = false;
    	}
    	
    }
 	
 	//携帯のメールアドレスのみ強制的にJISにする   
    function chengeEncoding($sendTo){
    	
    	if(preg_match('/@docomo\.ne\.jp$/',$sendTo)){
    		$this->encoding = 'ISO-2022-JP';
    		return;
    	}
    	
    	if(preg_match('/@ezweb\.ne\.jp$/',$sendTo)){
    		$this->encoding = 'ISO-2022-JP';
    		return;
    	}
    	
    	if(preg_match('/@softbank\.ne\.jp$/',$sendTo)){
    		$this->encoding = 'ISO-2022-JP';
    		return;
    	}
    	
    	if(preg_match('/@[a-z]\.vodafone\.ne\.jp$/',$sendTo)){
    		$this->encoding = 'ISO-2022-JP';
    		return;
    	}
    	
    	if(preg_match('/@[a-z]*\.?pdx\.ne\.jp$/',$sendTo)){
    		$this->encoding = 'ISO-2022-JP';
    		return;
    	}
    	
    	if(preg_match('/@pdx\.ne\.jp$/',$sendTo)){
    		$this->encoding = 'ISO-2022-JP';
    		return;
    	}
    	
    	if(preg_match('/@hotmail\.co\.jp$/',$sendTo)){
    		$this->encoding = 'ISO-2022-JP';
    		return;
    	}
    	
    	if(preg_match('/@hotmail\.com$/',$sendTo)){
    		$this->encoding = 'ISO-2022-JP';
    		return;
    	}
    	
    	$this->encoding = $this->_encoding;
    	return;    	
    }
    
    function connect(){
    	
    	$this->smtpConnect = fsockopen($this->SERVER_NAME, 25, $errno, $errstr);
				
		if(!$this->smtpConnect){
			$this->disconnect();
			throw new Exception("faild to connet");
		}

		//hello
		$this->smtpCommand("EHLO ".$this->SERVER_NAME);
		$buff = $this->getSmtpResponse();
		
		if(substr($buff,0,3) != "220"){
			throw new Exception("Failed:EHLO");
		}
	}
	
	function auth(){
		
		$this->popConnect = fsockopen($this->SERVER_NAME, 110, $errno, $errstr);

		if(!$this->popConnect){
			$this->disconnect();
			throw new Exception("faild to connet");
		}
		
		$buf = $this->popCommand("USER ".$this->USER_NAME);
		$buf = $this->popCommand("PASS ".$this->USER_PASSWORD);
		
	}
	
	function disconnect(){
		
		if($this->popConnect){
			$this->popCommand("QUIT");
			fclose($this->popConnect);
		}
		if($this->smtpConnect && $this->smtpCommand("QUIT")){
			fclose($this->smtpConnect);
		}
		
		$this->smtpConnect = null;
		$this->popConnect = null;
		$this->connected = false;
	}
    
    function popCommand($string){
    	
    	fputs($this->popConnect, $string."\r\n");
  		$buf = fgets($this->popConnect, 512);
  		
  		if(substr($buf, 0, 3) == '+OK') {
    		return $buf;
  		} else {
    		return false;
  		}
    }
    
    function smtpCommand($string){
 		
 		if(!$this->smtpConnect){
			throw new Exception('SMTP is null');
 			return;
 		}
 		
 		$result = fputs($this->smtpConnect, $string."\r\n");
 		
 		if($result == false){
 			throw new Exception('MailUtil->data. Result is false.');
 		}
 		
    }
    
    function getSmtpResponse(){
    	$buff = fgets($this->smtpConnect);
    	
 		return $buff;
    }
    
    function data($data){
    	if($this->encoding == "ISO-2022-JP"){
    		$encoding = "JIS";
    	}else{
    		$encoding = $this->encoding;
    	}
    	
    	$data = mb_convert_encoding($data,$encoding,"UTF-8");
    	$result = fputs($this->smtpConnect, $data."\r\n");
    	if($result == false){
			throw new Exception('MailUtil->data. Result is false.');
    	}
    }
    
    function convertTitle($title){
    	
    	if($this->encoding == "ISO-2022-JP"){
    		$encoding = "JIS";
    	}else{
    		$encoding = $this->encoding;
    	}
    	
		if(strlen($title)){
			return mb_encode_mimeheader($title,$encoding);
		}else{
			return $title;
		}
    }
    
    static function checkEmailValidity($email){
    	$ascii  = '[a-zA-Z0-9!#$%&\'*+\-\/=?^_`{|}~.]';//'[\x01-\x7F]';
    	$domain = '(?:[-a-z0-9]+\.)+[a-z]{2,10}';//'([-a-z0-9]+\.)*[a-z]+';
		$d3     = '\d{1,3}';
		$ip     = $d3.'\.'.$d3.'\.'.$d3.'\.'.$d3;
    	$validEmail = "^$ascii+\@(?:$domain|\\[$ip\\])$";
    	
    	return ( preg_match('/'.$validEmail.'/i', $email) ) ? true : false ;
    }

}
?>