commit ab2ddeed8743abcae016d8fb7b6d3d7c86729752 Author: ptrcnull Date: Sat Dec 5 19:12:05 2020 +0100 wip: Initial commit diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..464246a --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module tgmail + +go 1.15 diff --git a/main.go b/main.go new file mode 100644 index 0000000..c981f7f --- /dev/null +++ b/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "log" + "net" + "tgmail/server" +) + +func main() { + l, err := net.Listen("tcp", "0.0.0.0:2525") + if err != nil { + panic(err) + } + defer l.Close() + + log.Println("Listening!") + + for { + c, err := l.Accept() + if err != nil { + log.Println(err) + return + } + go server.Handle(c) + } +} diff --git a/server/conn_wrapper.go b/server/conn_wrapper.go new file mode 100644 index 0000000..bcde6a6 --- /dev/null +++ b/server/conn_wrapper.go @@ -0,0 +1,49 @@ +package server + +import ( + "bufio" + "log" + "net" + "strconv" + "strings" +) + +type wrapper struct { + net.Conn + r *bufio.Reader +} + +func (w *wrapper) cmd(code int64, msgs ...string) error { + for i, msg := range msgs { + sep := "-" + if i == len(msgs)-1 { + sep = " " + } + err := w.send(strconv.FormatInt(code, 10) + sep + msg) + if err != nil { + return err + } + } + return nil +} + +func (w *wrapper) send(message string) error { + log.Println("+", message) + // fuck some MTAs + _, err := w.Write([]byte(message + "\r\n")) + return err +} + +func (w *wrapper) recv() (string, error) { + if w.r == nil { + w.r = bufio.NewReader(w) + } + //log.Println("* recv called") + msg, err := w.r.ReadString('\n') + if err != nil { + return "", err + } + msg = strings.TrimRight(msg, " \t\r\n") + log.Println("-", msg) + return msg, nil +} diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..c6b0856 --- /dev/null +++ b/server/server.go @@ -0,0 +1,95 @@ +package server + +import ( + "bytes" + "io/ioutil" + "log" + "net" + "net/mail" + "strings" +) + +const response = "uwu" + +func Handle(conn net.Conn) { + c := wrapper{Conn: conn} + log.Println("Connection received from", c.RemoteAddr().String()) + c.cmd(220, response+" ESMTP") + + for { + msg, err := c.recv() + if err != nil { + log.Println(err) + c.Close() + return + } + + cmd := strings.ToUpper(strings.Split(msg, " ")[0]) + + if cmd == "EHLO" { + c.cmd(250, + response, + "8BITMIME", + "SMTPUTF8", + "SIZE 104857600") + continue + } + + if cmd == "DATA" { + c.cmd(354, response) + + data, err := readContent(c) + if err != nil { + log.Println(err) + c.Close() + return + } + + go handleMessage(data) + + continue + } + + if cmd == "QUIT" { + c.cmd(221, response) + c.Close() + break + } + + c.cmd(250, response) + } + c.Close() +} + +func readContent(c wrapper) (string, error) { + data := "" + for { + msg, err := c.recv() + if err != nil { + return "", err + } + if msg == "." { + break + } + data += msg + "\r\n" + } + c.cmd(250, response) + return data, nil +} + +func handleMessage(data string) { + msg, err := mail.ReadMessage(bytes.NewReader([]byte(data))) + if err != nil { + log.Println(err) + return + } + + body, err := ioutil.ReadAll(msg.Body) + if err != nil { + log.Println(err) + return + } + + log.Println("FROM: ", msg.Header.Get("From")) + log.Println(string(body)) +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..d8d7097 --- /dev/null +++ b/test.js @@ -0,0 +1,16 @@ +const net = require('net') + +const server = net.createServer(c => { + console.log('Connected') + c.on('data', d => { + console.log('data', d.toString()) + }) + c.on('end', () => { + console.log('client disconnected') + }) + c.write('220 uwu ESMTP\n') +}) + +server.listen(2525, () => { + console.log('works') +})