commit
0b45421323
@ -0,0 +1,2 @@
|
||||
.idea/
|
||||
*_test.go
|
@ -0,0 +1,23 @@
|
||||
package nwmail
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Address struct {
|
||||
Alias string
|
||||
Address string
|
||||
}
|
||||
|
||||
func NewAddress(alias, address string) Address {
|
||||
return Address{
|
||||
Alias: alias,
|
||||
Address: address,
|
||||
}
|
||||
}
|
||||
|
||||
func (a Address) String() string {
|
||||
if len(a.Alias) > 0 {
|
||||
return fmt.Sprintf("\"%s\" <%s>", a.Alias, a.Address)
|
||||
}
|
||||
|
||||
return a.Address
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package nwmail
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/smtp"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
SMTPHostname string
|
||||
SMTPPort int
|
||||
PreferSTARTTLS bool
|
||||
}
|
||||
|
||||
func NewClient(smtpHostname string, smtpPort int, preferSTARTTLS bool) *Client {
|
||||
return &Client{SMTPHostname: smtpHostname, SMTPPort: smtpPort, PreferSTARTTLS: preferSTARTTLS}
|
||||
}
|
||||
|
||||
func (c Client) SendMail(mail *Mail) error {
|
||||
conn, err := smtp.Dial(fmt.Sprintf("%s:%d", c.SMTPHostname, c.SMTPPort))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.PreferSTARTTLS {
|
||||
if hasStartTLS, _ := conn.Extension("STARTTLS"); hasStartTLS {
|
||||
err = conn.StartTLS(&tls.Config{ServerName: c.SMTPHostname})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
conn.Mail(mail.sender)
|
||||
for _, recipient := range mail.recipients {
|
||||
conn.Rcpt(recipient)
|
||||
}
|
||||
|
||||
writer, err := conn.Data()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
io.Copy(writer, mail.Buffer())
|
||||
writer.Close()
|
||||
|
||||
return conn.Quit()
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package nwmail
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
HTMLUTF8 = "text/html; charset=utf-8"
|
||||
PlainTextUTF8 = "text/plain; charset=utf-8"
|
||||
)
|
||||
|
||||
type Mail struct {
|
||||
sender string
|
||||
recipients []string
|
||||
headers map[string]string
|
||||
body *bytes.Buffer
|
||||
}
|
||||
|
||||
func NewMail(sender Address) *Mail {
|
||||
m := &Mail{
|
||||
sender: sender.Address,
|
||||
headers: map[string]string{},
|
||||
body: new(bytes.Buffer),
|
||||
}
|
||||
|
||||
m.headers["Message-ID"] = m.generateMessageId()
|
||||
m.headers["From"] = sender.String()
|
||||
m.headers["Content-Type"] = PlainTextUTF8 //default, may be overridden
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Mail) AddRecipient(recipient Address) {
|
||||
m.recipients = append(m.recipients, recipient.Address)
|
||||
if len(m.headers["To"]) != 0 {
|
||||
m.headers["To"] += ","
|
||||
}
|
||||
|
||||
m.headers["To"] += recipient.String()
|
||||
}
|
||||
|
||||
func (m *Mail) AddCC(recipient Address) {
|
||||
m.recipients = append(m.recipients, recipient.Address)
|
||||
if len(m.headers["Cc"]) != 0 {
|
||||
m.headers["Cc"] += ","
|
||||
}
|
||||
|
||||
m.headers["Cc"] += recipient.String()
|
||||
}
|
||||
|
||||
func (m *Mail) AddBCC(recipient Address) {
|
||||
m.recipients = append(m.recipients, recipient.Address)
|
||||
if len(m.headers["Bcc"]) != 0 {
|
||||
m.headers["Bcc"] += ","
|
||||
}
|
||||
|
||||
m.headers["Bcc"] += recipient.String()
|
||||
}
|
||||
|
||||
func (m *Mail) SetSubject(subject string) {
|
||||
m.headers["Subject"] = subject
|
||||
}
|
||||
|
||||
func (m *Mail) SetContentType(contentType string) {
|
||||
m.headers["Content-Type"] = contentType
|
||||
}
|
||||
|
||||
func (m *Mail) SetPriority(priority Priority) {
|
||||
m.headers["Priority"] = priority.String()
|
||||
}
|
||||
|
||||
func (m *Mail) SetImportant() {
|
||||
m.headers["Importance"] = "high"
|
||||
}
|
||||
|
||||
func (m *Mail) SetSensitivity(sensitivity Sensitivity) {
|
||||
m.headers["Sensitivity"] = sensitivity.String()
|
||||
}
|
||||
|
||||
func (m *Mail) SetReplyTo(replyTo Address) {
|
||||
m.headers["Reply-To"] = replyTo.String()
|
||||
}
|
||||
|
||||
func (m *Mail) SetReadConfirmation(to Address) {
|
||||
m.headers["Disposition-Notification-To"] = to.String()
|
||||
}
|
||||
|
||||
func (m *Mail) SetReceivedConfirmation(to Address) {
|
||||
m.headers["Return-Receipt-To"] = to.String()
|
||||
}
|
||||
|
||||
func (m *Mail) Write(p []byte) (n int, err error) {
|
||||
return m.body.Write(p)
|
||||
}
|
||||
|
||||
func (m *Mail) WriteString(s string) (int, error) {
|
||||
return m.body.WriteString(s)
|
||||
}
|
||||
|
||||
func (m Mail) Buffer() *bytes.Buffer {
|
||||
mailBuf := new(bytes.Buffer)
|
||||
for key, value := range m.headers {
|
||||
mailBuf.WriteString(fmt.Sprintf("%s: %s\n", key, value))
|
||||
}
|
||||
|
||||
mailBuf.WriteString("\n")
|
||||
io.Copy(mailBuf, m.body)
|
||||
return mailBuf
|
||||
}
|
||||
|
||||
func (m Mail) String() string {
|
||||
return m.Buffer().String()
|
||||
}
|
||||
|
||||
func (m Mail) generateMessageId() string {
|
||||
uniqueId := make([]byte, 8)
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
rand.Read(uniqueId)
|
||||
|
||||
host := m.sender[strings.Index(m.sender, "@")+1:]
|
||||
|
||||
return fmt.Sprintf("<%s@%s>", hex.EncodeToString(uniqueId), host)
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package nwmail
|
||||
|
||||
type Priority int
|
||||
|
||||
const (
|
||||
PriorityUrgent Priority = iota
|
||||
PriorityNormal
|
||||
PriorityNonUrgent
|
||||
)
|
||||
|
||||
func (p Priority) String() string {
|
||||
return [...]string{
|
||||
"urgent",
|
||||
"normal",
|
||||
"non-urgent",
|
||||
}[p]
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package nwmail
|
||||
|
||||
type Sensitivity int
|
||||
|
||||
const (
|
||||
SensitivityPersonal Sensitivity = iota
|
||||
SensitivityPrivate
|
||||
SensitivityConfidential
|
||||
)
|
||||
|
||||
func (s Sensitivity) String() string {
|
||||
return [...]string{
|
||||
"Personal",
|
||||
"Private",
|
||||
"Company-Confidential",
|
||||
}[s]
|
||||
}
|
Loading…
Reference in new issue