Ive seen email systems done in the past, but here's the first usable version of mine. I spent a lot of time writing this stuff at 3am, so it probably needs some cleaning up. It involves a few separate systems: a login server, a DNS-like server, an email server, and an email client. The login server is similar to the one from the wiki, but with changes to the way it works to make it more secure, and allow the server owner to add/remove accounts on the fly. The code comes with an account for the email server to use by default, so you need to add user accounts. To do so , just start the program and press the 'a' key. It will ask for a name and a password, then confirm adding the user to the list. Removing is just pressing the 'r' key, entering the username, and confirming. You can press 'm' to view the list of users currently in the system. DANGER: since this is an early version, anything in any of the servers not hardcoded will not persist after a crash/reboot Code: pullEvent = os.pullEvent os.pullEvent = os.pullEventRaw users = {"mailserver"} passwords = {"legomail"} term.clear() term.setCursorPos(1,1) print("Legoman technologies authentication server running") id = os.computerID() term.setCursorPos(1,2) print("Computer ID = "..id) local firstCycle = true local modemSide = "right" local valid = false local DNSID = 2 while true do if firstCycle then rednet.open(modemSide) firstCycle = false end event, p1, p2, p3 = os.pullEvent() term.clear() term.setCursorPos(1,1) print("Legoman technologies authentication server running") id = os.computerID() term.setCursorPos(1,2) print("Computer ID = "..id) if event =="char" then if p1 == "m" then for i, v in ipairs(users) do print(v) end end if p1 == "a" then term.setCursorPos(1,10) print("Enter name: ") name = read() print("Enter password: ") password = read() print("Confim add " .. name .. " Y/N?") if read() == "Y" then table.insert(users, name) table.insert(passwords, password) print("Added") end end if p1 == "r" then print("Enter name: ") name = read() print("Confim remove " .. name .. " Y/N?") if read() == "Y" then for i,v in ipairs(users) do if name == v then table.remove(users, i) table.remove(passwords, i) end end end end end if event == "terminate" then term.setCursorPos(1,10) print("Enter password: ") if read("*") == "unlock" then os.pullEvent = pullEvent shell.exit() end end if event == "rednet_message" then senderId = p1 message = p2 term.setCursorPos(1,4) term.clearLine() print(message) for i,v in ipairs(users) do if message == v then valid = true password = passwords[i] user = users[i] break else valid = false end end if valid then rednet.send(senderId, "Valid") print("Valid") else rednet.send(senderId, "Not Valid") print("Not valid") end sender, passwordRcv, dist = rednet.receive(3) print(sender) if passwordRcv == password then rednet.send(senderId, "Authenticated") rednet.send(DNSID, "Add " .. senderId .. " " .. user) print("Authenticated") else rednet.send(senderId, "Failed") end end end There is a variable near the start named DNSID. you need to change that to the id of the next computer, the DNS server. When someone logs in, the login server tells the DNS server the name and id of the person who logged in, so others can check the names of users and the ids to send things to. It also supports listing the names in the system using the 'm' key. The variable AUTHID needs to be set to the id of the login server for it to accept new entries, and it is a good idea to give the ids table correct ids for the login and DNS server as well. Currently, if it gets multiple commands to add the same name, the one added first will be the one that counts. If you send a remove message, it will delete you from its table as a means of logging out. Code: pullEvent = os.pullEvent os.pullEvent = os.pullEventRaw names = {"authserver","dnsserver"} ids = {0,1} term.clear() term.setCursorPos(1,1) print("Legoman technologies DNS server running") myid = os.computerID() term.setCursorPos(1,2) print("Computer ID = " .. myid) local firstCycle = true local modemSide = "right" local AUTHID = 1 while true do if firstCycle then rednet.open(modemSide) firstCycle = false end event, p1, p2, p3 = os.pullEvent() term.clear() term.setCursorPos(1,1) print("Legoman technologies DNS server running") myid = os.computerID() term.setCursorPos(1,2) print("Computer ID = " .. myid) if event == "terminate" then term.setCursorPos(1,10) print("Enter password: ") if read("*") == "unlock" then os.pullEvent = pullEvent shell.exit() end end if event =="char" then if p1 == "m" then for i, v in ipairs(names) do print(v) end end end if event == "rednet_message" then senderId = p1 message = p2 term.setCursorPos(1,4) term.clearLine() if string.match(message, 'Id') == "Id" then print("Command: " .. string.match(message, 'Id')) idLookup = string.match(message, '%d+') + 0 term.clearLine() print("Param: " .. idLookup) for i, v in ipairs(ids) do if idLookup == v then nameLookup = names[i] term.clearLine() print("Return: " .. nameLookup) rednet.send(senderId, nameLookup) break end end end if string.match(message, 'Name') == "Name" then print("Command: " .. string.match(message, 'Name')) nameLookup = string.match(message, '%a+', 5) term.clearLine() print("Param: " .. nameLookup) for i, v in ipairs(names) do if nameLookup == v then idLookup = ids[i] term.clearLine() print("Return: " .. idLookup) rednet.send(senderId, idLookup.."") break end end end if string.match(message, 'Add') == "Add" and senderId + 0 == AUTHID then print("Command: " .. string.match(message, 'Add')) nameAdd = string.match(message, '%a+', 4) idAdd = string.match(message, '%d+', 4) print("Params: " .. nameAdd .. ", " .. idAdd) table.insert(names, nameAdd) table.insert(ids, idAdd+0) end if string.match(message, 'Remove') == "Remove" then print("Command: " .. string.match(message, 'Remove')) term.clearLine() print("Param: " .. senderId) for i, v in ipairs(ids) do if senderId == v then table.remove(ids, i) table.remove(names, i) end end end end end The third and final server in this system is the email server itself. It needs the login and DNS server ids coded into the AUTHID and DNSID variables, respectively. Pressing 'm' lists the recipients of the messages in the system, 'a' adds a user to the list of people who can use email, and 'l' tries to update its id in the DNS server. It works by sending and receiving a variety of messages to and from the clients, and checking who each one is using the reverse DNS function of the DNS server. Code: pullEvent = os.pullEvent os.pullEvent = os.pullEventRaw users = {"test"} messages = {"blank"} recipients = {"test"} term.clear() term.setCursorPos(1,1) print("Legoman technologies email server running") myid = os.computerID() term.setCursorPos(1,2) print("Computer ID = " .. myid) local firstCycle = true local modemSide = "right" local AUTHID = 0 local DNSID = 1 local senderValid = false local recipientValid = false function DNSreverse (Id) rednet.open(modemSide) rednet.send(DNSID, "Id " .. Id) local temp, message = rednet.receive(1) return message end function login() rednet.send(AUTHID, "mailserver") os.sleep(1) rednet.send(AUTHID, "legomail") end while true do if firstCycle then rednet.open(modemSide) firstCycle = false rednet.send(DNSID, "Remove") login() end event, p1, p2, p3 = os.pullEvent() term.clear() term.setCursorPos(1,1) print("Legoman technologies email server running") myid = os.computerID() term.setCursorPos(1,2) print("Computer ID = " .. myid) if event == "terminate" then term.setCursorPos(1,10) print("Enter password: ") if read("*") == "unlock" then os.pullEvent = pullEvent shell.exit() end end if event =="char" then if p1 == "m" then for i, v in ipairs(recipients) do print(v) end end if p1 == "a" then term.setCursorPos(1,10) print("Enter name: ") name = read() print("Confim add " .. name .. " Y/N?") if read() == "Y" then table.insert(users, name) print("Added") end end if p1 == "l" then rednet.send(DNSID, "Remove") login() end end if event == "rednet_message" then senderId = p1 message = p2 senderName = DNSreverse(senderId) for i, v in ipairs(users) do if senderName == v then senderValid = true print("Sender is valid") break else senderValid = false end end if string.match(message, 'Send') == "Send" and senderValid then print("Command: " .. string.match(message, 'Send')) recipient = string.match(message, '%a+', 5) mailMessage = string.match(message, '%p.+', 5) print("Recipient: " .. recipient) --print("Message: " .. mailMessage) os.sleep(1) for i, v in ipairs(users) do print(v) if recipient == v then recipientValid = true print("Recipient is valid") break else recipientValid = false end end if recipientValid then table.insert(messages, mailMessage) table.insert(recipients, recipient) rednet.send(senderId, "Ok") end end if string.match(message, 'Check') == "Check" and senderValid then print("Command: " .. string.match(message, 'Check')) messageNumber = 0 for i, v in ipairs(recipients) do if senderName == v then messageNumber = messageNumber + 1 end end rednet.send(senderId, messageNumber .. "") end if string.match(message, 'Read') == "Read" and senderValid then print("Command: " .. string.match(message, 'Read')) readNumber = string.match(message, '%d+', 5) + 0 print("Read number: " .. readNumber) messageNumber = 0 for i, v in ipairs(recipients) do if senderName == v then messageNumber = messageNumber + 1 end if messageNumber == readNumber then print("Message found") rednet.send(senderId, messages[i].."") break end end end if string.match(message, 'Remove') == 'Remove' and senderValid then print("Command: " .. string.match(message, 'Remove')) removeNumber = string.match(message, '%d+', 7) print("Remove number: " .. removeNumber) messageNumber = 0 for i, v in ipairs(recipients) do if senderName == v then messageNumber = messageNumber + 1 end if messageNumber == removeNumber + 0 then table.remove(messages, i) table.remove(recipients, i) print("Removed") break end end end end end The email client interfaces to all 3 servers, and it will attempt to find the id of the mail and login servers from DNS, so be sure they are both registered in the DNS server. It supports roaming accounts, so you can log in from any computer in rednet range. It can: 1- Check the number of messages in your inbox 2- Read one of the messages (input the number of the message you want read, with the first in the inbox being number one, the second number two, etc) 3- Send a message to a particular user, which give feedback in the form of "Sent" or "error" (which usually means invalid recipient) 4- Remove a message from the inbox, using a number system like reading messages 5-Log out of your account Code: pullEvent = os.pullEvent os.pullEvent = os.pullEventRaw term.clear() term.setCursorPos(1,1) print("Legoman technologies email client running") myid = os.computerID() term.setCursorPos(1,2) print("Computer ID = " .. myid) local firstCycle = true local modemSide = "right" local AUTHID = 0 local DNSID = 1 local loggedin = false function DNSreverse (Id) rednet.open(modemSide) rednet.send(DNSID, "Id " .. Id) local temp, message = rednet.receive(1) return message end function DNSforward(servername) rednet.open(modemSide) rednet.send(DNSID, "Name " .. servername) local temp, message = rednet.receive(3) return message end while true do if firstCycle then rednet.open(modemSide) firstCycle = false end AUTHID = DNSforward("authserver") + 0 MAILID = DNSforward("mailserver") + 0 print("Mail ID: " .. MAILID) print("Auth ID: " .. AUTHID) print("Welcome! Please log in.") print("Username: ") username = read() print("Password:") password = read("*") rednet.send(AUTHID + 0, username) sender, message = rednet.receive(2) if message == "Valid" then print("Username ok!") rednet.send(AUTHID + 0, password) elseif message == "Not Valid" then print("Wrong username!") loggedin = false else print("Rednet error!") end sender, message = rednet.receive(2) if message == "Authenticated" then loggedin = true print("Logged in!") else print("Login failed!") end os.sleep(2) if loggedin then term.clear() term.setCursorPos(1,1) end while loggedin do print("Legoman technologies email client! Username: " .. DNSreverse(myid)) print("What would you like to do?") print(" 1 - Check for messages") print(" 2 - Read a message") print(" 3 - Send a message") print(" 4 - Remove a message") print(" 5 - Log out") print(">") input = read() if input == "1" then print("Checking for messages") rednet.send(MAILID, "Check") temp, message = rednet.receive(3) print("You have: " .. message .. " message(s)") end if input == "2" then print("Enter message number to read: ") messageNum = read() rednet.send(MAILID, "Read " .. messageNum) temp, message = rednet.receive(3) print(message) end if input == "3" then print("Enter recipient name: ") recipient = read() print("Enter message: ") toSend = read() print("Send message to " .. recipient .. " Y/N?") yn = read() if yn == "Y" then rednet.send(MAILID, "Send " .. recipient .. " !" .. toSend) temp, message = rednet.receive(3) if message == "Ok" then print("Sent!") else print("Error!") end end end if input == "4" then print("Enter message number to remove: ") messageNum = read() os.sleep(1) print("Proceed? Y/N?") yn = read() if yn == "Y" then rednet.send(MAILID, "Remove " .. messageNum) end end if input == "5" then term.clear() term.setCursorPos(1,1) print("Goodbye!") os.sleep(1) rednet.send(DNSID, "Remove") loggedin = false term.clear() term.setCursorPos(1,1) end end end If I implement this on my friends tekkit server(where we all live pretty close together), I may shoot some video. Planned features/improvements: -Save data to disk -Save data to disk(encrypted or something) -Misc robustness improvements (I usually let kexus321 try to break it until it does break, then fix what caused it to break) -clean up a little -support an inbox using subject lines instead of just "you have x messages" -support for dynamically discovering DNS and login servers -create a dynamic mesh network of repeaters to expand usable range (probably going to stay in the planned feature section for a while) -add other servers that use the login/DNS system to create a larger "internet" system Suggestions/comments/constructive criticism appreciated If you use this code, please keep the "Legoman technologies" statement as accreditation
Could you show what it looks like when you open that program in the computer's edit system? It indicates line 4, which is just term.clear() .
Looks like you havent put the ID number of the DNS and Auth server in the right places. AUTHID and DNSID need to have the number on the same line replaced with the Computer ID of the Authentication and DNS computers. the ID for each computer is displayed on that computer when the program is running. Code: local AUTHID = 0 local DNSID = 1 these lines^
Sorry I've been out. Show/post the top of the code in the computer that is broken, so I can check the configuration.