6 # Copies mail from an IMAP account
9 # http://ruby-doc.org/stdlib/libdoc/net/imap/rdoc/index.html
19 opts.mailboxes = Array.new
21 # Fill in $opts values
22 parser = OptionParser.new do |myparser|
23 myparser.banner = "Usage: #{ File.basename($0) } [opts]"
24 myparser.separator("Specific options:")
25 myparser.on("--username USERNAME", "-u",
26 "Email account to fetch. (example: \
27 RareCactus@gmail.com)") do |u|
30 myparser.on("--list-folders", "-l",
31 "List the IMAP folders that are present.") do |a|
32 raise "can only specify one action" if (opts.action)
35 myparser.on("--snarf", "-S",
36 "Copy mail to the current directory.") do |a|
37 raise "can only specify one action" if (opts.action)
40 myparser.on("--box [MAILBOX]", "-b",
41 "Act on a given mailbox. You may specify -b more than once for \
42 multiple mailboxes.") do |a|
45 myparser.on("--server [SERVER]", "-s",
46 "Email server to use") do |u|
52 raise "must specify an action" unless opts.action
53 raise "must give a username" unless opts.username
54 raise "must give a server" unless opts.server
59 # Get a password from STDIN without echoing it.
60 # This is kind of ugly, but it does work.
61 def get_password(prompt)
62 shell_cmds = 'stty -echo && read password && echo ${password}'
66 pipe = IO.popen(shell_cmds, "r") do |pipe|
69 echo_status = $?.exitstatus
72 if (echo_status != 0) then
73 raise "get_password: error executing: #{shell_cmds}"
79 # We don't know how to deal with non-numeric UIDs. Best just to leave them
81 return uid if (uid =~ /[^0123456789]/)
83 # Pad numeric uids out to 6 digits
84 return sprintf("%006d", uid)
87 def snarf_mailbox(imap, mailbox)
91 imap.search(["NOT", "DELETED"]).each do |message_id|
92 data = imap.fetch(message_id, [ "UID", "RFC822.HEADER", "RFC822.TEXT" ])
94 filename = "#{mailbox}#{format_uid(a["UID"])}"
95 fp = File.open(filename, 'w')
96 fp.write(a["RFC822.HEADER"])
97 fp.write(a["RFC822.TEXT"])
100 total_count = total_count + 1
107 puts "fetched #{total_count} messages from #{mailbox}"
112 $opts = MyOptions.parse(ARGV)
113 rescue Exception => msg
114 $stderr.print("#{msg}.\nType --help to see usage information.\n")
118 password = get_password("Please enter the password for #{$opts.username}:")
119 imap = Net::IMAP.new($opts.server, 993, true)
120 imap.login($opts.username, password)
123 imap.list("", "*").each do |mbl|
127 $opts.mailboxes.each do |mailbox|
128 snarf_mailbox(imap, mailbox)
131 raise "unknown action #{$opts.action}"