package server import ( "bytes" "encoding/json" "git.ddd.rip/ptrcnull/telegram" "io" "io/ioutil" "log" "mime" "mime/multipart" "mime/quotedprintable" "net" "net/http" "net/mail" "strings" ) const response = "uwu" var Tg telegram.Client const chatId = "456311800" 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 } type Header interface { Get(key string) string } func readTextBody(header Header, body io.Reader) (string, error) { log.Println("reading text body") var bodyBytes []byte var err error if header.Get("Content-Transfer-Encoding") == "quoted-printable" { bodyBytes, err = ioutil.ReadAll(quotedprintable.NewReader(body)) } else { bodyBytes, err = ioutil.ReadAll(body) } log.Println("ended reading text body") return string(bodyBytes), err } func readMultipartBody(msg *mail.Message, boundary string) (string, error) { r := multipart.NewReader(msg.Body, boundary) body := "" for { part, err := r.NextPart() if err == io.EOF { break } if err != nil { log.Println("error parsing multipart:", err) break } mimetype, _, err := mime.ParseMediaType(part.Header.Get("Content-Type")) if err != nil { log.Println("error parsing multipart mimetype:", err) continue } if mimetype == "text/plain" { body, err = readTextBody(part.Header, part) if err != nil { log.Println("error reading text body from multipart:", err) } } else if mimetype == "text/html" && body == "" { body, err = readTextBody(part.Header, part) if err != nil { log.Println("error reading html body from multipart:", err) } } } return body, nil } func handleMessage(data string) { msg, err := mail.ReadMessage(bytes.NewReader([]byte(data))) if err != nil { log.Println(err) return } res := "New mail!" res += "\nFrom: " + msg.Header.Get("From") res += "\nTo: " + msg.Header.Get("To") mimetype, mimeparams, err := mime.ParseMediaType(msg.Header.Get("Content-Type")) if err != nil { log.Println(err) return } log.Println("handling email with content-type", mimetype) var body string if strings.HasPrefix(mimetype, "text/") { body, err = readTextBody(msg.Header, msg.Body) } else if strings.HasPrefix(mimetype, "multipart/") { body, err = readMultipartBody(msg, mimeparams["boundary"]) } else { body = "check console for more info" } if err != nil { log.Println("reading body failed:", err) return } if len(body) > 1000 { // curl 'https://bin.ddd.rip/documents' --compressed -H 'Content-Type: application/json; charset=utf-8' -H 'X-Requested-With: XMLHttpRequest' -H 'Origin: https://bin.ddd.rip' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Referer: https://bin.ddd.rip/' -H 'TE: Trailers' --data-raw dupa log.Println("mail too long, uploading to hastebin") res, err := http.Post("https://bin.ddd.rip/documents", "text/plain", bytes.NewReader([]byte(body))) if err != nil { body = "error uploading email: " + err.Error() } else { var response map[string]string json.NewDecoder(res.Body).Decode(&response) body = "https://bin.ddd.rip/" + response["key"] } } res += "\n\n" + body log.Println("sending telegram message") _, err = Tg.SendMessage(chatId, res) if err != nil { log.Println(err) } }