From c598f287da63520cb95a7f89a722d405a2a157a8 Mon Sep 17 00:00:00 2001 From: Paul Fawkesley Date: Wed, 1 Mar 2023 14:33:56 +0000 Subject: [PATCH] add client.GetSuppressions See https://postmarkapp.com/developer/api/suppressions-api Credit to Bochao Wang (@plutowang) for their original pull request: https://github.com/keighl/postmark/pull/31 --- suppressions.go | 89 ++++++++++++++++++++++++++++++++++++++++++++ suppressions_test.go | 84 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 suppressions.go create mode 100644 suppressions_test.go diff --git a/suppressions.go b/suppressions.go new file mode 100644 index 0000000..fc8656b --- /dev/null +++ b/suppressions.go @@ -0,0 +1,89 @@ +package postmark + +import ( + "context" + "fmt" + "net/url" + "time" +) + +// SuppressionReasonType - The reason type of suppression +type SuppressionReasonType string + +// OriginType - The reason type of origin +type OriginType string + +const ( + // HardBounceReason means an email sent to the address returned a hard bounce. + HardBounceReason SuppressionReasonType = "HardBounce" + + // SpamComplaintReason means the recipient marked an email as spam. + SpamComplaintReason SuppressionReasonType = "SpamComplaint" + + // ManualSuppressionReason means the recipient followed an unsubscribe link. + ManualSuppressionReason SuppressionReasonType = "ManualSuppression" + + // RecipientOrigin means the email was added to the suppression list + // as a result of the recipient's own action, e.g. by following an unsubscribe link. + RecipientOrigin OriginType = "Recipient" + + // CustomerOrigin means the email was added to the suppression list as + // the result of action by the Postmark account holder (e.g. Postmark's + // customer). + CustomerOrigin OriginType = "Customer" + + // AdminOrigin means the email was added to the suppression list as + // the result of action by Postmark staff. + AdminOrigin OriginType = "Admin" +) + +// Suppression contains a suppressed email address for a particular message stream. +type Suppression struct { + // EmailAddress is the address that is suppressed (can't be emailed any more) + EmailAddress string + + // SuppressionReason is why the email address was added to the suppression list. + // Possible options: HardBounce, SpamComplaint, ManualSuppression + SuppressionReason SuppressionReasonType + + // Origin describes who added the email address to the suppression list. + // Possible options: Recipient, Customer, Admin. + Origin OriginType + + // CreatedAt is when the email address was added to the suppression list. + CreatedAt time.Time +} + +// suppressionsResponse - A message received from the Postmark server +type suppressionsResponse struct { + // Suppressions - The slice of suppression email address. + Suppressions []Suppression +} + +// GetSuppressions fetches email addresses in the list of suppression dump on the server +// It returns a Suppressions slice, and any error that occurred +// https://postmarkapp.com/developer/api/suppressions-api#suppression-dump +func (client *Client) GetSuppressions( + ctx context.Context, + streamID string, + options map[string]interface{}, +) ([]Suppression, error) { + + values := &url.Values{} + for k, v := range options { + values.Add(k, fmt.Sprintf("%v", v)) + } + + path := fmt.Sprintf("message-streams/%s/suppressions/dump", streamID) + if len(options) != 0 { + path = fmt.Sprintf("%s?%s", path, values.Encode()) + } + + res := suppressionsResponse{} + err := client.doRequest(ctx, parameters{ + Method: "GET", + Path: path, + TokenType: serverToken, + }, &res) + return res.Suppressions, err +} diff --git a/suppressions_test.go b/suppressions_test.go new file mode 100644 index 0000000..eabe99f --- /dev/null +++ b/suppressions_test.go @@ -0,0 +1,84 @@ +package postmark + +import ( + "context" + "net/http" + "testing" + + "goji.io/pat" +) + +func TestGetSuppressions(t *testing.T) { + responseJSON := `{ + "Suppressions":[ + { + "EmailAddress":"address@wildbit.com", + "SuppressionReason":"ManualSuppression", + "Origin": "Recipient", + "CreatedAt":"2019-12-10T08:58:33-05:00" + }, + { + "EmailAddress":"bounce.address@wildbit.com", + "SuppressionReason":"HardBounce", + "Origin": "Recipient", + "CreatedAt":"2019-12-11T08:58:33-05:00" + }, + { + "EmailAddress":"spam.complaint.address@wildbit.com", + "SuppressionReason":"SpamComplaint", + "Origin": "Recipient", + "CreatedAt":"2019-12-12T08:58:33-05:00" + } + ] + }` + + tMux.HandleFunc(pat.Get("/message-streams/:StreamID/suppressions/dump"), func(w http.ResponseWriter, req *http.Request) { + w.Write([]byte(responseJSON)) + }) + + res, err := client.GetSuppressions(context.Background(), "outbound", nil) + + if err != nil { + t.Fatalf("GetSuppressions: %s", err.Error()) + } + + if len(res) != 3 { + t.Fatalf("GetSuppressions: wrong number of suppression (%d)", len(res)) + } + + if res[0].EmailAddress != "address@wildbit.com" { + t.Fatalf("GetSuppressions: wrong suppression email address: %s", res[0].EmailAddress) + } + + responseJSON = `{ + "Suppressions":[ + { + "EmailAddress":"address@wildbit.com", + "SuppressionReason":"ManualSuppression", + "Origin": "Recipient", + "CreatedAt":"2019-12-10T08:58:33-05:00" + } + ] + }` + + tMux.HandleFunc(pat.Get("/message-streams/:StreamID/suppressions/dump"), func(w http.ResponseWriter, req *http.Request) { + w.Write([]byte(responseJSON)) + }) + + res, err = client.GetSuppressions(context.Background(), "outbound", map[string]interface{}{ + "emailaddress": "address@wildbit.com", + "fromdate": "2019-12-10", + "todate": "2019-12-11", + "suppressionreason": HardBounceReason, + "origin": RecipientOrigin, + }) + + if len(res) != 1 { + t.Fatalf("GetSuppressions: wrong number of suppression (%d)", len(res)) + } + + if res[0].EmailAddress != "address@wildbit.com" { + t.Fatalf("GetSuppressions: wrong suppression email address: %s", res[0].EmailAddress) + } + +}