<?php
// *************************************************************
// *
// * Copyright (c) 2021 ysrock Co., Ltd.	<info@ysrock.co.jp>
// * Copyright (c) 2021 Yasuo Sugano		<sugano@ysrock.co.jp>
// *
// * Version	: 1.0.6
// * Update	: 2021.12.03
// *
// *	dieの時、ファイル名も返す
// *
// *************************************************************
// *
// * NEED CLASS
// *
// * character_1.0.2.php
// *
// *************************************************************
// *
// * USING
// *
// * mb_language()
// * mb_internal_encoding()
// * mb_send_mail()
// *
// *************************************************************
// *
// * INTERFACE
// *
// * $hoge = new YsMail();
// *
// * bool $hoge->Send(array(
// *   'from'       => string $from
// *  ,'to'         => string $to
// * [,'cc'         => string $cc ]
// * [,'bcc'        => string $bcc ]
// * [,'subject'    => string $subject ]
// * [,'text'       => string $text ]
// * [,'html'       => string $html ]
// * [,'file'       => array  $file ]
// * [,'return-path'=> string $return  = $from ]
// * [,'charset'    => string $charset = 'JIS' ]
// * ]);
// *
// *************************************************************
// *
// * HISTORY
// *
// * Version		: 1.0.5
// * Last Modified	: 2017.05.17
// *
// * bag fix.
// *
// *************************************************************
// *
// * Version		: 1.0.4
// * Last Modified	: 2017.02.22
// *
// * PHP 5.2に対応
// * 添付ファイルをパスにも対応
// *
// *************************************************************
// *
// * Version		: 1.0.3
// * Last Modified	: 2016.04.01
// *
// * bug fix. cidの修正
// *
// *************************************************************
// *
// * Version		: 1.0.2
// * Last Modified	: 2016.03.23
// *
// * bug fix. コンマで複数の送信先に対応
// *
// *************************************************************
// *
// * Version		: 1.0.1
// * Last Modified	: 2016.03.22
// *
// * Cc,Bccに対応
// *
// *************************************************************
// *
// * Version		: 1.0.0
// * Last Modified	: 2015.12.22
// *
// *************************************************************

if(is_file('character.1.0.3.php')) require_once "character.1.0.3.php";

class YsMail{
  public $YC;
  public $now;
  public $inline;

  public function __construct(){
    $this->YC     = new YsChar();
    $this->now    = date('ymd.His');
    $this->inline = array();
  }

  /*------------------------------
    メールを送信
  ------------------------------*/
  public function Send($input){
    if(!isset($input['from'])) die(var_dump([__FILE__, __LINE__, "args['from'] is not exists" ]));
    if(!isset($input['to'  ])) die(var_dump([__FILE__, __LINE__, "args['to'] is not exists" ]));

    $send = array();

    /*--- 文字コード ---*/
    $send['charset'] = (isset($input['charset']) && $input['charset']) ? $input['charset'] : "JIS";
    /*--- 文字コードの整理 ---*/
    if(    preg_match("/^utf-?8$/i"     , $send['charset'])) $send['charset']='UTF-8';
    elseif(preg_match("/^euc/i"         , $send['charset'])) $send['charset']='EUC-JP';
    elseif(preg_match("/^s.*jis$/i"     , $send['charset'])) $send['charset']='SJIS';
    elseif(preg_match("/^jis$/i"        , $send['charset'])
        || preg_match("/^iso-2022-jp$/i", $send['charset'])) $send['charset']='JIS';

    /*--- 設定 ---*/
    mb_language('Ja');
    mb_internal_encoding($send['charset']);

    /*--- return-path ---*/
    $send['return-path'] = (isset($input['return-path']) && $input['return-path']) ? $input['return-path'] : "";
    if(!$send['return-path']){
      if(preg_match("/\x3c([^\x3e]+)\x3e/", $input['from'], $matches)) $send['return-path'] = $matches[1];
      else $send['return-path'] = $input['from'];
    };

    /*--- from,to,cc,bcc ---*/
    foreach(array('from', 'to', 'cc', 'bcc') AS $foo){
      $send[$foo] = "";
      if(!isset($input[$foo]) || !$input[$foo]) continue;
      foreach(preg_split("/\x2c/", $input[$foo]) AS $line){
        if($send[$foo]) $send[$foo] .= ",";
        if(preg_match("/^(.+)\s?(\x3c[^\x3e]+\x3e)$/", $line, $matches)) $send[$foo] .= mb_encode_mimeheader($this->YC->Encode($matches[1], $send['charset']), $send['charset'], 'B') . " " . $matches[2];
        else $send[$foo] .= mb_encode_mimeheader($line, $send['charset'], 'B');
      }
    };

    /*--- subject ---*/
    $send['subject'] = (isset($input['subject']) && $input['subject']) ? $this->YC->Encode($input['subject'], $send['charset']) : "";

    /*--- header ---*/
    $send['header']  = "MIME-Version: 1.0\n";
    if($send['return-path']) $send['header'] .= "Return-Path: {$send['return-path']}\n";
    $send['header'] .= "From: {$send['from']}\n";
    if(isset($input['cc' ]) && $input['cc' ]) $send['header'] .= "Cc: {$send['cc']}\n";
    if(isset($input['bcc']) && $input['bcc']) $send['header'] .= "Bcc: {$send['bcc']}\n";

    /*--- text ---*/
    $send['text'] = isset($input['text']) ? $input['text'] : "";
    if(!$send['text'] && isset($input['html']) && $input['html']) $send['text'] = preg_replace(array("/<br[^\x3e]*>|<\/div>|<\/p>|\r|\n/i", "/<[^\x3e]*>/"), array("\n",""), $input['html']);
    $send['text'] = $this->YC->Encode($send['text'], $send['charset']);

    /*--- html ---*/
    $send['html'] = isset($input['html']) ? $input['html'] : "";
    if($send['html']){
      if(!preg_match("/<body[^\x3e]*>/i", $send['html'])) $send['html']="<BODY>{$send['html']}</BODY>";
      if(!preg_match("/<head[^\x3e]*>/i", $send['html'])) $send['html']="<HEAD><META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset={$send['charset']}\" /></HEAD>".$send['html'];
      if(!preg_match("/<html[^\x3e]*>/i", $send['html'])) $send['html']="<HTML>{$send['html']}</HTML>";
    };

    /*--- multipart ---*/
    if((isset($input['html']) && $input['html'])
    || (isset($input['file']) && is_array($input['file']))) $send = $this->multipart($input, $send);
    else $send['body'] = $send['text'];

    /*--- 改行コード ---*/
    foreach($send as $key=>$value) $send[$key] = preg_replace("/\r\n|\r|\n/", "\n", $value);
    while(preg_match("/\n$/", $send['header'])) $send['header'] = preg_replace("/\n+$/", "", $send['header']);
    if($send['header']) $send['header'] .= "\n";

    /*--- 送信 ---*/
    if(ini_get('safe_mode') || !$send['return-path']) return(mb_send_mail($send['to'], $send['subject'], $send['body'], $send['header']));
    else return(mb_send_mail($send['to'], $send['subject'], $send['body'], $send['header'], '-f' . $send['return-path']));
  }


  /*------------------------------
    multipartを作成
  ------------------------------*/
  public function multipart($input, $send){
    /*--- 添付ファイル ---*/
    $files = array();
    if(isset($input['file']) && is_array($input['file'])){
      foreach($input['file'] as $file){
        $urlscheme = $file;
        if(file_exists($file)){// パスからURLスキームを取得
          if(    preg_match('/\x2ejpg$/i', $file)) $urlscheme = "data:image/jpeg;base64," . base64_encode(file_get_contents($file));
          elseif(preg_match('/\x2egif$/i', $file)) $urlscheme = "data:image/gif;base64,"  . base64_encode(file_get_contents($file));
          elseif(preg_match('/\x2epng$/i', $file)) $urlscheme = "data:image/png;base64, " . base64_encode(file_get_contents($file));
          elseif(preg_match('/\x2epdf$/i', $file)) $urlscheme = "data:application/pdf;base64, " . base64_encode(file_get_contents($file));
        };
        if(preg_match("/^data:([^\x3b]+);base64,(.+)$/", $urlscheme, $matches)){
          $tail = "";
          if(     preg_match("/jpe?g$/i", $matches[1])) $tail = ".jpg";
          else if(preg_match("/gif$/i"  , $matches[1])) $tail = ".gif";
          else if(preg_match("/png$/i"  , $matches[1])) $tail = ".png";
          else if(preg_match("/pdf$/i"  , $matches[1])) $tail = ".pdf";
          if(!$tail) continue;
          $num      = sprintf("%03d", count($files) + 1);
          $filename = $num . $tail;
          $hash = array();
          $hash['head']  = "Content-Type: " . $matches[1] . ";\n";
          $hash['head'] .= "\tname=\"{$filename}\"\n";
          $hash['head'] .= "Content-Transfer-Encoding: base64\n";
          $hash['head'] .= "Content-Disposition: attachment;\n\tfilename=\"{$filename}\"\n";
          $hash['body']  = $matches[2];
          $files[] = $hash;
        };
      };
    };

    /*--- htmlからインライン画像を抽出 ---*/
    if(isset($send['html']) && $send['html']){
      $send['html'] = preg_replace("/src=[\x22\x27]([^\x22\x27]+)[\x22\x27]/", '$this->inline_image("$1")', $send['html']);
    };

    /*--- 添付＆インライン ---*/
    if(count($files) > 0 && count($this->inline) > 0){
      $mixed       = $this->phpprecipe();
      $alternative = $this->phpprecipe();
      $related     = $this->phpprecipe();

      $send['header'] .= "Content-Type: multipart/mixed; boundary=\"{$mixed}\"\n";
      $send['header'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body']  = "--{$mixed}\n";
      $send['body'] .= "Content-Type: multipart/alternative; boundary=\"{$alternative}\"\n";
      $send['body'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$alternative}\n";
      $send['body'] .= "Content-Type: text/plain; charset=\"{$send['charset']}\"\n";
      $send['body'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body'] .= "\n";
      $send['body'] .= $send['text']."\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$alternative}\n";
      $send['body'] .= "Content-Type: multipart/related; boundary=\"{$related}\"\n";
      $send['body'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$related}\n";
      $send['body'] .= "Content-Type: text/html; charset=\"".$this->YC->Code($send['html'])."\"\n";
      $send['body'] .= "Content-Transfer-Encoding: quoted-printable\n";
      $send['body'] .= "\n";
      $send['body'] .= mb_convert_encoding($send['html'], "Quoted-Printable", $send['charset'])."\n";
      $send['body'] .= "\n";
      foreach($this->inline as $hash){
        $send['body'] .= "--{$related}\n";
        $send['body'] .= $hash['head']."\n";
        $send['body'] .= $hash['body']."\n";
        $send['body'] .= "\n";
      }
      $send['body'].="--{$related}--\n";
      $send['body'].="--{$alternative}--\n";
      foreach($files as $hash){
        $send['body'] .= "--{$mixed}\n";
        $send['body'] .= $hash['head']."\n";
        $send['body'] .= $hash['body']."\n";
        $send['body'] .= "\n";
      };
      $send['body'] .= "--{$mixed}--\n";
      return $send;
    }
    /*--- 添付のみ ---*/
    elseif(count($files) > 0){
      $mixed       = $this->phpprecipe();
      $alternative = $this->phpprecipe();

      $send['header'] .= "Content-Type: multipart/mixed; boundary=\"{$mixed}\"\n";
      $send['header'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body']  = "--{$mixed}\n";
      $send['body'] .= "Content-Type: multipart/alternative; boundary=\"{$alternative}\"\n";
      $send['body'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$alternative}\n";
      $send['body'] .= "Content-Type: text/plain; charset=\"{$send['charset']}\"\n";
      $send['body'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body'] .= "\n";
      $send['body'] .= $send['text']."\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$alternative}\n";
      $send['body'] .= "Content-Type: text/html; charset=\"".$this->YC->Code($send['html'])."\"\n";
      $send['body'] .= "Content-Transfer-Encoding: quoted-printable\n";
      $send['body'] .= "\n";
      $send['body'] .= mb_convert_encoding($send['html'], "Quoted-Printable", $send['charset'])."\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$alternative}--\n";
      foreach($files as $hash){
        $send['body'] .= "--{$mixed}\n";
        $send['body'] .= $hash['head']."\n";
        $send['body'] .= $hash['body']."\n";
        $send['body'] .= "\n";
      }
      $send['body'] .= "--{$mixed}--\n";
      return $send;
    }

    /*--- インラインのみ ---*/
    else if(count($this->inline) > 0){
      $alternative = $this->phpprecipe();
      $related     = $this->phpprecipe();

      $send['header'] .= "Content-Type: multipart/alternative; boundary=\"{$alternative}\"\n";
      $send['header'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body']  = "--{$alternative}\n";
      $send['body'] .= "Content-Type: text/plain; charset=\"{$send['charset']}\"\n";
      $send['body'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body'] .= "\n";
      $send['body'] .= $send['text']."\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$alternative}\n";
      $send['body'] .= "Content-Type: multipart/related; boundary=\"{$related}\"\n";
      $send['body'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$related}\n";
      $send['body'] .= "Content-Type: text/html; charset=\"".$this->YC->Code($send['html'])."\"\n";
      $send['body'] .= "Content-Transfer-Encoding: quoted-printable\n";
      $send['body'] .= "\n";
      $send['body'] .= mb_convert_encoding($send['html'], "Quoted-Printable", $send['charset'])."\n";
      $send['body'] .= "\n";
      foreach($this->inline as $hash){
        $send['body'] .= "--{$related}\n";
        $send['body'] .= $hash['head']."\n";
        $send['body'] .= $hash['body']."\n";
        $send['body'] .= "\n";
      };
      $send['body'] .= "--{$related}--\n";
      $send['body'] .= "--{$alternative}--\n";
      return $send;
    }
    /*--- テキストのhtmlのみ ---*/
    else{
      $alternative = $this->phpprecipe();

      $send['header'] .= "Content-Type: multipart/alternative; boundary=\"{$alternative}\"\n";
      $send['header'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body']  = "--{$alternative}\n";
      $send['body'] .= "Content-Type: text/plain; charset=\"{$send['charset']}\"\n";
      $send['body'] .= "Content-Transfer-Encoding: 7bit\n";
      $send['body'] .= "\n";
      $send['body'] .= $send['text']."\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$alternative}\n";
      $send['body'] .= "Content-Type: text/html; charset=\"".$this->YC->Code($send['html'])."\"\n";
      $send['body'] .= "Content-Transfer-Encoding: quoted-printable\n";
      $send['body'] .= "\n";
      $send['body'] .= mb_convert_encoding($send['html'], "Quoted-Printable", $send['charset'])."\n";
      $send['body'] .= "\n";
      $send['body'] .= "--{$alternative}--\n";
      return $send;
    };

    return $send;
  }


  /*------------------------------
    インラインから画像を抽出
  ------------------------------*/
  public function inline_image($file){
    $urlscheme = $file;
    if(file_exists($urlscheme)){
      if(    preg_match('/\x2ejpg$/i', $file)) $urlscheme = "data:image/jpeg;base64," . base64_encode(file_get_contents($file));
      elseif(preg_match('/\x2egif$/i', $file)) $urlscheme = "data:image/gif;base64,"  . base64_encode(file_get_contents($file));
      elseif(preg_match('/\x2epng$/i', $file)) $urlscheme = "data:image/png;base64, " . base64_encode(file_get_contents($file));
    };
    if(preg_match("/^data:([^\x3b]+);base64,(.+)$/", $urlscheme, $matches)){
      $tail = "";
      if(     preg_match("/jpe?g$/i", $matches[1])) $tail = ".jpg";
      else if(preg_match("/gif$/i"  , $matches[1])) $tail = ".gif";
      else if(preg_match("/png$/i"  , $matches[1])) $tail = ".png";
      if(!$tail) return;
      $num      = sprintf("%03d", count($this->inline) + 1);
      $filename = "inline" . $num . $tail;
      $hash = array();
      $hash['cid']   = $num . '@' . $this->now;
      $hash['head']  = "Content-Type: " . $matches[1] . ";\n";
      $hash['head'] .= "\tname=\"{$filename}\"\n";
      $hash['head'] .= "Content-Transfer-Encoding: base64\n";
      $hash['head'] .= "Content-ID: <{$hash['cid']}>\n";
      $hash['head'] .= "Content-Disposition: inline;\n\tfilename=\"{$filename}\"\n";
      $hash['body']  = $matches[2];
      $this->inline[] = $hash;
      return "src=\"cid:{$hash['cid']}\"";
    };
    return $urlscheme;
  }


  /*------------------------------
    ランダムな英数字を作成
  ------------------------------*/
  public function phpprecipe(){
    $string = array_merge(range('A','Z'),range('0','9'));
    $result = "";
    for($i=0; $i<20; $i++) $result .= $string[rand(0, (count($string)-1))];
    return ($result);
  }
};


