aboutsummaryrefslogtreecommitdiff
path: root/internal/feed/mail.go
blob: 620b4449f7b7866f055c5d951a313e71f513a8bd (plain)
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package feed

import (
	"bytes"
	"fmt"
	"io"
	"strings"
	"time"

	"github.com/emersion/go-message/mail"

	"github.com/Necoro/feed2imap-go/internal/feed/template"
	"github.com/Necoro/feed2imap-go/pkg/config"
)

func address(name, address string) []*mail.Address {
	return []*mail.Address{{Name: name, Address: address}}
}

func fromAdress(feed *Feed, item feeditem, cfg *config.Config) []*mail.Address {
	switch {
	case item.Item.Author != nil && item.Item.Author.Email != "":
		return address(item.Item.Author.Name, item.Item.Author.Email)
	case item.Item.Author != nil && item.Item.Author.Name != "":
		return address(item.Item.Author.Name, cfg.DefaultEmail)
	case item.Feed.Author != nil && item.Feed.Author.Email != "":
		return address(item.Feed.Author.Name, item.Feed.Author.Email)
	case item.Feed.Author != nil && item.Feed.Author.Name != "":
		return address(item.Feed.Author.Name, cfg.DefaultEmail)
	default:
		return address(feed.Name, cfg.DefaultEmail)
	}
}

func writeHtml(writer io.Writer, item feeditem) error {
	return template.Feed.Execute(writer, item)
}

func writeToBuffer(b *bytes.Buffer, feed *Feed, item feeditem, cfg *config.Config) error {
	var h mail.Header
	h.SetAddressList("From", fromAdress(feed, item, cfg))
	h.SetAddressList("To", address(feed.Name, cfg.DefaultEmail))
	h.Add("X-Feed2Imap-Version", config.Version())
	h.Add("X-Feed2Imap-Reason", strings.Join(item.reasons, ","))

	{ // date
		date := item.Item.PublishedParsed
		if date == nil {
			now := time.Now()
			date = &now
		}
		h.SetDate(*date)
	}
	{ // subject
		subject := item.Item.Title
		if subject == "" {
			subject = item.Item.Published
		}
		if subject == "" {
			subject = item.Item.Link
		}
		h.SetSubject(subject)
	}

	tw, err := mail.CreateInlineWriter(b, h)
	if err != nil {
		return err
	}
	defer tw.Close()

	if false /* cfg.WithPartText() */ {
		var th mail.InlineHeader
		th.SetContentType("text/plain", map[string]string{"charset": "utf-8", "format": "flowed"})

		w, err := tw.CreatePart(th)
		if err != nil {
			return err
		}
		defer w.Close()

		_, _ = io.WriteString(w, "Who are you?")
	}

	if cfg.WithPartHtml() {
		var th mail.InlineHeader
		th.SetContentType("text/html", map[string]string{"charset": "utf-8"})

		w, err := tw.CreatePart(th)
		if err != nil {
			return err
		}

		if err = writeHtml(w, item); err != nil {
			return fmt.Errorf("writing html part: %w", err)
		}

		w.Close()
	}

	return nil
}

func asMail(feed *Feed, item feeditem, cfg *config.Config) (string, error) {
	var b bytes.Buffer

	if err := writeToBuffer(&b, feed, item, cfg); err != nil {
		return "", err
	}

	return b.String(), nil
}

func (feed *Feed) ToMails(cfg *config.Config) ([]string, error) {
	var (
		err   error
		mails = make([]string, len(feed.items))
	)
	for idx := range feed.items {
		if mails[idx], err = asMail(feed, feed.items[idx], cfg); err != nil {
			return nil, fmt.Errorf("creating mails for %s: %w", feed.Name, err)
		}
	}
	return mails, nil
}