forked from glycerine/sshego
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bounces.go
128 lines (113 loc) · 3.96 KB
/
bounces.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
120
121
122
123
124
125
126
127
128
package mailgun
import (
"strconv"
"time"
)
// Bounce aggregates data relating to undeliverable messages to a specific intended recipient,
// identified by Address.
// Code provides the SMTP error code causing the bounce,
// while Error provides a human readable reason why.
// CreatedAt provides the time at which Mailgun detected the bounce.
type Bounce struct {
CreatedAt string `json:"created_at"`
code interface{} `json:"code"`
Address string `json:"address"`
Error string `json:"error"`
}
type Paging struct {
First string `json:"first"`
Next string `json:"next"`
Previous string `json:"previous"`
Last string `json:"last"`
}
type bounceEnvelope struct {
Items []Bounce `json:"items"`
Paging Paging `json:"paging"`
}
// GetCreatedAt parses the textual, RFC-822 timestamp into a standard Go-compatible
// Time structure.
func (i Bounce) GetCreatedAt() (t time.Time, err error) {
return parseMailgunTime(i.CreatedAt)
}
// GetCode will return the bounce code for the message, regardless if it was
// returned as a string or as an integer. This method overcomes a protocol
// bug in the Mailgun API.
func (b Bounce) GetCode() (int, error) {
switch c := b.code.(type) {
case int:
return c, nil
case string:
return strconv.Atoi(c)
default:
return -1, strconv.ErrSyntax
}
}
// GetBounces returns a complete set of bounces logged against the sender's domain, if any.
// The results include the total number of bounces (regardless of skip or limit settings),
// and the slice of bounces specified, if successful.
// Note that the length of the slice may be smaller than the total number of bounces.
func (m *MailgunImpl) GetBounces(limit, skip int) (int, []Bounce, error) {
r := newHTTPRequest(generateApiUrl(m, bouncesEndpoint))
if limit != -1 {
r.addParameter("limit", strconv.Itoa(limit))
}
if skip != -1 {
r.addParameter("skip", strconv.Itoa(skip))
}
r.setClient(m.Client())
r.setBasicAuth(basicAuthUser, m.ApiKey())
var response bounceEnvelope
err := getResponseFromJSON(r, &response)
if err != nil {
return -1, nil, err
}
return len(response.Items), response.Items, nil
}
// GetSingleBounce retrieves a single bounce record, if any exist, for the given recipient address.
func (m *MailgunImpl) GetSingleBounce(address string) (Bounce, error) {
r := newHTTPRequest(generateApiUrl(m, bouncesEndpoint) + "/" + address)
r.setClient(m.Client())
r.setBasicAuth(basicAuthUser, m.ApiKey())
var response Bounce
err := getResponseFromJSON(r, &response)
return response, err
}
// AddBounce files a bounce report.
// Address identifies the intended recipient of the message that bounced.
// Code corresponds to the numeric response given by the e-mail server which rejected the message.
// Error providees the corresponding human readable reason for the problem.
// For example,
// here's how the these two fields relate.
// Suppose the SMTP server responds with an error, as below.
// Then, . . .
//
// 550 Requested action not taken: mailbox unavailable
// \___/\_______________________________________________/
// | |
// `-- Code `-- Error
//
// Note that both code and error exist as strings, even though
// code will report as a number.
func (m *MailgunImpl) AddBounce(address, code, error string) error {
r := newHTTPRequest(generateApiUrl(m, bouncesEndpoint))
r.setClient(m.Client())
r.setBasicAuth(basicAuthUser, m.ApiKey())
payload := newUrlEncodedPayload()
payload.addValue("address", address)
if code != "" {
payload.addValue("code", code)
}
if error != "" {
payload.addValue("error", error)
}
_, err := makePostRequest(r, payload)
return err
}
// DeleteBounce removes all bounces associted with the provided e-mail address.
func (m *MailgunImpl) DeleteBounce(address string) error {
r := newHTTPRequest(generateApiUrl(m, bouncesEndpoint) + "/" + address)
r.setClient(m.Client())
r.setBasicAuth(basicAuthUser, m.ApiKey())
_, err := makeDeleteRequest(r)
return err
}