-
Notifications
You must be signed in to change notification settings - Fork 0
/
exchange.go
115 lines (92 loc) · 1.68 KB
/
exchange.go
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
package smtpd
import (
"errors"
"fmt"
"io"
"net/mail"
"strings"
)
type Channel interface {
Hostname() string
Reply(code int, msg string)
}
type WriterChannel struct {
w io.Writer
host string
}
func (c *WriterChannel) Hostname() string {
return c.host
}
func (c *WriterChannel) Reply(code int, msg string) {
lines := strings.Split(msg, "\n")
for i, line := range lines {
last := i == len(lines)-1
space := " "
if !last {
space = "-"
}
out := fmt.Sprintf("%d%s%s\r\n", code, space, line)
c.w.Write([]byte(out))
}
}
type Exchange struct {
io.ReadCloser
Channel
domain string
from *mail.Address
to []*mail.Address
body io.Reader
mailer Mailer
parser *mail.AddressParser
}
func NewExchange(m Mailer, r io.ReadCloser, c Channel) *Exchange {
return &Exchange{
Channel: c,
ReadCloser: r,
mailer: m,
parser: &mail.AddressParser{},
}
}
func (ex *Exchange) Domain(domain string) error {
if !isDomainName(domain) && !isIp(domain) {
return errors.New("invalid domain")
}
ex.domain = domain
return nil
}
func (ex *Exchange) From(from string) error {
addr, err := ex.parser.Parse(from)
if err != nil {
return err
}
ex.from = addr
return nil
}
func (ex *Exchange) To(to string) error {
addr, err := ex.parser.Parse(to)
if err != nil {
return err
}
if ex.to == nil {
ex.to = []*mail.Address{addr}
} else {
ex.to = append(ex.to, addr)
}
return nil
}
func (ex *Exchange) Body(r io.Reader) {
ex.body = r
}
func (ex *Exchange) Done() error {
msg, err := mail.ReadMessage(ex.body)
if err != nil {
return err
}
ex.mailer.Send(msg)
ex.Reset()
return nil
}
func (ex *Exchange) Reset() {
ex.from = nil
ex.to = nil
}