Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add suppression list and delete support #31

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions suppressions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package postmark

import (
"fmt"
"net/url"
)

// SuppressionReasonType - The reason type of suppression
type SuppressionReasonType string

// OriginType - The reason type of origin
type OriginType string

const (
HardBounceReason SuppressionReasonType = "HardBounce"
SpamComplaintReason SuppressionReasonType = "SpamComplaint"
ManualSuppressionReason SuppressionReasonType = "ManualSuppression"
RecipientOrigin OriginType = "Recipient"
CustomerOrigin OriginType = "Customer"
AdminOrigin OriginType = "Admin"
)

// SuppressionEmail - Suppression email entry
type SuppressionEmail struct {
// EmailAddress - The email address of suppression.
EmailAddress string
// SuppressionReason - The reason of suppression.
SuppressionReason SuppressionReasonType
// Origin - Possible options: Recipient, Customer, Admin.
Origin OriginType
// CreatedAt - Timestamp.
CreatedAt string
}

// suppressionsResponse - A message received from the Postmark server
type suppressionsResponse struct {
// Suppressions - The slice of suppression email address.
Suppressions []SuppressionEmail
}

// EmailAddress - Email address to delete
type EmailAddress struct {
EmailAddress string `json:",omitempty"`
}

// DeleteSuppressions - A payload of email address to delete
type DeleteSuppressions struct {
// Suppressions - The slice of email address to delete.
Suppressions []EmailAddress `json:",omitempty"`
}

// deleteSuppressionsResponse - A message received from the Postmark server
type deleteSuppressionsResponse struct {
// Suppressions - The slice of deleted email status and reason.
Suppressions []SuppressionDelete
}

// SuppressionDelete - Suppression email deleted
type SuppressionDelete struct {
EmailAddress string
Status string
Message *string
}

// GetSuppressionEmails fetches a email addresses in the list of suppression dump on the server
// It returns a SuppressionEmails slice, and any error that occurred
// https://postmarkapp.com/developer/api/suppressions-api#suppression-dump
func (client *Client) GetSuppressionEmails(streamID string, options map[string]interface{}) ([]SuppressionEmail, 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(parameters{
Method: "GET",
Path: path,
TokenType: server_token,
}, &res)
return res.Suppressions, err
}

// DeleteSuppressionEmails delete email addresses in the list of suppression dump on the server
// Noet: SpamComplaint and ManualSuppression with Origin: Customer cannot be deleted
// It return a SuppressionDelete slice, and any error that occurred
// https://postmarkapp.com/developer/api/suppressions-api#delete-a-suppression
func (client *Client) DeleteSuppressionEmails(streamID string, delete []string) ([]SuppressionDelete, error) {
emailAddresses := make([]EmailAddress, 0, 8)
for _, address := range delete {
emailAddresses = append(emailAddresses, EmailAddress{
EmailAddress: address,
})
}

res := deleteSuppressionsResponse{}
err := client.doRequest(parameters{
Method: "POST",
Path: fmt.Sprintf("message-streams/%s/suppressions/delete", streamID),
Payload: DeleteSuppressions{
Suppressions: emailAddresses,
},
TokenType: server_token,
}, &res)
return res.Suppressions, err
}
119 changes: 119 additions & 0 deletions suppressions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package postmark

import (
"net/http"
"testing"

"goji.io/pat"
)

func TestGetSuppressionEmails(t *testing.T) {
responseJSON := `{
"Suppressions":[
{
"EmailAddress":"[email protected]",
"SuppressionReason":"ManualSuppression",
"Origin": "Recipient",
"CreatedAt":"2019-12-10T08:58:33-05:00"
},
{
"EmailAddress":"[email protected]",
"SuppressionReason":"HardBounce",
"Origin": "Recipient",
"CreatedAt":"2019-12-11T08:58:33-05:00"
},
{
"EmailAddress":"[email protected]",
"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.GetSuppressionEmails("outbound", nil)

if err != nil {
t.Fatalf("GetSuppressionEmails: %s", err.Error())
}

if len(res) != 3 {
t.Fatalf("GetSuppressionEmails: wrong number of suppression (%d)", len(res))
}

if res[0].EmailAddress != "[email protected]" {
t.Fatalf("GetSuppressionEmails: wrong suppression email address: %s", res[0].EmailAddress)
}

responseJSON = `{
"Suppressions":[
{
"EmailAddress":"[email protected]",
"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.GetSuppressionEmails("outbound", map[string]interface{}{
"emailaddress": "[email protected]",
"fromdate": "2019-12-10",
"todate": "2019-12-11",
"suppressionreason": HardBounceReason,
"origin": RecipientOrigin,
})

if len(res) != 1 {
t.Fatalf("GetSuppressionEmails: wrong number of suppression (%d)", len(res))
}

if res[0].EmailAddress != "[email protected]" {
t.Fatalf("GetSuppressionEmails: wrong suppression email address: %s", res[0].EmailAddress)
}

}

func TestDeleteSuppressionEmails(t *testing.T) {
responseJSON := `{
"Suppressions":[
{
"EmailAddress":"[email protected]",
"Status":"Deleted",
"Message": null
},
{
"EmailAddress":"[email protected]",
"Status":"Deleted",
"Message": null
},
{
"EmailAddress":"[email protected]",
"Status":"Failed",
"Message": "You do not have the required authority to change this suppression."
}
]
}`

tMux.HandleFunc(pat.Post("/message-streams/:StreamID/suppressions/delete"), func(w http.ResponseWriter, req *http.Request) {
w.Write([]byte(responseJSON))
})

res, err := client.DeleteSuppressionEmails("outbound", []string{"[email protected]", "[email protected]", "[email protected]"})

if err != nil {
t.Fatalf("DeleteSuppressionEmails: %s", err.Error())
}

if len(res) != 3 {
t.Fatalf("DeleteSuppressionEmails: wrong number of suppression (%d)", len(res))
}
}