読者です 読者をやめる 読者になる 読者になる

ChocoMemo

学んだことをメモがわりにアップしていきます!

Postfixでメールサーバを構築してメール受信をトリガーにプログラム実行して一部をSlackに送る

Slack Ruby Postfix

メールサーバを構築してメール受信ををトリガーにプログラムを実行する方法を簡単にまとめた。

やりたいこと

  • Postfixでメールサーバ構築
  • メール受信をトリガーにプログラム実行
  • メールの一部をSlackに送る

構成

  • EC2インスタンス(Amazon Linux)
  • Route53でドメイン設定
  • Postfix

EC2インスタンス

  • Amazon LinuxでEC2インスタンスをLaunchする。
  • セキュリティグループの設定は、sshでログインできることとメール使用するポートPOP3(110番ポート)及びにSMTP(25番ポート)を開けておく。

f:id:chocoken517:20160222235024p:plain

  • ドメイン設定にグローバルIPが必要になるので、Elastic IPを割り当てる

Route53

  • メールサーバのAレコードとMXレコードを追加
  • mail.example.com(Aレコード)のValueはメールサーバのIPアドレス

f:id:chocoken517:20160222235643p:plain

  • MXレコードのValueにはmail.example.com

f:id:chocoken517:20160222235752p:plain

Postfix

sshでサーバにログイン

$ ssh -i ~/.ssh/hogehoge.pem ec2-user@52.111.111.111

インストール

$sudo yum -y install postfix

設定

  • /etc/postfix/main.cfを設定する

メールサーバのホスト名(mail.example.com)を設定

myhostname = mail.example.com

メールアドレスで利用するドメイン(example.com)を設定

mydomain = example.com

ローカルから配信されたメールは、example.comのメールであると認識させるための設定

myorigin = $mydomain

メールサーバが自分宛のメールであると認識するためのドメイン名を設定

mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

ローカル以外から配信されたメールも受信する設定

inet_interfaces = all

VPC全体を信頼するネットワークとして設定

mynetworks = 10.0.0.0/16, 127.0.0.0/8

メールの保存形式をメールディレクトリ形式に設定。(user@example.cpmならば、/home/user/)のMaildirディレクトリに保存される

home_mailbox = Maildir/

SMTPサーバの認証設定。saslauthdを利用するための設定

smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $myhostname
smtpd_recipient_restrictions =
    permit_mynetworks
    permit_sasl_authenticated
    reject_unauth_destination

saslauthdの起動

$ sudo service saslauthd start
$ sudo chkconfig saslauthd on

postfixの起動

$ sudo alternatives --config mta
$ sudo service sendmail stop
$ sudo chkconfig sendmail off
$ sudo service postfix start
$ sudo chkconfig postfix on

ユーザの作成

メールアドレスとして利用するユーザ

$ sudo useradd user
$ sudo passwd user

メールディレクトリを作成

$ su - user
$ mkdir Maildir
$ exit

メール受信の確認

  • user@example.comにメールを送信し、/home/user/Maildirにファイルが追加されることを確認
  • 追加されない場合は、エラーメール(戻ってきている場合)や、ログ(/var/log/maillog)を確認

メール受信をトリガーにプログラム実行

実行プログラム作成

$ vi /home/user/hoge.rb
#! /usr/local/rbenv/shims/ruby
.
.
.

ファイルに実行権限あたえる

chmod a+x hoge.rb

設定

エイリアスに読み込ませるファイルを指定する

$ sudo vi /etc/aliases
user: :include:/home/user/alias

includeするファイルに実行コマンドを書く

$ vi /home/user/alias
"| /home/user/hoge.rb"

/etc/postfix/main.cfを編集

# Allowed to run :include: method in /etc/aliases
allow_mail_to_commands = alias, forward, include

変更を読み込みなおす

$ sudo newaliases
$ sudo  /etc/init.d/postfix reload

プログラム実行確認

  • user@example.comにメールを送信し、/home/user/hoge.rbが実行されていることを確認

メール内容の一部を取得してslackに通知

ここまで作ったので、slackに通知するのを作ってみた

gemをインストール

gem install slack-api
gem install mail

メールの一部をslackに送る

#! /usr/local/rbenv/shims/ruby
# coding: utf-8
#-------------------------------------------------
# Ruby script to get a mail via alias of postfix.
#-------------------------------------------------
require 'mail'
require 'slack'
require 'nkf'

class GetMail
  def execute
    Slack.configure do |config|
      config.token = 'slack token'
    end
    
    mail = Mail.new($stdin.read)
    row_body = mail.multipart? ? (mail.text_part ? mail.text_part.decoded : nil) : mail.body.decoded

    decoded_body = NKF.nkf('-w', row_body)
    body = body_to_pobody(decoded_body)

    subject = mail.subject.split('【日報】') 
    body = "#{subject[1]}\n ``` #{body}```"
    Slack.chat_postMessage(text: body, channel: '#nippo-zakkan', username: 'nippo-zakkan')
  end
  
  def body_to_pobody(body)
    items = body.split('-' * 73)
    return items[0] if items.count >= 1
    nil
  end
end

GetMail.new.execute