2 // vim: foldmethod=marker
6 * @author Masaki Fujimoto <fujimoto@php.net>
7 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
12 /** メールテンプレートタイプ: 直接送信 */
13 define('MAILSENDER_TYPE_DIRECT', 0);
16 // {{{ Ethna_MailSender
20 * @author Masaki Fujimoto <fujimoto@php.net>
24 class Ethna_MailSender
30 /** @var array メールテンプレート定義 */
34 /** @var string メールテンプレートディレクトリ */
35 var $mail_dir = 'mail';
37 /** @var int 送信メールタイプ */
40 /** @var string 送信オプション */
43 /** @var object Ethna_Backend backendオブジェクト */
46 /** @var object Ethna_Config 設定オブジェクト */
52 * Ethna_MailSenderクラスのコンストラクタ
55 * @param object Ethna_Backend &$backend backendオブジェクト
57 function Ethna_MailSender(&$backend)
59 $this->backend =& $backend;
60 $this->config =& $this->backend->getConfig();
67 * @param string $option メール送信オプション
69 function setOption($option)
71 $this->option = $option;
80 * array('filename' => '/tmp/hoge.xls', 'content-type' => 'application/vnd.ms-excel')
84 * array('name' => 'foo.txt', 'content' => 'this is foo.')
86 * 'content-type' 省略時は 'application/octet-stream' となる。
87 * 複数添付するときは上の配列を添字0から始まるふつうの配列に入れる。
90 * @param string $to メール送信先アドレス (nullのときは送信せずに内容を return する)
91 * @param string $template メールテンプレート名 or タイプ
92 * @param array $macro テンプレートマクロ or $templateがMAILSENDER_TYPE_DIRECTのときはメール送信内容)
93 * @param array $attach 添付ファイル
95 function send($to, $template, $macro, $attach = null)
98 if ($template === MAILSENDER_TYPE_DIRECT) {
101 $renderer =& $this->getTemplateEngine();
104 $env_datetime = _et('%Y/%m/%d %H:%M:%S');
105 $renderer->setProp("env_datetime", strftime($env_datetime));
106 $renderer->setProp("env_useragent", $_SERVER["HTTP_USER_AGENT"]);
107 $renderer->setProp("env_remoteaddr", $_SERVER["REMOTE_ADDR"]);
110 $macro = $this->_setDefaultMacro($macro);
113 if (is_array($macro)) {
114 foreach ($macro as $key => $value) {
115 $renderer->setProp($key, $value);
118 if (isset($this->def[$template])) {
119 $template = $this->def[$template];
121 $mail = $renderer->perform(sprintf('%s/%s', $this->mail_dir, $template), true);
122 if (Ethna::isError($mail)) {
131 $mail = str_replace("\r\n", "\n", $mail);
132 list($header, $body) = $this->_parse($mail);
134 // 添付ファイル (multipart)
135 if ($attach !== null) {
136 $attach = isset($attach[0]) ? $attach : array($attach);
137 $boundary = Ethna_Util::getRandom();
138 $body = "This is a multi-part message in MIME format.\n\n" .
140 "Content-Type: text/plain; charset=iso-2022-jp\n" .
141 "Content-Transfer-Encoding: 7bit\n\n" .
143 foreach ($attach as $part) {
144 if (isset($part['content']) === false
145 && isset($part['filename']) && is_readable($part['filename'])) {
146 $part['content'] = file_get_contents($part['filename']);
147 $part['filename'] = basename($part['filename']);
149 if (isset($part['content']) === false) {
152 if (isset($part['content-type']) === false) {
153 $part['content-type'] = 'application/octet-stream';
155 if (isset($part['name']) === false) {
156 $part['name'] = $part['filename'];
158 if (isset($part['filename']) === false) {
159 $part['filename'] = $part['name'];
161 $part['name'] = preg_replace('/([^\x00-\x7f]+)/e',
162 "Ethna_Util::encode_MIME('$1')", $part['name']); // XXX: rfc2231
163 $part['filename'] = preg_replace('/([^\x00-\x7f]+)/e',
164 "Ethna_Util::encode_MIME('$1')", $part['filename']);
168 "Content-Type: " . $part['content-type'] . ";\n" .
169 "\tname=\"" . $part['name'] . "\"\n" .
170 "Content-Transfer-Encoding: base64\n" .
171 "Content-Disposition: attachment;\n" .
172 "\tfilename=\"" . $part['filename'] . "\"\n\n";
173 $body .= chunk_split(base64_encode($part['content']));
175 $body .= "--$boundary--";
179 if (isset($header['mime-version']) === false) {
180 $header['mime-version'] = array('Mime-Version', '1.0');
182 if (isset($header['subject']) === false) {
183 $header['subject'] = array('Subject', 'no subject in original');
185 if (isset($header['content-type']) === false) {
186 $header['content-type'] = array(
188 $attach === null ? 'text/plain; charset=iso-2022-jp'
189 : "multipart/mixed; \n\tboundary=\"$boundary\"",
194 foreach ($header as $key => $value) {
195 if ($key == 'subject') {
196 // should be added by mail()
199 if ($header_line != "") {
200 $header_line .= "\n";
202 $header_line .= $value[0] . ": " . $value[1];
206 if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
207 $body = str_replace("\n", "\r\n", $body);
209 $header_line = str_replace("\n", "\r\n", $header_line);
212 foreach (to_array($to) as $rcpt) {
213 if (is_string($this->option)) {
214 mail($rcpt, $header['subject'][1], $body, $header_line, $this->option);
216 mail($rcpt, $header['subject'][1], $body, $header_line);
222 * アプリケーション固有のマクロを設定する
225 * @param array $macro ユーザ定義マクロ
226 * @return array アプリケーション固有処理済みマクロ
228 function _setDefaultMacro($macro)
234 * テンプレートメールのヘッダ情報を取得する
237 * @param string $mail メールテンプレート
238 * @return array ヘッダ, 本文
240 function _parse($mail)
242 list($header_line, $body) = preg_split('/\r?\n\r?\n/', $mail, 2);
243 $header_line .= "\n";
245 $header_lines = explode("\n", $header_line);
247 foreach ($header_lines as $h) {
248 if (strstr($h, ':') == false) {
251 list($key, $value) = preg_split('/\s*:\s*/', $h, 2);
252 $i = strtolower($key);
253 $header[$i] = array();
254 $header[$i][] = $key;
255 $header[$i][] = preg_replace('/([^\x00-\x7f]+)/e', "Ethna_Util::encode_MIME('$1')", $value);
258 $body = mb_convert_encoding($body, "ISO-2022-JP");
260 return array($header, $body);
264 * メールフォーマット用レンダラオブジェクト取得する
267 * @return object Ethna_Renderer レンダラオブジェクト
269 function &getRenderer()
271 $_ret_object =& $this->getTemplateEngine();
276 * メールフォーマット用レンダラオブジェクト取得する
279 * @return object Ethna_Renderer レンダラオブジェクト
281 function &getTemplateEngine()
283 $c =& $this->backend->getController();
284 $renderer =& $c->getRenderer();