Makefile: build all
[cmccabe-bin] / snarf_mail.rb
index a2490b1..a22e72f 100755 (executable)
@@ -17,11 +17,16 @@ class MyOptions
   def self.parse(args)
     opts = OpenStruct.new
     opts.mailboxes = Array.new
+    opts.delete_after = false
 
     # Fill in $opts values
     parser = OptionParser.new do |myparser|
       myparser.banner = "Usage: #{ File.basename($0) } [opts]"
       myparser.separator("Specific options:")
+      myparser.on("--delete-after", "-d",
+              "Delete emails after fetching them.") do |d|
+        opts.delete_after = true
+      end
       myparser.on("--username USERNAME", "-u",
               "Email account to fetch. (example: \
 RareCactus@gmail.com)") do |u|
@@ -84,27 +89,88 @@ def format_uid(uid)
   return sprintf("%006d", uid)
 end
 
+def get_sanitized_email_name(mailbox, uid)
+  msn = mailbox.dup
+  msn.gsub!(' ', '_')
+  msn.gsub!('/', '.')
+  return "#{msn}#{format_uid(uid)}"
+end
+
+def write_email_to_disk(mailbox, data)
+  arr = data[0].attr
+  filename = get_sanitized_email_name(mailbox, arr["UID"])
+  fp = File.open(filename, 'w')
+  fp.write(arr["RFC822.HEADER"])
+  fp.write(arr["RFC822.TEXT"])
+  fp.close
+end
+
 def snarf_mailbox(imap, mailbox)
-  imap.select(mailbox)
+  full_count = 0
+  first_time = true
   count = 0
-  total_count = 0
+
+  imap.select(mailbox)
   imap.search(["NOT", "DELETED"]).each do |message_id|
+    if (first_time == true) then
+      # Print a dot immediately after making first contact with the server.
+      # It is reassuring to the user.
+      printf(".")
+      STDOUT.flush()
+      first_time = false
+    end
     data = imap.fetch(message_id, [ "UID", "RFC822.HEADER", "RFC822.TEXT" ])
-    a = data[0].attr
-    filename = "#{mailbox}#{format_uid(a["UID"])}"
-    fp = File.open(filename, 'w')
-    fp.write(a["RFC822.HEADER"])
-    fp.write(a["RFC822.TEXT"])
-    fp.close
+    write_email_to_disk(mailbox, data)
+
     count = count + 1
-    total_count = total_count + 1
-    if (count > 10) then
-      count = 0
+    full_count = full_count + 1
+    if (count > 20)
+      # Print out a dot to signify progress
       printf(".")
       STDOUT.flush()
+      count = 0
+    end
+  end
+
+  puts "fetched: #{full_count} messages from #{mailbox}"
+end
+
+def snarf_and_delete_mailbox(imap, mailbox)
+  full_count = 0
+  first_time = true
+  while true
+    count = 0
+    msg_seqnos = Array.new
+
+    imap.select(mailbox)
+    imap.search(["NOT", "DELETED"]).each do |message_id|
+      if (first_time == true) then
+        # Print a dot immediately after making first contact with the server.
+        # It is reassuring to the user.
+        printf(".")
+        STDOUT.flush()
+        first_time = false
+      end
+      data = imap.fetch(message_id, [ "UID", "RFC822.HEADER", "RFC822.TEXT" ])
+      write_email_to_disk(mailbox, data)
+      count = count + 1
+      full_count = full_count + 1
+      msg_seqnos << data[0].seqno.to_i
+      #break if (count > 20)
+    end
+    if (count == 0) then
+      puts "fetched and deleted: #{full_count} messages from #{mailbox}"
+      return
     end
+
+    # Print out a dot to signify progress
+    printf(".")
+    STDOUT.flush()
+
+    # Delete messages
+    imap.store(msg_seqnos, "+FLAGS", [:Deleted])
+    imap.expunge
   end
-  puts "fetched #{total_count} messages from #{mailbox}"
 end
 
 # MAIN
@@ -125,7 +191,11 @@ when :list
   end
 when :snarf
   $opts.mailboxes.each do |mailbox|
-    snarf_mailbox(imap, mailbox)
+    if ($opts.delete_after == true)
+      snarf_and_delete_mailbox(imap, mailbox)
+    else
+      snarf_mailbox(imap, mailbox)
+    end
   end
 else
   raise "unknown action #{$opts.action}"