Skip to content
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":"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.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 != "address@wildbit.com" {
t.Fatalf("GetSuppressionEmails: 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.GetSuppressionEmails("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("GetSuppressionEmails: wrong number of suppression (%d)", len(res))
}

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

}

func TestDeleteSuppressionEmails(t *testing.T) {
responseJSON := `{
"Suppressions":[
{
"EmailAddress":"good.address@wildbit.com",
"Status":"Deleted",
"Message": null
},
{
"EmailAddress":"not.suppressed@wildbit.com",
"Status":"Deleted",
"Message": null
},
{
"EmailAddress":"spammy.address@wildbit.com",
"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{"good.address@wildbit.com", "not.suppressed@wildbit.com", "spammy.address@wildbit.com"})

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

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