今回は、webアプリには、必ず必要になるメール送信用のクラスを紹介します。 わたし自身も、もう何十年も使用しているライブラリです。
文字化け対策はもちろん、CC(カーボンコピー)やBcc(ブラインドカーボンコピー)に対応、html形式のメールも、 添付ファイルも送信できます。利用者が、問い合わせフォームにアップロードしたファイルも、 メールで受け取ることが可能で、添付ファイル付きのDMを送信することができます。
ただ、windowsのローカルマシーンには、MTA(メール転送エージェント)が有りませんので、ローカルでテストすることができません。 そこで、xamppのsendmailを設定して、ローカルでもLinuxのsendmail同様にテストが可能な環境を作って、クラスの紹介をします。
- windows sendmailの設定
- windowsにxamppをインストールすると、通常sendmailもインストールされていますが、設定ができていませんので、
デフォルトでは動作しません。
したがって、PHPのmailコマンドや、mb_send_mailも動作することはありません。
C:\xampp\sendmail\sendmail.iniをVSCodeで開いてください。; configuration for fake sendmail -- 中略 -- [sendmail] -- 中略 -- ;smtp_server=mail.mydomain.com smtp_server=smtp.gmail.com ; smtp port (normally 25) ;smtp_port=25 smtp_port=587 -- 中略 -- smtp_ssl=auto -- 中略 -- error_logfile=error.log -- 中略 -- ;auth_username= ;auth_password= auth_username=programming@gmail.com auth_password=passwd1234 -- 中略 -- ;force_sender= force_sender=programming@gmail.com
SMTPサーバが有りませんので、どこからか借りてこなくてはなりません。 この例では、Googoleのgmailを中継に送信するよう設定していますが、現在では、gmail、yahooメール共に、セキュリティを強化しているため、 利用は難しいかもしれません。
(Googleでは、2022-05-30でサービスを終了とのアナウンスがありました。)
太字の部分を、ご自身の企業メール等に変更してください。smtp_server=SMTPサーバー名(smtp.ドメイン名等) smtp_port=ポート番号(25/465/587等) auth_username=ログインアカウント(himojiiまたは、himojii@ドメイン名等) auth_password=ログイン用パスワード force_sender=メールアドレス
通常、メーラー(thunderbirdやOutlook等のメール送受信アプリ)に設定するSMTPの情報と同じです。
- 次に、PHPの設定を行います。
PHPの設定ファイル、C:\xampp\php\php.iniをVSCodeで開きます。
[mail function]セクションを検索して移動してください。[mail function] ; For Win32 only. ; http://php.net/smtp ; 無効にする ;SMTP=localhost ; http://php.net/smtp-port ; 無効にする ;smtp_port=25 ; For Win32 only. ; http://php.net/sendmail-from ;sendmail_from = me@example.com ; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). ; http://php.net/sendmail-path ; 有効にしてパスを設定 sendmail_path = "C:\xampp\sendmail\sendmail.exe"
SMTP=localhost
smtp_port=25
この2行を無効にして、sendmailのパスを絶対パスで指定してください。
簡単なメール送信用phpを作成してテストしてみてください。<?php $headers = join("\n", array( "MIME-Version: 1.0", "X-Sender: ", "X-Mailer: PHP/7.4", "Message-Id: <123456789abcdefghrjklmnopqrstuvwxyz>", "From: programming@gmail.com", "Reply-To: programming@gmail.com", "Return-Path: programming@gmail.com\n" )); $result = mb_send_mail( 'foo@ymail.ne.jp', 'Subject', 'windows sendmail test', $headers ); echo "End=". $result; ?>
メールアドレスをすべて、ご自身のメールアドレスに変更して、checkmail.phpで保存し、ブラウザからアクセスします。 End=1 と表示されれば送信完了です。メールが届いているか、確認してください。
私も初めて設定してみましたが、私の環境では、windowsからでも、正常に届いていることが確認できました。 これで、PHPのmailも、mb_send_mailも正常に機能します。
届いていない場合は、sendmail.iniの設定が問題だと思われますので、送信サーバを変更してみてください。
- windowsにxamppをインストールすると、通常sendmailもインストールされていますが、設定ができていませんので、
デフォルトでは動作しません。
したがって、PHPのmailコマンドや、mb_send_mailも動作することはありません。
- メール送信クラスライブラリ
こちらが、メール送信用のクラスです。<?php $GLOBALS['MIME_EXT'] = array( 'txt'=>'text/plain','csv'=>'text/csv','xml'=>'text/xml','htm'=>'text/html','html'=>'text/html', 'gif'=>'image/gif','jpg'=>'image/jpeg','jpeg'=>'image/jpeg','png'=>'image/png', 'tif'=>'image/tiff','tiff'=>'image/tiff','bmp'=>'image/x-bmp','ps'=>'appilcation/postscript', 'eps'=>'appilcation/postscript','epsf'=>'appilcation/postscript','ai'=>'application/postscript', 'zip'=>'application/zip','lzh'=>'application/x-lzh','lha'=>'application/octet-stream', 'tar'=>'application/x-tar','gzip'=>'application/x-tar','cpt'=>'application/mac-compactpro', 'doc'=>'application/msword','xls'=>'application/vnd.ms-excel', 'ppt'=>'application/vnd.ms-powerpoint','rtf'=>'application/rtf','pdf'=>'application/pdf', 'css'=>'application/css','au'=>'audio/basic','rpm'=>'audio/x-pn-realaudio-plugin', 'swa'=>'application/x-director','mp3'=>'audio/mpeg','mp4'=>'audio/mp4','wav'=>'audio/x-wav', 'midi'=>'audio/midi','avi'=>'vide/x-msvideo','mpeg'=>'video/mpeg','mpg'=>'video/mpeg', 'wmv'=>'video/x-ms-wmv','flash'=>'application/x-shockwave-flash','mmf'=>'application/x-smaf', 'smaf'=>'application/x-smaf','hdml'=>'text/x-hdml','3gpp2'=>'video/3gpp2','3g2'=>'video/3gpp2', 'amc'=>'video/3gpp2','kjx'=>'application/x-kjx','3gpp'=>'video/3gpp','3gp'=>'video/3gpp', 'amr'=>'video/3gpp','asf'=>'video/3gpp','jam'=>'application/x-jam', 'jar'=>'application/java-archive','jad'=>'text/vnd.sun.j2me.app-descriptor', 'exe'=>'application/octet-stream','khm'=>'application/x-kddi-htmlmail', 'dmt'=>'application/x-decomail-template','hmt'=>'application/x-htmlmail-template', 'hqx'=>'application/mac-binhex40','cpt'=>'application/mac-compactpro', 'php'=>'application/x-httpd-php','php4'=>'application/x-httpd-php', 'php3'=>'application/x-httpd-php','phtml'=>'application/x-httpd-php', 'phps'=>'application/x-httpd-php-source','js'=>'application/x-javascript', 'swf'=>'application/x-shockwave-flash','eml'=>'message/rfc822', ); class SendEmail /* 送信元($from)、送信先($to)、本文($body)が未設定の場合は送信されない 直接送信 $mail = new SendEmail($subject, $from, $to, $body); 詳細設定送信 $mail = new SendEmail(); $mail->subject = ""; $mail->to = ""; [必須] 送信先、cc、bccは、半角カンマで区切って複数設定可能 $mail->cc = ""; $mail->bcc = ""; $mail->from = ""; [必須] 送信元が複数設定されている場合は先頭が送信元になる $mail->body = ""; [必須] $mail->type = ""; $mail->files = ""; ファイルのパスをカンマで区切って複数設定可能 $mail->encode = ""; $mail->option = ""; $status = $mail->send_email(); */ { public $subject = ""; public $to = ""; public $cc = ""; public $bcc = ""; public $from = ""; public $body = ""; public $type = "plain"; public $files = ""; public $encode = "iso-2022-jp"; public $option = ""; public $status = ""; public function __construct($subject = '', $from = '', $to = '', $body = '') { if ($from && $to && $body) { $this->status = $this->send_email($subject, $from, $to, $body); } } function send_email($subject = '', $from = '', $to = '', $body = '') { $subject && $this->subject = $subject; $from && $this->from = $from; @list($this->from, $FROM) = preg_split("/,/", $this->from); $to && $this->to = $to; $this->to = $this->mail_str($this->to); $body && $this->body = $body; if ($this->from && $this->to && $this->body) { $options = array(); if ($this->option) { $op =preg_split("/,/", $this->option); foreach ($op as $line) { @list($key, $val) = preg_split("/=/", $line); $val && $options[$key] = $val; } } mb_language("Japanese"); mb_internal_encoding("UTF-8"); !$this->type && $type = "plain"; !$this->encode && $this->encode = "iso-2022-jp"; $this->cc && $this->cc = $this->mail_str($this->cc); $this->bcc && $this->bcc = $this->mail_str($this->bcc); @$Attach_files = preg_split("/,/", $this->files); $ATTACH_FILES = array(); foreach ($Attach_files as $val) { $val = trim($val); if (is_file($val)) { $ATTACH_FILES[] = $val; } } $sender = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'php-lib_formmail'; $mimeid = ""; if (count($ATTACH_FILES)) { $mimeid = $sender. "_" . uniqid(); } $headers = join("\n", array( "MIME-Version: 1.0", "X-Sender: $sender", "X-Mailer: PHP/". phpversion(), "Message-Id: <" . md5(uniqid(microtime())) . ">", "From: ". $this->from, "Reply-To: ". $this->from, "Return-Path: ". $this->from. "\n" )); $this->cc && $headers .= "Cc: ". $this->cc. "\r\n"; $this->bcc && $headers .= "Bcc: ". $this->bcc. "\r\n"; $Body = ""; if ($mimeid) { $headers .= "Content-Type: multipart/mixed; boundary=\"$mimeid\"\n\n"; $Body .= "--$mimeid\n"; $Body .= "Content-Type: text/". $this->type. "; charset=\"". $this->encode. "\"\n\n"; } else { $headers .= "Content-Type: text/". $this->type. "; charset=\"". $this->encode. "\"\n\n"; } if ($this->type == "plain") { $this->body = preg_replace("/(\r\n| | | |\r)/", "\n", $this->body); $this->body = preg_replace("/\t/", "", strip_tags($this->body)); } $Body .= $this->body ."\n\n"; if (count($ATTACH_FILES)) { foreach ($ATTACH_FILES as $attach_file) { if (is_file($attach_file)) { $filename = basename($attach_file); preg_match("/\.(.+)$/", $attach_file, $m); $ext = $m[1]; $Body .= "--$mimeid\n"; if (isset($GLOBALS['MIME_EXT'][$ext]) && $GLOBALS['MIME_EXT'][$ext]) { $Body .= "Content-type: ".$GLOBALS['MIME_EXT'][$ext]."; name=\"$filename\"\n"; } else { $Body .= "Content-type: application/octet-stream; name=\"$filename\"\n"; } $Body .= "Content-transfer-encoding: base64\n\n"; $encode_data = chunk_split(base64_encode(file_get_contents($attach_file))); $Body .= "$encode_data\n"; } } $Body .= "--$mimeid--\n"; } if (isset($options['subj']) && $options['subj']) { $this->subject = mb_encode_mimeheader($this->subject, $options['subj'], 'B'); } else { $this->subject = mb_encode_mimeheader($this->subject, $this->encode, 'B'); } $this->encode != "UTF-8" && $Body = mb_convert_encoding($Body, $this->encode, "UTF-8"); return(mail($this->to, $this->subject, $Body , $headers , "-f". $this->from)); } else { return(false); } } private function mail_str($address) { $ADDR = preg_split("/,/", $address); $email = ""; foreach ($ADDR as $val) { if (preg_match("/([\w\-\.]+\@[\w\-]+\.[\w\-\.]+)/", $val, $m)) { $email && $email .= ","; $email .= $m[1]; } } return($email); } } ?>
少しだけ解説しておきましょう。 49行目からは、プロパティを初期化しています。 60行目のコンストラクタに、引数が指定されていれば、引数を渡して、send_emailメソッドを呼び出して、 即座にメールを送信しています。 65行目のsend_emailメソッドで、メールを送信するのですが、メールアドレスの書式をチェックして、 無効なメールアドレスには、送信しないようにしています。 81行目からは、文字化け対策です。むかし、日本国内のメールの件名は、ISO-2022-JP(JIS)で送るように 定められていましたが、文字通り、JISは、日本工業規格ですので、日本でしか通用せず、 海外のメーラでは文字化けします。また、昨今では、全世界中でやり取りされることが当たり前ですので、 JISでは、日本以外の2バイト文字圏でメールの送受信ができないことから、UTF-8での送信が有効です。 本システムでも、標準はJISになっていますが、UTF-8を指定することも可能になっています。$mail->encode = "UTF-8";
122行目からは、添付ファイルの処理です。添付ファイルがバイナリの場合は、ファイルをBase64に変換して添付します。
バイナリファイル添付する場合は、Base64エンコードと、UUencodeのどちらかでエンコードしますが、本システムでは、Base64を採用しています。
これは、このままsendmail.phpとして保存しておき、必要な時にインクルードして使ってください。
使い方は、非常に簡単で、プレーンテキストのメールを送信するだけなら、
$status = $mail->send_email('件名','送信元','送信先','本文');
と、クラスをインスタンス化するだけです。これで、送信されています。成功すればtrue、失敗すればfalseを返します。
細かな設定をする場合は、クラスの上部のコメントにもあるように、カスタマイズできます。 $email = SendEmail();
プロパティ 項目 備考 subject 件名 先日の会議の件 from 送信元 watasi@gmail.com to 送信先 anata@gmail.com cc カーボンコピー ccopy@yohoo.co.jp,bccopy@gamil.com bcc ブラインドカーボンコピー bccopy@gamil.com,ccopy@yohoo.co.jp body 本文 先日は、お世話になりました。稟議を上げさせていただきました。 type plain/html 省略するとplain files 添付ファイル ../image.png,../confirm.pdf encode 文字コード iso-2022-jp/UTF-8/SJIS <?php include "./sendmail.php"; $mail = new SendEmail(); $mail->subject = "先日の会議の件"; $mail->to = "anata@gmail.com"; $mail->from = "watasi@gmail.com"; $mail->body = "先日は、お世話になりました。稟議を上げさせていただきました。"; $mail->files = "../image.png,../confirm.pdf"; $mail->encode = "UTF-8"; $status = $mail->send_email(); echo "status=". $status; ?>
各メールアドレス($mail->to/$mail->cc/$mail->bcc)は、カンマで区切って、複数設定できます。
添付ファイルは、カンマで区切って、複数設定できます。
SendEmailソースコード
実際のソースコードと、学習時に表示されたコードは、デバッグや表示の便宜上異なる場合があります。
予めご了承ください。