#!/usr/bin/perl ################################################################################ # # 汎用メールフォーム pgdmailform.cgi # PGD WORKS by Akira Motojima # http://pgd.jp/ # # #------------------------------------------------------------------------------- # # ○ 動作環境 # Perl5 # /usr/sbin/sendmail が使えること # モジュール HTML::Template, Jcode が動作すること # モジュール HTML::Template, Jcode が動作すること # #------------------------------------------------------------------------------- # # ○ 設定 # # ./lib/pgdmailform_config.cgi を編集してください。 # 詳細はファイル中のコメントを参照 # #------------------------------------------------------------------------------- # # ○ 実行 # # http://-------/****/pgdmailform.cgi # 別テンプレートで実行の場合は # http://-------/****/pgdmailform.cgi?type=TYPE # #------------------------------------------------------------------------------- # # ○ テンプレートの設置 # # ./template/default/ タイプが指定されていなければこちらが利用される # ./template/TYPE/ タイプが指定されている場合 # 但しファイルがなければdefaultのファイルが利用される(mail.txtを除く) # # テンプレートの書式については ./template/default/form.html 中のコメントを参照 # #------------------------------------------------------------------------------- # # ○ 履歴 # # 2008/05/25 Unicode::Japanese が有ればメール送信時のjis変換をJcodeを代替するようにした # 2008/04/28 修正 # 2008/03/13 作成 # ################################################################################ ##### require use lib './lib/'; use strict; use CGI qw/:standard/; use CGI::Carp qw(fatalsToBrowser set_message); set_message(' '); use HTML::Template; use Jcode; require 'pgdmailform_common.cgi'; require 'pgdmailform_config.cgi'; require 'pgdmailform_sendmail.cgi'; require 'pgduserinfo.cgi'; ##### run my $in = new CGI; my %in; foreach my $key ($in->param) { my @list = $in->param($key); $in{$key} = join('/',@list); } # フォームタイプの取得 my $type = $in{'type'}; if ($type eq '') { $type = 'default';} if (!$PgdMailFormConfig::type_available{$type}) { die("このフォームは現在利用できません。");} # 遷移状態の取得 my $mode = $in{'mode'}; delete $in{'mode'}; # 引数のhiddenによるまとめ渡しから除外する if ($mode eq 'check') { &check_and_send; } elsif ($mode eq 'send') { &check_and_send; } else { &form; } exit; ##### routine sub form { my ($form_value,$error_list) = @_; # html テンプレート my $html_template_file = $PgdMailFormCommon::template_dir . $type . '/' . $PgdMailFormCommon::template_form; # テンプレートが無ければデフォルトテンプレートを利用する if (!-e $html_template_file) { $html_template_file = $PgdMailFormCommon::template_dir . 'default/' . $PgdMailFormCommon::template_form;} # テンプレートの選択 my $tmpl = HTML::Template->new( 'die_on_bad_params' => 0, 'filename' => $html_template_file, ); # HTMLテンプレート パラメータ $tmpl->param( 'type' => $type, 'error_count' => scalar keys %{$error_list}, ); # 初期代入値、エラー値をテンプレートに引き渡す foreach my $key (keys %{$form_value}) { # input/textarea用 $tmpl->param($key => %{$form_value}->{$key}); # select/radio/checkbox用 値はURLエンコードを行う my $keystr = %{$form_value}->{$key}; $keystr =~ s/([^a-zA-Z0-9_.!~*'()-])/'%'.unpack('H2',$1)/eg; $keystr = $key . '-' . $keystr; $tmpl->param($keystr => 1); } foreach my $key (keys %{$error_list}) { $tmpl->param("error-$key" => %{$error_list}->{$key});} # 環境変数をテンプレートに送る $tmpl->param(%ENV); print "Content-Type: text/html\n\n"; print $tmpl->output(); } sub check_and_send { # 必須項目一覧の取得 my @required_list = split(/[^\w\-\_]+/,$in{'required'}); my %required_list; foreach my $key (@required_list) { if ($key =~ /^[\w\-\_]+$/) { $required_list{$key} = 1; } } my @loop_list = (); my %form_value; my %error_list; foreach my $key (keys %in) { if ($key eq '') { next;} # 値、キーのサイズのチェック if (length $in{$key} > $PgdMailFormCommon::max_size || length $key > $PgdMailFormCommon::max_size) { $error_list{$key} = 1; } # フォーマットチェック if ($in{$key} ne '') { if (($key =~ /^zip$/i || $key =~ /^zip[^12].+/i) && $in{$key} !~ /^\d{3}\-?\d{4}$/) { $error_list{$key} = 1;} if ($key =~ /^zip1/i && $in{$key} !~ /^\d{3}$/) { $error_list{$key} = 1;} elsif ($key =~ /^zip2/i && $in{$key} !~ /^\d{4}$/) { $error_list{$key} = 1;} if ($key =~ /^(tel|fax)/i && $in{$key} !~ /^\d[\d\-]+\d$/) { $error_list{$key} = 1;} if ($key =~ /^email/i && $in{$key} !~ /^[\w\.\-\_\,\/\?\+]+\@\w+[\w\-\.]+\.[\w\-\.]+\w$/) { $error_list{$key} = 1;} } # 特例エラーチェック #if ($key eq 'email2' && $in{'email2'} ne $in{'email'}) { $error_list{$key} = 1;} #elsif ($key eq 'age' && $in{$key} ne '' && $in{$key} < 10) { $error_list{$key} = 1;} if ($in{$key} ne '') { # 値の格納 loop用 my %row_data; $row_data{'key'} = $key; $row_data{'value'} = $in{$key}; push(@loop_list,\%row_data); $form_value{$key} = $in{$key}; } } # 必須項目のチェック foreach my $key (keys %required_list) { my $error_flg = 0; # まず値がなければエラーとする if ($in{$key} eq '') { $error_flg = 1; } # checkbox の場合の key-数字 に値が一つでもあればエラーを解除 foreach my $key_in (keys %in) { if ($key_in !~ /^$key\-\d+$/) { next;} if ($in{$key_in} ne '') { $error_flg = 0;} } # エラーだった場合テンプレートに出力 if ($error_flg) { $error_list{$key} = 1; } } # エラーが有る場合はフォームに差し戻す if (scalar keys %error_list != 0) { &form(\%form_value,\%error_list); exit; } # checkモードの場合確認画面を表示する if ($mode eq 'check') { # html テンプレート my $html_template_file = $PgdMailFormCommon::template_dir . $type . '/' . $PgdMailFormCommon::template_check; # テンプレートが無ければデフォルトテンプレートを利用する if (!-e $html_template_file) { $html_template_file = $PgdMailFormCommon::template_dir . 'default/' . $PgdMailFormCommon::template_check;} # テンプレートの選択 my $tmpl = HTML::Template->new( 'die_on_bad_params' => 0, 'filename' => $html_template_file, ); # HTMLテンプレート パラメータ $tmpl->param('loop_list' => \@loop_list); # 入力された情報をテンプレートに出力 $tmpl->param(%form_value); # 環境変数をテンプレートに送る $tmpl->param(%ENV); print "Content-Type: text/html\n\n"; print $tmpl->output(); # sendモードの場合メールを送信する } elsif ($mode eq 'send') { # ユーザ情報全般の取得 my %userinfo = (); &Userinfo::GetUserInfo(\%userinfo); ##### メールの送信 # メールテンプレート # タイプに対応するメールテンプレートが無い場合は設置忘れと見なしてデフォルトテンプレートを呼び出さずエラーとする my $mail_template_file = $PgdMailFormCommon::template_dir . $type . '/' . $PgdMailFormCommon::template_mail; # テンプレートが無ければエラー if (!-e $mail_template_file) { die('メールテンプレートが設置されていません。');} # テンプレートの選択 my $mail = HTML::Template->new( 'die_on_bad_params' => 0, 'filename' => $mail_template_file, ); # HTMLテンプレート パラメータ $mail->param( 'loop_list' => \@loop_list, ); # 入力された情報をテンプレートに出力 $mail->param(%form_value); # ユーザ情報をテンプレートに出力 foreach my $key (keys %userinfo) { $mail->param("userinfo-$key" => $userinfo{$key});} # 環境変数をテンプレートに送る $mail->param(%ENV); # メール送信先のセレクト if (!$PgdMailFormConfig::mail_to{$type}) { $PgdMailFormConfig::mail_to{$type} = $PgdMailFormConfig::mail_to{'default'};} if (!$PgdMailFormConfig::mail_cc{$type}) { $PgdMailFormConfig::mail_cc{$type} = $PgdMailFormConfig::mail_cc{'default'};} my %maildata = ( 'From' => $in{'email'}, 'To' => $PgdMailFormConfig::mail_to{$type}, 'Cc' => $PgdMailFormConfig::mail_cc{$type}, 'Bcc' => $PgdMailFormConfig::mail_bcc{$type}, 'Subject' => $PgdMailFormConfig::mail_subject{$type}, 'Return-Path' => '', 'Data' => $mail->output(), ); # Unicode -> JIS 文字化け対策置換 if ($PgdMailFormConfig::utf8_char_fix) { # フォーム画面のhtmlテンプレート my $html_template_file = $PgdMailFormCommon::template_dir . $type . '/' . $PgdMailFormCommon::template_form; # テンプレートが無ければデフォルトテンプレートを利用する if (!-e $html_template_file) { $html_template_file = $PgdMailFormCommon::template_dir . 'default/' . $PgdMailFormCommon::template_form;} open(FILE,$html_template_file); flock(FILE,1); my @template_text = ; flock(FILE,8); close(DATA); my $template_text = join('',@template_text); # UTF8で有れば置換を行う if(Jcode::getcode($template_text) eq 'utf8') { foreach my $key (keys %maildata) { $maildata{$key} =~ s/\xEF\xBD\x9E/\xE3\x80\x9C/g; # チルダ EFBD9E E3809C $maildata{$key} =~ s/\xEF\xBC\x8D/\xE2\x88\x92/g; # ハイフン EFBC8D E28892 $maildata{$key} =~ s/\xE2\x88\xA5/\xE2\x80\x96/g; # 平行記号 E288A5 E28096 } } } # メール送信 &PgdMailFormSendmail::sendmail(\%maildata) or die("メールの送信に失敗しました [$@]"); ##### 送信者向け自動返答メールの送信 # メールテンプレート my $mail_sender_template_file = $PgdMailFormCommon::template_dir . $type . '/' . $PgdMailFormCommon::template_mail_sender; # テンプレートがある場合のみ送信 if (-e $mail_sender_template_file) { # テンプレートの選択 my $mail_sender = HTML::Template->new( 'die_on_bad_params' => 0, 'filename' => $mail_sender_template_file, ); # HTMLテンプレート パラメータ $mail_sender->param( 'loop_list' => \@loop_list, ); # 入力された情報をテンプレートに出力 foreach my $key (keys %form_value) { $mail_sender->param($key => $form_value{$key}); # 変数名にエンコードした値を付けてテンプレートに出力(TMPL_IF判定用) my $keystr = $form_value{$key}; $keystr =~ s/([^a-zA-Z0-9_.!~*'()-])/'%'.unpack('H2',$1)/eg; $keystr = $key . '-' . $keystr; $mail_sender->param($keystr => 1); } # ユーザ情報をテンプレートに出力 foreach my $key (keys %userinfo) { $mail_sender->param("userinfo-$key" => $userinfo{$key});} # 環境変数をテンプレートに送る $mail_sender->param(%ENV); # メールFromのセレクト mail_sender_to が設定されていればそちらを、されていなければ送信先メールアドレスをFromにセット。 my $mail_from; if ($PgdMailFormConfig::mail_sender_to{$type}) { $mail_from = $PgdMailFormConfig::mail_sender_to{$type}; } else { $mail_from = $PgdMailFormConfig::mail_to{$type}; } my %maildata = ( 'From' => $mail_from, 'To' => $in{'email'}, 'Subject' => $PgdMailFormConfig::mail_sender_subject{$type}, 'Return-Path' => '', 'Data' => $mail_sender->output(), ); # メール送信 &PgdMailFormSendmail::sendmail(\%maildata) or die("メールの送信に失敗しました [$@]"); } ##### 送信完了画面出力 # html テンプレート my $html_template_file = $PgdMailFormCommon::template_dir . $type . '/' . $PgdMailFormCommon::template_send; # テンプレートが無ければデフォルトテンプレートを利用する if (!-e $html_template_file) { $html_template_file = $PgdMailFormCommon::template_dir . 'default/' . $PgdMailFormCommon::template_send;} # テンプレートの選択 my $tmpl = HTML::Template->new( 'die_on_bad_params' => 0, 'filename' => $html_template_file, ); # 入力された情報をテンプレートに出力 $tmpl->param(%form_value); # 環境変数をテンプレートに送る $tmpl->param(%ENV); print "Content-Type: text/html\n\n"; print $tmpl->output(); } else { die('mode が正しくありません。'); } }