feat(GODT-3113): Only force UTF-8 charset for HTML part when needed.
This commit is contained in:
parent
fa430ee0fb
commit
83bbdbd63e
|
@ -197,9 +197,6 @@ func convertForeignEncodings(p *parser.Parser) error {
|
|||
|
||||
return p.NewWalker().
|
||||
RegisterContentTypeHandler("text/html", func(p *parser.Part) error {
|
||||
if p.IsAttachment() {
|
||||
return nil
|
||||
}
|
||||
if err := p.ConvertToUTF8(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ type Part struct {
|
|||
children Parts
|
||||
}
|
||||
|
||||
const utf8Charset = "UTF-8"
|
||||
|
||||
func (p *Part) ContentType() (string, map[string]string, error) {
|
||||
t, params, err := p.Header.ContentType()
|
||||
if err != nil {
|
||||
|
@ -116,7 +118,7 @@ func (p *Part) ConvertToUTF8() error {
|
|||
params = make(map[string]string)
|
||||
}
|
||||
|
||||
params["charset"] = "UTF-8"
|
||||
params["charset"] = utf8Charset
|
||||
|
||||
p.Header.SetContentType(t, params)
|
||||
|
||||
|
@ -129,6 +131,8 @@ func (p *Part) ConvertMetaCharset() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Override charset to UTF-8 in meta headers only if needed.
|
||||
var metaModified = false
|
||||
goquery.NewDocumentFromNode(doc).Find("meta").Each(func(n int, sel *goquery.Selection) {
|
||||
if val, ok := sel.Attr("content"); ok {
|
||||
t, params, err := pmmime.ParseMediaType(val)
|
||||
|
@ -136,24 +140,31 @@ func (p *Part) ConvertMetaCharset() error {
|
|||
return
|
||||
}
|
||||
|
||||
params["charset"] = "UTF-8"
|
||||
if charset, ok := params["charset"]; ok && charset != utf8Charset {
|
||||
params["charset"] = utf8Charset
|
||||
}
|
||||
|
||||
sel.SetAttr("content", mime.FormatMediaType(t, params))
|
||||
metaModified = true
|
||||
}
|
||||
|
||||
if _, ok := sel.Attr("charset"); ok {
|
||||
sel.SetAttr("charset", "UTF-8")
|
||||
if charset, ok := sel.Attr("charset"); ok && charset != utf8Charset {
|
||||
sel.SetAttr("charset", utf8Charset)
|
||||
metaModified = true
|
||||
}
|
||||
})
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
// Override the body part only if modification was applied
|
||||
// as html.render will sanitise the html headers.
|
||||
if metaModified {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
if err := html.Render(buf, doc); err != nil {
|
||||
return err
|
||||
if err := html.Render(buf, doc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Body = buf.Bytes()
|
||||
}
|
||||
|
||||
p.Body = buf.Bytes()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -431,7 +431,7 @@ func TestParseTextHTML(t *testing.T) {
|
|||
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
|
||||
assert.Equal(t, `"Receiver" <receiver@pm.me>`, m.ToList[0].String())
|
||||
|
||||
assert.Equal(t, "<html><head></head><body>This is body of <b>HTML mail</b> without attachment</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "<html><body>This is body of <b>HTML mail</b> without attachment</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "This is body of *HTML mail* without attachment", string(m.PlainBody))
|
||||
|
||||
assert.Len(t, m.Attachments, 0)
|
||||
|
@ -446,7 +446,7 @@ func TestParseTextHTMLAlready7Bit(t *testing.T) {
|
|||
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
|
||||
assert.Equal(t, `"Receiver" <receiver@pm.me>`, m.ToList[0].String())
|
||||
|
||||
assert.Equal(t, "<html><head></head><body>This is body of <b>HTML mail</b> without attachment</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "<html><body>This is body of <b>HTML mail</b> without attachment</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "This is body of *HTML mail* without attachment", string(m.PlainBody))
|
||||
|
||||
assert.Len(t, m.Attachments, 0)
|
||||
|
@ -461,7 +461,7 @@ func TestParseTextHTMLWithOctetAttachment(t *testing.T) {
|
|||
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
|
||||
assert.Equal(t, `"Receiver" <receiver@pm.me>`, m.ToList[0].String())
|
||||
|
||||
assert.Equal(t, "<html><head></head><body>This is body of <b>HTML mail</b> with attachment</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "<html><body>This is body of <b>HTML mail</b> with attachment</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "This is body of *HTML mail* with attachment", string(m.PlainBody))
|
||||
|
||||
require.Len(t, m.Attachments, 1)
|
||||
|
@ -478,7 +478,7 @@ func TestParseTextHTMLWithPlainAttachment(t *testing.T) {
|
|||
assert.Equal(t, `"Receiver" <receiver@pm.me>`, m.ToList[0].String())
|
||||
|
||||
// BAD: plainBody should not be empty!
|
||||
assert.Equal(t, "<html><head></head><body>This is body of <b>HTML mail</b> with attachment</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "<html><body>This is body of <b>HTML mail</b> with attachment</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "This is body of *HTML mail* with attachment", string(m.PlainBody))
|
||||
|
||||
require.Len(t, m.Attachments, 1)
|
||||
|
@ -496,7 +496,7 @@ func TestParseTextHTMLWithImageInline(t *testing.T) {
|
|||
|
||||
require.Len(t, m.Attachments, 1)
|
||||
|
||||
assert.Equal(t, fmt.Sprintf(`<html><head></head><body>This is body of <b>HTML mail</b> with attachment</body></html><html><body><img src="cid:%v"/></body></html>`, m.Attachments[0].ContentID), string(m.RichBody))
|
||||
assert.Equal(t, fmt.Sprintf(`<html><body>This is body of <b>HTML mail</b> with attachment</body></html><html><body><img src="cid:%v"/></body></html>`, m.Attachments[0].ContentID), string(m.RichBody))
|
||||
assert.Equal(t, "This is body of *HTML mail* with attachment", string(m.PlainBody))
|
||||
|
||||
// The inline image is an 8x8 mic-dropping gopher.
|
||||
|
@ -627,7 +627,7 @@ func TestParseWithTrailingEndOfMailIndicator(t *testing.T) {
|
|||
assert.Equal(t, `"Sender" <sender@sender.com>`, m.Sender.String())
|
||||
assert.Equal(t, `"Receiver" <receiver@receiver.com>`, m.ToList[0].String())
|
||||
|
||||
assert.Equal(t, "<!DOCTYPE html><html><head></head><body>boo!</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "<!DOCTYPE HTML>\n<html><body>boo!</body></html>", string(m.RichBody))
|
||||
assert.Equal(t, "boo!", string(m.PlainBody))
|
||||
}
|
||||
|
||||
|
|
|
@ -241,6 +241,7 @@ Feature: SMTP sending of HTMl messages to Internal recipient
|
|||
{
|
||||
"content-type": "application/pgp-keys",
|
||||
"content-disposition": "attachment",
|
||||
|
||||
"transfer-encoding": "base64"
|
||||
}
|
||||
]
|
||||
|
@ -763,7 +764,7 @@ Feature: SMTP sending of HTMl messages to Internal recipient
|
|||
"content-disposition": "attachment",
|
||||
"content-disposition-filename": "index.html",
|
||||
"transfer-encoding": "base64",
|
||||
"body-is": "PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+Cjx0aXRsZT5QYWdlIFRpdGxlPC90aXRsZT4KPC9o\r\nZWFkPgo8Ym9keT4KCjxoMT5NeSBGaXJzdCBIZWFkaW5nPC9oMT4KPHA+TXkgZmlyc3QgcGFyYWdy\r\nYXBoLjwvcD4KCgogPC9ib2R5PjwvaHRtbD4="
|
||||
"body-is": "IDwhRE9DVFlQRSBodG1sPg0KPGh0bWw+DQo8aGVhZD4NCjx0aXRsZT5QYWdlIFRpdGxlPC90aXRs\r\nZT4NCjwvaGVhZD4NCjxib2R5Pg0KDQo8aDE+TXkgRmlyc3QgSGVhZGluZzwvaDE+DQo8cD5NeSBm\r\naXJzdCBwYXJhZ3JhcGguPC9wPg0KDQo8L2JvZHk+DQo8L2h0bWw+IA=="
|
||||
},
|
||||
{
|
||||
"content-type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
|
@ -1070,7 +1071,6 @@ Feature: SMTP sending of HTMl messages to Internal recipient
|
|||
}
|
||||
"""
|
||||
|
||||
|
||||
Scenario: Replying to a message after enabling attach public key
|
||||
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]":
|
||||
"""
|
||||
|
|
|
@ -1242,7 +1242,7 @@ Feature: SMTP sending of PLAIN messages to Internal recipient
|
|||
"content-disposition": "attachment",
|
||||
"content-disposition-filename": "index.html",
|
||||
"transfer-encoding": "base64",
|
||||
"body-is": "PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+Cjx0aXRsZT5QYWdlIFRpdGxlPC90aXRsZT4KPC9o\r\nZWFkPgo8Ym9keT4KCjxoMT5NeSBGaXJzdCBIZWFkaW5nPC9oMT4KPHA+TXkgZmlyc3QgcGFyYWdy\r\nYXBoLjwvcD4KCgogPC9ib2R5PjwvaHRtbD4="
|
||||
"body-is": "IDwhRE9DVFlQRSBodG1sPg0KPGh0bWw+DQo8aGVhZD4NCjx0aXRsZT5QYWdlIFRpdGxlPC90aXRs\r\nZT4NCjwvaGVhZD4NCjxib2R5Pg0KDQo8aDE+TXkgRmlyc3QgSGVhZGluZzwvaDE+DQo8cD5NeSBm\r\naXJzdCBwYXJhZ3JhcGguPC9wPg0KDQo8L2JvZHk+DQo8L2h0bWw+IA=="
|
||||
},
|
||||
{
|
||||
"content-type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
|
|
Loading…
Reference in New Issue