Simplified variable name of Message
This commit is contained in:
parent
79f88c6aa1
commit
b01506efc6
140
message.go
140
message.go
|
@ -34,52 +34,52 @@ type part struct {
|
||||||
// NewMessage creates a new message. It uses UTF-8 and quoted-printable encoding
|
// NewMessage creates a new message. It uses UTF-8 and quoted-printable encoding
|
||||||
// by default.
|
// by default.
|
||||||
func NewMessage(settings ...MessageSetting) *Message {
|
func NewMessage(settings ...MessageSetting) *Message {
|
||||||
msg := &Message{
|
m := &Message{
|
||||||
header: make(header),
|
header: make(header),
|
||||||
charset: "UTF-8",
|
charset: "UTF-8",
|
||||||
encoding: QuotedPrintable,
|
encoding: QuotedPrintable,
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.applySettings(settings)
|
m.applySettings(settings)
|
||||||
|
|
||||||
if msg.encoding == Base64 {
|
if m.encoding == Base64 {
|
||||||
msg.hEncoder = mime.BEncoding
|
m.hEncoder = mime.BEncoding
|
||||||
} else {
|
} else {
|
||||||
msg.hEncoder = mime.QEncoding
|
m.hEncoder = mime.QEncoding
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets the message so it can be reused. The message keeps its previous
|
// Reset resets the message so it can be reused. The message keeps its previous
|
||||||
// settings so it is in the same state that after a call to NewMessage.
|
// settings so it is in the same state that after a call to NewMessage.
|
||||||
func (msg *Message) Reset() {
|
func (m *Message) Reset() {
|
||||||
for k := range msg.header {
|
for k := range m.header {
|
||||||
delete(msg.header, k)
|
delete(m.header, k)
|
||||||
}
|
}
|
||||||
msg.parts = nil
|
m.parts = nil
|
||||||
msg.attachments = nil
|
m.attachments = nil
|
||||||
msg.embedded = nil
|
m.embedded = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *Message) applySettings(settings []MessageSetting) {
|
func (m *Message) applySettings(settings []MessageSetting) {
|
||||||
for _, s := range settings {
|
for _, s := range settings {
|
||||||
s(msg)
|
s(m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A MessageSetting can be used as an argument in NewMessage to configure an
|
// A MessageSetting can be used as an argument in NewMessage to configure an
|
||||||
// email.
|
// email.
|
||||||
type MessageSetting func(msg *Message)
|
type MessageSetting func(m *Message)
|
||||||
|
|
||||||
// SetCharset is a message setting to set the charset of the email.
|
// SetCharset is a message setting to set the charset of the email.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// msg := gomail.NewMessage(SetCharset("ISO-8859-1"))
|
// m := gomail.NewMessage(SetCharset("ISO-8859-1"))
|
||||||
func SetCharset(charset string) MessageSetting {
|
func SetCharset(charset string) MessageSetting {
|
||||||
return func(msg *Message) {
|
return func(m *Message) {
|
||||||
msg.charset = charset
|
m.charset = charset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,10 +87,10 @@ func SetCharset(charset string) MessageSetting {
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// msg := gomail.NewMessage(SetEncoding(gomail.Base64))
|
// m := gomail.NewMessage(SetEncoding(gomail.Base64))
|
||||||
func SetEncoding(enc Encoding) MessageSetting {
|
func SetEncoding(enc Encoding) MessageSetting {
|
||||||
return func(msg *Message) {
|
return func(m *Message) {
|
||||||
msg.encoding = enc
|
m.encoding = enc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,57 +109,57 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetHeader sets a value to the given header field.
|
// SetHeader sets a value to the given header field.
|
||||||
func (msg *Message) SetHeader(field string, value ...string) {
|
func (m *Message) SetHeader(field string, value ...string) {
|
||||||
for i := range value {
|
for i := range value {
|
||||||
value[i] = msg.encodeHeader(value[i])
|
value[i] = m.encodeHeader(value[i])
|
||||||
}
|
}
|
||||||
msg.header[field] = value
|
m.header[field] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHeaders sets the message headers.
|
// SetHeaders sets the message headers.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// msg.SetHeaders(map[string][]string{
|
// m.SetHeaders(map[string][]string{
|
||||||
// "From": {"alex@example.com"},
|
// "From": {"alex@example.com"},
|
||||||
// "To": {"bob@example.com", "cora@example.com"},
|
// "To": {"bob@example.com", "cora@example.com"},
|
||||||
// "Subject": {"Hello"},
|
// "Subject": {"Hello"},
|
||||||
// })
|
// })
|
||||||
func (msg *Message) SetHeaders(h map[string][]string) {
|
func (m *Message) SetHeaders(h map[string][]string) {
|
||||||
for k, v := range h {
|
for k, v := range h {
|
||||||
msg.SetHeader(k, v...)
|
m.SetHeader(k, v...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAddressHeader sets an address to the given header field.
|
// SetAddressHeader sets an address to the given header field.
|
||||||
func (msg *Message) SetAddressHeader(field, address, name string) {
|
func (m *Message) SetAddressHeader(field, address, name string) {
|
||||||
msg.header[field] = []string{msg.FormatAddress(address, name)}
|
m.header[field] = []string{m.FormatAddress(address, name)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatAddress formats an address and a name as a valid RFC 5322 address.
|
// FormatAddress formats an address and a name as a valid RFC 5322 address.
|
||||||
func (msg *Message) FormatAddress(address, name string) string {
|
func (m *Message) FormatAddress(address, name string) string {
|
||||||
enc := msg.encodeHeader(name)
|
enc := m.encodeHeader(name)
|
||||||
if enc == name {
|
if enc == name {
|
||||||
msg.buf.WriteByte('"')
|
m.buf.WriteByte('"')
|
||||||
for i := 0; i < len(name); i++ {
|
for i := 0; i < len(name); i++ {
|
||||||
b := name[i]
|
b := name[i]
|
||||||
if b == '\\' || b == '"' {
|
if b == '\\' || b == '"' {
|
||||||
msg.buf.WriteByte('\\')
|
m.buf.WriteByte('\\')
|
||||||
}
|
}
|
||||||
msg.buf.WriteByte(b)
|
m.buf.WriteByte(b)
|
||||||
}
|
}
|
||||||
msg.buf.WriteByte('"')
|
m.buf.WriteByte('"')
|
||||||
} else if hasSpecials(name) {
|
} else if hasSpecials(name) {
|
||||||
msg.buf.WriteString(mime.BEncoding.Encode(msg.charset, name))
|
m.buf.WriteString(mime.BEncoding.Encode(m.charset, name))
|
||||||
} else {
|
} else {
|
||||||
msg.buf.WriteString(enc)
|
m.buf.WriteString(enc)
|
||||||
}
|
}
|
||||||
msg.buf.WriteString(" <")
|
m.buf.WriteString(" <")
|
||||||
msg.buf.WriteString(address)
|
m.buf.WriteString(address)
|
||||||
msg.buf.WriteByte('>')
|
m.buf.WriteByte('>')
|
||||||
|
|
||||||
addr := msg.buf.String()
|
addr := m.buf.String()
|
||||||
msg.buf.Reset()
|
m.buf.Reset()
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,33 +174,33 @@ func hasSpecials(text string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *Message) encodeHeader(value string) string {
|
func (m *Message) encodeHeader(value string) string {
|
||||||
return msg.hEncoder.Encode(msg.charset, value)
|
return m.hEncoder.Encode(m.charset, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDateHeader sets a date to the given header field.
|
// SetDateHeader sets a date to the given header field.
|
||||||
func (msg *Message) SetDateHeader(field string, date time.Time) {
|
func (m *Message) SetDateHeader(field string, date time.Time) {
|
||||||
msg.header[field] = []string{msg.FormatDate(date)}
|
m.header[field] = []string{m.FormatDate(date)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatDate formats a date as a valid RFC 5322 date.
|
// FormatDate formats a date as a valid RFC 5322 date.
|
||||||
func (msg *Message) FormatDate(date time.Time) string {
|
func (m *Message) FormatDate(date time.Time) string {
|
||||||
return date.Format(time.RFC1123Z)
|
return date.Format(time.RFC1123Z)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeader gets a header field.
|
// GetHeader gets a header field.
|
||||||
func (msg *Message) GetHeader(field string) []string {
|
func (m *Message) GetHeader(field string) []string {
|
||||||
return msg.header[field]
|
return m.header[field]
|
||||||
}
|
}
|
||||||
|
|
||||||
// DelHeader deletes a header field.
|
// DelHeader deletes a header field.
|
||||||
func (msg *Message) DelHeader(field string) {
|
func (m *Message) DelHeader(field string) {
|
||||||
delete(msg.header, field)
|
delete(m.header, field)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBody sets the body of the message.
|
// SetBody sets the body of the message.
|
||||||
func (msg *Message) SetBody(contentType, body string) {
|
func (m *Message) SetBody(contentType, body string) {
|
||||||
msg.parts = []part{
|
m.parts = []part{
|
||||||
part{
|
part{
|
||||||
contentType: contentType,
|
contentType: contentType,
|
||||||
copier: func(w io.Writer) error {
|
copier: func(w io.Writer) error {
|
||||||
|
@ -217,12 +217,12 @@ func (msg *Message) SetBody(contentType, body string) {
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// msg.SetBody("text/plain", "Hello!")
|
// m.SetBody("text/plain", "Hello!")
|
||||||
// msg.AddAlternative("text/html", "<p>Hello!</p>")
|
// m.AddAlternative("text/html", "<p>Hello!</p>")
|
||||||
//
|
//
|
||||||
// More info: http://en.wikipedia.org/wiki/MIME#Alternative
|
// More info: http://en.wikipedia.org/wiki/MIME#Alternative
|
||||||
func (msg *Message) AddAlternative(contentType, body string) {
|
func (m *Message) AddAlternative(contentType, body string) {
|
||||||
msg.parts = append(msg.parts,
|
m.parts = append(m.parts,
|
||||||
part{
|
part{
|
||||||
contentType: contentType,
|
contentType: contentType,
|
||||||
copier: func(w io.Writer) error {
|
copier: func(w io.Writer) error {
|
||||||
|
@ -239,11 +239,11 @@ func (msg *Message) AddAlternative(contentType, body string) {
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// t := template.Must(template.New("example").Parse("Hello {{.}}!"))
|
// t := template.Must(template.New("example").Parse("Hello {{.}}!"))
|
||||||
// msg.AddAlternativeWriter("text/plain", func(w io.Writer) error {
|
// m.AddAlternativeWriter("text/plain", func(w io.Writer) error {
|
||||||
// return t.Execute(w, "Bob")
|
// return t.Execute(w, "Bob")
|
||||||
// })
|
// })
|
||||||
func (msg *Message) AddAlternativeWriter(contentType string, f func(io.Writer) error) {
|
func (m *Message) AddAlternativeWriter(contentType string, f func(io.Writer) error) {
|
||||||
msg.parts = []part{
|
m.parts = []part{
|
||||||
part{
|
part{
|
||||||
contentType: contentType,
|
contentType: contentType,
|
||||||
copier: f,
|
copier: f,
|
||||||
|
@ -288,11 +288,11 @@ func (f *File) setHeader(field string, value ...string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach attaches the files to the email.
|
// Attach attaches the files to the email.
|
||||||
func (msg *Message) Attach(f ...*File) {
|
func (m *Message) Attach(f ...*File) {
|
||||||
if msg.attachments == nil {
|
if m.attachments == nil {
|
||||||
msg.attachments = f
|
m.attachments = f
|
||||||
} else {
|
} else {
|
||||||
msg.attachments = append(msg.attachments, f...)
|
m.attachments = append(m.attachments, f...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,12 +304,12 @@ func (msg *Message) Attach(f ...*File) {
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// panic(err)
|
// panic(err)
|
||||||
// }
|
// }
|
||||||
// msg.Embed(f)
|
// m.Embed(f)
|
||||||
// msg.SetBody("text/html", `<img src="cid:image.jpg" alt="My image" />`)
|
// m.SetBody("text/html", `<img src="cid:image.jpg" alt="My image" />`)
|
||||||
func (msg *Message) Embed(image ...*File) {
|
func (m *Message) Embed(image ...*File) {
|
||||||
if msg.embedded == nil {
|
if m.embedded == nil {
|
||||||
msg.embedded = image
|
m.embedded = image
|
||||||
} else {
|
} else {
|
||||||
msg.embedded = append(msg.embedded, image...)
|
m.embedded = append(m.embedded, image...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
210
message_test.go
210
message_test.go
|
@ -25,18 +25,18 @@ type message struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMessage(t *testing.T) {
|
func TestMessage(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetAddressHeader("From", "from@example.com", "Señor From")
|
m.SetAddressHeader("From", "from@example.com", "Señor From")
|
||||||
msg.SetHeader("To", msg.FormatAddress("to@example.com", "Señor To"), "tobis@example.com")
|
m.SetHeader("To", m.FormatAddress("to@example.com", "Señor To"), "tobis@example.com")
|
||||||
msg.SetAddressHeader("Cc", "cc@example.com", "A, B")
|
m.SetAddressHeader("Cc", "cc@example.com", "A, B")
|
||||||
msg.SetAddressHeader("X-To", "ccbis@example.com", "à, b")
|
m.SetAddressHeader("X-To", "ccbis@example.com", "à, b")
|
||||||
msg.SetDateHeader("X-Date", now())
|
m.SetDateHeader("X-Date", now())
|
||||||
msg.SetHeader("X-Date-2", msg.FormatDate(now()))
|
m.SetHeader("X-Date-2", m.FormatDate(now()))
|
||||||
msg.SetHeader("Subject", "¡Hola, señor!")
|
m.SetHeader("Subject", "¡Hola, señor!")
|
||||||
msg.SetHeaders(map[string][]string{
|
m.SetHeaders(map[string][]string{
|
||||||
"X-Headers": {"Test", "Café"},
|
"X-Headers": {"Test", "Café"},
|
||||||
})
|
})
|
||||||
msg.SetBody("text/plain", "¡Hola, señor!")
|
m.SetBody("text/plain", "¡Hola, señor!")
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -59,14 +59,14 @@ func TestMessage(t *testing.T) {
|
||||||
"=C2=A1Hola, se=C3=B1or!",
|
"=C2=A1Hola, se=C3=B1or!",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 0, want)
|
testMessage(t, m, 0, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBodyWriter(t *testing.T) {
|
func TestBodyWriter(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.AddAlternativeWriter("text/plain", func(w io.Writer) error {
|
m.AddAlternativeWriter("text/plain", func(w io.Writer) error {
|
||||||
_, err := w.Write([]byte("Test message"))
|
_, err := w.Write([]byte("Test message"))
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
@ -82,17 +82,17 @@ func TestBodyWriter(t *testing.T) {
|
||||||
"Test message",
|
"Test message",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 0, want)
|
testMessage(t, m, 0, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCustomMessage(t *testing.T) {
|
func TestCustomMessage(t *testing.T) {
|
||||||
msg := NewMessage(SetCharset("ISO-8859-1"), SetEncoding(Base64))
|
m := NewMessage(SetCharset("ISO-8859-1"), SetEncoding(Base64))
|
||||||
msg.SetHeaders(map[string][]string{
|
m.SetHeaders(map[string][]string{
|
||||||
"From": {"from@example.com"},
|
"From": {"from@example.com"},
|
||||||
"To": {"to@example.com"},
|
"To": {"to@example.com"},
|
||||||
"Subject": {"Café"},
|
"Subject": {"Café"},
|
||||||
})
|
})
|
||||||
msg.SetBody("text/html", "¡Hola, señor!")
|
m.SetBody("text/html", "¡Hola, señor!")
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -106,17 +106,17 @@ func TestCustomMessage(t *testing.T) {
|
||||||
"wqFIb2xhLCBzZcOxb3Ih",
|
"wqFIb2xhLCBzZcOxb3Ih",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 0, want)
|
testMessage(t, m, 0, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnencodedMessage(t *testing.T) {
|
func TestUnencodedMessage(t *testing.T) {
|
||||||
msg := NewMessage(SetEncoding(Unencoded))
|
m := NewMessage(SetEncoding(Unencoded))
|
||||||
msg.SetHeaders(map[string][]string{
|
m.SetHeaders(map[string][]string{
|
||||||
"From": {"from@example.com"},
|
"From": {"from@example.com"},
|
||||||
"To": {"to@example.com"},
|
"To": {"to@example.com"},
|
||||||
"Subject": {"Café"},
|
"Subject": {"Café"},
|
||||||
})
|
})
|
||||||
msg.SetBody("text/html", "¡Hola, señor!")
|
m.SetBody("text/html", "¡Hola, señor!")
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -130,19 +130,19 @@ func TestUnencodedMessage(t *testing.T) {
|
||||||
"¡Hola, señor!",
|
"¡Hola, señor!",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 0, want)
|
testMessage(t, m, 0, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRecipients(t *testing.T) {
|
func TestRecipients(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeaders(map[string][]string{
|
m.SetHeaders(map[string][]string{
|
||||||
"From": {"from@example.com"},
|
"From": {"from@example.com"},
|
||||||
"To": {"to@example.com"},
|
"To": {"to@example.com"},
|
||||||
"Cc": {"cc@example.com"},
|
"Cc": {"cc@example.com"},
|
||||||
"Bcc": {"bcc1@example.com", "bcc2@example.com"},
|
"Bcc": {"bcc1@example.com", "bcc2@example.com"},
|
||||||
"Subject": {"Hello!"},
|
"Subject": {"Hello!"},
|
||||||
})
|
})
|
||||||
msg.SetBody("text/plain", "Test message")
|
m.SetBody("text/plain", "Test message")
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -157,15 +157,15 @@ func TestRecipients(t *testing.T) {
|
||||||
"Test message",
|
"Test message",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 0, want)
|
testMessage(t, m, 0, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAlternative(t *testing.T) {
|
func TestAlternative(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.SetBody("text/plain", "¡Hola, señor!")
|
m.SetBody("text/plain", "¡Hola, señor!")
|
||||||
msg.AddAlternative("text/html", "¡<b>Hola</b>, <i>señor</i>!</h1>")
|
m.AddAlternative("text/html", "¡<b>Hola</b>, <i>señor</i>!</h1>")
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -187,14 +187,14 @@ func TestAlternative(t *testing.T) {
|
||||||
"--_BOUNDARY_1_--\r\n",
|
"--_BOUNDARY_1_--\r\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 1, want)
|
testMessage(t, m, 1, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAttachmentOnly(t *testing.T) {
|
func TestAttachmentOnly(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.Attach(testFile("/tmp/test.pdf"))
|
m.Attach(testFile("/tmp/test.pdf"))
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -208,15 +208,15 @@ func TestAttachmentOnly(t *testing.T) {
|
||||||
base64.StdEncoding.EncodeToString([]byte("Content of test.pdf")),
|
base64.StdEncoding.EncodeToString([]byte("Content of test.pdf")),
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 0, want)
|
testMessage(t, m, 0, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAttachment(t *testing.T) {
|
func TestAttachment(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.SetBody("text/plain", "Test")
|
m.SetBody("text/plain", "Test")
|
||||||
msg.Attach(testFile("/tmp/test.pdf"))
|
m.Attach(testFile("/tmp/test.pdf"))
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -239,15 +239,15 @@ func TestAttachment(t *testing.T) {
|
||||||
"--_BOUNDARY_1_--\r\n",
|
"--_BOUNDARY_1_--\r\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 1, want)
|
testMessage(t, m, 1, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAttachmentsOnly(t *testing.T) {
|
func TestAttachmentsOnly(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.Attach(testFile("/tmp/test.pdf"))
|
m.Attach(testFile("/tmp/test.pdf"))
|
||||||
msg.Attach(testFile("/tmp/test.zip"))
|
m.Attach(testFile("/tmp/test.zip"))
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -271,16 +271,16 @@ func TestAttachmentsOnly(t *testing.T) {
|
||||||
"--_BOUNDARY_1_--\r\n",
|
"--_BOUNDARY_1_--\r\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 1, want)
|
testMessage(t, m, 1, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAttachments(t *testing.T) {
|
func TestAttachments(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.SetBody("text/plain", "Test")
|
m.SetBody("text/plain", "Test")
|
||||||
msg.Attach(testFile("/tmp/test.pdf"))
|
m.Attach(testFile("/tmp/test.pdf"))
|
||||||
msg.Attach(testFile("/tmp/test.zip"))
|
m.Attach(testFile("/tmp/test.zip"))
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -309,18 +309,18 @@ func TestAttachments(t *testing.T) {
|
||||||
"--_BOUNDARY_1_--\r\n",
|
"--_BOUNDARY_1_--\r\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 1, want)
|
testMessage(t, m, 1, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEmbedded(t *testing.T) {
|
func TestEmbedded(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
f := testFile("image1.jpg")
|
f := testFile("image1.jpg")
|
||||||
f.Header["Content-ID"] = []string{"<test-content-id>"}
|
f.Header["Content-ID"] = []string{"<test-content-id>"}
|
||||||
msg.Embed(f)
|
m.Embed(f)
|
||||||
msg.Embed(testFile("image2.jpg"))
|
m.Embed(testFile("image2.jpg"))
|
||||||
msg.SetBody("text/plain", "Test")
|
m.SetBody("text/plain", "Test")
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -351,17 +351,17 @@ func TestEmbedded(t *testing.T) {
|
||||||
"--_BOUNDARY_1_--\r\n",
|
"--_BOUNDARY_1_--\r\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 1, want)
|
testMessage(t, m, 1, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFullMessage(t *testing.T) {
|
func TestFullMessage(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.SetBody("text/plain", "¡Hola, señor!")
|
m.SetBody("text/plain", "¡Hola, señor!")
|
||||||
msg.AddAlternative("text/html", "¡<b>Hola</b>, <i>señor</i>!</h1>")
|
m.AddAlternative("text/html", "¡<b>Hola</b>, <i>señor</i>!</h1>")
|
||||||
msg.Attach(testFile("test.pdf"))
|
m.Attach(testFile("test.pdf"))
|
||||||
msg.Embed(testFile("image.jpg"))
|
m.Embed(testFile("image.jpg"))
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -406,7 +406,7 @@ func TestFullMessage(t *testing.T) {
|
||||||
"--_BOUNDARY_1_--\r\n",
|
"--_BOUNDARY_1_--\r\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 3, want)
|
testMessage(t, m, 3, want)
|
||||||
|
|
||||||
want = &message{
|
want = &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -418,18 +418,18 @@ func TestFullMessage(t *testing.T) {
|
||||||
"\r\n" +
|
"\r\n" +
|
||||||
"Test reset",
|
"Test reset",
|
||||||
}
|
}
|
||||||
msg.Reset()
|
m.Reset()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.SetBody("text/plain", "Test reset")
|
m.SetBody("text/plain", "Test reset")
|
||||||
testMessage(t, msg, 0, want)
|
testMessage(t, m, 0, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQpLineLength(t *testing.T) {
|
func TestQpLineLength(t *testing.T) {
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.SetBody("text/plain",
|
m.SetBody("text/plain",
|
||||||
strings.Repeat("0", 76)+"\r\n"+
|
strings.Repeat("0", 76)+"\r\n"+
|
||||||
strings.Repeat("0", 75)+"à\r\n"+
|
strings.Repeat("0", 75)+"à\r\n"+
|
||||||
strings.Repeat("0", 74)+"à\r\n"+
|
strings.Repeat("0", 74)+"à\r\n"+
|
||||||
|
@ -455,14 +455,14 @@ func TestQpLineLength(t *testing.T) {
|
||||||
strings.Repeat("0", 75) + "=\r\n0\r\n",
|
strings.Repeat("0", 75) + "=\r\n0\r\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 0, want)
|
testMessage(t, m, 0, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBase64LineLength(t *testing.T) {
|
func TestBase64LineLength(t *testing.T) {
|
||||||
msg := NewMessage(SetCharset("UTF-8"), SetEncoding(Base64))
|
m := NewMessage(SetCharset("UTF-8"), SetEncoding(Base64))
|
||||||
msg.SetHeader("From", "from@example.com")
|
m.SetHeader("From", "from@example.com")
|
||||||
msg.SetHeader("To", "to@example.com")
|
m.SetHeader("To", "to@example.com")
|
||||||
msg.SetBody("text/plain", strings.Repeat("0", 58))
|
m.SetBody("text/plain", strings.Repeat("0", 58))
|
||||||
|
|
||||||
want := &message{
|
want := &message{
|
||||||
from: "from@example.com",
|
from: "from@example.com",
|
||||||
|
@ -475,18 +475,18 @@ func TestBase64LineLength(t *testing.T) {
|
||||||
strings.Repeat("MDAw", 19) + "\r\nMA==",
|
strings.Repeat("MDAw", 19) + "\r\nMA==",
|
||||||
}
|
}
|
||||||
|
|
||||||
testMessage(t, msg, 0, want)
|
testMessage(t, m, 0, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMessage(t *testing.T, msg *Message, bCount int, want *message) {
|
func testMessage(t *testing.T, m *Message, bCount int, want *message) {
|
||||||
err := Send(stubSendMail(t, bCount, want), msg)
|
err := Send(stubSendMail(t, bCount, want), m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func stubSendMail(t *testing.T, bCount int, want *message) SendFunc {
|
func stubSendMail(t *testing.T, bCount int, want *message) SendFunc {
|
||||||
return func(from string, to []string, msg io.WriterTo) error {
|
return func(from string, to []string, m io.WriterTo) error {
|
||||||
if from != want.from {
|
if from != want.from {
|
||||||
t.Fatalf("Invalid from, got %q, want %q", from, want.from)
|
t.Fatalf("Invalid from, got %q, want %q", from, want.from)
|
||||||
}
|
}
|
||||||
|
@ -506,7 +506,7 @@ func stubSendMail(t *testing.T, bCount int, want *message) SendFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
_, err := msg.WriteTo(buf)
|
_, err := m.WriteTo(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -575,8 +575,8 @@ func missingLine(t *testing.T, line, got, want string) {
|
||||||
t.Fatalf("Missing line %q\ngot:\n%s\nwant:\n%s", line, got, want)
|
t.Fatalf("Missing line %q\ngot:\n%s\nwant:\n%s", line, got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBoundaries(t *testing.T, count int, msg string) []string {
|
func getBoundaries(t *testing.T, count int, m string) []string {
|
||||||
if matches := boundaryRegExp.FindAllStringSubmatch(msg, count); matches != nil {
|
if matches := boundaryRegExp.FindAllStringSubmatch(m, count); matches != nil {
|
||||||
boundaries := make([]string, count)
|
boundaries := make([]string, count)
|
||||||
for i, match := range matches {
|
for i, match := range matches {
|
||||||
boundaries[i] = match[1]
|
boundaries[i] = match[1]
|
||||||
|
@ -601,30 +601,30 @@ func testFile(name string) *File {
|
||||||
|
|
||||||
func BenchmarkFull(b *testing.B) {
|
func BenchmarkFull(b *testing.B) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
emptyFunc := func(from string, to []string, msg io.WriterTo) error {
|
emptyFunc := func(from string, to []string, m io.WriterTo) error {
|
||||||
msg.WriteTo(buf)
|
m.WriteTo(buf)
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := NewMessage()
|
m := NewMessage()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
msg.SetAddressHeader("From", "from@example.com", "Señor From")
|
m.SetAddressHeader("From", "from@example.com", "Señor From")
|
||||||
msg.SetHeaders(map[string][]string{
|
m.SetHeaders(map[string][]string{
|
||||||
"To": {"to@example.com"},
|
"To": {"to@example.com"},
|
||||||
"Cc": {"cc@example.com"},
|
"Cc": {"cc@example.com"},
|
||||||
"Bcc": {"bcc1@example.com", "bcc2@example.com"},
|
"Bcc": {"bcc1@example.com", "bcc2@example.com"},
|
||||||
"Subject": {"¡Hola, señor!"},
|
"Subject": {"¡Hola, señor!"},
|
||||||
})
|
})
|
||||||
msg.SetBody("text/plain", "¡Hola, señor!")
|
m.SetBody("text/plain", "¡Hola, señor!")
|
||||||
msg.AddAlternative("text/html", "<p>¡Hola, señor!</p>")
|
m.AddAlternative("text/html", "<p>¡Hola, señor!</p>")
|
||||||
msg.Attach(testFile("benchmark.txt"))
|
m.Attach(testFile("benchmark.txt"))
|
||||||
msg.Embed(testFile("benchmark.jpg"))
|
m.Embed(testFile("benchmark.jpg"))
|
||||||
|
|
||||||
if err := Send(SendFunc(emptyFunc), msg); err != nil {
|
if err := Send(SendFunc(emptyFunc), m); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
msg.Reset()
|
m.Reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
send.go
18
send.go
|
@ -42,28 +42,28 @@ func Send(s Sender, msg ...*Message) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func send(s Sender, msg *Message) error {
|
func send(s Sender, m *Message) error {
|
||||||
from, err := msg.getFrom()
|
from, err := m.getFrom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
to, err := msg.getRecipients()
|
to, err := m.getRecipients()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.Send(from, to, msg); err != nil {
|
if err := s.Send(from, to, m); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *Message) getFrom() (string, error) {
|
func (m *Message) getFrom() (string, error) {
|
||||||
from := msg.header["Sender"]
|
from := m.header["Sender"]
|
||||||
if len(from) == 0 {
|
if len(from) == 0 {
|
||||||
from = msg.header["From"]
|
from = m.header["From"]
|
||||||
if len(from) == 0 {
|
if len(from) == 0 {
|
||||||
return "", errors.New(`gomail: invalid message, "From" field is absent`)
|
return "", errors.New(`gomail: invalid message, "From" field is absent`)
|
||||||
}
|
}
|
||||||
|
@ -72,10 +72,10 @@ func (msg *Message) getFrom() (string, error) {
|
||||||
return parseAddress(from[0])
|
return parseAddress(from[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *Message) getRecipients() ([]string, error) {
|
func (m *Message) getRecipients() ([]string, error) {
|
||||||
var list []string
|
var list []string
|
||||||
for _, field := range []string{"To", "Cc", "Bcc"} {
|
for _, field := range []string{"To", "Cc", "Bcc"} {
|
||||||
if addresses, ok := msg.header[field]; ok {
|
if addresses, ok := m.header[field]; ok {
|
||||||
for _, a := range addresses {
|
for _, a := range addresses {
|
||||||
addr, err := parseAddress(a)
|
addr, err := parseAddress(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
4
smtp.go
4
smtp.go
|
@ -108,14 +108,14 @@ func addr(host string, port int) string {
|
||||||
|
|
||||||
// DialAndSend opens a connection to the SMTP server, sends the given emails and
|
// DialAndSend opens a connection to the SMTP server, sends the given emails and
|
||||||
// closes the connection.
|
// closes the connection.
|
||||||
func (d *Dialer) DialAndSend(msg ...*Message) error {
|
func (d *Dialer) DialAndSend(m ...*Message) error {
|
||||||
s, err := d.Dial()
|
s, err := d.Dial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
return Send(s, msg...)
|
return Send(s, m...)
|
||||||
}
|
}
|
||||||
|
|
||||||
type smtpSender struct {
|
type smtpSender struct {
|
||||||
|
|
50
writeto.go
50
writeto.go
|
@ -12,65 +12,65 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// WriteTo implements io.WriterTo. It dumps the whole message into w.
|
// WriteTo implements io.WriterTo. It dumps the whole message into w.
|
||||||
func (msg *Message) WriteTo(w io.Writer) (int64, error) {
|
func (m *Message) WriteTo(w io.Writer) (int64, error) {
|
||||||
mw := &messageWriter{w: w}
|
mw := &messageWriter{w: w}
|
||||||
mw.writeMessage(msg)
|
mw.writeMessage(m)
|
||||||
return mw.n, mw.err
|
return mw.n, mw.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *messageWriter) writeMessage(msg *Message) {
|
func (w *messageWriter) writeMessage(m *Message) {
|
||||||
if _, ok := msg.header["Mime-Version"]; !ok {
|
if _, ok := m.header["Mime-Version"]; !ok {
|
||||||
w.writeString("Mime-Version: 1.0\r\n")
|
w.writeString("Mime-Version: 1.0\r\n")
|
||||||
}
|
}
|
||||||
if _, ok := msg.header["Date"]; !ok {
|
if _, ok := m.header["Date"]; !ok {
|
||||||
w.writeHeader("Date", msg.FormatDate(now()))
|
w.writeHeader("Date", m.FormatDate(now()))
|
||||||
}
|
}
|
||||||
w.writeHeaders(msg.header)
|
w.writeHeaders(m.header)
|
||||||
|
|
||||||
if msg.hasMixedPart() {
|
if m.hasMixedPart() {
|
||||||
w.openMultipart("mixed")
|
w.openMultipart("mixed")
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.hasRelatedPart() {
|
if m.hasRelatedPart() {
|
||||||
w.openMultipart("related")
|
w.openMultipart("related")
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.hasAlternativePart() {
|
if m.hasAlternativePart() {
|
||||||
w.openMultipart("alternative")
|
w.openMultipart("alternative")
|
||||||
}
|
}
|
||||||
for _, part := range msg.parts {
|
for _, part := range m.parts {
|
||||||
contentType := part.contentType + "; charset=" + msg.charset
|
contentType := part.contentType + "; charset=" + m.charset
|
||||||
w.writeHeaders(map[string][]string{
|
w.writeHeaders(map[string][]string{
|
||||||
"Content-Type": []string{contentType},
|
"Content-Type": []string{contentType},
|
||||||
"Content-Transfer-Encoding": []string{string(msg.encoding)},
|
"Content-Transfer-Encoding": []string{string(m.encoding)},
|
||||||
})
|
})
|
||||||
w.writeBody(part.copier, msg.encoding)
|
w.writeBody(part.copier, m.encoding)
|
||||||
}
|
}
|
||||||
if msg.hasAlternativePart() {
|
if m.hasAlternativePart() {
|
||||||
w.closeMultipart()
|
w.closeMultipart()
|
||||||
}
|
}
|
||||||
|
|
||||||
w.addFiles(msg.embedded, false)
|
w.addFiles(m.embedded, false)
|
||||||
if msg.hasRelatedPart() {
|
if m.hasRelatedPart() {
|
||||||
w.closeMultipart()
|
w.closeMultipart()
|
||||||
}
|
}
|
||||||
|
|
||||||
w.addFiles(msg.attachments, true)
|
w.addFiles(m.attachments, true)
|
||||||
if msg.hasMixedPart() {
|
if m.hasMixedPart() {
|
||||||
w.closeMultipart()
|
w.closeMultipart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *Message) hasMixedPart() bool {
|
func (m *Message) hasMixedPart() bool {
|
||||||
return (len(msg.parts) > 0 && len(msg.attachments) > 0) || len(msg.attachments) > 1
|
return (len(m.parts) > 0 && len(m.attachments) > 0) || len(m.attachments) > 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *Message) hasRelatedPart() bool {
|
func (m *Message) hasRelatedPart() bool {
|
||||||
return (len(msg.parts) > 0 && len(msg.embedded) > 0) || len(msg.embedded) > 1
|
return (len(m.parts) > 0 && len(m.embedded) > 0) || len(m.embedded) > 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *Message) hasAlternativePart() bool {
|
func (m *Message) hasAlternativePart() bool {
|
||||||
return len(msg.parts) > 1
|
return len(m.parts) > 1
|
||||||
}
|
}
|
||||||
|
|
||||||
type messageWriter struct {
|
type messageWriter struct {
|
||||||
|
|
Loading…
Reference in New Issue