diff --git a/msg_test.go b/msg_test.go index e133397..6e35d49 100644 --- a/msg_test.go +++ b/msg_test.go @@ -1894,6 +1894,23 @@ func TestMsg_hasAlt(t *testing.T) { } } +// TestMsg_hasAlt tests the hasAlt() method of the Msg with active S/MIME +func TestMsg_hasAltWithSMime(t *testing.T) { + keyPair, err := getDummyCertificate() + if err != nil { + t.Errorf("failed to load dummy certificate. Cause: %v", err) + } + m := NewMsg() + m.SetBodyString(TypeTextPlain, "Plain") + m.AddAlternativeString(TypeTextHTML, "HTML") + if err := m.SignWithSMime(keyPair); err != nil { + t.Errorf("set of certificate was not successful") + } + if m.hasAlt() { + t.Errorf("mail has alternative parts and S/MIME is active, but hasAlt() returned true") + } +} + // TestMsg_hasRelated tests the hasRelated() method of the Msg func TestMsg_hasRelated(t *testing.T) { m := NewMsg() @@ -3233,32 +3250,33 @@ func TestNewMsgWithNoDefaultUserAgent(t *testing.T) { } } -// TestWithSMimeSinging_ValidPrivateKey tests WithSMimeSinging with given privateKey -func TestWithSMimeSinging_ValidPrivateKey(t *testing.T) { - privateKey, err := getDummyPrivateKey() +// TestSignWithSMime_ValidKeyPair tests WithSMimeSinging with given key pair +func TestSignWithSMime_ValidKeyPair(t *testing.T) { + keyPair, err := getDummyCertificate() if err != nil { - t.Errorf("failed to load dummy private key: %s", err) + t.Errorf("failed to load dummy certificate. Cause: %v", err) } - certificate, err := getDummyCertificate(privateKey) - if err != nil { - t.Errorf("failed to load dummy certificate: %s", err) - } - m := NewMsg() - if err := m.SignWithSMime(privateKey, certificate); err != nil { + if err := m.SignWithSMime(keyPair); err != nil { t.Errorf("failed to set sMime. Cause: %v", err) } - if m.sMime.privateKey != privateKey { - t.Errorf("WithSMimeSinging. Expected %v, got: %v", privateKey, m.sMime.privateKey) + if m.sMime.privateKey == nil { + t.Errorf("WithSMimeSinging() - no private key is given") + } + 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") } } -// TestWithSMimeSinging_InvalidPrivateKey tests WithSMimeSinging with given invalid privateKey -func TestWithSMimeSinging_InvalidPrivateKey(t *testing.T) { +// TestSignWithSMime_InvalidKeyPair tests WithSMimeSinging with given invalid key pair +func TestSignWithSMime_InvalidKeyPair(t *testing.T) { m := NewMsg() - err := m.SignWithSMime(nil, nil) - if !errors.Is(err, ErrInvalidPrivateKey) { + err := m.SignWithSMime(nil) + if !errors.Is(err, ErrInvalidKeyPair) { t.Errorf("failed to check sMimeAuthConfig values correctly: %s", err) } } @@ -3290,3 +3308,83 @@ func FuzzMsg_From(f *testing.F) { m.Reset() }) } + +// TestMsg_createSignaturePart tests the Msg.createSignaturePart method +func TestMsg_createSignaturePart(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") + } + body := []byte("This is the body") + part, err := m.createSignaturePart(EncodingQP, TypeTextPlain, CharsetUTF7, body) + if err != nil { + t.Errorf("createSignaturePart() method failed.") + } + + if part.GetEncoding() != EncodingB64 { + t.Errorf("createSignaturePart() method failed. Expected encoding: %s, got: %s", EncodingB64, part.GetEncoding()) + } + if part.GetContentType() != typeSMimeSigned { + t.Errorf("createSignaturePart() method failed. Expected content type: %s, got: %s", typeSMimeSigned, part.GetContentType()) + } + if part.GetCharset() != CharsetUTF8 { + t.Errorf("createSignaturePart() method failed. Expected charset: %s, got: %s", CharsetUTF8, part.GetCharset()) + } + if content, err := part.GetContent(); err != nil || len(content) == len(body) { + t.Errorf("createSignaturePart() method failed. Expected content should not be equal: %s, got: %s", body, part.GetEncoding()) + } +} + +// TestMsg_signMessage tests the Msg.signMessage method +func TestMsg_signMessage(t *testing.T) { + keyPair, err := getDummyCertificate() + if err != nil { + t.Errorf("failed to load dummy certificate. Cause: %v", err) + } + m := NewMsg() + body := []byte("This is the body") + if err := m.SignWithSMime(keyPair); err != nil { + t.Errorf("set of certificate was not successful") + } + msg, err := m.signMessage(m) + if err != nil { + t.Errorf("createSignaturePart() method failed.") + } + + parts := msg.GetParts() + if len(parts) != 2 { + t.Errorf("createSignaturePart() method failed. Expected 2 parts, got: %d", len(parts)) + } + + signedPart := parts[0] + if signedPart.GetEncoding() != EncodingQP { + t.Errorf("createSignaturePart() method failed. Expected encoding: %s, got: %s", EncodingB64, signedPart.GetEncoding()) + } + if signedPart.GetContentType() != TypeTextPlain { + t.Errorf("createSignaturePart() method failed. Expected content type: %s, got: %s", typeSMimeSigned, signedPart.GetContentType()) + } + if signedPart.GetCharset() != CharsetUTF8 { + t.Errorf("createSignaturePart() method failed. Expected charset: %s, got: %s", CharsetUTF8, signedPart.GetCharset()) + } + if content, err := signedPart.GetContent(); err != nil || len(content) != len(body) { + t.Errorf("createSignaturePart() method failed. Expected content should be equal: %s, got: %s", body, content) + } + + signaturePart := parts[1] + if signaturePart.GetEncoding() != EncodingB64 { + t.Errorf("createSignaturePart() method failed. Expected encoding: %s, got: %s", EncodingB64, signaturePart.GetEncoding()) + } + if signaturePart.GetContentType() != typeSMimeSigned { + t.Errorf("createSignaturePart() method failed. Expected content type: %s, got: %s", typeSMimeSigned, signaturePart.GetContentType()) + } + if signaturePart.GetCharset() != CharsetUTF8 { + t.Errorf("createSignaturePart() method failed. Expected charset: %s, got: %s", CharsetUTF8, signaturePart.GetCharset()) + } + if content, err := signaturePart.GetContent(); err != nil || len(content) == len(body) { + t.Errorf("createSignaturePart() method failed. Expected content should not be equal: %s, got: %s", body, signaturePart.GetEncoding()) + } +} diff --git a/msgwriter_test.go b/msgwriter_test.go index a41e5d3..ca1a982 100644 --- a/msgwriter_test.go +++ b/msgwriter_test.go @@ -154,3 +154,26 @@ func TestMsgWriter_writeMsg_PGP(t *testing.T) { t.Errorf("writeMsg failed. Expected PGP encoding header but didn't find it in message output") } } + +// TestMsgWriter_writeMsg_SMime tests the writeMsg method of the msgWriter with S/MIME types set +func TestMsgWriter_writeMsg_SMime(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.From(`"Toni Tester" `) + _ = m.To(`"Toni Receiver" `) + m.Subject("This is a subject") + m.SetBodyString(TypeTextPlain, "This is the body") + buf := bytes.Buffer{} + mw := &msgWriter{writer: &buf, charset: CharsetUTF8, encoder: mime.QEncoding} + mw.writeMsg(m) + ms := buf.String() + if !strings.Contains(ms, `multipart/signed; protocol="application/pkcs7-signature"; micalg=sha256;`) { + t.Errorf("writeMsg failed. Expected PGP encoding header but didn't find it in message output") + } +} diff --git a/util_test.go b/util_test.go index efc088c..8f235ed 100644 --- a/util_test.go +++ b/util_test.go @@ -1,41 +1,19 @@ package mail import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "math/big" - "time" + "crypto/tls" ) -func getDummyPrivateKey() (*rsa.PrivateKey, error) { - privateKey, err := rsa.GenerateKey(rand.Reader, 2048) +const ( + certFilePath = "dummy-cert.pem" + keyFilePath = "dummy=key.pem" +) + +func getDummyCertificate() (*tls.Certificate, error) { + keyPair, err := tls.LoadX509KeyPair(certFilePath, keyFilePath) if err != nil { return nil, err } - return privateKey, nil -} - -func getDummyCertificate(privateKey *rsa.PrivateKey) (*x509.Certificate, error) { - template := &x509.Certificate{ - SerialNumber: big.NewInt(1234), - Subject: pkix.Name{Organization: []string{"My Organization"}}, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(1, 0, 0), - KeyUsage: x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - } - - certDER, err := x509.CreateCertificate(rand.Reader, template, template, &privateKey.PublicKey, privateKey) - if err != nil { - return nil, err - } - - cert, err := x509.ParseCertificate(certDER) - if err != nil { - return nil, err - } - - return cert, nil + + return &keyPair, nil }