VBA-WEB unable to authorize with httpbasic authenticator - excel

I am trying to use VBA-Web for submitting REST API via Excel VBA and running into issues
https://github.com/VBA-tools/VBA-Web
I tried to modify this example to use HttpBasicAuthenticator but unsuccessful it says HTTP error 401. When I use Postman to submit the rest request it is fine.
https://github.com/revisohq/api-samples/tree/master/rest/excel
If I use this Url that does not need to authenticate. It works as expected
https://rest.reviso.com/customers?demo=true
Private Sub Worksheet_Activate()
Dim Client As New WebClient
Dim Request As New WebRequest
Client.TimeoutMs = 30000 ' 30 seconds
Client.BaseUrl = "https://postman-echo.com/basic-auth"
'Client.BaseUrl = "https://rest.reviso.com/customers?demo=true"
Request.Format = WebFormat.Json
Dim Auth As New HttpBasicAuthenticator
Auth.Setup _
Username:="postman", _
Password:="password"
Dim Response As WebResponse
Set Response = Client.Execute(Request)
If Response.StatusCode <> Ok Then
Sheets("Test").Range("A1") = Response.StatusDescription
Exit Sub
End If
Dim Json As Object
Set Json = WebHelpers.ParseJson(Response.Content)
FillData Json
End Sub

Related

Excel VBA API Request

So I don't have any experience coding whatsoever but I'm working on pulling some vehicle data from an government site with an API using VBA. so i don't have to manually adjust data in our vehicle list.
the code i wrote/stole:
Sub SendAPIRequest()
Dim httpreq As Object
Dim url As String
Dim response As String
Dim headers As Collection
Set headers = New Collection
headers.Add "SVV-Authorization", "Apikey {1234}"
Set httpreq = CreateObject("MSXML2.XMLHTTP")
url = "https://www.vegvesen.no/ws/no/vegvesen/kjoretoy/felles/datautlevering/enkeltoppslag/kjoretoydata?kjennemerke=AA91620" + kjennemerke
With httpreq
.Open "GET", url, False
.setRequestHeader "SVV-Authorization", "1234}"
.send
End With
response = httpreq.responseText
Debug.Print response
End Sub
the request goes out but the with the following response: "status":403,"error":"Forbidden","path":"/enkeltoppslag/kjoretoydata"}
403 The API key does not exist in the database, has the status active and/or the user is blocked.
Additional info: REST service - Json response.
https://autosys-kjoretoy-api.atlas.vegvesen.no/api-ui/index-enkeltoppslag.html
key is legit so I'm sending the header out wrong?
Thanks in advance :)
copy & paste other code, etc.

how to take application control back from application_error

I got an old application that is using aspnet membership controls changepassword and createuserwizard etc. These send emails in the end, via gmail, after sending the email successfully, I get an application_error
The SMTP server requires a secure connection or the client was not authenticated...
The requirement is I can go back to the normal flow of application and ignore this error.
Note that the email is being sent successfully to the client. There is no exception within the procedure/catch.
Protected Sub ChangePwd_SendingMail(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.MailMessageEventArgs) Handles ChangePwd.SendingMail
Dim obj As SecurePassword = New SecurePassword()
Select Case ConfigurationSettings.AppSettings("WhichSMTP")
Case "gmail"
Try
obj.SendViaGmail(e.Message.Subject, e.Message.Body, e.Message.To.ToString())
Catch ex As Exception
Response.Write("Error sending email via gmail smtp: " & ex.Message)
End Try
End Select
End Sub
SecurePassword.vb
Public Function SendViaGmail(subject As String, body As String, recipients As String)
Dim fromEmail As String = ConfigurationSettings.AppSettings("ContactEmail")
Dim smtpClient As SmtpClient = New SmtpClient("smtp.gmail.com") With {
.Port = 587,
.DeliveryMethod = SmtpDeliveryMethod.Network,
.Credentials = New NetworkCredential(fromEmail, "apppasswordgeneratedviagoogle"),
.EnableSsl = True
}
Dim mailMessage As MailMessage = New MailMessage With {
.From = New MailAddress(fromEmail),
.Subject = subject,
.Body = body,
.IsBodyHtml = True
}
mailMessage.[To].Add(recipients)
If smtpClient IsNot Nothing Then
smtpClient.Send(mailMessage)
End If
End Function
I got the above code from here
few things to note,
I am running this code from my development machine (IISExpress).
previously there was no code written under
Case "gmail"
Update:
I have tried catching it in page_error, it actually comes here but it shows me an empty page now instead of successtemplate from changepassword control
Private Sub Page_Error(sender As Object, e As EventArgs) Handles Me.Error
Dim exc As Exception = Server.GetLastError()
' Handle specific exception.
If exc.GetType = GetType(SmtpException) Then
ChangePwd.SuccessTemplate.InstantiateIn(ChangePassword)
'ChangePwd.ChangePasswordTemplateContainer.Visible = False
End If
' Clear the error from the server.
Server.ClearError()
End Sub

Session ID not refreshing in API call

I am trying to use VBA Excel to access the API provided by the website www.myfxbook.com. The API documentation is here(https://www.myfxbook.com/fr/api). The Steps to get the data are as follows:
Login through Login API
Get session ID of the session from response of Login API
Get data based on this Session ID through various other APIs
Logout through the Logout API to generate a new session
The Problem I am facing is that even though the Login and Logout APIs are being used and throwing no error, I am always getting the same Session ID when I am trying to use it through Excel VBA. On the other hand, using the same URLs through Python or even the browser is giving me a different session ID each time. i can only use Excel for this project. Could someone please help me how to get different session ID on successful logout?
I am using the code below to do this. I have hidden (*******) the Email ID and password for security purposes.
Sub extract()
Dim sht1 As Worksheet
Dim email As String
Dim password As String
Dim accountName As String
Dim url As String
Dim hreq As Object
Set hreq = CreateObject("MSXML2.XMLHTTP")
Dim accountID As String
Set sht1 = Sheets(1)
email = "*******"
password = "********"
accountName = "all day multiple currency coinexx"
loginURL = "https://www.myfxbook.com/api/login.xml?email=" + email + "&password=" + password
hreq.Open "GET", loginURL, False
hreq.Send
Dim xmlDoc As New MSXML2.DOMDocument60
Dim response As String
response = hreq.ResponseText
If Not xmlDoc.LoadXML(response) Then
MsgBox ("Load Error")
End If
Dim xnodelist As MSXML2.IXMLDOMNodeList
Set xnodelist = xmlDoc.getElementsByTagName("session")
Dim sessionID As String
sessionID = xnodelist(0).Text
'Do Something here to get data. This part is working fine.
logoutURL = "https://www.myfxbook.com/api/logout.xml?session=" + sessionID
hreq.Open "GET", logoutURL, False
hreq.Send
response = hreq.ResponseText
If Not xmlDoc.LoadXML(response) Then
MsgBox ("Load Error")
End If
End Sub
I think it likely you are hitting caching. Try to force an avoidance of this with an additional header
hreq.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"

Reading GMail email messages via VBA without Outlook

How can I read GMail emails via VBA without having Outlook installed on the PC ?
I googled it but I didn't find any solution which does not relies on Outlook.
You can use the google api to archive this without outlook.
There is VBA-Web on github that supports the gmail api.
Here is an example for gmail with vba-web:
Attribute VB_Name = "Gmail"
' Setup client and authenticator (cached between requests)
Private pGmailClient As WebClient
Private Property Get GmailClient() As WebClient
If pGmailClient Is Nothing Then
' Create client with base url that is appended to all requests
Set pGmailClient = New WebClient
pGmailClient.BaseUrl = "https://www.googleapis.com/gmail/v1/"
' Use the pre-made GoogleAuthenticator found in authenticators/ folder
' - Automatically uses Google's OAuth approach including login screen
' - Get API client id and secret from https://console.developers.google.com/
' - https://github.com/timhall/Excel-REST/wiki/Google-APIs for more info
Dim Auth As New GoogleAuthenticator
Auth.Setup CStr(Credentials.Values("Google")("id")), CStr(Credentials.Values("Google")("secret"))
Auth.AddScope "https://www.googleapis.com/auth/gmail.readonly"
Auth.Login
Set pGmailClient.Authenticator = Auth
End If
Set GmailClient = pGmailClient
End Property
' Load messages for inbox
Function LoadInbox() As Collection
Set LoadInbox = New Collection
' Create inbox request with userId and querystring for inbox label
Dim Request As New WebRequest
Request.Resource = "users/{userId}/messages"
Request.AddUrlSegment "userId", "me"
Request.AddQuerystringParam "q", "label:inbox"
Dim Response As WebResponse
Set Response = GmailClient.Execute(Request)
If Response.StatusCode = WebStatusCode.Ok Then
Dim MessageInfo As Dictionary
Dim Message As Dictionary
For Each MessageInfo In Response.Data("messages")
' Load full messages for each id
Set Message = LoadMessage(MessageInfo("id"))
If Not Message Is Nothing Then
LoadInbox.Add Message
End If
Next MessageInfo
End If
End Function
' Load message details
Function LoadMessage(MessageId As String) As Dictionary
Dim Request As New WebRequest
Request.Resource = "users/{userId}/messages/{messageId}"
Request.AddUrlSegment "userId", "me"
Request.AddUrlSegment "messageId", MessageId
Dim Response As WebResponse
Set Response = GmailClient.Execute(Request)
If Response.StatusCode = WebStatusCode.Ok Then
Set LoadMessage = New Dictionary
' Pull out relevant parts of message (from, to, and subject from headers)
LoadMessage.Add "snippet", Response.Data("snippet")
Dim Header As Dictionary
For Each Header In Response.Data("payload")("headers")
Select Case Header("name")
Case "From"
LoadMessage.Add "from", Header("value")
Case "To"
LoadMessage.Add "to", Header("value")
Case "Subject"
LoadMessage.Add "subject", Header("value")
End Select
Next Header
End If
End Function
Sub Test()
Dim Message As Dictionary
For Each Message In LoadInbox
Debug.Print "From: " & Message("from") & ", Subject: " & Message("subject")
Debug.Print Message("snippet") & vbNewLine
Next Message
End Sub
You can pull GMAIL email data into Excel by adding a custom reference library EAGetMail.
You can find the install link and a demo macro here.

Fetching gmail inbox mail messages via CDO in vba excel

I would like to access the inbox in a gmail account using CDO in VBA.
I have already managed to send a mail message but do not know how to fetch the inbox messages into an excel sheet.
If possible I would like to be able to identify the tags of each message as well.
While the question asks for CDO in particular, from this similar SO question it doesn't look like this is possible directly with CDO.
As an alternative approach to fetching inbox mail messages, Google has recently released a Gmail API that could be consumed with Excel. Below is an example using VBA-Web:
' Setup client and authenticator (cached between requests)
Private pGmailClient As WebClient
Private Property Get GmailClient() As WebClient
If pGmailClient Is Nothing Then
' Create client with base url that is appended to all requests
Set pGmailClient = New WebClient
pGmailClient.BaseUrl = "https://www.googleapis.com/gmail/v1/"
' Use the pre-made GoogleAuthenticator found in authenticators/ folder
' - Automatically uses Google's OAuth approach including login screen
' - Get API client id and secret from https://console.developers.google.com/
' - https://github.com/timhall/Excel-REST/wiki/Google-APIs for more info
Dim Auth As New GoogleAuthenticator
Auth.Setup "Your client id", "Your client secret"
Auth.AddScope "https://www.googleapis.com/auth/gmail.readonly"
Auth.Login
Set pGmailClient.Authenticator = Auth
End If
Set GmailClient = pGmailClient
End Property
' Load messages for inbox
Function LoadInbox() As Collection
Set LoadInbox = New Collection
' Create inbox request with userId and querystring for inbox label
Dim Request As New WebRequest
Request.Resource = "users/{userId}/messages"
Request.AddUrlSegment "userId", "me"
Request.AddQuerystringParam "q", "label:inbox"
Dim Response As WebResponse
Set Response = GmailClient.Execute(Request)
If Response.StatusCode = WebStatusCode.Ok Then
Dim MessageInfo As Dictionary
Dim Message As Dictionary
For Each MessageInfo In Response.Data("messages")
' Load full messages for each id
Set Message = LoadMessage(MessageInfo("id"))
If Not Message Is Nothing Then
LoadInbox.Add Message
End If
Next MessageInfo
End If
End Function
' Load message details
Function LoadMessage(MessageId As String) As Dictionary
Dim Request As New WebRequest
Request.Resource = "users/{userId}/messages/{messageId}"
Request.AddUrlSegment "userId", "me"
Request.AddUrlSegment "messageId", MessageId
Dim Response As WebResponse
Set Response = GmailClient.Execute(Request)
If Response.StatusCode = WebStatusCode.Ok Then
Set LoadMessage = New Dictionary
' Pull out relevant parts of message (from, to, and subject from headers)
LoadMessage.Add "snippet", Response.Data("snippet")
Dim Header As Dictionary
For Each Header In Response.Data("payload")("headers")
Select Case Header("name")
Case "From"
LoadMessage.Add "from", Header("value")
Case "To"
LoadMessage.Add "to", Header("value")
Case "Subject"
LoadMessage.Add "subject", Header("value")
End Select
Next Header
End If
End Function
Sub Test()
Dim Message As Dictionary
For Each Message In LoadInbox
Debug.Print "From: " & Message("from") & ", Subject: " & Message("subject")
Debug.Print Message("snippet") & vbNewLine
Next Message
End Sub

Resources