====== PHPでシンプルなメールの送信&受信したメールの解析 - MailMan.php ====== {{php-tool-box:email-3.png|}} 送信はmb_send_mail()のラッパーなので、[[http://jp2.php.net/manual/ja/ref.mbstring.php|mb_send_mail()用の設定]](mbstring.language = Japanese とmbstring.internal_encoding)がされていないと文字化けする。 メール解析は[[http://pear.php.net/package/Mail_mimeDecode|PEAR::Mail_mimeDecode]]のラッパーなので、Mail_mimeDecodeのインストールが必要。 Windowsでのみ動作確認した。 ===== ちょっとした機能 ===== * 宛先や送信元のメールアドレスに、下記のような表示名を付けられる "山田太郎 " * 解析したメールに対して、返信を返せる ===== ソースコード ===== 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); } }