PSLブログ

ヨシナシゴトヲツヅリマス

Perl+WWW::CurlでSendGridからメールを送ってみた(2)

前回の続き。

blog.psl.ne.jp

 WWW::Curlを使う

curlコマンドにJSONデータを直接指定してメールが送られることは分かったので、今度は、PerlCurlインターフェースであるWWW::Curlを使って送ってみる。

もともと、curlに明るくなく、WWW:Curlのドキュメントはcurlを知っている前提で書かれていたため、とてもわかりにくかったが、結果分かったことを整理する。

  • 今回やりたかったことは、WWW::Curl::Easyでできる。
  • WWW::Curl::Easy->newでインスタンス生成。
  • curlのコマンドオプションに相当するものは、すべてsetoptで値をセットできる。
    CURLOPT_URL…--urlオプション
    CURLOPT_POST…真の値をセットすると--request POSTと同じ。
    CURLOPT_HTTPHEADER…--headerオプション。配列のリファレンスで渡す。
    CURLOPT_POSTFIELDS…--dataオプション。JSONデータを指定する。
  • performで実行。
use strict;
use warnings;
use WWW::Curl::Easy;

my $curl = WWW::Curl::Easy->new;

$curl->setopt(CURLOPT_URL, "https://api.sendgrid.com/v3/mail/send");
$curl->setopt(CURLOPT_POST, 1);
$curl->setopt(CURLOPT_HTTPHEADER, [
	"Authorization: Bearer [API KEY]",
	"Content-Type: application/json",
]);
$curl->setopt(CURLOPT_POSTFIELDS, [JSON DATA]);

my $retcode = $curl->perform;

print $retcode;
$ perl wwwcurl.pl
0$

preformの返り値は0だと正常終了、それ以外はエラーコードとなる。よく見たら、ドキュメントにサンプルコードが載っていた。

http://search.cpan.org/~szbalint/WWW-Curl-4.17/lib/WWW/Curl.pm#WWW::Curl::Easy

とりあえず、これで、curlコマンドと同等の処理をPerlでできた。

sendmail_sendgrid - JSONデータの部分を動的に生成する

今までの方法だと、JSONデータ部分がまったく手動で作る必要があり(手っ取り早くPHPjson_encodeを使ったりした)、汎用性がないので、データ部分を動的に生成して送るようにする。SendGridのオプションは猛烈にたくさんあるが、私が今までに使っていたパラメータだけを使う前提とした。つまり、送信先アドレス、件名、送信元アドレス、送信元名、本文(プレーンテキスト)のみとした。

use strict;
use WWW::Curl::Easy;
use MIME::Base64;
use JSON;
use Unicode::Japanese;

sub sendgrid_send {
	my %opt = (
		"CURLOPT_URL" => "https://api.sendgrid.com/v3/mail/send",
		"api_key" => "[API_KEY]",
	@_);
	my $json = {
		"personalizations" => [
			{
				"to" => [
					{
						"email" => $opt{"sendto"},
					}
				],
				"subject" => sendmail_enc_b64($opt{"subject"}),
			}
		],
		"from" => {
			"name" => sendmail_enc_b64($opt{"sendfrom_name"}),
			"email" => $opt{"sendfrom"}
		},
		"content" => [
			{
				"type" => "text/plain",
				"value" => Unicode::Japanese->new($opt{"mailbody"})->getu,
			}
		],
	};
	if ($opt{"sendto_name"}) {
		$json->{"personalizations"}->[0]->{"to"}->[0]->{"name"} = sendmail_enc_b64($opt{"sendto_name"});
	}
	if (ref $opt{"cc"} eq "ARRAY") {
		for my $cc(@{$opt{"cc"}}) {
			push(@{$json->{"personalizations"}->[0]->{"cc"}}, { "email" => $cc });
		}
	}
	if (ref $opt{"bcc"} eq "ARRAY") {
		for my $cc(@{$opt{"bcc"}}) {
			push(@{$json->{"personalizations"}->[0]->{"bcc"}}, { "email" => $cc });
		}
	}
	my $curl = WWW::Curl::Easy->new;
	$curl->setopt(CURLOPT_URL, "https://api.sendgrid.com/v3/mail/send");
	$curl->setopt(CURLOPT_POST, 1);
	$curl->setopt(CURLOPT_HTTPHEADER, [
		qq|Authorization: Bearer $opt{"api_key"}|,
		"Content-Type: application/json",
	]);
	$curl->setopt(CURLOPT_POSTFIELDS, JSON->new->ascii(1)->utf8(1)->encode($json));
	my $retcode = $curl->perform;
	die $retcode if $retcode;
}
sub sendmail_enc_b64 {
	my $subject = shift;
	return "=?utf-8?B?" .encode_base64($subject, "") . "?=";
}
1;
# 1通ずつ送る
require "lib_sendmail_sendgrid.pl";
sendgrid_send(
	"sendto_name" => "山田太郎",
	"sendto" =>  q|sendto@example.com|,
	"subject" =>  "メール送信テスト",
	"sendfrom_name" =>  "送信元名",
	"sendfrom" =>  q|sendfrom@example.com|,
	"mailbody" => "これはメール送信のテストです。これはメール送信のテストです。これはメール送信のテストです。これはメール送信のテストです。",
);

 これでメールを送ることができた。SendGridのAPIでは、メールヘッダにマルチバイト文字を使っても何も処理してくれない(生のまま)ので、MIMEエンコードの処理を入れた。

次回へ続く。