テキストをAmazon SNSで送りたいだけなのに。

こんにちは、ひるたんぬです。

前回のブログに続き醤油についての話題です。
※ 最近ふと思いつく小ネタが、たまたま醤油になってしまっているだけです。
「濃口醤油」と「淡口醤油」の違い、皆さんはご存知ですか?
色が違うというのは字面からイメージできますし、それに伴い製法や材料も異なるんだろうなぁ…とは想像できます。

では、どちらがしょっぱいのでしょうか?
私はてっきり「色が濃い濃口醤油の方がしょっぱいでしょ。漢字にも「濃」ってあるし。」と思っていたのですが、実は、淡口醤油の方がしょっぱいのです。

うすくちの塩分は、こいくちよりやや高め
うすくちしょうゆというと、塩分も低いと思われがちですが、実際はやや高めです。色や香りがつきすぎないよう、食塩をこいくちより1割ほど多く含むためです。
引用:しょうゆ情報センター「種類

しょうゆ情報センターなる機関が存在することを、この調査を通じて初めて知りました。

さて、今回は題名にもありますが、Amazon SNSでテキスト情報を送る際に何度が躓いた点があったので、その点と実際の解決策の一つをご紹介いたします。

やりたかったこと・試したこと

物理コンピュータ(Windows)で所有しているテキストファイルの内容を、Amazon SNSを利用してメールで送る、という作業です。テキストファイルのファイルサイズ(≒文字数)はファイルによって大きく異なります。

案① CLIでそのまま書き込む

後述する案では、メールの本文をカスタマイズできないため、最初はCLIの引数として、直接テキストファイルの内容を与えることを検討しました。
この場合、Amazon SNSのpublishコマンドにより実行が可能です。

aws sns publish --topic-arn "arn:aws:sns:[リージョン]:123456789012:[トピック名]" --subject "[題名]" --message "[本文]"

実際に送ってみましょう。

問題なく送れますね。実際に受信メールも確認してみます。

題名も本文も問題ないですね。

さて、ここからが本題です。
先程は本文が一文と短かったのですが、これが長くなってくるとどうでしょうか?

例えば、「吾輩は猫である」の一節を送りたいとき、ありますよね。うんうん。
先程と同じような手順で送ってみます。
本文をテキストファイルに保存し、本文内容を引数として格納したうえで、メール用に追記してから送ってみます。

本文は青空文庫(吾輩は猫である)より引用しております。
「吾輩は猫である」は著作権の切れている作品であるため、青空文庫のファイルの取り扱い規準を確認の上利用しております。
$contents = Get-Content "[読み込みたいテキストファイル]" -Raw
$message = "以下は夏目漱石の「吾輩は猫である」の一節です。`n`n" + $contents
aws sns publish --topic-arn "arn:aws:sns:[リージョン]:[アカウントID]:[トピック名]" --subject "おすすめ小説" --message $message
エラーが出てしまいました。
この原因は、AWSによるものではなく、PowerShellによるものです。
ピッタリ該当する公式のドキュメントは見つからなかったのですが、PowerShellなどで使える最大文字数は32,767文字とされています。
実際に検証もしてみましたが、32,767文字前後にてエラーが出ることを確認しました。
公式ではありませんが、redditでも同様の議論がされています。
今回送ろうとしていた「吾輩は猫である」の一節は、およそ5.6万文字のため、今回の制限に引っかかっているものと考えられます。

案② テキストファイルの内容の箇所を、ファイルパスとして引数で与える

案①の制限を踏まえ、少し手間ではありますが、メールの本文にカスタマイズしたファイルを別途作成し、そのファイルパスを引数として与えることを検討しました。

ただ手順としては、先程のコマンドを少し変更するのみです。

$contents = Get-Content "[読み込みたいテキストファイル]" -Raw
$message = "以下は夏目漱石の「吾輩は猫である」の一節です。`n`n" + $contents
Set-Content "[メール本文のテキストファイル]" $message
aws sns publish --topic-arn "arn:aws:sns:[リージョン]:[アカウントID]:[トピック名]" --subject "おすすめ小説" --message file://[メール本文のテキストファイル]

ここでの注意点としては、最後のmessageの引数の値の先頭に「file://」を忘れないことです。これがないと、パスそのものが送られてしまいます。

…さぁ、これでどうでしょうか。

送れていますね!実際のメールも見てみましょう。

しっかり届いていますね!

…ここまで来たら、全文送ってみたくなりますよね?
(メールで小説は読まない、というご意見は一旦受け付けないでおきます。)

同じようにやってみましょう。
(読み込ませるファイルが変わるだけなので、コマンド例は省略します。)

エラーが出ましたね。ただ、先程とは異なり、今度はAWS CLI側のエラーのようです。
こちらのエラーはAmazon SNSのクォータに抵触したために出たものになります。

メッセージの最大サイズは 262,144 バイト (256 KiB) です。…(後略)
引用:AWS 公式ドキュメント「Amazon Simple Notification Service エンドポイントとクォータ

キロバイト(KB)表記ではないんですね。。
今回送ろうとしていたファイルは約680KiBだったため、上記クォータに抵触していることが分かりました。

最終的な解決策

クォータのページを見てみると、以下のような記載がありました。

(前略)…256 KiB を超えるメッセージを発行するには、Amazon SNS 拡張クライアントライブラリを確認します。最大ペイロードサイズは2GBです。
引用:AWS 公式ドキュメント「Amazon Simple Notification Service エンドポイントとクォータ

ただ、こちらはJavaやPythonにて実行するものと記載があり、今回はPowerShell(AWS CLI)のみで完結させたかったため、この手順は使いません。

拡張クライアントライブラリを使うことによって、2GBまでのメールを送ることが可能になります。
ここはGiBではなく、GBなんですね…謎です。

今回はメールの受信者が、テキストファイルの内容を確認できることがゴールだったため、「S3にテキストファイルをアップロードした後に署名付きURLを発行、そのURLをAmazon SNSにて送付」という手段を取ることにしました。

下準備

上記を実現するためには、テキストファイルを格納するためのS3バケットが必要です。
設定はデフォルトで問題ありません。

作成されたS3にライフサイクルを設定しておくと、送信するファイルが溜まり続ける点を解消できます。

実行

一番肝となるのが、署名付きURLです。

バケットポリシーを更新せずに、Amazon S3 内のオブジェクトへの時間制限付きのアクセス権を付与するには、署名付き URL を使用できます。…(後略)
引用:AWS公式ドキュメント「署名付き URL を使用したオブジェクトのダウンロードおよびアップロード

これにより、メールの受信者に対して、期限を設けてファイルを共有することができます。

設定可能な時間制限は、署名付きURLの発行方法により異なります。
コンソールから作成する場合は1分~12時間、CLIやSDKの場合は1秒~7日間まで設定可能です。
参考:AWS公式ドキュメント「署名付き URL を使用したオブジェクトのダウンロードおよびアップロード
AWS CLIを使う場合は、以下で署名付きURLを発行可能です。
aws s3 presign "[S3URI]" --expires-in [有効期限(秒)]
有効期限を設定しない場合は、既定で1時間有効の署名付きURLが発行されます。
今回は10分(600秒)に設定します。
これを使って「吾輩は猫である」の全文を送ってみましょう。
aws s3 cp "[送りたいテキストファイル]" "s3://[バケット名]"
$presignurl = aws s3 presign "s3://[バケット名]/[テキストファイル名]" --expires-in 600
$message = "以下は夏目漱石の「吾輩は猫である」の全文です。`n`n全文はこちら!`n" + $presignurl
aws sns publish --topic-arn "arn:aws:sns:[リージョン]:[アカウントID]:[トピック名]" --subject "おすすめ小説" --message $message

無事に送れました!一安心…
では、同じくメール本文を確認してみます。

メールが届いており、最後に全文のリンクが付いていますね!
こちらにアクセスしてみると…

呪文のように表示されました。しっかり見れますね。
(もちろん保存も可能です。)

ちなみに有効期限(10分)が経過した後はどうなるのでしょうか?

アクセスが拒否され、閲覧ができなくなっていることが確認できました。
そのため、受信者が閲覧できる時間をしっかり設定する必要がありますね。

まとめ

今回遭遇・調査したクォータ(制限)をまとめると以下のようになります。
S3を用いることで、より大きなテキストファイルを送ることが可能になりますね。

おわりに

AWSのクォータだけでなく、PowerShellのコマンドにも制限があるなど、様々な制約があるということを痛感する出来事でした。
…でも、Amazon S3の保存容量(データ総量)は事実上無制限なんですよね。。どう実現しているのでしょう🤔

Amazon S3 に格納可能なデータの総量とオブジェクトの数には制限はありません。
引用:AWS「Amazon S3 よくある質問

タイトルとURLをコピーしました