mirror of
https://github.com/wneessen/go-mail.git
synced 2024-12-23 02:50:39 +01:00
334 lines
10 KiB
Go
334 lines
10 KiB
Go
// SPDX-FileCopyrightText: 2022-2023 The go-mail Authors
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package mail
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/ecdsa"
|
|
"crypto/rsa"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestGet_RSA(t *testing.T) {
|
|
p := privateKeyHolder{
|
|
ecdsa: nil,
|
|
rsa: &rsa.PrivateKey{},
|
|
}
|
|
|
|
if p.get() == nil {
|
|
t.Errorf("get() did not return the correct private key")
|
|
}
|
|
}
|
|
|
|
func TestGet_ECDSA(t *testing.T) {
|
|
p := privateKeyHolder{
|
|
ecdsa: &ecdsa.PrivateKey{},
|
|
rsa: nil,
|
|
}
|
|
|
|
if p.get() == nil {
|
|
t.Errorf("get() did not return the correct private key")
|
|
}
|
|
}
|
|
|
|
// TestNewSMimeWithRSA tests the newSMime method with RSA crypto material
|
|
func TestNewSMimeWithRSA(t *testing.T) {
|
|
privateKey, certificate, intermediateCertificate, err := getDummyRSACryptoMaterial()
|
|
if err != nil {
|
|
t.Errorf("Error getting dummy crypto material: %s", err)
|
|
}
|
|
|
|
sMime, err := newSMimeWithRSA(privateKey, certificate, intermediateCertificate)
|
|
if err != nil {
|
|
t.Errorf("Error creating new SMime from keyPair: %s", err)
|
|
}
|
|
|
|
if sMime.privateKey.rsa != privateKey {
|
|
t.Errorf("NewSMime() did not return the same private key")
|
|
}
|
|
if sMime.certificate != certificate {
|
|
t.Errorf("NewSMime() did not return the same certificate")
|
|
}
|
|
if sMime.intermediateCertificate != intermediateCertificate {
|
|
t.Errorf("NewSMime() did not return the same intermedidate certificate")
|
|
}
|
|
}
|
|
|
|
// TestNewSMimeWithECDSA tests the newSMime method with ECDSA crypto material
|
|
func TestNewSMimeWithECDSA(t *testing.T) {
|
|
privateKey, certificate, intermediateCertificate, err := getDummyECDSACryptoMaterial()
|
|
if err != nil {
|
|
t.Errorf("Error getting dummy crypto material: %s", err)
|
|
}
|
|
|
|
sMime, err := newSMimeWithECDSA(privateKey, certificate, intermediateCertificate)
|
|
if err != nil {
|
|
t.Errorf("Error creating new SMime from keyPair: %s", err)
|
|
}
|
|
|
|
if sMime.privateKey.ecdsa != privateKey {
|
|
t.Errorf("NewSMime() did not return the same private key")
|
|
}
|
|
if sMime.certificate != certificate {
|
|
t.Errorf("NewSMime() did not return the same certificate")
|
|
}
|
|
if sMime.intermediateCertificate != intermediateCertificate {
|
|
t.Errorf("NewSMime() did not return the same intermedidate certificate")
|
|
}
|
|
}
|
|
|
|
// TestSign tests the sign method
|
|
func TestSign(t *testing.T) {
|
|
privateKey, certificate, intermediateCertificate, err := getDummyRSACryptoMaterial()
|
|
if err != nil {
|
|
t.Errorf("Error getting dummy crypto material: %s", err)
|
|
}
|
|
|
|
sMime, err := newSMimeWithRSA(privateKey, certificate, intermediateCertificate)
|
|
if err != nil {
|
|
t.Errorf("Error creating new SMime from keyPair: %s", err)
|
|
}
|
|
|
|
message := "This is a test message"
|
|
singedMessage, err := sMime.signMessage(message)
|
|
if err != nil {
|
|
t.Errorf("Error creating singed message: %s", err)
|
|
}
|
|
|
|
if *singedMessage == message {
|
|
t.Errorf("Sign() did not work")
|
|
}
|
|
}
|
|
|
|
// TestPrepareMessage tests the createMessage method
|
|
func TestPrepareMessage(t *testing.T) {
|
|
privateKey, certificate, intermediateCertificate, err := getDummyRSACryptoMaterial()
|
|
if err != nil {
|
|
t.Errorf("Error getting dummy crypto material: %s", err)
|
|
}
|
|
|
|
sMime, err := newSMimeWithRSA(privateKey, certificate, intermediateCertificate)
|
|
if err != nil {
|
|
t.Errorf("Error creating new SMime from keyPair: %s", err)
|
|
}
|
|
|
|
encoding := EncodingB64
|
|
contentType := TypeTextPlain
|
|
charset := CharsetUTF8
|
|
body := []byte("This is the body!")
|
|
result, err := sMime.prepareMessage(encoding, contentType, charset, body)
|
|
if err != nil {
|
|
t.Errorf("Error preparing message: %s", err)
|
|
}
|
|
|
|
if !strings.Contains(*result, encoding.String()) {
|
|
t.Errorf("prepareMessage() did not return the correct encoding")
|
|
}
|
|
if !strings.Contains(*result, contentType.String()) {
|
|
t.Errorf("prepareMessage() did not return the correct contentType")
|
|
}
|
|
if !strings.Contains(*result, string(body)) {
|
|
t.Errorf("prepareMessage() did not return the correct body")
|
|
}
|
|
if *result != fmt.Sprintf("Content-Transfer-Encoding: %s\r\nContent-Type: %s; charset=%s\r\n\r\n%s", encoding, contentType, charset, string(body)) {
|
|
t.Errorf("prepareMessage() did not sucessfully create the message")
|
|
}
|
|
}
|
|
|
|
// TestPrepareMessage_QuotedPrintable tests the prepareMessage method with quoted printable encoding
|
|
func TestPrepareMessage_QuotedPrintable(t *testing.T) {
|
|
privateKey, certificate, intermediateCertificate, err := getDummyRSACryptoMaterial()
|
|
if err != nil {
|
|
t.Errorf("Error getting dummy crypto material: %s", err)
|
|
}
|
|
|
|
sMime, err := newSMimeWithRSA(privateKey, certificate, intermediateCertificate)
|
|
if err != nil {
|
|
t.Errorf("Error creating new SMime from keyPair: %s", err)
|
|
}
|
|
|
|
body := "This is the body with special chars like äöü ÄÖÜ ß!"
|
|
quotedPrintableBody := "This is the body with special chars like =C3=A4=C3=B6=C3=BC =C3=84=C3=96=C3=\r\n=9C =C3=9F!"
|
|
encoding := EncodingQP
|
|
contentType := TypeTextPlain
|
|
charset := CharsetUTF8
|
|
result, err := sMime.prepareMessage(encoding, contentType, charset, []byte(body))
|
|
if err != nil {
|
|
t.Errorf("Error preparing message: %s", err)
|
|
}
|
|
|
|
if !strings.Contains(*result, encoding.String()) {
|
|
t.Errorf("prepareMessage() did not return the correct encoding")
|
|
}
|
|
if !strings.Contains(*result, contentType.String()) {
|
|
t.Errorf("prepareMessage() did not return the correct contentType")
|
|
}
|
|
if !strings.Contains(*result, quotedPrintableBody) {
|
|
t.Errorf("prepareMessage() did not return the correct body")
|
|
}
|
|
if *result != fmt.Sprintf("Content-Transfer-Encoding: %s\r\nContent-Type: %s; charset=%s\r\n\r\n%s", encoding, contentType, charset, quotedPrintableBody) {
|
|
t.Errorf("prepareMessage() did not sucessfully create the message")
|
|
}
|
|
}
|
|
|
|
// TestEncodeMessage tests the TestEncodeMessage method without any encoding
|
|
func TestEncodeMessage(t *testing.T) {
|
|
body := "This is the body with special chars like äöü ÄÖÜ ß!"
|
|
encoding := EncodingUSASCII
|
|
|
|
privateKey, certificate, intermediateCertificate, err := getDummyRSACryptoMaterial()
|
|
if err != nil {
|
|
t.Errorf("Error getting dummy crypto material: %s", err)
|
|
}
|
|
|
|
sMime, err := newSMimeWithRSA(privateKey, certificate, intermediateCertificate)
|
|
if err != nil {
|
|
t.Errorf("Error creating new SMime from keyPair: %s", err)
|
|
}
|
|
|
|
result, err := sMime.encodeMessage(encoding, body)
|
|
if err != nil {
|
|
t.Errorf("Error preparing message: %s", err)
|
|
}
|
|
|
|
if *result != body {
|
|
t.Errorf("encodeMessage() did not return the correct encoded message: %s", *result)
|
|
}
|
|
}
|
|
|
|
// TestEncodeMessage_QuotedPrintable tests the TestEncodeMessage method with quoted printable body
|
|
func TestEncodeMessage_QuotedPrintable(t *testing.T) {
|
|
body := "This is the body with special chars like äöü ÄÖÜ ß!"
|
|
quotedPrintableBody := "This is the body with special chars like =C3=A4=C3=B6=C3=BC =C3=84=C3=96=C3=\r\n=9C =C3=9F!"
|
|
encoding := EncodingQP
|
|
|
|
privateKey, certificate, intermediateCertificate, err := getDummyRSACryptoMaterial()
|
|
if err != nil {
|
|
t.Errorf("Error getting dummy crypto material: %s", err)
|
|
}
|
|
|
|
sMime, err := newSMimeWithRSA(privateKey, certificate, intermediateCertificate)
|
|
if err != nil {
|
|
t.Errorf("Error creating new SMime from keyPair: %s", err)
|
|
}
|
|
|
|
result, err := sMime.encodeMessage(encoding, body)
|
|
if err != nil {
|
|
t.Errorf("Error preparing message: %s", err)
|
|
}
|
|
|
|
if *result != quotedPrintableBody {
|
|
t.Errorf("encodeMessage() did not return the correct encoded message: %s", *result)
|
|
}
|
|
}
|
|
|
|
// TestEncodeToPEM tests the encodeToPEM method
|
|
func TestEncodeToPEM(t *testing.T) {
|
|
message := []byte("This is a test message")
|
|
|
|
pemMessage, err := encodeToPEM(message)
|
|
if err != nil {
|
|
t.Errorf("Error encoding message: %s", err)
|
|
}
|
|
|
|
base64Encoded := base64.StdEncoding.EncodeToString(message)
|
|
if *pemMessage != base64Encoded {
|
|
t.Errorf("encodeToPEM() did not work")
|
|
}
|
|
}
|
|
|
|
// TestBytesFromLines tests the bytesFromLines method
|
|
func TestBytesFromLines(t *testing.T) {
|
|
ls := lines{
|
|
{line: []byte("Hello"), endOfLine: []byte("\n")},
|
|
{line: []byte("World"), endOfLine: []byte("\n")},
|
|
}
|
|
expected := []byte("Hello\nWorld\n")
|
|
|
|
result := ls.bytesFromLines([]byte("\n"))
|
|
if !bytes.Equal(result, expected) {
|
|
t.Errorf("Expected %s, but got %s", expected, result)
|
|
}
|
|
}
|
|
|
|
// FuzzBytesFromLines tests the bytesFromLines method with fuzzing
|
|
func FuzzBytesFromLines(f *testing.F) {
|
|
f.Add([]byte("Hello"), []byte("\n"))
|
|
f.Fuzz(func(t *testing.T, lineData, sep []byte) {
|
|
ls := lines{
|
|
{line: lineData, endOfLine: sep},
|
|
}
|
|
_ = ls.bytesFromLines(sep)
|
|
})
|
|
}
|
|
|
|
// TestParseLines tests the parseLines method
|
|
func TestParseLines(t *testing.T) {
|
|
input := []byte("Hello\r\nWorld\nHello\rWorld")
|
|
expected := lines{
|
|
{line: []byte("Hello"), endOfLine: []byte("\r\n")},
|
|
{line: []byte("World"), endOfLine: []byte("\n")},
|
|
{line: []byte("Hello"), endOfLine: []byte("\r")},
|
|
{line: []byte("World"), endOfLine: []byte("")},
|
|
}
|
|
|
|
result := parseLines(input)
|
|
if len(result) != len(expected) {
|
|
t.Errorf("Expected %d lines, but got %d", len(expected), len(result))
|
|
}
|
|
|
|
for i := range result {
|
|
if !bytes.Equal(result[i].line, expected[i].line) || !bytes.Equal(result[i].endOfLine, expected[i].endOfLine) {
|
|
t.Errorf("Line %d mismatch. Expected line: %s, endOfLine: %s, got line: %s, endOfLine: %s",
|
|
i, expected[i].line, expected[i].endOfLine, result[i].line, result[i].endOfLine)
|
|
}
|
|
}
|
|
}
|
|
|
|
// FuzzParseLines tests the parseLines method with fuzzing
|
|
func FuzzParseLines(f *testing.F) {
|
|
f.Add([]byte("Hello\nWorld\r\nAnother\rLine"))
|
|
f.Fuzz(func(t *testing.T, input []byte) {
|
|
_ = parseLines(input)
|
|
})
|
|
}
|
|
|
|
// TestSplitLine tests the splitLine method
|
|
func TestSplitLine(t *testing.T) {
|
|
ls := lines{
|
|
{line: []byte("Hello\r\nWorld\r\nAnotherLine"), endOfLine: []byte("")},
|
|
}
|
|
expected := lines{
|
|
{line: []byte("Hello"), endOfLine: []byte("\r\n")},
|
|
{line: []byte("World"), endOfLine: []byte("\r\n")},
|
|
{line: []byte("AnotherLine"), endOfLine: []byte("")},
|
|
}
|
|
|
|
result := ls.splitLine([]byte("\r\n"))
|
|
if len(result) != len(expected) {
|
|
t.Errorf("Expected %d lines, but got %d", len(expected), len(result))
|
|
}
|
|
|
|
for i := range result {
|
|
if !bytes.Equal(result[i].line, expected[i].line) || !bytes.Equal(result[i].endOfLine, expected[i].endOfLine) {
|
|
t.Errorf("Line %d mismatch. Expected line: %s, endOfLine: %s, got line: %s, endOfLine: %s",
|
|
i, expected[i].line, expected[i].endOfLine, result[i].line, result[i].endOfLine)
|
|
}
|
|
}
|
|
}
|
|
|
|
// FuzzSplitLine tests the parseLsplitLineines method with fuzzing
|
|
func FuzzSplitLine(f *testing.F) {
|
|
f.Add([]byte("Hello\r\nWorld"), []byte("\r\n"))
|
|
f.Fuzz(func(t *testing.T, input, sep []byte) {
|
|
ls := lines{
|
|
{line: input, endOfLine: []byte("")},
|
|
}
|
|
_ = ls.splitLine(sep)
|
|
})
|
|
}
|