Browse Source

Support for non-ascii text in email headers (#83)

* Support UTF-8 in email subject

Was trying to import that email sample from https://cdn.online-convert.com/example-file/document/eml/example.eml into GoPhish but the subject is just displayed as "=?UTF-8?Q?_EML Example File?=". The patch is adding UTF-8 support for the subject string.

* Support for more non-ASCII text in headers

According to RFC2047 non ascii text is also allowed in other fields like From, To, ...

* Add test function for non ascii email parsing
David Maciejak 6 years ago
parent
commit
041e0cec78
2 changed files with 67 additions and 3 deletions
  1. 32 3
      email.go
  2. 35 0
      email_test.go

+ 32 - 3
email.go

@@ -95,18 +95,47 @@ func NewEmailFromReader(r io.Reader) (*Email, error) {
 		switch {
 		case h == "Subject":
 			e.Subject = v[0]
+			subj, err := (&mime.WordDecoder{}).DecodeHeader(e.Subject)
+			if err == nil && len(subj) > 0 {
+				e.Subject = subj
+			}
 			delete(hdrs, h)
 		case h == "To":
-			e.To = v
+			for _, to := range v {
+				tt, err := (&mime.WordDecoder{}).DecodeHeader(to)
+				if err == nil {
+					e.To = append(e.To, tt)
+				} else {
+					e.To = append(e.To, to)
+				}
+			}
 			delete(hdrs, h)
 		case h == "Cc":
-			e.Cc = v
+			for _, cc := range v {
+				tcc, err := (&mime.WordDecoder{}).DecodeHeader(cc)
+				if err == nil {
+					e.Cc = append(e.Cc, tcc)
+				} else {
+					e.Cc = append(e.Cc, cc)
+				}
+			}
 			delete(hdrs, h)
 		case h == "Bcc":
-			e.Bcc = v
+			for _, bcc := range v {
+				tbcc, err := (&mime.WordDecoder{}).DecodeHeader(bcc)
+				if err == nil {
+					e.Bcc = append(e.Bcc, tbcc)
+				} else {
+					e.Bcc = append(e.Bcc, bcc)
+				}
+			}
 			delete(hdrs, h)
 		case h == "From":
 			e.From = v[0]
+			fr, err := (&mime.WordDecoder{}).DecodeHeader(e.From)
+			if err == nil && len(fr) > 0 {
+				e.From = fr
+			}
 			delete(hdrs, h)
 		}
 	}

+ 35 - 0
email_test.go

@@ -296,6 +296,41 @@ d-printable decoding.</div>
 
 }
 
+func TestNonAsciiEmailFromReader(t *testing.T) {
+	ex := &Email{
+		Subject: "Test Subject",
+		To:      []string{"Anaïs <anais@example.org>"},
+		Cc:      []string{"Patrik Fältström <paf@example.com>"},
+		From:    "Mrs Valérie Dupont <valerie.dupont@example.com>",
+		Text:    []byte("This is a test message!"),
+	}
+	raw := []byte(`
+	MIME-Version: 1.0
+Subject: =?UTF-8?Q?Test Subject?=
+From: Mrs =?ISO-8859-1?Q?Val=C3=A9rie=20Dupont?= <valerie.dupont@example.com>
+To: =?utf-8?q?Ana=C3=AFs?= <anais@example.org>
+Cc: =?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@example.com>
+Content-type: text/plain; charset=ISO-8859-1
+
+This is a test message!`)
+	e, err := NewEmailFromReader(bytes.NewReader(raw))
+	if err != nil {
+		t.Fatalf("Error creating email %s", err.Error())
+	}
+	if e.Subject != ex.Subject {
+		t.Fatalf("Incorrect subject. %#q != %#q", e.Subject, ex.Subject)
+	}
+	if e.From != ex.From {
+		t.Fatalf("Incorrect \"From\": %#q != %#q", e.From, ex.From)
+	}
+	if e.To[0] != ex.To[0] {
+		t.Fatalf("Incorrect \"To\": %#q != %#q", e.To, ex.To)
+	}
+	if e.Cc[0] != ex.Cc[0] {
+		t.Fatalf("Incorrect \"Cc\": %#q != %#q", e.Cc, ex.Cc)
+	}
+}
+
 func TestNonMultipartEmailFromReader(t *testing.T) {
 	ex := &Email{
 		Text:    []byte("This is a test message!"),