mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 13:50:49 +01:00
Add support for 7bit and 8bit encodings in EML parsing
Enhanced EML parsing to handle 7bit and 8bit content transfer encodings. Updated related test cases to verify the correct handling of these encodings. This ensures compliance with RFC2045 for defaulting to 7bit when no encoding is specified.
This commit is contained in:
parent
a28cf14efd
commit
ed93e51cec
2 changed files with 161 additions and 2 deletions
18
eml.go
18
eml.go
|
@ -207,6 +207,12 @@ func parseEMLBodyParts(parsedMsg *netmail.Message, bodybuf *bytes.Buffer, msg *M
|
||||||
// parseEMLBodyPlain parses the mail body of plain type mails
|
// parseEMLBodyPlain parses the mail body of plain type mails
|
||||||
func parseEMLBodyPlain(mediatype string, parsedMsg *netmail.Message, bodybuf *bytes.Buffer, msg *Msg) error {
|
func parseEMLBodyPlain(mediatype string, parsedMsg *netmail.Message, bodybuf *bytes.Buffer, msg *Msg) error {
|
||||||
contentTransferEnc := parsedMsg.Header.Get(HeaderContentTransferEnc.String())
|
contentTransferEnc := parsedMsg.Header.Get(HeaderContentTransferEnc.String())
|
||||||
|
// According to RFC2045, if no Content-Transfer-Encoding is set, we can imply 7bit US-ASCII encoding
|
||||||
|
if contentTransferEnc == "" || strings.EqualFold(contentTransferEnc, EncodingUSASCII.String()) {
|
||||||
|
msg.SetEncoding(EncodingUSASCII)
|
||||||
|
msg.SetBodyString(ContentType(mediatype), bodybuf.String())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if strings.EqualFold(contentTransferEnc, NoEncoding.String()) {
|
if strings.EqualFold(contentTransferEnc, NoEncoding.String()) {
|
||||||
msg.SetEncoding(NoEncoding)
|
msg.SetEncoding(NoEncoding)
|
||||||
msg.SetBodyString(ContentType(mediatype), bodybuf.String())
|
msg.SetBodyString(ContentType(mediatype), bodybuf.String())
|
||||||
|
@ -308,14 +314,22 @@ ReadNextPart:
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
case strings.EqualFold(mutliPartTransferEnc[0], EncodingUSASCII.String()):
|
||||||
|
part.SetEncoding(EncodingUSASCII)
|
||||||
|
part.SetContent(string(multiPartData))
|
||||||
|
case strings.EqualFold(mutliPartTransferEnc[0], NoEncoding.String()):
|
||||||
|
part.SetEncoding(NoEncoding)
|
||||||
|
part.SetContent(string(multiPartData))
|
||||||
case strings.EqualFold(mutliPartTransferEnc[0], EncodingB64.String()):
|
case strings.EqualFold(mutliPartTransferEnc[0], EncodingB64.String()):
|
||||||
if err := handleEMLMultiPartBase64Encoding(multiPartData, part); err != nil {
|
part.SetEncoding(EncodingB64)
|
||||||
|
if err = handleEMLMultiPartBase64Encoding(multiPartData, part); err != nil {
|
||||||
return fmt.Errorf("failed to handle multipart base64 transfer-encoding: %w", err)
|
return fmt.Errorf("failed to handle multipart base64 transfer-encoding: %w", err)
|
||||||
}
|
}
|
||||||
case strings.EqualFold(mutliPartTransferEnc[0], EncodingQP.String()):
|
case strings.EqualFold(mutliPartTransferEnc[0], EncodingQP.String()):
|
||||||
|
part.SetEncoding(EncodingQP)
|
||||||
part.SetContent(string(multiPartData))
|
part.SetContent(string(multiPartData))
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported Content-Transfer-Encoding")
|
return fmt.Errorf("unsupported Content-Transfer-Encoding: %s", mutliPartTransferEnc[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.parts = append(msg.parts, part)
|
msg.parts = append(msg.parts, part)
|
||||||
|
|
145
eml_test.go
145
eml_test.go
|
@ -32,6 +32,29 @@ This is a test mail. Please do not reply to this. Also this line is very long so
|
||||||
should be wrapped.
|
should be wrapped.
|
||||||
|
|
||||||
|
|
||||||
|
Thank your for your business!
|
||||||
|
The go-mail team
|
||||||
|
|
||||||
|
--
|
||||||
|
This is a signature`
|
||||||
|
exampleMailPlain7Bit = `Date: Wed, 01 Nov 2023 00:00:00 +0000
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Message-ID: <1305604950.683004066175.AAAAAAAAaaaaaaaaB@go-mail.dev>
|
||||||
|
Subject: Example mail // plain text without encoding
|
||||||
|
User-Agent: go-mail v0.4.0 // https://github.com/wneessen/go-mail
|
||||||
|
X-Mailer: go-mail v0.4.0 // https://github.com/wneessen/go-mail
|
||||||
|
From: "Toni Tester" <go-mail@go-mail.dev>
|
||||||
|
To: <go-mail+test@go-mail.dev>
|
||||||
|
Cc: <go-mail+cc@go-mail.dev>
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
|
Dear Customer,
|
||||||
|
|
||||||
|
This is a test mail. Please do not reply to this. Also this line is very long so it
|
||||||
|
should be wrapped.
|
||||||
|
|
||||||
|
|
||||||
Thank your for your business!
|
Thank your for your business!
|
||||||
The go-mail team
|
The go-mail team
|
||||||
|
|
||||||
|
@ -525,6 +548,72 @@ hw22iFHl7YlpOmedZvtMTfQffXeXnvI+rTKNxguyvDKvB7U4qQAAAAlwSFlzAAALEwAACxMBAJqc
|
||||||
GAAAABFJREFUCJljnMoAA0wMNGcCAEQrAKk9oHKhAAAAAElFTkSuQmCC
|
GAAAABFJREFUCJljnMoAA0wMNGcCAEQrAKk9oHKhAAAAAElFTkSuQmCC
|
||||||
|
|
||||||
--fe785e0384e2607697cc2ecb17cce003003bb7ca9112104f3e8ce727edb5--`
|
--fe785e0384e2607697cc2ecb17cce003003bb7ca9112104f3e8ce727edb5--`
|
||||||
|
exampleMultiPart7BitBase64 = `Date: Wed, 01 Nov 2023 00:00:00 +0000
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Message-ID: <1305604950.683004066175.AAAAAAAAaaaaaaaaB@go-mail.dev>
|
||||||
|
Subject: Example mail // 7bit with base64 attachment
|
||||||
|
User-Agent: go-mail v0.4.1 // https://github.com/wneessen/go-mail
|
||||||
|
X-Mailer: go-mail v0.4.1 // https://github.com/wneessen/go-mail
|
||||||
|
From: "Toni Tester" <go-mail@go-mail.dev>
|
||||||
|
To: <go-mail+test@go-mail.dev>
|
||||||
|
Cc: <go-mail+cc@go-mail.dev>
|
||||||
|
Content-Type: multipart/mixed;
|
||||||
|
boundary="------------26A45336F6C6196BD8BBA2A2"
|
||||||
|
|
||||||
|
This is a multi-part message in MIME format.
|
||||||
|
--------------26A45336F6C6196BD8BBA2A2
|
||||||
|
Content-Type: text/plain; charset=US-ASCII; format=flowed
|
||||||
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
|
||||||
|
--------------26A45336F6C6196BD8BBA2A2
|
||||||
|
Content-Type: text/plain; charset=UTF-8;
|
||||||
|
name="testfile.txt"
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
Content-Disposition: attachment;
|
||||||
|
filename="testfile.txt"
|
||||||
|
|
||||||
|
VGhpcyBpcyBhIHRlc3QgaW4gQmFzZTY0
|
||||||
|
--------------26A45336F6C6196BD8BBA2A2--`
|
||||||
|
exampleMultiPart8BitBase64 = `Date: Wed, 01 Nov 2023 00:00:00 +0000
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Message-ID: <1305604950.683004066175.AAAAAAAAaaaaaaaaB@go-mail.dev>
|
||||||
|
Subject: Example mail // 8bit with base64 attachment
|
||||||
|
User-Agent: go-mail v0.4.1 // https://github.com/wneessen/go-mail
|
||||||
|
X-Mailer: go-mail v0.4.1 // https://github.com/wneessen/go-mail
|
||||||
|
From: "Toni Tester" <go-mail@go-mail.dev>
|
||||||
|
To: <go-mail+test@go-mail.dev>
|
||||||
|
Cc: <go-mail+cc@go-mail.dev>
|
||||||
|
Content-Type: multipart/mixed;
|
||||||
|
boundary="------------26A45336F6C6196BD8BBA2A2"
|
||||||
|
|
||||||
|
This is a multi-part message in MIME format.
|
||||||
|
--------------26A45336F6C6196BD8BBA2A2
|
||||||
|
Content-Type: text/plain; charset=US-ASCII; format=flowed
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
testtest
|
||||||
|
|
||||||
|
--------------26A45336F6C6196BD8BBA2A2
|
||||||
|
Content-Type: text/plain; charset=UTF-8;
|
||||||
|
name="testfile.txt"
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
Content-Disposition: attachment;
|
||||||
|
filename="testfile.txt"
|
||||||
|
|
||||||
|
VGhpcyBpcyBhIHRlc3QgaW4gQmFzZTY0
|
||||||
|
--------------26A45336F6C6196BD8BBA2A2--`
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEMLToMsgFromString(t *testing.T) {
|
func TestEMLToMsgFromString(t *testing.T) {
|
||||||
|
@ -534,6 +623,10 @@ func TestEMLToMsgFromString(t *testing.T) {
|
||||||
enc string
|
enc string
|
||||||
sub string
|
sub string
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
"Plain text no encoding (7bit)", exampleMailPlain7Bit, "7bit",
|
||||||
|
"Example mail // plain text without encoding",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Plain text no encoding", exampleMailPlainNoEnc, "8bit",
|
"Plain text no encoding", exampleMailPlainNoEnc, "8bit",
|
||||||
"Example mail // plain text without encoding",
|
"Example mail // plain text without encoding",
|
||||||
|
@ -866,6 +959,58 @@ func TestEMLToMsgFromStringMultipartMixedAlternativeRelated(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEMLToMsgFromStringMultipartMixedWith7Bit(t *testing.T) {
|
||||||
|
wantSubject := "Example mail // 7bit with base64 attachment"
|
||||||
|
msg, err := EMLToMsgFromString(exampleMultiPart7BitBase64)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("EML multipart mixed with 7bit: %s", err)
|
||||||
|
}
|
||||||
|
if subject := msg.GetGenHeader(HeaderSubject); len(subject) > 0 && !strings.EqualFold(subject[0], wantSubject) {
|
||||||
|
t.Errorf("EMLToMsgFromString of EML multipart mixed with 7bit: expected subject: %s,"+
|
||||||
|
" but got: %s", wantSubject, subject[0])
|
||||||
|
}
|
||||||
|
if len(msg.parts) != 1 {
|
||||||
|
t.Errorf("EMLToMsgFromString of EML multipart mixed with 7bit failed: expected 1 part, got: %d",
|
||||||
|
len(msg.parts))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !strings.EqualFold(msg.parts[0].GetEncoding().String(), EncodingUSASCII.String()) {
|
||||||
|
t.Errorf("EMLToMsgFromString of EML multipart mixed with 7bit failed: expected encoding: %s, got %s",
|
||||||
|
EncodingUSASCII.String(), msg.parts[0].GetEncoding().String())
|
||||||
|
}
|
||||||
|
if len(msg.attachments) != 1 {
|
||||||
|
t.Errorf("EMLToMsgFromString of EML multipart mixed with 7bit failed: expected 1 attachment, got: %d",
|
||||||
|
len(msg.attachments))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEMLToMsgFromStringMultipartMixedWith8Bit(t *testing.T) {
|
||||||
|
wantSubject := "Example mail // 8bit with base64 attachment"
|
||||||
|
msg, err := EMLToMsgFromString(exampleMultiPart8BitBase64)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("EML multipart mixed with 8bit: %s", err)
|
||||||
|
}
|
||||||
|
if subject := msg.GetGenHeader(HeaderSubject); len(subject) > 0 && !strings.EqualFold(subject[0], wantSubject) {
|
||||||
|
t.Errorf("EMLToMsgFromString of EML multipart mixed with 8bit: expected subject: %s,"+
|
||||||
|
" but got: %s", wantSubject, subject[0])
|
||||||
|
}
|
||||||
|
if len(msg.parts) != 1 {
|
||||||
|
t.Errorf("EMLToMsgFromString of EML multipart mixed with 8bit failed: expected 1 part, got: %d",
|
||||||
|
len(msg.parts))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !strings.EqualFold(msg.parts[0].GetEncoding().String(), NoEncoding.String()) {
|
||||||
|
t.Errorf("EMLToMsgFromString of EML multipart mixed with 8bit failed: expected encoding: %s, got %s",
|
||||||
|
NoEncoding.String(), msg.parts[0].GetEncoding().String())
|
||||||
|
}
|
||||||
|
if len(msg.attachments) != 1 {
|
||||||
|
t.Errorf("EMLToMsgFromString of EML multipart mixed with 8bit failed: expected 1 attachment, got: %d",
|
||||||
|
len(msg.attachments))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// stringToTempFile is a helper method that will create a temporary file form a give data string
|
// stringToTempFile is a helper method that will create a temporary file form a give data string
|
||||||
func stringToTempFile(data, name string) (string, string, error) {
|
func stringToTempFile(data, name string) (string, string, error) {
|
||||||
tempDir, err := os.MkdirTemp("", fmt.Sprintf("*-%s", name))
|
tempDir, err := os.MkdirTemp("", fmt.Sprintf("*-%s", name))
|
||||||
|
|
Loading…
Reference in a new issue