WindowsのPHPでsendmailを使えるようにする
Web開発をする際、てっとり早くWindows+PHPの環境を作った後、ふとした拍子に困るのがメール関連だと思うのです。
PHPはmail関数(あるいはmb_send_mail関数)でメールの送信が可能ですが、Windowsにはsendmailコマンドがないためそのままでは動きません。
そのため、デフォルトではphp.iniがこんな感じに設定されていてlocalhostのSMTPサーバーを使うようになっているはずです。
; For Win32 only.
; http://php.net/smtp
SMTP = localhost
; http://php.net/smtp-port
smtp_port = 25
Windowsにはメールサーバーがインストールされていませんし、localhostを外部のメールサーバーにしたところでSMTP認証を通らないのでメールが送信できません。
昔はプロバイダーで使っているSMTPサーバーのPort:25で普通にメール送信できたんですけど、勝手に他人のSMTPサーバーを使ってSPAMを送る業者が増えてしまいましたから、いまどき認証なしで送信できるサーバーは滅多にないでしょう。
では、どうやったらWindows+PHPの環境でてっとり早くメール送信できるようになるか考えてみたいと思います。
この記事で使っているソフトのバージョン情報
- Windows 10 Pro (1809)
- PHP 7.2.12
- fake sendmail version 32
Windowsにメールサーバーをインストールする
有名どころだとMercury Mailあたりでしょうか。
http://www.pmail.com/index.htm
SMTP認証やIMAPに対応していますし、何よりXAMPPに採用されていることから安心感があります。
有名どころなだけに設定方法の解説も豊富です。
でもけっこう面倒くさい…。
うちでも前は使っていたのですが、テスト用のサーバーは複数用意するし、入れ替えもけっこうするので、インストール作業は極力簡略化したいんですよね。
あと商用利用する場合はライセンス購入が必要なあたりも地味に気になります。
Windowsにダミーのメールサーバーをインストールする
完全にテスト用と割り切るなら、smtp4devが一番お手軽で簡単かも知れません。ぼくも以前お世話になっていました。
smtp4dev-2.0.10-binaries.zip をダウンロードすると smtp4dev.exe というファイルが1つだけ入っているのですが、これをダブルクリックして実行するだけというお手軽っぷり。
https://github.com/rnwood/smtp4dev/releases/tag/v2.0.10
それだけでこんなダイアログが立ち上がり、localhostのPort:25で待ち受けてくれるのでローカルでPHP動かしているならphp.iniの編集の必要すらありません。
PHPでメール送信するとこのダイアログにメールが入ってくるので、それをダブルクリックして中身を確認できます。
とっても手軽なのでけっこう長い間お世話になっていました。
ただ、開発環境もサーバーも同じローカルPCで、というならこれが楽ですけど、開発するクライアントPCと開発用のサーバーが別だった場合は面倒です。
ダイアログの確認をしなければいけないので、例えばリモートデスクトップで接続して内容を確認とかしなければいけません。(物理的に近いなら画面を覗き込めばOKですが)
また、ダミーメールサーバーなのでどこにも送信されないのはテスト中の身としては安心感があるものの、運用直前くらいまで開発が進んでくると、Gmailではどう見えるだろう、Yahooメールではどうだろう、Thunderbirdでは………などなど、受け手の環境を変えてのテストもしたくなります。
そうしたとき、ダミーメールサーバーで外部にメールが送信できないというのはちょっと歯がゆくなってくるんですよね。
PHPでPEAR::Mailを使う
PHPのmail関数が使えないなら、PEARライブラリのMailを使えばいいじゃない、という発想です。
PEARライブラリのMailなら、PHPスクリプトの中でSMTPサーバーやPortの指定が可能で、SMTP認証にももちろん対応しています。
実際、新規に開発するなら良い選択肢だと思いますし、ぼくも長らくこの方法を使っていました。
■PEAR::Mailのコーディング例
<?php
require_once 'Mail.php';
$mail_param['host'] = 'example.com';//メールサーバー
$mail_param["port"] = '587';
$mail_param["auth"] = true; //smtp認証
$mail_param["username"] = "[メールアカウント]";
$mail_param["password"] = "[パスワード]";
$mail_to = "[email protected]";
$mail_from = "[email protected]";
$mail_subject = "メールのタイトル";
$mail_body = "メールの本文";
$header['From'] = $mail_from;
$header['Subject'] = $mail_subject;
$mail = Mail::factory("smtp", $mail_param);
$ret = $mail->send($mail_to, $header, $mail_body);
if (PEAR::isError($ret)) {
echo $ret->getMessage();
}
?>
ちょっと前までなら、メール送るならISO-2022JPじゃないと!
それならエンコーディングしてくれるmb_send_mailのほうが、とかそんな話もあったかも知れませんが、いまどきUTF-8を受信できないメールクライアントってあるのでしょうか。いやもちろんそんなメールソフトも存在するのかも知れませんが、正直ほとんど無視しても良い気がしています。
というのも、送り手側もパソコン通信時代のように機種依存文字が~とか文字コードのことまで考えて入力しないですよね。Webの入力フォームとかあったら普通に「はしご高(髙)」とか絵文字とか入力されまくります。
すると自然とUTF-8がメインになりますし、その内容を送るメールもUTF-8で良いんじゃないかって思うんですよ。
ええと、話が脱線しましたが、ともかく、最近はあえてmb_send_mailを使う理由はあんまりないかなってのが正直なところです。
例えば先程の例をmail関数で書いたとしてもUTF-8ならエンコードせずにそのまま送れますしね。
■mail関数の例
$mail_to = "[email protected]";
$mail_from = "[email protected]";
$mail_subject = "メールのタイトル";
$mail_body = "メールの本文";
$ret = mail($mail_to, $mail_subject, $mail_body, "From:".$mail_from);
if(!$ret) {
echo 'error!';
}
そんなわけで、メール送信にPEAR::Mailを使おうとmail関数を使おうとどちらでも構わないのですが、PEARを使う場合、2点だけ気になるところがあります。
- 既にあるプログラムを書き換えるのがだるい
- PHPのバージョンアップよりもPEARライブラリのバージョンアップは遅い
前者については自分のプログラムなら「だるい」の一言で済みますが、どこかから持ってきたオープンソースのスクリプトとかだと予想外に手間取ったりしますよね。
WordPressくらいユーザー数の多いアプリだと普通にSMTP設定できたりしますけれども、そうじゃないマイナー系だと自分で直す必要があります。
後者についてですが、これはぼくがPEAR::Mailをやめた主な理由です。
PHPのバージョンアップってけっこう頻繁じゃないですか。
そして古いバージョンのほうはセキュリティパッチも出なくなるから、はよ!はよ!とバージョンアップを急かされたりします。なので、仕方なく新しいPHPにしてテストして、いざレンタルサーバーにUPして………PEARだけ古くて動かないっ!とかあるあるネタなんですよね。
PEARのバージョンアップが遅れていることもあれば、単にレンタルサーバー側でPHP5.3では入れてたのに5.5では入れ忘れてたとか、後から聞いたら笑うけど、当事者としては真顔な事態とか実際に経験があります。
まぁ、PEARはPHPなので自分で新しいライブラリDLしてきて、自分のアカウントのpublic_htmlとかにほおりこんでincludeパス変えれば動くんですけども。そういう対処をした経験から、外部ライブラリ使わずに済むなら、そのほうがいいかなぁと思うように。
そうだ、fake sendmailを使おう
元々、PHPのメール関数はLinux上の/usr/bin/sendmailに丸投げする存在です。
なら、Windowsでもsendmail.exeがあればいいんじゃね、という話です。
しかしそれだけだとメールサーバーを用意することと同義です。
(アカウント作ったり認証設定とか面倒くさい)
そこで、このfake sendmailなのですが、このアプリは自分が受け取ったメールをそのままSMTPサーバーに投げてくれます。
つまり、あらかじめfake sendmailのiniファイルに普段使っているメールサーバーのログイン情報を書いておけば、そこに投げてくれるっていうわけです。なんて素敵なのでしょう。
fake sendmailのインストール手順
DLして解凍してiniファイルを書き換えるだけです。
- fake sendmailをダウンロード https://www.glob.com.au/sendmail/
- DLしたsendmail.zipを解凍して c:\sendmail へコピー
- sendmail.iniを編集
- php.iniを編集
- Webサーバー再起動
sendmail.iniの編集箇所
[sendmail]
; you must change mail.mydomain.com to your smtp server,
; or to IIS's "pickup" directory. (generally C:\Inetpub\mailroot\Pickup)
; emails delivered via IIS's pickup directory cause sendmail to
; run quicker, but you won't get error messages back to the calling
; application.
smtp_server=mail.mydomain.com
; if your smtp server requires authentication, modify the following two lines
auth_username=
auth_password=
SMTPサーバーのアドレスとログイン情報を記述するだけです。
php.iniの編集箇所
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
; http://php.net/sendmail-path
;sendmail_path =
sendmail_path = c:/sendmail/sendmail.exe -t -i
For Unix onlyとか書いてあるのは無視して、sendmailのパスを設定してあげるだけです。
なお、-t はヘッダー情報を読み取るオプションで、これがないとCC:やBCC:が使えないので必須と思ってもらって構いません。
-i はデフォルトだとドット(.)だけの行をメールの終了の合図と受け取ってしまうのを防ぐオプションです。これも付けておいたほうが安心です。
まとめ
Windows+PHPの開発環境でメール送信をするには、以下のいずれかの方法が現実的かなと思います。
- Mercury Mailをインストールする
- ダミーのsmtp4devを使う
- メール送信をPEAR::Mailに置き換える
- Fake sendmailでSMTPサーバーにパススルーする
個人的には余計なライブラリを入れる必要がなく、既存コードの書き換えも不要な Fake sendmail がお気に入りです。