My開発メモ

XAMPPのsendmailを使ってPerlでメール発信

XAMPPのsendmailからgmailのsmtpサーバーを使ってメール発信ができるようにはしてある。

http://stmemo.herokuapp.com/memos/172

この時は、phpのmb_send_mail関数を使ってやった。

これをPerlを使ってやりたい。

やり方がわかったきっかけは以下のサイト。

ここでKENTさんは、xamppのsendmail.iniの設定のしかたと、KENTさん作のpostmail.cgiの設定について述べられているんだけれど、そのpostmail.cgiの変更箇所が、

  1. 送信先アドレス
  2. sendmail.exeへのパス

なんと、この2つだけ!

じゃあ、posimail.cgiではどういう方法でsendmailにメールを送っているのかというと、

open で ファイルを開いて、そこに文字列を送っているだけ。

で、ほかのサイトでも情報がないか探ると、以下のサイトがあった。

  1. メールを送るには?
  2. How do I send e-mail from my Perl Program?

1. で書かれていることは、以下である。

open(SENDMAIL, "|/usr/lib/sendmail -oi -t -odq")
        or die "Can't fork for sendmail: $!\n";
print SENDMAIL <<"EOF";
From: User Originating Mail <me\@host>
To: Final Destination <you\@otherhost>
Subject: A relevant subject line

Body of the message goes here after the blank line
in as many lines as you like.
EOF
close(SENDMAIL)     or warn "sendmail didn't close nicely";

これで結局うまくメールできたんだが、注意点としては、

From: と To: のメールアドレスの「@」の前に「\」が必要な点である。

(あと、最後の行の「;」の書き忘れで、だいぶエラーが出て悩んだ笑)

できたmail.cgi

一応、動いたので、ここにメモしておく。(下に追記あり)

#!D:\xampp\perl\bin\perl.exe

# ==============================
# mail.cgi
# 参考サイトは一番下に記述。
# ==============================

use strict;
use utf8;
use Encode;
use MIME::Base64;
use CGI;

# ================== 確認項目 ==========================
my $cgi = CGI::new();
# お客様のメールアドレスを取り込む
my $mail_from = $cgi->param('mail');
# お客様のコメントを取り込む
my $usercomment = $cgi->param('comment');
utf8::decode($usercomment) unless utf8::is_utf8($usercomment);
# お客様の名前を取り込む
my $mail_from_name = $cgi->param('name');
utf8::decode($mail_from_name) unless utf8::is_utf8($mail_from_name);
# お問い合わせの種類を取り込む
my $syurui = $cgi->param('syurui');
# はじめてかどうか
my $hajimete = $cgi->param('hajimete');
# きっかけは?
my $kikkake = join(',', $cgi->param('kikkake[]'));
# お問い合わせの件名は?
my $kenmei = $cgi->param('kenmei');
utf8::decode($kenmei) unless utf8::is_utf8($kenmei);

#--------- 追加項目 ---------------
my $message = "\nお名前:" . $mail_from_name;
$message .= "\nメールアドレス:" . $mail_from;
$message .= "\n種類:" . $syurui;
$message .= "\n初めて:" . $hajimete;
$message .= "\nきっかけ:" . $kikkake;
$message .= "\n件名:" . $kenmei;
$message .= "\nお問い合わせ内容:" . $usercomment;
#----------------------------------

# ================ あなたが設定する項目 ==================
# あなたの名前をメールアドレスを記述する。
# お客様のコメントがメールとなって、あなたのもとに届く。
my $mail_to_name = 'XXXXXXXX';
my $mail_to = 'XXXXXXXX@example.com';

# メールの件名を設定する。
# この件名であなたのもとに届くよ。
my $subject = 'コメントが届いてます。';

# メール送信後に「戻る」でどこにリンクするか?
my $modoru = './';

# xamppのsendmail.exeへのパス
my $scmd = "d:/xampp/sendmail/sendmail.exe -oi -t";
    
# ============== 設定項目おわり =====================

# メール本文をUTF-8でエンコードしてバイト文字列に変換、
# そして、base64エンコードする。
my $enc_message = encode_base64(encode('utf-8', $message));

# ==================================================
# メールヘッダを作成する。
# from、to、件名共にMIME-Header(UTF-8)へエンコードします。
my $mail_header;

# 送信者名、送信者のメールアドレスを、
# From: 送信者名 <送信者メールアドレス> 形式へ変換する。
$mail_header = make_name_addr('From:',$mail_from_name,$mail_from);

# 宛名、宛先のメールアドレスを、
# To: 宛名 <宛先メールアドレス> 形式へ変換する。
$mail_header .= make_name_addr('To:',$mail_to_name,$mail_to);

# 件名をMIMEエンコードする。
$mail_header .= 'Subject: '.encode('MIME-Header',$subject)."\n";

# UTF-8とbase64エンコードを使う事を明記します。
$mail_header .= "MIME-Version: 1.0\n";
$mail_header .= "Content-type: text/plain; charset=UTF-8\n";
$mail_header .= "Content-Transfer-Encoding: base64\n";

# メールヘッダの終わり。(これ以降は本文となります。)
$mail_header .= "\n";

# -------------------------------------------
# sendmailへ送信
open(SENDMAIL, "| $scmd") or die "Can't fork for sendmail: $!\n";

print SENDMAIL <<"EOF";
$mail_header
$enc_message
EOF

close(SENDMAIL) or warn "sendmail didn't close nicely";
# -------------------------------------------

my $show_message = <<"EOM";
Content-type: text/html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>メール送信</title>

<script type="text/javascript" charset="UTF-8" src="//cache1.value-domain.com/xrea_header.js" async="async"></script>

<script type="text/javascript" charset="UTF-8" src="//cache1.value-domain.com/xrea_header.js" async="async"></script>

<script type="text/javascript" charset="UTF-8" src="//cache1.value-domain.com/xrea_header.js" async="async"></script>

<script type="text/javascript" charset="UTF-8" src="//cache1.value-domain.com/xrea_header.js" async="async"></script>
</head>
<body>
メールを送信しました。<br><br>
<a href=" $modoru ">戻る</a>
<p>送信内容: $message</p>
</body></html>
EOM

print encode('utf-8', $show_message);

exit;

# 名前とメールアドレスから、name_addr形式のフォーマットを作るサブルーチン。
sub make_name_addr {
# 引数を受け取る。
my ($mail_direction,$mail_name,$mail_address) = @_;
# 末尾にスペースを追加して"From: "または "To: "を作る。
my $name_addr = $mail_direction.' ';

# 名前(送信者名または宛名)が設定されているか調べる。
if ($mail_name ne "") {
# 名前が設定されていたら、
# 名前をMIMEエンコードして、末尾にスペースを追加する。
$name_addr .= encode('MIME-Header',$mail_name).' ';
}
# メールアドレスを追加する。
return ($name_addr .= '<'.$mail_address.">\n");
}

########################################################
# 参考(というか引用元)
# perlでUnicode(UTF-8)で書かれたメールを送信する方法
# http://www.fantasy.jp/~hibernal/document/20100217.htm
########################################################

追記

Perlでは文字列の扱いに、「内部文字列」と「バイト文字列」がある。

外部から入力された文字列は、必ず内部文字列に変換しなくてはならない。

use Encode;

$str = decode('utf-8', $str);

また、外部へ出力するときは、バイト文字列に変換しなくてはならない。

use Encode;

$str = encode('utf-8', $str);

上記スクリプトでは、最初、メール本文をバイト文字列に変換していなかったため、

一部メールクライアントソフトでは、メール本文が文字化けしていた。

自分はスマホの GMAIL アプリでテストしていたのだが、アプリ側で適切に処理 されていたため、気づかなかったのである。

他のアプリでメールを表示したところ、メール本文が文字化けしていたため、 そのことに気づいたというわけである。

参考


カテゴリ: Perl

タグ: XAMPP gmail sendmail

Count: 6

作成日: 2017-12-03 12:16:38

更新日: 2017-12-08 09:53:44