mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 05:40:50 +01:00
feat: s/mime singing supports quoted printable encoding, also added tests
This commit is contained in:
parent
cc4c5bfd04
commit
faffc025cb
3 changed files with 131 additions and 13 deletions
7
msg.go
7
msg.go
|
@ -2184,8 +2184,11 @@ func (m *Msg) signMessage(msg *Msg) (*Msg, error) {
|
||||||
|
|
||||||
// createSignaturePart creates an additional part that be used for storing the S/MIME signature of the given body
|
// 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) {
|
func (m *Msg) createSignaturePart(encoding Encoding, contentType ContentType, charSet Charset, body []byte) (*Part, error) {
|
||||||
message := m.sMime.prepareMessage(encoding, contentType, charSet, body)
|
message, err := m.sMime.prepareMessage(encoding, contentType, charSet, body)
|
||||||
signedMessage, err := m.sMime.signMessage(message)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
signedMessage, err := m.sMime.signMessage(*message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
29
smime.go
29
smime.go
|
@ -13,6 +13,7 @@ import (
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"mime/quotedprintable"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -119,8 +120,32 @@ func (sm *SMime) signMessage(message string) (*string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// createMessage prepares the message that will be used for the sign method later
|
// createMessage prepares the message that will be used for the sign method later
|
||||||
func (sm *SMime) prepareMessage(encoding Encoding, contentType ContentType, charset Charset, body []byte) string {
|
func (sm *SMime) prepareMessage(encoding Encoding, contentType ContentType, charset Charset, body []byte) (*string, error) {
|
||||||
return fmt.Sprintf("Content-Transfer-Encoding: %v\r\nContent-Type: %v; charset=%v\r\n\r\n%v", encoding, contentType, charset, string(body))
|
encodedMessage, err := sm.encodeMessage(encoding, string(body))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
preparedMessage := fmt.Sprintf("Content-Transfer-Encoding: %v\r\nContent-Type: %v; charset=%v\r\n\r\n%v", encoding, contentType, charset, *encodedMessage)
|
||||||
|
return &preparedMessage, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// encodeMessage encodes the message with the given encoding
|
||||||
|
func (sm *SMime) encodeMessage(encoding Encoding, message string) (*string, error) {
|
||||||
|
if encoding != EncodingQP {
|
||||||
|
return &message, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := bytes.Buffer{}
|
||||||
|
writer := quotedprintable.NewWriter(&buffer)
|
||||||
|
if _, err := writer.Write([]byte(message)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := writer.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encodedMessage := buffer.String()
|
||||||
|
|
||||||
|
return &encodedMessage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeToPEM uses the method pem.Encode from the standard library but cuts the typical PEM preamble
|
// encodeToPEM uses the method pem.Encode from the standard library but cuts the typical PEM preamble
|
||||||
|
|
108
smime_test.go
108
smime_test.go
|
@ -121,19 +121,109 @@ func TestPrepareMessage(t *testing.T) {
|
||||||
contentType := TypeTextPlain
|
contentType := TypeTextPlain
|
||||||
charset := CharsetUTF8
|
charset := CharsetUTF8
|
||||||
body := []byte("This is the body!")
|
body := []byte("This is the body!")
|
||||||
result := sMime.prepareMessage(encoding, contentType, charset, 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()) {
|
if !strings.Contains(*result, encoding.String()) {
|
||||||
t.Errorf("createMessage() did not return the correct encoding")
|
t.Errorf("prepareMessage() did not return the correct encoding")
|
||||||
}
|
}
|
||||||
if !strings.Contains(result, contentType.String()) {
|
if !strings.Contains(*result, contentType.String()) {
|
||||||
t.Errorf("createMessage() did not return the correct contentType")
|
t.Errorf("prepareMessage() did not return the correct contentType")
|
||||||
}
|
}
|
||||||
if !strings.Contains(result, string(body)) {
|
if !strings.Contains(*result, string(body)) {
|
||||||
t.Errorf("createMessage() did not return the correct 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)) {
|
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("createMessage() did not sucessfully create the message")
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue