LaterMail 再修正
昨日、今日とまたいくつかのバグに対応しました。
ヘッダの順番依存
Message-Id: ヘッダの前に From: や To: などの重要なヘッダが来るものだと思い込んで作っていたのですが、そういう前提はまったくないようです。Message-Id: ヘッダがかなり最初の方に出てきて、そのあと、From: や To: が続くメールもたくさんあるようです。ですから、どの順序で出てきても大丈夫なようにプログラムを修正しました。
CC:、BCC:
CC: と BCC: については特に処理をしないでそのまま配達用のファイルに書いていたのですが、CC: や BCC: が書かれていると、sendmail がそのファイルを読んで処理するときに、CC: や BCC: 宛てにもメールを送ってしまいます。(当然ですね)
もし、"CC: 1@5-55.jp" となっていると、再配達したメールを送り先(root@5-55.jp です)へ1時間後に再配達することになり、延々と root@5-55.jp にメールが届くような事態になってしまいます。
ですので、CC: と BCC: についてはファイルに書かない(再配達しない)ようにしました。
latermail.rb
たぶんこれで最後だと思いますので、最新ソースを貼り付けておきます。
require 'time' require 'nkf' $KCODE = 'utf-8' class LaterMail # ファイル名(時刻+Message-Id)が決まるまで、@bufに溜めておく def initialize(mdir = '') @dir = mdir @buf = Array.new @io = nil end # 0 - 24 --> 指定時間をプラス # sunday - saturday --> 次の指定曜日までの日数をプラス(曜日以外は入ってこないが、入ってきてもプラスしないだけ) def add(dt, to) week = { 'sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday' => 3, 'thursday' => 4, 'friday' => 5, 'saturday' => 6 } t = Time.parse(NKF.nkf('-Jw -xm0', dt).gsub(/[年月日]/,'/')) if to if to =~ /\d/ t += to.to_i * 3600 elsif week[to] t += ]/).each { |wd| return wd if wd.include?('@') } nil end def putbuf(line) if @io @io.puts line else @buf << line end end def write ct = 0 from = to = boundary = dt = nil from_write = to_write = tof = ccf = false while line = gets if boundary && line.include?("--#{boundary}") if (ct += 1) == 2 putbuf(commercial(to">*1 end end if (mail = get_mail(line)) user = mail.split('@')[0] end case line when /^From /i, /^Return-Path:/i, /^Sender:/i from = mail putbuf(line) when /^X-Original-To:/i to = user putbuf("X-Original-To: #{from}") when /for\s*<.*@5-55\.jp>/i to = user putbuf(line) when /^Delivered-To:/i to = user # sendmailがINSERTするので書かない when /^Date:/i dt = add(line, to) putbuf("Date: #{dt.to_s}") when /^From:/i from_write = true putbuf(from_message) when /^To:/i to_write, tof, ccf = true, true, false putbuf("To: #{from}") when /^Cc:/i, /^Bcc:/i ccf, tof = true, false # Cc: Bcc: は処理しない when /^Content-Type: multipart/i boundary = line.split('"')[1] putbuf(line) when /^Message-Id:/i putbuf(from_message) if !from_write && from putbuf("To: #{from}") if !to_write putbuf(line) dt = add(Time.now.to_s, to) unless dt @io = open("#{@dir}#{dt.strftime('%Y%m%d%H%M%S')}.#{user}", "w") @buf.each { |bf| putbuf(bf) } else if tof || ccf next if line =~ /^\s/ tof = ccf = false end putbuf(line) end end unless boundary putbuf(commercial(to)) end end end if __FILE__ == $0 # cat mail > ruby latermail.rb lmail = LaterMail.new("/home/hml/Maildir/tmp/") lmail.write end
*1:6 - t.wday + week[to]) % 7 + 1) * 3600 * 24
t = Time.mktime(t.year, t.month, t.day, 7)
end
end
t
end
def from_message
"From: LaterMail