Compare commits

..

No commits in common. "3154649420179555644057f3c1927f65b88bd917" and "894936092edc287fd9d7f4ce803360894ce8aab2" have entirely different histories.

5 changed files with 95 additions and 50 deletions

View file

@ -19,6 +19,9 @@ type MIMEVersion string
// MIMEType represents the MIME type for the mail
type MIMEType string
// Disposition represents a content disposition for the Msg
type Disposition string
// List of supported encodings
const (
// EncodingB64 represents the Base64 encoding as specified in RFC 2045.
@ -160,6 +163,11 @@ const (
MIMESMime MIMEType = `signed; protocol="application/pkcs7-signature"; micalg=sha256`
)
// List of common content disposition
const (
DispositionSMime Disposition = `attachment; filename="smime.p7s"`
)
// String is a standard method to convert an Charset into a printable format
func (c Charset) String() string {
return string(c)
@ -174,3 +182,8 @@ func (c ContentType) String() string {
func (e Encoding) String() string {
return string(e)
}
// String is a standard method to convert an Disposition into a printable format
func (d Disposition) String() string {
return string(d)
}

View file

@ -126,3 +126,22 @@ func TestCharset_String(t *testing.T) {
})
}
}
// TestDisposition_String tests the string method of the Disposition object
func TestDisposition_String(t *testing.T) {
tests := []struct {
name string
d Disposition
want string
}{
{"Disposition: S/Mime", DispositionSMime, `attachment; filename="smime.p7s"`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.d.String() != tt.want {
t.Errorf("wrong string for Disposition returned. Expected: %s, got: %s",
tt.want, tt.d.String())
}
})
}
}

View file

@ -269,6 +269,9 @@ func (mw *msgWriter) writePart(part *Part, charset Charset) {
if part.description != "" {
mimeHeader.Add(string(HeaderContentDescription), part.description)
}
if part.disposition != "" {
mimeHeader.Add(string(HeaderContentDisposition), part.disposition.String())
}
mimeHeader.Add(string(HeaderContentType), contentType)
mimeHeader.Add(string(HeaderContentTransferEnc), contentTransferEnc)
mw.newPart(mimeHeader)

20
part.go
View file

@ -17,10 +17,10 @@ type Part struct {
contentType ContentType
charset Charset
description string
disposition Disposition
encoding Encoding
isDeleted bool
writeFunc func(io.Writer) (int64, error)
smime bool
}
// GetContent executes the WriteFunc of the Part and returns the content as byte slice
@ -57,9 +57,9 @@ func (p *Part) GetDescription() string {
return p.description
}
// IsSMimeSigned returns true if the Part should be singed with S/MIME
func (p *Part) IsSMimeSigned() bool {
return p.smime
// GetDisposition returns the currently set Content-Disposition of the Part
func (p *Part) GetDisposition() Disposition {
return p.disposition
}
// SetContent overrides the content of the Part with the given string
@ -88,9 +88,9 @@ func (p *Part) SetDescription(description string) {
p.description = description
}
// SetIsSMimeSigned sets the flag for signing the Part with S/MIME
func (p *Part) SetIsSMimeSigned(smime bool) {
p.smime = smime
// SetDisposition overrides the Content-Disposition of the Part
func (p *Part) SetDisposition(disposition Disposition) {
p.disposition = disposition
}
// SetWriteFunc overrides the WriteFunc of the Part
@ -125,9 +125,9 @@ func WithPartContentDescription(description string) PartOption {
}
}
// WithSMimeSinging overrides the flag for signing the Part with S/MIME
func WithSMimeSinging() PartOption {
// WithContentDisposition overrides the default Part Content-Disposition
func WithContentDisposition(disposition Disposition) PartOption {
return func(p *Part) {
p.smime = true
p.disposition = disposition
}
}

View file

@ -102,21 +102,32 @@ func TestPart_WithPartContentDescription(t *testing.T) {
}
}
// TestPart_WithSMimeSinging tests the WithSMimeSinging method
func TestPart_WithSMimeSinging(t *testing.T) {
// TestPart_withContentDisposition tests the WithContentDisposition method
func TestPart_withContentDisposition(t *testing.T) {
tests := []struct {
name string
disposition Disposition
}{
{"Part disposition: test", "test"},
{"Part disposition: empty", ""},
}
for _, tt := range tests {
m := NewMsg()
part := m.newPart(TypeTextPlain, WithSMimeSinging())
t.Run(tt.name, func(t *testing.T) {
part := m.newPart(TypeTextPlain, WithContentDisposition(tt.disposition), nil)
if part == nil {
t.Errorf("newPart() WithSMimeSinging() failed: no part returned")
t.Errorf("newPart() WithPartContentDescription() failed: no part returned")
return
}
if part.smime != true {
t.Errorf("newPart() WithSMimeSinging() failed: expected: %v, got: %v", true, part.smime)
if part.disposition != tt.disposition {
t.Errorf("newPart() WithContentDisposition() failed: expected: %s, got: %s", tt.disposition, part.description)
}
part.smime = true
part.SetIsSMimeSigned(false)
if part.smime != false {
t.Errorf("newPart() SetIsSMimeSigned() failed: expected: %v, got: %v", false, part.smime)
part.disposition = ""
part.SetDisposition(tt.disposition)
if part.disposition != tt.disposition {
t.Errorf("newPart() SetDisposition() failed: expected: %s, got: %s", tt.disposition, part.description)
}
})
}
}
@ -263,32 +274,6 @@ func TestPart_GetContentBroken(t *testing.T) {
}
}
// TestPart_IsSMimeSigned tests Part.IsSMimeSigned
func TestPart_IsSMimeSigned(t *testing.T) {
tests := []struct {
name string
want bool
}{
{"smime:", true},
{"smime:", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m := NewMsg()
pl, err := getPartList(m)
if err != nil {
t.Errorf("failed: %s", err)
return
}
pl[0].SetIsSMimeSigned(tt.want)
smime := pl[0].IsSMimeSigned()
if smime != tt.want {
t.Errorf("SetContentType failed. Got: %v, expected: %v", smime, tt.want)
}
})
}
}
// TestPart_SetWriteFunc tests Part.SetWriteFunc
func TestPart_SetWriteFunc(t *testing.T) {
c := "This is a test with ümläutß"
@ -367,6 +352,31 @@ func TestPart_SetDescription(t *testing.T) {
}
}
// TestPart_SetDisposition tests Part.SetDisposition
func TestPart_SetDisposition(t *testing.T) {
c := "This is a test"
d := Disposition("test-disposition")
m := NewMsg()
m.SetBodyString(TypeTextPlain, c)
pl, err := getPartList(m)
if err != nil {
t.Errorf("failed: %s", err)
return
}
pd := pl[0].GetDisposition()
if pd != "" {
t.Errorf("Part.GetDisposition failed. Expected empty description but got: %s", pd)
}
pl[0].SetDisposition(d)
if pl[0].disposition != d {
t.Errorf("Part.SetDisposition failed. Expected description to be: %s, got: %s", d, pd)
}
pd = pl[0].GetDisposition()
if pd != d {
t.Errorf("Part.GetDisposition failed. Expected: %s, got: %s", d, pd)
}
}
// TestPart_Delete tests Part.Delete
func TestPart_Delete(t *testing.T) {
c := "This is a test with ümläutß"