メールを受信する(テスト編)

■テストコード
まず、mail.txtを作成。参照:http://i.loveruby.net/ja/projects/tmail/doc/basics.html


▼最初にプロンプトからrunnerを使ってみよう。
C:\Rails\app\trunk>ruby script/runner 'MailHandler.receive(STDIN.read)' < mail.txt

※この時、mail.txtはRAILS_ROOTにあるとする。この例ではapp/trunk/mail.txt


ユニットテスト

 def test_receive
    MailHandler.receive(File.new(File.dirname(__FILE__) + '/../mail_template/mail.txt',"r").read)
  end


■参考
http://d.hatena.ne.jp/omochist/20060828
http://www.fdiary.net/ml/rails/msg/883
http://www.fdiary.net/ml/rails/msg/884
http://www.kbmj.com/~shinya/rails_seminar/slides/#(49)

Always Be Happy

プログラミングをやっていると、ストレスが溜まることもあるだろう。
しかし、そこでストレスを感じてはいけない。何事もそうだ。ストレスを感じでいいことなど、1つもない。
そういう時は、「障害がないゲームはつまらない」と思い楽しめ。簡単にクリアできるRPG等つまらない。


そして、常に余裕を持て。間違っても、周りに「ストレス感じているな。めちゃ大変そう」と思わせるな。
そうできてこそ、プロなのだ。

アプリでメールを受信する(連携編)

では、実際にサーバーと連携して、アプリでメールを受信します。
作戦としては、sendmailでメールを受け取って、外部プログラムにパイプする。という感じ。


まずはメールの設定。ここでは、前提として、sendmailで外部からメールを送信できる。受信できる
という状態にあるとしましょう。

受信できない場合は、DNSが通ってなかったりします。通ってる場合は、locah_lost_domains
ファイルに取得したサーバードメインを書きましょう。
そしたら、account_name@domain_nameのメールに対して外からメールを送れます。

sendmailの設定に関してはこちらを参考にしてください。↓

http://www.stackasterisk.jp/tech/systemConstruction/sendmailSec01_01.jsp
http://hp.vector.co.jp/authors/VA003991/linux/smtp/sendmail.html


注意としては、.mcファイル内の一文をコメントアウトする記述があるが、似たような文があるので、
過ってそれをコメントアウトしないこと。
以前設定したとき、
DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnlをコメントアウトするはずが、
DAEMON_OPTIONS(`Port=smtp, Name=MTA')dnlをアウトしてしまった。


しかし、これでやったら上手くいきませんでした。次の様にはまりました。
メールを送れるが、エラーも返ってこないし、アプリも起動しない。これは次の様な原因です。
http://www.puni.net/~mimori/sendmail/qgroup.html
実際、ps xしたら次の様になっていました。
20352 ? S 0:00 sendmail: ./l8E8TgtL020350 from queue
この場合、タイムアウトするまで返ってきません。3時間くらいすると返ってきます。

 **********************************************
     **      THIS IS A WARNING MESSAGE ONLY      **
     **  YOU DO NOT NEED TO RESEND YOUR MESSAGE  **
 **********************************************

 The original message was received at Thu, 13 Sep 2007 18:33:42 +0900
 from atg-asm1.t-com.ne.jp [218.219.54.53]

    ----- Transcript of session follows -----
 <root@live.example>... Deferred: Connection timed out with c13-ss-2-lb.cnet.com.
 Warning: message still undelivered after 4 hours
 Will keep trying until message is 5 days old


本当は、mxファイル等を調べ、DNSを引けているかとかを調べるのですが、この時は、.mcファイル
の誤った部分をコメントアウトしたおかげで、ローカルホストに対して接続できなくなり、ローカル内
ですらメールが送れなくなっていたのです。
当然、外部メールを受け、アプリに渡すなど不可能な話でした。これは次の様にすると簡単に分かります。


telnet localhost 25


中からこれを叩いても接続できませんでした。
先ほどでてきたDAEMON_OPTIONS(`Port=smtp, Name=MTA')dnlのコメントアウトをといて、m4コンパイル
すればなおりました。


結局、僕が使っているsendmailの.mcファイルには上記(Addr='127.0.0.1')が含まれた部分が見つからなかった
ので、コメントアウトしていない。


さて、ではメールをアプリに渡すことを考えます。
アプリに渡す場合、/etc/mail/aliasesを編集する方法もあります。
http://www.techscore.com/tech/OtherTech/rubyonrails/4.html
しかし、この通りに書いてみると次の様な事態になりました。


▼送っても次の様なメッセージが返ってくる
※******は、メールを受けるサーバーのドメイン


The original message was received at Fri, 14 Sep 2007 18:39:59 +0900
from mx1.mail-filter.nifty.com [202.248.236.202]

----- The following addresses had permanent fatal errors -----
'| /usr/bin/ruby /var/www/app/trunk/script/runner
"NotifyMailer.deliver_confirm_entry_mailaddress('test')"'
(reason: 550 5.1.1 User unknown)
(expanded from: )

----- Transcript of session follows -----
550 5.1.1 '| /usr/bin/ruby /var/www/app/trunk/script/runner
"NotifyMailer.deliver_confirm_entry_mailaddress('test')"'... User unknown


これについてはこちら
http://www.fiberbit.net/member/trouble/trouble_2_2.html
https://omakase.jp/member/mag/200411.html


その時、aliasesファイルには以下のように書いていました
aiasファイル中のユーザーね
root@****: '| /usr/bin/ruby /var/www/app/trunk/script/runner "NotifyMailer.deliver_confirm_entry_mailaddress('test')"'


この中の、root@****をrootだけにしたりすると、また変化します。


なんか、ユーザー指定の部分 root: の部分がややこしかったので、aliasesを使うのはやめました。
そこで、次の方法を使います。


http://blog.g-up.com/hidenori_goto/?s=2&b=10662


これの場合は、ホームディレクトリに.forwardを作成し、次のように記述するだけです。
'| /usr/bin/ruby /var/www/app/trunk/script/runner "NotifyMailer.deliver_confirm_entry_mailaddress('test')"'
と思ったら、こけた。Unknown Hostエラー。
どうやら、 "と'の混在で上手く行っていないらしい。
しかし、実はこのコードは完全テスト用のコードだったので本番用に変更。
上のコードの場合、メールを受けたら起動するというだけで、受け取ったメールには何ら依存していない。
なので、コードを次の様に変更(これが本当に試したかったやつ)


"| /usr/bin/ruby /var/www/app/trunk/script/runner 'MailHandler.receive STDIN.read'"


このコードはメールを受け、内部で処理をする。おそらく、送り主に新たなメールを返すだろう。
NotifyMailerは、その返信に使われる。
受信メールから情報(あて先等)をとり、それをNotifyMailerに送るといった感じ。


※本番環境の場合は、script/runnerの後に、 -e productionを付ける。でないと、開発環境のDBを見たり
してしまうので注意。
http://brass.to/blog/rails_batch_2.html


以上である。エラーなどを省けば、以下の2つの記事を参照するとこの機能は実現できる。
http://www.techscore.com/tech/OtherTech/rubyonrails/4.html
http://blog.g-up.com/hidenori_goto/?s=2&b=10662
但し、rubyが/usr/bun/loca/rubyに入っていたりする場合は、そこを変えるのを忘れずに。
この例では、rubyが/ur/bin/rubyにインストールされている。


また、エラーした時に欠かせないのが次のファイルであった。
/var/log/maillog

なお、サーバーのメールの設定がデフォルトでSMTP経由になっている場合は、environment系ファイルに、
ActionMailer::Base.delivery_method = :sendmailを書かないとエラーする。