~bigbes/core-go

ref: 70c7fe3b3e4da6e331eb19c65d334d215c986332 core-go/email/send.go -rw-r--r-- 1.3 KiB
70c7fe3b — Drew DeVault webhooks/legacy: increase specificity of logging 5 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package email

import (
	"bytes"
	"context"
	"crypto/rand"
	"encoding/binary"
	"errors"
	"fmt"
	"os"
	"strconv"
	"time"

	"github.com/martinlindhe/base36"
	gomail "gopkg.in/mail.v2"

	"git.sr.ht/~sircmpwn/core-go/config"
)

// Sends an email. Blocks until it's sent or an error occurs.
func Send(ctx context.Context, m *gomail.Message) error {
	conf := config.ForContext(ctx)

	portStr, ok := conf.Get("mail", "smtp-port")
	if !ok {
		return errors.New("internal system error")
	}
	port, _ := strconv.Atoi(portStr)
	host, _ := conf.Get("mail", "smtp-host")
	user, _ := conf.Get("mail", "smtp-user")
	pass, _ := conf.Get("mail", "smtp-password")

	m.SetHeader("Message-ID", generateMessageID())
	m.SetDateHeader("Date", time.Now().UTC())

	d := gomail.NewDialer(host, port, user, pass)
	return d.DialAndSend(m)
}

// Generates an RFC 2822-compliant Message-Id based on the informational draft
// "Recommendations for generating Message IDs", for lack of a better
// authoritative source.
func generateMessageID() string {
	var (
		now   bytes.Buffer
		nonce []byte = make([]byte, 8)
	)
	binary.Write(&now, binary.BigEndian, time.Now().UnixNano())
	rand.Read(nonce)
	hostname, err := os.Hostname()
	if err != nil {
		hostname = "localhost"
	}
	return fmt.Sprintf("<%s.%s@%s>",
		base36.EncodeBytes(now.Bytes()),
		base36.EncodeBytes(nonce),
		hostname)
}