func read_message(r io.Reader) (NNTPMessage, error) { msg, err := mail.ReadMessage(r) var nntp nntpArticle if err == nil { nntp.headers = ArticleHeaders(msg.Header) content_type := nntp.ContentType() media_type, params, err := mime.ParseMediaType(content_type) if err != nil { log.Println("failed to parse media type", err, "for mime", content_type) return nil, err } boundary, ok := params["boundary"] if ok { partReader := multipart.NewReader(msg.Body, boundary) for { part, err := partReader.NextPart() if err == io.EOF { return nntp, nil } else if err == nil { hdr := part.Header // get content type of part part_type := hdr.Get("Content-Type") // parse content type media_type, _, err = mime.ParseMediaType(part_type) if err == nil { if media_type == "text/plain" { att := readAttachmentFromMimePart(part) if att != nil { nntp.message = att.(nntpAttachment) nntp.message.header.Set("Content-Type", part_type) } } else { // non plaintext gets added to attachments att := readAttachmentFromMimePart(part) if att != nil { nntp = nntp.Attach(att).(nntpArticle) } } } else { log.Println("part has no content type", err) } part.Close() } else { log.Println("failed to load part! ", err) return nil, err } } } else if media_type == "message/rfc822" { // tripcoded message sig := nntp.headers.Get("X-Signature-Ed25519-Sha512", "") pk := nntp.Pubkey() if pk == "" || sig == "" { log.Println("invalid sig or pubkey", sig, pk) return nil, errors.New("invalid headers") } log.Printf("got signed message from %s", pk) pk_bytes := unhex(pk) sig_bytes := unhex(sig) r := bufio.NewReader(msg.Body) crlf := []byte{13, 10} for { line, err := r.ReadBytes('\n') if err == io.EOF { break } nntp.signedPart.body.Write(line[:len(line)-1]) nntp.signedPart.body.Write(crlf) } if nntp.signedPart.body.Len() < 2 { log.Println("signed body is too small") } else { body := nntp.signedPart.body.Bytes()[:nntp.signedPart.body.Len()-2] body_hash := sha512.Sum512(body) log.Printf("hash=%s", hexify(body_hash[:])) if nacl.CryptoVerifyFucky(body_hash[:], sig_bytes, pk_bytes) { log.Println("signature is valid :^)") return nntp, nil } else { log.Println("!!!signature is invalid!!!") } } } else { // plaintext attachment var buff bytes.Buffer _, err = io.Copy(&buff, msg.Body) nntp.message = createPlaintextAttachment(buff.String()) return nntp, err } } else { log.Println("failed to read message", err) return nil, err } return nntp, err }