アドベントカレンダークリスマスイブ担当koniaです。
自己紹介
この会社に入り本格的にエンジニアとして働き出して早1年目、まだまだ足りないもの感じながらしごかれて最後には星になります。そんな若輩者の拙い文章ですが、ちょっとした時間に読んでいただき1つでも為になったら心中でワルツが踊り出します。
ふとした依頼
さて、自己紹介はこれくらいにして最近サークルの後輩からこういう依頼が来ました。
「最近イベントとかするんですけど、そのメールを自動で返信してくれるシステム的なの欲しいんですよ…」
「サクッと作れないですかね」
お、これは作るしかないと。いろんなサービスが今や横行していますが、なんかちょっとエンジニアチックに作りたいなと思って色々みていました。
そこで見つけたのが、fetchmailというOSSです。
リモートのメールサーバからメールを取得し、 これをローカル (クライアント) マシンの配送システムに転送します。 受け取ったメールは普通のメールユーザエージェントで扱うことができます。
https://linuxjm.osdn.jp/html/fetchmail/man1/fetchmail.1.html
こちらを参照
と言ったようにメールを扱うOSSがありましたのでこちらを使用していきます。
自動メール送信
OSS : fetchmail
OS : Ubuntu 18.04
言語 : Ruby
OS、言語選定については後輩がわかるものに揃えた為、特に理由があったわけではないので他でもできます。
fetchmail設定ファイルについて
#86400秒(24時間)ごとに起動する
set daemon 86400
defaults
uidl
no mimedecode
no rewrite
# メールを渡すプログラムのフルパス
mda /home/name/process/textProcessing.rb
keep
#メールサーバの情報
poll mail.example.jp protocol POP3
username example@example.jp
password xxxxxxxx
ssl
特定の時間がきた場合、textProcessing.rbが起動するようになってます。
次にtextProcessing.rbのコードを示します。
このコード内部で行なっているのはイベント登録に来たメールからデータを取得し、CSV吐き出しにしています。(今回はDBを用いていません。)
#! /usr/bin/ruby
# coding: utf-8
#-------------------------------------------------
# Ruby script to get a mail via alias of postfix.
#-------------------------------------------------
require 'mail'
require 'csv'
class GetMail
def initialize
#csvの格納場所
@out_csv = "/home/konia/deskTop/mail.csv"
end
# イベント登録した際の学生情報メールを改行とコロンによって情報を配列化
def execute
CSV.open(@out_csv, "a") do |f|
mail = Mail.new($stdin.read.gsub(/\r?\n/,"\r\n"))
mail_sender = mail.from.first
mail_subject = mail.subject.to_s
mail_body = mail.body.to_s
mail_body = mail_body.force_encoding("utf-8")
mail_array = mail_body.scan(/:\s*([^\r]*)/)
if mail_array.length >= 7 && mail_sender == "hoge@gmail.com" && mail_subject.scan("event").empty?
date = mail_array[6].to_s.scan(/(\d+[^\(])/)
time = date[3]
date.slice!(3,2)
mail_array[6] = date.join
mail_array[7] = time
# 配列化した情報をcsvで取り込む
f << mail_array.flatten
end
end
rescue => e
$stderr.puts "[#{e.class}] #{e.message}"
e.backtrace.each{|trace| $stderr.puts "\t#{trace}"}
exit 1
end
end
exit unless $0 == __FILE__
GetMail.new.execute
そこから次はメールを送信する際の処理を下記に示します。
CSVから特定のデータを取得し、それを整形し特定の日付になった際にメール送信を行う。
#! /usr/bin/ruby
# coding: utf-8
#-------------------------------------------------
# Ruby script to get a mail via alias of postfix.
#-------------------------------------------------
require 'mail'
require 'csv'
require 'time'
class TextProcess
def initialize
@@from_mail = '送信者'
@@to_mail = '受信者'
@csv = "/home/hashi/deskTop/mail.csv"
end
# csvファイルから時間帯のデータを取ってき、イベント3日前と前日についての学生をまとめる
def mailProcess
student_info = {}
flg_3 = i = 0
CSV.foreach(@csv) do |cs|
date = Time.strptime(cs[6].to_s,'%Y年%m月%d日')
today = Time.now
three_date_before = date - 259200
two_date_before = date - 172800
one_date_before = date - 86400
if three_date_before <= today && today < two_date_before
flg_3 = 1
student_info[i] = cs
i += 1
elsif one_date_before <= today && today < date
sendMail(2,cs)
end
end
if flg_3 == 1
processed_text = textProcess(student_info)
sendMail(1,processed_text)
end
end
# 上記のイベント前に合致する学生情報をメールの本文に作成する
def textProcess(tmp)
i = 0
info = ""
for j in 0...tmp.length do
info << "氏名:#{tmp[j][0].to_s}\nメールアドレス:#{tmp[j][4].to_s}\n会場:#{tmp[j][5].to_s}\n日時:#{tmp[j][6].to_s+tmp[j][7].to_s}\n\n\n"
i += 1
end
return info
end
# 作成したメールについて送信を行う
def sendMail(flg,tmp)
if flg == 2
mail = Mail.new do
from @@from_mail
to @@to_mail
cc @@to_mail2
bcc @@to_mail3
subject "前日のお知らせです"
body "氏名:#{tmp[0].to_s}\nメールアドレス:#{tmp[4].to_s}\n会場:#{tmp[5].to_s}\n日時:#{tmp[6].to_s+tmp[7].to_s}"
end
elsif flg == 1
mail = Mail.new do
from @@from_mail
to @@to_mail
cc @@to_mail2
bcc @@to_mail3
subject "3日前のお知らせです"
body tmp
end
end
mail.charset = 'utf-8'
mail.delivery_method(:smtp,
address: "送信サーバ",
port: ポート番号,
domain: "ドメイン名",
authentication: :login,
user_name: "メールアドレス",
password: "送信サーバのパスワード",
enable_starttls_auto: false
)
mail.deliver
end
end
exit unless $0 == __FILE__
TextProcess.new.mailProcess
以上となります。OSS使って書いてみると色々と気づくものもありますが今の時代なんでもそろってるからそっちを使った方が楽なのは間違いないですね😇