master
Niels Westland 2 years ago
commit 0b45421323

2
.gitignore vendored

@ -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,3 @@
module git.nwestland.com/tools/nwmail
go 1.18

@ -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…
Cancel
Save