├── .env_sample ├── helpers ├── inbound │ ├── sample_data │ │ ├── default_data_with_attachments.txt │ │ ├── bad_data.txt │ │ ├── default_data.txt │ │ └── raw_data.txt │ ├── README.md │ ├── inbound_test.go │ └── inbound.go ├── mail │ └── README.md └── eventwebhook │ ├── README.md │ ├── eventwebhook.go │ └── eventwebhook_test.go ├── static └── img │ ├── github-fork.png │ └── github-sign-up.png ├── twilio_sendgrid_logo.png ├── .gitignore ├── use-cases ├── sections.md ├── attachments.md ├── custom-args.md ├── substitutions.md ├── personalizations.md ├── twilio-email.md ├── README.md ├── transactional-templates.md ├── legacy-templates.md ├── personalizations-with-mailer-helper.md ├── view-email-stats.md ├── email-activity.md ├── personalizations-without-mailer-helper.md ├── legacy-templates-with-mailer-helper.md ├── personalization-without-helper-sending-single-email-single-recipient.md ├── setup-domain-authentication.md ├── legacy-templates-without-mailer-helper.md ├── personalization-without-helper-sending-single-email-single-recipient-with-cc.md ├── personalization-without-helper-sending-single-email-single-recipient-with-cc-bcc.md ├── personalization-without-helper-sending-same-email-to-multiple-recipients.md ├── personalization-without-helper-sending-two-emails-to-two-groups-recipients-from-two-different-from-emails.md ├── personalization-without-helper-sending-single-email-to-single-recipients-with-multiple-cc-bcc.md ├── custom-args-with-mailer-helper.md ├── substitutions-with-mailer-helper.md ├── sections-with-mailer-helper.md ├── personalization-sending-single-email-single-recipient.md ├── custom-args-without-mailer-helper.md ├── substitutions-without-mailer-helper.md ├── twilio-setup.md ├── sections-without-mailer-helper.md ├── personalization-sending-single-email-single-recipient-with-cc.md ├── personalization-sending-single-email-to-multiple-recipients.md ├── personalization-sending-single-email-single-recipient-with-cc-bcc.md ├── attachments-without-mailer-helper.md ├── personalization-sending-single-email-to-single-recipients-with-multiple-cc-bcc.md ├── personalization-without-helper-sending-two-emails-to-two-groups-recipients.md ├── personalization-sending-two-emails-to-two-groups-recipients-from-two-different-from-emails.md ├── transactional-templates-without-mailer-helper.md ├── personalization-sending-two-emails-to-two-groups-recipients.md ├── attachments-with-mailer-helper.md └── transactional-templates-with-mailer-helper.md ├── go.coverage.sh ├── Makefile ├── .github └── workflows │ ├── pr-lint.yml │ └── test-and-deploy.yml ├── Dockerfile ├── examples ├── scopes │ └── scopes.go ├── stats │ └── stats.go ├── devices │ └── devices.go ├── geo │ └── geo.go ├── browsers │ └── browsers.go ├── mailboxproviders │ └── mailboxproviders.go ├── eventwebhook │ └── eventwebhook.go ├── clients │ └── clients.go ├── partnersettings │ └── partnersettings.go ├── emailactivity │ └── emailactivity.go ├── categories │ └── categories.go ├── dataresidency │ └── setRegion.go ├── alerts │ └── alerts.go ├── apikeys │ └── apikeys.go ├── accesssettings │ └── accesssettings.go ├── senders │ └── senders.go ├── mail │ └── mail.go ├── trackingsettings │ └── trackingsettings.go ├── templates │ └── templates.go ├── campaigns │ └── campaigns.go ├── ips │ └── ips.go └── asm │ └── asm.go ├── twilio_email_test.go ├── LICENSE ├── twilio_email.go ├── PULL_REQUEST_TEMPLATE.md ├── sendgrid.go ├── FIRST_TIMERS.md ├── CODE_OF_CONDUCT.md ├── base_interface.go ├── TROUBLESHOOTING.md ├── CONTRIBUTING.md └── README.md /.env_sample: -------------------------------------------------------------------------------- 1 | export SENDGRID_API_KEY='' -------------------------------------------------------------------------------- /helpers/inbound/sample_data/default_data_with_attachments.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /helpers/inbound/sample_data/bad_data.txt: -------------------------------------------------------------------------------- 1 | this is bad invalid data -------------------------------------------------------------------------------- /static/img/github-fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-go/HEAD/static/img/github-fork.png -------------------------------------------------------------------------------- /twilio_sendgrid_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-go/HEAD/twilio_sendgrid_logo.png -------------------------------------------------------------------------------- /static/img/github-sign-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sendgrid/sendgrid-go/HEAD/static/img/github-sign-up.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | temp.go 3 | *.swp 4 | .env 5 | coverage.txt 6 | sendgrid.env 7 | .vscode 8 | prism* 9 | **/.idea/**/* 10 | -------------------------------------------------------------------------------- /use-cases/sections.md: -------------------------------------------------------------------------------- 1 | # Sections 2 | 3 | * [With Mail Helper Class](sections-with-mailer-helper.md) 4 | * [Without Mail Helper Class](sections-without-mailer-helper.md) -------------------------------------------------------------------------------- /use-cases/attachments.md: -------------------------------------------------------------------------------- 1 | # Attachments 2 | 3 | * [With Mail Helper Class](attachments-with-mailer-helper.md) 4 | * [Without Mail Helper Class](attachments-without-mailer-helper.md) -------------------------------------------------------------------------------- /use-cases/custom-args.md: -------------------------------------------------------------------------------- 1 | # CustomArgs 2 | 3 | * [With Mail Helper Class](custom-args-with-mailer-helper.md) 4 | * [Without Mail Helper Class](custom-args-without-mailer-helper.md) -------------------------------------------------------------------------------- /use-cases/substitutions.md: -------------------------------------------------------------------------------- 1 | # Substitutions 2 | 3 | * [With Mail Helper Class](substitutions-with-mailer-helper.md) 4 | * [Without Mail Helper Class](substitutions-without-mailer-helper.md) -------------------------------------------------------------------------------- /use-cases/personalizations.md: -------------------------------------------------------------------------------- 1 | # Personalizations 2 | 3 | * [With Mail Helper Class](personalizations-with-mailer-helper.md) 4 | * [Without Mail Helper Class](personalizations-without-mailer-helper.md) -------------------------------------------------------------------------------- /go.coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | echo > coverage.txt 5 | 6 | for d in $(go list ./... | grep -v -E '/vendor|/examples|/docker'); do 7 | go test -coverprofile=profile.out -covermode=atomic "$d" 8 | if [ -f profile.out ]; then 9 | cat profile.out >> coverage.txt 10 | rm profile.out 11 | fi 12 | done 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test install test-integ test-docker 2 | 3 | install: 4 | go get -t -v ./... 5 | 6 | test: 7 | ./go.coverage.sh 8 | bash -c 'diff -u <(echo -n) <(gofmt -d -s .)' 9 | 10 | test-integ: test 11 | 12 | version ?= latest 13 | test-docker: 14 | curl -s https://raw.githubusercontent.com/sendgrid/sendgrid-oai/HEAD/prism/prism.sh -o prism.sh 15 | version=$(version) bash ./prism.sh 16 | -------------------------------------------------------------------------------- /.github/workflows/pr-lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint PR 2 | on: 3 | pull_request_target: 4 | types: [ opened, edited, synchronize, reopened ] 5 | 6 | jobs: 7 | validate: 8 | name: Validate title 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: amannn/action-semantic-pull-request@v4 12 | with: 13 | types: chore docs fix feat test misc 14 | env: 15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.21.11 2 | 3 | ENV GO111MODULE 'off' 4 | 5 | COPY prism/prism/nginx/cert.crt /usr/local/share/ca-certificates/cert.crt 6 | RUN update-ca-certificates 7 | 8 | WORKDIR /go/src/github.com/sendgrid/sendgrid-go 9 | COPY . . 10 | 11 | RUN make install 12 | 13 | # Use the last version of testify that works for older go versions, and then 14 | # re-install to update dependencies. 15 | RUN (cd /go/src/github.com/stretchr/testify && git checkout v1.6.0) 16 | RUN make install 17 | -------------------------------------------------------------------------------- /use-cases/twilio-email.md: -------------------------------------------------------------------------------- 1 | First, follow the [Twilio Setup](twilio-setup.md) guide for creating a Twilio account and setting up environment variables with the proper credentials. 2 | 3 | Then, initialize the Twilio Email Client. 4 | 5 | ```go 6 | mailClient := NewTwilioEmailSendClient(os.Getenv("TWILIO_API_KEY"), os.Getenv("TWILIO_API_SECRET")) 7 | 8 | // or 9 | 10 | mailClient := NewTwilioEmailSendClient(os.Getenv("TWILIO_ACCOUNT_SID"), os.Getenv("TWILIO_AUTH_TOKEN")) 11 | ``` 12 | 13 | This sets the client to use Twilio Auth and the Twilio Email API. 14 | -------------------------------------------------------------------------------- /examples/scopes/scopes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/sendgrid/sendgrid-go" 9 | ) 10 | 11 | // Retrievealistofscopesforwhichthisuserhasaccess : Retrieve a list of scopes for which this user has access. 12 | // GET /scopes 13 | func Retrievealistofscopesforwhichthisuserhasaccess() { 14 | apiKey := os.Getenv("SENDGRID_API_KEY") 15 | host := "https://api.sendgrid.com" 16 | request := sendgrid.GetRequest(apiKey, "/v3/scopes", host) 17 | request.Method = "GET" 18 | response, err := sendgrid.API(request) 19 | if err != nil { 20 | log.Println(err) 21 | } else { 22 | fmt.Println(response.StatusCode) 23 | fmt.Println(response.Body) 24 | fmt.Println(response.Headers) 25 | } 26 | } 27 | 28 | func main() { 29 | // add your function calls here 30 | } 31 | -------------------------------------------------------------------------------- /helpers/mail/README.md: -------------------------------------------------------------------------------- 1 | **This helper allows you to quickly and easily build a Mail object for sending email through Twilio SendGrid.** 2 | 3 | ## Dependencies 4 | 5 | - [rest](https://github.com/sendgrid/rest) 6 | 7 | # Quick Start 8 | 9 | Run the [example](../../examples/helpers/mail/example.go) (make sure you have set your environment variable to include your SENDGRID_API_KEY). 10 | 11 | ```bash 12 | go run examples/helpers/mail/example.go 13 | ``` 14 | 15 | ## Usage 16 | 17 | - See the [example](../../examples/helpers/mail/example.go) for a complete working example. 18 | - [Documentation](https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html) 19 | 20 | ## Test 21 | 22 | ```bash 23 | go test ./... -v 24 | ``` 25 | 26 | or 27 | 28 | ```bash 29 | cd helpers/mail 30 | go test -v 31 | ``` 32 | -------------------------------------------------------------------------------- /use-cases/README.md: -------------------------------------------------------------------------------- 1 | This documentation provides examples for specific Twilio SendGrid use cases. Please [open an issue](https://github.com/sendgrid/sendgrid-go/issues) or make a pull request for any use cases you would like us to document here. Thank you! 2 | 3 | # Email Use Cases 4 | * [Transactional Templates](transactional-templates.md) 5 | * [Legacy Templates](legacy-templates.md) 6 | * [CustomArgs](custom-args.md) 7 | * [Personalizations](personalizations.md) 8 | * [Substitutions](substitutions.md) 9 | * [Sections](sections.md) 10 | * [Attachments](attachments.md) 11 | * [How to View Email Statistics](view-email-stats.md) 12 | * [How to Setup a Domain Authentication](setup-domain-authentication.md) 13 | 14 | # Twilio Use Cases 15 | * [Twilio Setup](twilio-setup.md) 16 | * [Send an Email With Twilio Email (Pilot)](twilio-email.md) 17 | -------------------------------------------------------------------------------- /helpers/eventwebhook/README.md: -------------------------------------------------------------------------------- 1 | **This helper allows you to quickly and easily enable/disable SecureWebhook feature or get the public key through Twilio SendGrid.** 2 | 3 | ## Dependencies 4 | 5 | - [rest](https://github.com/sendgrid/rest) 6 | 7 | # Quick Start 8 | 9 | Run the [example](../../examples/eventwebhook/eventwebhook.go) (make sure you have set your environment variable to include your SENDGRID_API_KEY). 10 | ```bash 11 | go run examples/eventwebhook/eventwebhook.go 12 | ``` 13 | 14 | ## Usage 15 | 16 | - See the [example](../../examples/eventwebhook/eventwebhook.go) for a complete working example. 17 | - [Documentation](https://sendgrid.com/docs/for-developers/tracking-events/) 18 | 19 | ## Test 20 | 21 | ```bash 22 | go test ./... -v 23 | ``` 24 | 25 | or 26 | 27 | ```bash 28 | cd helpers/eventwebhook 29 | go test -v 30 | ``` 31 | -------------------------------------------------------------------------------- /use-cases/transactional-templates.md: -------------------------------------------------------------------------------- 1 | # Transactional Templates 2 | For this example, we assume you have created a [dynamic transactional template](https://sendgrid.com/docs/ui/sending-email/how-to-send-an-email-with-dynamic-transactional-templates/) in the UI or via the API. Following is the dynamic template data we used for testing. 3 | 4 | Template ID (replace with your own): 5 | 6 | ```text 7 | d-c6dcf1f72bdd4beeb15a9aa6c72fcd2c 8 | ``` 9 | 10 | [Template Body](https://github.com/sendgrid/email-templates/blob/HEAD/dynamic-templates/receipt/receipt.html) 11 | 12 | [Template Data](https://github.com/sendgrid/email-templates/blob/HEAD/dynamic-templates/receipt/receipt_data.json) 13 | 14 | * [With Mail Helper Class](transactional-templates-with-mailer-helper.md) 15 | * [Without Mail Helper Class](transactional-templates-without-mailer-helper.md) 16 | -------------------------------------------------------------------------------- /use-cases/legacy-templates.md: -------------------------------------------------------------------------------- 1 | # Legacy Templates 2 | 3 | For this example, we assume you have created a [legacy transactional template](https://sendgrid.com/docs/User_Guide/Transactional_Templates/index.html) in the UI or via the API. Following is the template content we used for testing. 4 | 5 | Template ID (replace with your own): 6 | 7 | ```text 8 | 13b8f94f-bcae-4ec6-b752-70d6cb59f932 9 | ``` 10 | 11 | Email Subject: 12 | 13 | ```text 14 | <%subject%> 15 | ``` 16 | 17 | Template Body: 18 | 19 | ```html 20 | 21 |
22 |%fname% : %CustomerID% - Personalizations are awesome!
" 35 | } 36 | ] 37 | }`) 38 | response, err := sendgrid.API(request) 39 | if err != nil { 40 | log.Println(err) 41 | } else { 42 | fmt.Println(response.StatusCode) 43 | fmt.Println(response.Body) 44 | fmt.Println(response.Headers) 45 | } 46 | } 47 | ``` -------------------------------------------------------------------------------- /twilio_email.go: -------------------------------------------------------------------------------- 1 | package sendgrid 2 | 3 | import ( 4 | "encoding/base64" 5 | 6 | "github.com/sendgrid/rest" 7 | ) 8 | 9 | // TwilioEmailOptions for GetTwilioEmailRequest 10 | type TwilioEmailOptions struct { 11 | Username string 12 | Password string 13 | Endpoint string 14 | Host string 15 | } 16 | 17 | // NewTwilioEmailSendClient constructs a new Twilio Email client given a username and password 18 | func NewTwilioEmailSendClient(username, password string) *Client { 19 | request := GetTwilioEmailRequest(TwilioEmailOptions{Username: username, Password: password, Endpoint: "/v3/mail/send"}) 20 | request.Method = "POST" 21 | return &Client{request} 22 | } 23 | 24 | // GetTwilioEmailRequest create Request 25 | // @return [Request] a default request object 26 | func GetTwilioEmailRequest(twilioEmailOptions TwilioEmailOptions) rest.Request { 27 | credentials := twilioEmailOptions.Username + ":" + twilioEmailOptions.Password 28 | encodedCreds := base64.StdEncoding.EncodeToString([]byte(credentials)) 29 | 30 | options := options{ 31 | Auth: "Basic " + encodedCreds, 32 | Endpoint: twilioEmailOptions.Endpoint, 33 | Host: twilioEmailOptions.Host, 34 | } 35 | 36 | if options.Host == "" { 37 | options.Host = "https://email.twilio.com" 38 | } 39 | 40 | return requestNew(options) 41 | } 42 | -------------------------------------------------------------------------------- /use-cases/setup-domain-authentication.md: -------------------------------------------------------------------------------- 1 | ## How to Setup a Domain Authentication 2 | 3 | You can find documentation for how to setup a domain authentication via the UI [here](https://sendgrid.com/docs/ui/account-and-settings/how-to-set-up-domain-authentication/). 4 | Find more information about all of Twilio SendGrid's authentication related documentation [here](https://sendgrid.com/docs/ui/account-and-settings/). 5 | 6 | To create a Domain authentication Via the API: 7 | ``` 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "log" 13 | "os" 14 | 15 | "github.com/sendgrid/sendgrid-go" 16 | ) 17 | 18 | func main() { 19 | apiKey := os.Getenv("SENDGRID_API_KEY") 20 | host := "https://api.sendgrid.com" 21 | request := sendgrid.GetRequest(apiKey, "/v3/whitelabel/domains", host) 22 | request.Method = "POST" 23 | request.Body = []byte(` { 24 | "automatic_security": false, 25 | "custom_spf": true, 26 | "default": true, 27 | "domain": "example.com", 28 | "ips": [ 29 | "192.168.1.1", 30 | "192.168.1.2" 31 | ], 32 | "subdomain": "SUBDOMAIN", 33 | "username": "YOUR_SENDGRID_SUBUSER_NAME" 34 | }`) 35 | response, err := sendgrid.API(request) 36 | if err != nil { 37 | log.Println(err) 38 | } else { 39 | fmt.Println(response.StatusCode) 40 | fmt.Println(response.Body) 41 | fmt.Println(response.Headers) 42 | } 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /use-cases/legacy-templates-without-mailer-helper.md: -------------------------------------------------------------------------------- 1 | ## Without Mail Helper Class 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | func main() { 15 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 16 | request.Method = "POST" 17 | request.Body = []byte(` { 18 | "personalizations": [ 19 | { 20 | "to": [ 21 | { 22 | "email": "test@example.com" 23 | } 24 | ], 25 | "subject": "I'm replacing the subject tag", 26 | "substitutions": { 27 | "-name-": "Example User", 28 | "-city-": "Denver" 29 | }, 30 | } 31 | ], 32 | "from": { 33 | "email": "test@example.com" 34 | }, 35 | "content": [ 36 | { 37 | "type": "text/html", 38 | "value": "I'm replacing the body tag" 39 | } 40 | ], 41 | "template_id": "13b8f94f-bcae-4ec6-b752-70d6cb59f932" 42 | }`) 43 | response, err := sendgrid.API(request) 44 | if err != nil { 45 | log.Println(err) 46 | } else { 47 | fmt.Println(response.StatusCode) 48 | fmt.Println(response.Body) 49 | fmt.Println(response.Headers) 50 | } 51 | } 52 | ``` -------------------------------------------------------------------------------- /use-cases/personalization-without-helper-sending-single-email-single-recipient-with-cc.md: -------------------------------------------------------------------------------- 1 | ### Personalization (without helper) - Sending a Single Email to a Single Recipient With a CC 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | func main() { 15 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 16 | request.Method = "POST" 17 | request.Body = []byte(`{ 18 | "personalizations": [{ 19 | "to": [{ 20 | "email": "recipient1@example.com" 21 | }], 22 | "cc": [{ 23 | "email": "recipient2@example.com" 24 | }], 25 | "substitutions": { 26 | "%fname%": "recipient", 27 | "%CustomerID%": "CUSTOMER ID GOES HERE" 28 | }, 29 | "subject": "YOUR SUBJECT LINE GOES HERE" 30 | }], 31 | "from": { 32 | "email": "test@example.com" 33 | }, 34 | "content": [ 35 | { 36 | "type": "text/html", 37 | "value": "%fname% : %CustomerID% - Personalizations are awesome!
" 38 | } 39 | ] 40 | }`) 41 | response, err := sendgrid.API(request) 42 | if err != nil { 43 | log.Println(err) 44 | } else { 45 | fmt.Println(response.StatusCode) 46 | fmt.Println(response.Body) 47 | fmt.Println(response.Headers) 48 | } 49 | } 50 | ``` -------------------------------------------------------------------------------- /use-cases/personalization-without-helper-sending-single-email-single-recipient-with-cc-bcc.md: -------------------------------------------------------------------------------- 1 | ### Sending a Single Email to a Single Recipient With a CC and a BCC 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | func main() { 15 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 16 | request.Method = "POST" 17 | request.Body = []byte(`{ 18 | "personalizations": [{ 19 | "to": [{ 20 | "email": "recipient1@example.com" 21 | }], 22 | "cc": [{ 23 | "email": "recipient2@example.com" 24 | }], 25 | "bcc": [{ 26 | "email": "recipient3@example.com" 27 | }], 28 | "substitutions": { 29 | "%fname%": "recipient", 30 | "%CustomerID%": "CUSTOMER ID GOES HERE" 31 | } 32 | }], 33 | "from": { 34 | "email": "test@example.com" 35 | }, 36 | "content": [ 37 | { 38 | "type": "text/html", 39 | "value": "%fname% : %CustomerID% - Personalizations are awesome!
" 40 | } 41 | ] 42 | }`) 43 | response, err := sendgrid.API(request) 44 | if err != nil { 45 | log.Println(err) 46 | } else { 47 | fmt.Println(response.StatusCode) 48 | fmt.Println(response.Body) 49 | fmt.Println(response.Headers) 50 | } 51 | } 52 | ``` -------------------------------------------------------------------------------- /use-cases/personalization-without-helper-sending-same-email-to-multiple-recipients.md: -------------------------------------------------------------------------------- 1 | ### Personalization (without helper) - Sending the same Email to Multiple Recipients 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | func main() { 15 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 16 | request.Method = "POST" 17 | request.Body = []byte(`{ 18 | "personalizations": [{ 19 | "to": [{ 20 | "email": "recipient1@example.com" 21 | }, { 22 | "email": "recipient2@example.com" 23 | }, { 24 | "email": "recipient3@example.com" 25 | }], 26 | "substitutions": { 27 | "%fname%": "recipient", 28 | "%CustomerID%": "CUSTOMER ID GOES HERE" 29 | }, 30 | "subject": "YOUR SUBJECT LINE GOES HERE" 31 | }], 32 | "from": { 33 | "email": "test@example.com" 34 | }, 35 | "content": [ 36 | { 37 | "type": "text/html", 38 | "value": "%fname% : %CustomerID% - Personalizations are awesome!
" 39 | } 40 | ] 41 | }`) 42 | response, err := sendgrid.API(request) 43 | if err != nil { 44 | log.Println(err) 45 | } else { 46 | fmt.Println(response.StatusCode) 47 | fmt.Println(response.Body) 48 | fmt.Println(response.Headers) 49 | } 50 | } 51 | ``` -------------------------------------------------------------------------------- /use-cases/personalization-without-helper-sending-two-emails-to-two-groups-recipients-from-two-different-from-emails.md: -------------------------------------------------------------------------------- 1 | ### Personalization (without helper) - Sending Two Different Emails to Two Different Groups of Recipients from two different From email address 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | func main() { 15 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 16 | request.Method = "POST" 17 | request.Body = []byte(`{ 18 | "personalizations": [{ 19 | "to": [{ 20 | "email": "recipient1@example.com" 21 | }], 22 | "subject": "YOUR SUBJECT LINE GOES HERE" 23 | }, { 24 | "to": [{ 25 | "email": "recipient2@example.com" 26 | }], 27 | "from": { 28 | "email": "sender2@example.com" 29 | }, 30 | "subject": "YOUR OTHER SUBJECT LINE GOES HERE" 31 | }], 32 | "from": { 33 | "email": "defaultSender@example.com" 34 | }, 35 | "content": [ 36 | { 37 | "type": "text/html", 38 | "value": "Personalizations are awesome!
" 39 | } 40 | ] 41 | }`) 42 | response, err := sendgrid.API(request) 43 | if err != nil { 44 | log.Println(err) 45 | } else { 46 | fmt.Println(response.StatusCode) 47 | fmt.Println(response.Body) 48 | fmt.Println(response.Headers) 49 | } 50 | } 51 | ``` -------------------------------------------------------------------------------- /use-cases/personalization-without-helper-sending-single-email-to-single-recipients-with-multiple-cc-bcc.md: -------------------------------------------------------------------------------- 1 | ### Personalization (without helper) - Sending a Single Email to a Single Recipient with Multiple CCs/BCCs 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | func main() { 15 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 16 | request.Method = "POST" 17 | request.Body = []byte(`{ 18 | "personalizations": [{ 19 | "to": [{ 20 | "email": "recipient1@example.com" 21 | }], 22 | "cc": [{ 23 | "email": "recipient2@example.com" 24 | }, { 25 | "email": "recipient3@example.com" 26 | }, { 27 | "email": "recipient4@example.com" 28 | }], 29 | "substitutions": { 30 | "%fname%": "recipient", 31 | "%CustomerID%": "CUSTOMER ID GOES HERE" 32 | }, 33 | "subject": "YOUR SUBJECT LINE GOES HERE" 34 | }], 35 | "from": { 36 | "email": "test@example.com" 37 | }, 38 | "content": [ 39 | { 40 | "type": "text/html", 41 | "value": "%fname% : %CustomerID% - Personalizations are awesome!
" 42 | } 43 | ] 44 | }`) 45 | response, err := sendgrid.API(request) 46 | if err != nil { 47 | log.Println(err) 48 | } else { 49 | fmt.Println(response.StatusCode) 50 | fmt.Println(response.Body) 51 | fmt.Println(response.Headers) 52 | } 53 | } 54 | ``` -------------------------------------------------------------------------------- /use-cases/custom-args-with-mailer-helper.md: -------------------------------------------------------------------------------- 1 | ## CustomArgs - With Mail Helper Class 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | "github.com/sendgrid/sendgrid-go/helpers/mail" 13 | ) 14 | 15 | func main() { 16 | from := mail.NewEmail("Example User", "test@example.com") 17 | subject := "CustomArgs can be fun" 18 | to := mail.NewEmail("Example User", "test@example.com") 19 | content := mail.NewContent("text/html", "\n\n\t%fname% : %CustomerID% - Personalizations are awesome!
") 21 | 22 | m.SetFrom(from) 23 | m.AddContent(content) 24 | 25 | // create new *Personalization 26 | personalization := mail.NewPersonalization() 27 | 28 | // populate `personalization` with data 29 | to := mail.NewEmail("Example User", "test1@example.com") 30 | 31 | personalization.AddTos(to) 32 | personalization.SetSubstitution("%fname%", "recipient") 33 | personalization.SetSubstitution("%CustomerID%", "CUSTOMER ID GOES HERE") 34 | personalization.Subject = "Having fun learning about personalizations?" 35 | 36 | // add `personalization` to `m` 37 | m.AddPersonalizations(personalization) 38 | 39 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 40 | request.Method = "POST" 41 | request.Body = mail.GetRequestBody(m) 42 | response, err := sendgrid.API(request) 43 | if err != nil { 44 | log.Println(err) 45 | } else { 46 | fmt.Println(response.StatusCode) 47 | fmt.Println(response.Body) 48 | fmt.Println(response.Headers) 49 | } 50 | } 51 | ``` -------------------------------------------------------------------------------- /use-cases/custom-args-without-mailer-helper.md: -------------------------------------------------------------------------------- 1 | ## CustomArgs - Without Mail Helper Class 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | func main() { 15 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 16 | request.Method = "POST" 17 | request.Body = []byte(` { 18 | "personalizations": [ 19 | { 20 | "to": [ 21 | { 22 | "email": "test@example.com" 23 | } 24 | ], 25 | "subject": "CustomArgs can be fun", 26 | "substitutions": { 27 | "-name-": "Example User", 28 | "-city-": "Denver" 29 | }, 30 | "custom_args": { 31 | "user_id": "343", 32 | "batch_id": "3" 33 | } 34 | } 35 | ], 36 | "from": { 37 | "email": "test@example.com" 38 | }, 39 | "content": [ 40 | { 41 | "type": "text/html", 42 | "value": "\n\n\t%fname% : %CustomerID% - Personalizations are awesome!
") 22 | 23 | m.SetFrom(from) 24 | m.AddContent(content) 25 | 26 | // create new *Personalization 27 | personalization := mail.NewPersonalization() 28 | 29 | // populate `personalization` with data 30 | to := mail.NewEmail("Example User", "test1@example.com") 31 | cc1 := mail.NewEmail("Example CC", "test2@example.com") 32 | 33 | personalization.AddTos(to) 34 | personalization.AddCCs(cc1) 35 | personalization.SetSubstitution("%fname%", "recipient") 36 | personalization.SetSubstitution("%CustomerID%", "CUSTOMER ID GOES HERE") 37 | personalization.Subject = "Having fun learning about personalizations?" 38 | 39 | // add `personalization` to `m` 40 | m.AddPersonalizations(personalization) 41 | 42 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 43 | request.Method = "POST" 44 | request.Body = mail.GetRequestBody(m) 45 | response, err := sendgrid.API(request) 46 | if err != nil { 47 | log.Println(err) 48 | } else { 49 | fmt.Println(response.StatusCode) 50 | fmt.Println(response.Body) 51 | fmt.Println(response.Headers) 52 | } 53 | } 54 | ``` -------------------------------------------------------------------------------- /use-cases/personalization-sending-single-email-to-multiple-recipients.md: -------------------------------------------------------------------------------- 1 | ### Personalization (with helper) - Sending a Single Email to Multiple Recipients 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | "github.com/sendgrid/sendgrid-go/helpers/mail" 13 | ) 14 | 15 | func main() { 16 | // create new *SGMailV3 17 | m := mail.NewV3Mail() 18 | 19 | from := mail.NewEmail("test", "test@example.com") 20 | content := mail.NewContent("text/html", "%fname% : %CustomerID% - Personalizations are awesome!
") 21 | 22 | m.SetFrom(from) 23 | m.AddContent(content) 24 | 25 | // create new *Personalization 26 | personalization := mail.NewPersonalization() 27 | 28 | // populate `personalization` with data 29 | to1 := mail.NewEmail("Example User 1", "test1@example.com") 30 | to2 := mail.NewEmail("Example User 2", "test2@example.com") 31 | to3 := mail.NewEmail("Example User 3", "test3@example.com") 32 | 33 | personalization.AddTos(to1, to2, to3) 34 | personalization.SetSubstitution("%fname%", "recipient") 35 | personalization.SetSubstitution("%CustomerID%", "CUSTOMER ID GOES HERE") 36 | personalization.Subject = "Having fun learning about personalizations?" 37 | 38 | // add `personalization` to `m` 39 | m.AddPersonalizations(personalization) 40 | 41 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 42 | request.Method = "POST" 43 | request.Body = mail.GetRequestBody(m) 44 | response, err := sendgrid.API(request) 45 | if err != nil { 46 | log.Println(err) 47 | } else { 48 | fmt.Println(response.StatusCode) 49 | fmt.Println(response.Body) 50 | fmt.Println(response.Headers) 51 | } 52 | } 53 | ``` -------------------------------------------------------------------------------- /examples/clients/clients.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/sendgrid/sendgrid-go" 9 | ) 10 | 11 | // Retrieveemailstatisticsbyclienttype : Retrieve email statistics by client type. 12 | // GET /clients/stats 13 | func Retrieveemailstatisticsbyclienttype() { 14 | apiKey := os.Getenv("SENDGRID_API_KEY") 15 | host := "https://api.sendgrid.com" 16 | request := sendgrid.GetRequest(apiKey, "/v3/clients/stats", host) 17 | request.Method = "GET" 18 | queryParams := make(map[string]string) 19 | queryParams["aggregated_by"] = "day" 20 | queryParams["start_date"] = "2016-01-01" 21 | queryParams["end_date"] = "2016-04-01" 22 | request.QueryParams = queryParams 23 | response, err := sendgrid.API(request) 24 | if err != nil { 25 | log.Println(err) 26 | } else { 27 | fmt.Println(response.StatusCode) 28 | fmt.Println(response.Body) 29 | fmt.Println(response.Headers) 30 | } 31 | } 32 | 33 | // Retrievestatsbyaspecificclienttype : Retrieve stats by a specific client type. 34 | // GET /clients/{client_type}/stats 35 | func Retrievestatsbyaspecificclienttype() { 36 | apiKey := os.Getenv("SENDGRID_API_KEY") 37 | host := "https://api.sendgrid.com" 38 | request := sendgrid.GetRequest(apiKey, "/v3/clients/{client_type}/stats", host) 39 | request.Method = "GET" 40 | queryParams := make(map[string]string) 41 | queryParams["aggregated_by"] = "day" 42 | queryParams["start_date"] = "2016-01-01" 43 | queryParams["end_date"] = "2016-04-01" 44 | request.QueryParams = queryParams 45 | response, err := sendgrid.API(request) 46 | if err != nil { 47 | log.Println(err) 48 | } else { 49 | fmt.Println(response.StatusCode) 50 | fmt.Println(response.Body) 51 | fmt.Println(response.Headers) 52 | } 53 | } 54 | 55 | func main() { 56 | // add your function calls here 57 | } 58 | -------------------------------------------------------------------------------- /use-cases/personalization-sending-single-email-single-recipient-with-cc-bcc.md: -------------------------------------------------------------------------------- 1 | ### Personalization (with helper) - Sending a Single Email to a Single Recipient with a CC and a BCC 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | "github.com/sendgrid/sendgrid-go/helpers/mail" 13 | ) 14 | 15 | func main() { 16 | // create new *SGMailV3 17 | m := mail.NewV3Mail() 18 | 19 | from := mail.NewEmail("test", "test@example.com") 20 | content := mail.NewContent("text/html", "%fname% : %CustomerID% - Personalizations are awesome!
") 21 | 22 | m.SetFrom(from) 23 | m.AddContent(content) 24 | 25 | // create new *Personalization 26 | personalization := mail.NewPersonalization() 27 | 28 | // populate `personalization` with data 29 | to := mail.NewEmail("Example User", "test1@example.com") 30 | cc1 := mail.NewEmail("Example CC", "test2@example.com") 31 | bcc1 := mail.NewEmail("Example BCC", "test3@example.com") 32 | 33 | personalization.AddTos(to) 34 | personalization.AddCCs(cc1) 35 | personalization.AddBCCs(bcc1) 36 | personalization.SetSubstitution("%fname%", "recipient") 37 | personalization.SetSubstitution("%CustomerID%", "CUSTOMER ID GOES HERE") 38 | personalization.Subject = "Having fun learning about personalizations?" 39 | 40 | // add `personalization` to `m` 41 | m.AddPersonalizations(personalization) 42 | 43 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 44 | request.Method = "POST" 45 | request.Body = mail.GetRequestBody(m) 46 | response, err := sendgrid.API(request) 47 | if err != nil { 48 | log.Println(err) 49 | } else { 50 | fmt.Println(response.StatusCode) 51 | fmt.Println(response.Body) 52 | fmt.Println(response.Headers) 53 | } 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /use-cases/attachments-without-mailer-helper.md: -------------------------------------------------------------------------------- 1 | ## Attachments - Without Mail Helper Class 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | func main() { 15 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 16 | request.Method = "POST" 17 | request.Body = []byte(` { 18 | "personalizations": [ 19 | { 20 | "to": [ 21 | { 22 | "email": "test1@example.com" 23 | } 24 | ], 25 | "subject": "Attachments - Demystified!" 26 | } 27 | } 28 | ], 29 | "from": { 30 | "email": "test@example.com" 31 | }, 32 | "content": [ 33 | { 34 | "type": "text/html", 35 | "value": "Sending different attachments.
" 36 | } 37 | ], 38 | "attachments": [ 39 | { 40 | "content": "SGVsbG8gV29ybGQh", 41 | "disposition": "attachment", 42 | "filename": "testing.txt", 43 | "type": "txt" 44 | }, 45 | { 46 | "content": "BASE64 encoded content block here", 47 | "disposition": "inline", 48 | "content_id": "testing_2", 49 | "filename": "testing.jpg", 50 | "type": "jpg" 51 | }, 52 | { 53 | "content": "BASE64 encoded content block here", 54 | "disposition": "attachment", 55 | "filename": "testing.pdf", 56 | "type": "pdf" 57 | } 58 | ] 59 | }`) 60 | response, err := sendgrid.API(request) 61 | if err != nil { 62 | log.Println(err) 63 | } else { 64 | fmt.Println(response.StatusCode) 65 | fmt.Println(response.Body) 66 | fmt.Println(response.Headers) 67 | } 68 | } 69 | ``` 70 | -------------------------------------------------------------------------------- /use-cases/personalization-sending-single-email-to-single-recipients-with-multiple-cc-bcc.md: -------------------------------------------------------------------------------- 1 | ### Personalization (with helper) - Sending a Single Email to a Single Recipient with Multiple CCs/BCCs 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | "github.com/sendgrid/sendgrid-go/helpers/mail" 13 | ) 14 | 15 | func main() { 16 | // create new *SGMailV3 17 | m := mail.NewV3Mail() 18 | 19 | from := mail.NewEmail("test", "test@example.com") 20 | content := mail.NewContent("text/html", "%fname% : %CustomerID% - Personalizations are awesome!
") 21 | 22 | m.SetFrom(from) 23 | m.AddContent(content) 24 | 25 | // create new *Personalization 26 | personalization := mail.NewPersonalization() 27 | 28 | // populate `personalization` with data 29 | to := mail.NewEmail("Example User 1", "test1@example.com") 30 | cc1 := mail.NewEmail("Example User 2", "test2@example.com") 31 | cc2 := mail.NewEmail("Example User 3", "test3@example.com") 32 | cc3 := mail.NewEmail("Example User 3", "test4@example.com") 33 | 34 | personalization.AddTos(to) 35 | personalization.AddCCs(cc1, cc2, cc3) 36 | personalization.SetSubstitution("%fname%", "recipient") 37 | personalization.SetSubstitution("%CustomerID%", "CUSTOMER ID GOES HERE") 38 | personalization.Subject = "Having fun learning about personalizations?" 39 | 40 | // add `personalization` to `m` 41 | m.AddPersonalizations(personalization) 42 | 43 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 44 | request.Method = "POST" 45 | request.Body = mail.GetRequestBody(m) 46 | response, err := sendgrid.API(request) 47 | if err != nil { 48 | log.Println(err) 49 | } else { 50 | fmt.Println(response.StatusCode) 51 | fmt.Println(response.Body) 52 | fmt.Println(response.Headers) 53 | } 54 | } 55 | ``` -------------------------------------------------------------------------------- /use-cases/personalization-without-helper-sending-two-emails-to-two-groups-recipients.md: -------------------------------------------------------------------------------- 1 | ### Personalization (without helper) - Sending Two Different Emails to Two Different Groups of Recipients 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | func main() { 15 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 16 | request.Method = "POST" 17 | request.Body = []byte(`{ 18 | "personalizations": [{ 19 | "to": [{ 20 | "email": "recipient1@example.com" 21 | }], 22 | "cc": [{ 23 | "email": "recipient2@example.com" 24 | }, { 25 | "email": "recipient3@example.com" 26 | }, { 27 | "email": "recipient4@example.com" 28 | }], 29 | "substitutions": { 30 | "%fname%": "recipient", 31 | "%CustomerID%": "CUSTOMER ID GOES HERE" 32 | }, 33 | "subject": "YOUR SUBJECT LINE GOES HERE" 34 | }, { 35 | "to": [{ 36 | "email": "recipient5@example.com" 37 | }], 38 | "cc": [{ 39 | "email": "recipient6@example.com" 40 | }, { 41 | "email": "recipient7@example.com" 42 | }, { 43 | "email": "recipient8@example.com" 44 | }], 45 | "substitutions": { 46 | "%fname%": "recipient2", 47 | "%CustomerID%": 55 48 | }, 49 | "subject": "YOUR SUBJECT LINE GOES HERE" 50 | }], 51 | "from": { 52 | "email": "test@example.com" 53 | }, 54 | "content": [ 55 | { 56 | "type": "text/html", 57 | "value": "%fname% : %CustomerID% - Personalizations are awesome!
" 58 | } 59 | ] 60 | }`) 61 | response, err := sendgrid.API(request) 62 | if err != nil { 63 | log.Println(err) 64 | } else { 65 | fmt.Println(response.StatusCode) 66 | fmt.Println(response.Body) 67 | fmt.Println(response.Headers) 68 | } 69 | } 70 | ``` -------------------------------------------------------------------------------- /use-cases/personalization-sending-two-emails-to-two-groups-recipients-from-two-different-from-emails.md: -------------------------------------------------------------------------------- 1 | 2 | ### Personalization (with helper) - Sending Two Different Emails to Two Different Groups of Recipients from two different From emails 3 | 4 | ```go 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | "os" 11 | 12 | "github.com/sendgrid/sendgrid-go" 13 | "github.com/sendgrid/sendgrid-go/helpers/mail" 14 | ) 15 | 16 | func main() { 17 | // create new *SGMailV3 18 | m := mail.NewV3Mail() 19 | 20 | from := mail.NewEmail("Example Sender 1", "defaultSender@example.com") 21 | content := mail.NewContent("text/html", "Personalizations are awesome!
") 22 | 23 | m.SetFrom(from) 24 | m.AddContent(content) 25 | 26 | // create new *Personalization(s) 27 | personalization1 := mail.NewPersonalization() 28 | personalization2 := mail.NewPersonalization() 29 | 30 | // populate `personalization1` with data 31 | //this email will be sent from Example Sender 1 32 | p1_to := mail.NewEmail("Example User 1", "test1@example.com") 33 | 34 | personalization1.AddTos(p1_to) 35 | personalization1.Subject = "Having fun learning about personalizations?" 36 | 37 | // populate `personalization2` with data 38 | //this email will be sent from Example Sender 2 39 | p2_from :=mail.NewEmail("Example Sender 2", "sender2@example.com") 40 | p2_to := mail.NewEmail("Example User 1", "test1@example.com") 41 | 42 | personalization2.AddFrom(p2_from) 43 | personalization2.AddTos(p2_to) 44 | personalization2.Subject = "Personalizations are fun!" 45 | 46 | // add `personalization1` and `personalization2` to `m` 47 | m.AddPersonalizations(personalization1, personalization2) 48 | 49 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 50 | request.Method = "POST" 51 | request.Body = mail.GetRequestBody(m) 52 | response, err := sendgrid.API(request) 53 | if err != nil { 54 | log.Println(err) 55 | } else { 56 | fmt.Println(response.StatusCode) 57 | fmt.Println(response.Body) 58 | fmt.Println(response.Headers) 59 | } 60 | } 61 | ``` -------------------------------------------------------------------------------- /examples/partnersettings/partnersettings.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/sendgrid/sendgrid-go" 9 | ) 10 | 11 | // Returnsalistofallpartnersettings : Returns a list of all partner settings. 12 | // GET /partner_settings 13 | func Returnsalistofallpartnersettings() { 14 | apiKey := os.Getenv("SENDGRID_API_KEY") 15 | host := "https://api.sendgrid.com" 16 | request := sendgrid.GetRequest(apiKey, "/v3/partner_settings", host) 17 | request.Method = "GET" 18 | queryParams := make(map[string]string) 19 | queryParams["limit"] = "1" 20 | queryParams["offset"] = "1" 21 | request.QueryParams = queryParams 22 | response, err := sendgrid.API(request) 23 | if err != nil { 24 | log.Println(err) 25 | } else { 26 | fmt.Println(response.StatusCode) 27 | fmt.Println(response.Body) 28 | fmt.Println(response.Headers) 29 | } 30 | } 31 | 32 | // UpdatesNewRelicpartnersettings : Updates New Relic partner settings. 33 | // PATCH /partner_settings/new_relic 34 | func UpdatesNewRelicpartnersettings() { 35 | apiKey := os.Getenv("SENDGRID_API_KEY") 36 | host := "https://api.sendgrid.com" 37 | request := sendgrid.GetRequest(apiKey, "/v3/partner_settings/new_relic", host) 38 | request.Method = "PATCH" 39 | request.Body = []byte(` { 40 | "enable_subuser_statistics": true, 41 | "enabled": true, 42 | "license_key": "" 43 | }`) 44 | response, err := sendgrid.API(request) 45 | if err != nil { 46 | log.Println(err) 47 | } else { 48 | fmt.Println(response.StatusCode) 49 | fmt.Println(response.Body) 50 | fmt.Println(response.Headers) 51 | } 52 | } 53 | 54 | // ReturnsallNewRelicpartnersettings : Returns all New Relic partner settings. 55 | // GET /partner_settings/new_relic 56 | func ReturnsallNewRelicpartnersettings() { 57 | apiKey := os.Getenv("SENDGRID_API_KEY") 58 | host := "https://api.sendgrid.com" 59 | request := sendgrid.GetRequest(apiKey, "/v3/partner_settings/new_relic", host) 60 | request.Method = "GET" 61 | response, err := sendgrid.API(request) 62 | if err != nil { 63 | log.Println(err) 64 | } else { 65 | fmt.Println(response.StatusCode) 66 | fmt.Println(response.Body) 67 | fmt.Println(response.Headers) 68 | } 69 | } 70 | 71 | func main() { 72 | // add your function calls here 73 | } 74 | -------------------------------------------------------------------------------- /helpers/eventwebhook/eventwebhook.go: -------------------------------------------------------------------------------- 1 | package eventwebhook 2 | 3 | import ( 4 | "crypto/ecdsa" 5 | "crypto/sha256" 6 | "crypto/x509" 7 | "encoding/asn1" 8 | "encoding/base64" 9 | "encoding/json" 10 | "math/big" 11 | ) 12 | 13 | const ( 14 | // VerificationHTTPHeader is the signature verification http header name for the signature being sent 15 | VerificationHTTPHeader = "X-Twilio-Email-Event-Webhook-Signature" 16 | // TimestampHTTPHeader is the timestamp http header name for timestamp 17 | TimestampHTTPHeader = "X-Twilio-Email-Event-Webhook-Timestamp" 18 | ) 19 | 20 | // Settings ... 21 | type Settings struct { 22 | EnableSignedWebhook *bool `json:"enabled,omitempty"` 23 | } 24 | 25 | // RS represents the ECDSA signature 26 | type RS struct { 27 | R *big.Int 28 | S *big.Int 29 | } 30 | 31 | // NewSettings ... 32 | func NewSettings() *Settings { 33 | return &Settings{} 34 | } 35 | 36 | // SetEnableSignedWebhook ... 37 | func (s *Settings) SetEnableSignedWebhook(enable bool) { 38 | s.EnableSignedWebhook = &enable 39 | } 40 | 41 | // GetRequestBody ... 42 | func GetRequestBody(s *Settings) ([]byte, error) { 43 | b, err := json.Marshal(s) 44 | if err != nil { 45 | return nil, err 46 | } 47 | return b, nil 48 | } 49 | 50 | // ConvertPublicKeyBase64ToECDSA takes a base64 ECDSA public key and converts it into the ECDSA Public Key type 51 | func ConvertPublicKeyBase64ToECDSA(base64PublicKey string) (*ecdsa.PublicKey, error) { 52 | pk, err := base64.StdEncoding.DecodeString(base64PublicKey) 53 | if err != nil { 54 | return nil, err 55 | } 56 | 57 | publicKey, err := x509.ParsePKIXPublicKey(pk) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | return publicKey.(*ecdsa.PublicKey), nil 63 | } 64 | 65 | // VerifySignature uses the ECDSA publicKey and verifies received payload and signature 66 | func VerifySignature(publicKey *ecdsa.PublicKey, payload []byte, signature, timestamp string) (bool, error) { 67 | signatureBytes, err := base64.StdEncoding.DecodeString(signature) 68 | if err != nil { 69 | return false, err 70 | } 71 | 72 | ecdsaSig := &RS{} 73 | _, err = asn1.Unmarshal(signatureBytes, ecdsaSig) 74 | if err != nil { 75 | return false, err 76 | } 77 | 78 | hash := sha256.New() 79 | hash.Write([]byte(timestamp)) 80 | hash.Write(payload) 81 | 82 | return ecdsa.Verify(publicKey, hash.Sum(nil), ecdsaSig.R, ecdsaSig.S), nil 83 | } 84 | -------------------------------------------------------------------------------- /use-cases/transactional-templates-without-mailer-helper.md: -------------------------------------------------------------------------------- 1 | ## Transaction Templates - Without Mail Helper Class 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/sendgrid/sendgrid-go" 9 | "github.com/sendgrid/sendgrid-go/helpers/mail" 10 | "os" 11 | ) 12 | 13 | func main() { 14 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 15 | request.Method = "POST" 16 | request.Body = []byte(` { 17 | "from": { 18 | "email": "test@example.com" 19 | }, 20 | "personalizations": [ 21 | { 22 | "to": [ 23 | { 24 | "email": "test@example.com" 25 | } 26 | ], 27 | "dynamic_template_data":{ 28 | "total":"$ 239.85", 29 | "items":[ 30 | { 31 | "text":"New Line Sneakers", 32 | "image":"https://marketing-image-production.s3.amazonaws.com/uploads/8dda1131320a6d978b515cc04ed479df259a458d5d45d58b6b381cae0bf9588113e80ef912f69e8c4cc1ef1a0297e8eefdb7b270064cc046b79a44e21b811802.png", 33 | "price":"$ 79.95" 34 | }, 35 | { 36 | "text":"Old Line Sneakers", 37 | "image":"https://marketing-image-production.s3.amazonaws.com/uploads/3629f54390ead663d4eb7c53702e492de63299d7c5f7239efdc693b09b9b28c82c924225dcd8dcb65732d5ca7b7b753c5f17e056405bbd4596e4e63a96ae5018.png", 38 | "price":"$ 79.95" 39 | }, 40 | { 41 | "text":"Blue Line Sneakers", 42 | "image":"https://marketing-image-production.s3.amazonaws.com/uploads/00731ed18eff0ad5da890d876c456c3124a4e44cb48196533e9b95fb2b959b7194c2dc7637b788341d1ff4f88d1dc88e23f7e3704726d313c57f350911dd2bd0.png", 43 | "price":"$ 79.95" 44 | } 45 | ], 46 | "receipt":true, 47 | "name":"Sample Name", 48 | "address01":"1234 Fake St.", 49 | "address02":"Apt. 123", 50 | "city":"Place", 51 | "state":"CO", 52 | "zip":"80202" 53 | } 54 | } 55 | ], 56 | "template_id":"d-c6dcf1f72bdd4beeb15a9aa6c72fcd2c" 57 | }`) 58 | response, err := sendgrid.API(request) 59 | if err != nil { 60 | log.Println(err) 61 | } else { 62 | fmt.Println(response.StatusCode) 63 | fmt.Println(response.Body) 64 | fmt.Println(response.Headers) 65 | } 66 | } 67 | ``` -------------------------------------------------------------------------------- /use-cases/personalization-sending-two-emails-to-two-groups-recipients.md: -------------------------------------------------------------------------------- 1 | 2 | ### Personalization (with helper) - Sending Two Different Emails to Two Different Groups of Recipients 3 | 4 | ```go 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | "os" 11 | 12 | "github.com/sendgrid/sendgrid-go" 13 | "github.com/sendgrid/sendgrid-go/helpers/mail" 14 | ) 15 | 16 | func main() { 17 | // create new *SGMailV3 18 | m := mail.NewV3Mail() 19 | 20 | from := mail.NewEmail("test", "test@example.com") 21 | content := mail.NewContent("text/html", "%fname% : %CustomerID% - Personalizations are awesome!
") 22 | 23 | m.SetFrom(from) 24 | m.AddContent(content) 25 | 26 | // create new *Personalization(s) 27 | personalization1 := mail.NewPersonalization() 28 | personalization2 := mail.NewPersonalization() 29 | 30 | // populate `personalization1` with data 31 | p1_to := mail.NewEmail("Example User 1", "test1@example.com") 32 | p1_cc1 := mail.NewEmail("Example User 2", "test2@example.com") 33 | p1_cc2 := mail.NewEmail("Example User 3", "test3@example.com") 34 | p1_cc3 := mail.NewEmail("Example User 3", "test4@example.com") 35 | 36 | personalization1.AddTos(p1_to) 37 | personalization1.AddCCs(p1_cc1, p1_cc2, p1_cc3) 38 | personalization1.SetSubstitution("%fname%", "recipient") 39 | personalization1.SetSubstitution("%CustomerID%", "CUSTOMER ID GOES HERE") 40 | personalization1.Subject = "Having fun learning about personalizations?" 41 | 42 | // populate `personalization2` with data 43 | p2_to := mail.NewEmail("Example User 1", "test1@example.com") 44 | p2_cc1 := mail.NewEmail("Example User 2", "test2@example.com") 45 | p2_cc2 := mail.NewEmail("Example User 3", "test3@example.com") 46 | p2_cc3 := mail.NewEmail("Example User 3", "test4@example.com") 47 | 48 | personalization2.AddTos(p2_to) 49 | personalization2.AddCCs(p2_cc1, p2_cc2, p2_cc3) 50 | personalization2.SetSubstitution("%fname%", "recipient2") 51 | personalization2.SetSubstitution("%CustomerID%", "55") 52 | personalization2.Subject = "Personalizations are fun!" 53 | 54 | // add `personalization1` and `personalization2` to `m` 55 | m.AddPersonalizations(personalization1, personalization2) 56 | 57 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 58 | request.Method = "POST" 59 | request.Body = mail.GetRequestBody(m) 60 | response, err := sendgrid.API(request) 61 | if err != nil { 62 | log.Println(err) 63 | } else { 64 | fmt.Println(response.StatusCode) 65 | fmt.Println(response.Body) 66 | fmt.Println(response.Headers) 67 | } 68 | } 69 | ``` -------------------------------------------------------------------------------- /use-cases/attachments-with-mailer-helper.md: -------------------------------------------------------------------------------- 1 | ## Attachments - With Mail Helper Class 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | "encoding/base64" 11 | "io/ioutil" 12 | "github.com/sendgrid/sendgrid-go" 13 | "github.com/sendgrid/sendgrid-go/helpers/mail" 14 | ) 15 | 16 | func main() { 17 | // create new *SGMailV3 18 | m := mail.NewV3Mail() 19 | 20 | from := mail.NewEmail("test", "test@example.com") 21 | content := mail.NewContent("text/html", "Sending different attachments.
") 22 | to := mail.NewEmail("Example User", "test1@example.com") 23 | 24 | m.SetFrom(from) 25 | m.AddContent(content) 26 | 27 | // create new *Personalization 28 | personalization := mail.NewPersonalization() 29 | personalization.AddTos(to) 30 | personalization.Subject = "Attachments - Demystified!" 31 | 32 | // add `personalization` to `m` 33 | m.AddPersonalizations(personalization) 34 | 35 | // read/attach .txt file 36 | a_txt := mail.NewAttachment() 37 | dat, err := io.ReadFile("testing.txt") 38 | if err != nil { 39 | fmt.Println(err) 40 | } 41 | encoded := base64.StdEncoding.EncodeToString([]byte(dat)) 42 | a_txt.SetContent(encoded) 43 | a_txt.SetType("text/plain") 44 | a_txt.SetFilename("testing.txt") 45 | a_txt.SetDisposition("attachment") 46 | 47 | // read/attach .pdf file 48 | a_pdf := mail.NewAttachment() 49 | dat, err = io.ReadFile("testing.pdf") 50 | if err != nil { 51 | fmt.Println(err) 52 | } 53 | encoded = base64.StdEncoding.EncodeToString([]byte(dat)) 54 | a_pdf.SetContent(encoded) 55 | a_pdf.SetType("application/pdf") 56 | a_pdf.SetFilename("testing.pdf") 57 | a_pdf.SetDisposition("attachment") 58 | 59 | // read/attach inline .jpg file 60 | a_jpg := mail.NewAttachment() 61 | dat, err = io.ReadFile("testing.jpg") 62 | if err != nil { 63 | fmt.Println(err) 64 | } 65 | encoded = base64.StdEncoding.EncodeToString([]byte(dat)) 66 | a_jpg.SetContent(encoded) 67 | a_jpg.SetType("image/jpeg") 68 | a_jpg.SetFilename("testing.jpg") 69 | a_jpg.SetDisposition("inline") 70 | a_jpg.SetContentID("Test Attachment") 71 | 72 | // add `a_txt`, `a_pdf` and `a_jpg` to `m` 73 | m.AddAttachment(a_txt) 74 | m.AddAttachment(a_pdf) 75 | m.AddAttachment(a_jpg) 76 | 77 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 78 | request.Method = "POST" 79 | request.Body = mail.GetRequestBody(m) 80 | response, err := sendgrid.API(request) 81 | if err != nil { 82 | log.Println(err) 83 | } else { 84 | fmt.Println(response.StatusCode) 85 | fmt.Println(response.Body) 86 | fmt.Println(response.Headers) 87 | } 88 | } 89 | ``` 90 | -------------------------------------------------------------------------------- /examples/emailactivity/emailactivity.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/url" 7 | "os" 8 | 9 | "github.com/sendgrid/sendgrid-go" 10 | ) 11 | 12 | // GetMessages : Filter all messages 13 | // GET /messages 14 | func GetMessages() { 15 | apiKey := os.Getenv("YOUR_SENDGRID_APIKEY") 16 | host := "https://api.sendgrid.com" 17 | request := sendgrid.GetRequest(apiKey, "/v3/messages", host) 18 | request.Method = "GET" 19 | 20 | filterKey := "to_email" 21 | filterOperator := url.QueryEscape("=") 22 | filterValue := "testing@sendgrid.net" 23 | filterValue = url.QueryEscape(fmt.Sprintf("\"%s\"", filterValue)) 24 | 25 | queryParams := make(map[string]string) 26 | queryParams["query"] = fmt.Sprintf("%s%s%s", filterKey, filterOperator, filterValue) 27 | queryParams["limit"] = "1" 28 | request.QueryParams = queryParams 29 | 30 | response, err := sendgrid.API(request) 31 | if err != nil { 32 | log.Println(err) 33 | } else { 34 | fmt.Println(response.StatusCode) 35 | fmt.Println(response.Body) 36 | fmt.Println(response.Headers) 37 | } 38 | } 39 | 40 | // GetMessagesByID : Filter messages by message ID 41 | // GET /messages/{msg_id} 42 | func GetMessagesByID() { 43 | apiKey := os.Getenv("YOUR_SENDGRID_APIKEY") 44 | host := "https://api.sendgrid.com" 45 | request := sendgrid.GetRequest(apiKey, "/v3/messages/{msg_id}", host) 46 | request.Method = "GET" 47 | response, err := sendgrid.API(request) 48 | if err != nil { 49 | log.Println(err) 50 | } else { 51 | fmt.Println(response.StatusCode) 52 | fmt.Println(response.Body) 53 | fmt.Println(response.Headers) 54 | } 55 | } 56 | 57 | // RequestCSV : Request a CSV 58 | // POST /messages/download 59 | func RequestCSV() { 60 | apiKey := os.Getenv("YOUR_SENDGRID_APIKEY") 61 | host := "https://api.sendgrid.com" 62 | request := sendgrid.GetRequest(apiKey, "/v3/messages/download", host) 63 | request.Method = "POST" 64 | response, err := sendgrid.API(request) 65 | if err != nil { 66 | log.Println(err) 67 | } else { 68 | fmt.Println(response.StatusCode) 69 | fmt.Println(response.Body) 70 | fmt.Println(response.Headers) 71 | } 72 | } 73 | 74 | // DownloadCSV : Download CSV 75 | // GET /messages/download/{download_uuid} 76 | func DownloadCSV() { 77 | apiKey := os.Getenv("YOUR_SENDGRID_APIKEY") 78 | host := "https://api.sendgrid.com" 79 | request := sendgrid.GetRequest(apiKey, "/v3/messages/download/{download_uuid}", host) 80 | request.Method = "GET" 81 | response, err := sendgrid.API(request) 82 | if err != nil { 83 | log.Println(err) 84 | } else { 85 | fmt.Println(response.StatusCode) 86 | fmt.Println(response.Body) 87 | fmt.Println(response.Headers) 88 | } 89 | } 90 | 91 | func main() { 92 | // add your function calls here 93 | } 94 | -------------------------------------------------------------------------------- /use-cases/transactional-templates-with-mailer-helper.md: -------------------------------------------------------------------------------- 1 | ## Transactional Templates - With Mail Helper Class 2 | 3 | ```go 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/sendgrid/sendgrid-go" 9 | "github.com/sendgrid/sendgrid-go/helpers/mail" 10 | "os" 11 | ) 12 | 13 | func main() { 14 | m := mail.NewV3Mail() 15 | 16 | address := "test@example.com" 17 | name := "Example User" 18 | e := mail.NewEmail(name, address) 19 | m.SetFrom(e) 20 | 21 | m.SetTemplateID("d-c6dcf1f72bdd4beeb15a9aa6c72fcd2c") 22 | 23 | p := mail.NewPersonalization() 24 | tos := []*mail.Email{ 25 | mail.NewEmail("Example User", "test1@example.com"), 26 | } 27 | p.AddTos(tos...) 28 | 29 | p.SetDynamicTemplateData("receipt", "true") 30 | p.SetDynamicTemplateData("total", "$ 239.85") 31 | 32 | items := []struct { 33 | text string 34 | image string 35 | price string 36 | }{ 37 | {"New Line Sneakers", "https://marketing-image-production.s3.amazonaws.com/uploads/8dda1131320a6d978b515cc04ed479df259a458d5d45d58b6b381cae0bf9588113e80ef912f69e8c4cc1ef1a0297e8eefdb7b270064cc046b79a44e21b811802.png", "$ 79.95"}, 38 | {"Old Line Sneakers", "https://marketing-image-production.s3.amazonaws.com/uploads/3629f54390ead663d4eb7c53702e492de63299d7c5f7239efdc693b09b9b28c82c924225dcd8dcb65732d5ca7b7b753c5f17e056405bbd4596e4e63a96ae5018.png", "$ 79.95"}, 39 | {"Blue Line Sneakers", "https://marketing-image-production.s3.amazonaws.com/uploads/00731ed18eff0ad5da890d876c456c3124a4e44cb48196533e9b95fb2b959b7194c2dc7637b788341d1ff4f88d1dc88e23f7e3704726d313c57f350911dd2bd0.png", "$ 79.95"}, 40 | } 41 | 42 | var itemList []map[string]string 43 | var item map[string]string 44 | for _, v := range items { 45 | item = make(map[string]string) 46 | item["text"] = v.text 47 | item["image"] = v.image 48 | item["price"] = v.price 49 | itemList = append(itemList, item) 50 | } 51 | p.SetDynamicTemplateData("items", itemList) 52 | 53 | p.SetDynamicTemplateData("name", "Sample Name") 54 | p.SetDynamicTemplateData("address01", "1234 Fake St.") 55 | p.SetDynamicTemplateData("address02", "Apt. 123") 56 | p.SetDynamicTemplateData("city", "Place") 57 | p.SetDynamicTemplateData("state", "CO") 58 | p.SetDynamicTemplateData("zip", "80202") 59 | 60 | m.AddPersonalizations(p) 61 | 62 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 63 | request.Method = "POST" 64 | var Body = mail.GetRequestBody(m) 65 | request.Body = Body 66 | response, err := sendgrid.API(request) 67 | if err != nil { 68 | fmt.Println(err) 69 | } else { 70 | fmt.Println(response.StatusCode) 71 | fmt.Println(response.Body) 72 | fmt.Println(response.Headers) 73 | } 74 | } 75 | ``` 76 | -------------------------------------------------------------------------------- /sendgrid.go: -------------------------------------------------------------------------------- 1 | package sendgrid 2 | 3 | import ( 4 | "errors" 5 | "github.com/sendgrid/rest" 6 | "net/url" 7 | ) 8 | 9 | // sendGridOptions for CreateRequest 10 | type sendGridOptions struct { 11 | Key string 12 | Endpoint string 13 | Host string 14 | Subuser string 15 | } 16 | 17 | // sendgrid host map for different regions 18 | var allowedRegionsHostMap = map[string]string{ 19 | "eu": "https://api.eu.sendgrid.com", 20 | "global": "https://api.sendgrid.com", 21 | } 22 | 23 | // GetRequest 24 | // @return [Request] a default request object 25 | func GetRequest(key, endpoint, host string) rest.Request { 26 | return createSendGridRequest(sendGridOptions{key, endpoint, host, ""}) 27 | } 28 | 29 | // GetRequestSubuser like GetRequest but with On-Behalf of Subuser 30 | // @return [Request] a default request object 31 | func GetRequestSubuser(key, endpoint, host, subuser string) rest.Request { 32 | return createSendGridRequest(sendGridOptions{key, endpoint, host, subuser}) 33 | } 34 | 35 | // createSendGridRequest create Request 36 | // @return [Request] a default request object 37 | func createSendGridRequest(sgOptions sendGridOptions) rest.Request { 38 | options := options{ 39 | "Bearer " + sgOptions.Key, 40 | sgOptions.Endpoint, 41 | sgOptions.Host, 42 | sgOptions.Subuser, 43 | } 44 | 45 | if options.Host == "" { 46 | options.Host = "https://api.sendgrid.com" 47 | } 48 | 49 | return requestNew(options) 50 | } 51 | 52 | // NewSendClient constructs a new Twilio SendGrid client given an API key 53 | func NewSendClient(key string) *Client { 54 | request := GetRequest(key, "/v3/mail/send", "") 55 | request.Method = "POST" 56 | return &Client{request} 57 | } 58 | 59 | // extractEndpoint extracts the endpoint from a baseURL 60 | func extractEndpoint(link string) (string, error) { 61 | parsedURL, err := url.Parse(link) 62 | if err != nil { 63 | return "", err 64 | } 65 | 66 | return parsedURL.Path, nil 67 | } 68 | 69 | // SetDataResidency modifies the host as per the region 70 | /* 71 | * This allows support for global and eu regions only. This set will likely expand in the future. 72 | * Global should be the default 73 | * Global region means the message should be sent through: 74 | * HTTP: api.sendgrid.com 75 | * EU region means the message should be sent through: 76 | * HTTP: api.eu.sendgrid.com 77 | */ 78 | // @return [Request] the modified request object 79 | func SetDataResidency(request rest.Request, region string) (rest.Request, error) { 80 | regionalHost, present := allowedRegionsHostMap[region] 81 | if !present { 82 | return request, errors.New("error: region can only be \"eu\" or \"global\"") 83 | } 84 | endpoint, err := extractEndpoint(request.BaseURL) 85 | if err != nil { 86 | return request, err 87 | } 88 | request.BaseURL = regionalHost + endpoint 89 | return request, nil 90 | } 91 | -------------------------------------------------------------------------------- /examples/categories/categories.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/sendgrid/sendgrid-go" 9 | ) 10 | 11 | // Retrieveallcategories : Retrieve all categories 12 | // GET /categories 13 | func Retrieveallcategories() { 14 | apiKey := os.Getenv("SENDGRID_API_KEY") 15 | host := "https://api.sendgrid.com" 16 | request := sendgrid.GetRequest(apiKey, "/v3/categories", host) 17 | request.Method = "GET" 18 | queryParams := make(map[string]string) 19 | queryParams["category"] = "test_string" 20 | queryParams["limit"] = "1" 21 | queryParams["offset"] = "1" 22 | request.QueryParams = queryParams 23 | response, err := sendgrid.API(request) 24 | if err != nil { 25 | log.Println(err) 26 | } else { 27 | fmt.Println(response.StatusCode) 28 | fmt.Println(response.Body) 29 | fmt.Println(response.Headers) 30 | } 31 | } 32 | 33 | // RetrieveEmailStatisticsforCategories : Retrieve Email Statistics for Categories 34 | // GET /categories/stats 35 | func RetrieveEmailStatisticsforCategories() { 36 | apiKey := os.Getenv("SENDGRID_API_KEY") 37 | host := "https://api.sendgrid.com" 38 | request := sendgrid.GetRequest(apiKey, "/v3/categories/stats", host) 39 | request.Method = "GET" 40 | queryParams := make(map[string]string) 41 | queryParams["end_date"] = "2016-04-01" 42 | queryParams["aggregated_by"] = "day" 43 | queryParams["limit"] = "1" 44 | queryParams["offset"] = "1" 45 | queryParams["start_date"] = "2016-01-01" 46 | queryParams["categories"] = "test_string" 47 | request.QueryParams = queryParams 48 | response, err := sendgrid.API(request) 49 | if err != nil { 50 | log.Println(err) 51 | } else { 52 | fmt.Println(response.StatusCode) 53 | fmt.Println(response.Body) 54 | fmt.Println(response.Headers) 55 | } 56 | } 57 | 58 | // Retrievesumsofemailstatsforeachcategory : Retrieve sums of email stats for each category [Needs: Stats object -- 59 | // -- defined, has category ID?] 60 | // GET /categories/stats/sums 61 | func Retrievesumsofemailstatsforeachcategory() { 62 | apiKey := os.Getenv("SENDGRID_API_KEY") 63 | host := "https://api.sendgrid.com" 64 | request := sendgrid.GetRequest(apiKey, "/v3/categories/stats/sums", host) 65 | request.Method = "GET" 66 | queryParams := make(map[string]string) 67 | queryParams["end_date"] = "2016-04-01" 68 | queryParams["aggregated_by"] = "day" 69 | queryParams["limit"] = "1" 70 | queryParams["sort_by_metric"] = "test_string" 71 | queryParams["offset"] = "1" 72 | queryParams["start_date"] = "2016-01-01" 73 | queryParams["sort_by_direction"] = "asc" 74 | request.QueryParams = queryParams 75 | response, err := sendgrid.API(request) 76 | if err != nil { 77 | log.Println(err) 78 | } else { 79 | fmt.Println(response.StatusCode) 80 | fmt.Println(response.Body) 81 | fmt.Println(response.Headers) 82 | } 83 | } 84 | 85 | func main() { 86 | // add your function calls here 87 | } 88 | -------------------------------------------------------------------------------- /.github/workflows/test-and-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Test and Deploy 2 | on: 3 | push: 4 | branches: [ '*' ] 5 | tags: [ '*' ] 6 | pull_request: 7 | branches: [ main ] 8 | schedule: 9 | # Run automatically at 8AM PST Monday-Friday 10 | - cron: '0 15 * * 1-5' 11 | workflow_dispatch: 12 | 13 | jobs: 14 | test: 15 | name: Build & Test 16 | runs-on: ubuntu-latest 17 | timeout-minutes: 20 18 | strategy: 19 | matrix: 20 | go: [ '1.14', '1.15', '1.16', '1.17', '1.18', '1.19' ] 21 | env: 22 | DOCKER_LOGIN: ${{ secrets.DOCKER_USERNAME && secrets.DOCKER_AUTH_TOKEN }} 23 | steps: 24 | - name: Checkout sendgrid-go 25 | uses: actions/checkout@v2 26 | 27 | - name: Login to Docker Hub 28 | if: env.DOCKER_LOGIN 29 | uses: docker/login-action@v1 30 | with: 31 | username: ${{ secrets.DOCKER_USERNAME }} 32 | password: ${{ secrets.DOCKER_AUTH_TOKEN }} 33 | 34 | - name: Setup Go environment 35 | uses: actions/setup-go@v2 36 | with: 37 | go-version: ${{ matrix.go }} 38 | 39 | - name: Set Go env vars 40 | run: | 41 | echo "GOPATH=$HOME" >> $GITHUB_ENV 42 | echo "GOBIN=$HOME/bin" >> $GITHUB_ENV 43 | echo "GO111MODULE=off" >> $GITHUB_ENV 44 | 45 | - name: Install Docker Compose 46 | run: | 47 | sudo apt-get update 48 | sudo apt-get install -y docker-compose 49 | 50 | - name: Run Tests 51 | run: make test-docker 52 | 53 | deploy: 54 | name: Deploy 55 | if: success() && github.ref_type == 'tag' 56 | needs: [ test ] 57 | runs-on: ubuntu-latest 58 | steps: 59 | - name: Checkout sendgrid-go 60 | uses: actions/checkout@v2 61 | 62 | - name: Create GitHub Release 63 | uses: sendgrid/dx-automator/actions/release@main 64 | env: 65 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 66 | 67 | - name: Submit metric to Datadog 68 | uses: sendgrid/dx-automator/actions/datadog-release-metric@main 69 | env: 70 | DD_API_KEY: ${{ secrets.DATADOG_API_KEY }} 71 | 72 | notify-on-failure: 73 | name: Slack notify on failure 74 | if: failure() && github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || github.ref_type == 'tag') 75 | needs: [ test, deploy ] 76 | runs-on: ubuntu-latest 77 | steps: 78 | - uses: rtCamp/action-slack-notify@v2 79 | env: 80 | SLACK_COLOR: failure 81 | SLACK_ICON_EMOJI: ':github:' 82 | SLACK_MESSAGE: ${{ format('Test *{0}*, Deploy *{1}*, {2}/{3}/actions/runs/{4}', needs.test.result, needs.deploy.result, github.server_url, github.repository, github.run_id) }} 83 | SLACK_TITLE: Action Failure - ${{ github.repository }} 84 | SLACK_USERNAME: GitHub Actions 85 | SLACK_MSG_AUTHOR: twilio-dx 86 | SLACK_FOOTER: Posted automatically using GitHub Actions 87 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} 88 | MSG_MINIMAL: true 89 | -------------------------------------------------------------------------------- /examples/dataresidency/setRegion.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/sendgrid/rest" 9 | "github.com/sendgrid/sendgrid-go/helpers/mail" 10 | 11 | "github.com/sendgrid/sendgrid-go" 12 | ) 13 | 14 | var SAMPLE_EMAIL = "test@example.com" 15 | 16 | // SetDataResidency : Set region for sendgrid. 17 | func SetDataResidencyGlobal() { 18 | message := buildHelloEmail() 19 | request, err := buildSendgridObj("global") 20 | if err != nil { 21 | log.Println(err) 22 | } else { 23 | request.Body = mail.GetRequestBody(message) 24 | response, err := sendgrid.API(request) 25 | if err != nil { 26 | log.Println(err) 27 | } else { 28 | fmt.Println(response.StatusCode) 29 | fmt.Println(response.Body) 30 | fmt.Println(response.Headers) 31 | } 32 | } 33 | } 34 | 35 | func SetDataResidencyEu() { 36 | message := buildHelloEmail() 37 | request, err := buildSendgridObj("eu") 38 | if err != nil { 39 | log.Println(err) 40 | } else { 41 | request.Body = mail.GetRequestBody(message) 42 | response, err := sendgrid.API(request) 43 | if err != nil { 44 | log.Println(err) 45 | } else { 46 | fmt.Println(response.StatusCode) 47 | fmt.Println(response.Body) 48 | fmt.Println(response.Headers) 49 | } 50 | } 51 | } 52 | 53 | func SetDataResidencyDefault() { 54 | message := buildHelloEmail() 55 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "") 56 | request.Method = "POST" 57 | request.Body = mail.GetRequestBody(message) 58 | response, err := sendgrid.API(request) 59 | if err != nil { 60 | log.Println(err) 61 | } else { 62 | fmt.Println(response.StatusCode) 63 | fmt.Println(response.Body) 64 | fmt.Println(response.Headers) 65 | } 66 | } 67 | 68 | func buildHelloEmail() *mail.SGMailV3 { 69 | // Note that when you use this constructor an initial personalization object 70 | // is created for you. It can be accessed via 71 | // mail.personalization.get(0) as it is a List object 72 | 73 | from := mail.NewEmail("test_user", SAMPLE_EMAIL) 74 | subject := "Sending with Twilio SendGrid is Fun" 75 | to := mail.NewEmail("test_user", SAMPLE_EMAIL) 76 | plainTextContent := "and easy to do anywhere, even with Go" 77 | htmlContent := "and easy to do anywhere, even with Go" 78 | message := mail.NewSingleEmail(from, subject, to, plainTextContent, htmlContent) 79 | email := mail.NewEmail("test_user", SAMPLE_EMAIL) 80 | 81 | p := mail.NewPersonalization() 82 | p.AddTos(email) 83 | message.AddPersonalizations(p) 84 | 85 | return message 86 | } 87 | 88 | func buildSendgridObj(region string) (rest.Request, error) { 89 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "") 90 | request.Method = "POST" 91 | request, err := sendgrid.SetDataResidency(request, region) 92 | if err != nil { 93 | return request, err 94 | } 95 | return request, nil 96 | } 97 | 98 | func main() { 99 | // add your function calls here 100 | } 101 | -------------------------------------------------------------------------------- /FIRST_TIMERS.md: -------------------------------------------------------------------------------- 1 | # How To Contribute to Twilio SendGrid Repositories via GitHub 2 | Contributing to the Twilio SendGrid repositories is easy! All you need to do is find an open issue (see the bottom of this page for a list of repositories containing open issues), fix it and submit a pull request. Once you have submitted your pull request, the team can easily review it before it is merged into the repository. 3 | 4 | To make a pull request, follow these steps: 5 | 6 | 1. Log into GitHub. If you do not already have a GitHub account, you will have to create one in order to submit a change. Click the Sign up link in the upper right-hand corner to create an account. Enter your username, password, and email address. If you are an employee of Twilio SendGrid, please use your full name with your GitHub account and enter Twilio SendGrid as your company so we can easily identify you. 7 | 8 |
9 |
10 | 2. __[Fork](https://help.github.com/fork-a-repo/)__ the [sendgrid-go](https://github.com/sendgrid/sendgrid-go) repository:
11 |
12 |
13 |
14 | 3. __Clone__ your fork via the following commands:
15 |
16 | ```bash
17 | # Clone your fork of the repo into the current directory
18 | git clone https://github.com/your_username/sendgrid-go
19 | # Navigate to the newly cloned directory
20 | cd sendgrid-go
21 | # Assign the original repo to a remote called "upstream"
22 | git remote add upstream https://github.com/sendgrid/sendgrid-go
23 | ```
24 |
25 | > Don't forget to replace *your_username* in the URL by your real GitHub username.
26 |
27 | 4. __Create a new topic branch__ (off the main project development branch) to contain your feature, change, or fix:
28 |
29 | ```bash
30 | git checkout -b Hello, world!
ThanksThe Twilio SendGrid Team
", 105 | "text": "Thanks,/n The Twilio SendGrid Team" 106 | }, 107 | "sandbox_mode": { 108 | "enable": false 109 | }, 110 | "spam_check": { 111 | "enable": true, 112 | "post_to_url": "http://example.com/compliance", 113 | "threshold": 3 114 | } 115 | }, 116 | "personalizations": [ 117 | { 118 | "bcc": [ 119 | { 120 | "email": "sam.doe@example.com", 121 | "name": "Sam Doe" 122 | } 123 | ], 124 | "cc": [ 125 | { 126 | "email": "jane.doe@example.com", 127 | "name": "Jane Doe" 128 | } 129 | ], 130 | "custom_args": { 131 | "New Argument 1": "New Value 1", 132 | "activationAttempt": "1", 133 | "customerAccountNumber": "[CUSTOMER ACCOUNT NUMBER GOES HERE]" 134 | }, 135 | "headers": { 136 | "X-Accept-Language": "en", 137 | "X-Mailer": "MyApp" 138 | }, 139 | "send_at": 1409348513, 140 | "subject": "Hello, World!", 141 | "substitutions": { 142 | "id": "substitutions", 143 | "type": "object" 144 | }, 145 | "from": { 146 | "email": "bob.doe@example.com", 147 | "name": "Bob Doe" 148 | }, 149 | "to": [ 150 | { 151 | "email": "john.doe@example.com", 152 | "name": "John Doe" 153 | } 154 | ] 155 | } 156 | ], 157 | "reply_to": { 158 | "email": "sam.smith@example.com", 159 | "name": "Sam Smith" 160 | }, 161 | "sections": { 162 | "section": { 163 | ":sectionName1": "section 1 text", 164 | ":sectionName2": "section 2 text" 165 | } 166 | }, 167 | "send_at": 1409348513, 168 | "subject": "Hello, World!", 169 | "template_id": "[YOUR TEMPLATE ID GOES HERE]", 170 | "tracking_settings": { 171 | "click_tracking": { 172 | "enable": true, 173 | "enable_text": true 174 | }, 175 | "ganalytics": { 176 | "enable": true, 177 | "utm_campaign": "[NAME OF YOUR REFERRER SOURCE]", 178 | "utm_content": "[USE THIS SPACE TO DIFFERENTIATE YOUR EMAIL FROM ADS]", 179 | "utm_medium": "[NAME OF YOUR MARKETING MEDIUM e.g. email]", 180 | "utm_name": "[NAME OF YOUR CAMPAIGN]", 181 | "utm_term": "[IDENTIFY PAID KEYWORDS HERE]" 182 | }, 183 | "open_tracking": { 184 | "enable": true, 185 | "substitution_tag": "%opentrack" 186 | }, 187 | "subscription_tracking": { 188 | "enable": true, 189 | "html": "If you would like to unsubscribe and stop receiving these emails <% clickhere %>.", 190 | "substitution_tag": "<%click here%>", 191 | "text": "If you would like to unsubscribe and stop receiveing these emails <% click here %>." 192 | } 193 | } 194 | }`) 195 | response, err := sendgrid.API(request) 196 | if err != nil { 197 | log.Println(err) 198 | } else { 199 | fmt.Println(response.StatusCode) 200 | fmt.Println(response.Body) 201 | fmt.Println(response.Headers) 202 | } 203 | } 204 | 205 | func main() { 206 | // add your function calls here 207 | } 208 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Hello! Thank you for choosing to help contribute to one of the Twilio SendGrid open-source libraries. There are many ways you can contribute and help is always welcome. We simply ask that you follow the following contribution policies. 2 | 3 | All third-party contributors acknowledge that any contributions they provide will be made under the same open-source license that the open-source project is provided under. 4 | 5 | - [Improvements to the Codebase](#improvements-to-the-codebase) 6 | - [Understanding the Code Base](#understanding-the-codebase) 7 | - [Testing](#testing) 8 | - [Style Guidelines & Naming Conventions](#style-guidelines-and-naming-conventions) 9 | - [Creating a Pull Request](#creating-a-pull-request) 10 | - [Code Reviews](#code-reviews) 11 | 12 | There are a few ways to contribute, which we'll enumerate below: 13 | 14 | 15 | ## Improvements to the Codebase 16 | 17 | We welcome direct contributions to the sendgrid-go code base. Thank you! 18 | 19 | ### Development Environment ### 20 | 21 | #### Install and Run Locally #### 22 | 23 | ##### Prerequisites ##### 24 | 25 | - Go version 1.14, 1.15 or 1.16 26 | - [rest](https://github.com/sendgrid/rest) 27 | 28 | ##### Initial setup: ##### 29 | 30 | ```bash 31 | git clone https://github.com/sendgrid/sendgrid-go.git 32 | cd sendgrid-go 33 | ``` 34 | 35 | ### Environment Variables 36 | 37 | First, get your free Twilio SendGrid account [here](https://sendgrid.com/free?source=sendgrid-go). 38 | 39 | Next, update your environment with your [SENDGRID_API_KEY](https://app.sendgrid.com/settings/api_keys). 40 | 41 | ```bash 42 | echo "export SENDGRID_API_KEY='YOUR_API_KEY'" > sendgrid.env 43 | echo "sendgrid.env" >> .gitignore 44 | source ./sendgrid.env 45 | ``` 46 | 47 | ##### Execute: ##### 48 | 49 | * Check out the documentation for [Web API v3 endpoints](https://sendgrid.com/docs/API_Reference/Web_API_v3/index.html). 50 | * Review the corresponding [example](examples). 51 | * Update the file 52 | 53 | ```bash 54 | go runCheck out our spring line!
", 24 | "ip_pool": "marketing", 25 | "list_ids": [ 26 | 110, 27 | 124 28 | ], 29 | "plain_content": "Check out our spring line!", 30 | "segment_ids": [ 31 | 110 32 | ], 33 | "sender_id": 124451, 34 | "subject": "New Products for Spring!", 35 | "suppression_group_id": 42, 36 | "title": "March Newsletter" 37 | }`) 38 | response, err := sendgrid.API(request) 39 | if err != nil { 40 | log.Println(err) 41 | } else { 42 | fmt.Println(response.StatusCode) 43 | fmt.Println(response.Body) 44 | fmt.Println(response.Headers) 45 | } 46 | } 47 | 48 | // RetrieveallCampaigns : Retrieve all Campaigns 49 | // GET /campaigns 50 | func RetrieveallCampaigns() { 51 | apiKey := os.Getenv("SENDGRID_API_KEY") 52 | host := "https://api.sendgrid.com" 53 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns", host) 54 | request.Method = "GET" 55 | queryParams := make(map[string]string) 56 | queryParams["limit"] = "1" 57 | queryParams["offset"] = "1" 58 | request.QueryParams = queryParams 59 | response, err := sendgrid.API(request) 60 | if err != nil { 61 | log.Println(err) 62 | } else { 63 | fmt.Println(response.StatusCode) 64 | fmt.Println(response.Body) 65 | fmt.Println(response.Headers) 66 | } 67 | } 68 | 69 | // UpdateaCampaign : Update a Campaign 70 | // PATCH /campaigns/{campaign_id} 71 | func UpdateaCampaign() { 72 | apiKey := os.Getenv("SENDGRID_API_KEY") 73 | host := "https://api.sendgrid.com" 74 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns/{campaign_id}", host) 75 | request.Method = "PATCH" 76 | request.Body = []byte(` { 77 | "categories": [ 78 | "summer line" 79 | ], 80 | "html_content": "Check out our summer line!
", 81 | "plain_content": "Check out our summer line!", 82 | "subject": "New Products for Summer!", 83 | "title": "May Newsletter" 84 | }`) 85 | response, err := sendgrid.API(request) 86 | if err != nil { 87 | log.Println(err) 88 | } else { 89 | fmt.Println(response.StatusCode) 90 | fmt.Println(response.Body) 91 | fmt.Println(response.Headers) 92 | } 93 | } 94 | 95 | // Retrieveasinglecampaign : Retrieve a single campaign 96 | // GET /campaigns/{campaign_id} 97 | func Retrieveasinglecampaign() { 98 | apiKey := os.Getenv("SENDGRID_API_KEY") 99 | host := "https://api.sendgrid.com" 100 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns/{campaign_id}", host) 101 | request.Method = "GET" 102 | response, err := sendgrid.API(request) 103 | if err != nil { 104 | log.Println(err) 105 | } else { 106 | fmt.Println(response.StatusCode) 107 | fmt.Println(response.Body) 108 | fmt.Println(response.Headers) 109 | } 110 | } 111 | 112 | // DeleteaCampaign : Delete a Campaign 113 | // DELETE /campaigns/{campaign_id} 114 | func DeleteaCampaign() { 115 | apiKey := os.Getenv("SENDGRID_API_KEY") 116 | host := "https://api.sendgrid.com" 117 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns/{campaign_id}", host) 118 | request.Method = "DELETE" 119 | response, err := sendgrid.API(request) 120 | if err != nil { 121 | log.Println(err) 122 | } else { 123 | fmt.Println(response.StatusCode) 124 | fmt.Println(response.Body) 125 | fmt.Println(response.Headers) 126 | } 127 | } 128 | 129 | // UpdateaScheduledCampaign : Update a Scheduled Campaign 130 | // PATCH /campaigns/{campaign_id}/schedules 131 | func UpdateaScheduledCampaign() { 132 | apiKey := os.Getenv("SENDGRID_API_KEY") 133 | host := "https://api.sendgrid.com" 134 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns/{campaign_id}/schedules", host) 135 | request.Method = "PATCH" 136 | request.Body = []byte(` { 137 | "send_at": 1489451436 138 | }`) 139 | response, err := sendgrid.API(request) 140 | if err != nil { 141 | log.Println(err) 142 | } else { 143 | fmt.Println(response.StatusCode) 144 | fmt.Println(response.Body) 145 | fmt.Println(response.Headers) 146 | } 147 | } 148 | 149 | // ScheduleaCampaign : Schedule a Campaign 150 | // POST /campaigns/{campaign_id}/schedules 151 | func ScheduleaCampaign() { 152 | apiKey := os.Getenv("SENDGRID_API_KEY") 153 | host := "https://api.sendgrid.com" 154 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns/{campaign_id}/schedules", host) 155 | request.Method = "POST" 156 | request.Body = []byte(` { 157 | "send_at": 1489771528 158 | }`) 159 | response, err := sendgrid.API(request) 160 | if err != nil { 161 | log.Println(err) 162 | } else { 163 | fmt.Println(response.StatusCode) 164 | fmt.Println(response.Body) 165 | fmt.Println(response.Headers) 166 | } 167 | } 168 | 169 | // ViewScheduledTimeofaCampaign : View Scheduled Time of a Campaign 170 | // GET /campaigns/{campaign_id}/schedules 171 | func ViewScheduledTimeofaCampaign() { 172 | apiKey := os.Getenv("SENDGRID_API_KEY") 173 | host := "https://api.sendgrid.com" 174 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns/{campaign_id}/schedules", host) 175 | request.Method = "GET" 176 | response, err := sendgrid.API(request) 177 | if err != nil { 178 | log.Println(err) 179 | } else { 180 | fmt.Println(response.StatusCode) 181 | fmt.Println(response.Body) 182 | fmt.Println(response.Headers) 183 | } 184 | } 185 | 186 | // UnscheduleaScheduledCampaign : Unschedule a Scheduled Campaign 187 | // DELETE /campaigns/{campaign_id}/schedules 188 | func UnscheduleaScheduledCampaign() { 189 | apiKey := os.Getenv("SENDGRID_API_KEY") 190 | host := "https://api.sendgrid.com" 191 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns/{campaign_id}/schedules", host) 192 | request.Method = "DELETE" 193 | response, err := sendgrid.API(request) 194 | if err != nil { 195 | log.Println(err) 196 | } else { 197 | fmt.Println(response.StatusCode) 198 | fmt.Println(response.Body) 199 | fmt.Println(response.Headers) 200 | } 201 | } 202 | 203 | // SendaCampaign : Send a Campaign 204 | // POST /campaigns/{campaign_id}/schedules/now 205 | func SendaCampaign() { 206 | apiKey := os.Getenv("SENDGRID_API_KEY") 207 | host := "https://api.sendgrid.com" 208 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns/{campaign_id}/schedules/now", host) 209 | request.Method = "POST" 210 | response, err := sendgrid.API(request) 211 | if err != nil { 212 | log.Println(err) 213 | } else { 214 | fmt.Println(response.StatusCode) 215 | fmt.Println(response.Body) 216 | fmt.Println(response.Headers) 217 | } 218 | } 219 | 220 | // SendaTestCampaign : Send a Test Campaign 221 | // POST /campaigns/{campaign_id}/schedules/test 222 | func SendaTestCampaign() { 223 | apiKey := os.Getenv("SENDGRID_API_KEY") 224 | host := "https://api.sendgrid.com" 225 | request := sendgrid.GetRequest(apiKey, "/v3/campaigns/{campaign_id}/schedules/test", host) 226 | request.Method = "POST" 227 | request.Body = []byte(` { 228 | "to": "your.email@example.com" 229 | }`) 230 | response, err := sendgrid.API(request) 231 | if err != nil { 232 | log.Println(err) 233 | } else { 234 | fmt.Println(response.StatusCode) 235 | fmt.Println(response.Body) 236 | fmt.Println(response.Headers) 237 | } 238 | } 239 | 240 | func main() { 241 | // add your function calls here 242 | } 243 | -------------------------------------------------------------------------------- /helpers/inbound/inbound.go: -------------------------------------------------------------------------------- 1 | package inbound 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "mime" 8 | "mime/multipart" 9 | "net/http" 10 | "strings" 11 | ) 12 | 13 | // ParsedEmail defines a multipart parsed email 14 | // Body and Attachments are only populated if the Raw option is checked on the SendGrid inbound configuration and are named for backwards compatability 15 | type ParsedEmail struct { 16 | // Header values are raw and not pre-processed by SendGrid. They may change depending on the email client. Use carefully 17 | Headers map[string]string 18 | // Please see https://docs.sendgrid.com/for-developers/parsing-email/setting-up-the-inbound-parse-webhook to see the available fields in the email headers 19 | // all fields listed there are available within the headers map except for text which lives in the TextBody field 20 | ParsedValues map[string]string 21 | // Primary email body parsed with \n. A common approach is to Split by the \n to bring every line of the email into a string array 22 | TextBody string 23 | 24 | // Envelope expresses the exact email address that the email was addressed to and the exact email address it was from, without extra characters 25 | Envelope struct { 26 | From string `json:"from"` 27 | To []string `json:"to"` 28 | } 29 | 30 | // Attachments have been fully parsed to include the filename, size, content type and actual file for uploading or processing 31 | ParsedAttachments map[string]*EmailAttachment 32 | 33 | // Raw only 34 | Attachments map[string][]byte 35 | // accessed with text/html and text/plain. text/plain is always parsed to the TextBody field 36 | Body map[string]string 37 | 38 | rawRequest *http.Request 39 | rawValues map[string][]string 40 | withAttachments bool 41 | } 42 | 43 | // EmailAttachment defines information related to an email attachment 44 | type EmailAttachment struct { 45 | File multipart.File `json:"-"` 46 | Filename string `json:"filename"` 47 | Size int64 `json:"-"` 48 | ContentType string `json:"type"` 49 | } 50 | 51 | func newParsedEmail(request *http.Request) ParsedEmail { 52 | return ParsedEmail{ 53 | Headers: make(map[string]string), 54 | ParsedValues: make(map[string]string), 55 | ParsedAttachments: make(map[string]*EmailAttachment), 56 | 57 | Body: make(map[string]string), 58 | Attachments: make(map[string][]byte), 59 | 60 | rawRequest: request, 61 | withAttachments: false, 62 | } 63 | } 64 | 65 | // Parse parses an email using Go's multipart parser and populates the headers, and body 66 | // This method skips processing the attachment file and is therefore more performant 67 | func Parse(request *http.Request) (*ParsedEmail, error) { 68 | result := newParsedEmail(request) 69 | 70 | err := result.parse() 71 | return &result, err 72 | } 73 | 74 | // ParseWithAttachments parses an email using Go's multipart parser and populates the headers, body and processes attachments 75 | func ParseWithAttachments(request *http.Request) (*ParsedEmail, error) { 76 | result := newParsedEmail(request) 77 | result.withAttachments = true 78 | 79 | err := result.parse() 80 | return &result, err 81 | } 82 | 83 | func (email *ParsedEmail) parse() error { 84 | err := email.rawRequest.ParseMultipartForm(0) 85 | if err != nil { 86 | return err 87 | } 88 | 89 | email.rawValues = email.rawRequest.MultipartForm.Value 90 | 91 | // unmarshal the envelope 92 | if len(email.rawValues["envelope"]) > 0 { 93 | if err := json.Unmarshal([]byte(email.rawValues["envelope"][0]), &email.Envelope); err != nil { 94 | return err 95 | } 96 | } 97 | 98 | // parse included headers 99 | if len(email.rawValues["headers"]) > 0 { 100 | email.parseHeaders(email.rawValues["headers"][0]) 101 | } 102 | 103 | // apply the rest of the SendGrid fields to the headers map 104 | for k, v := range email.rawValues { 105 | if k == "text" || k == "email" || k == "headers" || k == "envelope" { 106 | continue 107 | } 108 | 109 | if len(v) > 0 { 110 | email.ParsedValues[k] = v[0] 111 | } 112 | } 113 | 114 | // apply the plain text body 115 | if len(email.rawValues["text"]) > 0 { 116 | email.TextBody = email.rawValues["text"][0] 117 | } 118 | 119 | // only included if the raw box is checked 120 | if len(email.rawValues["email"]) > 0 { 121 | email.parseRawEmail(email.rawValues["email"][0]) 122 | } 123 | 124 | // if the client chose not to parse attachments, return as is 125 | if !email.withAttachments { 126 | return nil 127 | } 128 | 129 | return email.parseAttachments(email.rawValues) 130 | } 131 | 132 | func (email *ParsedEmail) parseAttachments(values map[string][]string) error { 133 | if len(values["attachment-info"]) != 1 { 134 | return nil 135 | } 136 | // unmarshal the sendgrid parsed aspects of the email attachment into the attachment struct 137 | if err := json.Unmarshal([]byte(values["attachment-info"][0]), &email.ParsedAttachments); err != nil { 138 | return err 139 | } 140 | 141 | // range through the multipart files 142 | for key, val := range email.rawRequest.MultipartForm.File { 143 | // open the attachment file for processing 144 | file, err := val[0].Open() 145 | if err != nil { 146 | return err 147 | } 148 | 149 | // add the actual file and the size to the parsed files 150 | email.ParsedAttachments[key].File = file 151 | email.ParsedAttachments[key].Size = val[0].Size 152 | 153 | // if the file does not have a name. give it Untitled 154 | if email.ParsedAttachments[key].Filename == "" { 155 | email.ParsedAttachments[key].Filename = "Untitled" 156 | } 157 | } 158 | 159 | return nil 160 | } 161 | 162 | func (email *ParsedEmail) parseRawEmail(rawEmail string) error { 163 | sections := strings.SplitN(rawEmail, "\n\n", 2) 164 | email.parseHeaders(sections[0]) 165 | raw, err := parseMultipart(strings.NewReader(sections[1]), email.Headers["Content-Type"]) 166 | if err != nil { 167 | return err 168 | } 169 | 170 | for { 171 | emailPart, err := raw.NextPart() 172 | if err == io.EOF { 173 | return nil 174 | } 175 | rawEmailBody, err := parseMultipart(emailPart, emailPart.Header.Get("Content-Type")) 176 | if err != nil { 177 | return err 178 | } 179 | if rawEmailBody != nil { 180 | for { 181 | emailBodyPart, err := rawEmailBody.NextPart() 182 | if err == io.EOF { 183 | break 184 | } 185 | header := emailBodyPart.Header.Get("Content-Type") 186 | b, err := io.ReadAll(emailPart) 187 | if err != nil { 188 | return err 189 | } 190 | email.Body[header] = string(b) 191 | } 192 | 193 | } else if emailPart.FileName() != "" { 194 | b, err := io.ReadAll(emailPart) 195 | if err != nil { 196 | return err 197 | } 198 | email.Attachments[emailPart.FileName()] = b 199 | } else { 200 | header := emailPart.Header.Get("Content-Type") 201 | b, err := io.ReadAll(emailPart) 202 | if err != nil { 203 | return err 204 | } 205 | 206 | email.Body[header] = string(b) 207 | } 208 | } 209 | } 210 | 211 | func parseMultipart(body io.Reader, contentType string) (*multipart.Reader, error) { 212 | mediaType, params, err := mime.ParseMediaType(contentType) 213 | if err != nil { 214 | return nil, err 215 | } 216 | 217 | if strings.HasPrefix(mediaType, "multipart/") { 218 | return multipart.NewReader(body, params["boundary"]), nil 219 | } 220 | return nil, nil 221 | } 222 | 223 | func (email *ParsedEmail) parseHeaders(headers string) { 224 | splitHeaders := strings.Split(strings.TrimSpace(headers), "\n") 225 | for _, header := range splitHeaders { 226 | splitHeader := strings.SplitN(header, ": ", 2) 227 | // keeps outlook emails from causing a panic 228 | if len(splitHeader) != 2 { 229 | continue 230 | } 231 | 232 | email.Headers[splitHeader[0]] = splitHeader[1] 233 | } 234 | } 235 | 236 | // Validate validates the DKIM and SPF scores to ensure that the email client and address was not spoofed 237 | func (email *ParsedEmail) Validate() error { 238 | if len(email.rawValues["dkim"]) == 0 || len(email.rawValues["SPF"]) == 0 { 239 | return fmt.Errorf("missing DKIM and SPF score") 240 | } 241 | 242 | for _, val := range email.rawValues["dkim"] { 243 | if !strings.Contains(val, "pass") { 244 | return fmt.Errorf("DKIM validation failed") 245 | } 246 | } 247 | 248 | for _, val := range email.rawValues["SPF"] { 249 | if !strings.Contains(val, "pass") { 250 | return fmt.Errorf("SPF validation failed") 251 | } 252 | } 253 | 254 | return nil 255 | } 256 | -------------------------------------------------------------------------------- /examples/ips/ips.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/sendgrid/sendgrid-go" 9 | ) 10 | 11 | // RetrieveallIPaddresses : Retrieve all IP addresses 12 | // GET /ips 13 | func RetrieveallIPaddresses() { 14 | apiKey := os.Getenv("SENDGRID_API_KEY") 15 | host := "https://api.sendgrid.com" 16 | request := sendgrid.GetRequest(apiKey, "/v3/ips", host) 17 | request.Method = "GET" 18 | queryParams := make(map[string]string) 19 | queryParams["subuser"] = "test_string" 20 | queryParams["ip"] = "test_string" 21 | queryParams["limit"] = "1" 22 | queryParams["exclude_whitelabels"] = "true" 23 | queryParams["offset"] = "1" 24 | request.QueryParams = queryParams 25 | response, err := sendgrid.API(request) 26 | if err != nil { 27 | log.Println(err) 28 | } else { 29 | fmt.Println(response.StatusCode) 30 | fmt.Println(response.Body) 31 | fmt.Println(response.Headers) 32 | } 33 | } 34 | 35 | // RetrieveallassignedIPs : Retrieve all assigned IPs 36 | // GET /ips/assigned 37 | func RetrieveallassignedIPs() { 38 | apiKey := os.Getenv("SENDGRID_API_KEY") 39 | host := "https://api.sendgrid.com" 40 | request := sendgrid.GetRequest(apiKey, "/v3/ips/assigned", host) 41 | request.Method = "GET" 42 | response, err := sendgrid.API(request) 43 | if err != nil { 44 | log.Println(err) 45 | } else { 46 | fmt.Println(response.StatusCode) 47 | fmt.Println(response.Body) 48 | fmt.Println(response.Headers) 49 | } 50 | } 51 | 52 | // CreateanIPpool : Create an IP pool. 53 | // POST /ips/pools 54 | func CreateanIPpool() { 55 | apiKey := os.Getenv("SENDGRID_API_KEY") 56 | host := "https://api.sendgrid.com" 57 | request := sendgrid.GetRequest(apiKey, "/v3/ips/pools", host) 58 | request.Method = "POST" 59 | request.Body = []byte(` { 60 | "name": "marketing" 61 | }`) 62 | response, err := sendgrid.API(request) 63 | if err != nil { 64 | log.Println(err) 65 | } else { 66 | fmt.Println(response.StatusCode) 67 | fmt.Println(response.Body) 68 | fmt.Println(response.Headers) 69 | } 70 | } 71 | 72 | // RetrieveallIPpools : Retrieve all IP pools. 73 | // GET /ips/pools 74 | func RetrieveallIPpools() { 75 | apiKey := os.Getenv("SENDGRID_API_KEY") 76 | host := "https://api.sendgrid.com" 77 | request := sendgrid.GetRequest(apiKey, "/v3/ips/pools", host) 78 | request.Method = "GET" 79 | response, err := sendgrid.API(request) 80 | if err != nil { 81 | log.Println(err) 82 | } else { 83 | fmt.Println(response.StatusCode) 84 | fmt.Println(response.Body) 85 | fmt.Println(response.Headers) 86 | } 87 | } 88 | 89 | // UpdateanIPpoolsname : Update an IP pools name. 90 | // PUT /ips/pools/{pool_name} 91 | func UpdateanIPpoolsname() { 92 | apiKey := os.Getenv("SENDGRID_API_KEY") 93 | host := "https://api.sendgrid.com" 94 | request := sendgrid.GetRequest(apiKey, "/v3/ips/pools/{pool_name}", host) 95 | request.Method = "PUT" 96 | request.Body = []byte(` { 97 | "name": "new_pool_name" 98 | }`) 99 | response, err := sendgrid.API(request) 100 | if err != nil { 101 | log.Println(err) 102 | } else { 103 | fmt.Println(response.StatusCode) 104 | fmt.Println(response.Body) 105 | fmt.Println(response.Headers) 106 | } 107 | } 108 | 109 | // RetrieveallIPsinaspecifiedpool : Retrieve all IPs in a specified pool. 110 | // GET /ips/pools/{pool_name} 111 | func RetrieveallIPsinaspecifiedpool() { 112 | apiKey := os.Getenv("SENDGRID_API_KEY") 113 | host := "https://api.sendgrid.com" 114 | request := sendgrid.GetRequest(apiKey, "/v3/ips/pools/{pool_name}", host) 115 | request.Method = "GET" 116 | response, err := sendgrid.API(request) 117 | if err != nil { 118 | log.Println(err) 119 | } else { 120 | fmt.Println(response.StatusCode) 121 | fmt.Println(response.Body) 122 | fmt.Println(response.Headers) 123 | } 124 | } 125 | 126 | // DeleteanIPpool : Delete an IP pool. 127 | // DELETE /ips/pools/{pool_name} 128 | func DeleteanIPpool() { 129 | apiKey := os.Getenv("SENDGRID_API_KEY") 130 | host := "https://api.sendgrid.com" 131 | request := sendgrid.GetRequest(apiKey, "/v3/ips/pools/{pool_name}", host) 132 | request.Method = "DELETE" 133 | response, err := sendgrid.API(request) 134 | if err != nil { 135 | log.Println(err) 136 | } else { 137 | fmt.Println(response.StatusCode) 138 | fmt.Println(response.Body) 139 | fmt.Println(response.Headers) 140 | } 141 | } 142 | 143 | // AddanIPaddresstoapool : Add an IP address to a pool 144 | // POST /ips/pools/{pool_name}/ips 145 | func AddanIPaddresstoapool() { 146 | apiKey := os.Getenv("SENDGRID_API_KEY") 147 | host := "https://api.sendgrid.com" 148 | request := sendgrid.GetRequest(apiKey, "/v3/ips/pools/{pool_name}/ips", host) 149 | request.Method = "POST" 150 | request.Body = []byte(` { 151 | "ip": "0.0.0.0" 152 | }`) 153 | response, err := sendgrid.API(request) 154 | if err != nil { 155 | log.Println(err) 156 | } else { 157 | fmt.Println(response.StatusCode) 158 | fmt.Println(response.Body) 159 | fmt.Println(response.Headers) 160 | } 161 | } 162 | 163 | // RemoveanIPaddressfromapool : Remove an IP address from a pool. 164 | // DELETE /ips/pools/{pool_name}/ips/{ip} 165 | func RemoveanIPaddressfromapool() { 166 | apiKey := os.Getenv("SENDGRID_API_KEY") 167 | host := "https://api.sendgrid.com" 168 | request := sendgrid.GetRequest(apiKey, "/v3/ips/pools/{pool_name}/ips/{ip}", host) 169 | request.Method = "DELETE" 170 | response, err := sendgrid.API(request) 171 | if err != nil { 172 | log.Println(err) 173 | } else { 174 | fmt.Println(response.StatusCode) 175 | fmt.Println(response.Body) 176 | fmt.Println(response.Headers) 177 | } 178 | } 179 | 180 | // AddanIPtowarmup : Add an IP to warmup 181 | // POST /ips/warmup 182 | func AddanIPtowarmup() { 183 | apiKey := os.Getenv("SENDGRID_API_KEY") 184 | host := "https://api.sendgrid.com" 185 | request := sendgrid.GetRequest(apiKey, "/v3/ips/warmup", host) 186 | request.Method = "POST" 187 | request.Body = []byte(` { 188 | "ip": "0.0.0.0" 189 | }`) 190 | response, err := sendgrid.API(request) 191 | if err != nil { 192 | log.Println(err) 193 | } else { 194 | fmt.Println(response.StatusCode) 195 | fmt.Println(response.Body) 196 | fmt.Println(response.Headers) 197 | } 198 | } 199 | 200 | // RetrieveallIPscurrentlyinwarmup : Retrieve all IPs currently in warmup 201 | // GET /ips/warmup 202 | func RetrieveallIPscurrentlyinwarmup() { 203 | apiKey := os.Getenv("SENDGRID_API_KEY") 204 | host := "https://api.sendgrid.com" 205 | request := sendgrid.GetRequest(apiKey, "/v3/ips/warmup", host) 206 | request.Method = "GET" 207 | response, err := sendgrid.API(request) 208 | if err != nil { 209 | log.Println(err) 210 | } else { 211 | fmt.Println(response.StatusCode) 212 | fmt.Println(response.Body) 213 | fmt.Println(response.Headers) 214 | } 215 | } 216 | 217 | // RetrievewarmupstatusforaspecificIPaddress : Retrieve warmup status for a specific IP address 218 | // GET /ips/warmup/{ip_address} 219 | func RetrievewarmupstatusforaspecificIPaddress() { 220 | apiKey := os.Getenv("SENDGRID_API_KEY") 221 | host := "https://api.sendgrid.com" 222 | request := sendgrid.GetRequest(apiKey, "/v3/ips/warmup/{ip_address}", host) 223 | request.Method = "GET" 224 | response, err := sendgrid.API(request) 225 | if err != nil { 226 | log.Println(err) 227 | } else { 228 | fmt.Println(response.StatusCode) 229 | fmt.Println(response.Body) 230 | fmt.Println(response.Headers) 231 | } 232 | } 233 | 234 | // RemoveanIPfromwarmup : Remove an IP from warmup 235 | // DELETE /ips/warmup/{ip_address} 236 | func RemoveanIPfromwarmup() { 237 | apiKey := os.Getenv("SENDGRID_API_KEY") 238 | host := "https://api.sendgrid.com" 239 | request := sendgrid.GetRequest(apiKey, "/v3/ips/warmup/{ip_address}", host) 240 | request.Method = "DELETE" 241 | response, err := sendgrid.API(request) 242 | if err != nil { 243 | log.Println(err) 244 | } else { 245 | fmt.Println(response.StatusCode) 246 | fmt.Println(response.Body) 247 | fmt.Println(response.Headers) 248 | } 249 | } 250 | 251 | // RetrieveallIPpoolsanIPaddressbelongsto : Retrieve all IP pools an IP address belongs to 252 | // GET /ips/{ip_address} 253 | func RetrieveallIPpoolsanIPaddressbelongsto() { 254 | apiKey := os.Getenv("SENDGRID_API_KEY") 255 | host := "https://api.sendgrid.com" 256 | request := sendgrid.GetRequest(apiKey, "/v3/ips/{ip_address}", host) 257 | request.Method = "GET" 258 | response, err := sendgrid.API(request) 259 | if err != nil { 260 | log.Println(err) 261 | } else { 262 | fmt.Println(response.StatusCode) 263 | fmt.Println(response.Body) 264 | fmt.Println(response.Headers) 265 | } 266 | } 267 | 268 | func main() { 269 | // add your function calls here 270 | } 271 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | [](https://github.com/sendgrid/sendgrid-go/actions/workflows/test-and-deploy.yml) 4 | [](https://godoc.org/github.com/sendgrid/sendgrid-go) 5 | [](LICENSE) 6 | [](https://twitter.com/sendgrid) 7 | [](https://github.com/sendgrid/sendgrid-go/graphs/contributors) 8 | [](https://www.codetriage.com/sendgrid/sendgrid-go) 9 | 10 | **This library allows you to quickly and easily use the Twilio SendGrid Web API v3 via Go.** 11 | 12 | Version 3.X.X of this library provides full support for all Twilio SendGrid [Web API v3](https://sendgrid.com/docs/API_Reference/Web_API_v3/index.html) endpoints, including the new [v3 /mail/send](https://sendgrid.com/blog/introducing-v3mailsend-sendgrids-new-mail-endpoint). 13 | 14 | This library represents the beginning of a new path for Twilio SendGrid. We want this library to be community driven and Twilio SendGrid led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create [issues](https://github.com/sendgrid/sendgrid-go/issues) and [pull requests](CONTRIBUTING.md) or simply upvote or comment on existing issues or pull requests. 15 | 16 | **If you need help using SendGrid, please check the [Twilio SendGrid Support Help Center](https://support.sendgrid.com).** 17 | 18 | # Table of Contents 19 | 20 | * [Installation](#installation) 21 | * [Quick Start](#quick-start) 22 | * [Processing Inbound Email](#inbound) 23 | * [Usage](#usage) 24 | * [Use Cases](#use-cases) 25 | * [Announcements](#announcements) 26 | * [How to Contribute](#contribute) 27 | * [Troubleshooting](#troubleshooting) 28 | * [About](#about) 29 | * [License](#license) 30 | 31 | 32 | # Installation 33 | 34 | ## Supported Versions 35 | 36 | This library supports the following Go implementations: 37 | 38 | * Go 1.14 39 | * Go 1.15 40 | * Go 1.16 41 | * Go 1.17 42 | * Go 1.18 43 | * Go 1.19 44 | 45 | ## Prerequisites 46 | 47 | - The Twilio SendGrid service, starting at the [free level](https://sendgrid.com/free?source=sendgrid-go), to send up to 40,000 emails for the first 30 days, then send 100 emails/day free forever or check out [our pricing](https://sendgrid.com/pricing?source=sendgrid-go). 48 | 49 | ## Setup Environment Variables 50 | 51 | Update the development environment with your [SENDGRID_API_KEY](https://app.sendgrid.com/settings/api_keys), for example: 52 | 53 | ```bash 54 | echo "export SENDGRID_API_KEY='YOUR_API_KEY'" > sendgrid.env 55 | echo "sendgrid.env" >> .gitignore 56 | source ./sendgrid.env 57 | ``` 58 | 59 | ## Install Package 60 | 61 | `go get github.com/sendgrid/sendgrid-go` 62 | 63 | ## Dependencies 64 | 65 | - [rest](https://github.com/sendgrid/rest) 66 | 67 | ## Setup Environment Variables 68 | 69 | ### Initial Setup 70 | 71 | ```bash 72 | cp .env_sample .env 73 | ``` 74 | 75 | ### Environment Variable 76 | 77 | Update the development environment with your [SENDGRID_API_KEY](https://app.sendgrid.com/settings/api_keys), for example: 78 | 79 | ```bash 80 | echo "export SENDGRID_API_KEY='YOUR_API_KEY'" > sendgrid.env 81 | echo "sendgrid.env" >> .gitignore 82 | source ./sendgrid.env 83 | ``` 84 | 85 | 86 | # Quick Start 87 | 88 | ## Hello Email 89 | 90 | The following is the minimum needed code to send an email with the [/mail/send Helper](helpers/mail) ([here](examples/helpers/mail/example.go#L32) is a full example): 91 | 92 | ### With Mail Helper Class 93 | 94 | ```go 95 | package main 96 | 97 | import ( 98 | "fmt" 99 | "log" 100 | "os" 101 | 102 | "github.com/sendgrid/sendgrid-go" 103 | "github.com/sendgrid/sendgrid-go/helpers/mail" 104 | ) 105 | 106 | func main() { 107 | from := mail.NewEmail("Example User", "test@example.com") 108 | subject := "Sending with Twilio SendGrid is Fun" 109 | to := mail.NewEmail("Example User", "test@example.com") 110 | plainTextContent := "and easy to do anywhere, even with Go" 111 | htmlContent := "and easy to do anywhere, even with Go" 112 | message := mail.NewSingleEmail(from, subject, to, plainTextContent, htmlContent) 113 | client := sendgrid.NewSendClient(os.Getenv("SENDGRID_API_KEY")) 114 | response, err := client.Send(message) 115 | if err != nil { 116 | log.Println(err) 117 | } else { 118 | fmt.Println(response.StatusCode) 119 | fmt.Println(response.Body) 120 | fmt.Println(response.Headers) 121 | } 122 | } 123 | ``` 124 | 125 | The `NewEmail` constructor creates a [personalization object](https://sendgrid.com/docs/Classroom/Send/v3_Mail_Send/personalizations.html) for you. [Here](examples/helpers/mail/example.go#L28) is an example of how to add to it. 126 | 127 | ### Without Mail Helper Class 128 | 129 | The following is the minimum needed code to send an email without the /mail/send Helper ([here](examples/mail/mail.go#L47) is a full example): 130 | 131 | ```go 132 | package main 133 | 134 | import ( 135 | "fmt" 136 | "github.com/sendgrid/sendgrid-go" 137 | "log" 138 | "os" 139 | ) 140 | 141 | func main() { 142 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/mail/send", "https://api.sendgrid.com") 143 | request.Method = "POST" 144 | request.Body = []byte(` { 145 | "personalizations": [ 146 | { 147 | "to": [ 148 | { 149 | "email": "test@example.com" 150 | } 151 | ], 152 | "subject": "Sending with Twilio SendGrid is Fun" 153 | } 154 | ], 155 | "from": { 156 | "email": "test@example.com" 157 | }, 158 | "content": [ 159 | { 160 | "type": "text/plain", 161 | "value": "and easy to do anywhere, even with Go" 162 | } 163 | ] 164 | }`) 165 | response, err := sendgrid.API(request) 166 | if err != nil { 167 | log.Println(err) 168 | } else { 169 | fmt.Println(response.StatusCode) 170 | fmt.Println(response.Body) 171 | fmt.Println(response.Headers) 172 | } 173 | } 174 | ``` 175 | 176 | ## General v3 Web API Usage 177 | 178 | ```go 179 | package main 180 | 181 | import ( 182 | "fmt" 183 | "github.com/sendgrid/sendgrid-go" 184 | "log" 185 | "os" 186 | ) 187 | 188 | func main() { 189 | request := sendgrid.GetRequest(os.Getenv("SENDGRID_API_KEY"), "/v3/api_keys", "https://api.sendgrid.com") 190 | request.Method = "GET" 191 | 192 | response, err := sendgrid.API(request) 193 | if err != nil { 194 | log.Println(err) 195 | } else { 196 | fmt.Println(response.StatusCode) 197 | fmt.Println(response.Body) 198 | fmt.Println(response.Headers) 199 | } 200 | } 201 | ``` 202 | 203 | 204 | 205 | # Processing Inbound Email 206 | 207 | Please see [our helper](helpers/inbound) for utilizing our Inbound Parse webhook. 208 | 209 | 210 | # Usage 211 | 212 | - [Twilio SendGrid Docs](https://sendgrid.com/docs/API_Reference/index.html) 213 | - [Library Usage Docs](USAGE.md) 214 | - [Example Code](examples) 215 | - [How-to: Migration from v2 to v3](https://sendgrid.com/docs/Classroom/Send/v3_Mail_Send/how_to_migrate_from_v2_to_v3_mail_send.html) 216 | - [v3 Web API Mail Send Helper](helpers/mail/README.md) 217 | 218 | 219 | # Use Cases 220 | 221 | [Examples of common API use cases](use-cases/README.md), such as how to send an email with a transactional template. 222 | 223 | 224 | # Announcements 225 | 226 | All updates to this library are documented in our [CHANGELOG](CHANGELOG.md) and [releases](https://github.com/sendgrid/sendgrid-go/releases). 227 | 228 | 229 | # How to Contribute 230 | 231 | We encourage contribution to our libraries (you might even score some nifty swag), please see our [CONTRIBUTING](CONTRIBUTING.md) guide for details. 232 | 233 | Quick links: 234 | 235 | - [Feature Request](CONTRIBUTING.md#feature-request) 236 | - [Bug Reports](CONTRIBUTING.md#submit-a-bug-report) 237 | - [Improvements to the Codebase](CONTRIBUTING.md#improvements-to-the-codebase) 238 | - [Review Pull Requests](CONTRIBUTING.md#code-reviews) 239 | 240 | 241 | # Troubleshooting 242 | 243 | Please see our [troubleshooting guide](TROUBLESHOOTING.md) for common library issues. 244 | 245 | 246 | # About 247 | 248 | sendgrid-go is maintained and funded by Twilio SendGrid, Inc. The names and logos for sendgrid-go are trademarks of Twilio SendGrid, Inc. 249 | 250 | 251 | # Support 252 | 253 | If you need help using SendGrid, please check the [Twilio SendGrid Support Help Center](https://support.sendgrid.com). 254 | 255 | # License 256 | [The MIT License (MIT)](LICENSE) 257 | -------------------------------------------------------------------------------- /examples/asm/asm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | 8 | "github.com/sendgrid/sendgrid-go" 9 | ) 10 | 11 | // Createanewsuppressiongroup : Create a new suppression group 12 | // POST /asm/groups 13 | func Createanewsuppressiongroup() { 14 | apiKey := os.Getenv("SENDGRID_API_KEY") 15 | host := "https://api.sendgrid.com" 16 | request := sendgrid.GetRequest(apiKey, "/v3/asm/groups", host) 17 | request.Method = "POST" 18 | request.Body = []byte(` { 19 | "description": "Suggestions for products our users might like.", 20 | "is_default": true, 21 | "name": "Product Suggestions" 22 | }`) 23 | response, err := sendgrid.API(request) 24 | if err != nil { 25 | log.Println(err) 26 | } else { 27 | fmt.Println(response.StatusCode) 28 | fmt.Println(response.Body) 29 | fmt.Println(response.Headers) 30 | } 31 | } 32 | 33 | // Retrieveinformationaboutmultiplesuppressiongroups : Retrieve information about multiple suppression groups 34 | // GET /asm/groups 35 | func Retrieveinformationaboutmultiplesuppressiongroups() { 36 | apiKey := os.Getenv("SENDGRID_API_KEY") 37 | host := "https://api.sendgrid.com" 38 | request := sendgrid.GetRequest(apiKey, "/v3/asm/groups", host) 39 | request.Method = "GET" 40 | queryParams := make(map[string]string) 41 | queryParams["id"] = "1" 42 | request.QueryParams = queryParams 43 | response, err := sendgrid.API(request) 44 | if err != nil { 45 | log.Println(err) 46 | } else { 47 | fmt.Println(response.StatusCode) 48 | fmt.Println(response.Body) 49 | fmt.Println(response.Headers) 50 | } 51 | } 52 | 53 | // Updateasuppressiongroup : Update a suppression group. 54 | // PATCH /asm/groups/{group_id} 55 | func Updateasuppressiongroup() { 56 | apiKey := os.Getenv("SENDGRID_API_KEY") 57 | host := "https://api.sendgrid.com" 58 | request := sendgrid.GetRequest(apiKey, "/v3/asm/groups/{group_id}", host) 59 | request.Method = "PATCH" 60 | request.Body = []byte(` { 61 | "description": "Suggestions for items our users might like.", 62 | "id": 103, 63 | "name": "Item Suggestions" 64 | }`) 65 | response, err := sendgrid.API(request) 66 | if err != nil { 67 | log.Println(err) 68 | } else { 69 | fmt.Println(response.StatusCode) 70 | fmt.Println(response.Body) 71 | fmt.Println(response.Headers) 72 | } 73 | } 74 | 75 | // Getinformationonasinglesuppressiongroup : Get information on a single suppression group. 76 | // GET /asm/groups/{group_id} 77 | func Getinformationonasinglesuppressiongroup() { 78 | apiKey := os.Getenv("SENDGRID_API_KEY") 79 | host := "https://api.sendgrid.com" 80 | request := sendgrid.GetRequest(apiKey, "/v3/asm/groups/{group_id}", host) 81 | request.Method = "GET" 82 | response, err := sendgrid.API(request) 83 | if err != nil { 84 | log.Println(err) 85 | } else { 86 | fmt.Println(response.StatusCode) 87 | fmt.Println(response.Body) 88 | fmt.Println(response.Headers) 89 | } 90 | } 91 | 92 | // Deleteasuppressiongroup : Delete a suppression group. 93 | // DELETE /asm/groups/{group_id} 94 | func Deleteasuppressiongroup() { 95 | apiKey := os.Getenv("SENDGRID_API_KEY") 96 | host := "https://api.sendgrid.com" 97 | request := sendgrid.GetRequest(apiKey, "/v3/asm/groups/{group_id}", host) 98 | request.Method = "DELETE" 99 | response, err := sendgrid.API(request) 100 | if err != nil { 101 | log.Println(err) 102 | } else { 103 | fmt.Println(response.StatusCode) 104 | fmt.Println(response.Body) 105 | fmt.Println(response.Headers) 106 | } 107 | } 108 | 109 | // Addsuppressionstoasuppressiongroup : Add suppressions to a suppression group 110 | // POST /asm/groups/{group_id}/suppressions 111 | func Addsuppressionstoasuppressiongroup() { 112 | apiKey := os.Getenv("SENDGRID_API_KEY") 113 | host := "https://api.sendgrid.com" 114 | request := sendgrid.GetRequest(apiKey, "/v3/asm/groups/{group_id}/suppressions", host) 115 | request.Method = "POST" 116 | request.Body = []byte(` { 117 | "recipient_emails": [ 118 | "test1@example.com", 119 | "test2@example.com" 120 | ] 121 | }`) 122 | response, err := sendgrid.API(request) 123 | if err != nil { 124 | log.Println(err) 125 | } else { 126 | fmt.Println(response.StatusCode) 127 | fmt.Println(response.Body) 128 | fmt.Println(response.Headers) 129 | } 130 | } 131 | 132 | // Retrieveallsuppressionsforasuppressiongroup : Retrieve all suppressions for a suppression group 133 | // GET /asm/groups/{group_id}/suppressions 134 | func Retrieveallsuppressionsforasuppressiongroup() { 135 | apiKey := os.Getenv("SENDGRID_API_KEY") 136 | host := "https://api.sendgrid.com" 137 | request := sendgrid.GetRequest(apiKey, "/v3/asm/groups/{group_id}/suppressions", host) 138 | request.Method = "GET" 139 | response, err := sendgrid.API(request) 140 | if err != nil { 141 | log.Println(err) 142 | } else { 143 | fmt.Println(response.StatusCode) 144 | fmt.Println(response.Body) 145 | fmt.Println(response.Headers) 146 | } 147 | } 148 | 149 | // Searchforsuppressionswithinagroup : Search for suppressions within a group 150 | // POST /asm/groups/{group_id}/suppressions/search 151 | func Searchforsuppressionswithinagroup() { 152 | apiKey := os.Getenv("SENDGRID_API_KEY") 153 | host := "https://api.sendgrid.com" 154 | request := sendgrid.GetRequest(apiKey, "/v3/asm/groups/{group_id}/suppressions/search", host) 155 | request.Method = "POST" 156 | request.Body = []byte(` { 157 | "recipient_emails": [ 158 | "exists1@example.com", 159 | "exists2@example.com", 160 | "doesnotexists@example.com" 161 | ] 162 | }`) 163 | response, err := sendgrid.API(request) 164 | if err != nil { 165 | log.Println(err) 166 | } else { 167 | fmt.Println(response.StatusCode) 168 | fmt.Println(response.Body) 169 | fmt.Println(response.Headers) 170 | } 171 | } 172 | 173 | // Deleteasuppressionfromasuppressiongroup : Delete a suppression from a suppression group 174 | // DELETE /asm/groups/{group_id}/suppressions/{email} 175 | func Deleteasuppressionfromasuppressiongroup() { 176 | apiKey := os.Getenv("SENDGRID_API_KEY") 177 | host := "https://api.sendgrid.com" 178 | request := sendgrid.GetRequest(apiKey, "/v3/asm/groups/{group_id}/suppressions/{email}", host) 179 | request.Method = "DELETE" 180 | response, err := sendgrid.API(request) 181 | if err != nil { 182 | log.Println(err) 183 | } else { 184 | fmt.Println(response.StatusCode) 185 | fmt.Println(response.Body) 186 | fmt.Println(response.Headers) 187 | } 188 | } 189 | 190 | // Retrieveallsuppressions : Retrieve all suppressions 191 | // GET /asm/suppressions 192 | func Retrieveallsuppressions() { 193 | apiKey := os.Getenv("SENDGRID_API_KEY") 194 | host := "https://api.sendgrid.com" 195 | request := sendgrid.GetRequest(apiKey, "/v3/asm/suppressions", host) 196 | request.Method = "GET" 197 | response, err := sendgrid.API(request) 198 | if err != nil { 199 | log.Println(err) 200 | } else { 201 | fmt.Println(response.StatusCode) 202 | fmt.Println(response.Body) 203 | fmt.Println(response.Headers) 204 | } 205 | } 206 | 207 | // Addrecipientaddressestotheglobalsuppressiongroup : Add recipient addresses to the global suppression group. 208 | // POST /asm/suppressions/global 209 | func Addrecipientaddressestotheglobalsuppressiongroup() { 210 | apiKey := os.Getenv("SENDGRID_API_KEY") 211 | host := "https://api.sendgrid.com" 212 | request := sendgrid.GetRequest(apiKey, "/v3/asm/suppressions/global", host) 213 | request.Method = "POST" 214 | request.Body = []byte(` { 215 | "recipient_emails": [ 216 | "test1@example.com", 217 | "test2@example.com" 218 | ] 219 | }`) 220 | response, err := sendgrid.API(request) 221 | if err != nil { 222 | log.Println(err) 223 | } else { 224 | fmt.Println(response.StatusCode) 225 | fmt.Println(response.Body) 226 | fmt.Println(response.Headers) 227 | } 228 | } 229 | 230 | // RetrieveaGlobalSuppression : Retrieve a Global Suppression 231 | // GET /asm/suppressions/global/{email} 232 | func RetrieveaGlobalSuppression() { 233 | apiKey := os.Getenv("SENDGRID_API_KEY") 234 | host := "https://api.sendgrid.com" 235 | request := sendgrid.GetRequest(apiKey, "/v3/asm/suppressions/global/{email}", host) 236 | request.Method = "GET" 237 | response, err := sendgrid.API(request) 238 | if err != nil { 239 | log.Println(err) 240 | } else { 241 | fmt.Println(response.StatusCode) 242 | fmt.Println(response.Body) 243 | fmt.Println(response.Headers) 244 | } 245 | } 246 | 247 | // DeleteaGlobalSuppression : Delete a Global Suppression 248 | // DELETE /asm/suppressions/global/{email} 249 | func DeleteaGlobalSuppression() { 250 | apiKey := os.Getenv("SENDGRID_API_KEY") 251 | host := "https://api.sendgrid.com" 252 | request := sendgrid.GetRequest(apiKey, "/v3/asm/suppressions/global/{email}", host) 253 | request.Method = "DELETE" 254 | response, err := sendgrid.API(request) 255 | if err != nil { 256 | log.Println(err) 257 | } else { 258 | fmt.Println(response.StatusCode) 259 | fmt.Println(response.Body) 260 | fmt.Println(response.Headers) 261 | } 262 | } 263 | 264 | // Retrieveallsuppressiongroupsforanemailaddress : Retrieve all suppression groups for an email address 265 | // GET /asm/suppressions/{email} 266 | func Retrieveallsuppressiongroupsforanemailaddress() { 267 | apiKey := os.Getenv("SENDGRID_API_KEY") 268 | host := "https://api.sendgrid.com" 269 | request := sendgrid.GetRequest(apiKey, "/v3/asm/suppressions/{email}", host) 270 | request.Method = "GET" 271 | response, err := sendgrid.API(request) 272 | if err != nil { 273 | log.Println(err) 274 | } else { 275 | fmt.Println(response.StatusCode) 276 | fmt.Println(response.Body) 277 | fmt.Println(response.Headers) 278 | } 279 | } 280 | 281 | func main() { 282 | // add your function calls here 283 | } 284 | --------------------------------------------------------------------------------