emailgmailgoogle-oauthlibcurlsmtp-auth

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


I know that others already posted similar questions, but all the tips there did not help. I try to send with SMTP using a google account and XOAuth2. I use libcurl 7.71.1 on Windows.

To get the bearer token, I call the following URL in users webbrowser:

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

The site opens and, after successful authentication, it calls my localhost port 8100 and sends me the token like this:

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

NOTE: I changed the token and IDs in this post so I do not get a security issue here by posting.

Side quest: Here, I answer with some 200 code, but the auth page still waits for something?

[UPDATE]

Now I use this code for compiling a request to the token url and I send like this as a POST form (values changed for security reasons, so sad it does not work as a GET call):

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

Upon this, I get a json back:

{
"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"
}

Now I use the access_token as bearer.

[/UPDATE]

I then submit the values to libcurl like this:

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)

This is what curl does then:

(...)
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

If I decode the b64 encoded result behind 334, it means

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

What I already tried:

Is there anything else for me to find out why it is not working?


Solution

  • For any other struggling with the same issue, this is how I solved it:

    First I followed the guidelines and used only the scope for sending:

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

    This did not work!

    Turns out that it works immediately, after I set the scope to

    https://mail.google.com