ゼロと無限の間に

フリーでオープンソースなJavaScriptとかPHPとか。

ユーザ用ツール

サイト用ツール


php-tool-box:mail-man

PHPでシンプルなメールの送信&受信したメールの解析 - MailMan.php

送信はmb_send_mail()のラッパーなので、mb_send_mail()用の設定(mbstring.language = Japanese とmbstring.internal_encoding)がされていないと文字化けする。

メール解析はPEAR::Mail_mimeDecodeのラッパーなので、Mail_mimeDecodeのインストールが必要。

Windowsでのみ動作確認した。

ちょっとした機能

  • 宛先や送信元のメールアドレスに、下記のような表示名を付けられる
    "山田太郎 <taro.yamada@example.com>"
  • 解析したメールに対して、返信を返せる

ソースコード

<?php
/**
 *  @version 0.2.0
 */
class MailMan {
    const CC = 'Cc';
    const BCC = 'Bcc';
    const REPLY_TO = 'Reply-To';    //返信先メールアドレス
    const SENDER = 'Sender';    //送信者
    const X_MAILER = 'X-Mailer';    //送信元クライアントアプリケーション名
 
    public $from;
    public $to;
    public $subject;
    public $body;
 
    public $fromName;    //表示名付きのFrom
    public $toName;    //表示名付きのTo
    public $files;    //添付ファイル(送信はできない)
 
    /**
     *    コンストラクタ
     *    @param    string    $from    送信元メールアドレス
     *    @param    string    $to    宛先メールアドレス
     *    @param    string    $subject    件名
     *    @param    string    $body    本文
     */
    public function __construct($from, $to, $subject, $body) {
        $this->from = $from;
        $this->to = $to;
        $this->subject = $subject;
        $this->body = $body;
 
        $this->files = array();
    }
 
    /**
     *    送信元メールアドレスに表示名をセットする
     *    @param    string    $from    表示名
     */
    public function setFromName($name) {
        $this->fromName = MailMan::_toDisplayName($this->from, $name);
    }
 
    /**
     *    宛先メールアドレスに表示名をセットする
     *    @param    string    $from    表示名
     */
    public function setToName($name) {
        $this->toName = MailMan::_toDisplayName($this->to, $name);
    }
 
    /**
     *    メールを送信する
     *    @param    array    $headerVal    メールヘッダーの追加オプション
     *    @return    string    送信成功の場合空文字、失敗の場合メール情報
     */
    public function send($headerVal = array()) {
        ini_set("sendmail_from", $this->from);    //WindowsではSMTPのMAIL FROM(エンベロープFrom)に使われる
 
        //メールヘッダー作成
        if ($this->fromName) {
            $headerVal['From'] = $this->fromName;
        }
        if ($this->toName) {
            $headerVal['To'] = $this->toName;    //表示名付きのToで上書き
        }
        foreach ($headerVal as $k => $v) {
            $header[] = ucfirst($k) . ": $v";
        }
 
        //送信(第1引数はSMTPのRCPT TO(エンベロープTO)にも使われる)
        if (@mb_send_mail($this->to, $this->subject, $this->body, implode("\r\n", $header))) {
            return '';
        } else {
            return $this->_toString($header);
        }
    }
 
    /**
     *    メール内容を見やすい形にする
     *    @param    array    $header    メールヘッダー情報
     */
    protected function _toString($header) {
        $s .= "[MAIL FROM]:{$this->from}\n";
        $s .= "[RCPT TO]:{$this->to}\n";
        $s .= "[header]:\n";
        foreach ($header as $line) {
            $s .= "$line\n";
        }
        $s .= "[subject]:{$this->subject}\n";
        $s .= "[body]\n";
        $s .= "{$this->body}\n";
        return $s;
    }
 
    /**
     *    返信する
     *    @param    string    $msg    返信メッセージ
     *    @return    string    送信成功の場合空文字、失敗の場合メール情報
     */
    public function reply($msg, $header = array()) {
        //元のメッセージを引用として付ける
        $msg .= "\n\n";
        $lines = split("\n", $this->body);
        foreach ($lines as $line) {
            $msg .= '> ' . $line . "\n";
        }
 
        $reply = new MailMan($this->to, $this->from, 'RE: ' . $this->subject, $msg);
 
        //メールアドレスの表示名をセット
        if ($this->fromName) {
            $reply->toName = mb_encode_mimeheader($this->fromName);
        }
        if ($this->toName) {
            $reply->fromName = mb_encode_mimeheader($this->toName);
        }
 
        return $reply->send($header);
    }
 
    /**
     *    メールのファイルからデータを取り出す($pathか$dataのどちらかのみ渡すこと)
     *    @param    string    $path    メールのファイルパス
     *    @param    string    $data    メールの生データ
     *    @return    MailMan    取り出したメール
     */
    public static function file2mail($path, $data = "") {
        $decoded = MailMan::decode($path, $data);
 
        //基本情報を取り出す
        $fromName = MailMan::_jis2internal($decoded->headers['from']);
        $toName = MailMan::_jis2internal($decoded->headers['to']);
 
        $from = MailMan::_toOnlyEmail($fromName);
        $to = MailMan::_toOnlyEmail($toName);
        $subject = MailMan::_jis2internal($decoded->headers['subject']);
 
        $mail = new MailMan($from, $to, $subject, '');
 
        $mail->fromName = $fromName;
        $mail->toName = $toName;
 
        //本文と添付ファイルを掘り出す
        MailMan::_digBody($mail, $decoded);
 
        return $mail;
    }
 
    /**
     *    メールを分解する($pathか$dataのどちらかのみ渡すこと)
     *    @param    string    $path    メールのファイルパス
     *    @param    string    $data    メールの生データ
     *    @return    object    分解したメールデータ
     */
    public static function decode($path, $data = "") {
        require_once('Mail/mimeDecode.php');    //要PEAR
 
        if (!$data) {
            $data = file_get_contents($path);
        }
 
        $decoder = new Mail_mimeDecode($data);
        $params['decode_headers'] = true;
        $params['include_bodies'] = true;
        $params['decode_bodies']  = true;
        return $decoder->decode($params);
    }
 
    /**
     *    本文と添付ファイルを取り出す再帰処理
     *    @access    private
     */
    private static function _digBody($mail, $part) {
        if (is_array($part) || is_object($part)) {    //子要素がある場合は再帰処理
            foreach($part as $child) {
                MailMan::_digBody($mail, $child);
            }
        }
        if (!$part->ctype_primary) {
            return;
        }
        switch (strToLower($part->ctype_primary)) {
            case 'multipart':
                return;
            case 'text':    //本文
                if (strToLower($part->ctype_secondary) == "plain") {    //プレーンテキストのみが対象
                    $mail->body = MailMan::_jis2internal($part->body);
                }
                break;
            default:    //添付ファイル
                $file['name'] = MailMan::_jis2internal($part->d_parameters['filename']);
                $file['type'] = $part->ctype_primary . '/' . $part->ctype_secondary;
                $file['data'] = $part->body;
                $mail->files[] = $file;
        }
    }
    /**
     *    JISから内部文字コードに変換
     *    @access    private
     */
    private static function _jis2internal($str) {
        return mb_convert_encoding($str, mb_internal_encoding(), 'JIS');
    }
 
    /**
     *    メールアドレスに表示名を加える
     *    @private
     */
    private static function _toDisplayName($email, $name) {
        return mb_encode_mimeheader($name) . " <$email>";
    }
 
    /**
     *    メールアドレスだけを取り出す
     *    @private
     */
    private static function _toOnlyEmail($displayName) {
        return preg_replace('/(^.*<|>$)/', '', $displayName);
    }
}
php-tool-box/mail-man.txt · 最終更新: 2010/08/14 23:34 by dgbadmin

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki