トップ 最新 追記   RSS 1.0 FEED  

Journal InTime


2011-09-02 (Fri) [長年日記]

_ [Ruby] IMAPサーバ上のメールのアーカイブ

最近はMUAとしてWanderlustを使っているのだが、メールをexpireして別のフォルダに移動する時に時間がかかり、また、いつ終わるかが予測できないのが不便だったため、簡単なRubyスクリプトで処理するようにしてみた。

$ imaparchive --mailbox work imap.netlab.jp 
Password: 
archiving 18360 messages to archive/work-20110602...
work:          100% |oooooooooooooooooooooooooooooooooooooooo| Time: 00:47:00
Done

といった感じで、3か月以上前のメール(既読、かつ、削除されてないもの)を、IMAP上の別のフォルダ(archive/<mailbox名>-<日付>)に移動する。内容は以下のとおり(Ruby 1.9前提、ぜんぜんテストしてないので注意)。

#!/usr/bin/env ruby

require "optparse"
require "net/imap"
require "io/console"
require "ostruct"
require "date"
require "pp"
require "progressbar"

def get_password
  io = IO.console
  io.print("Password: ")
  io.flush
  s = io.noecho {
    io.gets.chomp
  }
  io.puts
  return s
end

conf = OpenStruct.new
conf.user = ENV["USER"]
conf.mailbox = "INBOX"
conf.imap_options = {}
conf.archive_prefix = "archive/"
conf.months = 3
opt_parser = OptionParser.new do |opts|
  opts.banner = "Usage: imaparchive [options] <hostname>"

  opts.on("-u", "--user=USER", "Username") do |u|
    conf.user = u
  end
  opts.on("-m", "--mailbox=MAILBOX", "Mailbox name") do |mbx|
    conf.mailbox = mbx
  end
  opts.on("-a", "--archive-prefix=PREFIX", "Archive prefix") do |prefix|
    conf.archive_prefix = prefix
  end
  opts.on("-m", "--months=N", "Keep messages for N months") do |prefix|
    conf.months = 3
  end
  opts.on("-s", "--[no-]ssl", "Use imaps") do |val|
    conf.imap_options[:ssl] = val
  end
end
opt_parser.parse!
if ARGV.length == 0
  STDERR.print(opt_parser.help)
  exit 1
end
conf.host = ARGV[0]
conf.user = ENV["USER"]
conf.password = get_password

imap = Net::IMAP.new(conf.host, conf.imap_options)
imap.login(conf.user, conf.password)
imap.select(conf.mailbox)
date = Date.today << conf.months
uids = imap.uid_search(["BEFORE", Net::IMAP.format_date(date),
                        "SEEN", "NOT", "DELETED"])
if uids.empty?
  exit
end
archive_mailbox = conf.archive_prefix + File.basename(conf.mailbox) +
  date.strftime("-%Y%m%d")
unless imap.list("", archive_mailbox)
  imap.create(archive_mailbox)
end
puts "archiving #{uids.length} messages to #{archive_mailbox}..."
pbar = ProgressBar.new(conf.mailbox, uids.length)
uids.each do |uid|
  imap.uid_copy(uid, archive_mailbox)
  imap.uid_store(uid, "+FLAGS", [:Deleted])
  pbar.inc
end
pbar.finish
imap.expunge
puts "Done"

2011-09-06 (Tue) [長年日記]

_ [Ruby] RubyWorld Conference 2011

RubyWorld 2011 Speakers

台風の影響で無事開催できるか心配だったが、みなさんのご協力のおかげで今年も恙無くRubyWorld Conference*1開催終了することができた。 上の写真はスピーカーの記念写真だが、やむを得ない事情により写真撮影に参加できなかったあいざわさんの写真を合成してみた(問題があったら報告ください)。

RubyWorld ConferenceはRubyKaigiと違って大分ビジネス寄りのカンファレンスなんだけど、個人的にいかにもビジネスっぽいイベントにしたくないと思っている。セッションによってはスピーカーと聴衆の間に温度差を感じることもあるけど、将来的にその温度差を埋めていくことがRubyWorld Conferenceの役割なんじゃないかなという気がする。Rubyの普及・発展というのが、RubyアソシエーションやRubyWorld Conferenceの目的ではあるけれど、Rubyはたんなるツールなので、Rubyユーザが増えたり市場規模が広がったところで、Rubyに関わる人たちの生活が何らかの意味で豊かにならなければ意味がない。極端な話、強制されて嫌々Rubyを使うくらいだったら他の言語で開発した方がマシだし、 楽しく開発できていいソフトウェアができるならJavaだってHaskellだってPHPだっていいと思う。 参加者のみなさんが今後必ずしもRubyを使うとは限らないけれど、今後のソフトウェア開発に今回の各セッションで提示されたRuby的なやり方を何かしらの形で活かしていただけると嬉しい。

えーと、何か今一つまとまらないけど、参加いただいたみなさん、開催に協力いただいたみなさん、ありがとうございました。 来年もよろしくお願いします。

*1  「Ruby World」じゃなくて「RubyWorld」なので注意。


2011-09-09 (Fri) [長年日記]

_ [圏論] Conceptual Mathematics読書会

今日は、Article IIを原君が担当。ペースがなかなか上がらないので英語の音読をやめることに。結局ペースはあまり上がらず、Article IIの1で力尽きた。

演習で証明の問題が出てきて、やっと勉強会っぽい雰囲気になってきた。

p.43の

Exercise 3:
If f has an inverse, then f satisfies the two cancellation laws:
  (a) If f . h = f . k, then h = k.
  (b) If h . f = k . f, then h = k.
Warning: The following `cancellation law' is not correct, even if f has an inverse.
  (c) (wrong): If h . f = f . k, then h = k.

という演習で(c)の反例を考えていたら、小学生の時に先生から聞いた次のようなクイズを思い出した。

目の前に二本の別れ道があり、一方は天国に、他方は地獄に続いている。どちらの道にも鬼がいるが、一方の鬼は正直者で必ず正しい答えを返し、もう一方の鬼は嘘吐きで必ず間違った答えを返す。どちらの鬼が正直者かあなたは知らない。この状況で、どちらか一方の鬼に一回だけ質問をして、天国に続く道がどちらかを知るには、どのような質問をすればよいか。

この問題は、次のような問題に置き換えることができる。

BOOLを二つの要素trueとfalseをもつ集合とする。honestをBOOL上のidentity map、
lierをBOOL上のendomapであり、trueをfalseに、falseをtrueに移すものとする。
f . honest = g . lierとなる二つの写像fとgを示せ。
ここで、fとgはhonest又はlierのいずれかとする。

何かあまり面白くないし、よく考えるとこの答えは(c)の反例じゃなくて、cancellation lawが成り立つ例だな。

yesmanをBOOL上のendomapであり、trueとfalseをいずれもtrueに移すものとし、nomanをBOOL上のendomapであり、trueとfalseをいずれもfalseに移すものとすると、

yesman . lier = lier . noman, but yesman /= noman

というわけで、これが(c)の反例。