2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

この記事誰得? 私しか得しないニッチな技術で記事投稿!

Rubyでメールをシンプルに受信したい時

Last updated at Posted at 2023-07-02

TL;DR

require 'mail' # Railsは不要

# 接続情報の設定
imap_handler = Mail::IMAP.new(
  address: 'outlook.office365.com', user_name: '<username>', password: '<password>',
  port: 993, enable_ssl: true,
)
# 特定条件でメールを検索(ここの条件は`未読かつ添付ファイル付き`)
emails = imap_handler.find(read_only: true, keys: 'UNSEEN HEADER Content-Type multipart/mixed')

emails.size
=> 1
emails[0].subject
=> "添付ファイルテスト"
emails[0].attachments
=> [#<Mail::Part:70339964299180, Multipart: false, Headers: <Content-Type: application/pdf; name="test.pdf">, <Content-Transfer-Encoding: base64>, <Content-Disposition: attachment; filename="test.pdf">, <Content-ID: <f_ljl7cuad0>>, <X-Attachment-Id: f_ljl7cuad0>>]

はじめに

RubyやRailsでメール受信をキーワードで検索すると、ほとんどの検索結果がActionMailboxの使い方の説明になっています。
ActionMailboxはたしかに素晴らしい機能ですが、Rails6(以上)を使っていない方には導入コストが重過ぎです。仮にRails6(以上)を使っているとしても、MailgunMandrillのような有料の特定のサービスを契約しないと使えません。
実はかの有名Gem mikel/mail を使えば、OutlookやThunderbirdのように、既存のEmailアカウントからメールを読み取ることもできるのです。

方法解説

[非推奨] retriever_methodについて

GitHubのReadmeもGoogle先生の検索結果も、ほとんどは下記のようなコードが提示されています。

Mail.defaults do
  retriever_method :imap, address: 'imap.mailbox.org',
                          user_name: '<username>', password: '<password>',
                          port: 993, enable_ssl: true
end

しかし上記書き方だと、接続情報がグローバルに設定されて、複数のアカウントを扱う際は不便です。
Rubydocを読む、下記の書き方もできるとわかりました。

[推奨] IMAPで受信

imap_handler = Mail::IMAP.new(
  address: 'outlook.office365.com', user_name: '<username>', password: '<password>',
  port: 993, enable_ssl: true,
)
emails = imap_handler.find(
  what: :last, # 新しいほうのメールを取得する
  order: :desc, # 取得したメールは新しい順で並び替える
  count: 10, # 最大10メールを取得する
  read_only: true, # メールを取得する際、サーバーに「既読」をつかない(IMAPのみ)
  keys: ['FROM', 'microsoft'] # 差出人に「microsoft」の文字列があるか検索(IMAPのみ)
)
emails[0].subject
=> "Microsoft アカウントのセキュリティ情報の確認"
emails[0].from
=> ["account-security-noreply@accountprotection.microsoft.com"]

参考:

[非推奨] POP3で受信

pop3_handler = Mail::POP3.new(
  address: 'outlook.office365.com', user_name: '<username>', password: '<password>',
  port: 995, enable_ssl: true,
)
emails = pop3_handler.find(what: :first, count: 50, delete_after_find: true)

emails[0].subject
=> "新しい Outlook.com アカウントへようこそ"

参考: Class: Mail::POP3

余談

IMAPかPOP3か

結論言うと、IMAPが使える時は断然にIMAPを選ぶべきです、なぜなら「検索条件で一部のメールのみ取得」ができるです。

IMAPの検索条件について

添付ファイルを持つメールのみ抽出したい

こちらの記事によるとHEADER Content-Type multipart/mixedという条件が良さそうです。
一部画像付きメールでは.attachmentsで画像も反応してしまうので、multipart/mixedで抽出した方は「ザ添付ファイル」のみ検出できるのです。

複数条件で検索したい

IMAPの検索条件はポーランド記法を用いられています。

AND条件

デフォルトはANDになっているので、下記の書き方で十分です。

FROM microsoft SUBJECT Outlook

OR条件

予めORをつけるべきです。

OR FROM microsoft SUBJECT Outlook

条件が多い場合はその分ORも複数書きます。

OR OR BODY Android SUBJECT Outlook FROM microsoft

複合条件

OR (FROM microsoft SUBJECT Outlook) BODY Android

※ 差出人にmicrosoftを含み、かつ件名にOutlookが入っているメール、又は本文にAndroidが存在するメールを検索します。

参考: IMAP search requires parentheses

日本語で検索したい

残念ながら難しいそうです。Outlookの場合はsearch_charset: 'UTF-8'を設定すると、下記のエラーが返ってきました。

Net::IMAP::NoResponseError:  The specified charset is not supported.

なぜHotmail(Outlook)が例

Gmailさんも手軽で良さそうですが、プログラムで触る際に、アプリパスワードが必要です。アプリパスワードをONにするには、2段階認証が必要です。また、GmailはデフォルトPOP3もIMAPもオフにしているので、設定も面倒です。
現段階デモストレーション用にすぐ取得できるメールはHotmail(Outlook)のみです。(Yahooメールも携帯番号が必要となったので)

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?