【问题标题】:How to use SendGrid from Google App Engine Golang?如何从 Google App Engine Golang 使用 SendGrid?
【发布时间】:2018-04-01 07:55:02
【问题描述】:

示例代码位于:https://sendgrid.com/blog/send-email-go-google-app-engine/

我猜这是在 Google App Engine 上使用 sendgrid-go 的非常古老的示例代码。

我尝试了 4 次排列,但每次都失败了:

https://api.sendgrid.com/v3/mail/send: http.DefaultTransport and http.DefaultClient are not available in App Engine. See https://cloud.google.com/appengine/docs/go/urlfetch/

这里是一些记录的最小硬编码尝试:

package sendgridgo


import(
    "github.com/sendgrid/sendgrid-go"
    "fmt"
    _"google.golang.org/appengine"
    "net/http"
    "google.golang.org/appengine/log"
    "google.golang.org/appengine"
    "google.golang.org/appengine/urlfetch"
     _ "github.com/sendgrid/sendgrid-go/helpers/mail"
)

func init(){
    http.HandleFunc("/", IndexHandler)
    appengine.Main()
}

func IndexHandler (w http.ResponseWriter, r *http.Request){
    ctx := appengine.NewContext(r)

    log.Infof(ctx, "IndexHandler")
    sg := sendgrid.NewSendClient("SENDGRID_API_KEY")
    log.Infof(ctx, "%v", sg)
    bob := urlfetch.Client(ctx)

    log.Infof(ctx, "UrlFetchClient %v", bob)
    //resp, err := sg.Send(m)
    request := sendgrid.GetRequest("SENDGRID_API_KEY", "/v3/mail/send", "https://api.sendgrid.com")
    request.Method = "POST"

    request.Body = []byte(` {
    "personalizations": [
        {
            "to": [
                {
                    "email": "darian.hickman@gmail.com"
                }
            ],
            "subject": "Sending with SendGrid is Fun"
        }
    ],
    "from": {
        "email": "darian.hickman@villagethegame.com"
    },
    "content": [
        {
            "type": "text/plain",
            "value": "and easy to do anywhere, even with Go"
        }
    ]
}`)
    resp, err := sendgrid.API(request)

    if err != nil{
        log.Errorf(ctx, "Failed %v", err)
    }

    fmt.Fprint(w, resp)


}

【问题讨论】:

  • 不要公开分享您的 API 密钥。
  • v3 包有一个DefaultClient 变量。您是否尝试将其设置为 bob

标签: google-app-engine go sendgrid urlfetch sendgrid-api-v3


【解决方案1】:

经过 8 次不同的尝试,包括尝试在 Google Cloud 文档中发布的使用 Sendgrid 的示例、来自 Sendgrid 博客的示例,以及尝试使用已弃用的 Sendgrid api 版本,我在以下位置找到了 Sendgrid curl 示例:

https://sendgrid.com/docs/Classroom/Send/v3_Mail_Send/curl_examples.html

curl --request POST \
  --url https://api.sendgrid.com/v3/mail/send \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{"personalizations": [{"to": [{"email": "recipient@example.com"}]}],"from": {"email": "sendeexampexample@example.com"},"subject": "Hello, World!","content": [{"type": "text/plain", "value": "Heya!"}]}'

然后我将 HelloWorld 示例翻译成 URLFetch 用法

client := urlfetch.Client(ctx)

request, err := http.NewRequest("POST", "https://api.sendgrid.com/v3/mail/send", buf)
    if err != nil {
        log.Errorf(ctx, "Failed Request %v", request)
    }
    request.Header.Set("Authorization", "Bearer SENDGRID_API_KEY")
    request.Header.Set("Content-Type", "application/json")
    resp, err := client.Do(request)

一个复活节周末,稍后,它起作用了!

【讨论】:

    【解决方案2】:

    您在正确的轨道上,但跳过了用urlfetch 客户端覆盖默认的sendgrid 客户端。

    .
    .
    .
    func IndexHandler (w http.ResponseWriter, r *http.Request){
        ctx := appengine.NewContext(r)    
        sg := sendgrid.NewSendClient("REPLACE_WITH_API_KEY")
        bob := urlfetch.Client(ctx)
    
        sg.Client = bob
    
        request := sendgrid.GetRequest("REPLACE_WITH_API_KEY", "/v3/mail/send", "https://api.sendgrid.com")
        request.Method = "POST"
    .
    .
    .
    

    说明

    当 sendgrid 尝试使用默认的 net/http 方法获取 url 时发生错误。

    引用 AppEngine 文档

    App Engine 使用 URL Fetch 服务来发出出站 HTTP(S) 请求。要发出出站 HTTP 请求,请照常使用 http 包,但使用 urlfetch.Client 创建客户端。 urlfetch.Client 返回一个使用 urlfetch.Transport 的 *http.Client,它是使用 URL Fetch API 发出请求的 http.RoundTripper 接口的实现。

    解决方法是覆盖 Sendgrid 客户端以使用 urlfetch

            context := appengine.NewContext(r)
            sg := sendgrid.NewSendClient(os.Getenv("SENDGRID_API_KEY"))
            sg.Client = urlfetch.Client(context)
    

    参考文献

    1. GCloud Documentation- Issuing HTTP(S) Requests in App Engine Golang

    【讨论】:

    • 很好的答案,我赞成。值得注意的是,GAE 对它可以做的事情有很多限制(GAE 沙箱),我们的 URLFetch 方法基本上是为了确保我们不需要向用户公开本机 net/http 方法。跨度>
    • 最新的sendgrid-go包版本没有sg.Client。它甚至不会编译。我尝试了几种不同的解决方法并放弃了。
    • 当我找到使用旧的 Sendgrid v2 api 的导入语句:“gopkg.in/sendgrid/sendgrid-go.v2”时,我得到它来编译和运行,但是 sendgrid 返回错误的用户名 /传递每一次尝试。埋在他们的文档中的某个地方是:“您不能将 API 密钥用于任何早于 v3 的东西”。
    • @Darian311 来自 v2 github 页面上的文档,它说如果您使用 api 密钥,则需要使用 sendgrid.NewSendGridClientWithApiKey 而不是 sendgrid.NewSendGridClient
    【解决方案3】:

    解决方案记录在 sendgrid.go 中:

    // DefaultClient is used if no custom HTTP client is defined
    var DefaultClient = rest.DefaultClient
    

    所以只需在发送开始时执行此操作,其中 ctxappengine.NewContext(req)

    sendgrid.DefaultClient = &rest.Client{HTTPClient: urlfetch.Client(ctx)}
    

    【讨论】:

    • 这对我来说非常有效,在 Google App Angine Standard 上使用 go 1.11,最新示例来自 github 上 sendgrid 的 go library v3 示例。谢谢!
    【解决方案4】:

    SendGrid 记录在 AppEngine 中使用 Go 发送电子邮件所需的最少代码 How to send email using Go。它与@birju-prajapati 的回答不同;客户端是使用sendgrid.NewSendClient 创建的。

    必须生成 API 密钥并使用您的 SENDGRID_API_KEY 更新您的开发环境。然后使用 go get github.com/sendgrid/sendgrid-go 安装 sendgrid-go 及其依赖项。

    // using SendGrid's Go Library
    // https://github.com/sendgrid/sendgrid-go
    package main
    
    import (
        "fmt"
        "log"
        "os"
    
        "github.com/sendgrid/sendgrid-go"
        "github.com/sendgrid/sendgrid-go/helpers/mail"
    )
    
    func main() {
        from := mail.NewEmail("Example User", "test@example.com")
        subject := "Sending with SendGrid is Fun"
        to := mail.NewEmail("Example User", "test@example.com")
        plainTextContent := "and easy to do anywhere, even with Go"
        htmlContent := "<strong>and easy to do anywhere, even with Go</strong>"
        message := mail.NewSingleEmail(from, subject, to, plainTextContent, htmlContent)
        client := sendgrid.NewSendClient(os.Getenv("SENDGRID_API_KEY"))
        response, err := client.Send(message)
        if err != nil {
            log.Println(err)
        } else {
            fmt.Println(response.StatusCode)
            fmt.Println(response.Body)
            fmt.Println(response.Headers)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-01
      • 2012-09-30
      • 2016-03-04
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多