トップ «前の日記(2011-08-27 (Sat)) 最新 次の日記(2011-09-06 (Tue))» 編集   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"