mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 05:40:50 +01:00
Merge pull request #22 from wneessen/21-envfrom
Add possibility to set dedicated envelope FROM address
This commit is contained in:
commit
d9491eef0b
5 changed files with 120 additions and 7 deletions
2
doc.go
2
doc.go
|
@ -2,4 +2,4 @@
|
||||||
package mail
|
package mail
|
||||||
|
|
||||||
// VERSION is used in the default user agent string
|
// VERSION is used in the default user agent string
|
||||||
const VERSION = "0.2.2"
|
const VERSION = "0.2.4"
|
||||||
|
|
|
@ -81,7 +81,7 @@ const (
|
||||||
HeaderXPriority Header = "X-Priority"
|
HeaderXPriority Header = "X-Priority"
|
||||||
)
|
)
|
||||||
|
|
||||||
// List of common generic header field names
|
// List of common address header field names
|
||||||
const (
|
const (
|
||||||
// HeaderBcc is the "Blind Carbon Copy" header field
|
// HeaderBcc is the "Blind Carbon Copy" header field
|
||||||
HeaderBcc AddrHeader = "Bcc"
|
HeaderBcc AddrHeader = "Bcc"
|
||||||
|
@ -89,6 +89,10 @@ const (
|
||||||
// HeaderCc is the "Carbon Copy" header field
|
// HeaderCc is the "Carbon Copy" header field
|
||||||
HeaderCc AddrHeader = "Cc"
|
HeaderCc AddrHeader = "Cc"
|
||||||
|
|
||||||
|
// HeaderEnvelopeFrom is the envelope FROM header field
|
||||||
|
// It's not included in the mail body but only used by the Client for the envelope
|
||||||
|
HeaderEnvelopeFrom AddrHeader = "EnvelopeFrom"
|
||||||
|
|
||||||
// HeaderFrom is the "From" header field
|
// HeaderFrom is the "From" header field
|
||||||
HeaderFrom AddrHeader = "From"
|
HeaderFrom AddrHeader = "From"
|
||||||
|
|
||||||
|
|
24
msg.go
24
msg.go
|
@ -197,6 +197,18 @@ func (m *Msg) SetAddrHeaderIgnoreInvalid(h AddrHeader, v ...string) {
|
||||||
m.addrHeader[h] = al
|
m.addrHeader[h] = al
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnvelopeFrom takes and validates a given mail address and sets it as envelope "FROM"
|
||||||
|
// addrHeader of the Msg
|
||||||
|
func (m *Msg) EnvelopeFrom(f string) error {
|
||||||
|
return m.SetAddrHeader(HeaderEnvelopeFrom, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnvelopeFromFormat takes a name and address, formats them RFC5322 compliant and stores them as
|
||||||
|
// the envelope FROM address header field
|
||||||
|
func (m *Msg) EnvelopeFromFormat(n, a string) error {
|
||||||
|
return m.SetAddrHeader(HeaderEnvelopeFrom, fmt.Sprintf(`"%s" <%s>`, n, a))
|
||||||
|
}
|
||||||
|
|
||||||
// From takes and validates a given mail address and sets it as "From" genHeader of the Msg
|
// From takes and validates a given mail address and sets it as "From" genHeader of the Msg
|
||||||
func (m *Msg) From(f string) error {
|
func (m *Msg) From(f string) error {
|
||||||
return m.SetAddrHeader(HeaderFrom, f)
|
return m.SetAddrHeader(HeaderFrom, f)
|
||||||
|
@ -365,12 +377,16 @@ func (m *Msg) SetUserAgent(a string) {
|
||||||
m.SetHeader(HeaderXMailer, a)
|
m.SetHeader(HeaderXMailer, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSender returns the currently set FROM address. If f is true, it will return the full
|
// GetSender returns the currently set envelope FROM address. If no envelope FROM is set it will use
|
||||||
// address string including the address name, if set
|
// the first mail body FROM address. If ff is true, it will return the full address string including
|
||||||
|
// the address name, if set
|
||||||
func (m *Msg) GetSender(ff bool) (string, error) {
|
func (m *Msg) GetSender(ff bool) (string, error) {
|
||||||
f, ok := m.addrHeader[HeaderFrom]
|
f, ok := m.addrHeader[HeaderEnvelopeFrom]
|
||||||
if !ok || len(f) == 0 {
|
if !ok || len(f) == 0 {
|
||||||
return "", ErrNoFromAddress
|
f, ok = m.addrHeader[HeaderFrom]
|
||||||
|
if !ok || len(f) == 0 {
|
||||||
|
return "", ErrNoFromAddress
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ff {
|
if ff {
|
||||||
return f[0].String(), nil
|
return f[0].String(), nil
|
||||||
|
|
78
msg_test.go
78
msg_test.go
|
@ -266,6 +266,84 @@ func TestMsg_From(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestMsg_EnvelopeFrom tests the Msg.EnvelopeFrom and Msg.GetSender methods
|
||||||
|
func TestMsg_EnvelopeFrom(t *testing.T) {
|
||||||
|
e := "envelope@example.com"
|
||||||
|
a := "toni@example.com"
|
||||||
|
n := "Toni Tester"
|
||||||
|
na := fmt.Sprintf(`"%s" <%s>`, n, a)
|
||||||
|
ne := fmt.Sprintf(`<%s>`, e)
|
||||||
|
m := NewMsg()
|
||||||
|
|
||||||
|
_, err := m.GetSender(false)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("GetSender(false) without a set envelope From address succeeded but was expected to fail")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.EnvelopeFrom(e); err != nil {
|
||||||
|
t.Errorf("failed to set envelope FROM addresses: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gs, err := m.GetSender(false)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSender(false) failed: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if gs != e {
|
||||||
|
t.Errorf("From() failed. Expected: %s, got: %s", e, gs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.From(na); err != nil {
|
||||||
|
t.Errorf("failed to set FROM addresses: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gs, err = m.GetSender(false)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSender(false) failed: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if gs != e {
|
||||||
|
t.Errorf("From() failed. Expected: %s, got: %s", e, gs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
gs, err = m.GetSender(true)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSender(true) failed: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if gs != ne {
|
||||||
|
t.Errorf("From() failed. Expected: %s, got: %s", ne, gs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.Reset()
|
||||||
|
|
||||||
|
if err := m.From(na); err != nil {
|
||||||
|
t.Errorf("failed to set FROM addresses: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gs, err = m.GetSender(false)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSender(true) failed: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if gs != a {
|
||||||
|
t.Errorf("From() failed. Expected: %s, got: %s", a, gs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gs, err = m.GetSender(true)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("GetSender(true) failed: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if gs != na {
|
||||||
|
t.Errorf("From() failed. Expected: %s, got: %s", na, gs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestMsg_AddToFormat tests the Msg.AddToFormat method
|
// TestMsg_AddToFormat tests the Msg.AddToFormat method
|
||||||
func TestMsg_AddToFormat(t *testing.T) {
|
func TestMsg_AddToFormat(t *testing.T) {
|
||||||
a := []string{"address1@example.com", "address2@example.com"}
|
a := []string{"address1@example.com", "address2@example.com"}
|
||||||
|
|
17
msgwriter.go
17
msgwriter.go
|
@ -54,7 +54,22 @@ func (mw *msgWriter) writeMsg(m *Msg) {
|
||||||
m.addDefaultHeader()
|
m.addDefaultHeader()
|
||||||
m.checkUserAgent()
|
m.checkUserAgent()
|
||||||
mw.writeGenHeader(m)
|
mw.writeGenHeader(m)
|
||||||
for _, t := range []AddrHeader{HeaderFrom, HeaderTo, HeaderCc} {
|
|
||||||
|
// Set the FROM header (or envelope FROM if FROM is empty)
|
||||||
|
hf := true
|
||||||
|
f, ok := m.addrHeader[HeaderFrom]
|
||||||
|
if !ok || len(f) == 0 {
|
||||||
|
f, ok = m.addrHeader[HeaderEnvelopeFrom]
|
||||||
|
if !ok || len(f) == 0 {
|
||||||
|
hf = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hf {
|
||||||
|
mw.writeHeader(Header(HeaderFrom), f[0].String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the rest of the address headers
|
||||||
|
for _, t := range []AddrHeader{HeaderTo, HeaderCc} {
|
||||||
if al, ok := m.addrHeader[t]; ok {
|
if al, ok := m.addrHeader[t]; ok {
|
||||||
var v []string
|
var v []string
|
||||||
for _, a := range al {
|
for _, a := range al {
|
||||||
|
|
Loading…
Reference in a new issue