/** * テンプレートメールのヘッダ情報を取得する * * @access private * @param string $mail メールテンプレート * @return array ヘッダ, 本文 */ function _parse($mail) { list($header_line, $body) = preg_split('/\\r?\\n\\r?\\n/', $mail, 2); $header_line .= "\n"; $header_lines = explode("\n", $header_line); $header = array(); foreach ($header_lines as $h) { if (strstr($h, ':') == false) { continue; } list($key, $value) = preg_split('/\\s*:\\s*/', $h, 2); $i = strtolower($key); $header[$i] = array(); $header[$i][] = $key; $header[$i][] = preg_replace_callback('/([^\\x00-\\x7f]+)/', function ($matches) { return Ethna_Util::encode_MIME($matches[1]); }, $value); } return array($header, $body); }
/** * メールを送信する * * $attach の指定方法: * - 既存のファイルを添付するとき * <code> * array('filename' => '/tmp/hoge.xls', 'content-type' => 'application/vnd.ms-excel') * </code> * - 文字列に名前を付けて添付するとき * <code> * array('name' => 'foo.txt', 'content' => 'this is foo.') * </code> * 'content-type' 省略時は 'application/octet-stream' となる。 * 複数添付するときは上の配列を添字0から始まるふつうの配列に入れる。 * * @param string $to メール送信先アドレス (nullのときは送信せずに内容を return する) * @param string $template メールテンプレート名 or タイプ * @param array $macro テンプレートマクロ or $templateがMAILSENDER_TYPE_DIRECTのときはメール送信内容) * @param array $attach 添付ファイル */ function send($to, $template, $macro, $attach = null) { // メール内容を作成 if ($template === MAILSENDER_TYPE_DIRECT) { $mail = $macro; } else { $renderer = $this->getTemplateEngine(); // 基本情報設定 $env_datetime = _et('%Y/%m/%d %H:%M:%S'); $renderer->setProp("env_datetime", strftime($env_datetime)); $renderer->setProp("env_useragent", $_SERVER["HTTP_USER_AGENT"]); $renderer->setProp("env_remoteaddr", $_SERVER["REMOTE_ADDR"]); // デフォルトマクロ設定 $macro = $this->_setDefaultMacro($macro); // ユーザ定義情報設定 if (is_array($macro)) { foreach ($macro as $key => $value) { $renderer->setProp($key, $value); } } if (isset($this->def[$template])) { $template = $this->def[$template]; } $mail = $renderer->perform(sprintf('%s/%s', $this->mail_dir, $template), true); if (Ethna::isError($mail)) { return $mail; } } if ($to === null) { return $mail; } // メール内容をヘッダと本文に分離 $mail = str_replace("\r\n", "\n", $mail); list($header, $body) = $this->_parse($mail); // 添付ファイル (multipart) if ($attach !== null) { $attach = isset($attach[0]) ? $attach : array($attach); $boundary = Ethna_Util::getRandom(); $body = "This is a multi-part message in MIME format.\n\n" . "--{$boundary}\n" . "Content-Type: text/plain; charset=iso-2022-jp\n" . "Content-Transfer-Encoding: 7bit\n\n" . "{$body}\n"; foreach ($attach as $part) { if (isset($part['content']) === false && isset($part['filename']) && is_readable($part['filename'])) { $part['content'] = file_get_contents($part['filename']); $part['filename'] = basename($part['filename']); } if (isset($part['content']) === false) { continue; } if (isset($part['content-type']) === false) { $part['content-type'] = 'application/octet-stream'; } if (isset($part['name']) === false) { $part['name'] = $part['filename']; } if (isset($part['filename']) === false) { $part['filename'] = $part['name']; } $part['name'] = preg_replace_callback('/([^\\x00-\\x7f]+)/', function (array $matches) { return Ethna_Util::encode_MIME($matches[1]); }, $part['name']); // XXX: rfc2231 $part['filename'] = preg_replace_callback('/([^\\x00-\\x7f]+)/', function (array $matches) { return Ethna_Util::encode_MIME($matches[1]); }, $part['filename']); $body .= "--{$boundary}\n" . "Content-Type: " . $part['content-type'] . ";\n" . "\tname=\"" . $part['name'] . "\"\n" . "Content-Transfer-Encoding: base64\n" . "Content-Disposition: attachment;\n" . "\tfilename=\"" . $part['filename'] . "\"\n\n"; $body .= chunk_split(base64_encode($part['content'])); } $body .= "--{$boundary}--"; } // ヘッダ if (isset($header['mime-version']) === false) { $header['mime-version'] = array('Mime-Version', '1.0'); } if (isset($header['subject']) === false) { $header['subject'] = array('Subject', 'no subject in original'); } if (isset($header['content-type']) === false) { $header['content-type'] = array('Content-Type', $attach === null ? 'text/plain; charset=iso-2022-jp' : "multipart/mixed; \n\tboundary=\"{$boundary}\""); } $header_line = ""; foreach ($header as $key => $value) { if ($key == 'subject') { // should be added by mail() continue; } if ($header_line != "") { $header_line .= "\n"; } $header_line .= $value[0] . ": " . $value[1]; } // 改行コードを CRLF に if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { $body = str_replace("\n", "\r\n", $body); } $wa_config = 'mail_func_workaround'; if ($this->config->get($wa_config) == false && isset($this->options[$wa_config]) == false) { $header_line = str_replace("\n", "\r\n", $header_line); } // 送信 foreach (to_array($to) as $rcpt) { if (is_string($this->option)) { mail($rcpt, $header['subject'][1], $body, $header_line, $this->option); } else { mail($rcpt, $header['subject'][1], $body, $header_line); } } }