Has there been any update on the new oAuth2 class/functions?
I'm using FWH 2023.06 and xHarbour.
Where can I find the HttpPost function?
Can I use Curl with these versions and if so, what do I need?
Thanks,
Randal
Has there been any update on the new oAuth2 class/functions?
I'm using FWH 2023.06 and xHarbour.
Where can I find the HttpPost function?
Can I use Curl with these versions and if so, what do I need?
Thanks,
Randal
Dear Randal,
In FWH 25.01 there is a new Class TOAuth and a Class TGmail that inherits from TOAuth, both developed by Lailton and a samples\gmail\testgmail.prg example
Buenos días.
El ejemplo al que haces referencia menciona un archivo readme.rd :
"// USE Your ID and Secret Key. check README.md"
Este archivo no está en la carpeta gmail.
Quisiera saber como obtengo mi ID y Clave Secreta que se menciona, o a que refiere.
Muchas Gracias.
https://cloud.google.com/gcpSi no te funciona el anterior enlace, busca Console Google Cloud
En Google Cloud Console, el ID de clave y la clave secreta (o clave API) se utilizan para autenticar las solicitudes a las API de Google. El ID de clave es un identificador único de la clave, mientras que la clave secreta es el secreto que se utiliza para generar tokens de autorización.
Cómo encontrar o crear claves de API (ID y clave secreta):
En la Consola de Google Cloud: Ve a la sección "APIs & Services" y luego a "Credentials".
Crea una clave API: Selecciona "Create Credentials" y luego "API Key".
Acepta la clave API: La clave API recién creada se mostrará en la consola.
ID de cliente de OAuth 2.0: Si necesitas un ID de cliente y un secreto de cliente para OAuth, selecciona "OAuth client ID" en lugar de "API Key".
Cuentas de servicio: Para cuentas de servicio, puedes generar una clave en formato JSON que contiene el ID de cliente y la clave secreta.
Dónde encontrar la clave secreta:
Después de crear una clave API: La clave API se mostrará en el diálogo de creación.
Para claves de cuentas de servicio: Se te proporcionará la clave secreta en el archivo JSON de la clave.
Para OAuth 2.0: El ID de cliente y el secreto de cliente se mostrarán en la consola después de la creación.
xxxx-ncpllhkbr7hu8e78fn6lcctvsepsi142.apps.googleusercontent.comxxxx-JEhuFwW6AnGHjfShV-buEkYrirvD oGmail:setConfig( {;
"client_id" => "xxxx-ncpllhkbr7hu8e78fn6lcctvsepsi142.apps.googleusercontent.com",;
"client_secret" => "xxxx-JEhuFwW6AnGHjfShV-buEkYrirvD",;
"redirect_uri" => "http://localhost:2025/";
} )openid
https://www.googleapis.com/auth/userinfo.profile
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/gmail.sendfreeimage64.dll
libcurl.dll
libssl-3-x64.dll
zlib1.dll # =============================================
# PowerShell All-in-One: Gmail API E-Mailversand
# =============================================
# === Konfiguration: Zugangsdaten deiner Google API ===
$client_id = "DEINE_CLIENT_ID"
$client_secret = "DEIN_CLIENT_SECRET"
$redirect_uri = "http://localhost" # Muss mit deiner OAuth2-App übereinstimmen
$tokenFile = "token.json"
# === Deine E-Mail-Daten ===
$to = "empfaenger@example.com"
$subject = "Testmail über Gmail API"
$body = "Hallo! Diese Nachricht wurde mit PowerShell und der Gmail API gesendet."
# === Hilfsfunktionen ===
function Load-Token {
if (Test-Path $tokenFile) {
return Get-Content $tokenFile | ConvertFrom-Json
}
return $null
}
function Save-Token($data) {
$data | ConvertTo-Json | Set-Content -Encoding UTF8 $tokenFile
}
function Get-AccessToken {
$tokenData = Load-Token
if (-not $tokenData -or -not $tokenData.refresh_token) {
Write-Host "🔐 Kein Token gefunden. Starte erstmalige Autorisierung..."
$scope = "https://www.googleapis.com/auth/gmail.send"
$auth_url = "https://accounts.google.com/o/oauth2/v2/auth?" +
"client_id=$client_id&redirect_uri=$redirect_uri&response_type=code" +
"&scope=$scope&access_type=offline&prompt=consent"
Start-Process $auth_url
$code = Read-Host "`n❓ Bitte den Autorisierungscode von Google eingeben"
$response = Invoke-RestMethod `
-Uri "https://oauth2.googleapis.com/token" `
-Method POST `
-Body @{
code = $code
client_id = $client_id
client_secret = $client_secret
redirect_uri = $redirect_uri
grant_type = "authorization_code"
} `
-ContentType "application/x-www-form-urlencoded"
if ($response.access_token) {
$tokenData = @{
access_token = $response.access_token
refresh_token = $response.refresh_token
expires_in = $response.expires_in
obtained_at = (Get-Date).ToString("s")
}
Save-Token $tokenData
Write-Host "✅ Erstes Login erfolgreich. Token gespeichert."
} else {
Write-Host "⛔ Fehler beim Abrufen des Tokens."
exit
}
}
$refresh_token = $tokenData.refresh_token
$response = Invoke-RestMethod `
-Uri "https://oauth2.googleapis.com/token" `
-Method POST `
-Body @{
client_id = $client_id
client_secret = $client_secret
refresh_token = $refresh_token
grant_type = "refresh_token"
} `
-ContentType "application/x-www-form-urlencoded"
if ($response.access_token) {
$tokenData.access_token = $response.access_token
$tokenData.obtained_at = (Get-Date).ToString("s")
Save-Token $tokenData
return $response.access_token
} else {
Write-Host "⛔ Fehler beim Token-Refresh."
exit
}
}
function Send-GmailMail($access_token, $to, $subject, $body) {
$msg = "From: me`r`nTo: $to`r`nSubject: $subject`r`nContent-Type: text/plain; charset=UTF-8`r`n`r`n$body"
$bytes = [System.Text.Encoding]::UTF8.GetBytes($msg)
$base64 = [System.Convert]::ToBase64String($bytes) `
-replace '\+', '-' `
-replace '/', '_' `
-replace '='
$json = @{ raw = $base64 } | ConvertTo-Json -Compress
$response = Invoke-RestMethod `
-Uri "https://gmail.googleapis.com/gmail/v1/users/me/messages/send" `
-Method POST `
-Headers @{ Authorization = "Bearer $access_token" } `
-ContentType "application/json" `
-Body $json
Write-Host "📤 E-Mail wurde gesendet!"
}
# === Hauptablauf ===
$access_token = Get-AccessToken
Send-GmailMail -access_token $access_token -to $to -subject $subject -body $bodyHello Lailton,
Thank you for your input. I suggested the PowerShell-based approach not because TGmail doesn’t work – but because we, as Harbour developers, will inevitably have to consider PowerShell (and other external tools) more seriously in the future.
The reason is simple: Harbour developer resources are limited, and maintaining internal solutions for everything (like MIME encoding, token handling, API changes) is not scalable. PowerShell, on the other hand, is natively available on all modern Windows systems, well-documented, actively maintained by Microsoft, and easily automatable.
When wrapped securely – with encrypted configs and compiled .exe wrappers – PowerShell becomes a maintainable and robust companion to Harbour. It allows us to focus Harbour on what it does best: core logic and UI, while offloading complex tasks to specialized, scriptable tools.
This isn’t a workaround – it’s a strategic design decision based on sustainability and maintainability. and just because something is embedded in a .prg doesn’t mean it's inherently safer. In fact, access tokens or secrets stored inside a Harbour .exe can be extracted just as easily.
Best regards,
Otto