Documentation
¶
Overview ¶
Package sendclipper is the official Go client for the SendClipper email API.
client := sendclipper.NewClient("sc_live_...") // or NewClient(""): reads SENDCLIPPER_API_KEY
email, err := client.Emails.Send(ctx, &sendclipper.SendEmailParams{
From: "hello@send.acme.io",
To: "ada@lumen.io",
Subject: "Your receipt",
HTML: "<p>Thanks for your order.</p>",
})
var apiErr *sendclipper.Error
if errors.As(err, &apiErr) {
log.Println(apiErr.Name, apiErr.Message) // e.g. domain_not_verified
}
Every method takes a context and returns the decoded response or an error. A refusal from the API or a failed connection is always a *Error whose Name is SendClipper's machine-readable code ("validation_failed", "rate_limited", "network_error", ...).
Network errors, 429 and 5xx answers are retried with backoff, honouring Retry-After. Every JSON write carries an Idempotency-Key, and the API answers a repeated key with the first result for 24 hours, so a retried send never goes out twice.
Verify webhook deliveries with VerifyWebhook.
Example ¶
package main
import (
"context"
"errors"
"fmt"
"log"
"github.com/sendclipper/sendclipper-go"
)
func main() {
client := sendclipper.NewClient("sc_live_xxxxxxxxxxxxxxxx")
email, err := client.Emails.Send(context.Background(), &sendclipper.SendEmailParams{
From: "hello@send.acme.io",
To: "ada@lumen.io",
Subject: "Your receipt",
HTML: "<p>Thanks for your order.</p>",
Text: "Thanks for your order.",
})
var apiErr *sendclipper.Error
if errors.As(err, &apiErr) {
log.Println(apiErr.Name, apiErr.Message) // e.g. domain_not_verified
return
}
fmt.Println("Email", email.ID, "accepted")
}
Output:
Index ¶
- Constants
- func Bool(b bool) *bool
- func ParseSignatureHeader(header string) (timestamp int64, signatures []string, ok bool)
- func SignPayload(secret string, timestamp int64, rawBody []byte) string
- func WebhookSignatureHeader(secret string, rawBody []byte, timestamp int64) string
- type APIKey
- type APIKeysService
- type Audience
- type AudienceList
- type AudiencesService
- type AutomationsService
- type BatchItemError
- type BatchResult
- type BatchService
- type Client
- type ClientOption
- type Contact
- type ContactList
- type ContactsService
- func (s *ContactsService) All(ctx context.Context, params *ListContactsParams, opts ...RequestOption) iter.Seq2[Contact, error]
- func (s *ContactsService) Create(ctx context.Context, params *CreateContactParams, opts ...RequestOption) (*Contact, error)
- func (s *ContactsService) Export(ctx context.Context, params *ExportContactsParams, opts ...RequestOption) (string, error)
- func (s *ContactsService) Import(ctx context.Context, params *ImportContactsParams, opts ...RequestOption) (map[string]any, error)
- func (s *ContactsService) ImportPreview(ctx context.Context, params *ImportContactsParams, opts ...RequestOption) (map[string]any, error)
- func (s *ContactsService) List(ctx context.Context, params *ListContactsParams, opts ...RequestOption) (*ContactList, error)
- type CreateContactParams
- type CreateDomainParams
- type CreateMailboxParams
- type CreateSuppressionParams
- type CreateTemplateParams
- type CreateWebhookParams
- type CursorInfo
- type DNSRecord
- type Domain
- type DomainRecords
- type DomainsService
- func (s *DomainsService) Create(ctx context.Context, params *CreateDomainParams, opts ...RequestOption) (*Domain, error)
- func (s *DomainsService) DeletionPreview(ctx context.Context, id string, opts ...RequestOption) (map[string]any, error)
- func (s *DomainsService) DisableReceiving(ctx context.Context, id string, opts ...RequestOption) (*Domain, error)
- func (s *DomainsService) EnableReceiving(ctx context.Context, id string, opts ...RequestOption) (*Domain, error)
- func (s *DomainsService) List(ctx context.Context, opts ...RequestOption) ([]Domain, error)
- func (s *DomainsService) Records(ctx context.Context, id string, opts ...RequestOption) (*DomainRecords, error)
- func (s *DomainsService) Remove(ctx context.Context, id string, opts ...RequestOption) error
- func (s *DomainsService) SetRegion(ctx context.Context, id string, region Region, opts ...RequestOption) (*Domain, error)
- func (s *DomainsService) Verify(ctx context.Context, id string, opts ...RequestOption) (*Domain, error)
- type DownloadedFile
- type EmailDetail
- type EmailEvent
- type EmailList
- type EmailRow
- type EmailStats
- type EmailStatus
- type EmailsService
- func (s *EmailsService) All(ctx context.Context, params *ListEmailsParams, opts ...RequestOption) iter.Seq2[EmailRow, error]
- func (s *EmailsService) Get(ctx context.Context, id string, opts ...RequestOption) (*EmailDetail, error)
- func (s *EmailsService) List(ctx context.Context, params *ListEmailsParams, opts ...RequestOption) (*EmailList, error)
- func (s *EmailsService) Send(ctx context.Context, params *SendEmailParams, opts ...RequestOption) (*SentEmail, error)
- func (s *EmailsService) SendBatch(ctx context.Context, emails []SendEmailParams, opts ...RequestOption) (*SendBatchResponse, error)
- func (s *EmailsService) Stats(ctx context.Context, opts ...RequestOption) (*EmailStats, error)
- type Error
- type ExportContactsParams
- type ImportContactsParams
- type ListContactsParams
- type ListEmailsParams
- type ListMailboxMessagesParams
- type ListSandboxMessagesParams
- type ListSuppressionsParams
- type ListTemplatesParams
- type ListWebhookDeliveriesParams
- type ListWebhookDispatchesParams
- type Mailbox
- type MailboxMessage
- type MailboxMessageList
- type MailboxMessageRow
- type MailboxMessagesService
- func (s *MailboxMessagesService) All(ctx context.Context, mailboxID string, params *ListMailboxMessagesParams, ...) iter.Seq2[MailboxMessageRow, error]
- func (s *MailboxMessagesService) Attachment(ctx context.Context, mailboxID, messageID, attachmentID string, ...) (*DownloadedFile, error)
- func (s *MailboxMessagesService) Get(ctx context.Context, mailboxID, messageID string, opts ...RequestOption) (*MailboxMessage, error)
- func (s *MailboxMessagesService) List(ctx context.Context, mailboxID string, params *ListMailboxMessagesParams, ...) (*MailboxMessageList, error)
- type MailboxesService
- func (s *MailboxesService) Archive(ctx context.Context, id string, opts ...RequestOption) (*Mailbox, error)
- func (s *MailboxesService) Create(ctx context.Context, params *CreateMailboxParams, opts ...RequestOption) (*Mailbox, error)
- func (s *MailboxesService) Get(ctx context.Context, id string, opts ...RequestOption) (*Mailbox, error)
- func (s *MailboxesService) List(ctx context.Context, includeArchived bool, opts ...RequestOption) ([]Mailbox, error)
- func (s *MailboxesService) Update(ctx context.Context, id string, params *UpdateMailboxParams, ...) (*Mailbox, error)
- type NamedRef
- type Region
- type ReplayAllParams
- type ReplayAllResult
- type RequestOption
- type ResetSandboxCredentials
- type Sandbox
- type SandboxCredentials
- type SandboxMessage
- type SandboxMessageSummary
- type SandboxMessagesService
- func (s *SandboxMessagesService) Clear(ctx context.Context, sandboxID string, opts ...RequestOption) (int, error)
- func (s *SandboxMessagesService) Get(ctx context.Context, sandboxID, messageID string, opts ...RequestOption) (*SandboxMessage, error)
- func (s *SandboxMessagesService) List(ctx context.Context, sandboxID string, params *ListSandboxMessagesParams, ...) ([]SandboxMessageSummary, error)
- func (s *SandboxMessagesService) MarkAllRead(ctx context.Context, sandboxID string, opts ...RequestOption) (int, error)
- func (s *SandboxMessagesService) Raw(ctx context.Context, sandboxID, messageID string, opts ...RequestOption) (string, error)
- func (s *SandboxMessagesService) Remove(ctx context.Context, sandboxID, messageID string, opts ...RequestOption) error
- func (s *SandboxMessagesService) WaitFor(ctx context.Context, sandboxID string, opts *WaitForOptions) (*SandboxMessage, error)
- type SandboxParams
- type SandboxSendResult
- type SandboxesService
- func (s *SandboxesService) Create(ctx context.Context, params *SandboxParams, opts ...RequestOption) (*Sandbox, error)
- func (s *SandboxesService) Credentials(ctx context.Context, id string, opts ...RequestOption) (*SandboxCredentials, error)
- func (s *SandboxesService) Get(ctx context.Context, id string, opts ...RequestOption) (*Sandbox, error)
- func (s *SandboxesService) List(ctx context.Context, opts ...RequestOption) ([]Sandbox, error)
- func (s *SandboxesService) Remove(ctx context.Context, id string, opts ...RequestOption) (int, error)
- func (s *SandboxesService) ResetCredentials(ctx context.Context, id string, opts ...RequestOption) (*ResetSandboxCredentials, error)
- func (s *SandboxesService) Send(ctx context.Context, sandboxToken string, params *SendEmailParams, ...) (*SandboxSendResult, error)
- func (s *SandboxesService) Update(ctx context.Context, id string, params *SandboxParams, opts ...RequestOption) (*Sandbox, error)
- type SendBatchResponse
- type SendClass
- type SendEmailParams
- type SentEmail
- type Suppression
- type SuppressionCreated
- type SuppressionList
- type SuppressionsService
- func (s *SuppressionsService) All(ctx context.Context, params *ListSuppressionsParams, opts ...RequestOption) iter.Seq2[Suppression, error]
- func (s *SuppressionsService) Create(ctx context.Context, params *CreateSuppressionParams, opts ...RequestOption) (*SuppressionCreated, error)
- func (s *SuppressionsService) Export(ctx context.Context, params *ListSuppressionsParams, opts ...RequestOption) (string, error)
- func (s *SuppressionsService) List(ctx context.Context, params *ListSuppressionsParams, opts ...RequestOption) (*SuppressionList, error)
- func (s *SuppressionsService) Remove(ctx context.Context, id, reason string, opts ...RequestOption) error
- type Template
- type TemplateAsset
- type TemplateAssetsService
- type TemplateBlock
- type TemplatePreview
- type TemplateSummary
- type TemplateTag
- type TemplateTagsService
- func (s *TemplateTagsService) Create(ctx context.Context, name, color string, opts ...RequestOption) (*TemplateTag, error)
- func (s *TemplateTagsService) List(ctx context.Context, opts ...RequestOption) ([]TemplateTag, error)
- func (s *TemplateTagsService) Remove(ctx context.Context, id string, opts ...RequestOption) (int, error)
- func (s *TemplateTagsService) Update(ctx context.Context, id, name, color string, opts ...RequestOption) (*TemplateTag, error)
- type TemplatesService
- func (s *TemplatesService) Create(ctx context.Context, params *CreateTemplateParams, opts ...RequestOption) (*Template, error)
- func (s *TemplatesService) Duplicate(ctx context.Context, id string, opts ...RequestOption) (*Template, error)
- func (s *TemplatesService) Get(ctx context.Context, id string, opts ...RequestOption) (*Template, error)
- func (s *TemplatesService) HTML(ctx context.Context, id string, opts ...RequestOption) (string, error)
- func (s *TemplatesService) List(ctx context.Context, params *ListTemplatesParams, opts ...RequestOption) ([]TemplateSummary, error)
- func (s *TemplatesService) Preview(ctx context.Context, id string, variables map[string]any, ...) (*TemplatePreview, error)
- func (s *TemplatesService) Projects(ctx context.Context, opts ...RequestOption) ([]NamedRef, error)
- func (s *TemplatesService) Publish(ctx context.Context, id string, opts ...RequestOption) (*Template, error)
- func (s *TemplatesService) Remove(ctx context.Context, id string, opts ...RequestOption) error
- func (s *TemplatesService) SetTags(ctx context.Context, id string, tagIDs []string, opts ...RequestOption) ([]TemplateTag, error)
- func (s *TemplatesService) Unpublish(ctx context.Context, id string, opts ...RequestOption) (*Template, error)
- func (s *TemplatesService) Update(ctx context.Context, id string, params *UpdateTemplateParams, ...) (*Template, error)
- type UpdateMailboxParams
- type UpdateTemplateParams
- type UpdateWebhookParams
- type UploadTemplateAssetParams
- type VerifyOption
- type WaitForOptions
- type WebhookDispatch
- type WebhookDispatchPage
- type WebhookDispatchesService
- func (s *WebhookDispatchesService) All(ctx context.Context, params *ListWebhookDispatchesParams, ...) iter.Seq2[WebhookDispatch, error]
- func (s *WebhookDispatchesService) Get(ctx context.Context, id string, opts ...RequestOption) (*WebhookDispatch, error)
- func (s *WebhookDispatchesService) List(ctx context.Context, params *ListWebhookDispatchesParams, ...) (*WebhookDispatchPage, error)
- func (s *WebhookDispatchesService) Replay(ctx context.Context, id string, opts ...RequestOption) (*WebhookDispatch, error)
- func (s *WebhookDispatchesService) ReplayAll(ctx context.Context, params *ReplayAllParams, opts ...RequestOption) (*ReplayAllResult, error)
- type WebhookEndpoint
- type WebhookEndpointWithSecret
- type WebhookEvent
- type WebhookEventData
- type WebhookEventType
- type WebhookVerificationError
- type WebhooksService
- func (s *WebhooksService) Create(ctx context.Context, params *CreateWebhookParams, opts ...RequestOption) (*WebhookEndpointWithSecret, error)
- func (s *WebhooksService) Deliveries(ctx context.Context, params *ListWebhookDeliveriesParams, ...) ([]map[string]any, error)
- func (s *WebhooksService) List(ctx context.Context, opts ...RequestOption) ([]WebhookEndpoint, error)
- func (s *WebhooksService) Remove(ctx context.Context, id string, opts ...RequestOption) error
- func (s *WebhooksService) RotateSecret(ctx context.Context, id string, opts ...RequestOption) (*WebhookEndpointWithSecret, error)
- func (s *WebhooksService) Update(ctx context.Context, id string, params *UpdateWebhookParams, ...) (*WebhookEndpoint, error)
- func (s *WebhooksService) Verify(payload []byte, headers http.Header, secret string, opts ...VerifyOption) (*WebhookEvent, error)
- type Workspace
- type WorkspaceService
Examples ¶
Constants ¶
const DefaultBaseURL = "https://sendclipper.com"
DefaultBaseURL is where requests go unless WithBaseURL or SENDCLIPPER_BASE_URL says otherwise.
const SignatureHeader = "X-SendClipper-Signature-V2"
SignatureHeader is the header SendClipper signs deliveries in.
const Version = "0.1.1"
Version is this SDK's release. CI keeps it equal to the release tag.
const WebhookTolerance = 5 * time.Minute
WebhookTolerance is SendClipper's documented tolerance: five minutes.
Variables ¶
This section is empty.
Functions ¶
func Bool ¶
Bool returns a pointer to b, for the optional booleans in params (TrackOpens: sendclipper.Bool(false)).
func ParseSignatureHeader ¶
ParseSignatureHeader reads t=<seconds>,v1=<hex>[,v1=<hex>]. ok is false when there is no valid t=.
func SignPayload ¶
SignPayload is hex(HMAC-SHA256(secret, "{timestamp}.{rawBody}")). Exported for tests of your own handler.
Types ¶
type APIKey ¶
type APIKey struct {
ID string `json:"id"`
Name string `json:"name"`
Masked string `json:"masked"`
Prefix string `json:"prefix"`
Last4 string `json:"last4"`
Permission string `json:"permission"` // full, sending or read
DomainID *string `json:"domainId"`
Domain *string `json:"domain"`
CreatedAt time.Time `json:"createdAt"`
LastUsedAt *time.Time `json:"lastUsedAt"`
}
APIKey is one of the workspace's keys, masked.
type APIKeysService ¶
type APIKeysService struct {
// contains filtered or unexported fields
}
APIKeysService lists API keys. Keys are created and revoked in the dashboard only.
func (*APIKeysService) List ¶
func (s *APIKeysService) List(ctx context.Context, opts ...RequestOption) ([]APIKey, error)
List returns the workspace's keys, masked.
type Audience ¶
type Audience struct {
ID string `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
Count int `json:"count"`
}
Audience is a list of contacts.
type AudienceList ¶
type AudienceList struct {
Audiences []Audience `json:"audiences"`
TotalContacts int `json:"totalContacts"`
}
AudienceList is every audience.
type AudiencesService ¶
type AudiencesService struct {
// contains filtered or unexported fields
}
AudiencesService lists audiences.
func (*AudiencesService) List ¶
func (s *AudiencesService) List(ctx context.Context, opts ...RequestOption) (*AudienceList, error)
List returns every audience and the total contact count.
type AutomationsService ¶
type AutomationsService struct {
// contains filtered or unexported fields
}
AutomationsService starts automations.
func (*AutomationsService) Enroll ¶
func (s *AutomationsService) Enroll(ctx context.Context, automationID, email string, opts ...RequestOption) (map[string]any, error)
Enroll starts a Live automation with a manual trigger for one contact.
type BatchItemError ¶
type BatchItemError struct {
Code string `json:"code"`
Message string `json:"message"`
Detail json.RawMessage `json:"detail,omitempty"`
}
BatchItemError is why one batch item was refused.
type BatchResult ¶
type BatchResult struct {
Index int `json:"index"`
Status string `json:"status"`
ID string `json:"id,omitempty"`
MessageID string `json:"messageId,omitempty"`
Error *BatchItemError `json:"error,omitempty"`
}
BatchResult is one submitted item's outcome. Status is "accepted" (ID and MessageID set) or "failed" (Error set).
type BatchService ¶
type BatchService struct {
// contains filtered or unexported fields
}
BatchService sends up to 500 messages in one request.
func (*BatchService) Send ¶
func (s *BatchService) Send(ctx context.Context, emails []SendEmailParams, opts ...RequestOption) (*SendBatchResponse, error)
Send sends up to 500 messages (one recipient each). Every item is accepted or refused on its own; a refused item costs its siblings nothing.
type Client ¶
type Client struct {
Emails *EmailsService
Batch *BatchService
Domains *DomainsService
Templates *TemplatesService
Sandboxes *SandboxesService
Webhooks *WebhooksService
Contacts *ContactsService
Audiences *AudiencesService
Suppressions *SuppressionsService
Mailboxes *MailboxesService
Automations *AutomationsService
Workspace *WorkspaceService
APIKeys *APIKeysService
// contains filtered or unexported fields
}
Client talks to the SendClipper API. Make one with NewClient and share it: it is safe for concurrent use.
func NewClient ¶
func NewClient(apiKey string, opts ...ClientOption) *Client
NewClient makes a client. An empty apiKey reads SENDCLIPPER_API_KEY.
type ClientOption ¶
type ClientOption func(*Client)
ClientOption configures a Client.
func WithBaseURL ¶
func WithBaseURL(url string) ClientOption
WithBaseURL points the client at another API origin (no /v1). The default is SENDCLIPPER_BASE_URL, then https://sendclipper.com.
func WithDefaultHeader ¶
func WithDefaultHeader(name, value string) ClientOption
WithDefaultHeader adds a header to every request.
func WithHTTPClient ¶
func WithHTTPClient(hc *http.Client) ClientOption
WithHTTPClient sends requests through your own *http.Client (a proxy, a custom transport). Its Timeout, if any, applies on top of the per-attempt one.
func WithMaxRetries ¶
func WithMaxRetries(n int) ClientOption
WithMaxRetries sets how often a network error, 429 or 5xx is retried. Default 2.
func WithTimeout ¶
func WithTimeout(d time.Duration) ClientOption
WithTimeout sets the per-attempt timeout. Default 30 seconds.
type Contact ¶
type Contact struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Status string `json:"status"` // subscribed, unsubscribed or bounced
AudienceID *string `json:"audienceId"`
AudienceName *string `json:"audienceName"`
AudienceColor *string `json:"audienceColor"`
CreatedAt time.Time `json:"createdAt"`
}
Contact is one person in an audience.
type ContactList ¶
type ContactList struct {
Items []Contact `json:"items"`
Total int `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
TotalPages int `json:"totalPages"`
TotalAll int `json:"totalAll"`
}
ContactList is one numbered page of contacts.
type ContactsService ¶
type ContactsService struct {
// contains filtered or unexported fields
}
ContactsService manages contacts.
func (*ContactsService) All ¶
func (s *ContactsService) All(ctx context.Context, params *ListContactsParams, opts ...RequestOption) iter.Seq2[Contact, error]
All walks every contact, page after page.
func (*ContactsService) Create ¶
func (s *ContactsService) Create(ctx context.Context, params *CreateContactParams, opts ...RequestOption) (*Contact, error)
Create adds a contact.
func (*ContactsService) Export ¶
func (s *ContactsService) Export(ctx context.Context, params *ExportContactsParams, opts ...RequestOption) (string, error)
Export returns every contact as CSV (re-importable) or vCard 4.0 (Format "vcf").
func (*ContactsService) Import ¶
func (s *ContactsService) Import(ctx context.Context, params *ImportContactsParams, opts ...RequestOption) (map[string]any, error)
Import imports a CSV or vCard file. Importing never suppresses anyone.
func (*ContactsService) ImportPreview ¶
func (s *ContactsService) ImportPreview(ctx context.Context, params *ImportContactsParams, opts ...RequestOption) (map[string]any, error)
ImportPreview says what an import would do, without importing.
func (*ContactsService) List ¶
func (s *ContactsService) List(ctx context.Context, params *ListContactsParams, opts ...RequestOption) (*ContactList, error)
List returns one page of contacts.
type CreateContactParams ¶
type CreateContactParams struct {
Name string `json:"name"`
Email string `json:"email"`
AudienceID string `json:"audienceId,omitempty"`
Status string `json:"status,omitempty"`
}
CreateContactParams adds a contact.
type CreateDomainParams ¶
type CreateDomainParams struct {
// Name is a hostname such as send.acme.com. No scheme, no trailing slash.
Name string `json:"name"`
// Region cannot change once the domain holds messages.
Region Region `json:"region"`
}
CreateDomainParams registers a domain.
type CreateMailboxParams ¶
type CreateMailboxParams struct {
DomainID string `json:"domainId"`
LocalPart string `json:"localPart"`
DisplayName string `json:"displayName,omitempty"`
Color string `json:"color,omitempty"`
CatchAll bool `json:"catchAll,omitempty"`
}
CreateMailboxParams makes an address.
type CreateSuppressionParams ¶
type CreateSuppressionParams struct {
Email string `json:"email"`
Note string `json:"note,omitempty"`
}
CreateSuppressionParams suppresses an address (reason manual).
type CreateTemplateParams ¶
type CreateTemplateParams struct {
Name string `json:"name,omitempty"`
Subject string `json:"subject,omitempty"`
Preheader string `json:"preheader,omitempty"`
// Blocks: see https://sendclipper.com/docs for the block types. Unknown fields are dropped.
Blocks []TemplateBlock `json:"blocks,omitempty"`
ProjectDomainID string `json:"projectDomainId,omitempty"`
// Key is the send name, unique in its project: Emails.Send with Template: key.
Key string `json:"key,omitempty"`
}
CreateTemplateParams makes a draft. Every field is optional.
type CreateWebhookParams ¶
type CreateWebhookParams struct {
URL string `json:"url"`
Events []WebhookEventType `json:"events"`
// AllowInsecureHTTP accepts a plain http:// URL. Off by default.
AllowInsecureHTTP bool `json:"allowInsecureHttp,omitempty"`
}
CreateWebhookParams registers an endpoint.
type CursorInfo ¶
CursorInfo is the paging block of a cursor-addressed list.
type DNSRecord ¶
type DNSRecord struct {
Type string `json:"type"`
Purpose string `json:"purpose"`
Host string `json:"host"`
Value string `json:"value"`
CopyValue string `json:"copyValue,omitempty"`
Priority int `json:"priority,omitempty"`
Status string `json:"status,omitempty"`
}
DNSRecord is one record to publish.
type Domain ¶
type Domain struct {
ID string `json:"id"`
Name string `json:"name"`
Region Region `json:"region"`
Status string `json:"status"` // verified, pending or failed
SpfOK bool `json:"spfOk"`
DkimOK bool `json:"dkimOk"`
DmarcOK bool `json:"dmarcOk"`
Records []struct {
Name string `json:"name"`
OK bool `json:"ok"`
} `json:"records"`
Sent int `json:"sent"`
CheckCount int `json:"checkCount"`
LastCheckedAt *time.Time `json:"lastCheckedAt"`
CreatedAt time.Time `json:"createdAt"`
LastError *string `json:"lastError"`
ReceivingEnabled bool `json:"receivingEnabled"`
MxOK bool `json:"mxOk"`
ReceivingVerified bool `json:"receivingVerified"`
ReceivingError *string `json:"receivingError"`
}
Domain is a sending (and optionally receiving) domain.
type DomainRecords ¶
DomainRecords is a domain with the DNS records to publish.
type DomainsService ¶
type DomainsService struct {
// contains filtered or unexported fields
}
DomainsService manages sending and receiving domains.
func (*DomainsService) Create ¶
func (s *DomainsService) Create(ctx context.Context, params *CreateDomainParams, opts ...RequestOption) (*Domain, error)
Create registers a sending domain. Next: Records, publish them, then Verify.
func (*DomainsService) DeletionPreview ¶
func (s *DomainsService) DeletionPreview(ctx context.Context, id string, opts ...RequestOption) (map[string]any, error)
DeletionPreview says what deleting the domain would take with it.
func (*DomainsService) DisableReceiving ¶
func (s *DomainsService) DisableReceiving(ctx context.Context, id string, opts ...RequestOption) (*Domain, error)
DisableReceiving stops receiving mail on the domain.
func (*DomainsService) EnableReceiving ¶
func (s *DomainsService) EnableReceiving(ctx context.Context, id string, opts ...RequestOption) (*Domain, error)
EnableReceiving starts receiving mail on the domain. It adds receiving records and never blocks sending.
func (*DomainsService) List ¶
func (s *DomainsService) List(ctx context.Context, opts ...RequestOption) ([]Domain, error)
List returns every domain.
func (*DomainsService) Records ¶
func (s *DomainsService) Records(ctx context.Context, id string, opts ...RequestOption) (*DomainRecords, error)
Records returns the DNS records to publish, each with its current status.
func (*DomainsService) Remove ¶
func (s *DomainsService) Remove(ctx context.Context, id string, opts ...RequestOption) error
Remove deletes a domain.
func (*DomainsService) SetRegion ¶
func (s *DomainsService) SetRegion(ctx context.Context, id string, region Region, opts ...RequestOption) (*Domain, error)
SetRegion moves a domain to another region. Refused (region_immutable) once it holds messages.
func (*DomainsService) Verify ¶
func (s *DomainsService) Verify(ctx context.Context, id string, opts ...RequestOption) (*Domain, error)
Verify checks DNS now instead of waiting for the background check.
type DownloadedFile ¶
DownloadedFile is what a download returns.
type EmailDetail ¶
type EmailDetail struct {
EmailRow
HTML *string `json:"html"`
Text *string `json:"text"`
// BodyExpired is true once the retention window deleted the body.
BodyExpired bool `json:"bodyExpired"`
Events []EmailEvent `json:"events"`
ThreadID *string `json:"threadId"`
SendClass SendClass `json:"sendClass"`
TrackOpens *bool `json:"trackOpens"`
TrackClicks *bool `json:"trackClicks"`
}
EmailDetail is one message with its body and timeline.
type EmailEvent ¶
type EmailEvent struct {
ID string `json:"id"`
Type string `json:"type"`
Meta json.RawMessage `json:"meta"`
CreatedAt time.Time `json:"createdAt"`
}
EmailEvent is one step of a message's timeline.
type EmailList ¶
type EmailList struct {
Items []EmailRow `json:"items"`
Total int `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
// TotalCapped: a search counts only its newest 1,000 matches.
TotalCapped bool `json:"totalCapped"`
}
EmailList is one numbered page of the log.
type EmailRow ¶
type EmailRow struct {
ID string `json:"id"`
MessageID string `json:"messageId"`
From string `json:"from"`
To string `json:"to"`
Domain string `json:"domain"`
Subject string `json:"subject"`
Status EmailStatus `json:"status"`
SesMessageID *string `json:"sesMessageId"`
CreatedAt time.Time `json:"createdAt"`
}
EmailRow is one message in the log.
type EmailStats ¶
type EmailStats struct {
Total int `json:"total"`
Queued int `json:"queued"`
Sent int `json:"sent"`
Delivered int `json:"delivered"`
Opened int `json:"opened"`
Clicked int `json:"clicked"`
Bounced int `json:"bounced"`
Complained int `json:"complained"`
Failed int `json:"failed"`
BodyRetentionDays int `json:"bodyRetentionDays"`
}
EmailStats counts messages per status.
type EmailStatus ¶
type EmailStatus string
EmailStatus is a message's delivery state.
const ( StatusQueued EmailStatus = "queued" StatusSent EmailStatus = "sent" StatusDelivered EmailStatus = "delivered" StatusOpened EmailStatus = "opened" StatusClicked EmailStatus = "clicked" StatusBounced EmailStatus = "bounced" StatusComplained EmailStatus = "complained" StatusFailed EmailStatus = "failed" )
type EmailsService ¶
type EmailsService struct {
// contains filtered or unexported fields
}
EmailsService sends mail and reads the sent-mail log.
func (*EmailsService) All ¶
func (s *EmailsService) All(ctx context.Context, params *ListEmailsParams, opts ...RequestOption) iter.Seq2[EmailRow, error]
All walks every message matching params, page after page:
for email, err := range client.Emails.All(ctx, nil) { ... }
A failed page yields its error once and stops.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/sendclipper/sendclipper-go"
)
func main() {
client := sendclipper.NewClient("")
for email, err := range client.Emails.All(context.Background(), &sendclipper.ListEmailsParams{Status: sendclipper.StatusBounced}) {
if err != nil {
log.Println(err)
break
}
fmt.Println(email.To)
}
}
Output:
func (*EmailsService) Get ¶
func (s *EmailsService) Get(ctx context.Context, id string, opts ...RequestOption) (*EmailDetail, error)
Get returns one message with its body and event timeline.
func (*EmailsService) List ¶
func (s *EmailsService) List(ctx context.Context, params *ListEmailsParams, opts ...RequestOption) (*EmailList, error)
List returns one page of the sent-mail log, newest first.
func (*EmailsService) Send ¶
func (s *EmailsService) Send(ctx context.Context, params *SendEmailParams, opts ...RequestOption) (*SentEmail, error)
Send sends one message. It returns once SendClipper accepted it (status queued); delivery is reported later through Get and webhooks.
Every call carries an Idempotency-Key, so the SDK's own retries never send twice. Pass WithIdempotencyKey to make YOUR retries safe too.
Example (Template) ¶
package main
import (
"context"
"log"
"github.com/sendclipper/sendclipper-go"
)
func main() {
client := sendclipper.NewClient("")
_, err := client.Emails.Send(context.Background(), &sendclipper.SendEmailParams{
From: "hello@send.acme.io",
To: "ada@lumen.io",
TemplateID: "tpl_9f2b7c10ad42", // or Template: "welcome"
Variables: map[string]any{"first_name": "Ada"},
}, sendclipper.WithIdempotencyKey("order-42-receipt"))
if err != nil {
log.Println(err)
}
}
Output:
func (*EmailsService) SendBatch ¶
func (s *EmailsService) SendBatch(ctx context.Context, emails []SendEmailParams, opts ...RequestOption) (*SendBatchResponse, error)
SendBatch is the same as Batch.Send.
func (*EmailsService) Stats ¶
func (s *EmailsService) Stats(ctx context.Context, opts ...RequestOption) (*EmailStats, error)
Stats counts messages per status.
type Error ¶
type Error struct {
// Name is the API's code: "domain_not_verified", "template_variables_missing",
// "validation_failed", "rate_limited", or "network_error" when no answer arrived.
Name string
// Message is a sentence meant for a person.
Message string
// StatusCode is the HTTP status, or 0 when no answer arrived.
StatusCode int
// Detail holds code-specific facts (e.g. the missing template tags), as JSON.
Detail json.RawMessage
// Headers are the response headers, or nil when no answer arrived.
Headers http.Header
// contains filtered or unexported fields
}
Error is what every failed call returns: an API refusal, or a request that never got an answer. Branch on Name, SendClipper's machine-readable code; Message is a sentence meant for a person.
type ExportContactsParams ¶
ExportContactsParams picks the export format.
type ImportContactsParams ¶
type ImportContactsParams struct {
// File is the CSV or vCard contents.
File []byte
// Filename (contacts.csv / contacts.vcf): the extension decides the parser.
Filename string
AudienceID string
NewAudience string
CreateAudiences *bool
// OnDuplicate is "skip" or "update".
OnDuplicate string
// Mapping is the column mapping as ImportPreview returns it.
Mapping map[string]any
}
ImportContactsParams is a CSV or vCard import.
type ListContactsParams ¶
type ListContactsParams struct {
AudienceID string
Status string
Page int
PageSize int // 1-200, default 25
}
ListContactsParams filters contacts.
type ListEmailsParams ¶
type ListEmailsParams struct {
Search string
Status EmailStatus
Domain string // exact sending domain
BroadcastID string
From string // ISO 8601 lower bound
To string // ISO 8601 upper bound
Page int
PageSize int // 1-100, default 50
}
ListEmailsParams filters the sent-mail log.
type ListMailboxMessagesParams ¶
type ListMailboxMessagesParams struct {
Folder string // all, inbox, starred, sent, drafts, archive, spam, trash
Search string
Label string
Limit int // 1-200
Cursor string
}
ListMailboxMessagesParams filters an address's mail.
type ListSandboxMessagesParams ¶
ListSandboxMessagesParams filters a sandbox's messages.
type ListSuppressionsParams ¶
type ListSuppressionsParams struct {
Q string // address search
Reason string
Cursor string
Limit int // 1-100
}
ListSuppressionsParams filters the list.
type ListTemplatesParams ¶
ListTemplatesParams filters the template list.
type ListWebhookDeliveriesParams ¶
ListWebhookDeliveriesParams filters delivery attempts.
type ListWebhookDispatchesParams ¶
type ListWebhookDispatchesParams struct {
// State defaults to dead_lettered; "retrying" = pending or delivering; "all".
State string
EndpointID string
Cursor string
Limit int // 1-100
}
ListWebhookDispatchesParams filters undelivered events.
type Mailbox ¶
type Mailbox struct {
ID string `json:"id"`
Address string `json:"address"`
DisplayName string `json:"displayName"`
Domain string `json:"domain"`
DomainID string `json:"domainId"`
CatchAll bool `json:"catchAll"`
Archived bool `json:"archived"`
CanReceive bool `json:"canReceive"`
CanSend bool `json:"canSend"`
Unread int `json:"unread"`
Total int `json:"total"`
}
Mailbox is one address on a receiving domain.
type MailboxMessage ¶
type MailboxMessage struct {
MailboxMessageRow
BodyText *string `json:"bodyText"`
BodyHTML *string `json:"bodyHtml"`
BodyExpiredAt *time.Time `json:"bodyExpiredAt"`
Thread *struct {
ID string `json:"id"`
Subject string `json:"subject"`
MessageCount int `json:"messageCount"`
LastAt time.Time `json:"lastAt"`
Participants []string `json:"participants"`
Messages json.RawMessage `json:"messages"`
} `json:"thread"`
// Attachments: download one with Mailboxes.Messages.Attachment.
Attachments []struct {
ID string `json:"id"`
Filename string `json:"filename"`
ContentType string `json:"contentType"`
SizeBytes int `json:"sizeBytes"`
} `json:"attachments"`
// Authentication holds SPF/DKIM/DMARC/spam verdicts for received mail; nil for your own sends.
Authentication map[string]any `json:"authentication"`
}
MailboxMessage is one message in full, with its conversation.
type MailboxMessageList ¶
type MailboxMessageList struct {
Items []MailboxMessageRow `json:"items"`
Total int `json:"total"`
Unread int `json:"unread"`
TotalCapped bool `json:"totalCapped"`
Page CursorInfo `json:"page"`
}
MailboxMessageList is one cursor page of a mailbox.
type MailboxMessageRow ¶
type MailboxMessageRow struct {
ID string `json:"id"`
Folder string `json:"folder"`
From string `json:"from"`
FromName string `json:"fromName"`
To string `json:"to"`
Cc *string `json:"cc"`
Bcc *string `json:"bcc"`
Subject string `json:"subject"`
Snippet string `json:"snippet"`
Label *string `json:"label"`
Unread bool `json:"unread"`
Starred bool `json:"starred"`
ReceivedAt time.Time `json:"receivedAt"`
MailboxID *string `json:"mailboxId"`
ThreadID *string `json:"threadId"`
}
MailboxMessageRow is one message in a mailbox list.
type MailboxMessagesService ¶
type MailboxMessagesService struct {
// contains filtered or unexported fields
}
MailboxMessagesService reads mail filed under an address. Reading never marks anything read.
func (*MailboxMessagesService) All ¶
func (s *MailboxMessagesService) All(ctx context.Context, mailboxID string, params *ListMailboxMessagesParams, opts ...RequestOption) iter.Seq2[MailboxMessageRow, error]
All walks an address's mail, following the cursor.
func (*MailboxMessagesService) Attachment ¶
func (s *MailboxMessagesService) Attachment(ctx context.Context, mailboxID, messageID, attachmentID string, opts ...RequestOption) (*DownloadedFile, error)
Attachment downloads one attachment.
func (*MailboxMessagesService) Get ¶
func (s *MailboxMessagesService) Get(ctx context.Context, mailboxID, messageID string, opts ...RequestOption) (*MailboxMessage, error)
Get returns one message in full, with its conversation.
func (*MailboxMessagesService) List ¶
func (s *MailboxMessagesService) List(ctx context.Context, mailboxID string, params *ListMailboxMessagesParams, opts ...RequestOption) (*MailboxMessageList, error)
List returns one cursor page of an address's mail.
type MailboxesService ¶
type MailboxesService struct {
Messages *MailboxMessagesService
// contains filtered or unexported fields
}
MailboxesService manages addresses on receiving domains.
func (*MailboxesService) Archive ¶
func (s *MailboxesService) Archive(ctx context.Context, id string, opts ...RequestOption) (*Mailbox, error)
Archive archives the address. Its mail is kept.
func (*MailboxesService) Create ¶
func (s *MailboxesService) Create(ctx context.Context, params *CreateMailboxParams, opts ...RequestOption) (*Mailbox, error)
Create makes a new address on a receiving domain.
func (*MailboxesService) Get ¶
func (s *MailboxesService) Get(ctx context.Context, id string, opts ...RequestOption) (*Mailbox, error)
Get returns one address.
func (*MailboxesService) List ¶
func (s *MailboxesService) List(ctx context.Context, includeArchived bool, opts ...RequestOption) ([]Mailbox, error)
List returns the addresses; includeArchived lists archived ones too.
func (*MailboxesService) Update ¶
func (s *MailboxesService) Update(ctx context.Context, id string, params *UpdateMailboxParams, opts ...RequestOption) (*Mailbox, error)
Update changes the fields set in params.
type ReplayAllParams ¶
type ReplayAllParams struct {
State string `json:"state,omitempty"`
EndpointID string `json:"endpointId,omitempty"`
}
ReplayAllParams scopes a bulk replay.
type ReplayAllResult ¶
type ReplayAllResult struct {
Queued int `json:"queued"`
Remaining int `json:"remaining"`
Capped bool `json:"capped"`
Max int `json:"max"`
}
ReplayAllResult says what a bulk replay queued.
type RequestOption ¶
type RequestOption func(*requestConfig)
RequestOption adjusts one call.
func WithHeader ¶
func WithHeader(name, value string) RequestOption
WithHeader adds a header to one call.
func WithIdempotencyKey ¶
func WithIdempotencyKey(key string) RequestOption
WithIdempotencyKey sets your own Idempotency-Key, so that YOUR retries of the same logical operation (a job that runs again after a crash) are safe too. Without it every write still gets a fresh key of its own.
func WithRequestMaxRetries ¶
func WithRequestMaxRetries(n int) RequestOption
WithRequestMaxRetries overrides the client's retry count for one call.
func WithRequestTimeout ¶
func WithRequestTimeout(d time.Duration) RequestOption
WithRequestTimeout overrides the client's per-attempt timeout for one call.
func WithResponseHeaders ¶
func WithResponseHeaders(dst *http.Header) RequestOption
WithResponseHeaders stores the response's headers in *dst when the call succeeds (on failure they are on the *Error).
type ResetSandboxCredentials ¶
type ResetSandboxCredentials struct {
Username string `json:"username"`
Password string `json:"password"`
APIToken string `json:"apiToken"`
}
ResetSandboxCredentials holds the new credentials. The token is shown once.
type Sandbox ¶
type Sandbox struct {
ID string `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
// InboxAddress: mail sent to this address lands in the sandbox.
InboxAddress string `json:"inboxAddress"`
InboundLive bool `json:"inboundLive"`
ProjectLabel string `json:"projectLabel"`
Color string `json:"color"`
Total int `json:"total"`
Unread int `json:"unread"`
MessageCap int `json:"messageCap"`
RetentionDays int `json:"retentionDays"`
LastTrappedAt *time.Time `json:"lastTrappedAt"`
CreatedAt time.Time `json:"createdAt"`
}
Sandbox traps mail: nothing sent to it is delivered.
type SandboxCredentials ¶
type SandboxCredentials struct {
Host string `json:"host"`
Port int `json:"port"`
TLS string `json:"tls"` // required, optional or none
MaxRecipients int `json:"maxRecipients"`
Username string `json:"username"`
Password string `json:"password"`
MaxMessageBytes int `json:"maxMessageBytes"`
RetentionDays int `json:"retentionDays"`
APIEndpoint string `json:"apiEndpoint"`
InboxID string `json:"inboxId"`
InboxAddress string `json:"inboxAddress"`
InboundDomain string `json:"inboundDomain"`
InboundLive bool `json:"inboundLive"`
// APITokenHint: the JSON token is hashed; only its hint can be read back.
APITokenHint string `json:"apiTokenHint"`
}
SandboxCredentials point a project at the sandbox.
type SandboxMessage ¶
type SandboxMessage struct {
SandboxMessageSummary
CcAddresses []string `json:"ccAddresses"`
// EnvelopeFrom/EnvelopeTo are the SMTP envelope, recorded apart from the
// headers (a Bcc recipient is only here).
EnvelopeFrom string `json:"envelopeFrom"`
EnvelopeTo []string `json:"envelopeTo"`
BodyHTML *string `json:"bodyHtml"`
// BodyText is nil when the message carried no text/plain part.
BodyText *string `json:"bodyText"`
Headers []struct {
Name string `json:"name"`
Value string `json:"value"`
} `json:"headers"`
Transport string `json:"transport"`
ClientIP *string `json:"clientIp"`
HasRaw bool `json:"hasRaw"`
}
SandboxMessage is one trapped message in full.
type SandboxMessageSummary ¶
type SandboxMessageSummary struct {
ID string `json:"id"`
Subject string `json:"subject"`
FromAddress string `json:"fromAddress"`
FromName string `json:"fromName"`
ToAddresses []string `json:"toAddresses"`
Snippet string `json:"snippet"`
SizeBytes int `json:"sizeBytes"`
Read bool `json:"read"`
TrappedAt time.Time `json:"trappedAt"`
}
SandboxMessageSummary is one trapped message in a list.
type SandboxMessagesService ¶
type SandboxMessagesService struct {
// contains filtered or unexported fields
}
SandboxMessagesService reads what a sandbox trapped.
func (*SandboxMessagesService) Clear ¶
func (s *SandboxMessagesService) Clear(ctx context.Context, sandboxID string, opts ...RequestOption) (int, error)
Clear empties the sandbox and returns how many messages went.
func (*SandboxMessagesService) Get ¶
func (s *SandboxMessagesService) Get(ctx context.Context, sandboxID, messageID string, opts ...RequestOption) (*SandboxMessage, error)
Get returns one trapped message in full.
func (*SandboxMessagesService) List ¶
func (s *SandboxMessagesService) List(ctx context.Context, sandboxID string, params *ListSandboxMessagesParams, opts ...RequestOption) ([]SandboxMessageSummary, error)
List returns a sandbox's messages, newest first.
func (*SandboxMessagesService) MarkAllRead ¶
func (s *SandboxMessagesService) MarkAllRead(ctx context.Context, sandboxID string, opts ...RequestOption) (int, error)
MarkAllRead marks every message read and returns how many changed.
func (*SandboxMessagesService) Raw ¶
func (s *SandboxMessagesService) Raw(ctx context.Context, sandboxID, messageID string, opts ...RequestOption) (string, error)
Raw returns the message's raw MIME source.
func (*SandboxMessagesService) Remove ¶
func (s *SandboxMessagesService) Remove(ctx context.Context, sandboxID, messageID string, opts ...RequestOption) error
Remove deletes one trapped message.
func (*SandboxMessagesService) WaitFor ¶
func (s *SandboxMessagesService) WaitFor(ctx context.Context, sandboxID string, opts *WaitForOptions) (*SandboxMessage, error)
WaitFor polls until a message arrives that opts.Match accepts, then returns it in full. Handy in end-to-end tests. Bound it with ctx: when ctx ends first the error's Name is "timeout".
type SandboxParams ¶
type SandboxParams struct {
Name string `json:"name,omitempty"`
ProjectLabel string `json:"projectLabel,omitempty"`
Color string `json:"color,omitempty"` // #rrggbb
}
SandboxParams creates or renames a sandbox.
type SandboxSendResult ¶
SandboxSendResult is what the sandbox JSON door answers.
type SandboxesService ¶
type SandboxesService struct {
Messages *SandboxMessagesService
// contains filtered or unexported fields
}
SandboxesService manages sandboxes: inboxes that trap mail while you develop.
func (*SandboxesService) Create ¶
func (s *SandboxesService) Create(ctx context.Context, params *SandboxParams, opts ...RequestOption) (*Sandbox, error)
Create makes a sandbox. Name is required.
func (*SandboxesService) Credentials ¶
func (s *SandboxesService) Credentials(ctx context.Context, id string, opts ...RequestOption) (*SandboxCredentials, error)
Credentials returns the SMTP host, port, username and password to point a project at.
func (*SandboxesService) Get ¶
func (s *SandboxesService) Get(ctx context.Context, id string, opts ...RequestOption) (*Sandbox, error)
Get returns one sandbox.
func (*SandboxesService) List ¶
func (s *SandboxesService) List(ctx context.Context, opts ...RequestOption) ([]Sandbox, error)
List returns every sandbox.
func (*SandboxesService) Remove ¶
func (s *SandboxesService) Remove(ctx context.Context, id string, opts ...RequestOption) (int, error)
Remove deletes the sandbox and every message in it, and returns how many messages went.
func (*SandboxesService) ResetCredentials ¶
func (s *SandboxesService) ResetCredentials(ctx context.Context, id string, opts ...RequestOption) (*ResetSandboxCredentials, error)
ResetCredentials replaces BOTH the SMTP password and the sc_sbx_ token. The token is shown only here.
func (*SandboxesService) Send ¶
func (s *SandboxesService) Send(ctx context.Context, sandboxToken string, params *SendEmailParams, opts ...RequestOption) (*SandboxSendResult, error)
Send sends to a sandbox through its JSON door, with the sandbox's own sc_sbx_ token. Same fields as Emails.Send; nothing is delivered.
func (*SandboxesService) Update ¶
func (s *SandboxesService) Update(ctx context.Context, id string, params *SandboxParams, opts ...RequestOption) (*Sandbox, error)
Update renames a sandbox. Renaming never changes the address or the credentials.
type SendBatchResponse ¶
type SendBatchResponse struct {
Data []BatchResult `json:"data"`
Summary struct {
Submitted int `json:"submitted"`
Accepted int `json:"accepted"`
Failed int `json:"failed"`
} `json:"summary"`
}
SendBatchResponse holds one result per submitted item, in order.
type SendEmailParams ¶
type SendEmailParams struct {
// From is a bare address on a verified domain: "hello@send.acme.io". A display-name form is refused.
From string `json:"from"`
// To is ONE recipient. For several, use Batch.Send with one item each.
To string `json:"to"`
Subject string `json:"subject,omitempty"`
HTML string `json:"html,omitempty"`
// Text is the plain-text alternative.
Text string `json:"text,omitempty"`
// TemplateID is a published template's public id (tpl_...) or uuid.
TemplateID string `json:"templateId,omitempty"`
// Template is a published template's send name (its key, e.g. "welcome"). Use this or TemplateID.
Template string `json:"template,omitempty"`
// Variables fill {{tags}} in a template, or in a hand-written HTML body.
Variables map[string]any `json:"variables,omitempty"`
// SendClass "marketing" adds one-click unsubscribe and the postal-address footer.
SendClass SendClass `json:"sendClass,omitempty"`
// TrackOpens false leaves the open-tracking pixel out. Default true.
TrackOpens *bool `json:"trackOpens,omitempty"`
// TrackClicks false leaves links unwrapped. Default true.
TrackClicks *bool `json:"trackClicks,omitempty"`
}
SendEmailParams is one message. Give it a body (Subject + HTML) or a published template (TemplateID or Template, plus Variables).
type SentEmail ¶
type SentEmail struct {
// ID is SendClipper's id for the message. Use it with Emails.Get.
ID string `json:"id"`
MessageID string `json:"messageId"`
SesMessageID *string `json:"sesMessageId"`
From string `json:"from"`
To string `json:"to"`
Domain string `json:"domain"`
Subject string `json:"subject"`
Status EmailStatus `json:"status"`
CreatedAt time.Time `json:"createdAt"`
TemplateID *string `json:"templateId"`
}
SentEmail is what Emails.Send answers: the message was accepted (queued).
type Suppression ¶
type Suppression struct {
ID string `json:"id"`
Email string `json:"email"`
Reason string `json:"reason"` // hard_bounce, soft_bounce, complaint, unsubscribe, manual, provider
ReasonLabel string `json:"reasonLabel"`
ReasonDetail *string `json:"reasonDetail"`
DiagnosticCode *string `json:"diagnosticCode"`
Scope string `json:"scope"` // marketing for an unsubscribe, all for everything else
SourceEmailID *string `json:"sourceEmailId"`
SourceMessageID *string `json:"sourceMessageId"`
CreatedAt time.Time `json:"createdAt"`
}
Suppression stops mail to one address.
type SuppressionCreated ¶
type SuppressionCreated struct {
Created bool `json:"created"`
Row *Suppression `json:"row"`
}
SuppressionCreated: Created is false when the address was already suppressed; Row is the entry either way.
type SuppressionList ¶
type SuppressionList struct {
Data []Suppression `json:"data"`
Page CursorInfo `json:"page"`
Counts struct {
Total int `json:"total"`
ByReason map[string]int `json:"byReason"`
} `json:"counts"`
}
SuppressionList is one cursor page of the list.
type SuppressionsService ¶
type SuppressionsService struct {
// contains filtered or unexported fields
}
SuppressionsService manages the suppression list.
func (*SuppressionsService) All ¶
func (s *SuppressionsService) All(ctx context.Context, params *ListSuppressionsParams, opts ...RequestOption) iter.Seq2[Suppression, error]
All walks every suppression matching params, following the cursor.
func (*SuppressionsService) Create ¶
func (s *SuppressionsService) Create(ctx context.Context, params *CreateSuppressionParams, opts ...RequestOption) (*SuppressionCreated, error)
Create stops all mail to an address (reason manual).
func (*SuppressionsService) Export ¶
func (s *SuppressionsService) Export(ctx context.Context, params *ListSuppressionsParams, opts ...RequestOption) (string, error)
Export returns the list as CSV. Cursor and Limit are ignored.
func (*SuppressionsService) List ¶
func (s *SuppressionsService) List(ctx context.Context, params *ListSuppressionsParams, opts ...RequestOption) (*SuppressionList, error)
List returns one cursor page of the list.
func (*SuppressionsService) Remove ¶
func (s *SuppressionsService) Remove(ctx context.Context, id, reason string, opts ...RequestOption) error
Remove lifts a suppression. reason (10+ characters) is recorded. Complaint and provider suppressions cannot be removed (suppression_not_removable).
type Template ¶
type Template struct {
TemplateSummary
Subject string `json:"subject"`
Preheader string `json:"preheader"`
Blocks []TemplateBlock `json:"blocks"`
HTML string `json:"html"`
}
Template is a template with its body.
type TemplateAsset ¶
type TemplateAsset struct {
ID string `json:"id"`
PublicID string `json:"publicId"`
// URL is public: a mail client can load it.
URL string `json:"url"`
MimeType string `json:"mimeType"`
Bytes int `json:"bytes"`
Name string `json:"name"`
CreatedAt time.Time `json:"createdAt"`
}
TemplateAsset is an uploaded image.
type TemplateAssetsService ¶
type TemplateAssetsService struct {
// contains filtered or unexported fields
}
TemplateAssetsService manages images templates can show.
func (*TemplateAssetsService) List ¶
func (s *TemplateAssetsService) List(ctx context.Context, opts ...RequestOption) ([]TemplateAsset, error)
List returns the uploaded images.
func (*TemplateAssetsService) Upload ¶
func (s *TemplateAssetsService) Upload(ctx context.Context, params *UploadTemplateAssetParams, opts ...RequestOption) (*TemplateAsset, error)
Upload stores an image and returns its public URL.
type TemplateBlock ¶
TemplateBlock is one block: {"type": "text", "text": "Hi {{first_name|there}}"}.
type TemplatePreview ¶
type TemplatePreview struct {
Subject string `json:"subject"`
Preheader string `json:"preheader"`
HTML string `json:"html"`
Text string `json:"text"`
Variables []struct {
Name string `json:"name"`
Fallback *string `json:"fallback"`
Value string `json:"value"`
Provided bool `json:"provided"`
} `json:"variables"`
// UnsafeLinks are links whose target a tag would make unsafe.
UnsafeLinks []string `json:"unsafeLinks"`
}
TemplatePreview is a render that sent nothing.
type TemplateSummary ¶
type TemplateSummary struct {
ID string `json:"id"`
PublicID string `json:"publicId"`
Name string `json:"name"`
Status string `json:"status"` // draft or published
BlockCount int `json:"blockCount"`
UpdatedAt time.Time `json:"updatedAt"`
PublishedAt *time.Time `json:"publishedAt"`
CreatedAt time.Time `json:"createdAt"`
Domains []NamedRef `json:"domains"`
Tags []TemplateTag `json:"tags"`
Key *string `json:"key"`
Project *NamedRef `json:"project"`
}
TemplateSummary is one card in the template list.
type TemplateTag ¶
type TemplateTag struct {
ID string `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
TemplateCount *int `json:"templateCount,omitempty"`
}
TemplateTag labels templates.
type TemplateTagsService ¶
type TemplateTagsService struct {
// contains filtered or unexported fields
}
TemplateTagsService manages template tags.
func (*TemplateTagsService) Create ¶
func (s *TemplateTagsService) Create(ctx context.Context, name, color string, opts ...RequestOption) (*TemplateTag, error)
Create makes a tag. color is gray, red, orange, amber, green, teal, blue, purple or pink.
func (*TemplateTagsService) List ¶
func (s *TemplateTagsService) List(ctx context.Context, opts ...RequestOption) ([]TemplateTag, error)
List returns every tag, each with its TemplateCount.
func (*TemplateTagsService) Remove ¶
func (s *TemplateTagsService) Remove(ctx context.Context, id string, opts ...RequestOption) (int, error)
Remove deletes a tag and returns how many templates it was taken off.
func (*TemplateTagsService) Update ¶
func (s *TemplateTagsService) Update(ctx context.Context, id, name, color string, opts ...RequestOption) (*TemplateTag, error)
Update renames or recolours a tag; an empty string leaves that field alone.
type TemplatesService ¶
type TemplatesService struct {
Tags *TemplateTagsService
Assets *TemplateAssetsService
// contains filtered or unexported fields
}
TemplatesService manages email templates.
func (*TemplatesService) Create ¶
func (s *TemplatesService) Create(ctx context.Context, params *CreateTemplateParams, opts ...RequestOption) (*Template, error)
Create makes a new draft. Publish it before sending with it. params may be nil.
func (*TemplatesService) Duplicate ¶
func (s *TemplatesService) Duplicate(ctx context.Context, id string, opts ...RequestOption) (*Template, error)
Duplicate copies a template as a new draft.
func (*TemplatesService) Get ¶
func (s *TemplatesService) Get(ctx context.Context, id string, opts ...RequestOption) (*Template, error)
Get returns a template by uuid or public id (tpl_...).
func (*TemplatesService) HTML ¶
func (s *TemplatesService) HTML(ctx context.Context, id string, opts ...RequestOption) (string, error)
HTML returns the rendered HTML, tags left in place.
func (*TemplatesService) List ¶
func (s *TemplatesService) List(ctx context.Context, params *ListTemplatesParams, opts ...RequestOption) ([]TemplateSummary, error)
List returns the templates, optionally filtered.
func (*TemplatesService) Preview ¶
func (s *TemplatesService) Preview(ctx context.Context, id string, variables map[string]any, opts ...RequestOption) (*TemplatePreview, error)
Preview renders with variables without sending anything. variables may be nil.
func (*TemplatesService) Projects ¶
func (s *TemplatesService) Projects(ctx context.Context, opts ...RequestOption) ([]NamedRef, error)
Projects returns the projects (domains) templates can belong to.
func (*TemplatesService) Publish ¶
func (s *TemplatesService) Publish(ctx context.Context, id string, opts ...RequestOption) (*Template, error)
Publish makes a template sendable.
func (*TemplatesService) Remove ¶
func (s *TemplatesService) Remove(ctx context.Context, id string, opts ...RequestOption) error
Remove deletes a template.
func (*TemplatesService) SetTags ¶
func (s *TemplatesService) SetTags(ctx context.Context, id string, tagIDs []string, opts ...RequestOption) ([]TemplateTag, error)
SetTags replaces the template's tags with these tag ids.
func (*TemplatesService) Unpublish ¶
func (s *TemplatesService) Unpublish(ctx context.Context, id string, opts ...RequestOption) (*Template, error)
Unpublish returns a template to draft.
func (*TemplatesService) Update ¶
func (s *TemplatesService) Update(ctx context.Context, id string, params *UpdateTemplateParams, opts ...RequestOption) (*Template, error)
Update changes the fields set in params.
type UpdateMailboxParams ¶
type UpdateMailboxParams struct {
LocalPart string `json:"localPart,omitempty"`
DisplayName *string `json:"displayName,omitempty"`
Color string `json:"color,omitempty"`
CatchAll *bool `json:"catchAll,omitempty"`
Archived *bool `json:"archived,omitempty"`
NotifyOwner *bool `json:"notifyOwner,omitempty"`
EmbedOrigins []string `json:"embedOrigins,omitempty"`
}
UpdateMailboxParams changes the fields you set.
type UpdateTemplateParams ¶
type UpdateTemplateParams struct {
Name *string `json:"name,omitempty"`
Subject *string `json:"subject,omitempty"`
Preheader *string `json:"preheader,omitempty"`
Blocks []TemplateBlock `json:"blocks,omitempty"`
DomainIDs []string `json:"domainIds,omitempty"`
ProjectDomainID *string `json:"projectDomainId,omitempty"`
Key *string `json:"key,omitempty"`
}
UpdateTemplateParams changes the fields you set. Use a pointer to "" (or an empty slice) to clear one.
type UpdateWebhookParams ¶
type UpdateWebhookParams struct {
URL string `json:"url,omitempty"`
Events []WebhookEventType `json:"events,omitempty"`
Active *bool `json:"active,omitempty"`
AllowInsecureHTTP *bool `json:"allowInsecureHttp,omitempty"`
}
UpdateWebhookParams changes the fields you set.
type UploadTemplateAssetParams ¶
type UploadTemplateAssetParams struct {
// MimeType is image/png, image/jpeg, image/gif or image/webp.
MimeType string
// Data is the file's bytes; it is base64-encoded for you.
Data []byte
Name string
}
UploadTemplateAssetParams is one image.
type VerifyOption ¶
type VerifyOption func(*verifyConfig)
VerifyOption tunes VerifyWebhook.
func WithTolerance ¶
func WithTolerance(d time.Duration) VerifyOption
WithTolerance replaces the five-minute tolerance.
type WaitForOptions ¶
type WaitForOptions struct {
// Match picks the message to wait for. Default: any message trapped after the call started.
Match func(SandboxMessageSummary) bool
// Interval between polls. Default 1 second.
Interval time.Duration
}
WaitForOptions tunes WaitFor.
type WebhookDispatch ¶
type WebhookDispatch struct {
ID string `json:"id"`
EndpointID string `json:"endpointId"`
EndpointURL string `json:"endpointUrl"`
// EventID is the id the receiver saw in the body.
EventID string `json:"eventId"`
Event WebhookEventType `json:"event"`
State string `json:"state"` // pending, delivering, delivered or dead_lettered
Attempts int `json:"attempts"`
LastStatusCode *int `json:"lastStatusCode"`
LastError *string `json:"lastError"`
LastAttemptError *string `json:"lastAttemptError"`
FirstAttemptAt *time.Time `json:"firstAttemptAt"`
LastAttemptAt *time.Time `json:"lastAttemptAt"`
NextAttemptAt *time.Time `json:"nextAttemptAt"`
CreatedAt time.Time `json:"createdAt"`
ReplayedAt *time.Time `json:"replayedAt"`
ReplayCount int `json:"replayCount"`
}
WebhookDispatch is one event's delivery to one endpoint.
type WebhookDispatchPage ¶
type WebhookDispatchPage struct {
Data []WebhookDispatch `json:"data"`
Page CursorInfo `json:"page"`
}
WebhookDispatchPage is one cursor page of dispatches.
type WebhookDispatchesService ¶
type WebhookDispatchesService struct {
// contains filtered or unexported fields
}
WebhookDispatchesService reads and replays undelivered events.
func (*WebhookDispatchesService) All ¶
func (s *WebhookDispatchesService) All(ctx context.Context, params *ListWebhookDispatchesParams, opts ...RequestOption) iter.Seq2[WebhookDispatch, error]
All walks every dispatch matching params, following the cursor.
func (*WebhookDispatchesService) Get ¶
func (s *WebhookDispatchesService) Get(ctx context.Context, id string, opts ...RequestOption) (*WebhookDispatch, error)
Get returns one dispatch.
func (*WebhookDispatchesService) List ¶
func (s *WebhookDispatchesService) List(ctx context.Context, params *ListWebhookDispatchesParams, opts ...RequestOption) (*WebhookDispatchPage, error)
List returns undelivered events: dead letters by default, or State "retrying".
func (*WebhookDispatchesService) Replay ¶
func (s *WebhookDispatchesService) Replay(ctx context.Context, id string, opts ...RequestOption) (*WebhookDispatch, error)
Replay makes one more immediate attempt for a dead-lettered event.
func (*WebhookDispatchesService) ReplayAll ¶
func (s *WebhookDispatchesService) ReplayAll(ctx context.Context, params *ReplayAllParams, opts ...RequestOption) (*ReplayAllResult, error)
ReplayAll replays every dead letter (optionally of one endpoint), up to the server's cap. params may be nil.
type WebhookEndpoint ¶
type WebhookEndpoint struct {
ID string `json:"id"`
URL string `json:"url"`
Events []WebhookEventType `json:"events"`
Active bool `json:"active"`
CreatedAt time.Time `json:"createdAt"`
SecretMasked string `json:"secretMasked"`
SecretRotatedAt *time.Time `json:"secretRotatedAt"`
PreviousSecretExpiresAt *time.Time `json:"previousSecretExpiresAt"`
SuccessRate *float64 `json:"successRate"`
SuccessRateWindowDays int `json:"successRateWindowDays"`
DeliveryCount int `json:"deliveryCount"`
DeliveredCount int `json:"deliveredCount"`
}
WebhookEndpoint is a URL SendClipper posts events to.
type WebhookEndpointWithSecret ¶
type WebhookEndpointWithSecret struct {
WebhookEndpoint
Secret string `json:"secret"`
}
WebhookEndpointWithSecret carries the full whsec_ signing secret, once.
type WebhookEvent ¶
type WebhookEvent struct {
// ID is stable for one (email, event): deduplicate on it.
ID string `json:"id"`
Event WebhookEventType `json:"event"`
CreatedAt time.Time `json:"createdAt"`
Data WebhookEventData `json:"data"`
}
WebhookEvent is a webhook delivery's body.
func VerifyWebhook ¶
func VerifyWebhook(payload []byte, headers http.Header, secret string, opts ...VerifyOption) (*WebhookEvent, error)
VerifyWebhook verifies a delivery and returns its parsed event.
payload is the body EXACTLY as received (read r.Body with io.ReadAll before decoding it), never re-encoded JSON; headers is r.Header.
SendClipper signs "{timestamp}.{rawBody}" with HMAC-SHA256 and sends X-SendClipper-Signature-V2: t=<seconds>,v1=<hex>[,v1=<hex>]. During a secret rotation there are two v1= values; any match is accepted.
Example ¶
package main
import (
"io"
"log"
"net/http"
"os"
"github.com/sendclipper/sendclipper-go"
)
func main() {
http.HandleFunc("/hooks/sendclipper", func(w http.ResponseWriter, r *http.Request) {
payload, err := io.ReadAll(r.Body) // the raw body, before any json.Decode
if err != nil {
http.Error(w, "read error", http.StatusBadRequest)
return
}
event, err := sendclipper.VerifyWebhook(payload, r.Header, os.Getenv("SENDCLIPPER_WEBHOOK_SECRET"))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// event.ID is stable across retries: deduplicate on it
log.Println(event.Event, event.Data.To)
w.WriteHeader(http.StatusOK)
})
}
Output:
func VerifyWebhookSignature ¶
func VerifyWebhookSignature(payload []byte, signature, secret string, opts ...VerifyOption) (*WebhookEvent, error)
VerifyWebhookSignature is VerifyWebhook for when you hold only the X-SendClipper-Signature-V2 header's value.
type WebhookEventData ¶
type WebhookEventData struct {
EmailID string `json:"emailId"`
MessageID string `json:"messageId"`
To string `json:"to"`
Domain string `json:"domain"`
Subject string `json:"subject"`
// Raw is the whole data object, for event-specific fields (bounce type, clicked link, ...).
Raw map[string]any `json:"-"`
}
WebhookEventData is the message an event is about. Raw holds every field.
func (*WebhookEventData) UnmarshalJSON ¶
func (d *WebhookEventData) UnmarshalJSON(b []byte) error
UnmarshalJSON keeps every field in Raw as well as the typed ones.
type WebhookEventType ¶
type WebhookEventType string
WebhookEventType names an event a webhook can subscribe to.
const ( EventDelivered WebhookEventType = "email.delivered" EventOpened WebhookEventType = "email.opened" EventClicked WebhookEventType = "email.clicked" EventBounced WebhookEventType = "email.bounced" EventComplained WebhookEventType = "email.complained" EventFailed WebhookEventType = "email.failed" )
type WebhookVerificationError ¶
type WebhookVerificationError struct {
// Reason is missing_header, malformed_header, timestamp_out_of_tolerance,
// signature_mismatch or invalid_payload.
Reason string
Message string
}
WebhookVerificationError is why VerifyWebhook refused a delivery.
func (*WebhookVerificationError) Error ¶
func (e *WebhookVerificationError) Error() string
type WebhooksService ¶
type WebhooksService struct {
Dispatches *WebhookDispatchesService
// contains filtered or unexported fields
}
WebhooksService manages webhook endpoints.
func (*WebhooksService) Create ¶
func (s *WebhooksService) Create(ctx context.Context, params *CreateWebhookParams, opts ...RequestOption) (*WebhookEndpointWithSecret, error)
Create registers an endpoint. The response carries the signing Secret once: store it.
func (*WebhooksService) Deliveries ¶
func (s *WebhooksService) Deliveries(ctx context.Context, params *ListWebhookDeliveriesParams, opts ...RequestOption) ([]map[string]any, error)
Deliveries returns recent delivery attempts.
func (*WebhooksService) List ¶
func (s *WebhooksService) List(ctx context.Context, opts ...RequestOption) ([]WebhookEndpoint, error)
List returns every endpoint.
func (*WebhooksService) Remove ¶
func (s *WebhooksService) Remove(ctx context.Context, id string, opts ...RequestOption) error
Remove deletes an endpoint.
func (*WebhooksService) RotateSecret ¶
func (s *WebhooksService) RotateSecret(ctx context.Context, id string, opts ...RequestOption) (*WebhookEndpointWithSecret, error)
RotateSecret makes a new secret. The old one keeps signing alongside it for the grace window.
func (*WebhooksService) Update ¶
func (s *WebhooksService) Update(ctx context.Context, id string, params *UpdateWebhookParams, opts ...RequestOption) (*WebhookEndpoint, error)
Update changes the fields set in params.
func (*WebhooksService) Verify ¶
func (s *WebhooksService) Verify(payload []byte, headers http.Header, secret string, opts ...VerifyOption) (*WebhookEvent, error)
Verify is VerifyWebhook. It makes no request.
type Workspace ¶
type Workspace struct {
ID string `json:"id"`
Name string `json:"name"`
PublicID string `json:"publicId"`
CreatedAt time.Time `json:"createdAt"`
SendingPaused *struct {
At time.Time `json:"at"`
Reason string `json:"reason"`
Message string `json:"message"`
} `json:"sendingPaused"`
PostalAddress *string `json:"postalAddress"`
}
Workspace is the workspace an API key belongs to.
type WorkspaceService ¶
type WorkspaceService struct {
// contains filtered or unexported fields
}
WorkspaceService reads the key's workspace.
func (*WorkspaceService) Get ¶
func (s *WorkspaceService) Get(ctx context.Context, opts ...RequestOption) (*Workspace, error)
Get returns the workspace this key belongs to.