Later Mail を作る(続き)
昨日の続きです。昨日はメールを受信して返信用メールを保存するところまでできましたので、今日は時間がきたメールを送信するところを作ります。
第2ステップ:メール送信
実はこちらの方がはるかに簡単です。「5秒間隔でディレクトリの一覧をみて、時間がきたファイルを Postfix sendmail に渡す」ということだけしかやっていません。50行ほどですので、このページの最後にソースを貼り付けておきます。(注意:今後プログラムの改変が行われたとしても、ここには反映しません)
プログラム本体
require 'daemonize' include Daemonize daemonize() sl = SendLater.new("/home/hml/Maildir/tmp/") loop do sl.monitor sleep 5 end
本体はこれだけです。ずっと動かす前提なので、こちら(→ http://grub.ath.cx/daemonize/ )をインクルードして daemon にしてあります。(Ubuntu起動時に自動起動させるためには update-rc.d で登録してやらないといけないんですが、まだ試してみていません)
動作させるときのパーミッションには注意してください。作成されたファイルは Postfix ユーザ(nogroup)の所有権でリードオンリーになっているはずですから、このサンプルのまま動かすのであれば、「sudo nice ruby sendlater.rb」とするなど、一工夫必要です。(こんなものを管理者権限で動かしたくないということであれば、File.chmod でコネコネやるか、書き込むときのパーミッションを工夫してください)
ファイル監視
def monitor Dir.glob("#{@dir}*").each do |path| name = File.basename(path) dt = name.split('.')[0] # 8日以上前は消す if dt < timef(Time.now - 3600*24*8) File.delete(path) elsif dt < timef(Time.now) if send(path) File.delete(path) else # 次は10分後に実施 File.rename(path, add(name, 600)) end end end end
やってることは 8日以上古いファイルは消してしまうことと、現在時刻より古いファイルを送信することです。送信が成功(system レベルで true が返ってくる)すれば、対象ファイルを削除して、失敗したらファイル名を 10分後のファイル名に書き換えます。
sendlater.rb
追記:'$'、バッククォートが入ったファイル名をエスケープしてしまい、not found になってしまっていたため、system("sendmail -t < '#{path}'") にシングルクォートを追加しました。
require 'time' class SendLater def initialize(mdir = '') @dir = mdir end def timef(t) t.strftime("%Y%m%d%H%M%S") end # name "20080825173033.20080825083051.76E9B2908D" def add(name, sec) @dir + timef(Time.parse(name.split('.')[0]) + sec) + '.' + name.split('.')[1..-1].join('.') end def send(path) system("sendmail -t < '#{path}'") end def monitor Dir.glob("#{@dir}*").each do |path| name = File.basename(path) dt = name.split('.')[0] if dt < timef(Time.now - 3600*24*8) # 8日以上前は消す File.delete(path) # puts "old delete=#{path}" elsif dt < timef(Time.now) if send(path) File.delete(path) # puts "send OK delete=#{path}" else File.rename(path, add(name, 600)) # 次は10分後に実施 # puts "send NG rename=#{path} - #{add(name, 600)}" end end end end end if __FILE__ == $0 # ruby sendlater.rb require 'daemonize' include Daemonize daemonize() sl = SendLater.new("/home/hml/Maildir/tmp/") loop do # puts Time.now.to_s sl.monitor sleep 5 end end