func sizeAndHashOf(p gmime.Part) (int, string) { dataWrapper := p.ContentObject() memStream := gmime.NewMemStream() c := dataWrapper.WriteToStream(memStream) memStream.Flush() data := memStream.Bytes() hasher := md5.New() hasher.Write(data) hashString := hex.EncodeToString(hasher.Sum(nil)) return int(c), hashString }
// "Parsing a Delivery Status Notification (DSN) for a bounce" func ParsingADeliveryStatusNotification(t *testing.T) { data, err := ioutil.ReadFile("fixtures/DSN-bounce.eml") assert.NoError(t, err) stream := gmime.NewMemStreamWithBuffer(string(data)) parser := gmime.NewParserWithStream(stream) message := parser.ConstructMessage() // "When the message has been constructed" { // "should have a hash that matches the hash of the file on disk" { h := sha1.New() h.Write([]byte(message.ToString())) assert.Equal(t, hex.EncodeToString(h.Sum(nil)), "fca9901a01ab33448c0b8c5f64f9f19404560234") } } // "When the iterator on the message is run" { var report gmime.Multipart var preamble gmime.Part var status gmime.Part var rfc822 gmime.MessagePart var ok bool iter := gmime.NewPartIter(message) // "should show the message mime part is a multipart/report container" { report, ok = iter.Current().(gmime.Multipart) assert.True(t, ok) container := report assert.NotNil(t, container) contentType := strings.ToLower(container.ContentType().ToString()) assert.Equal(t, contentType, "multipart/report") } iter.Next() // "should have a human-readable preamble for the bounced message" { preamble, ok = iter.Current().(gmime.Part) assert.True(t, ok) assert.NotNil(t, preamble) contentType := strings.ToLower(preamble.ContentType().ToString()) assert.Equal(t, contentType, "text/plain") header, ok := preamble.Header("Content-Description") assert.True(t, ok) assert.Equal(t, header, "Notification") explanation := preamble.ToString() assert.Contains(t, explanation, "not able to be") assert.Contains(t, explanation, "delivered to one of its intended recipients") assert.Contains(t, explanation, "550 5.1.1 sid=i01K1n00l0kn1Em01 Address rejected [email protected]. [code=28]") } iter.Next() // "should have a machine-readable message/delivery-status for the bounced message" { status, ok = iter.Current().(gmime.Part) assert.True(t, ok) assert.NotNil(t, status) contentType := strings.ToLower(status.ContentType().ToString()) assert.Equal(t, contentType, "message/delivery-status") header, ok := status.Header("Action") assert.True(t, ok) assert.Equal(t, header, "failed") header, ok = status.Header("Status") assert.True(t, ok) assert.Equal(t, header, "5.1.1") assert.Contains(t, status.ToString(), "Arrival-Date: 2014-03-26 00-01-19") assert.Contains(t, status.ToString(), "Diagnostic-Code: 550 5.1.1 sid=i01K1n00l0kn1Em01 Address rejected [email protected]. [code=28]") } iter.Next() // "should return a non-nil RFC822 container as one of the parts" { rfc822, ok = iter.Current().(gmime.MessagePart) assert.True(t, ok) assert.NotNil(t, rfc822) contentType := strings.ToLower(rfc822.ContentType().ToString()) assert.Equal(t, contentType, "message/rfc822") header, ok := rfc822.Header("Content-Description") assert.True(t, ok) assert.Equal(t, header, "Undelivered Message") } // "When examining the container part of the original message" { original := rfc822.Message() assert.NotNil(t, original) part := original.MimePart() contentType := strings.ToLower(part.ContentType().ToString()) assert.Equal(t, contentType, "multipart/alternative") // "should have enough information to be able to record the bounce" { header, ok := original.Header("To") assert.True(t, ok) assert.Equal(t, header, "*****@*****.**") // These headers encode things like user id, etc. header, ok = original.Header("X-SG-EID") assert.True(t, ok) assert.NotNil(t, header) header, ok = original.Header("X-SG-ID") assert.True(t, ok) assert.NotNil(t, header) } } } }