去sendgrid失败

Im trying to send a mail with sendgrid and golang. Im using "github.com/sendgrid/sendgrid-go"

Whenever I run the part sending email in my code, I get this error:

sendgrid.go: error:net/http: Client Transport of type init.failingTransport doesn't support CancelRequest; Timeout not supported; response:<nil>

I cant figure out what it is..

This is my code:

sg := sendgrid.NewSendGridClientWithApiKey("string")
    email := sendgrid.NewMail()
    email.AddTo(req.Email)
    email.SetSubject("Confirm your registration at domain")
    email.SetFrom("noreply@domain.com")
    email.SetFromName("domain")
    email.SetText(url)
    if r := sg.Send(email); r == nil {
        log.Infof(ctx, "email sent")
    } else {
        log.Errorf(ctx, "email not sent %v", r)
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

Normal Sendgrid API Usage in Go

The minimal program to use the Sendgrid API in Go is something like the following:

package main

import (
    "fmt"
    "github.com/sendgrid/sendgrid-go"
)

func main() {
    key := "SENDGRID_API_KEY"
    sg := sendgrid.NewSendGridClientWithApiKey(key)

    message := sendgrid.NewMail()
    message.AddTo("ezra@usefultiftrue.com")
    message.SetFrom("test@example.org")
    message.SetSubject("SUBJECT HERE")
    message.SetHTML("BODY OF THE EMAIL")

    if r := sg.Send(message); r == nil {
        fmt.Println("Sent!")
    } else {
        fmt.Println(r)
    }
}

You can see the Sendgrid Go Documentation on Github.

Quirks on App Engine

The issue is that you're attempting to fetch a Url using the default net/http client, which is not allowed by App Engine. You must use urlfetch to make HTTP requests on App Engine.

You can solve this by specifying your *http.Client to use urlfetch, since Sendgrid uses a client that uses the disallowed http.DefaultTransport by default. init.failingTransport is a dummy transport method that basically just throws an error.

This is ultimately a simple change. Simply import "appengine/urlfetch" and add

client := urlfetch.Client(ctx)

A Complete Example of the SendGrid Go API on App Engine

package ezralalonde

import (
    "appengine"
    "appengine/urlfetch"
    "fmt"
    "github.com/sendgrid/sendgrid-go"
    "net/http"
)

func send(w http.ResponseWriter, r *http.Request) {
    key := "SENDGRID_API_KEY"
    sg := sendgrid.NewSendGridClientWithApiKey(key)

    // must change the net/http client to not use default transport
    ctx := appengine.NewContext(r)
    client := urlfetch.Client(ctx)
    sg.Client = client // <-- now using urlfetch, "overriding" default

    message := sendgrid.NewMail()
    message.AddTo("ezra@usefultiftrue.com")
    message.SetFrom("test@example.org")
    message.SetSubject("SUBJECT HERE")
    message.SetHTML("BODY OF THE EMAIL")

    if e := sg.Send(message); e == nil {
        fmt.Fprintln(w, "Sent!")
    } else {
        fmt.Fprintln(w, e)
    }
}

func init() {
    http.HandleFunc("/", send)
}

Now each visit to / will cause an email to be sent by SendGrid to test@example.org.

To: test@example.org
From: ezra@usefuliftrue.com
Subject: SUBJECT HERE

BODY OF THE EMAIL

Please Note

Do not include your API keys in source code, or commit them to your source control. The above method is not advisable.