### Install Postmark Golang Library Source: https://github.com/mrz1836/postmark/blob/master/README.md Use this command to install the Postmark Golang library. Ensure you have a supported release of Go installed. ```shell go get github.com/mrz1836/postmark ``` -------------------------------- ### Install MAGE-X for Development Source: https://github.com/mrz1836/postmark/blob/master/README.md Installs the magex tool, which is used for development and building tasks. Ensure Go is installed and configured. ```bash go install github.com/mrz1836/mage-x/cmd/magex@latest magex update:install ``` -------------------------------- ### Send Email with Postmark Golang Source: https://github.com/mrz1836/postmark/blob/master/README.md Example of sending an email using the Postmark Golang library. Requires server and account tokens. Ensure you have the necessary imports. ```go package main import ( "context" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("[SERVER-TOKEN]", "[ACCOUNT-TOKEN]") email := postmark.Email{ From: "no-reply@example.com", To: "tito@example.com", Subject: "Reset your password", HTMLBody: "...", TextBody: "...", Tag: "pw-reset", TrackOpens: true, } _, err := client.SendEmail(context.Background(), email) if err != nil { panic(err) } } ``` -------------------------------- ### Get Current Server Source: https://github.com/mrz1836/postmark/blob/master/README.md Retrieves details about the currently configured server. ```APIDOC ## GET /server ### Description Retrieves details about the currently configured server. ### Method GET ### Endpoint /server ``` -------------------------------- ### Run Go Benchmarks Source: https://github.com/mrz1836/postmark/blob/master/README.md Executes the Go benchmarks for the project. These benchmarks measure real API client performance, including HTTP request setup, JSON marshaling/unmarshalling, and response processing against mock servers. ```bash magex bench ``` -------------------------------- ### Manage Servers with Postmark API Source: https://context7.com/mrz1836/postmark/llms.txt Shows how to manage Postmark servers, including getting current server details, editing server settings, creating sandbox servers, listing all servers, and deleting servers. Requires both server and account tokens. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "account-token") ctx := context.Background() // Current server (server token scoped) cur, err := client.GetCurrentServer(ctx) if err != nil { log.Fatal(err) } fmt.Printf("Current server: %s (ID=%d, SMTP=%v)\n", cur.Name, cur.ID, cur.SMTPAPIActivated) // Enable open tracking on current server _, _ = client.EditCurrentServer(ctx, postmark.Server{ Name: cur.Name, TrackOpens: true, TrackLinks: "HtmlAndText", }) // Create a sandbox server for testing sandbox, err := client.CreateServer(ctx, postmark.ServerCreateRequest{ Name: "test-sandbox", DeliveryType: "Sandbox", Color: "Blue", TrackOpens: true, }) if err != nil { log.Fatal(err) } fmt.Printf("Created sandbox server ID=%d\n", sandbox.ID) // List all servers (optionally filter by name) list, err := client.GetServers(ctx, 50, 0, "") if err != nil { log.Fatal(err) } fmt.Printf("Total servers: %d\n", list.TotalCount) // Cleanup sandbox _ = client.DeleteServer(ctx, sandbox.ID) } ``` -------------------------------- ### Deploy Library with Goreleaser Source: https://github.com/mrz1836/postmark/blob/master/README.md Uses goreleaser for streamlined binary and library deployment to GitHub. Install goreleaser via Homebrew. The release process is defined in .goreleaser.yml. Create and push a new Git tag to trigger the release. ```bash brew install goreleaser ``` ```bash magex version:bump bump=patch push=true branch=master ``` -------------------------------- ### Get a Server Source: https://github.com/mrz1836/postmark/blob/master/README.md Retrieves details for a specific server by its ID. ```APIDOC ## GET /servers/{serverid} ### Description Retrieves details for a specific server by its ID. ### Method GET ### Endpoint /servers/{serverid} ``` -------------------------------- ### Get Outbound Statistics with Postmark Go Source: https://context7.com/mrz1836/postmark/llms.txt Retrieves various outbound email statistics like sent, bounced, and spam complaints. Supports filtering by date range and tag. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") ctx := context.Background() opts := map[string]interface{}{ "fromdate": "2024-01-01", "todate": "2024-12-31", "tag": "newsletter", } // Overview outbound, err := client.GetOutboundStats(ctx, opts) if err != nil { log.Fatal(err) } fmt.Printf("Sent=%d Bounced=%d BounceRate=%.2f%% SpamComplaints=%d\n", outbound.Sent, outbound.Bounced, outbound.BounceRate, outbound.SpamComplaints) fmt.Printf("Opens=%d UniqueOpens=%d\n", outbound.Opens, outbound.UniqueOpens) // Daily sent counts sent, _ := client.GetSentCounts(ctx, opts) fmt.Printf("Total sent: %d across %d days\n", sent.Sent, len(sent.Days)) // Bounce breakdown bounces, _ := client.GetBounceCounts(ctx, opts) fmt.Printf("HardBounce=%d SoftBounce=%d SMTPError=%d\n", bounces.HardBounce, bounces.SoftBounce, bounces.SMTPApiError) // Open platform distribution platforms, _ := client.GetPlatformCounts(ctx, opts) fmt.Printf("Platforms — Desktop=%d Mobile=%d WebMail=%d Unknown=%d\n", platforms.Desktop, platforms.Mobile, platforms.WebMail, platforms.Unknown) // Click stats clicks, _ := client.GetClickCounts(ctx, opts) fmt.Printf("Clicks=%d Unique=%d\n", clicks.Clicks, clicks.Unique) browsers, _ := client.GetBrowserFamilyCounts(ctx, opts) fmt.Printf("Browser — Chrome=%d Safari=%d Firefox=%d\n", browsers.Chrome, browsers.Safari, browsers.Firefox) clickLoc, _ := client.GetClickLocationCounts(ctx, opts) fmt.Printf("Click location — HTML=%d Text=%d\n", clickLoc.HTML, clickLoc.Text) emailClients, _ := client.GetEmailClientCounts(ctx, opts) fmt.Printf("Email clients — Outlook=%d Gmail=%d AppleMail=%d\n", emailClients.Outlook, emailClients.Gmail, emailClients.AppleMail) } ``` -------------------------------- ### Get Outbound Message Clicks with Postmark Go Client Source: https://context7.com/mrz1836/postmark/llms.txt Retrieve link click events for outbound messages. Supports filtering by recipient, tag, client name, platform, and message stream. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") ctx := context.Background() // All clicks with filters clicks, total, err := client.GetOutboundMessagesClicks(ctx, 100, 0, map[string]interface{}{ "tag": "newsletter", "platform": "Desktop", "client_name": "Chrome", "messagestream": "outbound", }) if err != nil { log.Fatal(err) } fmt.Printf("Clicks: %d / %d\n", len(clicks), total) for _, c := range clicks { fmt.Printf(" %s clicked %s at %s (geo: %s, %s)\n", c.Recipient, c.OriginalLink, c.ReceivedAt.Format("2006-01-02"), c.Geo["City"], c.Geo["Country"]) } // Clicks for a specific message msgClicks, msgTotal, err := client.GetOutboundMessageClicks(ctx, "msg-id-xyz", 50, 0) if err != nil { log.Fatal(err) } fmt.Printf("Clicks for message: %d / %d\n", len(msgClicks), msgTotal) } ``` -------------------------------- ### Construct Postmark Client Source: https://context7.com/mrz1836/postmark/llms.txt Initializes a Postmark client with server and account tokens. Demonstrates setting a custom HTTP client with a timeout and verifying connectivity by fetching the current server details. Handles API errors by checking for the `APIError` type. ```go package main import ( "context" "fmt" "log" "net/http" "time" "github.com/mrz1836/postmark" ) func main() { // Default client client := postmark.NewClient("your-server-token", "your-account-token") // Custom HTTP client with timeout client.HTTPClient = &http.Client{Timeout: 10 * time.Second} // Override base URL (e.g., for testing) // client.BaseURL = "https://api.staging.postmarkapp.com" // Verify connectivity by fetching the current server server, err := client.GetCurrentServer(context.Background()) if err != nil { // APIError carries ErrorCode and Message if apiErr, ok := err.(postmark.APIError); ok { log.Fatalf("Postmark API error %d: %s", apiErr.ErrorCode, apiErr.Message) } log.Fatal(err) } fmt.Printf("Connected to server: %s (ID: %d)\n", server.Name, server.ID) // Output: Connected to server: My Production Server (ID: 42) } ``` -------------------------------- ### Create a Server Source: https://github.com/mrz1836/postmark/blob/master/README.md Creates a new server configuration. ```APIDOC ## POST /servers ### Description Creates a new server configuration. ### Method POST ### Endpoint /servers ``` -------------------------------- ### Copy Templates Between Servers with Postmark Go Source: https://context7.com/mrz1836/postmark/llms.txt Use `PushTemplates` to copy templates. Set `PerformChanges: false` for a simulation before actual changes. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "account-token") // Dry run resp, err := client.PushTemplates(context.Background(), postmark.PushTemplatesRequest{ SourceServerID: 1001, DestinationServerID: 1002, PerformChanges: false, }) if err != nil { log.Fatal(err) } fmt.Printf("Simulation: %d templates would be affected\n", resp.TotalCount) for _, t := range resp.Templates { fmt.Printf(" %s -> action: %s\n", t.Name, t.Action) } // Actually push resp, err = client.PushTemplates(context.Background(), postmark.PushTemplatesRequest{ SourceServerID: 1001, DestinationServerID: 1002, PerformChanges: true, }) if err != nil { log.Fatal(err) } fmt.Printf("Push complete: %d templates processed\n", resp.TotalCount) } ``` -------------------------------- ### Get Outbound Message Opens with Postmark Go Client Source: https://context7.com/mrz1836/postmark/llms.txt Retrieve open events for all outbound messages or a specific message. Supports filtering by tag and recipient. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") ctx := context.Background() // All opens across the server opens, total, err := client.GetOutboundMessagesOpens(ctx, 50, 0, map[string]interface{}{ "tag": "newsletter", "recipient": "alice@example.com", }) if err != nil { log.Fatal(err) } fmt.Printf("Opens: %d / %d\n", len(opens), total) for _, o := range opens { fmt.Printf(" MessageID=%s FirstOpen=%v Platform=%s ReadSecs=%d\n", o.MessageID, o.FirstOpen, o.Platform, o.ReadSeconds) } // Opens for a specific message messageOpens, msgTotal, err := client.GetOutboundMessageOpens(ctx, "msg-id-abc", 10, 0) if err != nil { log.Fatal(err) } fmt.Printf("Opens for message: %d / %d\n", len(messageOpens), msgTotal) } ``` -------------------------------- ### Configure Postmark Webhooks Source: https://context7.com/mrz1836/postmark/llms.txt Shows how to list, create, fetch, and delete webhooks for a specific message stream. Requires a server token and context. Webhook triggers can be configured with fine-grained settings. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") ctx := context.Background() // List webhooks for a specific stream hooks, err := client.ListWebhooks(ctx, "outbound") if err != nil { log.Fatal(err) } fmt.Printf("Existing webhooks: %d\n", len(hooks)) // Create a new webhook hook, err := client.CreateWebhook(ctx, postmark.Webhook{ URL: "https://example.com/hooks/postmark", MessageStream: "outbound", HTTPAuth: &postmark.WebhookHTTPAuth{ Username: "webhookuser", Password: "s3cr3t", }, HTTPHeaders: []postmark.Header{ {Name: "X-Webhook-Secret", Value: "my-shared-secret"}, }, Triggers: postmark.WebhookTrigger{ Delivery: postmark.WebhookTriggerEnabled{Enabled: true}, Open: postmark.WebhookTriggerOpen{ WebhookTriggerEnabled: postmark.WebhookTriggerEnabled{Enabled: true}, PostFirstOpenOnly: true, }, Bounce: postmark.WebhookTriggerIncContent{ WebhookTriggerEnabled: postmark.WebhookTriggerEnabled{Enabled: true}, IncludeContent: true, }, SpamComplaint: postmark.WebhookTriggerIncContent{ WebhookTriggerEnabled: postmark.WebhookTriggerEnabled{Enabled: true}, IncludeContent: false, }, Click: postmark.WebhookTriggerEnabled{Enabled: true}, SubscriptionChange: postmark.WebhookTriggerEnabled{Enabled: true}, }, }) if err != nil { log.Fatal(err) } fmt.Printf("Created webhook ID=%d url=%s\n", hook.ID, hook.URL) // Fetch and delete fetched, _ := client.GetWebhook(ctx, hook.ID) fmt.Printf("Fetched: %s\n", fetched.URL) _ = client.DeleteWebhook(ctx, hook.ID) } ``` -------------------------------- ### View All Build Commands Source: https://github.com/mrz1836/postmark/blob/master/README.md Displays all available build commands for the project. This is useful for understanding the project's build and task automation capabilities. ```bash magex help ``` -------------------------------- ### Configure Custom HTTPClient with Postmark Go SDK Source: https://github.com/mrz1836/postmark/blob/master/README.md Demonstrates how to configure a custom HTTP client for the Postmark Go SDK, specifically for use within the Google App Engine environment. This allows for custom request handling and transport mechanisms. ```go package main import ( "github.com/mrz1836/postmark" "google.golang.org/appengine" "google.golang.org/appengine/urlfetch" ) // .... client := postmark.NewClient("[SERVER-TOKEN]", "[ACCOUNT-TOKEN]") ctx := appengine.NewContext(req) client.HTTPClient = urlfetch.Client(ctx) // ... ``` -------------------------------- ### Bounce API Operations Source: https://context7.com/mrz1836/postmark/llms.txt Provides methods to inspect and manage delivery failures, including retrieving delivery statistics, listing bounces, getting bounce details, activating bounces, and listing bounced tags. ```APIDOC ## GetDeliveryStats ### Description Retrieves an overview of delivery statistics, including inactive email counts and a breakdown of bounce types. ### Method GET ### Endpoint `/stats/outbound` ### Response #### Success Response (200) - **InactiveMails** (integer) - The total number of inactive email addresses. - **Bounces** (array) - A list of bounce types and their counts. - **Name** (string) - The name of the bounce type (e.g., "HardBounce", "SpamConfirmation"). - **Count** (integer) - The number of bounces for this type. ### Response Example ```json { "InactiveMails": 150, "Bounces": [ { "Name": "HardBounce", "Count": 120 }, { "Name": "SpamConfirmation", "Count": 30 } ] } ``` ``` ```APIDOC ## GetBounces ### Description Retrieves a paginated list of bounces with filtering capabilities. ### Method GET ### Endpoint `/bounces` ### Parameters #### Query Parameters - **type** (string) - Optional - Filters bounces by type (e.g., "HardBounce"). - **inactive** (boolean) - Optional - Filters for inactive bounces. - **emailFilter** (string) - Optional - Filters bounces by email address pattern. - **tag** (string) - Optional - Filters bounces by tag. - **fromdate** (string) - Optional - Filters bounces from a specific date (YYYY-MM-DD). - **todate** (string) - Optional - Filters bounces up to a specific date (YYYY-MM-DD). - **count** (integer) - Optional - The number of bounces to return per page (default 50). - **offset** (integer) - Optional - The number of bounces to skip (default 0). ### Response #### Success Response (200) - **bounces** (array) - A list of bounce objects. - **ID** (integer) - The unique identifier for the bounce. - **Email** (string) - The email address that bounced. - **BouncedAt** (string) - The timestamp when the bounce occurred. - **DumpAvailable** (boolean) - Indicates if the bounce dump is available. - **CanActivate** (boolean) - Indicates if the bounce can be activated. - **total** (integer) - The total number of bounces matching the filter. ### Response Example ```json { "bounces": [ { "ID": 12345, "Email": "user@example.com", "BouncedAt": "2024-01-15T10:30:00Z", "DumpAvailable": true, "CanActivate": true } ], "total": 100 } ``` ``` ```APIDOC ## GetBounce ### Description Retrieves detailed information for a specific bounce. ### Method GET ### Endpoint `/bounces/{ID}` ### Parameters #### Path Parameters - **ID** (integer) - Required - The ID of the bounce to retrieve. ### Response #### Success Response (200) - **ID** (integer) - The unique identifier for the bounce. - **Email** (string) - The email address that bounced. - **BouncedAt** (string) - The timestamp when the bounce occurred. - **DumpAvailable** (boolean) - Indicates if the bounce dump is available. - **CanActivate** (boolean) - Indicates if the bounce can be activated. ### Response Example ```json { "ID": 12345, "Email": "user@example.com", "BouncedAt": "2024-01-15T10:30:00Z", "DumpAvailable": true, "CanActivate": true } ``` ``` ```APIDOC ## GetBounceDump ### Description Retrieves the raw SMTP dump for a specific bounce. Only available within 30 days of the bounce. ### Method GET ### Endpoint `/bounces/{ID}/dump` ### Parameters #### Path Parameters - **ID** (integer) - Required - The ID of the bounce to retrieve the dump for. ### Response #### Success Response (200) - **dump** (string) - The raw SMTP dump content. ### Response Example ``` Received: by ... ... ``` ``` ```APIDOC ## ActivateBounce ### Description Reactivates a bounced email address, allowing it to receive emails again. ### Method PUT ### Endpoint `/bounces/{ID}/activate` ### Parameters #### Path Parameters - **ID** (integer) - Required - The ID of the bounce to activate. ### Response #### Success Response (200) - **Inactive** (boolean) - The new inactive status of the email address. - **Message** (string) - A confirmation message. ### Response Example ```json { "Inactive": false, "Message": "Bounce reactivated successfully." } ``` ``` ```APIDOC ## GetBouncedTags ### Description Retrieves a list of tags that have produced bounces. ### Method GET ### Endpoint `/bounces/tags` ### Response #### Success Response (200) - **tags** (array) - A list of tags associated with bounces. ### Response Example ```json ["billing", "notifications", "support"] ``` ``` -------------------------------- ### Manage Postmark Message Streams Source: https://context7.com/mrz1836/postmark/llms.txt Demonstrates how to list, create, edit, archive, and unarchive message streams using the Postmark Go client. Ensure you have a valid server token and context. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") ctx := context.Background() // List all streams (including archived) streams, err := client.ListMessageStreams(ctx, "All", true) if err != nil { log.Fatal(err) } for _, s := range streams { fmt.Printf("Stream %s (%s): %s\n", s.ID, s.Name, s.MessageStreamType) } // Create a new broadcast stream desc := "Monthly product newsletter" created, err := client.CreateMessageStream(ctx, postmark.CreateMessageStreamRequest{ ID: "newsletter-broadcast", Name: "Newsletter", Description: &desc, MessageStreamType: postmark.BroadcastMessageStreamType, SubscriptionManagementConfiguration: postmark.MessageStreamSubscriptionManagementConfiguration{ UnsubscribeHandlingType: postmark.PostmarkUnsubscribeHandlingType, }, }) if err != nil { log.Fatal(err) } fmt.Printf("Created stream: %s (ID: %s)\n", created.Name, created.ID) // Edit newDesc := "Monthly product newsletter — updated" updated, err := client.EditMessageStream(ctx, created.ID, postmark.EditMessageStreamRequest{ Name: "Newsletter v2", Description: &newDesc, SubscriptionManagementConfiguration: postmark.MessageStreamSubscriptionManagementConfiguration{ UnsubscribeHandlingType: postmark.PostmarkUnsubscribeHandlingType, }, }) if err != nil { log.Fatal(err) } fmt.Printf("Updated: %s\n", updated.Name) // Archive (recoverable for 45 days) archived, err := client.ArchiveMessageStream(ctx, created.ID) if err != nil { log.Fatal(err) } fmt.Printf("Archived, will purge on: %s\n", archived.ExpectedPurgeDate) // Restore before purge date restored, err := client.UnarchiveMessageStream(ctx, created.ID) if err != nil { log.Fatal(err) } fmt.Printf("Restored: %s (archived: %v)\n", restored.Name, restored.ArchivedAt != nil) } ``` -------------------------------- ### Run All Tests (Fast) Source: https://github.com/mrz1836/postmark/blob/master/README.md Executes all unit and fuzz tests in the project. This is the fastest way to run tests and is suitable for quick checks during development. ```bash magex test ``` -------------------------------- ### Create, Edit, and Delete Templates with Postmark Go Client Source: https://context7.com/mrz1836/postmark/llms.txt Performs CRUD operations on stored templates. `CreateTemplate` and `EditTemplate` return a subset of fields; use `GetTemplate` for full content. Ensure a valid server token is used. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") ctx := context.Background() // Create info, err := client.CreateTemplate(ctx, postmark.Template{ Name: "Password Reset", Alias: "password-reset", TemplateType: "Standard", LayoutTemplate: "base-layout", Subject: "Reset your {{company_name}} password", HTMLBody: "
Hi {{name}}, reset your password.
", TextBody: "Hi {{name}}, reset your password: {{reset_url}}", }) if err != nil { log.Fatal(err) } fmt.Printf("Created template ID=%d alias=%s\n", info.TemplateID, info.Alias) // Edit updated, err := client.EditTemplate(ctx, "password-reset", postmark.Template{ Subject: "Reset your {{company_name}} password — expires in 24 hours", HTMLBody: "Hi {{name}}, this link expires in 24h: Reset
", }) if err != nil { log.Fatal(err) } fmt.Printf("Updated template: %s\n", updated.Name) // Delete if err := client.DeleteTemplate(ctx, fmt.Sprintf("%d", info.TemplateID)); err != nil { log.Fatal(err) } fmt.Println("Template deleted") } ``` -------------------------------- ### NewClient - Construct a Postmark client Source: https://context7.com/mrz1836/postmark/llms.txt Constructs a *Client with a default http.Client and the Postmark base URL. You can assign a custom HTTPClient afterward to control timeouts, transport, or middleware. ```APIDOC ## NewClient ### Description Constructs a `*Client` with a default `http.Client` and the Postmark base URL. Assign a custom `HTTPClient` afterward to control timeouts, transport, or middleware (e.g., App Engine's `urlfetch`). ### Usage ```go package main import ( "context" "fmt" "log" "net/http" "time" "github.com/mrz1836/postmark" ) func main() { // Default client client := postmark.NewClient("your-server-token", "your-account-token") // Custom HTTP client with timeout client.HTTPClient = &http.Client{Timeout: 10 * time.Second} // Override base URL (e.g., for testing) // client.BaseURL = "https://api.staging.postmarkapp.com" // Verify connectivity by fetching the current server server, err := client.GetCurrentServer(context.Background()) if err != nil { // APIError carries ErrorCode and Message if apiErr, ok := err.(postmark.APIError); ok { log.Fatalf("Postmark API error %d: %s", apiErr.ErrorCode, apiErr.Message) } log.Fatal(err) } fmt.Printf("Connected to server: %s (ID: %d)\n", server.Name, server.ID) // Output: Connected to server: My Production Server (ID: 42) } ``` ``` -------------------------------- ### Validate Template Content with Postmark Go Client Source: https://context7.com/mrz1836/postmark/llms.txt Validates template content and renders previews. It returns per-field validation results, rendered content, and a suggested model schema. Ensure a valid server token is used. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") result, err := client.ValidateTemplate(context.Background(), postmark.ValidateTemplateBody{ Subject: "Hello {{name}}", HTMLBody: "Your code: {{code}}
", TextBody: "Welcome {{name}}! Your code: {{code}}", TestRenderModel: map[string]interface{}{ "name": "Alice", "code": "ABC123", }, InlineCSSForHTMLTestRender: true, }) if err != nil { log.Fatal(err) } fmt.Printf("All content valid: %v\n", result.AllContentIsValid) fmt.Printf("Subject rendered: %s\n", result.Subject.RenderedContent) fmt.Printf("HTML valid: %v\n", result.HTMLBody.ContentIsValid) for _, e := range result.HTMLBody.ValidationErrors { fmt.Printf(" HTML error line %d col %d: %s\n", e.Line, e.CharacterPosition, e.Message) } fmt.Printf("Suggested model: %v\n", result.SuggestedTemplateModel) // Output: // All content valid: true // Subject rendered: Hello Alice // HTML valid: true } ``` -------------------------------- ### Retrieve Email Templates with Postmark Go Client Source: https://context7.com/mrz1836/postmark/llms.txt Fetches a specific template by ID or alias, paginates all templates, or filters templates by type and layout. Ensure you have a valid server token. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") ctx := context.Background() // Get a specific template by ID string or alias tmpl, err := client.GetTemplate(ctx, "welcome-email") if err != nil { log.Fatal(err) } fmt.Printf("Template: %s (ID=%d, Active=%v)\n", tmpl.Name, tmpl.TemplateID, tmpl.Active) fmt.Printf("Subject: %s\n", tmpl.Subject) // List first 50 templates (all types) infos, total, err := client.GetTemplates(ctx, 50, 0) if err != nil { log.Fatal(err) } fmt.Printf("Found %d / %d templates\n", len(infos), total) // List only Layout templates layouts, layoutTotal, err := client.GetTemplatesFiltered(ctx, 50, 0, "Layout", "") if err != nil { log.Fatal(err) } fmt.Printf("Layout templates: %d / %d\n", len(layouts), layoutTotal) // List Standard templates that use a specific layout standards, _, err := client.GetTemplatesFiltered(ctx, 50, 0, "Standard", "base-layout") if err != nil { log.Fatal(err) } for _, t := range standards { fmt.Printf(" - %s (alias: %s)\n", t.Name, t.Alias) } } ``` -------------------------------- ### Send Emails in Batch with Postmark Go Source: https://context7.com/mrz1836/postmark/llms.txt Use `SendEmailBatch` to send up to 500 emails in a single request. Iterate through the responses to check for individual email errors. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") emails := []postmark.Email{ { From: "no-reply@example.com", To: "alice@example.com", Subject: "Welcome, Alice!", TextBody: "Thanks for signing up.", Tag: "welcome", }, { From: "no-reply@example.com", To: "bob@example.com", Subject: "Welcome, Bob!", TextBody: "Thanks for signing up.", Tag: "welcome", }, } responses, err := client.SendEmailBatch(context.Background(), emails) if err != nil { log.Fatalf("batch send request failed: %v", err) } for i, r := range responses { if r.ErrorCode != 0 { fmt.Printf("Email %d to %s failed (code %d): %s\n", i, r.To, r.ErrorCode, r.Message) continue } fmt.Printf("Email %d sent to %s, MessageID=%s\n", i, r.To, r.MessageID) } // Output: // Email 0 sent to alice@example.com, MessageID=... // Email 1 sent to bob@example.com, MessageID=... } ``` -------------------------------- ### PushTemplates Source: https://context7.com/mrz1836/postmark/llms.txt Copies templates between Postmark servers. It can be used to simulate the operation first by setting `PerformChanges` to `false`. ```APIDOC ## PushTemplates Posts to `PUT /templates/push` using the account token. Set `PerformChanges: false` to simulate the operation first. ### Method PUT ### Endpoint `/templates/push` ### Parameters #### Request Body - **SourceServerID** (integer) - Required - The ID of the source server. - **DestinationServerID** (integer) - Required - The ID of the destination server. - **PerformChanges** (boolean) - Required - If true, perform the changes; if false, simulate the operation. ### Request Example ```json { "SourceServerID": 1001, "DestinationServerID": 1002, "PerformChanges": false } ``` ### Response #### Success Response (200) - **TotalCount** (integer) - The total number of templates that would be affected. - **Templates** (array) - A list of templates and their actions. - **Name** (string) - The name of the template. - **Action** (string) - The action to be performed on the template (e.g., "copy", "update"). ### Response Example ```json { "TotalCount": 5, "Templates": [ { "Name": "Welcome Email", "Action": "copy" }, { "Name": "Password Reset", "Action": "update" } ] } ``` ``` -------------------------------- ### List Servers Source: https://github.com/mrz1836/postmark/blob/master/README.md Retrieves a list of all available servers. ```APIDOC ## GET /servers ### Description Retrieves a list of all available servers. ### Method GET ### Endpoint /servers ``` -------------------------------- ### Manage Sender Signatures with Postmark API Source: https://context7.com/mrz1836/postmark/llms.txt Demonstrates creating, listing, updating, retrieving, and deleting sender signatures using the Postmark Go client. Requires an account token. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("", "account-token") ctx := context.Background() // List signatures list, err := client.GetSenderSignatures(ctx, 50, 0) if err != nil { log.Fatal(err) } fmt.Printf("Sender signatures: %d / %d\n", len(list.SenderSignatures), list.TotalCount) // Create sig, err := client.CreateSenderSignature(ctx, postmark.SenderSignatureCreateRequest{ FromEmail: "billing@example.com", Name: "Example Billing", ReplyToEmail: "support@example.com", ReturnPathDomain: "pm-bounces.example.com", ConfirmationPersonalNote: "Used for automated billing emails from Example Inc.", }) if err != nil { log.Fatal(err) } fmt.Printf("Created signature ID=%d for %s (confirmed: %v)\n", sig.ID, sig.FromEmail, sig.Confirmed) // Resend confirmation if not yet confirmed if !sig.Confirmed { _ = client.ResendSenderSignatureConfirmation(ctx, sig.ID) fmt.Println("Confirmation email resent") } // Edit updated, _ := client.EditSenderSignature(ctx, sig.ID, postmark.SenderSignatureEditRequest{ Name: "Example Billing v2", ReplyToEmail: "help@example.com", }) fmt.Printf("Updated name: %s\n", updated.Name) // Get full details details, _ := client.GetSenderSignature(ctx, sig.ID) fmt.Printf("DKIM host: %s DKIM status: %s\n", details.DKIMHost, details.DKIMUpdateStatus) // Delete _ = client.DeleteSenderSignature(ctx, sig.ID) } ``` -------------------------------- ### Manage Inbound Rule Triggers with Postmark API Source: https://context7.com/mrz1836/postmark/llms.txt Demonstrates how to manage inbound email blocking rules, including listing existing rules, creating new rules for specific email addresses or domains, and deleting rules. Requires a server token. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") ctx := context.Background() // List current rules rules, total, err := client.GetInboundRuleTriggers(ctx, 50, 0) if err != nil { log.Fatal(err) } fmt.Printf("Inbound rules: %d / %d\n", len(rules), total) // Block a specific address emailRule, err := client.CreateInboundRuleTrigger(ctx, "noreply@spammer.com") if err != nil { log.Fatal(err) } fmt.Printf("Created rule ID=%d: %s\n", emailRule.ID, emailRule.Rule) // Block an entire domain with wildcard domainRule, err := client.CreateInboundRuleTrigger(ctx, "*.disposable-mail.com") if err != nil { log.Fatal(err) } fmt.Printf("Created rule ID=%d: %s\n", domainRule.ID, domainRule.Rule) // Remove rules if err := client.DeleteInboundRuleTrigger(ctx, emailRule.ID); err != nil { log.Fatal(err) } if err := client.DeleteInboundRuleTrigger(ctx, domainRule.ID); err != nil { log.Fatal(err) } fmt.Println("Rules deleted") } ``` -------------------------------- ### Send Transactional Email with Attachments Source: https://context7.com/mrz1836/postmark/llms.txt Sends a single transactional email using the Postmark client. Supports various email fields like To, Cc, Subject, HTML/Text bodies, tags, tracking, inline CSS, message streams, reply-to, custom headers, metadata, and attachments. Reads attachment content from a file and encodes it in base64. Handles potential sending errors. ```go package main import ( "context" "encoding/base64" "fmt" "log" "os" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient(os.Getenv("POSTMARK_SERVER_TOKEN"), "") // Read a PDF attachment pdfData, _ := os.ReadFile("invoice.pdf") email := postmark.Email{ From: "billing@example.com", To: "customer@example.com", Cc: "accounts@example.com", Subject: "Your invoice #1234", HTMLBody: "Please find your invoice attached.
", TextBody: "Invoice\n\nPlease find your invoice attached.", Tag: "billing", TrackOpens: true, TrackLinks: "HtmlAndText", InlineCSS: true, MessageStream: "outbound", ReplyTo: "support@example.com", Headers: []postmark.Header{ {Name: "X-Invoice-ID", Value: "1234"}, }, Metadata: map[string]string{ "customer_id": "cust_abc123", "invoice_id": "inv_1234", }, Attachments: []postmark.Attachment{ { Name: "invoice-1234.pdf", Content: base64.StdEncoding.EncodeToString(pdfData), ContentType: "application/pdf", }, }, } res, err := client.SendEmail(context.Background(), email) if err != nil { log.Fatalf("send failed: %v", err) } fmt.Printf("Sent! MessageID=%s SubmittedAt=%s\n", res.MessageID, res.SubmittedAt) // Output: Sent! MessageID=abc-123-def SubmittedAt=2024-05-01 12:00:00 +0000 UTC } ``` -------------------------------- ### Manage Bounces with Postmark Go Client Source: https://context7.com/mrz1836/postmark/llms.txt Inspect and manage delivery failures using various bounce-related functions. `GetBounces` accepts a filter map for precise querying. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("server-token", "") ctx := context.Background() // Overview stats, err := client.GetDeliveryStats(ctx) if err != nil { log.Fatal(err) } fmt.Printf("Inactive addresses: %d\n", stats.InactiveMails) for _, bt := range stats.Bounces { fmt.Printf(" %s: %d\n", bt.Name, bt.Count) } // Paginated hard bounces bounces, total, err := client.GetBounces(ctx, 25, 0, map[string]interface{}{ "type": "HardBounce", "inactive": true, "emailFilter": "@example.com", }) if err != nil { log.Fatal(err) } fmt.Printf("Hard bounces: %d / %d\n", len(bounces), total) if len(bounces) > 0 { b := bounces[0] // Detailed single bounce detail, _ := client.GetBounce(ctx, b.ID) fmt.Printf("Bounce %d: %s at %s\n", detail.ID, detail.Email, detail.BouncedAt) // Raw SMTP dump (only available within 30 days) if detail.DumpAvailable { dump, _ := client.GetBounceDump(ctx, detail.ID) fmt.Printf("Dump length: %d bytes\n", len(dump)) } // Reactivate so the address can receive email again if detail.CanActivate { activated, msg, _ := client.ActivateBounce(ctx, detail.ID) fmt.Printf("Activated: %s, inactive=%v\n", msg, activated.Inactive) } } // Tags that have produced bounces tags, _ := client.GetBouncedTags(ctx) fmt.Printf("Bounced tags: %v\n", tags) } ``` -------------------------------- ### Manage Postmark Domains Source: https://context7.com/mrz1836/postmark/llms.txt Perform account-level operations to manage sending domains, including creation, verification, and DKIM key rotation. Requires an account token. ```go package main import ( "context" "fmt" "log" "github.com/mrz1836/postmark" ) func main() { client := postmark.NewClient("", "account-token") ctx := context.Background() // List list, err := client.GetDomains(ctx, 50, 0) if err != nil { log.Fatal(err) } fmt.Printf("Domains: %d / %d\n", len(list.Domains), list.TotalCount) // Create domain, err := client.CreateDomain(ctx, postmark.DomainCreateRequest{ Name: "transactional.example.com", ReturnPathDomain: "pm-bounces.example.com", }) if err != nil { log.Fatal(err) } fmt.Printf("Created domain %s (ID=%d)\n", domain.Name, domain.ID) fmt.Printf("Add DNS TXT: %s value: %s\n", domain.DKIMHost, domain.DKIMTextValue) fmt.Printf("Add DNS CNAME: %s -> pm.mtasv.net\n", domain.ReturnPathDomain) // Verify DNS records dkim, _ := client.VerifyDKIMStatus(ctx, domain.ID) fmt.Printf("DKIM verified: %v (status: %s)\n", dkim.DKIMVerified, dkim.DKIMUpdateStatus) rp, _ := client.VerifyReturnPath(ctx, domain.ID) fmt.Printf("Return-Path verified: %v\n", rp.ReturnPathDomainVerified) // Rotate DKIM keys rotated, _ := client.RotateDKIM(ctx, domain.ID) fmt.Printf("Rotation pending host: %s\n", rotated.DKIMPendingHost) // Edit return-path edited, _ := client.EditDomain(ctx, domain.ID, postmark.DomainEditRequest{ ReturnPathDomain: "bounces.example.com", }) fmt.Printf("Updated return-path: %s\n", edited.ReturnPathDomain) // Cleanup _ = client.DeleteDomain(ctx, domain.ID) } ```