Advertisement
Guest User

Untitled

a guest
Feb 5th, 2016
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.81 KB | None | 0 0
  1. use "net"
  2. use "net/ssl"
  3. use "lib:c"
  4.  
  5. primitive CAPABILITY
  6. primitive LOGIN
  7. primitive SELECT
  8. primitive IDLE
  9. primitive LIST
  10. primitive CLOSE
  11. primitive LOGOUT
  12. type Command is (CAPABILITY | LOGIN | SELECT | IDLE | LIST | CLOSE | LOGOUT)
  13.  
  14. primitive CONNECTING
  15. primitive CONNECTED
  16. type State is (CONNECTING | CONNECTED)
  17.  
  18. actor Main
  19. new create(env:Env) =>
  20. let getter = GetMail.create()
  21. var idler = Idler(env,getter,"gmail", "imap.gmail.com", "me@example.com", "password", "\"[Gmail]/All Mail\"")
  22. idler.connect()
  23.  
  24. class ResponseBuilder is TCPConnectionNotify
  25. let _buffer:Buffer = Buffer
  26. let _idler:Idler
  27. let _env:Env
  28.  
  29. new iso create(env:Env, idler:Idler) =>
  30. _idler = idler
  31. _env = env
  32.  
  33. fun ref connected(conn: TCPConnection ref) =>
  34. _env.out.print("connected")
  35. _idler.connected(conn)
  36.  
  37. fun ref connect_failed(conn: TCPConnection ref) =>
  38. _env.out.print("connect_failed")
  39. _idler.connect_failed()
  40.  
  41. fun ref auth_failed(conn: TCPConnection ref) =>
  42. _env.out.print("auth_failed")
  43. None
  44.  
  45. fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
  46. _buffer.append(consume data)
  47. try
  48. while true do
  49. _idler.got_line(_buffer.line())
  50. end
  51. end
  52.  
  53. fun ref connecting(conn: TCPConnection ref, count: U32) =>
  54. _env.out.print("connecting")
  55. None
  56.  
  57. fun ref closed(conn: TCPConnection ref) =>
  58. _env.out.print("closed")
  59. _idler.closed()
  60. None
  61.  
  62. actor Idler
  63. let _account:String
  64. let _server:String
  65. let _user:String
  66. let _password:String
  67. let _folder:String
  68. var _conn:(TCPConnection | None) = None
  69. let _env:Env
  70. let _getmail:GetMail
  71. var _count:U32 = 0
  72. var _state:State = CONNECTING
  73. var _cmd:(Command | None) = None
  74. var _idling:Bool = false
  75. var _fetched:Bool = false
  76.  
  77. new create(env:Env,getmail:GetMail,account:String,server:String, user:String, password:String, folder:String) =>
  78. _account = account
  79. _server = server
  80. _user = user
  81. _password = password
  82. _folder = folder
  83. _env = env
  84. _getmail = getmail
  85.  
  86. fun cmd_name(cmd:(Command | None)): String =>
  87. match cmd
  88. | CAPABILITY => "CAPABILITY"
  89. | LOGIN => "LOGIN"
  90. | SELECT => "SELECT"
  91. | IDLE => "IDLE"
  92. | LIST => "LIST"
  93. | CLOSE => "CLOSE"
  94. | LOGOUT => "LOGOUT"
  95. | None => "NONE"
  96. else ""
  97. end
  98.  
  99. be send_command(cmd:Command, data:(String | None)) =>
  100. try
  101. _count = _count + 1
  102. _cmd = cmd
  103. let c:String = match cmd
  104. | CAPABILITY => "CAPABILITY"
  105. | LOGIN => "LOGIN"
  106. | SELECT => "SELECT"
  107. | IDLE => "IDLE"
  108. | LIST => "LIST"
  109. | CLOSE => "CLOSE"
  110. | LOGOUT => "LOGOUT"
  111. else error
  112. end
  113. let tail:String = match data
  114. | (let s:String) => " " + s + "\r\n"
  115. | None => "\r\n"
  116. else ""
  117. end
  118. let s = _count.string() + " " + c + tail
  119. _env.out.print("Sending: " + s)
  120. (_conn as TCPConnection).write(s)
  121. end
  122.  
  123. be connect() =>
  124. try
  125. let ctx = SSLContext.set_client_verify(false)
  126. let ssl = ctx.client(_server)
  127.  
  128. _conn = TCPConnection(SSLConnection(ResponseBuilder(_env, this), consume ssl), _server, "993".string())
  129. else
  130. _env.out.print("Failed to connect")
  131. end
  132.  
  133. be connected(conn:TCPConnection) =>
  134. _env.out.print("Server connected")
  135.  
  136. be connect_failed() =>
  137. _env.out.print("Connect failed")
  138.  
  139. be closed() =>
  140. _env.out.print("Closed: " + _account)
  141.  
  142. be got_line(s:String) =>
  143. match _state
  144. | CONNECTING =>
  145. _state = CONNECTED
  146. on_connected(s)
  147. | CONNECTED =>
  148. on_command(_cmd, s)
  149. end
  150.  
  151. be on_connected(s:String) =>
  152. _env.out.print("connected: " + s)
  153. send_command(LOGIN, _user + " " + _password)
  154.  
  155. be on_command(c:(Command | None), s:String) =>
  156. try
  157. if s(0) == '*' then
  158. on_command_untagged(c, s)
  159. elseif s(0) == '+' then
  160. on_command_continue(c, s)
  161. else
  162. try
  163. let offset = s.find(" ")
  164. let tagg = s.substring(0, offset - 1).u32()
  165. if s.at("OK", offset + 1) then
  166. on_command_end(c, tagg, s.substring(offset + 3, -1))
  167. else
  168. on_command_tagged(c, tagg, s.substring(offset + 1, -1))
  169. end
  170. else
  171. on_command_unknown(c, s)
  172. end
  173. end
  174. else
  175. on_command_unknown(c, s)
  176. end
  177.  
  178. be on_command_untagged(c:(Command | None), s:String) =>
  179. _env.out.print("on_command_untagged: " + cmd_name(c) + ": " + s)
  180. match c
  181. | LOGOUT => None
  182. | IDLE =>
  183. let exists:Bool = try
  184. s.find("EXISTS")
  185. true
  186. else
  187. false
  188. end
  189. let recent:Bool = try
  190. s.find("RECENT")
  191. true
  192. else
  193. false
  194. end
  195. if not _fetched and (exists or recent) then
  196. _fetched = true
  197. try
  198. (_conn as TCPConnection).write("DONE\r\n")
  199. end
  200. _getmail.update(_account)
  201. end
  202. if s.at("* BYE", 0) then
  203. try
  204. (_conn as TCPConnection).dispose()
  205. _env.out.print("Reconnecting to " + _account)
  206. connect()
  207. end
  208. end
  209. else
  210. try
  211. if s.at("* BYE", 0) then
  212. (_conn as TCPConnection).dispose()
  213. _env.out.print("Reconnecting to " + _account)
  214. connect()
  215. end
  216. end
  217. end
  218.  
  219.  
  220. be on_command_tagged(c:(Command | None), tagg:U32, s:String) =>
  221. _env.out.print("on_command_tagged: " + tagg.string() + " " + cmd_name(c) + ": " + s)
  222.  
  223. be on_command_continue(c:(Command | None), s:String) =>
  224. _env.out.print("on_command_continue: " + cmd_name(c) + ":" + s)
  225. match c
  226. | IDLE => _idling = true
  227. end
  228.  
  229. be on_command_end(c:(Command | None), tagg:U32, s:String) =>
  230. _env.out.print("on_command_end: " + tagg.string() + " " + cmd_name(c) + ": " + s)
  231. match c
  232. | LOGIN => send_command(SELECT, _folder)
  233. | SELECT => send_command(IDLE, None)
  234. | IDLE => _idling = false
  235. _fetched = false
  236. // send_command(CLOSE, None)
  237. send_command(IDLE, None)
  238. | CLOSE => send_command(LOGOUT, None)
  239. | LOGOUT => try (_conn as TCPConnection).dispose() end
  240. end
  241.  
  242. be on_command_unknown(c:(Command | None), s:String) =>
  243. _env.out.print("on_command_unknown: " + cmd_name(c) + ": " + s)
  244.  
  245.  
  246.  
  247.  
  248.  
  249. actor GetMail
  250. let system:System = System.create()
  251.  
  252. be update(account:String) =>
  253. system.run("offlineimap -u ttyui -o -a " + account)
  254. system.run("notmuch new")
  255. system.run("notify-send -t 2000 \"Mail retrieved for account " + account + "\"")
  256.  
  257. actor System
  258. be run(s:String) =>
  259. @system[None](s.cstring())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement