<?php
/**
 * -----------------------------------------------------------------------------
 *
 * SyL - Web Application Framework for PHP
 *
 * PHP version 4 (>= 4.3.x) or 5
 *
 * Copyright (C) 2006 k.watanabe
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * -----------------------------------------------------------------------------
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_Mail.php,v 1.7 2006/12/23 11:13:09 seasonstream Exp $
 * @link      http://www.syl.jp/
 * -----------------------------------------------------------------------------
 */

/**
 * メール内容のエンコーディング
 */
define( 'SYL_MAIL_ENCODE', 'JIS' );
/**
 * 内部エンコーディング
 */
define( 'SYL_INTERNAL_ENCODE', 'EUC-JP');

/**
 *  メール送信クラス
 *
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_Mail.php,v 1.7 2006/12/23 11:13:09 seasonstream Exp $
 * @link      http://www.syl.jp/
 */
class SyL_Mail
{
    /**
     * メールヘッダー配列
     * 
     * @access protected
     * @var array
     */
    var $headers = array();
    /**
     * メールヘッダー配列（その他）
     * 
     * @access protected
     * @var array
     */
    var $headers_etc = array();
    /**
     * メール本文
     * 
     * @access protected
     * @var string
     */
    var $body = '';
  
    /**
     * 添付ファイル名
     * 
     * @access protected
     * @var array
     */
    var $f_name = array();
    /**
     * 添付ファイル内容
     * 
     * @access protected
     * @var array
     */
    var $f_contents = array();
    /**
     * バウンダリ
     * 
     * @access protected
     * @var string
     */
    var $f_boundary = '';
  
    /**
     * X-Mailerヘッダー
     * 
     * @access protected
     * @var string
     */
    var $x_mailer = 'SyL Mail';

/*
  var $htmail;
*/

    /**
     * 送信メール内容のエンコード
     * 
     * @access protected
     * @var string
     */
    var $mail_encode = SYL_MAIL_ENCODE;
    /**
     * 送信パラメータのエンコード
     * 
     * @access protected
     * @var string
     */
    var $parameter_encode = SYL_INTERNAL_ENCODE;
    /**
     * エラーメッセージ
     * 
     * @access protected
     * @var string
     */
    var $error_message = '';

    /**
     * コンストラクタ
     * 
     * @access public
     */
    function SyL_Mail()
    {
        // 以下デフォルトヘッダー
        $this->headers_etc['Mime-version'] = '1.0';
        $this->headers_etc['Content-type'] = 'text/plain; charset="iso-2022-jp"';
        $this->headers_etc['Content-transfer-encoding'] = '7bit';
        $this->headers_etc['X-Mailer']     = $this->x_mailer;

        $this->init();
    }

    /**
     * SyL_Mailクラスのインスタンス取得
     *
     * Mail送信オブジェクト作成
     *
     * ※取得方法
     *   $mail =& SyL_Mail::getInstance();
     *
     * @access public
     */
    function &getObject($type='Default')
    {
        $class_name = 'SyL_Mail' . ucfirst($type);
        include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Mail' . DIRECTORY_SEPARATOR . $class_name . '.php';
        $obj = new $class_name();
        return $obj;
    }

//  function setHtml( $flag=true )
//  {
//    if ($flag) {
//      $this->headers['Content-Type'] =  'multipart/alternative; boundary=--wbmd-multipart--';
//      $this->htmail = true;
//    } else {
//      $this->headers['Content-type'] = 'text/plain; charset="ISO-2022-JP"';
//      $this->htmail = false;
//    }
//  }

    /**
     * 送信元アドレスをセット
     *
     * ※スペース区切りで、名前もセットすることも可能
     * 例）セット文字列: hoge@example.com ホゲ
     *     送信文字列:   ホゲ <hoge@example.com>
     * 
     * @access public
     * @param string 送信元アドレス
     */
    function setFrom($from, $name='')
    {
        $this->headers['From'] = $this->convertEncodingAddress($from, $name, true);
    }

    /**
     * 送信先アドレスをセット
     * ※スペース区切りで、名前もセットすることも可能
     * 例）セット文字列: hoge@hogehoge.com ホゲ
     *     送信文字列:   ホゲ <hoge@hogehoge.com>
     * 
     * @access public
     * @param string 送信先アドレス
     */
    function addTo($to, $name='')
    {
        if (is_array($to)) {
            foreach($to as $tmp) {
                $this->addTo($tmp, $name);
            }
        } else {
            $this->headers['To'][] = $this->convertEncodingAddress($to, $name);
        }
    }

    /**
     * 送信先アドレス(CC)をセット
     * ※スペース区切りで、名前もセットすることも可能
     * 例）セット文字列: hoge@hogehoge.com ホゲ
     *     送信文字列:   ホゲ <hoge@hogehoge.com>
     * 
     * @access public
     * @param string 送信先アドレス(CC)
     */
    function addCc($cc, $name='')
    {
        if (is_array($cc)) {
            foreach($cc as $tmp) {
                $this->addCc($tmp, $name);
            }
        } else {
            $this->headers['Cc'][] = $this->convertEncodingAddress($cc, $name);
        }
    }

    /**
     * 送信先アドレス(BCC)をセット
     * ※スペース区切りで、名前もセットすることも可能
     * 例）セット文字列: hoge@hogehoge.com ホゲ
     *     送信文字列:   ホゲ <hoge@hogehoge.com>
     * 
     * @access public
     * @param string 送信先アドレス(BCC)
     */
    function addBcc($bcc, $name='')
    {
        if (is_array($bcc)) {
            foreach($bcc as $tmp) {
                $this->addBcc($tmp, $name);
            }
        } else {
            $this->headers['Bcc'][] = $this->convertEncodingAddress($bcc, $name);
        }
    }

    /**
     * 件名をセット
     * 
     * @access public
     * @param string 件名
     */
    function setSubject($subject)
    {
        $this->headers['Subject'] = $this->convertEncoding($subject, true);
    }

    /**
     * 本文をセット
     * 
     * @access public
     * @param string 本文
     */
    function setBody($body)
    {
        $this->body = $this->convertEncoding($body);
    }

    /**
     * 送信パラメータのエンコードをセット
     *
     * @access public
     * @param string 送信パラメータのエンコード
     */
    function setParameterEncode($encode)
    {
        $this->parameter_encode = $encode;
    }

    /**
     * 送信メール内容のエンコードをセット
     *
     * @access public
     * @param string 送信メール内容のエンコード
     */
    function setMailEncode($encode)
    {
        $this->mail_encode = $encode;
    }

    /**
     * パラメータをメール送信用文字列にエンコードする
     *
     * @access private
     * @param string エンコード対象文字列
     * @param bool MIMEエンコードフラグ
     * @return エンコード後文字列
     */
    function convertEncoding($parameter, $mime_encode=false)
    {
        $parameter = mb_convert_encoding($parameter, $this->mail_encode, $this->parameter_encode);
        if ($mime_encode) {
            $parameter = mb_encode_mimeheader($parameter, $this->mail_encode);
        }
        return $parameter;
    }

    /**
     * メールアドレスをメール送信用文字列にエンコーディング
     * 
     * @access public
     * @param string メールアドレス
     * @param string メールアドレスの名前
     * @param bool Fromフラグ
     * @return string エンコーディングのメールアドレス
     */
    function convertEncodingAddress($address, $name='', $from=false)
    {
        $address = explode(' ', trim($address), 2);

        if (($name == '') && isset($address[1])) {
            $name = $address[1];
        }

        if ($from) {
            $this->headers['MAIL_FROM'] = $address[0];
            $this->headers_etc['Reply-To'] = $address[0];
        } else {
            $this->headers['RCPT_TO'][] = $address[0];
        }

        if (isset($address[1]) && (trim($address[1]) != '')) {
            return '"' . $this->convertEncoding($name, true) . '" <' . $address[0] . '>';
        } else {
            return '"' . $address[0] . '" <' . $address[0] . '>';
        }
    }

    /**
     * その他のメールヘッダーをセット
     * 
     * @access public
     * @param string ヘッダーのキー
     * @param string ヘッダーの値
     */
    function setHeader($key, $value)
    {
        $this->headers_etc[$key] = $value;
    }

    /**
     * その他のメールヘッダーをセット（複数対応）
     * 
     * @access public
     * @param array ヘッダーのキーと値のペア配列
     */
    function setHeaders($headers)
    {
        $this->headers_etc = array_merge($this->headers_etc, $headers);
/*
    foreach ($headers as $key => $value) {
      $this->setHeader($key, $value);
    }
*/
    }

    /**
     * 添付ファイルをセット
     * 
     * @access public
     * @param string ファイルパス（ファイル名まで含む）
     */
    function setFile($path)
    {
        // 添付ファイル取得
        $f_contents = file_get_contents($path);
        // ファイル名取得
        $f_name = basename($path);
        // 添付ファイル用ヘッダセット
        $this->headers_etc['Content-type'] = 'multipart/mixed; boundary=' . $this->f_boundary . ';';
        $this->headers_etc['Content-transfer-encoding'] = 'Base64';
        // 添付ファイル情報セット
        $this->f_name[]     = $this->convertEncoding($f_name, true);
        $this->f_contents[] = chunk_split(base64_encode($f_contents));
    }

    /**
     * メール送信前処理
     *
     * @access public
     * @param array メール送信属性
     * @param bool 完全初期化フラグ
     * @return OK: true, NG: false
     */
    function init($attributes=array(), $all=false)
    {
        $attributes = array_change_key_case($attributes, CASE_LOWER);

        // データ初期化
        $this->headers['MAIL_FROM'] = '';
        $this->headers['RCPT_TO']   = array();

        // 送り元
        $this->headers['From'] = '';
        if (isset($attributes['from'])) {
            $this->setFrom($attributes['from']);
        }
        // 送り先
        $this->headers['To'] = array();
        if (isset($attributes['to'])) {
            $this->setTo($attributes['to']);
        }
        // Cc
        $this->headers['Cc'] = array();
        if (isset($attributes['cc'])) {
            $this->setCc($attributes['cc']);
        }
        // Bcc
        $this->headers['Bcc'] = array();
        if (isset($attributes['bcc'])) {
            $this->setBcc($attributes['bcc']);
        }
        // 件名
        $this->headers['Subject'] = '';
        if (isset($attributes['subject'])) {
            $this->setSubject($attributes['subject']);
        }
        // 件名
        $this->body = '';
        if (isset($attributes['body'])) {
            $this->setBody($attributes['body']);
        }

        $this->f_name     = array();
        $this->f_contents = array();
        $this->f_boundary = "-=-=-=-=-=-=-=-=-Boundary_" . uniqid("b");
 
//    $this->htmail           = false;
  }

    /**
     * メールヘッダを含む全文取得
     *
     * @access public
     * @param string 本文
     * @return string メールヘッダを含む全文取得
     */
    function getHeaderMessage($body)
    {
        // メールヘッダ
        $data  = '';
        $data .= 'Subject: ' . $this->headers['Subject'] . "\r\n";
        $data .= 'From: '    . $this->headers['From']    . "\r\n";
        $data .= 'To: '      . implode(', ', $this->headers['To']) . "\r\n";
        if (count($this->headers['Cc']) > 0) {
            $data .= 'Cc: ' . implode(', ', $this->headers['Cc'])  . "\r\n";
        }
        if (count($this->headers['Bcc'] ) > 0) {
            $data .= 'Bcc: ' . implode(', ', $headers['Bcc']) . "\r\n";
        }
        foreach ($this->headers_etc as $key => $value) {
            $data .= $key . ': ' . $value . "\r\n";
        }
        $data .= "\r\n";

        // メール本文
        if (count($this->f_name) > 0) {
            // -------------------------------
            // 添付ファイル付きテキストメール
            // -------------------------------
            $data .= '--' . $this->f_boundary . "\r\n";
            $data .= 'Content-Type: text/plain; charset="iso-2022-jp"' . "\r\n";
            $data .= "\r\n";
            $data .= $body . "\r\n";
            for ($i=0; $i<count($this->f_name); $i++) {
                $data .= '--' . $this->f_boundary . "\r\n";
                $data .= 'Content-Type: application/octet-stream; name="' . $this->f_name[$i] . '"' . "\r\n";
                $data .= 'Content-Disposition: attachment; filename="'    . $this->f_name[$i] . '"' . "\r\n";
                $data .= 'Content-Transfer-Encoding: base64' . "\r\n";
                $data .= "\r\n";
                $data .= $this->f_contents[$i] . "\r\n";
                $data .= "\r\n";
            }
            $data .= '--' . $this->f_boundary . "--\r\n";
        } else {
            // 通常のテキストメール
            $data .= $body . "\r\n";
        }

        return $data;
    }


    /**
     * メール送信実行
     *
     * @access public
     * @return OK: true, NG: false
     */
    function send()
    {
        // From必須
        if ($this->headers['MAIL_FROM'] == '') {
            $this->error_message = "[SyL error] From Address not found";
            return false;
        }
        // To必須
        if (count($this->headers['To']) == 0) {
            $this->error_message = "[SyL error] To Address not found";
            return false;
        }
        return true;
    }

    /**
     * メール送信後処理
     *
     * @access public
     * @return OK: true, NG: false
     */
    function quit()
    {
    }

    /**
     * エラーメッセージ判定
     *
     * @access public
     * @return string エラーメッセージ
     */
    function isError()
    {
        return ($this->error_message != '');
    }

    /**
     * エラーメッセージを取得する
     *
     * @access public
     * @return string エラーメッセージ
     */
    function getErrorMessage()
    {
        return $this->error_message;
    }
}

?>
