mirror of
https://github.com/wneessen/go-mail.git
synced 2024-12-22 10:40:39 +01:00
Merge pull request #270 from wneessen/feature/262_support-7bit-encoding
Add 7bit support for EML parsing
This commit is contained in:
commit
3ca2968158
4 changed files with 165 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
|
||||
func parseEMLBodyPlain(mediatype string, parsedMsg *netmail.Message, bodybuf *bytes.Buffer, msg *Msg) error {
|
||||
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()) {
|
||||
msg.SetEncoding(NoEncoding)
|
||||
msg.SetBodyString(ContentType(mediatype), bodybuf.String())
|
||||
|
@ -308,14 +314,22 @@ ReadNextPart:
|
|||
}
|
||||
|
||||
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()):
|
||||
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)
|
||||
}
|
||||
case strings.EqualFold(mutliPartTransferEnc[0], EncodingQP.String()):
|
||||
part.SetEncoding(EncodingQP)
|
||||
part.SetContent(string(multiPartData))
|
||||
default:
|
||||
return fmt.Errorf("unsupported Content-Transfer-Encoding")
|
||||
return fmt.Errorf("unsupported Content-Transfer-Encoding: %s", mutliPartTransferEnc[0])
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
|
||||
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!
|
||||
The go-mail team
|
||||
|
||||
|
@ -525,6 +548,72 @@ hw22iFHl7YlpOmedZvtMTfQffXeXnvI+rTKNxguyvDKvB7U4qQAAAAlwSFlzAAALEwAACxMBAJqc
|
|||
GAAAABFJREFUCJljnMoAA0wMNGcCAEQrAKk9oHKhAAAAAElFTkSuQmCC
|
||||
|
||||
--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) {
|
||||
|
@ -534,6 +623,10 @@ func TestEMLToMsgFromString(t *testing.T) {
|
|||
enc string
|
||||
sub string
|
||||
}{
|
||||
{
|
||||
"Plain text no encoding (7bit)", exampleMailPlain7Bit, "7bit",
|
||||
"Example mail // plain text without encoding",
|
||||
},
|
||||
{
|
||||
"Plain text no encoding", exampleMailPlainNoEnc, "8bit",
|
||||
"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
|
||||
func stringToTempFile(data, name string) (string, string, error) {
|
||||
tempDir, err := os.MkdirTemp("", fmt.Sprintf("*-%s", name))
|
||||
|
|
|
@ -27,6 +27,9 @@ const (
|
|||
// EncodingQP represents the "quoted-printable" encoding as specified in RFC 2045.
|
||||
EncodingQP Encoding = "quoted-printable"
|
||||
|
||||
// EncodingUSASCII represents encoding with only US-ASCII characters (aka 7Bit)
|
||||
EncodingUSASCII Encoding = "7bit"
|
||||
|
||||
// NoEncoding avoids any character encoding (except of the mail headers)
|
||||
NoEncoding Encoding = "8bit"
|
||||
)
|
||||
|
|
|
@ -16,6 +16,7 @@ func TestEncoding_String(t *testing.T) {
|
|||
{"Encoding: Base64", EncodingB64, "base64"},
|
||||
{"Encoding: QP", EncodingQP, "quoted-printable"},
|
||||
{"Encoding: None/8bit", NoEncoding, "8bit"},
|
||||
{"Encoding: US-ASCII/7bit", EncodingUSASCII, "7bit"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue