はじめに

普段メールを使っていますか?
最近はLINEなどのメッセージングアプリが使われるようになった影響で、あまりメールを使わなくなった方も多いでしょう。
とはいえ、ビジネスではまだまだメールが使われ続けており、今後も当分はメールがなくなることはないでしょう。
メールは人の手で送られることもありますが、それよりも機械的に送られるメールが多いと思われます。
この記事では、Ruby初心者の方向けに、Rubyからメールを送信する方法を解説していきます。
あなたも自分のメールアドレスを使って試してみましょう。

メールの正体

私たちは何気なくメールを使っていますが、メールがどのようなものか考えたことはありますか?
メールは、基本的に単なるテキストデータに過ぎません。
それをSMTPというプロトコル(通信規約)で送信しています。
このため、手順としてはメールの形式でテキストデータを作成し、それをSMTPプロトコルで送信すればよいということになります。
Rubyには、さまざまなメールライブラリが提供されており、低レベルな処理を隠蔽してくれます。
しかし、それではあまり勉強にならないので、ここでは標準ライブラリの” net/smtp”を使ってメールを送信してみましょう。

メールヘッダパートの作成

メールは、大きく分けて「ヘッダパート・本文パート・添付ファイルパート」の3つの要素で構成されています。
ここでは、それぞれの要素を作成する関数を作成していきましょう。
まずは、メールヘッダパートからです。次の例をみて下さい。
例:

require 'net/smtp'
require 'base64'
BOUNDARY = "mailpart"
def get_header(from, to, subject)
  header =  "Date: " + Time.now.strftime("%a, %d %b %Y %X %z") + "\n"
  header << "From: #{from}\n"
  header << "To: #{to}\n"
  header << "Subject: #{subject}\n"
  header << "MIME-Version: 1.0\n"
  header << "Content-Type: multipart/mixed; boundary=#{BOUNDARY}\n"
  header << "\n"
end

先頭で、このサンプルコードで使用するすべてのライブラリを読み込んでいます。
メールを送信するためのSMTPライブラリ(net/smtp)と添付ファイルをエンコードするためのBase64ライブラリ(base64)です。
定数BOUNDARYは、メールの各パートを区切るための任意の文字列です。
「get_header関数」では、メールヘッダパート文字列を作成して返します。
メールヘッダパートには、送信者や受信者、件名などの情報が含まれています。
複雑そうに見えますが、すべては単なる文字列に過ぎません。

メール本文パートの作成

次に、メール本文パートを作成する関数を作ります。
次の例をみて下さい。
例:

def get_body(text)
  body =  "Content-Type: text/plain; charset=iso-2022-jp\n"
  body << "Content-Transfer-Encoding: 7bit\n"
  body << "\n"
  body << text
  body << "\n"
end

「get_body関数」では、メール本文パートを規定の形式で構成して返します。
実際のメール本文は、引数textで受け取っています。

添付ファイルパートの作成

次に、添付ファイルパートを作成する関数を作ります。
それには、次のようにします。
例:

def get_attachment(file_path)
  file =  "Content-Type: application/octet-stream;\n"
  file << " name=\"#{File.basename(file_path)}\"\n"
  file << "Content-Transfer-Encoding: base64\n"
  file << "Content-Disposition: attachment;\n"
  file << " filename=\"#{File.basename(file_path)}\"\n\n"
  file << Base64.strict_encode64(File.open(file_path).read) + "\n"
end

「get_attachment関数」は、添付ファイルパートを文字列として構成して返します。
ファイル本体は、Base64エンコードして文字列としてメールに含めます。そのままでは送信できません。

メール全体の構成

最後に、これまで作成してきた3つの関数を使って、メール全体を構成する関数を作ります。
次の例をみて下さい。
例:

def get_mail(from, to, subject, body, file_path)
  mail =  get_header(from, to, subject)
  mail << "--#{BOUNDARY}\n"
  mail << get_body(body)
  mail << "--#{BOUNDARY}\n"
  mail << get_attachment(file_path)
  mail << "--#{BOUNDARY}--\n"
end

「get_mail関数」は、ヘッダー・本文・添付ファイルの順で、各パートをバウンダリー文字列で区切りながら結合しています。
複数の添付ファイルを送信することも可能です。

メールの送信

それでは、いよいよメールを送信してみましょう。
メールを送信するためには、SMTPサーバーが必要です。
ここでは、GmailのSMTPサーバーを利用しています。
なお、事前にセキュリティの設定で「安全性の低いアプリの許可」を有効にしておく必要があります。
テストアカウントを使うか、終わったら設定を戻しておきましょう。
コードは次のようになります。
例:

FROM = "任意のメールアドレス"
TO = "任意のメールアドレス"
SUBJECT = "テストメール"
BODY = <<TEXT
テストメールです
添付ファイルも付いています
TEXT
FILE_PATH = "test.txt"
SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 587
DOMAIN = "smtp.gmail.com"
ACCUNT = "ACCUNT" #Gmailのアカウント
PASSWORD = "PASSWORD"   #Gmailのパスワード
smtp = Net::SMTP.new(SMTP_SERVER, SMTP_PORT)
smtp.enable_starttls
smtp.start(DOMAIN, ACCUNT, PASSWORD, :login) do |s|
    s.send_mail(get_mail(FROM, TO, SUBJECT, BODY, FILE_PATH), FROM, TO)
end

GmailのSMTPサーバーからメールを送信するには、ユーザー認証が必要です。
そのため、あなたのGmailのアカウントとパスワードを設定する必要があります。
パスワードの取り扱いには注意して下さい。
これでメール送信プログラムは完成です。
FROMとTOに、任意のメールアドレスを入力してテストメールを送信してみましょう。

まとめ

うまくメールを送れるようになりましたか?
自動的にメールを送れるようになれば、さまざまな用途に活用できます。
いろいろなアイディアを考えて、自作のアプリケーションに組み込んでみましょう。
あなたはメールをどんなことに活用しますか?