New FWH 25.01
Posted: Wed Feb 19, 2025 8:16 am
www.FiveTechSoft.com
https://forums.fivetechsupport.com/
I think it is an initiative by laiton maybe antonio is not awareJack wrote: Wed Feb 19, 2025 3:14 pm Hi
What about this :
We will provide support for the oAuth2 on the next version FWH
with samples to send e-mail using GMail/Outlook(Office365).
Thanks,
Philippe
It is coming. We will publish an updated FWH 25.01 asap.Jack wrote: Wed Feb 19, 2025 3:14 pm Hi
What about this :
We will provide support for the oAuth2 on the next version FWH
with samples to send e-mail using GMail/Outlook(Office365).
Thanks,
Philippe
Code: Select all | Expand
#include "fivewin.ch"
static oGmail, hStore
function main()
local oDlg
local oName, cName := ""
local oEmail, cEmail := ""
local oPhoto, oSend
local oConnect, oDisconnect
hStore := readStore( hb_dirBase() + "gmail.json" )
oGmail := TGmail():new()
oGmail:setConfig( {;
"client_id" => "your_client_id",;
"client_secret" => "your_client_secret",;
"redirect_uri" => "http://localhost:2025/";
} )
if !empty( hStore[ "token" ] )
oGmail:setToken( hStore[ "token" ] )
endif
define dialog oDlg resource "GMAIL"
redefine image oPhoto id 4002 of oDlg
redefine say oName var cName id 4003 of oDlg
redefine say oEmail var cEmail id 4004 of oDlg
redefine button oDisconnect id 4005 of oDlg action onDisconnect( oDlg, { oPhoto, oName, oEmail, oSend, oDisconnect }, { oConnect } )
redefine button oSend id 4006 of oDlg action onSendMail()
redefine button oConnect id 4001 of oDlg action onConnect( oDlg, { oPhoto, oName, oEmail, oSend, oDisconnect }, { oConnect } )
oDlg:bStart := { || updateControls( oDlg, { oPhoto, oName, oEmail, oSend, oDisconnect }, { oConnect } ) }
oDlg:lHelpIcon := .f.
activate dialog oDlg centered
saveStore( hb_dirBase() + "gmail.json", hStore )
return nil
function onConnect( oDlg, aConnect, aDisconnect )
local cToken
if !oGmail:isAuth()
cToken := oGmail:auth()
if !empty( cToken )
hStore[ "token" ] := cToken
else
msgStop( "Authentication failed!" )
endif
endif
updateControls( oDlg, aConnect, aDisconnect )
return nil
function onDisconnect( oDlg, aConnect, aDisconnect )
local cProfile := hb_dirBase() + "profile_gmail.jpg"
oGmail:revoke()
updateControls( oDlg, aConnect, aDisconnect )
if hb_vfExists( cProfile )
hb_vfErase( cProfile )
endif
return nil
function onSendMail()
if oGmail:send( "lailton@paysoft.com.br", "it is a test", "<b>Message from Gmail oAuth2</b>", .t., {} )
msgInfo( "Mail sent!" )
else
msgStop( "Failed to send email. You may not have authorized the required permissions..." )
endif
return nil
function updateControls( oDlg, aConnect, aDisconnect )
local hUser
local cProfile := hb_dirBase() + "profile_gmail.jpg"
if oGmail:isAuth()
hUser := oGmail:me()
endif
aEval( aConnect, { |o| o:hide() } )
aEval( aDisconnect, { |o| o:hide() } )
if hb_isHash( hUser )
aEval( aConnect, {|o|o:show(),o:refresh()} )
if !hb_vfExists( cProfile )
oGmail:downloadUrl( hUser[ "picture" ], cProfile )
endif
// Load Profile Photo
if hb_vfExists( cProfile )
aConnect[1]:loadImage(, cProfile )
aConnect[1]:refresh()
endif
aConnect[2]:setText( hUser[ "name" ] )
aConnect[3]:setText( hUser[ "email" ] )
aConnect[2]:update()
aConnect[3]:update()
else
aEval( aDisconnect, {|o|o:show(),o:refresh()} )
endif
oDlg:update()
return nil
function readStore( cFile )
local hStore
if hb_vfExists( cFile )
hStore := hb_jsonDecode( hb_memoRead( cFile ) )
endif
if !hb_isHash( hStore )
hStore := {;
"token" => "";
}
endif
return hStore
function saveStore( cFile, hStore )
hb_memoWrit( cFile, hb_jsonEncode( hStore ) )
return hb_vfExists( cFile )
Yes, It is TGmail. on the next days I will add too the version for Office365 following same idea.
I remember Cristobal made a Tgmail class some year ago
Code: Select all | Expand
#include "FiveWin.ch"
FUNCTION SendEmail()
LOCAL cUrl, cData, cResponse
LOCAL cAccessToken := "YOUR_ACCESS_TOKEN" // Get token via OAuth2
LOCAL cMessage := '{"message": {"subject": "Test Email", "body": {"contentType": "Text", "content": "Hello, this is a test email!"}, "toRecipients": [{"emailAddress": {"address": "example@domain.com"}}]}}'
cUrl := "https://graph.microsoft.com/v1.0/me/sendMail"
cData := cMessage
cResponse := HttpPostRequest(cUrl, cData, "Authorization: Bearer " + cAccessToken)
IF !Empty(cResponse)
MsgInfo("Email sent successfully!", "Success")
ELSE
MsgError("Failed to send email.", "Error")
ENDIF
RETURN
Code: Select all | Expand
CLASS Tgmail
DATA cClientId // OAuth2 Client ID
DATA cClientSecret // OAuth2 Client Secret
DATA cRedirectUri // Redirect URI
DATA cAccessToken // OAuth2 Access Token
DATA cRefreshToken // OAuth2 Refresh Token
DATA cAuthUrl // Authorization URL
METHOD Init( cClientId, cClientSecret, cRedirectUri )
METHOD GetAuthorizationUrl()
METHOD GetAccessToken( cCode )
METHOD SendEmail( cSubject, cBody, cRecipient )
ENDCLASS
// Constructor for Tgmail class
METHOD Init( cClientId, cClientSecret, cRedirectUri )
::cClientId := cClientId
::cClientSecret := cClientSecret
::cRedirectUri := cRedirectUri
::cAuthUrl := "https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/gmail.send&response_type=code&redirect_uri=" + SELF:cRedirectUri + "&client_id=" + SELF:cClientId
RETURN NIL
// Method to get the authorization URL
METHOD GetAuthorizationUrl()
RETURN ::cAuthUrl
// Method to get access token using authorization code
METHOD GetAccessToken( cCode )
LOCAL cUrl, cData, cResponse, cTokenUrl
LOCAL aJson
cTokenUrl := "https://oauth2.googleapis.com/token"
cData := "code=" + cCode + ;
"&client_id=" + ::cClientId + ;
"&client_secret=" + ::cClientSecret + ;
"&redirect_uri=" + ::cRedirectUri + ;
"&grant_type=authorization_code"
// Request to get the token
cResponse := HttpPostRequest( cTokenUrl, cData, "" )
IF !Empty(cResponse)
aJson := JsonParse( cResponse )
::cAccessToken := aJson[ "access_token" ]
::cRefreshToken := aJson[ "refresh_token" ]
RETURN .T.
ELSE
RETURN .F.
ENDIF
// Method to send an email via GMail
METHOD SendEmail( cSubject, cBody, cRecipient )
LOCAL cUrl, cMessage, cRaw, cResponse
// Prepare the message in MIME format
cRaw := "From: 'me'\r\n" + ;
"To: " + cRecipient + "\r\n" + ;
"Subject: " + cSubject + "\r\n" + ;
"Content-Type: text/plain; charset=UTF-8\r\n\r\n" + ;
cBody
// Encode the message in base64
cRaw := Base64Encode( cRaw )
// Build the request body
cMessage := '{"raw": "' + cRaw + '"}'
// URL to send the message
cUrl := "https://gmail.googleapis.com/upload/gmail/v1/users/me/messages/send?uploadType=multipart"
// Send HTTP request with access token
cResponse := HttpPostRequest( cUrl, cMessage, "Authorization: Bearer " + ::cAccessToken )
IF !Empty(cResponse)
RETURN .T.
ELSE
RETURN .F.
ENDIF
RETURN NIL
Code: Select all | Expand
LOCAL oGmail
oGmail := Tgmail():New()
Code: Select all | Expand
oGmail:Init( "YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "YOUR_REDIRECT_URI" )
Code: Select all | Expand
LOCAL cAuthUrl
cAuthUrl := oGmail:GetAuthorizationUrl()
MsgInfo( "Visita questo URL per autorizzare l'app: " + cAuthUrl, "Autorizzazione OAuth2" )
Code: Select all | Expand
LOCAL cCode, lSuccess
cCode := "AUTHORIZATION_CODE_OBTAINED_FROM_USER" // Ottieni il codice di autorizzazione
lSuccess := oGmail:GetAccessToken( cCode )
IF lSuccess
MsgInfo( "Token di accesso ottenuto!", "Successo" )
ELSE
MsgError( "Errore durante l'ottenimento del token.", "Errore" )
ENDIF
Code: Select all | Expand
LOCAL lSuccess
lSuccess := oGmail:SendEmail( "Test Email", "Ciao, questa è una prova di invio email!", "recipient@example.com" )
IF lSuccess
MsgInfo( "Email inviata con successo!", "Successo" )
ELSE
MsgError( "Errore durante l'invio dell'email.", "Errore" )
ENDIF
Code: Select all | Expand
FUNCTION HttpPostRequest( cUrl, cData, cHeaders )
LOCAL cResponse
cResponse := HttpPost( cUrl, cData, cHeaders )
RETURN cResponse
Code: Select all | Expand
FUNCTION Base64Encode( cData )
RETURN HB_BASE64ENCODE( cData )
Code: Select all | Expand
CLASS Toffice365
DATA cClientId // OAuth2 Client ID
DATA cClientSecret // OAuth2 Client Secret
DATA cRedirectUri // Redirect URI
DATA cAccessToken // OAuth2 Access Token
DATA cRefreshToken // OAuth2 Refresh Token
DATA cAuthUrl // Authorization URL
METHOD Init( cClientId, cClientSecret, cRedirectUri )
METHOD GetAuthorizationUrl()
METHOD GetAccessToken( cCode )
METHOD SendEmail( cSubject, cBody, cRecipient )
ENDCLASS
// Constructor for Toffice365 class
METHOD Init( cClientId, cClientSecret, cRedirectUri )
::cClientId := cClientId
::cClientSecret := cClientSecret
::cRedirectUri := cRedirectUri
::cAuthUrl := "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?" + ;
"client_id=" + SELF:cClientId + ;
"&response_type=code" + ;
"&redirect_uri=" + SELF:cRedirectUri + ;
"&scope=Mail.Send"
RETURN NIL
// Method to get the authorization URL
METHOD GetAuthorizationUrl()
RETURN ::cAuthUrl
// Method to get access token using authorization code
METHOD GetAccessToken( cCode )
LOCAL cUrl, cData, cResponse, cTokenUrl
LOCAL aJson
cTokenUrl := "https://login.microsoftonline.com/common/oauth2/v2.0/token"
cData := "code=" + cCode + ;
"&client_id=" + SELF:cClientId + ;
"&client_secret=" + SELF:cClientSecret + ;
"&redirect_uri=" + SELF:cRedirectUri + ;
"&grant_type=authorization_code"
// Request to get the token
cResponse := HttpPostRequest( cTokenUrl, cData, "" )
IF !Empty(cResponse)
aJson := JsonParse( cResponse )
::cAccessToken := aJson[ "access_token" ]
::cRefreshToken := aJson[ "refresh_token" ]
RETURN .T.
ELSE
RETURN .F.
ENDIF
// Method to send an email via Office 365 (Microsoft Graph)
METHOD SendEmail( cSubject, cBody, cRecipient )
LOCAL cUrl, cMessage, cRaw, cResponse
// Prepara il messaggio in formato MIME
cRaw := '{"message": {' + ;
'"subject": "' + cSubject + '",' + ;
'"body": {"contentType": "Text", "content": "' + cBody + '"},' + ;
'"toRecipients": [{"emailAddress": {"address": "' + cRecipient + '"}}]' + ;
'}}'
// URL to send message via Microsoft Graph
cUrl := "https://graph.microsoft.com/v1.0/me/sendMail"
// Send HTTP request with access token
cResponse := HttpPostRequest( cUrl, cRaw, "Authorization: Bearer " + SELF:cAccessToken )
IF !Empty(cResponse)
RETURN .T.
ELSE
RETURN .F.
ENDIF
RETURN NIL
Code: Select all | Expand
LOCAL oOffice365
oOffice365 := Toffice365():New()
// Initializes with the client_id, client_secret and redirect_uri obtained from Azure Portal
oOffice365:Init( "YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "YOUR_REDIRECT_URI" )
Code: Select all | Expand
LOCAL cAuthUrl
cAuthUrl := oOffice365:GetAuthorizationUrl()
MsgInfo( "Visita questo URL per autorizzare l'app: " + cAuthUrl, "Autorizzazione OAuth2" )
Code: Select all | Expand
LOCAL cCode, lSuccess
cCode := "AUTHORIZATION_CODE_OBTAINED_FROM_USER" // Codice di autorizzazione
lSuccess := oOffice365:GetAccessToken( cCode )
IF lSuccess
MsgInfo( "Token di accesso ottenuto!", "Successo" )
ELSE
MsgError( "Errore durante l'ottenimento del token.", "Errore" )
ENDIF
Code: Select all | Expand
LOCAL lSuccess
lSuccess := oOffice365:SendEmail( "Test Email", "Ciao, questa è una prova di invio email!", "recipient@example.com" )
IF lSuccess
MsgInfo( "Email inviata con successo!", "Successo" )
ELSE
MsgError( "Errore durante l'invio dell'email.", "Errore" )
ENDIF