Class: POPServer

Inherits:
GenericServer show all
Defined in:
lib/pop_server.rb

Overview

Basic POP server

Instance Method Summary collapse

Constructor Details

#initialize(port) ⇒ POPServer

Create new server listening on port 110



9
10
11
# File 'lib/pop_server.rb', line 9

def initialize(port)
  super(:port => port)
end

Instance Method Details

#capa(client) ⇒ Object

Show the client what we can do



41
42
43
44
45
46
# File 'lib/pop_server.rb', line 41

def capa(client)
  respond(client, true, "Here's what I can do:\r\n" +
                        "USER\r\n" +
                        "IMPLEMENTATION Bluerail Post Office POP3 Server\r\n" +
                        ".")
end

#dele(client, message) ⇒ Object

Deletes message



142
143
144
145
146
147
148
149
150
151
# File 'lib/pop_server.rb', line 142

def dele(client, message)
  if message == :invalid
    respond(client, false, "Invalid message number.")
  elsif message == :all
    respond(client, false, "Invalid message number.")
  else
    Store.instance.remove(message - 1)
    respond(client, true, "Message deleted.")
  end
end

#greet(client) ⇒ Object

Send a greeting to client



14
15
16
17
18
19
# File 'lib/pop_server.rb', line 14

def greet(client)
  # truncate messages for this session
  Store.instance.truncate
  
  respond(client, true, "Hello there")
end

#list(client, message) ⇒ Object

Shows list of messages

When a message id is specified only list the size of that message



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/pop_server.rb', line 62

def list(client, message)
  if message == :invalid
    respond(client, false, "Invalid message number.")
  elsif message == :all
    messages = ""
    Store.instance.get.each.with_index do |message, index|
      messages << "#{index + 1} #{message.size}\r\n"
    end
    respond(client, true, "POP3 clients that break here, they violate STD53.\r\n#{messages}.")
  else
    message_data = Store.instance.get[message - 1]
    respond(client, true, "#{message} #{message_data.size}")
  end
end

#pass(client, full_data) ⇒ Object

Authenticates client



54
55
56
# File 'lib/pop_server.rb', line 54

def pass(client, full_data)
  respond(client, true, "Logged in.")
end

#process(client, command, full_data) ⇒ Object

Process command



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/pop_server.rb', line 22

def process(client, command, full_data)
  case command
    when "CAPA" then capa(client)
    when "DELE" then dele(client, message_number(full_data))
    when "LIST" then list(client, message_number(full_data))
    when "NOOP" then respond(client, true, "Yup.")
    when "PASS" then pass(client, full_data)
    when "QUIT" then quit(client)
    when "RETR" then retr(client, message_number(full_data))
    when "RSET" then respond(client, true, "Resurrected.")
    when "STAT" then stat(client)
    when "TOP"  then top(client, full_data)
    when "UIDL" then uidl(client, message_number(full_data))
    when "USER" then user(client, full_data)
    else respond(client, false, "Invalid command.")
  end
end

#quit(client) ⇒ Object

Quits



136
137
138
139
# File 'lib/pop_server.rb', line 136

def quit(client)
  respond(client, true, "Better luck next time.")
  client.close
end

#retr(client, message) ⇒ Object

Retreives message



78
79
80
81
82
83
84
85
86
87
# File 'lib/pop_server.rb', line 78

def retr(client, message)
  if message == :invalid
    respond(client, false, "Invalid message number.")
  elsif message == :all
    respond(client, false, "Invalid message number.")
  else
    message_data = Store.instance.get[message - 1]
    respond(client, true, "#{message_data.size} octets to follow.\r\n" + message_data + "\r\n.")
  end
end

#stat(client) ⇒ Object

Shows total number of messages and size



109
110
111
112
113
# File 'lib/pop_server.rb', line 109

def stat(client)
  messages = Store.instance.get
  total_size = messages.collect{ |m| m.size }.inject(0) { |sum,x| sum+x }
  respond(client, true, "#{messages.length} #{total_size}")
end

#top(client, full_data) ⇒ Object

Display headers of message



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/pop_server.rb', line 116

def top(client, full_data)
  full_data = full_data.split(/TOP\s(\d*)/)
  messagenum = full_data[1].to_i
  number_of_lines = full_data[2].to_i

  messages = Store.instance.get
  if messages.length >= messagenum && messagenum > 0
    headers = ""
    line_number = -2
    messages[messagenum - 1].split(/\r\n/).each do |line|
      line_number = line_number + 1 if line.gsub(/\r\n/, "") == "" || line_number > -2
      headers += "#{line}\r\n" if line_number < number_of_lines
    end
    respond(client, true, "headers follow.\r\n" + headers + "\r\n.")
  else
    respond(client, false, "Invalid message number.")
  end
end

#uidl(client, message) ⇒ Object

Shows list of message uid

When a message id is specified only list the uid of that message



93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/pop_server.rb', line 93

def uidl(client, message)
  if message == :invalid
    respond(client, false, "Invalid message number.")
  elsif message == :all
    messages = ""
    Store.instance.get.each.with_index do |message, index|
      messages << "#{index + 1} #{message_uid(message)}\r\n"
    end
    respond(client, true, "unique-id listing follows.\r\n#{messages}.")
  else
    message_data = Store.instance.get[message - 1]
    respond(client, true, "#{message} #{message_uid(message_data)}")
  end
end

#user(client, full_data) ⇒ Object

Accepts username



49
50
51
# File 'lib/pop_server.rb', line 49

def user(client, full_data)
  respond(client, true, "Password required.")
end