diff --git a/pkg/message/section_test.go b/pkg/message/section_test.go index 69eaebee..1a1e4f26 100644 --- a/pkg/message/section_test.go +++ b/pkg/message/section_test.go @@ -20,6 +20,7 @@ package message import ( "bytes" "fmt" + "io/ioutil" "net/textproto" "path/filepath" "runtime" @@ -70,7 +71,7 @@ func TestParseBodyStructure(t *testing.T) { debug("%10s: %-50s %5s %5s %5s %5s", "section", "type", "start", "size", "bsize", "lines") for _, path := range paths { sec := (*bs)[path] - contentType := sec.Header.Get("Content-Type") + contentType := (*bs)[path].Header.Get("Content-Type") debug("%10s: %-50s %5d %5d %5d %5d", path, contentType, sec.Start, sec.Size, sec.BSize, sec.Lines) require.Equal(t, expectedStructure[path], contentType) } @@ -78,6 +79,38 @@ func TestParseBodyStructure(t *testing.T) { require.True(t, len(*bs) == len(expectedStructure), "Wrong number of sections expected %d but have %d", len(expectedStructure), len(*bs)) } +func TestParseBodyStructurePGP(t *testing.T) { + expectedStructure := map[string]string{ + "": "multipart/signed; micalg=pgp-sha256; protocol=\"application/pgp-signature\"; boundary=\"MHEDFShwcX18dyE3X7RXujo5fjpgdjHNM\"", + "1": "multipart/mixed; boundary=\"FBBl2LNv76z8UkvHhSkT9vLwVwxqV8378\"; protected-headers=\"v1\"", + "1.1": "multipart/mixed; boundary=\"------------F97C8ED4878E94675762AE43\"", + "1.1.1": "multipart/alternative; boundary=\"------------041318B15DD3FA540FED32C6\"", + "1.1.1.1": "text/plain; charset=utf-8; format=flowed", + "1.1.1.2": "text/html; charset=utf-8", + "1.1.2": "application/pdf; name=\"minimal.pdf\"", + "1.1.3": "application/pgp-keys; name=\"OpenPGP_0x161C0875822359F7.asc\"", + "2": "application/pgp-signature; name=\"OpenPGP_signature.asc\"", + } + + b, err := ioutil.ReadFile("testdata/enc-body-structure.eml") + require.NoError(t, err) + + bs, err := NewBodyStructure(bytes.NewReader(b)) + require.NoError(t, err) + + paths := []string{} + for path := range *bs { + paths = append(paths, path) + } + sort.Strings(paths) + + for _, path := range paths { + require.Equal(t, expectedStructure[path], (*bs)[path].Header.Get("Content-Type")) + } + + require.True(t, len(*bs) == len(expectedStructure), "Wrong number of sections expected %d but have %d", len(expectedStructure), len(*bs)) +} + func TestGetSection(t *testing.T) { structReader := strings.NewReader(sampleMail) bs, err := NewBodyStructure(structReader) diff --git a/pkg/message/testdata/enc-body-structure.eml b/pkg/message/testdata/enc-body-structure.eml new file mode 100644 index 00000000..726bf621 --- /dev/null +++ b/pkg/message/testdata/enc-body-structure.eml @@ -0,0 +1,164 @@ +Mime-Version: 1.0 +Content-Type: multipart/signed; micalg=pgp-sha256; + protocol="application/pgp-signature"; + boundary="MHEDFShwcX18dyE3X7RXujo5fjpgdjHNM" +Message-Id: +Date: Wed, 01 Jan 2020 00:00:00 +0000 + +This is an OpenPGP/MIME signed message (RFC 4880 and 3156) +--MHEDFShwcX18dyE3X7RXujo5fjpgdjHNM +Content-Type: multipart/mixed; boundary="FBBl2LNv76z8UkvHhSkT9vLwVwxqV8378"; + protected-headers="v1" +Subject: Alternative +From: "pm.bridge.qa" +To: schizofrenic@pm.me +Message-ID: <753d0314-0286-2c88-2abb-f8080ac7a4cb@gmail.com> + +--FBBl2LNv76z8UkvHhSkT9vLwVwxqV8378 +Content-Type: multipart/mixed; + boundary="------------F97C8ED4878E94675762AE43" +Content-Language: en-US + +This is a multi-part message in MIME format. +--------------F97C8ED4878E94675762AE43 +Content-Type: multipart/alternative; + boundary="------------041318B15DD3FA540FED32C6" + + +--------------041318B15DD3FA540FED32C6 +Content-Type: text/plain; charset=utf-8; format=flowed +Content-Transfer-Encoding: quoted-printable + +This Rich formated text + + * /What kind of shoes do ninjas wear? /*Sneakers!* + * /How does a penguin build its house?/**_/*Igloos it together.*/_ + + + + +--------------041318B15DD3FA540FED32C6 +Content-Type: text/html; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + + + + + + + +

This Rich formated text

+ +


+

+


+

+ + + +--------------041318B15DD3FA540FED32C6-- + +--------------F97C8ED4878E94675762AE43 +Content-Type: application/pdf; + name="minimal.pdf" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; + filename="minimal.pdf" + +JVBERi0xLjEKJcKlwrHDqwoKMSAwIG9iagogIDw8IC9UeXBlIC9DYXRhbG9nCiAgICAgL1Bh +Z2VzIDIgMCBSCiAgPj4KZW5kb2JqCgoyIDAgb2JqCiAgPDwgL1R5cGUgL1BhZ2VzCiAgICAg +L0tpZHMgWzMgMCBSXQogICAgIC9Db3VudCAxCiAgICAgL01lZGlhQm94IFswIDAgMzAwIDE0 +NF0KICA+PgplbmRvYmoKCjMgMCBvYmoKICA8PCAgL1R5cGUgL1BhZ2UKICAgICAgL1BhcmVu +dCAyIDAgUgogICAgICAvUmVzb3VyY2VzCiAgICAgICA8PCAvRm9udAogICAgICAgICAgIDw8 +IC9GMQogICAgICAgICAgICAgICA8PCAvVHlwZSAvRm9udAogICAgICAgICAgICAgICAgICAv +U3VidHlwZSAvVHlwZTEKICAgICAgICAgICAgICAgICAgL0Jhc2VGb250IC9UaW1lcy1Sb21h +bgogICAgICAgICAgICAgICA+PgogICAgICAgICAgID4+CiAgICAgICA+PgogICAgICAvQ29u +dGVudHMgNCAwIFIKICA+PgplbmRvYmoKCjQgMCBvYmoKICA8PCAvTGVuZ3RoIDU1ID4+CnN0 +cmVhbQogIEJUCiAgICAvRjEgMTggVGYKICAgIDAgMCBUZAogICAgKEhlbGxvIFdvcmxkKSBU +agogIEVUCmVuZHN0cmVhbQplbmRvYmoKCnhyZWYKMCA1CjAwMDAwMDAwMDAgNjU1MzUgZiAK +MDAwMDAwMDAxOCAwMDAwMCBuIAowMDAwMDAwMDc3IDAwMDAwIG4gCjAwMDAwMDAxNzggMDAw +MDAgbiAKMDAwMDAwMDQ1NyAwMDAwMCBuIAp0cmFpbGVyCiAgPDwgIC9Sb290IDEgMCBSCiAg +ICAgIC9TaXplIDUKICA+PgpzdGFydHhyZWYKNTY1CiUlRU9GCg== +--------------F97C8ED4878E94675762AE43 +Content-Type: application/pgp-keys; + name="OpenPGP_0x161C0875822359F7.asc" +Content-Transfer-Encoding: quoted-printable +Content-Disposition: attachment; + filename="OpenPGP_0x161C0875822359F7.asc" + +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xsBNBFxlUPwBCACx954Ey4SD88f8DSKFw9BaZNXrNwYxNYSgqaqOGHQ0WllF3mstEhTfuxxCZ= +pDh +I5IhWCXUNxanzsFkn88mRDwFRVl2sf2aAG4/P/p1381oh2kd0UElMRQaQGzoCadQMaQOL9WYT= +f4S +PWSCzjrPyKgjq5FbqjbF/ndu376na9L+tnsEXyL6RrI6aZhjWG73xlqxS65dzTIYzsyM/P97x= +Snd +NvlvWtGvLlpFkzxfAEGpVzfOYVYFKoc8rGmUDwrDWYfk5JczRDDogJnY+BNMZf9pjSqk6rTyB= +OfN +H5fpU8r7A5Q7l+HVakvMUQ9DzDWJtg2ru1Y8hexnJOF68avO4+a1ABEBAAHNKEJyaWRnZSBLe= +XUt +RWh5aiA8cG0uYnJpZGdlLnFhQGdtYWlsLmNvbT7CwJQEEwEIAD4CGwMFCwkIBwIGFQoJCAsCB= +BYC +AwECHgECF4AWIQRc5gl5cC8oW/Mo+bEWHAh1giNZ9wUCYC32ygUJB4sMzgAKCRAWHAh1giNZ9= +/K8 +B/4qs84Ii/zKH+q+C8vwO4jUJkOM73qD0pgB7zBs651zWbpgopyol1YUKNpFaHlx/Qch7RDI7= +Vcz +1+60/KZJSJR19/N2EDVbCUdh8ueioUp9X/218YWV2TRJNxTnljd4FAn7smZnXuP1TsLjQ6sKO= +V0U +u6JoiG6LZFXqDgxYpA++58Rkl6xaY6R71VkmVQlbEKtubX9AjHydq97Y+Jvn11XzWZaKhv4L7= +6Pa +4tMKXvvrKh1oywMmh6mZJo+5ZA/ABTkr45cwlTPYqGTS9+uvOHt+PH/oYwwJB4ls2cIAUldSj= +TVQ +IsseYz3LlbcCfKJiiCFxeHOQXA5J6zNLKOT58TsczsBNBFxlUPwBCADh2HsX23yVnJt9fxFz3= +D07 +kCBNvu4HQfps6h1rgNxGhE32VmpESHebvIB5xjL6xKbIqqRa3x/7KDVBNJvca0gUsqEt5kzYF= +88F +yf2NBcejpIbcP7BS/g+C6KOowYj+Et26T6GdwFXExUcl80JvoX8yHQOfvJpdiBRbjyB8UqfCa= +knm +3c7dNuXmhflz/w3aBj32q9ZyGqA1NpHCpLyVAlvSNQ/pat/rGUCPZ9duw4KhUUqEmatQPVFPk= +utT +ouEZQbMK+i+chOH3AsKCuNDfvCDwirnsSqIJmAgl1lC4de+bsWYCMqN9ei99hOCRUyhZ3g3sr= +8RB +owVAdcvjZxeIDKALABEBAAHCwHwEGAEIACYCGwwWIQRc5gl5cC8oW/Mo+bEWHAh1giNZ9wUCY= +C32 +lAUJB4sMmAAKCRAWHAh1giNZ9+Y2B/9rTKZaKviae+ummXNumXcrKvbkAAvfuLpKUn53FlQLm= +L6H +jB++lJnPWvVSzdZxdv8FiPP3d632XHKUrkQRQM/9byRDXDommi7Qttx7YCkhd4JLVYqJqpnAQ= +xI5 +RMkXiZNWyr1lz8JOM1XvDk1M7sJwPMWews8VOIE03E1nt7AsQGnvHtadgEnQaufrYNX3hFA8S= +osO +HSnedcys6yrzCSIGCqCD9VHbnMtS4DOv0XJGh2hwc8omzH0KZA517dyKBorJRwadcVauGXDKx= +Etv +Im4rl94PR/3An1Mj6HeeVVpLqDQ5Jb9J90BahWeQ53FzRa4EQzYCw0nLnxcsT1ZEEP5u +=3Dv/1p +-----END PGP PUBLIC KEY BLOCK----- + +--------------F97C8ED4878E94675762AE43-- + +--FBBl2LNv76z8UkvHhSkT9vLwVwxqV8378-- + +--MHEDFShwcX18dyE3X7RXujo5fjpgdjHNM +Content-Type: application/pgp-signature; name="OpenPGP_signature.asc" +Content-Description: OpenPGP digital signature +Content-Disposition: attachment; filename="OpenPGP_signature" + +-----BEGIN PGP SIGNATURE----- + +wsB5BAABCAAjFiEEXOYJeXAvKFvzKPmxFhwIdYIjWfcFAmBciUoFAwAAAAAACgkQFhwIdYIjWfez +rgf+NZCibnCUTovpWRVRiiPQtBPGeHUPEwz2xq2zz4AaqrHC2v4mYUIPe6am7INk8fkBLsa8Dj/A +UN/28Qh7tNb7JsXtHDT4PIoXszukQ8VIRbe09mSkkP6jR4WzNR166d6n3rSxzHpviOyQldjjpOMr +Zl7LxmgGr4ojsgCf6pvurWwCCOGJqbSusrD6JVv6DsmPmmQeBmnlTK/0oG9pnlNkugpNB1WS2K5d +RY6+kWkSrxbq95HrgILpHip8Y/+ITWvQocm14PBIAAdW8Hr7iFQLETFJ/KDA+VP19Bt8n4Kitdi8 +DPqMsV0oOhATqBjnD63AePJ0VWg8R1z6GEK5A+WOpg== +=Bc6p +-----END PGP SIGNATURE----- + +--MHEDFShwcX18dyE3X7RXujo5fjpgdjHNM--