Perl/CGI研究室 'PERL-LABO'

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

Reply-toに対応

研究内容

メールのヘッダには、To、Fromなどの必須のものの他に、 返信先メールアドレスを表すReply-toや、 同じメールを他の人にも送るCc、Bccなどがあります。 今回はReply-toに対応しましょう。

詳細

今回対応するメールヘッダ

今回の研究では、次のメールヘッダに対応したいと思います。

Reply-to 返信先メールアドレス。省略したときはFromが返信先になります。
互換性について

今回のポイントは、今までに加えて新しい引数を追加するときの処理です。 今までも、機能の追加の際に引数の数を増やすということをしてきましたが、 このメール送信関数 sendmail のように、いくつかのCGIプログラムで使用している 関数の変更には注意が必要です。互換性を保たなければいけません。

具体的には、引数の数を増やすのですが、 以前の少ない数の引数でも正しく動くようにしなければいけないということですね。 今回は、Reply-To用の名前とメールアドレスを引数に追加しますが、 これが指定されていなかった場合のことを考えて変更をしなきゃいけません。

日時とホスト名を付加する機能について

メール本文の末尾に日時とホスト名を自動的に付加する機能ですが、 この機能、便利なんですが、よく考えると邪魔なこともありますよね。 管理人にメールを送るぶんには、日時とホスト名が付くのは問題ないんですが、 誰か別の人に送る場合は、日時とホスト名が付いてたらなんじゃこりゃ?ということになります。 そこで、この機能のON/OFFができる機能も追加しましょう。 これも引数で与えることにします。

作成したCGIプログラム

sendmail.pl
# v 1.02

package plab;

# Jcode.pm を使用します。
use Jcode;

# sendmailのパス
$sendmailpath = '/usr/sbin/sendmail';

# 引数 (差出人名, 差出人メールアドレス, 送信先名, 送信先メールアドレス, 
#       件名, 本文 [, 返信先名, 返信先メールアドレス, 日時とホストを追加しない1])
# いずれも空欄可
sub sendmail
{
	local ($ip, $host, @tim, $year, $mon, $t);
	local ($jis_body, $jis_from_name, $jis_to_name, $jis_subject);
	local ($mime_from_name, $mime_to_name, $mime_subject);

	local $from_name  = $_[0];
	local $from_adr   = $_[1];
	local $to_name    = $_[2];
	local $to_adr     = $_[3];
	local $subject    = $_[4];
	local $body       = $_[5];
	local $rep_name   = $_[6];
	local $rep_adr    = $_[7];
	local $notimehost = $_[8];

	# Fromメールアドレスがからっぽだとエラーになるので
	if ($from_adr eq "") {
		return 0;
	}
	
	# 汚染チェック
	$from_adr  =~ s/\r|\n//g;
	$to_adr    =~ s/\r|\n//g;
	$rep_adr   =~ s/\r|\n//g;

	# JIS に変換します。
	$jis_body      = Jcode::convert($body,      'jis');
	$jis_from_name = Jcode::convert($from_name, 'jis');
	$jis_to_name   = Jcode::convert($to_name,   'jis');
	$jis_subject   = Jcode::convert($subject,   'jis');
	$jis_rep_name  = Jcode::convert($rep_name,  'jis');

	# MIMEヘッダ内の日本語をエンコードします。
	$mime_from_name = Jcode::mime_encode([\$jis_from_name]);
	$mime_to_name   = Jcode::mime_encode([\$jis_to_name]);
	$mime_subject   = Jcode::mime_encode([\$jis_subject]);
	if ($rep_adr ne "") {
		$mime_rep_name = Jcode::mime_encode([\$jis_rep_name]);
	}

	if (! open(MAIL, "| $sendmailpath -t")) {
		return 0;
	}

	# メールヘッダ〜本文を出力します。
	print MAIL "From: $mime_from_name<$from_adr>\n";
	print MAIL "To: $mime_to_name<$to_adr>\n";
	if ($rep_adr ne "") {
		print MAIL "Reply-To: $mime_rep_name<$rep_adr>\n";
	}
	print MAIL "Subject: $mime_subject\n";
	print MAIL "Content-Transfer-Encoding: 7bit\n";
	print MAIL "Content-Type: text/plain; charset=\"ISO-2022-JP\"\n";
	print MAIL "\n";
	print MAIL "$jis_body";

	if ($notimehost ne "1") {
		# ホスト名、送信時間を付加します。
		$ip   = $ENV{'REMOTE_ADDR'};
		$host = gethostbyaddr(pack("C4", split('\.', $ip)), 2) || $ip;
		@tim  = localtime(time());
		$year = $tim[5] + 1900;
		$mon  = $tim[4] + 1;
		$t    = sprintf('%02d:%02d:%02d', $tim[2], $tim[1], $tim[0]);

		print MAIL "\n";
		print MAIL "----------------------------\n";
		print MAIL "DateTime : $year/$mon/$tim[3] $t\n";
		print MAIL "Host     : $host";
	}

	close MAIL;

	return 1;
}

1;

考察

なんかだらだらしてきました

引数が増えて、なんだかコードがだらだらしてきました。 もうちょっとスッキリできないものでしょうか…

今後の課題

今回はReply-toに対応してみましたが、他にもCcとかBccとかあるわけです。 それらまで対応しようとすると引数の数がどんどん増えていってしまいます。 また、それらは指定したいときもあるかも知れませんが、 指定する必要がないときも多いですよね。 このことについて考えていて、引数に連想配列を使うという方法があるということに気が付きました。 必要なものだけ、連想配列に特定の名前で値をセットしておいて、それを 関数に渡すっていうやり方です。これ、私が考えたわけじゃなくて、どこかで そんなような関数を見たことがあるのを思い出したんです。 なるほどな、と思いました。でも、関数の互換性を考えると、 そのように変更するのはよくないな、と…。 それで、今回はReply-toにだけ対応しました。

あともう1つ。送信先のToとかって複数のアドレスを指定できるはずですよね? 普段メールするとき、複数の人にあてたメールを送信することもあります。 この関数はそれに対応していません。そもそも、どうやるのか分かりません (^^; これも今後の課題ですね。

Perl/CGI研究室 'PERL-LABO' TOPへ
戻る(History.Back)

Copyright (c) 'PERL-LABO' All Rights Reserved.  リンクフリーです。