mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 05:40:50 +01:00
Merge pull request #172 from wneessen/feature/171_implement-per-part-charsets
Add Charset support for message parts
This commit is contained in:
commit
64a07399c4
5 changed files with 101 additions and 1 deletions
1
msg.go
1
msg.go
|
@ -1141,6 +1141,7 @@ func (m *Msg) hasPGPType() bool {
|
||||||
func (m *Msg) newPart(ct ContentType, o ...PartOption) *Part {
|
func (m *Msg) newPart(ct ContentType, o ...PartOption) *Part {
|
||||||
p := &Part{
|
p := &Part{
|
||||||
ctype: ct,
|
ctype: ct,
|
||||||
|
cset: m.charset,
|
||||||
enc: m.encoding,
|
enc: m.encoding,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -245,7 +245,11 @@ func (mw *msgWriter) newPart(h map[string][]string) {
|
||||||
|
|
||||||
// writePart writes the corresponding part to the Msg body
|
// writePart writes the corresponding part to the Msg body
|
||||||
func (mw *msgWriter) writePart(p *Part, cs Charset) {
|
func (mw *msgWriter) writePart(p *Part, cs Charset) {
|
||||||
ct := fmt.Sprintf("%s; charset=%s", p.ctype, cs)
|
pcs := p.cset
|
||||||
|
if pcs.String() == "" {
|
||||||
|
pcs = cs
|
||||||
|
}
|
||||||
|
ct := fmt.Sprintf("%s; charset=%s", p.ctype, pcs)
|
||||||
cte := p.enc.String()
|
cte := p.enc.String()
|
||||||
if mw.d == 0 {
|
if mw.d == 0 {
|
||||||
mw.writeHeader(HeaderContentType, ct)
|
mw.writeHeader(HeaderContentType, ct)
|
||||||
|
|
|
@ -53,6 +53,7 @@ func TestMsgWriter_writeMsg(t *testing.T) {
|
||||||
m.SetDateWithValue(now)
|
m.SetDateWithValue(now)
|
||||||
m.SetMessageIDWithValue("message@id.com")
|
m.SetMessageIDWithValue("message@id.com")
|
||||||
m.SetBodyString(TypeTextPlain, "This is the body")
|
m.SetBodyString(TypeTextPlain, "This is the body")
|
||||||
|
m.AddAlternativeString(TypeTextHTML, "This is the alternative body")
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
mw := &msgWriter{w: &buf, c: CharsetUTF8, en: mime.QEncoding}
|
mw := &msgWriter{w: &buf, c: CharsetUTF8, en: mime.QEncoding}
|
||||||
mw.writeMsg(m)
|
mw.writeMsg(m)
|
||||||
|
@ -95,6 +96,26 @@ func TestMsgWriter_writeMsg(t *testing.T) {
|
||||||
if !strings.Contains(ms, "\r\n\r\nThis is the body") {
|
if !strings.Contains(ms, "\r\n\r\nThis is the body") {
|
||||||
ea = append(ea, "Message body")
|
ea = append(ea, "Message body")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pl := m.GetParts()
|
||||||
|
if len(pl) <= 0 {
|
||||||
|
t.Errorf("expected multiple parts but got none")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(pl) == 2 {
|
||||||
|
ap := pl[1]
|
||||||
|
ap.SetCharset(CharsetISO88591)
|
||||||
|
}
|
||||||
|
buf.Reset()
|
||||||
|
mw.writeMsg(m)
|
||||||
|
ms = buf.String()
|
||||||
|
if !strings.Contains(ms, "\r\n\r\nThis is the alternative body") {
|
||||||
|
ea = append(ea, "Message alternative body")
|
||||||
|
}
|
||||||
|
if !strings.Contains(ms, `Content-Type: text/html; charset=ISO-8859-1`) {
|
||||||
|
ea = append(ea, "alternative body charset")
|
||||||
|
}
|
||||||
|
|
||||||
if len(ea) > 0 {
|
if len(ea) > 0 {
|
||||||
em := "writeMsg() failed. The following errors occurred:\n"
|
em := "writeMsg() failed. The following errors occurred:\n"
|
||||||
for e := range ea {
|
for e := range ea {
|
||||||
|
|
18
part.go
18
part.go
|
@ -15,6 +15,7 @@ type PartOption func(*Part)
|
||||||
// Part is a part of the Msg
|
// Part is a part of the Msg
|
||||||
type Part struct {
|
type Part struct {
|
||||||
ctype ContentType
|
ctype ContentType
|
||||||
|
cset Charset
|
||||||
desc string
|
desc string
|
||||||
enc Encoding
|
enc Encoding
|
||||||
del bool
|
del bool
|
||||||
|
@ -30,6 +31,11 @@ func (p *Part) GetContent() ([]byte, error) {
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCharset returns the currently set Charset of the Part
|
||||||
|
func (p *Part) GetCharset() Charset {
|
||||||
|
return p.cset
|
||||||
|
}
|
||||||
|
|
||||||
// GetContentType returns the currently set ContentType of the Part
|
// GetContentType returns the currently set ContentType of the Part
|
||||||
func (p *Part) GetContentType() ContentType {
|
func (p *Part) GetContentType() ContentType {
|
||||||
return p.ctype
|
return p.ctype
|
||||||
|
@ -61,6 +67,11 @@ func (p *Part) SetContentType(c ContentType) {
|
||||||
p.ctype = c
|
p.ctype = c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCharset overrides the Charset of the Part
|
||||||
|
func (p *Part) SetCharset(c Charset) {
|
||||||
|
p.cset = c
|
||||||
|
}
|
||||||
|
|
||||||
// SetEncoding creates a new mime.WordEncoder based on the encoding setting of the message
|
// SetEncoding creates a new mime.WordEncoder based on the encoding setting of the message
|
||||||
func (p *Part) SetEncoding(e Encoding) {
|
func (p *Part) SetEncoding(e Encoding) {
|
||||||
p.enc = e
|
p.enc = e
|
||||||
|
@ -82,6 +93,13 @@ func (p *Part) Delete() {
|
||||||
p.del = true
|
p.del = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithPartCharset overrides the default Part charset
|
||||||
|
func WithPartCharset(c Charset) PartOption {
|
||||||
|
return func(p *Part) {
|
||||||
|
p.cset = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithPartEncoding overrides the default Part encoding
|
// WithPartEncoding overrides the default Part encoding
|
||||||
func WithPartEncoding(e Encoding) PartOption {
|
func WithPartEncoding(e Encoding) PartOption {
|
||||||
return func(p *Part) {
|
return func(p *Part) {
|
||||||
|
|
56
part_test.go
56
part_test.go
|
@ -45,6 +45,33 @@ func TestPartEncoding(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestWithPartCharset tests the WithPartCharset method
|
||||||
|
func TestWithPartCharset(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cs Charset
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"Part charset: UTF-8", CharsetUTF8, "UTF-8"},
|
||||||
|
{"Part charset: ISO-8859-1", CharsetISO88591, "ISO-8859-1"},
|
||||||
|
{"Part charset: empty", "", ""},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
m := NewMsg()
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
part := m.newPart(TypeTextPlain, WithPartCharset(tt.cs), nil)
|
||||||
|
if part == nil {
|
||||||
|
t.Errorf("newPart() WithPartCharset() failed: no part returned")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if part.cset.String() != tt.want {
|
||||||
|
t.Errorf("newPart() WithPartCharset() failed: expected charset: %s, got: %s",
|
||||||
|
tt.want, part.cset.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestPart_WithPartContentDescription tests the WithPartContentDescription method
|
// TestPart_WithPartContentDescription tests the WithPartContentDescription method
|
||||||
func TestPart_WithPartContentDescription(t *testing.T) {
|
func TestPart_WithPartContentDescription(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
@ -320,3 +347,32 @@ func getPartList(m *Msg) ([]*Part, error) {
|
||||||
}
|
}
|
||||||
return pl, nil
|
return pl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestPart_SetCharset tests Part.SetCharset method
|
||||||
|
func TestPart_SetCharset(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cs Charset
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"Charset: UTF-8", CharsetUTF8, "UTF-8"},
|
||||||
|
{"Charset: ISO-8859-1", CharsetISO88591, "ISO-8859-1"},
|
||||||
|
{"Charset: empty", "", ""},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
m := NewMsg()
|
||||||
|
m.SetBodyString(TypeTextPlain, "This is a test with ümläutß")
|
||||||
|
pl, err := getPartList(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pl[0].SetCharset(tt.cs)
|
||||||
|
cs := pl[0].GetCharset()
|
||||||
|
if string(cs) != tt.want {
|
||||||
|
t.Errorf("SetCharset failed. Got: %s, expected: %s", string(cs), tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue