diff --git a/msg.go b/msg.go index e0d83d6..c0327a9 100644 --- a/msg.go +++ b/msg.go @@ -25,7 +25,7 @@ import ( ) var ( - // ErrNoFromAddress should be used when a FROM address is requrested but not set + // ErrNoFromAddress should be used when a FROM address is requested but not set ErrNoFromAddress = errors.New("no FROM address set") // ErrNoRcptAddresses should be used when the list of RCPTs is empty @@ -1000,15 +1000,15 @@ func (m *Msg) signMessage(msg *Msg) (*Msg, error) { return m, err } +// createSignaturePart creates an additional part that be used for storing the S/MIME signature of the given body func (m *Msg) createSignaturePart(encoding Encoding, contentType ContentType, charSet Charset, body []byte) (*Part, error) { - message := m.sMime.createMessage(encoding, contentType, charSet, body) - signaturePart := m.newPart(typeSMimeSigned, WithPartEncoding(EncodingB64), WithSMimeSinging()) - + message := m.sMime.prepareMessage(encoding, contentType, charSet, body) signedMessage, err := m.sMime.signMessage(message) if err != nil { return nil, err } + signaturePart := m.newPart(typeSMimeSigned, WithPartEncoding(EncodingB64), WithSMimeSinging()) signaturePart.SetContent(*signedMessage) return signaturePart, nil diff --git a/msg_test.go b/msg_test.go index 9464a50..192af62 100644 --- a/msg_test.go +++ b/msg_test.go @@ -1911,6 +1911,22 @@ func TestMsg_hasAltWithSMime(t *testing.T) { } } +// TestMsg_hasSMime tests the hasSMime() method of the Msg +func TestMsg_hasSMime(t *testing.T) { + keyPair, err := getDummyCertificate() + if err != nil { + t.Errorf("failed to load dummy certificate. Cause: %v", err) + } + m := NewMsg() + if err := m.SignWithSMime(keyPair); err != nil { + t.Errorf("set of certificate was not successful") + } + m.SetBodyString(TypeTextPlain, "Plain") + if !m.hasSMime() { + t.Errorf("mail has smime configured but hasSMime() returned true") + } +} + // TestMsg_hasRelated tests the hasRelated() method of the Msg func TestMsg_hasRelated(t *testing.T) { m := NewMsg() @@ -1978,6 +1994,70 @@ func TestMsg_WriteToSkipMiddleware(t *testing.T) { } } +// TestMsg_WriteToWithSMIME tests the WriteTo() method of the Msg +func TestMsg_WriteToWithSMIME(t *testing.T) { + keyPair, err := getDummyCertificate() + if err != nil { + t.Errorf("failed to load dummy certificate. Cause: %v", err) + } + + m := NewMsg() + m.Subject("This is a test") + m.SetBodyString(TypeTextPlain, "Plain") + if err := m.SignWithSMime(keyPair); err != nil { + t.Errorf("set of certificate was not successful") + } + + wbuf := bytes.Buffer{} + if _, err = m.WriteTo(&wbuf); err != nil { + t.Errorf("WriteTo() failed: %s", err) + } + + result := wbuf.String() + boundary := result[strings.LastIndex(result, "--")-60 : strings.LastIndex(result, "--")] + if strings.Count(result, boundary) != 4 { + t.Errorf("WriteTo() failed. False number of boundaries found") + } + + parts := strings.Split(result, fmt.Sprintf("--%s", boundary)) + if len(parts) != 4 { + t.Errorf("WriteTo() failed. False number of parts found") + } + + preamble := parts[0] + if !strings.Contains(preamble, "MIME-Version: 1.0") { + t.Errorf("WriteTo() failed. Unable to find MIME-Version") + } + if !strings.Contains(preamble, "Subject: This is a test") { + t.Errorf("WriteTo() failed. Unable to find subject") + } + if !strings.Contains(preamble, fmt.Sprintf("Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha-256;\r\n boundary=%s", boundary)) { + t.Errorf("WriteTo() failed. Unable to find Content-Type") + } + + signedData := parts[1] + if !strings.Contains(signedData, "Content-Transfer-Encoding: quoted-printable") { + t.Errorf("WriteTo() failed. Unable to find Content-Transfer-Encoding") + } + if !strings.Contains(signedData, "Content-Type: text/plain; charset=UTF-8") { + t.Errorf("WriteTo() failed. Unable to find Content-Type") + } + if !strings.Contains(signedData, "Plain") { + t.Errorf("WriteTo() failed. Unable to find Content") + } + + signature := parts[2] + if !strings.Contains(signature, "Content-Transfer-Encoding: base64") { + t.Errorf("WriteTo() failed. Unable to find Content-Transfer-Encoding") + } + if !strings.Contains(signature, `application/pkcs7-signature; name="smime.p7s"`) { + t.Errorf("WriteTo() failed. Unable to find Content-Type") + } + if strings.Contains(signature, "Plain") { + t.Errorf("WriteTo() failed. Unable to find signature") + } +} + // TestMsg_WriteTo_fails tests the WriteTo() method of the Msg but with a failing body writer function func TestMsg_WriteTo_fails(t *testing.T) { m := NewMsg() @@ -3266,9 +3346,6 @@ func TestSignWithSMime_ValidKeyPair(t *testing.T) { if m.sMime.certificate == nil { t.Errorf("WithSMimeSinging() - no certificate is given") } - if len(m.sMime.parentCertificates) != len(keyPair.Certificate[:1]) { - t.Errorf("WithSMimeSinging() - no certificate is given") - } } // TestSignWithSMime_InvalidKeyPair tests WithSMimeSinging with given invalid key pair