-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
pop.go
119 lines (103 loc) · 2.63 KB
/
pop.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
116
117
118
119
package mailbox
import (
"encoding/json"
"time"
"github.com/knadh/go-pop3"
"github.com/knadh/listmonk/models"
)
// POP represents a POP mailbox.
type POP struct {
opt Opt
client *pop3.Client
}
// NewPOP returns a new instance of the POP mailbox client.
func NewPOP(opt Opt) *POP {
return &POP{
opt: opt,
client: pop3.New(pop3.Opt{
Host: opt.Host,
Port: opt.Port,
TLSEnabled: opt.TLSEnabled,
TLSSkipVerify: opt.TLSSkipVerify,
}),
}
}
// Scan scans the mailbox and pushes the downloaded messages into the given channel.
// The messages that are downloaded are deleted from the server. If limit > 0,
// all messages on the server are downloaded and deleted.
func (p *POP) Scan(limit int, ch chan models.Bounce) error {
c, err := p.client.NewConn()
if err != nil {
return err
}
defer c.Quit()
// Authenticate.
if p.opt.AuthProtocol != "none" {
if err := c.Auth(p.opt.Username, p.opt.Password); err != nil {
return err
}
}
// Get the total number of messages on the server.
count, _, err := c.Stat()
if err != nil {
return err
}
// No messages.
if count == 0 {
return nil
}
if limit > 0 && count > limit {
count = limit
}
// Download messages.
for id := 1; id <= count; id++ {
// Download just one line of the body as the body is not required at all.
m, err := c.Top(id, 1)
if err != nil {
return err
}
var (
campUUID = m.Header.Get(models.EmailHeaderCampaignUUID)
subUUID = m.Header.Get(models.EmailHeaderSubscriberUUID)
date, _ = time.Parse("Mon, 02 Jan 2006 15:04:05 -0700", m.Header.Get("Date"))
)
if campUUID == "" || subUUID == "" {
continue
}
if date.IsZero() {
date = time.Now()
}
// Additional bounce e-mail metadata.
meta, _ := json.Marshal(struct {
From string `json:"from"`
Subject string `json:"subject"`
MessageID string `json:"message_id"`
DeliveredTo string `json:"delivered_to"`
Received []string `json:"received"`
}{
From: m.Header.Get("From"),
Subject: m.Header.Get("Subject"),
MessageID: m.Header.Get("Message-Id"),
DeliveredTo: m.Header.Get("Delivered-To"),
Received: m.Header.Map()["Received"],
})
select {
case ch <- models.Bounce{
Type: "hard",
CampaignUUID: m.Header.Get(models.EmailHeaderCampaignUUID),
SubscriberUUID: m.Header.Get(models.EmailHeaderSubscriberUUID),
Source: p.opt.Host,
CreatedAt: date,
Meta: json.RawMessage(meta),
}:
default:
}
}
// Delete the downloaded messages.
for id := 1; id <= count; id++ {
if err := c.Dele(id); err != nil {
return err
}
}
return nil
}