PowerShell/.Net - Google API Contacts Modification : PUT Request 401 Unauthorized

753 Views Asked by At

I'm trying to modify Contacts in Gmail account, using the .Net API, and Loading it in powershell. I'm following the steps described here (Updating contacts, Doh !)

To update a contact, first retrieve the contact entry, modify the data and send an authorized PUT request to the contact's edit URL with the modified contact entry in the body.

OK, got it so I'm succesfull to retrieve contact informations using this code :

$Settings = New-Object Google.GData.Client.RequestSettings( "MyApp", $username , $password )
$Credentials = New-Object System.Net.NetworkCredential( $username, $password )

$Request = New-Object Google.Contacts.ContactsRequest( $Settings )
$Contacts = $Request.GetContacts()
$GoogleContact = $Contacts.Entries |? { $_.PrimaryEmail.Address -eq "[email protected]" }
$GoogleContact.Title

Of course, I had a Mail message from google indicating that an external App was bloqued, and I changed a security parameter to allow this code to work ... And it works, the code is prompting my Google Contact Title.

And now, my problem:
I'm changing a property on my Object:

$GoogleContact.Title = "Mac Gyver"

I'm using a function called Execute-HTTPPostCommand, slightly modified to add the Etag value, required by google to make sure I'm not modifying an entry that is actually modified somewhere else :

function Execute-HTTPPostCommand() {
    param(
        [string] $TargetUrl = $null
        ,[string] $PostData = $null
        ,$Credentials
        ,$Etag
    )

    $ErrorActionPreference = "Stop"
    $global:webRequest = [System.Net.WebRequest]::Create($TargetUrl)
    $webRequest.Headers.Add("etag", $Etag )
    $webRequest.ContentType = "text/html"
    $PostStr = [System.Text.Encoding]::UTF8.GetBytes($PostData)
    $webrequest.ContentLength = $PostStr.Length
    $webRequest.ServicePoint.Expect100Continue = $false
    $webRequest.Credentials = $Credentials

    $webRequest.PreAuthenticate = $true
    $webRequest.Method = "PUT"

    $Global:requestStream = $webRequest.GetRequestStream()
    $requestStream.Write($PostStr, 0,$PostStr.length)
    $requestStream.Close()

    [System.Net.WebResponse] $global:resp = $webRequest.GetResponse();
    $rs = $resp.GetResponseStream();
    [System.IO.StreamReader] $sr = New-Object System.IO.StreamReader -argumentList $rs;
    [string] $results = $sr.ReadToEnd();

    return $results;
}

And calling it this way:

Execute-HTTPPostCommand -TargetUrl $GoogleContact.Id -PostData $GoogleContact -Credentials $Credentials -Etag $GoogleContact.ETag

the Contact.ID value is the URL required by google to update the contact, it looks like this : https://www.google.com/m8/feeds/contacts/userEmail/full/{contactId}

I'm getting an error 401 : unautorized. Being a Windows Sysadmin, I'm not familiar with webservices PUT requests ... I'm using the same credentials to Read Datas and trying to update datas. What am I missing?

1

There are 1 best solutions below

0
On

Ok, that was pretty easy, I should have RTFM ...

#Loading Google API
$Settings = New-Object Google.GData.Client.RequestSettings( "MyApp", $username , $password )
$Credentials = New-Object System.Net.NetworkCredential( $username, $password )

#Loading Contacts, and getting the one I want
$Request = New-Object Google.Contacts.ContactsRequest( $Settings )
$Contacts = $Request.GetContacts()
$GoogleContact = $Contacts.Entries |? { $_.PrimaryEmail.Address -eq "[email protected]" }

#Updating the fields
$GoogleContact.Name.FullName = "Mac Gyver"
$GoogleContact.Name.GivenName = "Mac"
$GoogleContact.Name.FamilyName = "Gyver"
$GoogleContact.Title = "Handyman Masterchief"

#Update
$MAJ = $ContactRequest.Update($GoogleContact)

And it works as is, just like the .Net example.

No need to load a heavy PUT request, the API do his Job.

Sorry for loss of time guys !