-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimap-server.cs
133 lines (109 loc) · 3.13 KB
/
imap-server.cs
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
net = require 'net'
imap = require './imap.js'
starttls = require './starttls.js'
db = require './db.js'
database = new db.DataBase 'index.sqlite3'
# cmd: an array of an imap command, e.g. ['aa0', 'login', 'username', 'password']
# where aa0 is the id of the request, and must be sent when the response is complete
# assume cmd is correct
imap_reply =
end : (cmd) ->
cmd[0] + " OK " + cmd[1].toUpperCase() + " completed\r\n"
more : (cmd) ->
"+\r\n"
capability: (cmd, ssl) ->
if ssl
'* CAPABILITY IMAP4rev1 AUTH=EXTERNAL\r\n'
else
'* CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED\r\n'
flags: (cmd) ->
'* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n'
ok: () ->
'* OK\r\n'
bad: (cmd) ->
cmd[0] + " BAD " + cmd[1].toUpperCase() + "\r\n"
no_query_id: () ->
"* BAD You have to handle uids of the queries…\r\n"
server = net.createServer (c) -> #'connection' listener
console.log 'server connected'
wait_for_more = null
must_quit = false
ssl = false
username = false
# cmd: an array of an imap command, e.g. ['aa0', 'login', 'username', 'password']
# where aa0 is the id of the request, and must be sent when the response is complete
# send: a function that takes str and sends the result to the client
handle_command = (cmd, send) ->
if cmd.length < 2
send imap_reply.no_query_id
else
switch cmd[1].toLowerCase()
when 'capability'
send (imap_reply.capability cmd, c.ssl) + (imap_reply.end cmd)
when 'logout'
must_quit = true
send imap_reply.ok()
null
when 'starttls'
send starttls.starttls c, cmd[0]
when 'login'
if cmd.length != 4
send imap_reply.bad cmd
else
database.user.find where: username: cmd[2]
.complete (err, user) ->
if user and user.password == cmd[3]
username = user.username
send imap_reply.end cmd
else
send imap_reply.bad cmd
when 'list'
send imap_reply.end cmd
when 'lsub'
send imap_reply.end cmd
when 'create'
send imap_reply.end cmd
when 'select'
if username
send imap_reply.flags cmd
send imap_reply.end cmd
else
send imap_reply.bad cmd
when 'noop'
send imap_reply.end cmd
when 'subscribe'
send imap_reply.end cmd
else
send imap_reply.ok()
c.on 'end', () ->
console.log 'server disconnected'
c.on 'error', (e) ->
console.log e
c.on 'data', (e) ->
console.log ">>>> Reçu : " + e.toString()
reply = null
send = (reply) ->
if reply
console.log "<<<< Envoi : " + reply
if c.ssl
c.stream.write reply
else
c.write reply
if must_quit
c.end()
if wait_for_more
tmp = wait_for_more
wait_for_more = null
tmp_reject = reject
reject = null
tmp (e.toString() + tmp_reject)
else
# Extract the identifier of the command
[cmds, reject] = imap.parse (e.toString() + reject)
handle_command cmd, send for cmd in cmds
# Show we're alive, some clients don't start, event if it is not in the spec (?)
c.write imap_reply.ok()
# What's the use of this thing?
# c.pipe c
server.listen 1430, () -> #'listening' listener
console.log 'server bound'