ここの情報は古いです。ご理解頂いた上でお取り扱いください。

source: OpenPNE/branches/2.6.x/webapp/lib/OpenPNE/KtaiMail.php @ 2652

Last change on this file since 2652 was 2652, checked in by ogawa, 14 years ago

#612:正規表現中のブラケット([])内のハイフン(-)をエスケープ

File size: 8.4 KB
Line 
1<?php
2/**
3 * @copyright 2005-2006 OpenPNE Project
4 * @license   http://www.php.net/license/3_01.txt PHP License 3.01
5 */
6
7// PEAR::Mail_mimeDecode
8require_once 'Mail/mimeDecode.php';
9
10/**
11 * OpenPNE_KtaiMail
12 * 携帯メール用のメールデコーダ
13 */
14class OpenPNE_KtaiMail
15{
16    /**
17     * デコード結果
18     * @var stdClass
19     */ 
20    var $mail;
21
22    /** @var string 変換元文字エンコーディング(デフォルト値) */
23    var $from_encoding = 'auto';
24
25    /** @var string 変換先文字エンコーディング */
26    var $to_encoding = 'UTF-8';
27
28    /** @var string 画像検証用のテンポラリディレクトリ */
29    var $img_tmp_dir;
30
31    /** @var string 画像検証用のテンポラリファイルの接頭辞 */
32    var $img_tmp_prefix = 'OpenPNE_KtaiMail_';
33
34    /** @var string 画像の最大ファイルサイズ(byte) */
35    var $img_max_filesize;
36
37    /** @var bool 全角スペースを削除するかどうか */
38    var $trim_doublebyte_space = true;
39
40    /**
41     * constructor
42     *
43     * @access public
44     * @param string $options
45     *      - from_encoding    : 変換元文字エンコーディング
46     *      - to_encoding      : 変換先文字エンコーディング
47     *      - img_tmp_dir      : 画像検証用のテンポラリディレクトリ
48     *      - img_tmp_prefix   : 画像検証用のテンポラリファイルの接頭辞
49     *      - img_max_filesize : 画像の最大ファイルサイズ
50     *      - trim_doublebyte_space : 全角スペースを削除するかどうか
51     */
52    function OpenPNE_KtaiMail($options = array())
53    {
54        foreach ($options as $key => $value) {
55            switch ($key) {
56            case 'from_encoding':
57                $this->from_encoding = $value;
58                break;
59            case 'to_encoding':
60                $this->to_encoding = $value;
61                break;
62            case 'img_tmp_dir':
63                $this->img_tmp_dir = $value;
64                break;
65            case 'img_tmp_prefix':
66                $this->img_tmp_prefix = $value;
67                break;
68            case 'img_max_filesize':
69                $this->img_max_filesize = $value;
70                break;
71            case 'trim_doublebyte_space':
72                $this->trim_doublebyte_space = (bool)$value;
73                break;
74            }
75        }
76    }
77
78    /**
79     * メールをデコード
80     *
81     * @access public
82     * @param string メールの生データ
83     */
84    function decode($raw_mail)
85    {
86        $params['include_bodies'] = true;
87        $params['decode_bodies']  = true;
88        $params['decode_headers'] = true;
89        $params['input'] = $raw_mail;
90
91        $this->mail =& Mail_mimeDecode::decode($params);
92    }
93
94    /**
95     * ヘッダー(From:)から送信元メールアドレスを取得
96     *
97     * @access public
98     * @return string Fromメールアドレス
99     */
100    function get_from()
101    {
102        return $this->_get_mail_address($this->mail->headers['from']);
103    }
104
105    /**
106     * ヘッダー(To:)から宛先メールアドレスを取得
107     *
108     * @access public
109     * @return string Toメールアドレス
110     */
111    function get_to()
112    {
113        return $this->_get_mail_address($this->mail->headers['to']);
114    }
115
116    /**
117     * Subject の内容を抽出(+文字コード変換)
118     *
119     * @access public
120     * @return string Subject
121     */
122    function get_subject()
123    {
124        return isset($this->mail->headers['subject']) ?
125                    $this->convert_text($this->mail->headers['subject']) : '';
126    }
127
128    /**
129     * メール本文からテキストを抽出(+文字コード変換)
130     *
131     * @access public
132     * @return string メール本文のテキスト
133     */
134    function get_text_body()
135    {
136        return $this->_get_text_body($this->mail);
137    }
138
139    /** @access private */
140    function _get_text_body(&$mail)
141    {
142        $body = '';
143
144        if (isset($mail->parts) && is_array($mail->parts)) {
145            // multipart
146            foreach ($mail->parts as $part) {
147                if ($body = $this->_get_text_body($part)) break;
148            }
149        } elseif (strtolower($mail->ctype_primary) === 'text' &&
150                  strtolower($mail->ctype_secondary) === 'plain') {
151            $body = $mail->body;
152            $charset = $mail->ctype_parameters['charset'];
153
154            $body = $this->convert_text($body, $charset);
155        }
156
157        return $body;
158    }
159
160    /**
161     * メールから画像データを抽出
162     *
163     * @access public
164     * @return array 画像データ配列
165     */
166    function get_images()
167    {
168        return $this->_get_images($this->mail);
169    }
170
171    /** @access private */
172    function _get_images(&$mail)
173    {
174        $allowed_type = array('jpeg', 'gif', 'png');
175        $images = array();
176
177        if (isset($mail->parts) && is_array($mail->parts)) {
178            // multipart
179            foreach ($mail->parts as $part) {
180                $images = array_merge($images, $this->_get_images($part));
181            }
182        } elseif (strtolower($mail->ctype_primary) === 'image' &&
183                  in_array(strtolower($mail->ctype_secondary), $allowed_type)) {
184            $image_data = $mail->body;
185
186             // 画像かどうかチェック
187            if (!@imagecreatefromstring($image_data)) {
188                // base64_decodeしてリトライ
189                $image_data = base64_decode($image_data);
190                if (!@imagecreatefromstring($image_data)) {
191                    return array();
192                }
193            }
194
195            // 一時ファイルを作成
196            $tmpfname = tempnam($this->img_tmp_dir, $this->img_tmp_prefix);
197
198            $fp = fopen($tmpfname, 'wb');
199            fwrite($fp, $image_data);
200            fclose($fp);
201
202            // 画像サイズのチェック
203            if ($this->img_max_filesize && filesize($tmpfname) > $this->img_max_filesize) {
204                unlink($tmpfname);
205                return array();
206            }
207
208            // 画像が正しいかどうかチェック
209            switch (strtolower($mail->ctype_secondary)) {
210            case 'jpeg':
211                if (!@imagecreatefromjpeg($tmpfname)) $image_data = '';
212                break;
213            case 'gif':
214                if (!@imagecreatefromgif($tmpfname)) $image_data = '';
215                break;
216            case 'png':
217                if (!@imagecreatefrompng($tmpfname)) $image_data = '';
218                break;
219            }
220            unlink($tmpfname);
221
222            if ($image_data) {
223                $images = array($image_data);
224            }
225        }
226
227        return $images;
228    }
229
230    /**
231     * 文字列からメールアドレスを抽出
232     *
233     * @access private
234     * @param string $str 入力文字列
235     * @return string メールアドレス
236     */
237    function _get_mail_address($str)
238    {
239        if (!$str) {
240            return false;
241        }
242
243        // "(ダブルクォーテーション)を取り除く
244        // "example"@docomo.ne.jp
245        $str = str_replace('"', '', $str);
246
247        // <example@docomo.ne.jp> というアドレスになることがある。
248        //   日本語 <example@docomo.ne.jp>
249        // のような場合に複数マッチする可能性があるので、
250        // マッチした最後のものを取ってくるように変更
251        $matches = array();
252        $regx = '/([\.\w!#$%&\'*+\-\/=?^`{|}~]+@[\w!#$%&\'*+\-\/=?^`{|}~]+(\.[\w!#$%&\'*+\-\/=?^`{|}~]+)*)/';
253        if (preg_match_all($regx, $str, $matches)) {
254            return array_pop($matches[1]);
255        }
256
257        return false;
258    }
259
260    /**
261     * 文字エンコーディングの変換、空白文字の削除
262     *
263     * @access public
264     * @param string $str 変換前の文字列
265     * @param string $from_encoding
266     * @param string $to_encoding
267     * @return string 変換後の文字列
268     */
269    function convert_text($str, $from_encoding = '', $to_encoding = '')
270    {
271        if (!$from_encoding) $from_encoding = $this->from_encoding;
272        if (!$to_encoding)   $to_encoding = $this->to_encoding;
273
274        $str = mb_convert_encoding($str, $to_encoding, $from_encoding);
275
276        // 空白文字の削除
277        $str = str_replace("\0", '', $str);
278        if ($this->trim_doublebyte_space) {
279            $str = mb_ereg_replace('([\s ])+$', '', $str);
280        } else {
281            $str = rtrim($str);
282        }
283
284        return $str;
285    }
286}
287
288?>
Note: See TracBrowser for help on using the repository browser.