-
Notifications
You must be signed in to change notification settings - Fork 64
/
mandrill_messages.go
343 lines (301 loc) · 12.2 KB
/
mandrill_messages.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
// Copyright 2013 Matthew Baird
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gochimp
import (
"encoding/json"
"errors"
"strconv"
"time"
)
// see https://mandrillapp.com/api/docs/messages.html
const messages_send_endpoint string = "/messages/send.json" // Send a new transactional message through Mandrill
const messages_info_endpoint string = "/messages/info.json" // Get info about a message
const messages_send_template_endpoint string = "/messages/send-template.json" // Send a new transactional message through Mandrill using a template
const messages_search_endpoint string = "/messages/search.json" // Search the content of recently sent messages and optionally narrow by date range, tags and senders
const messages_parse_endpoint string = "/messages/parse.json" // Parse the full MIME document for an email message, returning the content of the message broken into its constituent pieces
const messages_send_raw_endpoint string = "/messages/send-raw.json" // Take a raw MIME document for a message, and send it exactly as if it were sent over the SMTP protocol
const messages_content_endpoint string = "/messages/content.json"
func (a *MandrillAPI) MessageContent(id string) (*MessageContent, error) {
var response MessageContent
var params map[string]interface{} = make(map[string]interface{})
params["id"] = id
err := parseMandrillJson(a, messages_content_endpoint, params, &response)
return &response, err
}
func (a *MandrillAPI) MessageInfo(id string) (map[string]interface{}, error) {
var response map[string]interface{}
var params map[string]interface{} = make(map[string]interface{})
params["id"] = id
err := parseMandrillJson(a, messages_info_endpoint, params, &response)
return response, err
}
// MessageSendWithOptions sends messages, allowing for a few configuration options
// todo: add ip_pool and key to MessageSendOptions
func (a *MandrillAPI) MessageSendWithOptions(message Message, opts MessageSendOptions) ([]SendResponse, error) {
var response []SendResponse
var params = make(map[string]interface{})
params["message"] = message
params["async"] = opts.Async
if opts.SendAt != nil {
params["send_at"] = opts.SendAt.UTC().Format("2006-01-02 15:04:05")
}
err := parseMandrillJson(a, messages_send_endpoint, params, &response)
return response, err
}
func (a *MandrillAPI) MessageSend(message Message, async bool) ([]SendResponse, error) {
return a.MessageSendWithOptions(message, MessageSendOptions{Async: async})
}
func (a *MandrillAPI) MessageSendTemplate(templateName string, templateContent []Var, message Message, async bool) ([]SendResponse, error) {
var response []SendResponse
if templateName == "" {
return response, errors.New("templateName cannot be blank")
}
var params map[string]interface{} = make(map[string]interface{})
params["message"] = message
params["template_name"] = templateName
params["async"] = async
params["template_content"] = templateContent
err := parseMandrillJson(a, messages_send_template_endpoint, params, &response)
return response, err
}
func (a *MandrillAPI) MessageSearch(searchRequest SearchRequest) ([]SearchResponse, error) {
var response []SearchResponse
var params map[string]interface{} = make(map[string]interface{})
//todo remove this hack
if searchRequest.Query != "" {
params["query"] = searchRequest.Query
}
if !searchRequest.DateFrom.IsZero() {
params["date_from"] = searchRequest.DateFrom
}
if !searchRequest.DateTo.IsZero() {
params["date_to"] = searchRequest.DateTo
}
if len(searchRequest.Tags) > 0 {
params["tags"] = searchRequest.Tags
}
if len(searchRequest.Senders) > 0 {
params["senders"] = searchRequest.Senders
}
params["limit"] = searchRequest.Limit
if len(searchRequest.APIKeys) > 0 {
params["api_keys"] = searchRequest.APIKeys
}
err := parseMandrillJson(a, messages_search_endpoint, params, &response)
return response, err
}
func (a *MandrillAPI) MessageParse(rawMessage string, async bool) (Message, error) {
var response Message
if rawMessage == "" {
return response, errors.New("rawMessage cannot be blank")
}
var params map[string]interface{} = make(map[string]interface{})
params["raw_message"] = rawMessage
err := parseMandrillJson(a, messages_parse_endpoint, params, &response)
return response, err
}
// Can return oneof Invalid_Key, ValidationError or GeneralError
func (a *MandrillAPI) MessageSendRaw(rawMessage string, to []string, from Recipient, async bool) ([]SendResponse, error) {
var response []SendResponse
if rawMessage == "" {
return response, errors.New("rawMessage cannot be blank")
}
if len(to) <= 0 {
return response, errors.New("You need at least one recipient in the To array")
}
var params map[string]interface{} = make(map[string]interface{})
params["raw_message"] = rawMessage
params["from_email"] = from.Email
params["from_name"] = from.Name
params["to"] = to
params["async"] = async
err := parseMandrillJson(a, messages_send_raw_endpoint, params, &response)
return response, err
}
type TS struct {
time.Time
}
func (t *TS) UnmarshalJSON(data []byte) error {
i, err := strconv.ParseInt(string(data), 10, 64)
if err != nil {
return err
}
*t = TS{time.Unix(i, 0)}
return nil
}
type SearchResponse struct {
Timestamp time.Duration `json:"ts"`
Id string `json:"_id"`
Sender string `json:"sender"`
Subject string `json:"subject"`
Email string `json:"email"`
Tags []string `json:"tags"`
Opens int `json:"opens"`
Clicks int `json:"clicks"`
State string `json:"state"`
Diag string `json:"diag"`
Metadata map[string]string `json:"metadata"`
Template interface{} `json:"template"`
Resends []Resend `json:"resends"`
SMTPEvents []SMTPEvent `json:"smtp_events"`
OpensDetail []ActivityDetail `json:"opens_detail"`
ClicksDetail []ActivityDetail `json:"clicks_detail"`
}
type Resend struct {
Timestamp time.Duration `json:"ts"`
}
type SMTPEvent struct {
Timestamp time.Duration `json:"ts"`
Type string `json:"type"`
Diagnostics string `json:"diag"`
SourceIP string `json:"source_ip"`
DestinationIP string `json:"destination_ip"`
Size int `json:"size"`
}
type ActivityDetail struct {
Timestamp time.Duration `json:"ts"`
IP string `json:"ip"`
Url string `json:"url"`
Location string `json:"location"`
UserAgent string `json:"ua"`
}
type SearchRequest struct {
Query string `json:"query"`
DateFrom APITime `json:"date_from"`
DateTo APITime `json:"date_to"`
Tags []string `json:"tags"`
Senders []string `json:"senders"`
APIKeys []string `json:"api_keys"`
Limit int `json:"limit"`
}
type MessageContent struct {
Timestamp TS `json:"ts"`
Id string `json:"_id"`
FromEmail string `json:"from_email"`
FromName string `json:"from_name"`
Subject string `json:"subject"`
To Recipient `json:"to"`
Text string `json:"text"`
Html string `json:"html"`
}
type Message struct {
Html string `json:"html,omitempty"`
Text string `json:"text,omitempty"`
Subject string `json:"subject"`
FromEmail string `json:"from_email"`
FromName string `json:"from_name"`
To []Recipient `json:"to"`
Headers map[string]string `json:"headers,omitempty"`
Important bool `json:"important,omitempty"`
TrackOpens bool `json:"track_opens"`
TrackClicks bool `json:"track_clicks"`
ViewContentLink bool `json:"view_content_link,omitempty"`
AutoText bool `json:"auto_text,omitempty"`
AutoHtml bool `json:"auto_html,omitempty"`
UrlStripQS bool `json:"url_strip_qs,omitempty"`
InlineCss bool `json:"inline_css,omitempty"`
PreserveRecipients bool `json:"preserve_recipients,omitempty"`
BCCAddress string `json:"bcc_address,omitempty"`
TrackingDomain string `json:"tracking_domain,omitempty"`
SigningDomain string `json:"signing_domain,omitempty"`
ReturnPathDomain string `json:"return_path_domain,omitempty"`
Merge bool `json:"merge,omitempty"`
GlobalMergeVars []Var `json:"global_merge_vars,omitempty"`
MergeVars []MergeVars `json:"merge_vars,omitempty"`
Tags []string `json:"tags,omitempty"`
Subaccount string `json:"subaccount,omitempty"`
GoogleAnalyticsDomains []string `json:"google_analytics_domains,omitempty"`
GoogleAnalyticsCampaign []string `json:"google_analytics_campaign,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
RecipientMetadata []RecipientMetaData `json:"recipient_metadata,omitempty"`
Attachments []Attachment `json:"attachments,omitempty"`
MergeLanguage string `json:"merge_language,omitempty"`
Images []Attachment `json:"images,omitempty"`
}
func (m *Message) String() string {
b, _ := json.Marshal(m)
return string(b)
}
func (m *Message) AddHeader(key, value string) {
if m.Headers == nil {
m.Headers = make(map[string]string)
}
m.Headers[key] = value
}
func (m *Message) AddRecipients(r ...Recipient) {
m.To = append(m.To, r...)
}
func (m *Message) AddGlobalMergeVar(globalvars ...Var) {
m.GlobalMergeVars = append(m.GlobalMergeVars, globalvars...)
}
func (m *Message) AddMergeVar(vars ...MergeVars) {
m.MergeVars = append(m.MergeVars, vars...)
}
func (m *Message) AddTag(tags ...string) {
m.Tags = append(m.Tags, tags...)
}
func (m *Message) AddGoogleAnalyticsDomains(domains ...string) {
m.GoogleAnalyticsDomains = append(m.GoogleAnalyticsDomains, domains...)
}
func (m *Message) AddGoogleAnalyticsCampaign(campaigns ...string) {
m.GoogleAnalyticsCampaign = append(m.GoogleAnalyticsCampaign, campaigns...)
}
func (m *Message) AddMetadata(key, value string) {
if m.Metadata == nil {
m.Metadata = make(map[string]string)
}
m.Metadata[key] = value
}
func (m *Message) AddRecipientMetadata(metadata ...RecipientMetaData) {
m.RecipientMetadata = append(m.RecipientMetadata, metadata...)
}
func (m *Message) AddAttachments(attachement ...Attachment) {
m.Attachments = append(m.Attachments, attachement...)
}
func (m *Message) AddImages(image ...Attachment) {
m.Images = append(m.Images, image...)
}
type Attachment struct {
Type string `json:"type"`
Name string `json:"name"`
Content string `json:"content"`
}
type RecipientMetaData struct {
Recipient string `json:"rcpt"`
Vars map[string]string `json:"values"`
}
type MergeVars struct {
Recipient string `json:"rcpt"`
Vars []Var `json:"vars"`
}
type Var struct {
Name string `json:"name"`
Content interface{} `json:"content"`
}
func NewVar(name string, content interface{}) *Var {
return &Var{Name: name, Content: content}
}
type Recipient struct {
Email string `json:"email"`
Name string `json:"name"`
Type string `json:"type"`
}
// MessageSendOptions wraps options for MessageSend API call
type MessageSendOptions struct {
Async bool
SendAt *time.Time
}
type SendResponse struct {
Email string `json:"email"`
Status string `json:"status"`
Id string `json:"_id"`
RejectedReason string `json:"reject_reason"`
}