IT・技術研修ならCTC教育サービス

サイト内検索 企業情報 サイトマップ

研修コース検索

コラム

Ruby & Rails

CTC 教育サービス

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  OpenStack  システムトラブルシュート 

第7回 RubyでのメールはMailライブラリにおまかせ! (松永紘) 2013年9月

 Webアプリケーションの開発をしていると、メールの送受信を扱う機会があると思います。RailsにはActionMailerというライブラリがありますが、今回はその中でも使われているMailライブラリ(*1)をご紹介いたします。
 尚、本コラムは以下の環境で動作確認を行っています。

  • Ruby : 1.9.3
  • Mail : 2.5.4

 まずはインストールを行いましょう(*2)。以下のコマンドを実行します。

> gem install mail

 正常に終了すればインストールの完了です。Rubyスクリプト上で使用するには「require "mail"」でロードします。

メールの作成

 Mailクラスをnewすると、メールのひな型となるMail::Messageオブジェクトが生成されます。当該オブジェクトのsetterを利用して値を設定していきます。

require "mail"

mail = Mail.new mail.from = "from@example.co.jp" mail.to = "to@example.co.jp" mail.subject = "subject text" mail.body = "body text"
# newのブロック内で値を設定することも可能 mail = Mail.new do from "from@example.co.jp" to "to@example.co.jp" subject "subject text" body File.read("body.txt") end
# 任意のヘッダを設定 mail["Comments"] = "Some comments"
# SMTPのエンベロープも設定可能 mail.smtp_envelope_from = "envelope_from@example.co.jp" mail.smtp_envelope_to = "envelope_to@example.co.jp"
<添付ファイル>

 添付ファイルを設定するには、add_fileメソッドもしくはattachmentsメソッドを使用します。attachmentsを用いる場合には添付するデータそのものを渡す必要がありますが、add_fileの場合はファイルパスでOKです。

# カレントディレクトリのpicture.jpgを添付
mail.add_file = "./picture.jpg"

# カレントディレクトリのpicture.jpgをphoto.jpgとして添付 mail.attachments["photo.jpg"] = File.binread("./picture.jpg")
# add_fileはnewのブロック内でも使用可能 mail = Mail.new do add_file "./picture.jpg" end
<HTML形式>

 text/plainなメールだけではなく、text/htmlを含むmultipart/alternativeなメールを作成することもできます。

mail = Mail.new do
  # text/plain部分
  text_part do
    body "ruby mail text/plain"
  end

# text/html部分 html_part do body "<h1>ruby mail text/html</h1>" end end
# ブロック外で定義する場合はMail::Partクラスを使用 text_plain = Mail::Part.new do body "ruby mail text/plain" end
text_html = Mail::Part.new do body "<h1>ruby mail text/html</h1>" end
mail.text_part = text_plain mail.html_part = text_html
<既存データの取り込み>

 ローカルにあるファイルや文字列からMail::Messageオブジェクトを生成することができます。

# カレントディレクトリのmail.emlを取り込み
local_mail = Mail.read("./mail.eml")

# 標準入力で受けたメール文字列の取り込み string_mail = Mail.new(STDIN.read)
メールの送信

 作成したメールオブジェクトのdeliverメソッドを呼び出すことで、メールの送信が行えます。

mail = Mail.new do
  from    "from@example.co.jp"
  to      "to@example.co.jp"
  subject "subject text"
  body    File.read("body.txt")
end

mail.deliver
# Mailクラスの特異メソッドdeliverを使って、以下のようにも記述可能 Mail.deliver do from "from@example.co.jp" to "to@example.co.jp" subject "subject text" body File.read("body.txt") end

 デフォルトでは以下の条件でメールを送信します。

  • 送信メソッド : SMTP
  • 接続先アドレス : localhost
  • 接続ポート : 25
  • 認証 : なし

 接続先などを変更するには、delivery_methodを使用します。

mail.delivery_method(:smtp,
  address:        "example.co.jp",
  port:           587,
  domain:         "example.co.jp",
  authentication: :login,
  user_name:      "<user_name>",
  password:       "<password>"
)
mail.deliver

 第1引数にはsmtpやsendmailといった送信メソッド、第2引数には送信メソッドに対応する送信オプションを設定します。
 以下にSMTP使用時の送信オプションを示します。

オプション 内容 初期値
address 接続先アドレスを設定 localhost
port 接続ポートを設定 25
domain HELOドメイン名を設定 localhost.localdomain
authentication 認証方法を設定
  • nil:認証なし
  • plain:PLAIN
  • login : LOGIN
  • cram_md5 : CRAM-MD5
nil
user_name 認証時のユーザ名を指定 nil
password 認証時のパスワードを指定 nil
ssl(tlsでも可) true設定時、SMTPSを使用 nil
enable_starttls_auto true設定時、STARTTLSが使用可能な場合にSTARTTLSを使用 true
openssl_verify_mode OpenSSLの検証モードを設定(*3 nil

 また、Mail.defaultsを用いることでデフォルトの挙動を変更することができます。

Mail.defaults do
delivery_method(:smtp,
    address:        "example.co.jp",
    port:           587,
    domain:         "example.co.jp",
    authentication: :login,
    user_name:      "<user_name>",
    password:       "<password>"
)
end

# example.co.jpサーバ宛てにメールを送信 Mail.deliver do from "from@example.co.jp" to "to@example.co.jp" subject "subject text" body File.read("body.txt") end
メールの受信

 受信用のメソッドを使用することで、メールサーバからメールを取得することができます。

Mail.all   # 全件取得
Mail.first # 先頭1件取得
Mail.last  # 末尾1件取得

# オプションを指定してメールを受信することも可能 Mail.find(count: 5, order: :desc, what: :all)

 findに設定できる条件は、以下のようなものがあります。

オプション 内容 初期値
count 取得件数を設定 10
order 取得順を設定
  • asc:昇順
  • desc:降順
asc
what 取得方法を設定
  • first:先頭1件
  • last:末尾一件
  • all:全件
first
delete_after_find true設定時、取得後にメールをサーバ上から削除 false

 また、デフォルトでは以下の条件でメールサーバへの接続を行います。

  • 送信メソッド : POP3
  • 接続先アドレス : localhost
  • 接続ポート : 110
  • 認証 : なし

 接続先などを変更するにはretriever_methodを使用します。

Mail.defaults do
retriever_method(:pop3,
    address:        "example.co.jp",
    port:           110,
    user_name:      "<user_name>",
    password:       "<password>"
)
end

Mail.all # example.co.jp上のメールを受信

 送信時と同様に、第1引数にpop3やimapといった受信メソッド、第2引数に対応するオプションを設定します。
 以下にPOP3使用時の受信オプションを示します。

オプション 内容 初期値
address 接続先アドレスを設定 localhost
port 接続ポートを設定 110
user_name 認証時のユーザ名を指定 nil
password 認証時のパスワードを指定 nil
enable_ssl true設定時、SSLを使用 false
メールの解析

 メールから件名や本文などといった情報を取り出すには、まず前述の「既存データの取り込み」を行ってMail::Messageオブジェクトを生成します。当該オブジェクトにはsetterに対応するgetterがありますのでそれらを用いて情報を取得します。
 尚、ヘッダ外の情報を取得する際はdecodedを使用します。

mail = Mail.read("./mail.eml")

mail.from.first mail.to.first mail.subject mail.date
# ヘッダ外(本文など)はdecodedを使用 mail.body.decoded
# 任意のヘッダ情報を取得 mail.header["X-Mailer"]
# エンベロープの情報を取得 mail.envelope_from mail.envelope_date

 また、multipartなメールから情報を取得することもできます。

mail = Mail.read("./multipart_mail.eml")
mail.multipart?  #=> true

mail.text_part.decoded # text/plain部分の取得 mail.html_part.decoded # text/html部分の取得
# 添付ファイルへのアクセス mail.attachments.first.filename mail.first.mime_type
# 添付ファイルの取得 File.open("picture.jpg", "w+b") do |f| f.write(mail.attachments.first.body.decoded) end
[補足] ISO-2022-JP

 現在の主要なメールクライアントはほとんどUTF-8に対応していると思いますが、それでも何らかの事情でISO-2022-JPのメールを扱わないといけないケースもあるでしょう。Rubyの場合ISO-2022-JPはダミーエンコーディング(*4)となっていることもあり、そのままでは扱いづらいです。
 そのような際はmail-iso-2022-jp(*5)というライブラリをお勧めします(*6)。詳しくはmail-iso-2022-jpのGitHubページをご覧ください。

まとめ

 以上、長くなってしまいましたがMailライブラリの説明でした。GitHub上にあるmailのREADMEにも詳しい説明がございますのであわせてご覧ください(*7)。

 メールそのものの作成や解析を自前で行うのは、かなり骨の折れる作業だと思います。本ライブラリはメールの送受信も行えますが、そういった部分にこそより力を発揮するのではないでしょうか。Rubyでメールを扱う際には是非Mailライブラリを使ってみてください。

 それでは、Enjoy Ruby!

注釈

*1https://github.com/mikel/mail

*2:Rails3以降をお使いであれば、ActionMailerの依存パッケージとしてインストールされていると思います。

*3:詳しくはRubyリファレンスマニュアルOpenSSLをご覧ください。http://doc.ruby-lang.org/ja/1.9.3/class/OpenSSL=3a=3aSSL=3a=3aSSLContext.html#I_VERIFY_MODE--3D

*4http://doc.ruby-lang.org/ja/1.9.3/doc/spec=2fm17n.html#encoding

*5https://github.com/kuroda/mail-iso-2022-jp

*6:現在プルリクエスト中みたいですので、そのうちmail本体にマージされるかもしれません。

*7:本コラムを書くにあたっても参考にさせていただきました。

 


 

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  OpenStack  システムトラブルシュート