I'm trying to forward emails with attachments to a specific email address via Azure Automation (with message ID). I get the error message at the bottom after I run the code. I'm not really sure am I on the right track here (both with email sending and sending of attachments). Perhaps there's a better way to do this.
Could anyone lend a hand?
$credObject = Get-AutomationPSCredential -Name "Myscreds"
$url = "https://outlook.office365.com/api/v1.0/me/AAMkADA1MTAAAH5JaL/forward"
$body = "{
""Message"":{
""Subject"": ""This is a test"",
""Importance"": ""Low"",
""Body"": {
""ContentType"": ""HTML"",
""Content"": ""This is great!""
},
""ToRecipients"": [
{
""EmailAddress"":{
""Address"": ""myname#test.com""
}
}
]
}}"
Invoke-RestMethod -Uri $url -Method Post -Credential $credobject -ContentType "application/json" -Body $Body
I get the following error message:
Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At line:24 char:1
+ Invoke-RestMethod -Uri $url -Method Post -Credential $credobject -Con ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod],
WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Thanks.
Per the Microsoft documentation, you need to modify your request.
https://outlook.office.com/api/v1.0/me/messages/AAMkAGE0Mz8DmAAA=/forward
It looks like you forgot to include /messages/ in your request.
However, it looks like you want to change the body of a message when you forward it. This is more complicated, and you need to follow this workflow instead:
Alternatively, if you need to modify any updateable properties in the message to be forwarded, you can first create a draft forward message, update the message properties, and then send the reply.
Here's how that would look.
First, make a Draft of the message you want to forward
$request = "https://outlook.office365.com/api/v1.0/me/messages/AAMkADA1MTAAAH5JaL/createforward"
$body = {
"ToRecipients":[
{
""EmailAddress"":{
""Address"": ""myname#test.com""
}
}
],
"Comment": "Your sample message here"
}
The response back is going to include some properties, including the ID of the new message. You then use that to edit the Draft (to change the subject, etc) and then send it off. Let me know if you need any further help.
Ok. I had the incorrect message ID, that was my main problem. It's all resolved. I can forward messages with attachments using the message ID. Thanks again.
$credObject = Get-AutomationPSCredential -Name "mycreds"
$url = "https://outlook.office365.com/api/v1.0/Users('it-test#test.com')/messages/ASHJFKHFUISDFWIzLT=/forward"
$body = "{
""Comment"": ""A mail with some attachments (hopefully)"",
""ToRecipients"": [
{
""EmailAddress"":{
""Address"": ""myname#test.com""
}
}
]
}"
Invoke-RestMethod -Uri $url -Method Post -Credential $credobject -ContentType "application/json" -body $body
Related
I am using an ARM Template of type "Microsoft.Resources/deploymentScripts". That uses a PowerShell script that should add an identity to a role in Azure AD. When I run that a second time the post requests, the last Invoke-RestMethod, to add the member fails. That intentional and okay because the member is already there. I wrapped that in a try catch and look for the specific error. This works fine locally but not when deployed on Azure. It still stops at the line of the invoke, 41, and does not seem to respect the try catch around that. What am I doing wrong?
param([string] $spObjectId, $roleName, $tenantId, $clientId, $clientSecret)
Write-Host $ErrorActionPreference
$ErrorActionPreference = "Continue"
$Body = #{
'tenant' = $tenantId
'client_id' = $clientId
'scope' = 'https://graph.microsoft.com/.default'
'client_secret' = $clientSecret
'grant_type' = 'client_credentials'
}
$url = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
Write-Host $url
$Params = #{
'Uri' = $url
'Method' = 'Post'
'Body' = $Body
'ContentType' = 'application/x-www-form-urlencoded'
}
$AuthResponse = Invoke-RestMethod #Params
$Headers = #{
'Authorization' = "Bearer $($AuthResponse.access_token)"
}
$roles = Invoke-RestMethod -Uri 'https://graph.microsoft.com/v1.0/directoryRoles' -Headers $Headers
$role = $roles.value | Where-Object { $_.displayName -eq "$roleName" }
$roleId = $role.id
$Body = #{
"#odata.id"= "https://graph.microsoft.com/v1.0/directoryObjects/$spObjectId"
}
$json = $Body | ConvertTo-Json
$url = "https://graph.microsoft.com/v1.0/directoryRoles/$roleId/members/`$ref"
try {
Invoke-RestMethod -Method 'Post' -Uri $url -Body $json -Headers $Headers -ContentType 'application/json'
}
catch {
$errordetails = $_.ErrorDetails.Message | ConvertFrom-Json
if($errordetails.error.message -ne "One or more added object references already exist for the following modified properties: 'members'.")
{
throw $_.Exception
}
}
Write-Host "Done"
The error in the Azure Portal
The provided script failed with the following error:
Microsoft.PowerShell.Commands.HttpResponseException: Response status
code does not indicate success: 400 (Bad Request). at
System.Management.Automation.MshCommandRuntime.ThrowTerminatingError(ErrorRecord
errorRecord) at ,
/mnt/azscripts/azscriptinput/AddMemberToRole.ps1: line 41 at
, : line 1 at ,
/mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 192. Please
refer to https://aka.ms/DeploymentScriptsTroubleshoot for more
deployment script information. (Code: DeploymentScriptError)
Ideally, Invoke-RestMethod's error is captured in the try catch block. Your code looks correct and similar to what has to be done:
try{ $restp=Invoke-RestMethod (...) } catch {$err=$_.Exception}
$err | Get-Member -MemberType Property
TypeName: System.Net.WebException
Name MemberType Definition
---- ---------- ----------
Message Property string Message {get;}
Response Property System.Net.WebResponse Response {get;}
Status Property System.Net.WebExceptionStatus Status {get;}
I suspect two reasons for this behavior:
The ARM template is having issues such that try catch block is neglected. Make sure the syntax is correct and expected (ARM works in local).
An old deployed script is messing with this script. Try changing the resource name and redeploy.
Following a script (from here) that many others have suggested works OK, I am having an error that is just outside my ability to understand. I am novice-to-intermediate with Power Shell and just beginning with API's.
The script is:
$domain = 'example.com' # your domain
$name = 'xyz' # name of the A record to update
$key = 'myKey # key for godaddy developer API
$secret = 'mySecret' # Secret for godday developer API
$headers = #{}
$headers["Authorization"] = 'sso-key ' + $key + ':' + $secret
$result = Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/records/A/$name -method get -headers $headers
$content = ConvertFrom-Json $result.content
$dnsIp = $content.data
# Get public ip address
$currentIp = Invoke-RestMethod http://ipinfo.io/json | Select -exp ip
# THE CODE WORKS FINE UP TO HERE
if ( $currentIp -ne $dnsIp) {
$Request = #{ttl=3600;data=$currentIp }
$JSON = Convertto-Json $request
# THE FOLLOWING LINE FAILS WITH THE ERROR NOTED BELOW
Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/records/A/$name -method put -headers $headers -Body $json -ContentType "application/json"
}
The following error is returned for the final Invoke-WebRequest:
Invoke-WebRequest : {"code":"INVALID_BODY","fields":[{"code":"UNEXPECTED_TYPE","message":"is not a array","path":"records"}],"message":"Request body doesn't fulfill schema, see details in `fields`"}
At C:\tfsCode\tfs\api.ps1:25 char:5
+ Invoke-WebRequest https://api.godaddy.com/v1/domains/$domain/reco ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
The Go Daddy reference page for the Get API is here and for the Put API is here.
The PUT API documentation says it’s expecting the body to be an array. This is also what the error message is saying. Try changing this line:
$Request = #{ttl=3600;data=$currentIp }
to
$Request = #(#{ttl=3600;data=$currentIp })
#() creates an array in PowerShell, when converted to JSON it will still be an array
#{} creates a hashtable in PowerShell, when converted to JSON it will be an object
I manage many subscriptions so the current Azure Advisor while interesting requires you to go through too many screens and there is no way to download the CSV recommendations and compile them using PowerShell. This led to attempt to interface with the API. The issue I am having is that it appears that it limits you to 200 records so changing top does nothing. Many of the records are a generic security warning with a risk of none. I attempted to filter them out but my knowledge of API filters is poor and the documentation Microsoft provides could be better. Below is the PowerShell command I am using:
Call:
$Response = Invoke-RestMethod -Uri "https://management.azure.com/subscriptions/${SubscriptionId}/providers/Microsoft.Advisor/Recommendations?api-version=2017-04-19&`$top=999&`$filter=risk -ne None" -Method GET -Headers #{"Authorization" = "$AccessToken"} -Verbose
Response:
Without Filter Parameter
https://management.azure.com/subscriptions/<SubID>/providers/microsoft.Advisor/recommendations?api-version=2017-04-19&$top=200&$s
kiptoken=<Token>
With Filter Parameter
Invoke-RestMethod -Uri "https://management.azure.com/subscriptions/${SubscriptionId}/providers/Microsoft.Advisor/Recommendations?api-version=2017-04-19&`$top=999&`$filter=risk -eq 'None'" -Method GET -Headers #{"Authorization" = "$AccessToken"} -Verbose
VERBOSE: GET https://management.azure.com/subscriptions/<sub ID>/providers/Microsoft.Advisor/Recommendations?api-version=2017-04-1
9&$top=999&$filter=risk -eq 'None' with 0-byte payload
Invoke-RestMethod : {"message":"Invalid $filter param"}
At line:1 char:13
+ $Response = Invoke-RestMethod -Uri "https://management.azure.com/subs ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I have been struggling with exactly the same today, hence I found your article.
I managed to resolve my issue by using a later version of the API, and slightly changing the filter
For example:
$filter="Category eq 'Cost'"
$url = "https://management.azure.com/subscriptions/$Subscriptionid/providers/microsoft.Advisor/recommendations?api-version=2017-04-19&`$top=999&`$filter=$filter"
There is a mistake in your API. The right API grammar is &$filter not $filter, you could see your API, you lose a &.
The following script works for me.
##get token
$TENANTID=""
$APPID=""
$PASSWORD=""
$result=Invoke-RestMethod -Uri https://login.microsoftonline.com/$TENANTID/oauth2/token?api-version=1.0 -Method Post -Body #{"grant_type" = "client_credentials"; "resource" = "https://management.core.windows.net/"; "client_id" = "$APPID"; "client_secret" = "$PASSWORD" }
$token=$result.access_token
##set subscriptionId
$subscriptionId=""
$Headers=#{
'authorization'="Bearer $token"
'host'="management.azure.com"
'contentype'='application/json'
}
$url="https://management.azure.com/subscriptions/$subscriptionID/providers/Microsoft.Advisor/Recommendations?api-version=2017-03-31&`$top=999`&$filter=risk -eq 'None'"
Invoke-RestMethod -Uri $url -Headers $Headers -Method GET
Using the Attask api, how can a I add an update through the rest api? Updating the task looks like it will completely replace all updates as per the PUT documentation on nested objects, and doing a post on the /api/update doesn't seem to work : here is what I have tried so far using Powershell for testing
$url = "https:///attask/api/update?sessionID=$($session.data.sessionID)&message=Test Message from api&refObjID=56e9b1d100741c6eb3cab7df95269ba7&objCode=UPDATE&updateObjCode=NOTE"
$result = Invoke-RestMethod -Uri $url -Method "POST"
Result is :
Invoke-RestMethod : {"error":{"class":"java.lang.UnsupportedOperationException","message":null}}
Instead of Updates, post to notes instead - e.g.
$url = "https://lockton.attask-ondemand.com/attask/api/note?sessionID=$($session.data.sessionID)&updates={noteText:'Test Message from api',objID:'56e9b1d100741c6eb3cab7df95269ba7',noteObjCode:'TASK'}"
$postResult = Invoke-RestMethod -Uri $url -Method "POST"
$postResult
I'm trying to create a powershell script to access DYN's API and perform checks/updates on DNS zones I use/test.
I'm following their API details and here's the first link, https://help.dyn.com/session-log-in/
Here's the beginning of the REST script I've put together:
$url = "https://api2.dynect.net/REST/Session/"
$body = #{customer_name='mahcompany';user_name='mahname';password='mahpass'}
Invoke-RestMethod -Method Post -Uri $url -Body $body
This produces the following results:
Invoke-RestMethod : The remote server returned an error: (406) Not Acceptable.
At line:12 char:9
+ $test = Invoke-RestMethod -Method Post -Uri $url -Body $body
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-> RestMethod], WebException
+ FullyQualifiedErrorId :
WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
This is supposed to be a JSON query according to the DYN information, and so I've tried sevveral other examples of DYN's using CURL as a basis:
$json = #"{"customer_name":"yourcustomer","user_name":"youruser","password":"yourpass"}'
However this doesn't work either.
Can anyone point me in the right direction here? This can't be that crazy, I'm just trying to pass the parameters into a rest-method query string. Any help would be very much appreciated at this point.
-Sean
Content Type
Invoke-RestMethod -Method Post -Uri $url -Body $body -ContentType 'application/json'
This might be the problem if dyn.com is expecting a proper content type.
According to the documentation on Invoke-RestMethod:
If this parameter is omitted and the request method is POST, Invoke-RestMethod sets the content type to "application/x-www-form-urlencoded". Otherwise, the content type is not specified in the call.
ConvertTo-JSON
You don't have to create your JSON string manually. You can create a hashtable and then convert it:
$data = #{
customer = 'something'
name = 'whatever'
}
$data | ConvertTo-JSON
I'm not saying that you are definitely making malformed JSON, but this can help prevent that.