Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net/mail: ReadMessage returns EOF error when the body is not present #47886

Closed
0xc0d opened this issue Aug 22, 2021 · 4 comments
Closed

net/mail: ReadMessage returns EOF error when the body is not present #47886

0xc0d opened this issue Aug 22, 2021 · 4 comments

Comments

@0xc0d
Copy link
Contributor

0xc0d commented Aug 22, 2021

What version of Go are you using (go version)?

$ go version
go version go1.16 darwin/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/user/Library/Caches/go-build"
GOENV="/Users/user/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/user/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/user/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/Users/user/sdk/go1.16"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/user/sdk/go1.16/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.16"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/_r/pyfmdgr15fz3_x7hhfk7gb3r0000gp/T/go-build2586304111=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"mime"
	"mime/multipart"
	"net/mail"
	"os"
	"strings"
)

var email = strings.NewReader(`From: Ali Josie <ajozi@harlemnext.com>
To: feedback@domain.com
Subject: Feedback Report
MIME-Version: 1.0
Content-Type: multipart/report; report-type=feedback-report; 
	boundary="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

This is plain text.

--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: message/feedback-report
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Feedback-Type: abuse
Original-Mail-From: <ajozi@harlemnext.com>

--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: message/rfc822
Content-Disposition: inline

Date: Mon, 3 Feb 2020 19:16:52 +0000
To: Test <test@gmail.com>
From: Ali Josie <ajozi@harlemnext.com>
Subject: Test 
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii

This is the original email.

--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--
`)

func main() {
	msg, err := mail.ReadMessage(email)
	if err != nil {
		log.Fatal(err)
	}
	_, params, err := mime.ParseMediaType(msg.Header.Get("Content-Type"))
	if err != nil {
		log.Fatal(err)
	}
	mr := multipart.NewReader(msg.Body, params["boundary"])
	for {
		part, err := mr.NextRawPart()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatal(err)
		}
		contentType := part.Header.Get("Content-Type")
		fmt.Printf("Content-Type: %v\n", contentType)

		b := new(bytes.Buffer)
		b.ReadFrom(part)
		fmt.Printf("Body: %q\n\n", b.String())


		switch {
		case strings.HasPrefix(contentType, "message"):
			msg, err = mail.ReadMessage(b)
			if err != nil {
				log.Println("error occurred:", err)
				break
			}
			io.Copy(os.Stdout, msg.Body)
		default:
			io.Copy(os.Stdout, b)
		}
		fmt.Println("-----------------------------")
	}
}

What did you expect to see?

Content-Type: text/plain; charset=us-ascii
Body: "This is a plain text.\n"

This is plain text.
-----------------------------
Content-Type: message/feedback-report
Body: "Feedback-Type: abuse\nOriginal-Mail-From: <ajozi@harlemnext.com>\n\n"


-----------------------------
Content-Type: message/rfc822
Body: "Date: Mon, 3 Feb 2020 19:16:52 +0000\nTo: Test <test@gmail.com>\nFrom: Ali Josie <ajozi@harlemnext.com>\nSubject: Test \nMIME-Version: 1.0\nContent-Type: text/plain; charset=us-ascii\n\nThis is a the original email.\n"

This is the original email.
-----------------------------

What did you see instead?

Content-Type: text/plain; charset=us-ascii
Body: "This is a plain text.\n"

This is plain text.
-----------------------------
Content-Type: message/feedback-report
Body: "Feedback-Type: abuse\nOriginal-Mail-From: <ajozi@harlemnext.com>\n"

2021/08/22 13:44:01 error occurred: EOF
-----------------------------
Content-Type: message/rfc822
Body: "Date: Mon, 3 Feb 2020 19:16:52 +0000\nTo: Test <test@gmail.com>\nFrom: Ali Josie <ajozi@harlemnext.com>\nSubject: Test \nMIME-Version: 1.0\nContent-Type: text/plain; charset=us-ascii\n\nThis is a the original email.\n"

This is the original email.
-----------------------------

Reason

According to RFC2822 Section 2.1:

A message consists of header fields (collectively called "the header
of the message") followed, optionally, by a body. The header is a
sequence of lines of characters with special syntax as defined in
this standard. The body is simply a sequence of characters that
follows the header and is separated from the header by an empty line
(i.e., a line with nothing preceding the CRLF).

This is a valid message/* without a body (is it?):

Content-Type: message/feedback-report
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Feedback-Type: abuse
Original-Mail-From: <ajozi@harlemnext.com>

--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Which I believe 'mime/multipart' should return this:

Feedback-Type: abuse\nOriginal-Mail-From: <ajozi@harlemnext.com>\n\n

But it omits the last \n which makes the message invalid due to the missing blank line after headers.

Refrence

I think we should fix this here.

@0xc0d
Copy link
Contributor Author

0xc0d commented Aug 22, 2021

According to RFC1341 Section 7.2:

The body must then contain one or more "body parts,"each preceded by an encapsulation boundary, and the last one followed by a closing boundary. Each part starts with an encapsulation boundary, and then contains a body part consisting of header area, a blank line, and a body area. Thus a body part is similar to an RFC 822 message in syntax, but different in meaning.

The encapsulation boundary MUST NOT appear inside any of the encapsulated parts. Thus, it is crucial that the composing agent be able to choose and specify the unique boundary that will separate the parts.

The encapsulation boundary is defined as a line consisting entirely of two hyphen characters ("-", decimal code 45) followed by the boundary parameter value from the Content-Type header field.

The encapsulation boundary must occur at the beginning of a line.

The CRLF preceding the encapsulation line is considered part of the boundary so that it is possible to have a part that does not end with a CRLF (line break). Body parts that must be considered to end with line breaks, therefore, should have two CRLFs preceding the encapsulation line, the first of which is part of the preceding body part, and the second of which is part of the encapsulation boundary.

So I believe the code is fine. It should be the message which doesn't follow RFC 822.

@0xc0d
Copy link
Contributor Author

0xc0d commented Aug 22, 2021

I guess the message is valid. According to RFC 822

A message consists of header fields and, optionally, a body. The body is simply a sequence of lines containing ASCII characters. It is separated from the headers by a null line (i.e., a line with nothing preceding the CRLF).

And there is an example here.

So it might be net/mail which return an error when there is no body present.

@0xc0d 0xc0d changed the title mime/multipart: Reader.NextPart() omits the blank line when the body is empty. net/mail: ReadMessage returns EOF error when the body is not present Aug 22, 2021
@0xc0d
Copy link
Contributor Author

0xc0d commented Aug 22, 2021

We may need some extra check here.

To return messages with no body present.

@0xc0d
Copy link
Contributor Author

0xc0d commented Aug 22, 2021

Moving this issue to #47897

@0xc0d 0xc0d closed this as completed Aug 22, 2021
@golang golang locked and limited conversation to collaborators Aug 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants