« PEARを使ってディレクトリの中身を全削除する | トップページ | PEAR::Mail_Mimeを使ってHTMLメールを送ってみよう »

2007年03月24日

PEAR::Mailを使ってメールを送信してみよう

PHPにはmb_send_mail()関数という日本語を含めたメールを送信する機能がありますがよく文字化けします。PHPの自動エンコーディング機能がうまくいかずに文字化けをするのですが、設定がシビアなので使ってません。例えば、同じサーバーを使っている場合は制作時に気をつければ問題ありませんが、サーバーを移行するようなことがあると新しいサーバーでメールが文字化けしたり結構大変だったりします。
結局send()関数を使うのですが、これで日本語のメールを送信する為には追加メールヘッダを記述する必要があります。mb_send_mail()関数よりはマシですが、これもこれで設定に左右されるので意外と大変。メール送信用の自作関数を作ったものの完璧ではありませんでした。
最終的に落ち着いたのは、PEARのMailです。記述がシンプルな上に自由に設定できて便利。
ということで今回はPEAR::Mailを紹介します。

インストールについて知りたい方は、過去の記事をご参照ください。
レンタルサーバーでPEARを使う方法
WindowsでPEARを自動インストールしてみよう

まずは、基本から以下のソースを見てください。

require_once("Mail.php");

$header['From'] = "piyo@s-memo.net";

$mail = Mail::factory("sendmail");
$ret = $mail->send("to@s-memo.net", $header, "メール本文");
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}


これはタイトルも宛先も空白の必須項目のみを記述したサンプルです。
PEAR::Mailで、必要なのは「From(送信者)」「To(送信先)」「メール本文」の3つです。

1行目はいつも通りMail.phpをインクルードしています。

require_once("Mail.php");

3行目では「From(送信者)」を配列にセットしています。
$header['From'] = "piyo@s-memo.net";

5行目でMail::factory()メーラインスタンスを作成しています。
$mail = Mail::factory("sendmail");

7行目でメールを送信しています。第2引数に3行目で作ったFromをセットしている配列を指定しています。
$ret = $mail->send("to@s-memo.net", $header, "メール本文");

8~10行目はメール送信に失敗した場合に、エラーメッセージを表示させます。
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}

メールを受信してみると分かるのですが、宛先も件名も空っぽになっています^^;
これだけだと使い道がないので、もう少し実用的なものを作ってみます。
先ほどのスクリプトに赤の部分を追加・修正してください。(メールアドレスは適当に変えてください)

require_once("Mail.php");

$header['From'] = "ピヨヒコ<piyo@s-memo.net>";
$header['To'] = "To様<to@s-memo.net>";
$header['Cc'] = "Cc様<cc@s-memo.net>";
$header['Bcc'] = "Bcc様<bcc@s-memo.net>";
$header['Reply-To'] = "piyopiyo@s-memo.net";
$header['Subject'] = "メールのタイトル";

$address = array("to@s-memo.net", "cc@s-memo.net", "bcc@s-memo.net");

$mail = Mail::factory("sendmail");
$ret = $mail->send($address, $header, "メール本文");
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}


$headerの連想配列を追加しました。この連想配列にメールアドレスをセットしても指定のアドレスにはメールは送信されません。この配列はメールを受信した時に表示されるテキストです。(上記の例だとメールを受信した時に送信者に「ピヨヒコ」、宛先に「To様」、Ccに「Cc様」と表示されます)
メールを送信先はsend()メソッドで指定します。最初の例のように直接記述することもできますが、複数のアドレスに送信する場合、配列又はカンマ区切りで指定します。
以下のように配列を作って、
$address = array("to@s-memo.net", "cc@s-memo.net", "bcc@s-memo.net");

send()メソッドから複数アドレスに送信します。
$mail->send($address, $header, "メール本文");

[ちょっと余談]
以下の「Reply-To」というのはメールの返信先です。
$header['Reply-To'] = "piyopiyo@s-memo.net";

Fromは「piyo@s-memo.net」ですが、メーラーから返信をすると宛先に「piyopiyo@s-memo.net」が指定されます。Fromと返信先を変えたい時に使いましょう。

最後にSMTPからメールを送信してみましょう。
SMTPを使用すれば外部のメールアドレスからメールを送信することができます。
先ほどのスクリプトを修正します。赤の部分を追加・修正してください。

require_once("Mail.php");

$param['host'] = "smtp.s-memo.net";
$param['port'] = 25;
$param['auth'] = TRUE;
$param['username'] = "piyohiko";
$param['password'] = "password";

$header['From'] = "ピヨヒコ<piyo@s-memo.net>";
$header['To'] = "To様<to@s-memo.net>";
$header['Cc'] = "Cc様<cc@s-memo.net>";
$header['Bcc'] = "Bcc様<bcc@s-memo.net>";
$header['Reply-To'] = "piyopiyo@s-memo.net";
$header['Subject'] = "メールのタイトル";

$address = array("to@s-memo.net", "cc@s-memo.net", "bcc@s-memo.net");

$mail = Mail::factory("smtp", $param);
$ret = $mail->send($address, $header, "メール本文");
if(PEAR::isError($ret)) {
  die("エラーメッセージ:".$ret->getMessage());
}


ホスト名やポート番号等を連想配列を追加しています。
$param['host'] = "smtp.s-memo.net";
$param['port'] = 25;
$param['auth'] = TRUE;
$param['username'] = "piyohiko";
$param['password'] = "password";

「auth」はSMTP認証を使用するかどうかを指定します。TRUEでSMTP認証を使用し、FALSEでSMTP認証を使用しません。
ユーザ名やパスワードはSMTP認証に使用するユーザ名とパスワードを挿入します。

次に制作した連想配列を以下にセットします。

$mail = Mail::factory("smtp", $param);

後はsend()メソッドでメールを送信すれば完了です。
SMTPは外部サーバーのメールを使用できますが、ポートを開いてもらう必要がありますのでご注意ください。
予想以上に長くなりましたが今日はここまで。
と思いましたが、せっかくなのでMailクラスのリファレンスも残しておきます。

Mailクラスのfactoryメソッドのリァレンスは以下の通り

factory($backend, [, $param]);
$backend:「mail」「smtp」「sendmail」のいずれか
$param:パラメータの連想配列(FromやToなど)以下を参照

factoryメソッドの第2引数のパラメータは以下の通り
[「sendmail」の場合]
$p['sendmail_path']:sendmailへのファイルパス /usr/bin/sendmail等
$p['sendmail_args']:sendmailに渡す追加パラメータ
[「smtp」の場合]
$p['host']:SMTPを利用するドメイン又はIP名(デフォルト:localhost)
$p['port']:接続ポート番号(デフォルト:25)
$p['auth']:SMTP認証を使用するかどうか(デフォルト:FALSE)
$p['username'}:SMTP認証のユーザ名
$p['password'}:SMTP認証のパスワード

Mailクラスのsendメソッドのリファレンスは以下の通り

send($address, $header, $msg);
$address:メールアドレス(複数送信は配列又はカンマ区切り)
$header:追加ヘッダの連想配列。詳細は以下を参照
$msg:メール本文

sendメソッドの第2引数のパラメータは以下の通り
$h['From']:送信者
$h['To']:送信先(To)
$h['Cc']:送信先(Cc)
$h['Bcc']:送信先(Bcc)
$h['Reply-To']:メールの返信先
$h['Subject']:メールタイトル

send()メソッドの第2引数に「To」や「Cc」を追加しても実際には送信されません。これはメール受信者の表示用の為の記述です。
実際に送信したい場合は、第1引数に同じアドレスを記述してください。

[関連記事]
PEAR::Mail_Mimeを使ってHTMLメールを送ってみよう

【雑談】
やっと昼型に戻りました!まあ、いつまでもつか分かりませんが、、、^^;

トラックバック

このエントリーのトラックバックURL:
http://www.s-memo.net/mt/mt-tb.cgi/39

コメント

ちょうどPEARでメール送信プログラムを作成していて、PHP経験自体が浅いので悩んでいたところととてもわかりやすい内容でした。
助かりました。

ちなみに・・・
宛先アドレスの存在有無っていうのは、Mail::send()の後で判定できたりするんですかね?

コメントありがとうございます。

>宛先アドレスの存在有無っていうのは、Mail::send()の後で判定できたりするんですかね?
そうですね。存在有無の判定とは少し違うのですが、存在しないメールアドレスにメールを送信した場合、エラーになります。

$ret = $mail->send("to@s-memo.net", $header, "メール本文");
if(PEAR::isError($ret)) {
die("エラーメッセージ:".$ret->getMessage());
}

上記のようにMail::send()を使ったとして、「to@s-memo.net」のアドレスが存在しなかった場合、下記のようにエラーメッセージが表示されます。
エラーメッセージ:unable to add recipient [to@s-memo.net]: Invalid response code received from server

 はじめまして。チャトランといいます。
 PHPで送信ページを作ろうと頑張っています。
 教えて頂きたいことがございまして、
 pearでは、以下のようにサーバ側メーラーのインスタンスを設定しなければならないということですが、クライアント側で契約しているプロバイダのメーラーを使用出来ないのでしょうか?

$mail = Mail::factory("sendmail");

ちゃ

thanks

はじめまして。
mb_send_mail()関数で外部サーバーのメール送信ができず困っておりましたところ、PEAR::Mailを使ったSMTP認証の記事を拝見いたしました。無事、メール送信できました。本当にありがとうございました。

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)