ソースコードで学ぶWebプログラミング

[Perl]お問い合わせフォームの作り方

お問い合わせフォームとは、サイト訪問者がサイト運営者と連絡を取るための窓口となるものです。フォーム画面は、HTMLのフォームタグで構成され、送信されたデータを受け取るWebプログラムが必要となります。今回は、そのデータを受け取るフォーム用プログラムをPerl言語で作成します。

Perlでお問い合わせフォームを作る方法

お問い合わせフォームには、どのような機能が必要となるか洗い出してみます。まず連絡を取り合うために、フォームから送信者のメールアドレスを受け取れるようにします。また送信先は、プログラム内で設定できるようにします。

1.データ「件名、送信者名、送信者アドレス、本文」を受け取る ・POSTリクエストで受け取る 2.データ「件名、送信者名、送信者アドレス、本文」を送信データに変換する ・送信データは、文字コードISO-2022-JPで送信する ・件名には、日本語を含める ・送信者名には、日本語を含める ・宛先には、日本語を含める 3.送信データを出力する ・指定アドレスに送信する

要件毎に送信するメール文章をテンプレート化しておく方法もありますが、今回は問い合わせのみとして、プログラム内に直接設定する構成にします。

Perlで同サーバからメールを送信する方法

Perlでメールを送信する場合は、sendmailコマンドを利用します。sendmailのパスは、一般的には/usr/sbin/sendmailですが、レンタルサーバによっては異なります。日本語の件名などで送る場合は、Encodeモジュールで文字コードを変換してから送信します。

#!/usr/bin/perl use strict; use warnings; use Encode qw(encode decode); # sendmailのパス my $sendmail = '/usr/sbin/sendmail'; # 管理者メールアドレス my $ADMIN_MAIL = '***'; sub sendMail { my $set = shift; open MAIL, '| '.$sendmail.' -t'; if (exists $set->{'to_name'}) { $set->{'to'} = encode('MIME-Header-ISO_2022_JP', $set->{'to_name'}) .'<'.$set->{'to'}.'>'; } if (exists $set->{'from_name'}) { $set->{'from'} = encode('MIME-Header-ISO_2022_JP', $set->{'from_name'}) .'<'.$set->{'from'}.'>'; } print MAIL 'From: '.$set->{'from'}."\n"; print MAIL 'To: '.$set->{'to'}."\n"; print MAIL 'Subject: '.encode('MIME-Header-ISO_2022_JP',$set->{'sub'})."\n"; print MAIL 'Content-Type: text/plain; charset="iso-2022-jp"'."\n"; print MAIL "Content-Transfer-Encoding: 7bit\n"; print MAIL "MIME-Version: 1.0\n\n"; print MAIL encode('ISO-2022-JP', decode('utf-8', $set->{'body'})); close MAIL; } # 送信サンプル my %set = ( 'to'=>$ADMIN_MAIL, 'to_name'=>'管理者', 'from'=>'送信元アドレス', 'from_name'=>'送信者名', 'sub'=>'件名', 'body'=>'メール本文', ); sendMail(\%set);

動作チェック用のコードも載せておきます。入力エラーの時、エラー用のURLへ飛ばし、送信後は完了用のURLへ飛ばしています。Perlでは、Net::DNSモジュールにより、メールアドレスのドメインをチェック出来ます。

# メールアドレスチェック用モジュール use Net::DNS qw(mx); require 'CgiDecode.pm'; CgiDecode->new; # our()で使えるように our(%_GET,%_POST,%_COOKIE,@_FILES); # POST送信を取得 sub gPOST { my $key = shift; return exists $_POST{$key} ? $_POST{$key}: ''; } # GET送信を取得 sub gGET { my $key = shift; return exists $_GET{$key} ? $_GET{$key}: ''; } # フォームから送信があった時 if ($ENV{'REQUEST_METHOD'} eq 'POST') { my $from = gPOST('from'); my $name = gPOST('name'); my $sub = gPOST('sub'); my $body = gPOST('body'); # メールドメインの確認 my $domain = 0; if ($from =~ m/@([^@]+)\z/) { foreach(mx($1)){ if (exists $_->{'exchange'}) { $domain = 1; last; } } } # お名前、メールアドレスが空欄、ドメインが存在しない場合エラー if ($name eq '' || $from eq '' || $domain==0) { print "Status: 301 Moved Permanently\n"; print 'Location: '.$ENV{'SCRIPT_NAME'}."?result=error\n\n"; exit; } $body = 'お名前:'.$name.' メールアドレス:'.$from.' お問い合わせ内容: '.$body; # 管理者へメール my $body1 = '下記の問い合わせがありました。 '.$body; my %set = ( 'to'=>$ADMIN_MAIL, 'to_name'=>'管理者', 'from'=>$from, 'from_name'=>$name, 'sub'=>$sub, 'body'=>$body1 ); sendMail(\%set); # 送信者へメール my $body2 = '下記の送信を行いました。 '.$body; %set = ( 'to'=>$from, 'to_name'=>$name, 'from'=>$ADMIN_MAIL, 'from_name'=>'自動返信', 'sub'=>'[送信控え]'.$sub, 'body'=>$body2 ); sendMail(\%set); print "Status: 301 Moved Permanently\n"; print 'Location: '.$ENV{'SCRIPT_NAME'}."?result=success\n\n"; exit; }

Perlでは、ヒアドキュメントによりHTMLタグをプログラムソース内に記述出来ます。

print "Content-Type: text/html; charset=utf-8\n\n"; print <<HTML; <html> <head> <meta charset="utf-8"> <title>[Perl]お問い合わせフォーム</title> <style> table { margin: 50px auto; width: 500px; } td { padding: 5px 0; } input,select,textarea { padding: 5px; width: 100%; } textarea { height: 100px; } .required { color: red; } #caution { margin-top: 50px; text-align: center; color: #a00; } #complete { margin-top: 50px; text-align: center; color: #060; } </style> </head> <body> HTML if (gGET('result') eq 'success') { print <<HTML; <div id="complete">送信を実行しました。ご返信まで今しばらくお待ちください。</div> </body> </html> HTML exit; } elsif(gGET('result') eq 'error') { print '<div id="caution">必須事項をご入力ください</div>'; } print <<HTML; <form method="post"> <table> <tr> <th>件名</th> <td> <select name="sub"> <option value="資料のご請求">資料のご請求</option> <option value="お申込み">お申込み</option> <option value="お問い合わせ">お問い合わせ</option> </select> </td> </tr> <tr> <th>お名前<span class="required">*</span></th> <td> <input type="text" name="name"> </td> </tr> <tr> <th>メールアドレス<span class="required">*</span></th> <td> <input type="text" name="from"> </td> </tr> <tr> <th>お問い合わせ内容</th> <td> <textarea name="body"></textarea> </td> </tr> <tr> <td colspan="2"><input type="submit" value="送信"></td> </tr> </form> </body> </html> HTML

Perlで別サーバからメールを送信する方法

別サーバにあるメールサーバから送信したい場合、SMTPサーバに接続して送信する事になります。Perlでは、メール送信ライブラリとしてNet::SMTPを利用できます。

#!/usr/bin/perl use strict; use warnings; use Net::SMTP; use Encode qw(encode decode); # SMTPサーバ my $MAIL_HOST = '***'; # 接続ユーザ my $MAIL_USER = '***'; # パスワード my $MAIL_PASS = '***'; # ポート番号 my $MAIL_PORT = 587; sub smtpSend { my $set = shift; my $to = $set->{'to'}; if (exists $set->{'to_name'}) { $to = encode('MIME-Header-ISO_2022_JP', $set->{'to_name'}) .'<'.$set->{'to'}.'>'; } my $from = $set->{'from'}; if (exists $set->{'from_name'}) { $from = encode('MIME-Header-ISO_2022_JP', $set->{'from_name'}) .'<'.$set->{'from'}.'>'; } my $header = 'From: '.$from."\n"; $header .= 'To: '.$to."\n"; $header .= 'Subject: '.$sub."\n" $header .= 'Content-Type: text/plain; charset="iso-2022-jp"'."\n"; $header .= "Content-Transfer-Encoding: 7bit\n"; $header .= "MIME-Version: 1.0\n\n"; my $s = Net::SMTP->new($MAIL_HOST, Port=>$MAIL_PORT); $s->auth($MAIL_USER, $MAIL_PASS); $s->mail($set->{'from'}); $s->to($set->{'to'}); $s->data(); $s->datasend($header); $s->datasend( encode('ISO-2022-JP', decode('utf-8', $set->{'body'})) ); $s->quit; } # 送信サンプル my %set = ( 'to'=>$MAIL_USER, 'to_name'=>'管理者', 'from'=>'送信元アドレス', 'from_name'=>'送信者名', 'sub'=>'件名', 'body'=>'メール本文', ); smtpSend(\%set);