From cc14864129a0b266d3974f4d1674ea63853253e2 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Fri, 10 Nov 2023 18:07:56 +0100 Subject: [PATCH] #152: Add new methods and tests for handling email addresses Added new methods `ToFromString()`, `CcFromString()` and `BccFromString()` in msg.go file to handle strings of comma-separated email addresses. --- msg.go | 19 ++++++ msg_test.go | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) diff --git a/msg.go b/msg.go index 1cbf251..e623958 100644 --- a/msg.go +++ b/msg.go @@ -17,6 +17,7 @@ import ( "os" "os/exec" "path/filepath" + "strings" "syscall" tt "text/template" "time" @@ -352,6 +353,12 @@ func (m *Msg) ToIgnoreInvalid(t ...string) { m.SetAddrHeaderIgnoreInvalid(HeaderTo, t...) } +// ToFromString takes and validates a given string of comma separted +// mail address and sets them as To: addresses of the Msg +func (m *Msg) ToFromString(v string) error { + return m.To(strings.Split(v, ",")...) +} + // Cc takes and validates a given mail address list sets the Cc: addresses of the Msg func (m *Msg) Cc(c ...string) error { return m.SetAddrHeader(HeaderCc, c...) @@ -374,6 +381,12 @@ func (m *Msg) CcIgnoreInvalid(c ...string) { m.SetAddrHeaderIgnoreInvalid(HeaderCc, c...) } +// CcFromString takes and validates a given string of comma separted +// mail address and sets them as Cc: addresses of the Msg +func (m *Msg) CcFromString(v string) error { + return m.Cc(strings.Split(v, ",")...) +} + // Bcc takes and validates a given mail address list sets the Bcc: addresses of the Msg func (m *Msg) Bcc(b ...string) error { return m.SetAddrHeader(HeaderBcc, b...) @@ -396,6 +409,12 @@ func (m *Msg) BccIgnoreInvalid(b ...string) { m.SetAddrHeaderIgnoreInvalid(HeaderBcc, b...) } +// BccFromString takes and validates a given string of comma separted +// mail address and sets them as Bcc: addresses of the Msg +func (m *Msg) BccFromString(v string) error { + return m.Bcc(strings.Split(v, ",")...) +} + // ReplyTo takes and validates a given mail address and sets it as "Reply-To" addrHeader of the Msg func (m *Msg) ReplyTo(r string) error { rt, err := mail.ParseAddress(r) diff --git a/msg_test.go b/msg_test.go index 908576e..a16e09f 100644 --- a/msg_test.go +++ b/msg_test.go @@ -2937,3 +2937,180 @@ func TestMsg_EmbedReadSeeker(t *testing.T) { t.Errorf("EmbedReadSeeker() failed. Expected string: %q, got: %q", ts, wbuf.String()) } } + +// TestMsg_ToFromString tests Msg.ToFromString in different scenarios +func TestMsg_ToFromString(t *testing.T) { + tests := []struct { + n string + v string + w []*mail.Address + sf bool + }{ + {"valid single address", "test@test.com", []*mail.Address{ + {"", "test@test.com"}, + }, false}, + { + "valid multiple addresses", "test@test.com,test2@example.com", + []*mail.Address{ + {"", "test@test.com"}, + {"", "test2@example.com"}, + }, + false, + }, + { + "valid multiple addresses with space and name", + `test@test.com, "Toni Tester" `, + []*mail.Address{ + {"", "test@test.com"}, + {"Toni Tester", "test2@example.com"}, + }, + false, + }, + { + "invalid and valid multiple addresses", "test@test.com,test2#example.com", nil, + true, + }, + } + + for _, tt := range tests { + t.Run(tt.n, func(t *testing.T) { + m := NewMsg() + if err := m.ToFromString(tt.v); err != nil && !tt.sf { + t.Errorf("Msg.ToFromString failed: %s", err) + return + } + mto := m.GetTo() + if len(mto) != len(tt.w) { + t.Errorf("Msg.ToFromString failed, expected len: %d, got: %d", len(tt.w), + len(mto)) + return + } + for i := range mto { + w := tt.w[i] + g := mto[i] + if w.String() != g.String() { + t.Errorf("Msg.ToFromString failed, expected address: %s, got: %s", + w.String(), g.String()) + } + } + }) + } +} + +// TestMsg_CcFromString tests Msg.CcFromString in different scenarios +func TestMsg_CcFromString(t *testing.T) { + tests := []struct { + n string + v string + w []*mail.Address + sf bool + }{ + {"valid single address", "test@test.com", []*mail.Address{ + {"", "test@test.com"}, + }, false}, + { + "valid multiple addresses", "test@test.com,test2@example.com", + []*mail.Address{ + {"", "test@test.com"}, + {"", "test2@example.com"}, + }, + false, + }, + { + "valid multiple addresses with space and name", + `test@test.com, "Toni Tester" `, + []*mail.Address{ + {"", "test@test.com"}, + {"Toni Tester", "test2@example.com"}, + }, + false, + }, + { + "invalid and valid multiple addresses", "test@test.com,test2#example.com", nil, + true, + }, + } + + for _, tt := range tests { + t.Run(tt.n, func(t *testing.T) { + m := NewMsg() + if err := m.CcFromString(tt.v); err != nil && !tt.sf { + t.Errorf("Msg.CcFromString failed: %s", err) + return + } + mto := m.GetCc() + if len(mto) != len(tt.w) { + t.Errorf("Msg.CcFromString failed, expected len: %d, got: %d", len(tt.w), + len(mto)) + return + } + for i := range mto { + w := tt.w[i] + g := mto[i] + if w.String() != g.String() { + t.Errorf("Msg.CcFromString failed, expected address: %s, got: %s", + w.String(), g.String()) + } + } + }) + } +} + +// TestMsg_BccFromString tests Msg.BccFromString in different scenarios +func TestMsg_BccFromString(t *testing.T) { + tests := []struct { + n string + v string + w []*mail.Address + sf bool + }{ + {"valid single address", "test@test.com", []*mail.Address{ + {"", "test@test.com"}, + }, false}, + { + "valid multiple addresses", "test@test.com,test2@example.com", + []*mail.Address{ + {"", "test@test.com"}, + {"", "test2@example.com"}, + }, + false, + }, + { + "valid multiple addresses with space and name", + `test@test.com, "Toni Tester" `, + []*mail.Address{ + {"", "test@test.com"}, + {"Toni Tester", "test2@example.com"}, + }, + false, + }, + { + "invalid and valid multiple addresses", "test@test.com,test2#example.com", nil, + true, + }, + } + + for _, tt := range tests { + t.Run(tt.n, func(t *testing.T) { + m := NewMsg() + if err := m.BccFromString(tt.v); err != nil && !tt.sf { + t.Errorf("Msg.BccFromString failed: %s", err) + return + } + mto := m.GetBcc() + if len(mto) != len(tt.w) { + t.Errorf("Msg.BccFromString failed, expected len: %d, got: %d", len(tt.w), + len(mto)) + return + } + for i := range mto { + w := tt.w[i] + g := mto[i] + if w.String() != g.String() { + t.Errorf("Msg.BccFromString failed, expected address: %s, got: %s", + w.String(), g.String()) + } + } + }) + } +}