diff --git a/dkim.go b/dkim.go index 0159519..74c5b7e 100644 --- a/dkim.go +++ b/dkim.go @@ -2,11 +2,17 @@ package dkim import ( "bytes" + //"fmt" "io/ioutil" + "regexp" "strings" "time" ) +const ( + CRLF = "\r\n" +) + // sigOptions represents signing options type sigOptions struct { @@ -128,6 +134,9 @@ func Sign(email *bytes.Reader, options sigOptions) (*bytes.Reader, error) { func canonicalize(emailReader *bytes.Reader, options sigOptions) (headers, body []byte, err error) { var email []byte + body = []byte{} + rxReduceWS := regexp.MustCompile(`[ \t]+`) + email, err = ioutil.ReadAll(emailReader) emailReader.Seek(0, 0) if err != nil { @@ -136,21 +145,37 @@ func canonicalize(emailReader *bytes.Reader, options sigOptions) (headers, body parts := bytes.SplitN(email, []byte{13, 10, 13, 10}, 2) + if len(parts) != 2 { + return headers, body, ErrBadMailFormat + } + + // Empty body + if len(parts[1]) == 0 { + parts[1] = []byte{13, 10} + } + canonicalizations := strings.Split(options.Canonicalization, "/") // canonicalyze body if canonicalizations[1] == "simple" { body = bytes.TrimRight(parts[1], "\r\n") body = append(body, []byte{13, 10}...) } else { - for _, line := range bytes.Split(parts[1], []byte{10}) { - println(line) + parts[1] = rxReduceWS.ReplaceAll(parts[1], []byte(" ")) + for _, line := range bytes.SplitAfter(parts[1], []byte{10}) { + line = bytes.TrimRight(line, " \r\n") + // Ignore all whitespace at the end of lines. Implementations + // MUST NOT remove the CRLF at the end of the line. + if len(line) != 0 { + body = append(body, line...) + body = append(body, []byte{13, 10}...) + } } } + return - println(string(parts[0])) + /*println(string(parts[0])) println("\r\n") println(string(parts[1])) - println(string(body)) - + println(string(body))*/ return } diff --git a/dkim_test.go b/dkim_test.go index 4df6fc2..9af4899 100644 --- a/dkim_test.go +++ b/dkim_test.go @@ -31,17 +31,32 @@ kS5vLkzRI84eiJrm3+IieUqIIicsO+WYxQs+JgVx5XhpPjX4SQjHtwEC2xKkWnEv selector = "test" ) -var email = `Received: (qmail 28277 invoked from network); 1 May 2015 09:43:37 -0000 -Received: (qmail 21323 invoked from network); 1 May 2015 09:48:39 -0000 -MIME-Version: 1.0 -Date: Fri, 1 May 2015 11:48:37 +0200 -Message-ID: -Subject: Test DKIM -From: =?UTF-8?Q?St=C3=A9phane_Depierrepont?= -To: =?UTF-8?Q?St=C3=A9phane_Depierrepont?= -Content-Type: text/plain; charset=UTF-8` + "\r\n\r\n" + `Hello world --- -Toorop` + "\r\n\r\n\r\n\r\n\r\n\r\n\r\n" +var email = "Received: (qmail 28277 invoked from network); 1 May 2015 09:43:37 -0000" + CRLF + + "Received: (qmail 21323 invoked from network); 1 May 2015 09:48:39 -0000" + CRLF + + "MIME-Version: 1.0" + CRLF + + "Date: Fri, 1 May 2015 11:48:37 +0200" + CRLF + + "Message-ID: " + CRLF + + "Subject: Test DKIM" + CRLF + + "From: =?UTF-8?Q?St=C3=A9phane_Depierrepont?= " + CRLF + + "To: =?UTF-8?Q?St=C3=A9phane_Depierrepont?= " + CRLF + + "Content-Type: text/plain; charset=UTF-8" + CRLF + CRLF + + "Hello world" + CRLF + + "line with trailing space " + CRLF + + "line with space " + CRLF + + "-- " + CRLF + + "Toorop " + CRLF + CRLF + CRLF + CRLF + CRLF + CRLF + +var bodySimple = "Hello world" + CRLF + + "line with trailing space " + CRLF + + "line with space " + CRLF + + "-- " + CRLF + + "Toorop " + CRLF + +var bodyRelaxed = "Hello world" + CRLF + + "line with trailing space" + CRLF + + "line with space" + CRLF + + "--" + CRLF + + "Toorop" + CRLF func Test_NewSigOptions(t *testing.T) { options := NewSigOptions() @@ -107,3 +122,20 @@ func Test_Sign(t *testing.T) { emailReader, err := Sign(emailReader, options) assert.NoError(t, err) } + +func Test_canonicalize(t *testing.T) { + emailReader := bytes.NewReader([]byte(email)) + options := NewSigOptions() + // simple/simple + options.Canonicalization = "simple/simple" + _, body, err := canonicalize(emailReader, options) + assert.NoError(t, err) + assert.Equal(t, []byte(bodySimple), body) + + // relaxed/relaxed + options.Canonicalization = "relaxed/relaxed" + _, body, err = canonicalize(emailReader, options) + assert.NoError(t, err) + assert.Equal(t, []byte(bodyRelaxed), body) + +} diff --git a/errors.go b/errors.go index 640df8e..4e18de3 100644 --- a/errors.go +++ b/errors.go @@ -21,5 +21,8 @@ var ( ErrSignBadCanonicalization = errors.New("bad Canonicalization parameter") // Bad algorithm - ErrSignBadAlgo = errors.New("bar algorithm. Only rsa-sha1 or rsa-sha256 are permitted") + ErrSignBadAlgo = errors.New("bad algorithm. Only rsa-sha1 or rsa-sha256 are permitted") + + // ErrBadMailFormat + ErrBadMailFormat = errors.New("bad mail formart") )