Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use "net"
- use "net/ssl"
- use "lib:c"
- primitive CAPABILITY
- primitive LOGIN
- primitive SELECT
- primitive IDLE
- primitive LIST
- primitive CLOSE
- primitive LOGOUT
- type Command is (CAPABILITY | LOGIN | SELECT | IDLE | LIST | CLOSE | LOGOUT)
- primitive CONNECTING
- primitive CONNECTED
- type State is (CONNECTING | CONNECTED)
- actor Main
- new create(env:Env) =>
- let getter = GetMail.create()
- var idler = Idler(env,getter,"gmail", "imap.gmail.com", "me@example.com", "password", "\"[Gmail]/All Mail\"")
- idler.connect()
- class ResponseBuilder is TCPConnectionNotify
- let _buffer:Buffer = Buffer
- let _idler:Idler
- let _env:Env
- new iso create(env:Env, idler:Idler) =>
- _idler = idler
- _env = env
- fun ref connected(conn: TCPConnection ref) =>
- _env.out.print("connected")
- _idler.connected(conn)
- fun ref connect_failed(conn: TCPConnection ref) =>
- _env.out.print("connect_failed")
- _idler.connect_failed()
- fun ref auth_failed(conn: TCPConnection ref) =>
- _env.out.print("auth_failed")
- None
- fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
- _buffer.append(consume data)
- try
- while true do
- _idler.got_line(_buffer.line())
- end
- end
- fun ref connecting(conn: TCPConnection ref, count: U32) =>
- _env.out.print("connecting")
- None
- fun ref closed(conn: TCPConnection ref) =>
- _env.out.print("closed")
- _idler.closed()
- None
- actor Idler
- let _account:String
- let _server:String
- let _user:String
- let _password:String
- let _folder:String
- var _conn:(TCPConnection | None) = None
- let _env:Env
- let _getmail:GetMail
- var _count:U32 = 0
- var _state:State = CONNECTING
- var _cmd:(Command | None) = None
- var _idling:Bool = false
- var _fetched:Bool = false
- new create(env:Env,getmail:GetMail,account:String,server:String, user:String, password:String, folder:String) =>
- _account = account
- _server = server
- _user = user
- _password = password
- _folder = folder
- _env = env
- _getmail = getmail
- fun cmd_name(cmd:(Command | None)): String =>
- match cmd
- | CAPABILITY => "CAPABILITY"
- | LOGIN => "LOGIN"
- | SELECT => "SELECT"
- | IDLE => "IDLE"
- | LIST => "LIST"
- | CLOSE => "CLOSE"
- | LOGOUT => "LOGOUT"
- | None => "NONE"
- else ""
- end
- be send_command(cmd:Command, data:(String | None)) =>
- try
- _count = _count + 1
- _cmd = cmd
- let c:String = match cmd
- | CAPABILITY => "CAPABILITY"
- | LOGIN => "LOGIN"
- | SELECT => "SELECT"
- | IDLE => "IDLE"
- | LIST => "LIST"
- | CLOSE => "CLOSE"
- | LOGOUT => "LOGOUT"
- else error
- end
- let tail:String = match data
- | (let s:String) => " " + s + "\r\n"
- | None => "\r\n"
- else ""
- end
- let s = _count.string() + " " + c + tail
- _env.out.print("Sending: " + s)
- (_conn as TCPConnection).write(s)
- end
- be connect() =>
- try
- let ctx = SSLContext.set_client_verify(false)
- let ssl = ctx.client(_server)
- _conn = TCPConnection(SSLConnection(ResponseBuilder(_env, this), consume ssl), _server, "993".string())
- else
- _env.out.print("Failed to connect")
- end
- be connected(conn:TCPConnection) =>
- _env.out.print("Server connected")
- be connect_failed() =>
- _env.out.print("Connect failed")
- be closed() =>
- _env.out.print("Closed: " + _account)
- be got_line(s:String) =>
- match _state
- | CONNECTING =>
- _state = CONNECTED
- on_connected(s)
- | CONNECTED =>
- on_command(_cmd, s)
- end
- be on_connected(s:String) =>
- _env.out.print("connected: " + s)
- send_command(LOGIN, _user + " " + _password)
- be on_command(c:(Command | None), s:String) =>
- try
- if s(0) == '*' then
- on_command_untagged(c, s)
- elseif s(0) == '+' then
- on_command_continue(c, s)
- else
- try
- let offset = s.find(" ")
- let tagg = s.substring(0, offset - 1).u32()
- if s.at("OK", offset + 1) then
- on_command_end(c, tagg, s.substring(offset + 3, -1))
- else
- on_command_tagged(c, tagg, s.substring(offset + 1, -1))
- end
- else
- on_command_unknown(c, s)
- end
- end
- else
- on_command_unknown(c, s)
- end
- be on_command_untagged(c:(Command | None), s:String) =>
- _env.out.print("on_command_untagged: " + cmd_name(c) + ": " + s)
- match c
- | LOGOUT => None
- | IDLE =>
- let exists:Bool = try
- s.find("EXISTS")
- true
- else
- false
- end
- let recent:Bool = try
- s.find("RECENT")
- true
- else
- false
- end
- if not _fetched and (exists or recent) then
- _fetched = true
- try
- (_conn as TCPConnection).write("DONE\r\n")
- end
- _getmail.update(_account)
- end
- if s.at("* BYE", 0) then
- try
- (_conn as TCPConnection).dispose()
- _env.out.print("Reconnecting to " + _account)
- connect()
- end
- end
- else
- try
- if s.at("* BYE", 0) then
- (_conn as TCPConnection).dispose()
- _env.out.print("Reconnecting to " + _account)
- connect()
- end
- end
- end
- be on_command_tagged(c:(Command | None), tagg:U32, s:String) =>
- _env.out.print("on_command_tagged: " + tagg.string() + " " + cmd_name(c) + ": " + s)
- be on_command_continue(c:(Command | None), s:String) =>
- _env.out.print("on_command_continue: " + cmd_name(c) + ":" + s)
- match c
- | IDLE => _idling = true
- end
- be on_command_end(c:(Command | None), tagg:U32, s:String) =>
- _env.out.print("on_command_end: " + tagg.string() + " " + cmd_name(c) + ": " + s)
- match c
- | LOGIN => send_command(SELECT, _folder)
- | SELECT => send_command(IDLE, None)
- | IDLE => _idling = false
- _fetched = false
- // send_command(CLOSE, None)
- send_command(IDLE, None)
- | CLOSE => send_command(LOGOUT, None)
- | LOGOUT => try (_conn as TCPConnection).dispose() end
- end
- be on_command_unknown(c:(Command | None), s:String) =>
- _env.out.print("on_command_unknown: " + cmd_name(c) + ": " + s)
- actor GetMail
- let system:System = System.create()
- be update(account:String) =>
- system.run("offlineimap -u ttyui -o -a " + account)
- system.run("notmuch new")
- system.run("notify-send -t 2000 \"Mail retrieved for account " + account + "\"")
- actor System
- be run(s:String) =>
- @system[None](s.cstring())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement