forked from mrz1836/postmark
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpostmark.go
124 lines (107 loc) · 3.34 KB
/
postmark.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
// Package postmark encapsulates the Postmark API via Go
package postmark
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
)
const postmarkURL = `https://api.postmarkapp.com`
// Client provides a connection to the Postmark API
type Client struct {
// HTTPClient is &http.Client{} by default
HTTPClient *http.Client
// Server Token: Used for requests that require server level privileges. This token can be found on the Credentials tab under your Postmark server.
ServerToken string
// AccountToken: Used for requests that require account level privileges. This token is only accessible by the account owner, and can be found on the Account tab of your Postmark account.
AccountToken string
// BaseURL is the root API endpoint
BaseURL string
}
const (
accountToken = "account"
serverToken = "server"
)
// Options is an object to hold variable parameters to perform request.
type parameters struct {
// Method is HTTP method type.
Method string
// Path is postfix for URI.
Path string
// Payload for the request.
Payload interface{}
// TokenType defines which token to use
TokenType string
}
// NewClient builds a new Client pointer using the provided tokens, a default HTTPClient, and a default API base URL
// Accepts `Server Token`, and `Account Token` as arguments
// http://developer.postmarkapp.com/developer-api-overview.html#authentication
func NewClient(serverToken string, accountToken string) *Client {
return &Client{
HTTPClient: &http.Client{},
ServerToken: serverToken,
AccountToken: accountToken,
BaseURL: postmarkURL,
}
}
// doRequest performs the request to the Postmark API
func (client *Client) doRequest(ctx context.Context, opts parameters, dst interface{}) (err error) {
url := fmt.Sprintf("%s/%s", client.BaseURL, opts.Path)
var req *http.Request
if req, err = http.NewRequestWithContext(
ctx, opts.Method, url, nil,
); err != nil {
return
}
if opts.Payload != nil {
var payloadData []byte
if payloadData, err = json.Marshal(opts.Payload); err != nil {
return
}
req.Body = io.NopCloser(bytes.NewBuffer(payloadData))
req.GetBody = func() (io.ReadCloser, error) {
return io.NopCloser(bytes.NewBuffer(payloadData)), nil
}
}
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/json")
switch opts.TokenType {
case accountToken:
req.Header.Add("X-Postmark-Account-Token", client.AccountToken)
default:
req.Header.Add("X-Postmark-Server-Token", client.ServerToken)
}
var res *http.Response
if res, err = client.HTTPClient.Do(req); err != nil {
return
}
defer func() {
_ = res.Body.Close()
}()
var body []byte
if body, err = io.ReadAll(res.Body); err != nil {
return
}
if res.StatusCode >= http.StatusBadRequest {
// If the status code is not a success, attempt to unmarshall the body into the APIError struct.
var apiErr APIError
if err = json.Unmarshal(body, &apiErr); err != nil {
return
}
return apiErr
}
return json.Unmarshal(body, dst)
}
// APIError represents errors returned by Postmark
type APIError struct {
// ErrorCode: see error codes here (https://postmarkapp.com/developer/api/overview#error-codes)
ErrorCode int64 `json:"ErrorCode"`
// Message contains error details
Message string `json:"Message"`
}
// Error returns the error message details
func (res APIError) Error() string {
return res.Message
}