質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.44%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

Q&A

解決済

2回答

2634閲覧

[rails] メールのencodeについて教えてください。

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

0グッド

0クリップ

投稿2019/11/05 13:40

前提・実現したいこと

当方、プログラミングを始めて3か月の初心者です。

現在、rails 5.2.3でメールの自動送信機能を実装しようとしております。
production環境はheroku&sendgridを利用しています。

rails チュートリアルを参考にメール本文を日本語にして、
下記のようなテストコードを書いたところ、
エンコードに関するエラーが発生しており、困っております。
どのようにテストコードを書き換えるべきか、またはエンコードの設定をすべきか
ご教示のほど、よろしくお願いします。

ruby

1class UserMailerTest < ActionMailer::TestCase 2 3 test "アカウント開設用URLのご案内" do 4 user = users(:michael) 5 user.activation_token = User.new_token 6 mail = UserMailer.account_activation(user) 7 assert_equal "アカウント開設用URLのご案内", mail.subject 8 assert_equal [user.email], mail.to 9 assert_equal ["noreply@yoursite.com"], mail.from 10 assert_equal [ENV['YAHOOMAIL_ADRESS']], mail.bcc 11 assert_match user.email, mail.body.encoded 12 assert_match user.activation_token, mail.body.encoded 13 assert_match CGI.escape(user.email), mail.body.encoded 14 end 15end

発生している問題・エラーメッセージ

Failure: UserMailerTest#test_アカウント開設用URLのご案内 [/home/vagrant/workspace/app/test/mailers/user_mailer_test.rb:13]: Expected /michael@example.com/ to match # encoding: US-ASCII # valid: true "\r\n----==_mimepart_5dc16b84311c1_e422b0a01ce39946426b\r\nContent-Type: text/plain;\r\n charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n\r\(省略)==\r\n\r\n---- ==_mimepart_5dc16b84311c1_e422b0a01ce39946426b\r\nContent-Type: text/html;\r\n charset=UTF-8\r\nContent-Transfer-Encoding: base64\r\n\r\(省略)==\r\n\r\n---- ==_mimepart_5dc16b84311c1_e422b0a01ce39946426b--\r\n". bin/rails test test/mailers/user_mailer_test.rb:5

現在の対応

railsにはdefaultでhtmlとtextの2種類のメール本文がありますが、
htmlは<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />と設定されているようですので、対策として現在は下記のようなコードを書いています。

ruby

1class UserMailerTest < ActionMailer::TestCase 2 3 test "アカウント開設用URLのご案内" do 4 user = users(:michael) 5 user.activation_token = User.new_token 6 mail = UserMailer.account_activation(user) 7 assert_equal "アカウント開設用URLのご案内", mail.subject 8 assert_equal [user.email], mail.to 9 assert_equal ["noreply@yoursite.com"], mail.from 10 assert_equal [ENV['YAHOOMAIL_ADRESS']], mail.bcc 11 assert_match user.email, 12 mail.text_part.body.to_s.encode("UTF-8") 13 assert_match user.email,mail.html_part.body.encoded 14 assert_match user.activation_token, 15 mail.text_part.body.to_s.encode("UTF-8") 16 assert_match user.activation_token,mail.html_part.body.encoded 17 assert_match CGI.escape(user.email), 18 mail.text_part.body.to_s.encode("UTF-8") 19 assert_match CGI.escape(user.email),mail.html_part.body.encoded 20 end 21end

疑問点・補足

①railsの ApplicationMailerはdefaultでcharset=UTF-8と
設定されているようですが、送信時に
UTF-8を一端ASCII文字(7bit文字)のbase64にエンコードして、
再度、受信側でデコードするのでしょうか?
②なぜtext形式のみこのようになっているのでしょうか?
③どのようにテストコードを書き換えるべきでしょうか。
assert_equrlの期待値をbase64に変換する?

なお、gmailやyahooメールで受信したところ、文字化け等はありませんでした。

以上よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

送信時に

UTF-8を一端ASCII文字(7bit文字)のbase64にエンコードして、
再度、受信側でデコードするのでしょうか?

昔はSMTPで7ビットしか転送できることが保証されていなかった(そして現在もそのようなメールサーバが残っている危険がある)ため、8ビット目のあるデータについては、Base64やQuoted-printableでエンコードして、7ビット以下に落とすこととなります。

②なぜtext形式のみこのようになっているのでしょうか?

HTMLメールも同様にエンコードされますが、中身にアクセスしようとした段階でデコードされます。

③どのようにテストコードを書き換えるべきでしょうか。

assert_equrlの期待値をbase64に変換する?

テストコードで、わざわざmail.body.encodedを取得しているのが原因かと思われます。mail.body.decodedとしてはどうでしょうか。

投稿2019/11/05 23:31

maisumakun

総合スコア145360

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/11/06 08:13 編集

ご返信ありがとうございます。色々調べており、返信が遅くなりました。 申し訳ございません。以下の2つ質問があります。 ①メール本文はもともと8bitデータ(utf-8等)で構成され、送信時に7bitデータ(ASCII文字)へ変換、開封時に8bitデータに戻ると理解しました。そうなると、 `mail.body.decoded` : UTF-8へ変換? `mail.body.encoded `: ASCII文字へ変換 となるのでしょうか。 ② `assert_match user.email,mail.body.decoded`のようにコードを変えて、再度`メールアドレスが、メール本文に含まれているかどうかをテスト`をしたのですが、以下のエラーが発生しました。 ``` UserMailerTest#test_アカウント開設用URLのご案内 [/home/vagrant/workspace/app/test/mailers/user_mailer_test.rb:13]: Expected /michael@example.com/ to match "". ``` mail.bodyだけでUTF-8になるのかと考え、 `assert_match user.email,mail.body` ともしてみたのですが、 `no implicit conversion of Mail::Body into String`とエラーが発生しましたので、やはり何かしらencodeは必要なようです。 もう一度何かテスト方法をご教授願えますでしょうか。
退会済みユーザー

退会済みユーザー

2019/11/06 11:28

assert_match user.email,mail.body.decodedではテストが通らなかったのですが、下記のような記入をしたところ、原因が不明ですが、テストが通りました。 ``` assert_match user.email,mail.html_part.body.decoded assert_match user.email,mail.text_part.body.decoded ``` なぜなのでしょうか。
退会済みユーザー

退会済みユーザー

2019/11/07 01:39

その後、`assert_match user.email,mail.body.raw_source`や`assert_match user.email,mail.body.to_s`等も試してみましたが、`assert_match user.email,mail.body.decoded`と同様のエラーとなりました。 最終的には assert_match user.email,mail.html_part.body.encoded assert_match user.email,mail.text_part.body.encoded としましたが、いまいち理解ができておりません。 どなたかご教示いただけますと幸いです。
guest

0

assert_match user.name, mail.body.encoded assert_match user.activation_token, mail.body.encoded assert_match CGI.escape(user.email), mail.body.encoded

# user.nameが本文に含まれている assert_match user.name, mail.text_part.body.encoded assert_match user.name, mail.html_part.body.encoded # user.activation_tokenが本文に含まれている assert_match user.activation_token, mail.text_part.body.encoded assert_match user.activation_token, mail.html_part.body.encoded # 特殊文字をエスケープしたuser.mailが本文に含まれている assert_match CGI.escape(user.email), mail.text_part.body.encoded assert_match CGI.escape(user.email), mail.html_part.body.encoded

に変更してみてください。
参考: https://rakuda3desu.net/rakudas-rails-tutorial11-2/

投稿2021/02/09 13:18

nekoyama141592

総合スコア53

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.44%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問