public
Last active

Ancient (2009) code for IMAP idle in Ruby

  • Download Gist
gistfile1.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
SERVER = 'imap.gmail.com'
USERNAME = 'XXX'
PW = 'XXX'
require 'net/imap'
require 'net/smtp'
require 'tmail'
require 'maruku'
 
def to_markdown(text)
Maruku.new(text).to_html
end
 
# Extend support for idle command. See online.
# http://www.ruby-forum.com/topic/50828
# but that was wrong. see /opt/ruby-1.9.1-p243/lib/net/imap.rb.
class Net::IMAP
def idle
cmd = "IDLE"
synchronize do
@idle_tag = generate_tag
put_string(@idle_tag + " " + cmd)
put_string(CRLF)
end
end
 
def say_done
cmd = "DONE"
synchronize do
put_string(cmd)
put_string(CRLF)
end
end
 
def await_done_confirmation
synchronize do
get_tagged_response(@idle_tag, nil)
puts 'just got confirmation'
end
end
end
 
class Remailer
attr_reader :imap
 
public
def initialize
@imap = nil
@smtp = nil
@mailer = nil
start_imap
end
 
def process
puts 'Processing!'
msg_ids = @imap.search(["SINCE", "25-Nov-2009", "TO", "XXX", "UNSEEN"])
puts 'Done with search!'
 
unless msg_ids.empty?
start_smtp
msg_ids.each do |msg_id|
mail = TMail::Mail.parse(@imap.fetch(msg_id, 'RFC822').first.attr['RFC822'])
print "Processing #{mail.subject}..."
mail.to = 'post@posterous.com'
mail.body = to_markdown(mail.body)
print ' marked down...'
@smtp.send_message mail.encoded, mail.from, [mail.to, 'XXX']
puts ' sent.'
 
@imap.store msg_id, '+FLAGS', [:Seen]
end
end
ensure
stop_smtp
end
 
def tidy
stop_smtp
stop_imap
end
 
def bounce_idle
# Bounces the idle command.
@imap.say_done
@imap.await_done_confirmation
# Do a manual check, just in case things aren't working properly.
process
@imap.idle
end
 
private
def start_imap
@imap = Net::IMAP.new SERVER, :ssl => true
@imap.login USERNAME, PW
@imap.select 'INBOX'
 
# Add handler.
@imap.add_response_handler do |resp|
if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
@imap.say_done
Thread.new do
@imap.await_done_confirmation
process
@imap.idle
end
end
end
 
process
@imap.idle
end
 
def stop_imap
@imap.done
end
 
def start_smtp
# Don't start more than once.
return unless @smtp.nil?
 
@smtp = Net::SMTP.new 'smtp.gmail.com', 465
@smtp.enable_tls
@smtp.start 'XXX', USERNAME, PW
end
 
def stop_smtp
# Don't stop if we haven't started.
return if @smtp.nil?
@smtp.finish
@smtp = nil
end
end
 
begin
Net::IMAP.debug = true
r = Remailer.new
loop do
puts 'bouncing...'
r.bounce_idle
sleep 10*60
end
ensure
r.tidy
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.