Skip to main content
The Receiving API allows you to access inbound emails sent to your domains. This guide covers retrieving received emails and downloading attachments with the Resend Go SDK.

Overview

The Receiving service provides:
  • Access to inbound emails sent to your verified domains
  • Full email content including HTML, text, and headers
  • Attachment management with download URLs
  • Pagination for listing large volumes of received emails
Inbound email functionality must be enabled on your Resend account. Contact Resend support to enable this feature.

Accessing the Receiving Service

The Receiving service is accessed through the Client.Emails.Receiving interface.
Initialize Client
import (
    "github.com/resend/resend-go/v3"
)

client := resend.NewClient("re_123456789")

// Access receiving methods
email, err := client.Emails.Receiving.Get("email-id")

Retrieving a Received Email

Get the full content of a specific inbound email by ID.
Get Received Email
import (
    "context"
    "fmt"
)

ctx := context.Background()

email, err := client.Emails.Receiving.GetWithContext(ctx, "8136d3fb-0439-4b09-b939-b8436a3524b6")
if err != nil {
    panic(err)
}

fmt.Println("Subject:", email.Subject)
fmt.Println("From:", email.From)
fmt.Println("To:", email.To)
fmt.Println("Received:", email.CreatedAt)
fmt.Println("\nHTML Body:")
fmt.Println(email.Html)
fmt.Println("\nText Body:")
fmt.Println(email.Text)

ReceivedEmail Structure

The ReceivedEmail struct contains complete email information:
Id
string
Unique identifier for the received email
Object
string
Always “email” for received emails
To
[]string
Array of recipient email addresses
From
string
Sender email address
Subject
string
Email subject line
Html
string
HTML version of the email body
Text
string
Plain text version of the email body
Cc
[]string
Array of CC recipient email addresses
Bcc
[]string
Array of BCC recipient email addresses
ReplyTo
[]string
Array of reply-to email addresses
Headers
map[string]string
Email headers as key-value pairs
MessageId
string
Message-ID header value
CreatedAt
string
Timestamp when the email was received
Attachments
[]ReceivedAttachment
Array of attachment metadata
Raw
RawEmail
Raw email download information

Listing Received Emails

Retrieve all received emails with optional pagination.
emails, err := client.Emails.Receiving.List()
if err != nil {
    panic(err)
}

fmt.Printf("You have %d received email(s)\n", len(emails.Data))

for _, email := range emails.Data {
    fmt.Printf("\n[%s] %s\n", email.CreatedAt, email.Subject)
    fmt.Printf("  From: %s\n", email.From)
    fmt.Printf("  To: %v\n", email.To)
    fmt.Printf("  Attachments: %d\n", len(email.Attachments))
}

fmt.Printf("\nHas more: %v\n", emails.HasMore)
The list response uses ListReceivedEmail which omits Html, Text, and Headers fields for efficiency. Use Get() to retrieve full email content.

Working with Email Headers

Access email headers for advanced processing:
Accessing Email Headers
email, err := client.Emails.Receiving.Get("email-id")
if err != nil {
    panic(err)
}

fmt.Println("Email Headers:")
for key, value := range email.Headers {
    fmt.Printf("%s: %s\n", key, value)
}

// Access specific headers
if spfResult, ok := email.Headers["received-spf"]; ok {
    fmt.Println("SPF Result:", spfResult)
}

if dkimResult, ok := email.Headers["dkim-signature"]; ok {
    fmt.Println("DKIM Signature:", dkimResult)
}

Managing Attachments

Received emails can include attachments. The SDK provides methods to list and retrieve attachment details including download URLs.

Listing Attachments

email, err := client.Emails.Receiving.Get("email-id")
if err != nil {
    panic(err)
}

fmt.Printf("Email has %d attachment(s)\n", len(email.Attachments))

for _, att := range email.Attachments {
    fmt.Printf("\nAttachment: %s\n", att.Filename)
    fmt.Printf("  Type: %s\n", att.ContentType)
    fmt.Printf("  ID: %s\n", att.Id)
}

ReceivedAttachment Structure

Id
string
Unique identifier for the attachment
Filename
string
Original filename of the attachment
ContentType
string
MIME type of the attachment (e.g., “application/pdf”, “image/png”)
ContentDisposition
string
Content-Disposition header value (e.g., “attachment”, “inline”)
ContentId
string
Content-ID for inline attachments (used in HTML emails)

Downloading Attachments

Get attachment details including temporary download URLs.
Get Attachment Details
ctx := context.Background()
emailId := "8136d3fb-0439-4b09-b939-b8436a3524b6"
attachmentId := "att-123456"

attachment, err := client.Emails.Receiving.GetAttachmentWithContext(
    ctx,
    emailId,
    attachmentId,
)
if err != nil {
    panic(err)
}

fmt.Println("Filename:", attachment.Filename)
fmt.Println("Content Type:", attachment.ContentType)
fmt.Println("Download URL:", attachment.DownloadUrl)
fmt.Println("Expires At:", attachment.ExpiresAt)

EmailAttachment Structure

Id
string
Unique identifier for the attachment
Filename
string
Original filename of the attachment
ContentType
string
MIME type of the attachment
ContentDisposition
string
Content-Disposition header value
ContentId
string
Content-ID for inline attachments
DownloadUrl
string
Temporary pre-signed URL for downloading the attachment
ExpiresAt
string
Timestamp when the download URL expires

Downloading Attachment Files

Use the download URL to fetch attachment content:
Download Attachment
import (
    "io"
    "net/http"
    "os"
)

attachment, err := client.Emails.Receiving.GetAttachment(emailId, attachmentId)
if err != nil {
    panic(err)
}

// Download the file
resp, err := http.Get(attachment.DownloadUrl)
if err != nil {
    panic(err)
}
defer resp.Body.Close()

// Save to disk
file, err := os.Create(attachment.Filename)
if err != nil {
    panic(err)
}
defer file.Close()

bytesWritten, err := io.Copy(file, resp.Body)
if err != nil {
    panic(err)
}

fmt.Printf("Downloaded %d bytes to %s\n", bytesWritten, attachment.Filename)
Download URLs are temporary and expire after a set period. Always download attachments promptly or store the URLs for short-term use only.

Complete Example

Here’s a complete example demonstrating received email processing:
Complete Receiving Workflow
package main

import (
    "context"
    "fmt"
    "io"
    "net/http"
    "os"
    
    "github.com/resend/resend-go/v3"
)

func main() {
    ctx := context.Background()
    apiKey := os.Getenv("RESEND_API_KEY")
    client := resend.NewClient(apiKey)

    // 1. List all received emails
    fmt.Println("Fetching received emails...")
    emails, err := client.Emails.Receiving.ListWithContext(ctx)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("\nFound %d received email(s)\n", len(emails.Data))
    
    if len(emails.Data) == 0 {
        fmt.Println("No received emails found")
        return
    }

    // 2. Get details of the first email
    firstEmail := emails.Data[0]
    fmt.Printf("\nRetrieving full details for: %s\n", firstEmail.Subject)
    
    email, err := client.Emails.Receiving.GetWithContext(ctx, firstEmail.Id)
    if err != nil {
        panic(err)
    }

    // 3. Display email details
    fmt.Printf("\n=== Email Details ===\n")
    fmt.Printf("Subject: %s\n", email.Subject)
    fmt.Printf("From: %s\n", email.From)
    fmt.Printf("To: %v\n", email.To)
    fmt.Printf("Received: %s\n", email.CreatedAt)
    fmt.Printf("Message ID: %s\n", email.MessageId)
    
    if len(email.Cc) > 0 {
        fmt.Printf("CC: %v\n", email.Cc)
    }
    
    if len(email.ReplyTo) > 0 {
        fmt.Printf("Reply-To: %v\n", email.ReplyTo)
    }

    // 4. Display headers
    fmt.Printf("\n=== Headers ===\n")
    for key, value := range email.Headers {
        fmt.Printf("%s: %s\n", key, value)
    }

    // 5. Display body preview
    fmt.Printf("\n=== Body Preview ===\n")
    if len(email.Text) > 200 {
        fmt.Printf("%s...\n", email.Text[:200])
    } else {
        fmt.Println(email.Text)
    }

    // 6. Process attachments
    if len(email.Attachments) > 0 {
        fmt.Printf("\n=== Attachments (%d) ===\n", len(email.Attachments))
        
        for i, att := range email.Attachments {
            fmt.Printf("\n[%d] %s\n", i+1, att.Filename)
            fmt.Printf("    Type: %s\n", att.ContentType)
            fmt.Printf("    ID: %s\n", att.Id)
            
            // Get attachment with download URL
            fullAttachment, err := client.Emails.Receiving.GetAttachmentWithContext(
                ctx,
                email.Id,
                att.Id,
            )
            if err != nil {
                fmt.Printf("    Error: %v\n", err)
                continue
            }
            
            fmt.Printf("    Download URL: %s\n", fullAttachment.DownloadUrl)
            fmt.Printf("    Expires: %s\n", fullAttachment.ExpiresAt)
            
            // Download the attachment
            if err := downloadAttachment(fullAttachment); err != nil {
                fmt.Printf("    Download failed: %v\n", err)
            } else {
                fmt.Printf("    ✓ Downloaded successfully\n")
            }
        }
    } else {
        fmt.Println("\nNo attachments")
    }

    // 7. Access raw email
    if email.Raw.DownloadUrl != "" {
        fmt.Printf("\n=== Raw Email ===\n")
        fmt.Printf("Download URL: %s\n", email.Raw.DownloadUrl)
        fmt.Printf("Expires: %s\n", email.Raw.ExpiresAt)
    }

    // 8. List attachments using dedicated endpoint
    attachmentsList, err := client.Emails.Receiving.ListAttachmentsWithContext(ctx, email.Id)
    if err != nil {
        panic(err)
    }
    fmt.Printf("\nAttachments list returned %d item(s)\n", len(attachmentsList.Data))
}

func downloadAttachment(attachment *resend.EmailAttachment) error {
    resp, err := http.Get(attachment.DownloadUrl)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return fmt.Errorf("download failed with status: %s", resp.Status)
    }

    file, err := os.Create(attachment.Filename)
    if err != nil {
        return err
    }
    defer file.Close()

    _, err = io.Copy(file, resp.Body)
    return err
}

Processing Patterns

Auto-Response System

Auto-Responder
func processInboundEmails(client *resend.Client) {
    emails, err := client.Emails.Receiving.List()
    if err != nil {
        panic(err)
    }

    for _, email := range emails.Data {
        // Check if we've already processed this email
        if alreadyProcessed(email.Id) {
            continue
        }

        // Get full email details
        fullEmail, err := client.Emails.Receiving.Get(email.Id)
        if err != nil {
            log.Printf("Error retrieving email %s: %v", email.Id, err)
            continue
        }

        // Send auto-response
        _, err = client.Emails.Send(&resend.SendEmailRequest{
            From:    "[email protected]",
            To:      []string{fullEmail.From},
            Subject: fmt.Sprintf("Re: %s", fullEmail.Subject),
            Html:    generateAutoResponseHTML(fullEmail),
        })

        if err != nil {
            log.Printf("Failed to send auto-response: %v", err)
        } else {
            markAsProcessed(email.Id)
        }
    }
}

Support Ticket Creation

Ticket System Integration
func createSupportTickets(client *resend.Client) {
    emails, err := client.Emails.Receiving.List()
    if err != nil {
        panic(err)
    }

    for _, email := range emails.Data {
        fullEmail, err := client.Emails.Receiving.Get(email.Id)
        if err != nil {
            continue
        }

        // Create support ticket
        ticket := SupportTicket{
            Subject:     fullEmail.Subject,
            From:        fullEmail.From,
            Body:        fullEmail.Text,
            HTMLBody:    fullEmail.Html,
            ReceivedAt:  fullEmail.CreatedAt,
            MessageId:   fullEmail.MessageId,
        }

        // Download attachments
        for _, att := range fullEmail.Attachments {
            attachment, err := client.Emails.Receiving.GetAttachment(
                fullEmail.Id,
                att.Id,
            )
            if err != nil {
                continue
            }

            ticket.Attachments = append(ticket.Attachments, TicketAttachment{
                Filename:    attachment.Filename,
                ContentType: attachment.ContentType,
                URL:         attachment.DownloadUrl,
            })
        }

        // Save to ticket system
        if err := saveTicket(ticket); err != nil {
            log.Printf("Failed to create ticket: %v", err)
        }
    }
}

Best Practices

Use Pagination

Always use pagination when listing large volumes of received emails to avoid memory issues.

Download Attachments Promptly

Attachment download URLs expire. Download and store attachments as soon as possible.

Track Processed Emails

Maintain a record of processed email IDs to avoid duplicate processing.

Handle Errors Gracefully

Implement robust error handling for network issues and missing emails.

Parse Headers Carefully

Check for header existence before accessing to avoid nil pointer errors.

Use Context Timeouts

Set appropriate timeouts when processing emails to prevent hanging operations.

Next Steps

Webhooks

Set up webhooks to receive notifications of inbound emails

Sending Emails

Learn how to send emails with attachments

Receiving Example

View the complete receiving emails example

API Reference

View the complete Receiving API reference

Build docs developers (and LLMs) love