Go
Official Unsent Go SDK for sending emails and managing contacts.
This guide shows how to install and use the official unsent Go SDK.
Installation
Install the SDK using go get to add it to your project's dependencies:
go get github.com/souravsspace/unsent-go/pkg/unsentInitialize
To start using the SDK, you need to create a client instance. You'll need your API key, which you can find in your Unsent dashboard.
Import the package and create a new client using unsent.NewClient. You can pass the API key directly, or if you have the UNSENT_API_KEY environment variable set, you can pass an empty string.
package main
import (
"log"
"github.com/souravsspace/unsent-go/pkg/unsent"
)
func main() {
// Initialize with API key
client, err := unsent.NewClient("un_xxx")
// Or use environment variable UNSENT_API_KEY
// client, err := unsent.NewClient("")
if err != nil {
log.Fatal(err)
}
}Send an email
Now you're ready to send your first email. Use the client.Emails.Send method with a SendEmailJSONBody struct.
Here is a simple example of sending an HTML email:
package main
import (
"fmt"
"log"
"github.com/souravsspace/unsent-go/pkg/unsent"
)
// Helper function for string pointers
func stringPtr(s string) *string {
return &s
}
func main() {
// Initialize the client
client, err := unsent.NewClient("un_xxx")
if err != nil {
log.Fatal(err)
}
// Send the email
email, err := client.Emails.Send(unsent.SendEmailJSONBody{
To: toEmail("user@example.com"),
From: "no-reply@yourdomain.com",
Subject: stringPtr("Welcome"),
Html: stringPtr("<strong>Hello!</strong>"),
})
if err != nil {
log.Printf("Error: %v", err)
} else {
fmt.Printf("Email sent! ID: %s\n", email.EmailID)
}
}
// Helper to construct email recipient
func toEmail(email string) unsent.SendEmailJSONBody_To {
var to unsent.SendEmailJSONBody_To
json.Unmarshal([]byte(`"`+email+`"`), &to)
return to
}With attachments and scheduling
You can also send emails with attachments and schedule them for a later time.
- Attachments: Provide base64-encoded content
- Scheduling: Set the
ScheduledAtfield with atime.Timepointer
import "time"
// Schedule for 10 minutes from now
scheduledTime := time.Now().Add(10 * time.Minute)
email, err := client.Emails.Create(unsent.SendEmailJSONBody{
To: toEmail("user@example.com"),
From: "no-reply@yourdomain.com",
Subject: stringPtr("Report"),
Text: stringPtr("See attached."),
Attachments: &[]map[string]interface{}{
{
"filename": "report.txt",
"content": "SGVsbG8gd29ybGQ=", // Base64 encoded
},
},
ScheduledAt: &scheduledTime,
})Batch send
If you need to send multiple emails at once, use the client.Emails.Batch method.
batchEmails := unsent.SendBatchEmailsJSONBody{
Emails: []unsent.SendBatchEmailsJSONBody_Emails_Item{
{
To: toEmail("a@example.com"),
From: "no-reply@yourdomain.com",
Subject: stringPtr("Email A"),
Html: stringPtr("<p>Content A</p>"),
},
{
To: toEmail("b@example.com"),
From: "no-reply@yourdomain.com",
Subject: stringPtr("Email B"),
Html: stringPtr("<p>Content B</p>"),
},
},
}
response, err := client.Emails.Batch(batchEmails)
if err != nil {
log.Printf("Error: %v", err)
} else {
fmt.Printf("Sent %d emails\n", len(response.Emails))
}Idempotent Retries
To safely retry requests, you can use unsent.WithIdempotencyKey. This ensures that duplicate requests with the same key won't result in duplicate emails.
// For single email
client.Emails.Send(email, unsent.WithIdempotencyKey("unique-key-123"))
// For batch emails
client.Emails.Batch(emails, unsent.WithIdempotencyKey("batch-unique-key-123"))Retrieve and manage emails
You can retrieve the status of sent emails, update their scheduled time, or cancel them if they haven't been sent yet.
List emails
Retrieve a list of sent emails with pagination:
emails, err := client.Emails.List(unsent.ListEmailsParams{
Page: stringPtr("1"),
Limit: stringPtr("50"),
})
if err != nil {
log.Printf("Error: %v", err)
} else {
for _, email := range *emails {
fmt.Printf("Email ID: %s, Status: %s\n", email.ID, email.Status)
}
}Get an email
To check the status of a specific email, use client.Emails.Get with the email ID:
email, err := client.Emails.Get("email_123")
if err != nil {
log.Printf("Error: %v", err)
} else {
fmt.Printf("Email status: %s\n", email.Status)
}Update schedule time
If you need to change when a scheduled email will be sent:
import "time"
newTime := time.Now().Add(1 * time.Hour)
response, err := client.Emails.Update("email_123", unsent.UpdateEmailJSONBody{
ScheduledAt: &newTime,
})Cancel a scheduled email
To stop a scheduled email from being sent:
response, err := client.Emails.Cancel("email_123")
if err != nil {
log.Printf("Error: %v", err)
} else {
fmt.Println("Email cancelled successfully")
}Get bounced emails
Retrieve emails that bounced:
func float32Ptr(f float32) *float32 {
return &f
}
bounces, err := client.Emails.GetBounces(unsent.GetBouncesParams{
Page: float32Ptr(1.0),
Limit: float32Ptr(20.0),
})Get spam complaints
Retrieve emails marked as spam:
complaints, err := client.Emails.GetComplaints(unsent.GetComplaintsParams{
Page: float32Ptr(1.0),
Limit: float32Ptr(20.0),
})Get unsubscribes
Retrieve unsubscribed contacts:
unsubscribes, err := client.Emails.GetUnsubscribes(unsent.GetUnsubscribesParams{
Page: float32Ptr(1.0),
Limit: float32Ptr(20.0),
})Contact Books
Manage contact books to organize your contacts.
List contact books
books, err := client.ContactBooks.List()
if err != nil {
log.Printf("Error: %v", err)
} else {
for _, book := range *books {
fmt.Printf("Book: %s (ID: %s)\n", book.Name, book.ID)
}
}Create a contact book
book, err := client.ContactBooks.Create(unsent.CreateContactBookJSONBody{
Name: "My Contacts",
Emoji: stringPtr("๐ง"),
})Get contact book details
book, err := client.ContactBooks.Get("book_123")Update a contact book
response, err := client.ContactBooks.Update("book_123", unsent.UpdateContactBookJSONBody{
Name: stringPtr("Updated Name"),
})Delete a contact book
response, err := client.ContactBooks.Delete("book_123")Contacts
Manage your audience by creating and updating contacts. Contacts must belong to a contact book.
List contacts
Retrieve contacts from a contact book with pagination:
contacts, err := client.Contacts.List("book_123", unsent.GetContactsParams{
Page: float32Ptr(1.0),
Limit: float32Ptr(50.0),
})Create a contact
Add a new contact to a specific contact book:
contact, err := client.Contacts.Create("book_123", unsent.CreateContactJSONBody{
Email: "user@example.com",
FirstName: stringPtr("Jane"),
LastName: stringPtr("Doe"),
Metadata: &map[string]string{
"plan": "pro",
},
})Get a contact
Retrieve details about a specific contact:
contact, err := client.Contacts.Get("book_123", "contact_456")Update a contact
Update a contact's information:
response, err := client.Contacts.Update("book_123", "contact_456", unsent.UpdateContactJSONBody{
FirstName: stringPtr("John"),
Metadata: &map[string]string{
"plan": "enterprise",
},
})Upsert a contact
Create a contact if they don't exist, or update them if they do:
contact, err := client.Contacts.Upsert("book_123", "contact_456", unsent.UpsertContactJSONBody{
Email: "user@example.com",
FirstName: stringPtr("Jane"),
})Delete a contact
Remove a contact from a book:
response, err := client.Contacts.Delete("book_123", "contact_456")Campaigns
Campaigns allow you to send emails to an entire contact book.
List campaigns
campaigns, err := client.Campaigns.List()Create a campaign
Create a new campaign by specifying the content and the target contact book ID:
campaign, err := client.Campaigns.Create(unsent.CreateCampaignJSONBody{
Name: "Welcome Series",
Subject: "Welcome!",
Html: stringPtr("<p>Thanks for joining us!</p>"),
From: "welcome@yourdomain.com",
ContactBookId: "book_123",
})Get campaign details
campaign, err := client.Campaigns.Get("campaign_123")Schedule a campaign
Once created, you can schedule the campaign to be sent at a specific time:
response, err := client.Campaigns.Schedule("campaign_123", unsent.ScheduleCampaignJSONBody{
ScheduledAt: stringPtr("2024-12-01T10:00:00Z"),
})Pause and resume campaigns
You can pause a running or scheduled campaign and resume it later:
// Pause
pauseResp, err := client.Campaigns.Pause("campaign_123")
// Resume
resumeResp, err := client.Campaigns.Resume("campaign_123")Domains
Manage the domains you use to send emails.
List domains
Retrieve a list of all your domains and their verification status:
domains, err := client.Domains.List()
if err != nil {
log.Printf("Error: %v", err)
} else {
for _, domain := range *domains {
fmt.Printf("Domain: %s, Status: %s\n", domain.Domain, domain.Status)
}
}Create a domain
Add a new domain to your account:
domain, err := client.Domains.Create(unsent.CreateDomainJSONBody{
Domain: "yourdomain.com",
})Get domain details
domain, err := client.Domains.Get("domain_123")Verify a domain
Trigger domain verification:
response, err := client.Domains.Verify("domain_123")Delete a domain
Remove a domain from your account:
response, err := client.Domains.Delete("domain_123")Analytics
Get insights into your email performance.
Get analytics overview
analytics, err := client.Analytics.Get()
if err != nil {
log.Printf("Error: %v", err)
} else {
fmt.Printf("Total: %d, Sent: %d, Delivered: %d, Opened: %d\n",
analytics.Total, analytics.Sent, analytics.Delivered, analytics.Opened)
}SMTP
You can also send emails via SMTP using Unsent's SMTP server.
import (
"fmt"
"net/smtp"
)
func sendViaSMTP(apiKey, from, to, subject, body string) error {
// SMTP configuration
smtpHost := "smtp.unsent.dev"
smtpPort := "587"
smtpUser := "apikey"
// Authentication
auth := smtp.PlainAuth("", smtpUser, apiKey, smtpHost)
// Email content
msg := []byte("To: " + to + "\r\n" +
"From: " + from + "\r\n" +
"Subject: " + subject + "\r\n" +
"MIME-Version: 1.0\r\n" +
"Content-Type: text/html; charset=UTF-8\r\n" +
"\r\n" +
body + "\r\n")
// Send email
addr := fmt.Sprintf("%s:%s", smtpHost, smtpPort)
return smtp.SendMail(addr, auth, from, []string{to}, msg)
}Error handling
The SDK supports different ways of handling errors.
Standard Error Handling (Default)
By default, SDK methods return an *APIError if the API request fails or returns a non-2xx status code:
import "github.com/souravsspace/unsent-go/pkg/unsent"
client, err := unsent.NewClient("un_xxx")
if err != nil {
log.Fatal(err)
}
email, err := client.Emails.Get("email_123")
if err != nil {
// err is *unsent.APIError
fmt.Printf("API Error: %s - %s\n", err.Code, err.Message)
}Disable Automatic Error Raising
If you prefer to handle HTTP errors manually without the SDK treating non-2xx responses as errors, you can use unsent.WithRaiseOnError(false):
client, err := unsent.NewClient("un_xxx", unsent.WithRaiseOnError(false))Advanced Configuration
For advanced use cases, such as adding custom timeouts, proxies, or changing the base URL, you can provide options to NewClient.
Custom HTTP Client
import (
"net/http"
"time"
)
// Create a custom HTTP client with a timeout
httpClient := &http.Client{
Timeout: 30 * time.Second,
}
// Initialize the SDK with the custom client
client, err := unsent.NewClient("un_xxx", unsent.WithHTTPClient(httpClient))Custom Base URL
If you need to point the SDK to a different URL (e.g. for testing), you can use WithBaseURL:
client, err := unsent.NewClient("un_xxx", unsent.WithBaseURL("https://api.example.com"))Complete Example
Here's a complete example demonstrating multiple SDK features:
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/souravsspace/unsent-go/pkg/unsent"
)
func main() {
// Initialize client
client, err := unsent.NewClient("un_xxx")
if err != nil {
log.Fatal(err)
}
// Send an email with idempotency
email, err := client.Emails.Send(
unsent.SendEmailJSONBody{
To: toEmail("user@example.com"),
From: "hello@yourdomain.com",
Subject: stringPtr("Welcome!"),
Html: stringPtr("<h1>Hello!</h1><p>Welcome to our service.</p>"),
},
unsent.WithIdempotencyKey("welcome-user-123"),
)
if err != nil {
log.Printf("Error sending email: %v", err)
return
}
fmt.Printf("โ
Email sent! ID: %s\n", email.EmailID)
// List recent emails
emails, err := client.Emails.List(unsent.ListEmailsParams{
Page: stringPtr("1"),
Limit: stringPtr("10"),
})
if err == nil {
fmt.Printf("๐ง Found %d recent emails\n", len(*emails))
}
// Get analytics
analytics, err := client.Analytics.Get()
if err == nil {
fmt.Printf("๐ Sent: %d, Delivered: %d, Opened: %d\n",
analytics.Sent, analytics.Delivered, analytics.Opened)
}
}
// Helper functions
func stringPtr(s string) *string {
return &s
}
func toEmail(email string) unsent.SendEmailJSONBody_To {
var to unsent.SendEmailJSONBody_To
json.Unmarshal([]byte(`"`+email+`"`), &to)
return to
}