-
メール送信機能の実装
##はじめに
メール送信については、多くの入門書席にあるようなサンプルコードではうまくいかないことが多い。かつてこのような記事も書かせてもらいました。
要点としては ちゃんとSMTPサーバーを通してメール送信しましょう ということだ。
外部ライブラリに PHPMailerを利用しています。
composer.jsonに以下を記述し、コマンド composer update
でインストールできます。
{
"name": "MyApp",
"description": "login",
"require": {
"php": ">=5.6.0",
"phpmailer/phpmailer": "~5.2",
"smarty/smarty": "~3.1"
}
}
利用しやすく、記述は簡単に がモットーなので、以下のように利用できるように設計します。
Mail::send($email, $title, $body);
Mail.class.php
を作成します。
- 要件にはないが、添付ファイル対応
- メール本文にテンプレートを利用できるようにした。
サービスが運用フェーズに入ると、意外と送信メールの書式を変更する場面が出てくる。その度にソースコードをGREPし、ファイルを探し、ヒアドキュメントを修正し…なんてことは非常に面倒。
テンプレートエンジンを使うことで、HTMLだけではなく、こういったメールテンプレート機能にも応用できます。
ポイントとしては、通常の display()
ではなく、fetch()
を使います。fetch()
の場合、返り値をブラウザには返すことなく、メモリ上に確保します。
リファレンス
fetch()
テンプレートを利用した記述は以下のようになります。
$email = 'recipient@example.com';
$title = 'メール・タイトル';
$body = Mail::getTemplate('template.tpl', array('name'=>'おなまえ'));
Mail::send($email, $title, $body);
##実装
<?php
namespace MyApp\common;
/**
* Mailer.php
* @since 2015/07/24
*/
class Mail
{
/**
* 送信専用メール
*/
const SEND_ONLY_EMAIL = "送信用メールアドレス";
/**
* 送信専用メール 表示名
*/
const SEND_ONLY_EMAIL_NAME = 'MyApp';
/**
* 送信専用メール 言語名
*/
const SEND_ONLY_EMAIL_LANGUAGE = "japanese";
/**
* 送信専用メール 文字コード
*/
const SEND_ONLY_EMAIL_ENCODING = 'utf-8';
/**
* ホスト名
*/
const MAIL_HOST = 'mail.example.com';
/**
* ポート
*/
const MAIL_PORT = '25';
/**
* ユーザー名
*/
const MAIL_USER = 'contact@example.com';
/**
* パスワード
*/
const MAIL_PASS = 'smtp_password';
/**
* メールを送信する
* @param string $strRecipient 宛先
* @param string $strSubject 題名
* @param string $strBody 本文
* @param array('path'=>'', 'name'=>'') $binAttachment 添付ファイル
* @throws \Exception
*/
public static function send($strRecipient, $strSubject, $strBody, array $binAttachment = [])
{
Log::write('*** send_mail ***');
if (empty($strRecipient)) {
throw new \Exception('宛先が設定されていません。');
}
if (empty($strSubject)) {
throw new \Exception('メールタイトルが設定されていません。');
}
if (empty($strBody)) {
throw new \Exception('メール本文が設定されていません。');
}
mb_language(self::SEND_ONLY_EMAIL_LANGUAGE);
mb_internal_encoding(self::SEND_ONLY_EMAIL_ENCODING);
$from = self::SEND_ONLY_EMAIL;
$fromname = self::SEND_ONLY_EMAIL_NAME;
$mail = new \PHPMailer();
$mail->IsSMTP();
$mail->SMTPAuth = TRUE;
$mail->Host = self::MAIL_HOST;
$mail->Port = self::MAIL_PORT;
$mail->Username = self::MAIL_USER;
$mail->Password = self::MAIL_PASS;
$mail->CharSet = "iso-2022-jp";
$mail->Encoding = "7bit";
$mail->AddAddress($strRecipient);
$mail->From = $from;
$mail->FromName = mb_encode_mimeheader(
mb_convert_encoding(
$fromname
, "JIS"
, self::SEND_ONLY_EMAIL_ENCODING
)
);
$mail->Subject = mb_encode_mimeheader($strSubject);
$mail->Body = mb_convert_encoding(
$strBody
, "JIS"
, self::SEND_ONLY_EMAIL_ENCODING
);
foreach ($binAttachment as $attachment) {
if (array_key_exists('path', $attachment) &&
array_key_exists('name', $attachment) &&
file_exists($attachment['path'])) {
$mail->AddAttachment(
$attachment['path']
, $attachment['name']
);
} else if (array_key_exists('path', $attachment) &&
file_exists($attachment['path'])) {
$mail->AddAttachment($attachment['path']);
} else if (file_exists($attachment)) {
$mail->AddAttachment($attachment);
}
}
if (!$mail->Send()) {
throw new \Exception($mail->ErrorInfo);
}
}
/**
* メールテンプレートに変数を割り当てて本文を取得
* @param string $templateName
* @param array $args
*/
static public function getTemplate($templateName, array $args = [])
{
$smarty = new \Smarty();
$smarty->setTemplateDir(BASE_DIR . '/smarty/templates/mail/');
foreach ($args as $k => $v) {
$smarty->assign($k, $v);
}
return $smarty->fetch($templateName);
}
}