Perl入門ゼミ

テキスト処理、Linuxサーバー管理、Web開発ならPerl

JSONとAjaxを使ったCGIのメールフォームが完成したので公開します

JSONとAjaxを使ったCGIのメールフォームが完成したので公開します。

配置する場合は、二つのファイルをドキュメントルートに置いてください。

JSONとAjaxを使ったCGIのメールフォーム(CGI.pmを使わないバージョン)

mail.html

HTMLファイルに、メールフォームを記述します。

Sendが押されたタイミングで、メールフォームの情報をJSONにして、Ajax通信で、送信します。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script>
  $(function() {
    $('.mail-form button').on('click', function () {
      var form_values = JSON.stringify($('.mail-form form').serializeArray(), null, 2);
      $.ajax({
        type:"post",
        url:"/mail.cgi",
        data:form_values,
        contentType: 'application/json',
        dataType: "json",
        success : function (data) {
          if (data) {
            $('.mail-form').html('<div>Thank you very much for contacting us.</div>');
          }
          else {
            alert('Fail sending mail');
          }
        }
      });
    });
  });
</script>

<h2>Message Form</h2>
<div class="mail-form">
  <form>
  	<label>
  		<div class="mail-form-title">
  		  Name:
  		</div>
  		<div class="mail-form-body">
  		  <input type="text" size=50 name="name"><br>
  		</div>
    </label>
  	<label>
  		<div class="mail-form-title">
  		  Mail:
  		</div>
  		<div class="mail-form-body">
  		  <input type="text" size=50 name="email">
  		</div>
    </label>
  	<label>
  		<div class="mail-form-title">
  		  Message:
  		</div>
  		<div class="mail-form-body">
  		  <textarea cols=50 rows=3 name="message"></textarea>
  		</div>
    </label>
  	<div>
  	  <button type="button">Send</button> <input type="reset" value="Clear">
  	</div>
  </form>
</div>

mail.cgi

標準入力から、メールフォームの情報をJSONで受け取って、メールを送信して、標準出力にJSONで、送信結果を書き出します。

CGIに特有の概念のない、通常のPerlスクリプトです。

#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use MIME::Base64;

use Encode 'decode', 'encode';

# Mail to
my $mailto = 'kimoto@foo.example';

# Mail title
my $subject = 'Mail From giblog-mail';

# Mail command
my $mail_cmd = '/usr/sbin/sendmail';

my $input = do { local $/; <STDIN> };
$input = decode('UTF-8', $input);

my $error = sendmail($input);

my $output;
if ($error) {
  $output = 0;
}
else {
  $output = 1;
}

my $res = <<"EOS";
Content-type: application/json;

$output
EOS

print encode('UTF-8', $res);

sub sendmail {
  my ($data) = @_;
  
	# Mail header
	my $mailfrom;
	my $mail_head = "";
	$mail_head .= "Content-Type: text/plain; charset=\"UTF-8\"\n";
	$mail_head .= "Content-Transfer-Encoding: base64\n";
	$mail_head .= "MIME-Version: 1.0\n";
	$mail_head .= "To: $mailto\n";
	$mail_head .= "From: $mailto\n";
	$mail_head .= "Subject: " . encode('MIME-Header', $subject) . "\n";
	$mail_head .= "\n";

	# Mail body
  my $mail_body = $data;

	# Send mail
	my $cmd = "$mail_cmd -f $mailto -t";
	my $send_error;
	if (open(my $out, "| $cmd")) {
	  if (print $out $mail_head) {
			if (print $out encode_base64(encode('UTF-8', $mail_body))) {
			  # Success
			}
			else {
				$send_error = "Mail sending fail(3)";
			}
	  }
	  else {
	    $send_error = "Mail sending fail(2)";
	  }
	}
	else {
		$send_error = "Mail sending fail(1)";
	}
	
	return $error;
}

Perlスクリプトとして、実行して試験できます。POSTされるデータは、標準入力から受け取ります。

chmod 755 mail.cgi
echo 'foo' | ./mail.cgi

JSONとAjaxを使ったCGIのメールフォーム(CGI.pmを使うバージョン)

JSONですべて完結できるかなぁと思っていたけど、ファイルアップロードまでを考慮に入れると、無理だったので、素直にCGI.pmとメール送信モジュールMIME::Liteを使ったバージョンも書きました。

mail.html

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script>
  $(function() {
    $('.mail-form button').on('click', function () {
      var form_values = $('.mail-form form').serialize();
      $.post("/mail.cgi", form_values, function (data) {
        if (data) {
          $('.mail-form').html('<div>Thank you very much for contacting us.</div>');
        }
        else {
          alert('Fail sending mail');
        }
      });
    });
  });
</script>

<h2>Message Form</h2>
<div class="mail-form">
  <form>
  	<label>
  		<div class="mail-form-title">
  		  Name:
  		</div>
  		<div class="mail-form-body">
  		  <input type="text" size=50 name="name"><br>
  		</div>
    </label>
  	<label>
  		<div class="mail-form-title">
  		  Mail:
  		</div>
  		<div class="mail-form-body">
  		  <input type="text" size=50 name="email">
  		</div>
    </label>
  	<label>
  		<div class="mail-form-title">
  		  Message:
  		</div>
  		<div class="mail-form-body">
  		  <textarea cols=50 rows=3 name="message"></textarea>
  		</div>
    </label>
  	<div>
  	  <button type="button">Send</button> <input type="reset" value="Clear">
  	</div>
  </form>
</div>

mail.cgi

#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use MIME::Base64;
use CGI;
use MIME::Lite;

use Encode 'decode', 'encode';

my $q = CGI->new;

# Mail to
my $mailto = 'kimoto_yuki@shinshina.co.jp';

# Mail title
my $subject = 'Mail From giblog-mail';

# Mail command
my $mail_cmd = '/usr/sbin/sendmail';

# Name
my $name = $q->param('name');
$name = decode('UTF-8', $name);

# Email
my $email = $q->param('email');
$email = decode('UTF-8', $email);

# Message
my $message = $q->param('message');
$message = decode('UTF-8', $message);

# Mail body
my $mail_body = <<"EOS";
Name: $name
Email: $email
Message: $message
EOS

# Send mail
my $msg = MIME::Lite->new(
  From    => $mailto,
  To      => $mailto,
  Subject => encode('MIME-Header', $subject),
  Type    => 'multipart/mixed'
);
$msg->attach(
  Type     => 'TEXT',
  Data     => encode('UTF-8', $mail_body),
);
$msg->send;

# Response
my $res = <<"EOS";
Content-type: application/json;

1
EOS
print encode('UTF-8', $res);
  • Perlとはテキスト処理の記述性とパフォーマンスに優れ、正規表現が言語に組み込まれているプログラミング言語です。
  • Linuxサーバーでのフィルタリングプログラム、複数行の文字列を処理、ファイル内容の検索・置換などが得意
  • Perlはgitopensslなど広く普及したUnix/Linuxミドルウェアの補助ツールとして採用実績あり。後方互換性とポータビリティの高さがひとつの理由と推測。
  • 大量のテキストを扱うWeb開発も得意。ロングテールSEOを意識したWebサイト、アドテクやソーシャルゲームでの50ms以内のJSONの生成など。