SMTPでメール送信 PERL版

SMTPを使ったメール送信方法としては、主にNet::SMTPを使う方法と、Email::Sender::Simpleがある。
現状、PERL5.16.3のレンタルサーバーが多いため、Email::Sender::Simpleが標準モジュールとして入っているのがヘテムルとロリポのみなので今回はNet::SMTPを使った方法をメモ。
なお、Net::SMTPが入っていても、Authen::SASLが入っていないと正常にメール送信ができないようなので、Kagoyaでは動かない。(useする必要はない)
また、Net::SMTPは、バージョンによってはSTARTTLSには非対応なので、暗号化するなら、Net::SMTP::SSL、Net::SMTP::TLS などで別途対応が必要。(PERL5.30.3なら、Net::SMTPのバージョンが新しいので対応している)
Net::SMTPを使ってメール送信するサンプルプログラム
#!/usr/local/bin/perl
use Jcode;
use Net::SMTP;
use MIME::Base64;
my $mailhost = 'SMTPサーバー名';
my $mailport = 587;
my $mail_username = 'ユーザー名';
my $mail_password = 'パスワード';
my $from_mail = '送信元メールアドレス';
my $to_mail = '送信先メールアドレス';
my $subject = 'テスト';
my $message = 'テストメールです。';
# 本文を ISO-2022-JP に変換
Jcode::convert(\$message, 'jis');
# SubjectをMIMEエンコード (ISO-2022-JP + Base64)
&Jcode::convert(\$subject, 'jis', 'utf8');
$subject_encoded = jcode($subject)->mime_encode;
# ヘッダー作成
my $header = <<"EOF";
From: $from_mail
To: $to_mail
Subject: $subject_encoded
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
EOF
# SMTP接続(TLS対応)
my $smtp = Net::SMTP->new($mailhost, Port => $mailport, Hello => 'localhost', Timeout => 30)
or die "Could not connect to SMTP server.";
$smtp->starttls() or die "Could not start TLS session.";
$smtp->auth($mail_username, $mail_password) or die "SMTP authentication failed.";
$smtp->mail($from_mail);
$smtp->to($to_mail);
$smtp->data();
$smtp->datasend($header);
$smtp->datasend($message);
$smtp->dataend();
$smtp->quit;
print "Content-type:text/html; charset=UTF-8\n\n";
print "メールを送信しました。\n";
SubjectをMIMEエンコードする。(ISO-2022-JP + Base64)
本文は、ISO-2022-JPに変換する。
Hello => 'localhost'
通常はこのままで動くが、明示的にサーバー名を記入しても良い。
STARTTLS非対応サーバー(Xサーバー系)の場合、以下を削除して平文で送信するしかない。
$smtp->starttls() or die "Could not start TLS session.";
もしくは、依存モジュールがない、Net::SMTPSを use lib して使う手もある。
メールヘッダーで日本語を使う場合はMIMEエンコードする
Subjectと同様に、メールヘッダー内で日本語を使う場合は、MIMEエンコードする必要がある。
(MIMEエンコードしなくても問題ない場合は多いが、メールアドレスは隠せない)
例えば、$from_mailを、メールアドレスではなく、
として送信したい場合は以下のようにする。
my $from_name = '風吹';
my $from_mail = 'fubuki@nb-style.info';
&Jcode::convert(\$from_name, 'jis', 'utf8');
$from_name_encoded = jcode($from_name)->mime_encode;
From: $from_name_encoded <$from_mail>
もし、To: や Reply-To: などでも日本語名を使いたい場合は、同じように mime_encode() を使えばOK。
SMTPメール送信サブルーチン
sub SendMail {
my ($from, $to, $subject, $body) = @_;
eval {
# 本文の文字コード変換
Jcode::convert(\$body, 'jis');
# 件名のエンコード(ISO-2022-JP + Base64)
Jcode::convert(\$subject, 'jis', 'utf8');
my $subject_encoded = jcode($subject)->mime_encode;
# ヘッダー生成
my $header = <<"EOF";
From: $from
To: $to
Subject: $subject_encoded
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
EOF
# SMTP送信処理
my $smtp = Net::SMTP->new($mailhost, Port => $mailport, Hello => 'localhost', Timeout => 30)
or die "SMTP接続失敗";
$smtp->starttls() or die "TLS開始失敗";
$smtp->auth($mail_username, $mail_password) or die "SMTP認証失敗";
$smtp->mail($from);
$smtp->to($to);
$smtp->data();
$smtp->datasend($header);
$smtp->datasend($body);
$smtp->dataend();
$smtp->quit;
};
if ($@) {
warn "メール送信エラー: $@";
return; # 偽(undef)を返す
}
return 1; # 真を返す(成功)
}
SendMail($from_mail, $to_mail, $subject, $message);
使用例
if (SendMail($from_mail, $to_mail, $subject, $message)) {
print "送信成功\n";
} else {
print "送信失敗\n";
}
Net::SMTPSを使った場合のサブルーチン
Net::SMTPSは、特別な依存モジュールがないので、use lib してやれば使える。
Net::SMTPと互換性が高いのでほぼそのままのコードで動くのが良い。
$smtp->starttls() を削除して、Net::SMTPS->new()時に doSSL => 'starttls' してやるだけ。
use FindBin;
use lib "$FindBin::Bin/lib";
use Net::SMTPS;
sub SendMail {
my ($from, $to, $subject, $body) = @_;
eval {
# 本文の文字コード変換
Jcode::convert(\$body, 'jis');
# 件名のエンコード(ISO-2022-JP + Base64)
Jcode::convert(\$subject, 'jis', 'utf8');
my $subject_encoded = jcode($subject)->mime_encode;
# ヘッダー生成
my $header = <<"EOF";
From: $from
To: $to
Subject: $subject_encoded
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit
EOF
# Net::SMTPS で TLS接続
my $smtp = Net::SMTPS->new(
$mailhost,
Port => $mailport,
Hello => 'localhost',
doSSL => 'starttls', # TLS有効化
Timeout => 30,
) or die "SMTP接続失敗";
$smtp->auth($mail_username, $mail_password) or die "SMTP認証失敗";
$smtp->mail($from);
$smtp->to($to);
$smtp->data();
$smtp->datasend($header);
$smtp->datasend($body);
$smtp->dataend();
$smtp->quit;
};
if ($@) {
warn "メール送信エラー: $@";
return; # 偽(undef)を返す
}
return 1; # 真を返す(成功)
}
doSSL の値について
| 値 | 内容 |
|---|---|
'starttls' |
ポート587向け(STARTTLS) |
'ssl' |
ポート465向け(SMTPS) |
undef |
暗号化しない |