使用 google xoauth2 的 SMTP 会导致错误 {“status”:“400”,“schemes”:“Bearer”,“scope”:“https://mail.google.com/”}

SMTP with google xoauth2 results in error {"status":"400","schemes":"Bearer","scope":"https://mail.google.com/"}

提问人:Volker 提问时间:10/5/2023 最后编辑:Volker 更新时间:10/10/2023 访问量:51

问:

我知道其他人已经发布了类似的问题,但那里的所有提示都没有帮助。我尝试使用 google 帐户和 XOAuth2 使用 SMTP 发送。我在 Windows 上使用 libcurl 7.71.1。

为了获取持有者令牌,我在用户 Web 浏览器中调用以下 URL:

https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&response_mode=query&prompt=consent&client_id=123456789876-d5pdtc7hl0p1n822cnjh7tf3qbcpqno1.apps.googleusercontent.com&login_hint=mymail%40gmail.com&redirect_uri=http%3A%2F%2Flocalhost%3A8100%2Fmyapp&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.send&state=xsf11765042151615245894

站点打开,身份验证成功后,它调用我的 localhost 端口 8100 并向我发送令牌,如下所示:

GET /myapp?state=xsf11765042151615245894&code=4/1AfJohXmrJc2GD-CGAk7OG7X5o7myvDymYZX-jUJG8s3WKbF63qy8wmt2_ziNTSqU2svQ2g&scope=https://www.googleapis.com/auth/gmail.send HTTP/1.1

注意:我在这篇文章中更改了令牌和 ID,因此我不会在这里发布安全问题。

支线任务:在这里,我用大约 200 个代码来回答,但身份验证页面还在等待什么?

[更新]

现在我使用此代码来编译对令牌 url 的请求,并像这样作为 POST 表单发送(出于安全原因更改了值,遗憾的是它不能用作 GET 调用):

Host: oauth2.googleapis.com
Accept: */*
Content-Length: 765
Content-Type: multipart/form-data
Content-Disposition: form-data; 
name="client_secret" GOCSPX-fds5mklfrw8cdnr42cdsc

name="grant_type" authorization_code
name="redirect_uri" http://localhost:8100/myapp
name="code" 4/0AfJohXkgfdcvgSujuj1Wxd8F4QwHipzJ4dcd5LD9mzh9oAw2Hph-Re8j7YoC-OvpxI4Axw
name="client_id" 123456789876-d5pdtc7hl0p1n822cnjh7tf3qbcpqno1.apps.googleusercontent.com

在此之后,我得到一个 json:

{
"access_token": "yt21.a6AfC_btretdfmit59nuvfd8zu9g5novgfdvt3-Qudygl1J2YHnz9EDuN5vxnvH4bKMDAhrrZCQh_cLiTdUbFeljavGH7HLl3nVVET1JrFgGPXL-wP5c6YX9qIjpGA9_narMf-AIkEOO4RDGXJQW4gJ_b9aCgYKAZESARESFQGOcNnCqOhXBKQK3Op-eEoN_pLqiQ0171",
"expires_in": 3599,
"refresh_token": "1//09MmzKo6J7xxFCfgdsmkt543mkvcxjgt4F-vfdimof542jucofdnuvifwe_VTD4bzu3176txgswzub-Zsqlvn9M15XCCuzO3GKfw",
"scope": "https://www.googleapis.com/auth/gmail.send",
"token_type": "Bearer"
}

现在我使用access_token作为承载。

[/更新]

然后,我将值提交到 libcurl,如下所示:

sbBearerToken = "yt21.a6AfC_btretdfmit59nuvfd8zu9g5novgfdvt3-Qudygl1J2YHnz9EDuN5vxnvH4bKMDAhrrZCQh_cLiTdUbFeljavGH7HLl3nVVET1JrFgGPXL-wP5c6YX9qIjpGA9_narMf-AIkEOO4RDGXJQW4gJ_b9aCgYKAZESARESFQGOcNnCqOhXBKQK3Op-eEoN_pLqiQ0171" // extracted from above call result json

curl_easy_setopt(curl_Handle, #CURLOPT_USE_SSL, #CURLUSESSL_ALL)
curl_easy_setopt(curl_Handle, #CURLOPT_USERNAME, @sbSMTPUsername)
curl_easy_setopt(curl_Handle, #CURLOPT_HTTPAUTH, #CURLAUTH_BEARER)
curl_easy_setopt(curl_Handle, #CURLOPT_XOAUTH2_BEARER, @sbBearerToken)

这就是 curl 的作用:

(...)
CURL: STARTTLS                                                                                                                                
CURL: 220 2.0.0 Ready to start TLS                                                                                                            
CURL: EHLO DESKTOP-LKLNJ7V                                                                                                                    
CURL: 250-smtp.gmail.com at your service, [62.26.97.31]                                                                                       
CURL: 250-SIZE 35882577                                                                                                                       
CURL: 250-8BITMIME                                                                                                                            
CURL: 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH                                                                       
CURL: 250-ENHANCEDSTATUSCODES                                                                                                                 
CURL: 250-PIPELINING                                                                                                                          
CURL: 250-CHUNKING                                                                                                                            
CURL: 250 SMTPUTF8                                                                                                                            
CURL: AUTH XOAUTH2 dXNlc....iRjYzcXk
CURL: 334 eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==                                    
CURL: Closing connection 0                                                                                                                    
CURL: schannel: shutting down SSL/TLS connection with smtp.gmail.com port 25                                                                  
Error performing GET. Curl ec:67

如果我解码 b64 后面的 b334 编码结果,这意味着

{"status":"400","schemes":"Bearer","scope":"https://mail.google.com/"}

我已经尝试过:

还有什么可以让我找出它不起作用的原因吗?

电子邮件 gmail google-oauth libcurl smtp-auth

评论


答:

0赞 Linda Lawton - DaImTo 10/5/2023 #1

代码=4/1AfJohXmrJc2GD-CGAk7OG7X5o7myvDymYZX-jUJG8s3WKbF63qy8wmt2_ziNTSqU2svQ2g

这是授权代码,而不是访问令牌。

您需要将授权代码交换为访问令牌。

POST https://accounts.google.com/o/oauth2/token
code=[CODE]&client_id=[ClientId]&redirect_uri=[redirectURI]&grant_type=authorization_code

评论

0赞 Volker 10/5/2023
谢谢!看起来我忘记了整个第二部分:-(我现在实施了这一步。但结果保持不变。最后是完全相同的错误。我刚刚更新了整个过程的初始问题(参见 [update] 标签)。
0赞 Volker 10/9/2023 #2

对于任何其他为同一问题而苦苦挣扎的人,我是这样解决的:

首先,我遵循了指南,仅使用发送范围:

https://www.googleapis.com/auth/gmail.send

这没有用!

事实证明,在我将范围设置为

https://mail.google.com