I have method who creates the contact and sends the request. After call Execute() method, an excepted appears. How to correctly send changes in Google contacts?
private readonly PeopleServiceService _peopleService;
private readonly string[] _scopes = { PeopleServiceService.Scope.Contacts };
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
secrets,
_scopes,
userName,
CancellationToken.None).Result;
_peopleService = new PeopleServiceService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "ApplicationName",
});
var contactToCreate = new Person
{
Names = new List<Name>
{
new Name
{
DisplayName = "John"
}
},
PhoneNumbers = new List<PhoneNumber>
{
new PhoneNumber
{
Value = "+7 777 777 7777"
}
}
};
var request = new PeopleResource.CreateContactRequest(_peopleService, contactToCreate);
request.Execute(); // Exception here
That exception:
enter image description here
insufficient authentication scopes.
Means that you dont currently have the permission to do what you are trying to do.
Method: people.createContact requires the following scope of permissions in order to exicute.
https://www.googleapis.com/auth/contacts
You apear to be using that. So one of two things is happening here.
You have changed the scope in your code and failed to logout and reauthenticate the script in order to get the new permissions.
there is some bug in the api. I have tested it and the API appears to be working.
Double check your code make sure your using that Scope then try and login again.
Related
I am supporting an IT admin, who is himself facilitating the use of compliance software. To that end, I have written some C# code that iterates through all users in a directory, and performs operations on their messages. My current solution uses two different APIs to accomplish this (code snippet below), but obviously it would be better to only use one API. Having scanned through other posts here, I failed to find a satisfactorily clear answer on how to make that happen. My app is a service account, with Google Workspace domain-wide delegation enabled. How can I use only one API to accomplish what I am doing with two?
[working code snippet]
string domain; // domain name
string adminEmail; // admin e-mail
string directoryClientEmail; // client e-mail for Directory API
string directoryPrivateKey; // private key for Directory API
string directoryPrivateKeyId; // private key ID for Directory API
string gmailClientEmail; // client e-mail for Gmail API
string gmailPrivateKey; // private key for Gmail API
string gmailPrivateKeyId; // private key ID for Gmail API
CancellationToken cancellationToken; // a cancellation token
DirectoryService directoryClient = new DirectoryService(
new BaseClientService.Initializer
{
HttpClientInitializer = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(creds.DirectoryClientEmail)
{
User = adminEmail,
Scopes = new[] { DirectoryService.Scope.AdminDirectoryUser },
Key = RSA.Create(directoryPrivateKey),
KeyId = directoryPrivateKeyId
}.FromPrivateKey(directoryPrivateKey))
});
UsersResource.ListRequest userListRequest = directoryClient.Users.List();
userListRequest.Domain = domain;
Users userList = await userListRequest.ExecuteAsync(cancellationToken);
foreach (User user in userList)
{
GmailService gmailClient = new GmailService(
new BaseClientService.Initializer
{
HttpClientInitializer = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(gmailClientEmail)
{
User = user.PrimaryEmail,
Scopes = new[] { GmailService.Scope.MailGoogleCom },
Key = RSA.Create(gmailPrivateKey),
KeyId = gmailPrivateKeyId
}.FromPrivateKey(gmailPrivateKey))
});
ListRequest listRequest = new ListRequest(gmailClient, "me");
ListMessageResponse listMessageResponse = await listRequest.ExecuteAsync(cancellationToken);
foreach (Message message in listMessageResponse.Messages)
{
// do stuff
}
}
To achieve what you want, you can't only use one API. As the Gmail API will not give you the users in the domain, but you can get a user's messages with it; which you need. So Gmail API is a requirement.
Then if you want an up-to-date domain users list, then you need to use the Directory API, so unless you have a list of users somewhere else, you require this API too.
Can anyone help as I'm getting bad request failed precondition errors when calling Gmail API to set forward address? Below is a C# .Net console app I'm trying do this with. I have delegated Domain Wide Authority to the Service Account.
Error:
Google.Apis.Requests.RequestError Bad Request [400] Errors [ Message[Bad Request] Location[ - ] Reason[failedPrecondition] Domain[global] ]
I think I was missing the User to impersonate. So, I added the user and now I get the following error.
Error:
Error:"unauthorized_client", Description:"Client is unauthorized to retrieve access tokens using this method.", Uri:""
namespace GmailForwarder
{
class Program
{
static string ApplicationName = "GmailForwarder";
static void Main(string[] args)
{
ServiceAccountCredential credential;
string serviceAccount = "gmailforwarder#gmailforwarder.iam.gserviceaccount.com";
var certificate = new X509Certificate2(#"key.p12", "notasecret", X509KeyStorageFlags.Exportable);
try
{
// Create credential
credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccount)
{
User = "wtestboonew#chicagobooth.edu",
Scopes = new[] { GmailService.Scope.GmailSettingsSharing }
}.FromCertificate(certificate));
// Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
string user = "wtestboonew#chicagobooth.edu"; // test gmail account
string fwdAddr = "acw5274#gmail.com";
ForwardingAddress fwdAddress = new ForwardingAddress();
fwdAddress.ForwardingEmail = fwdAddr;
var createFwdAddressResult = service.Users.Settings.ForwardingAddresses.Create(fwdAddress,"me").Execute();
}
catch (Exception ex)
{
}
}
}
}
This worked for me when I used : https://mail.google.com/ and https://www.googleapis.com/auth/gmail.settings.sharing OAuth2 scopes
I had this problem too (400 code). I was having two problems:
1) As ACW says, I was missing "https://mail.google.com/" from the list of scopes required, appart from "https://www.googleapis.com/auth/gmail.settings.sharing".
2) I was missing to put the scopes wrapped in quotes ("") in the administration console (when specifying the scopes for the service account).
Hope it helps someone
Environment: ASP.NET simple web application on .net 4.5.1 integrated pipeline running on iis8 on server 2012 which is not following MVC.
I'm attempting to get credentials from google's GoogleWebAuthorizationBroker but i keep getting "access is denied"...Even i allowed my urls in "Authorized JavaScript origins" and "Authorized redirect URIs"
Following below URL implementation for Installed App
https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#installed-applications
Here are mine code snippet
var folder = "F:\\MyApp\\WebApp\\MyGoogleStorage";
string[] scopes = new string[] {
Google.Apis.Proximitybeacon.v1beta1.ProximitybeaconService.Scope.UserlocationBeaconRegistry
};
ClientSecrets secrets = new ClientSecrets()
{
ClientId = CLIENT_ID,
ClientSecret = CLIENT_SECRET
};
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
secrets,
scopes,
"user",
CancellationToken.None,
new FileDataStore(folder)).Result;
And use another way to create credentials
using (var stream = new FileStream(Utility.AppPath + "/client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
scopes,
"user", CancellationToken.None, new FileDataStore(folder));
}
But in both cases i am getting access denied.
My assumption is that, it's happening because i am trying to use sample
"Installed Applications"
Please advice me what is the best way to do that in .net simple web application.
Also share some code if any one done it successfully.
Thanks in advance..!!!
For this solution work around I found was
string serviceAccountEmail = "proximitybeacon#proximitytest-1234.iam.gserviceaccount.com"; // Service Account Email
string userEmail = "abc#gmail.com"; //Email of yours
//.p12 file is having all the details about the Service Account we create a Cryptography certificate by it. This you need to download fron your project which you make in Google Developer Console. Foolow stesps from this link https://webapps.stackexchange.com/questions/58411/how-where-to-obtain-a-p12-key-file-from-the-google-developers-console
X509Certificate2 certificate = new X509Certificate2("F://yorrappPath/ProximityTest-2d889bd4fa49.p12", "notasecret", X509KeyStorageFlags.Exportable); // F://yorrappPath -- Give proper location of .p12 file
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
User = userEmail,
Scopes = new string[] { "https://www.googleapis.com/auth/userlocation.beacon.registry" }
}.FromCertificate(certificate));
if (!credential.RequestAccessTokenAsync(CancellationToken.None).Result)
{
return "Can't get the access token";
}
//Beacon Object with its values
Google.Apis.Proximitybeacon.v1beta1.Data.Beacon beacon = new Google.Apis.Proximitybeacon.v1beta1.Data.Beacon();
Google.Apis.Proximitybeacon.v1beta1.Data.AdvertisedId advertisedId = new Google.Apis.Proximitybeacon.v1beta1.Data.AdvertisedId();
beacon.AdvertisedId = new Google.Apis.Proximitybeacon.v1beta1.Data.AdvertisedId() { Id = "ZgCC7BLy8FXla3VmnnibWQ==", Type = "EDDYSTONE" };
beacon.BeaconName = "99911";
beacon.Status = "ACTIVE";
beacon.LatLng = new Google.Apis.Proximitybeacon.v1beta1.Data.LatLng() { Latitude = 28.38, Longitude = 77.12 };
beacon.ExpectedStability = "STABLE";
//Beacon Service for register which having HttpClientInitializer(credential with token detail)
Google.Apis.Proximitybeacon.v1beta1.ProximitybeaconService service = new Google.Apis.Proximitybeacon.v1beta1.ProximitybeaconService(new BaseClientService.Initializer()
{
ApplicationName = "proximityTest", // Replace that with you App name which you given in Google
HttpClientInitializer = credential
});
var registerRequest = new Google.Apis.Proximitybeacon.v1beta1.BeaconsResource.RegisterRequest(service, beacon);
//uncomment this for update beacons. 3 parameter is important for update BeaconName
//var updateRequest = new Google.Apis.Proximitybeacon.v1beta1.BeaconsResource.UpdateRequest(service, beacon, "beacons/3!660082ec12f2f055e56b75669e789b59");
//updateRequest.Execute();
//uncomment this for getting list of beacons.
// var listRequest = new Google.Apis.Proximitybeacon.v1beta1.BeaconsResource.ListRequest(service);
// return listRequest.Execute();
try
{
//This will register a Beacon
registerRequest.Execute();
}
catch (Exception ex)
{
return ex.Message;
}
return beacon;
I am trying to removing the message label. I am able to read the mail successfully, but when I am trying to modify the message Label i have a problem
An error occurred: Google.Apis.Requests.RequestError
Insufficient Permission [403]
Errors
Message[Insufficient Permission] Location[ - ] Reason[insufficientPermis
sions] Domain[global]
i had to try to created a service from json but it have a same issue.
and this is my code
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = clientId,
ClientSecret = clientSecret,
},
new[] { GmailService.Scope.MailGoogleCom, GmailService.Scope.GmailModify, GmailService.Scope.GmailCompose },//new[] { GmailService.Scope.GmailModify, GmailService.Scope.GmailCompose, GmailService.Scope.GmailReadonly },
"user",
CancellationToken.None).Result;
var service = new GmailService(new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
and then i call api to modify label UNREAD in message
ModifyMessageRequest mods = new ModifyMessageRequest();
mods.AddLabelIds = null;
mods.RemoveLabelIds = new List<string> { "UNREAD" });
service.Users.Messages.Modify(mods, userId, messageId).Execute();
You need to fix your scopes either add
https://www.googleapis.com/auth/gmail.labels Create, read, update, and delete labels only.
or just request
https://mail.google.com/ Full access to the account, including permanent deletion of threads and messages. This scope should only be requested if your application needs to immediately and permanently delete threads and messages, bypassing Trash; all other actions can be performed with less permissive scopes.
Also removelablesids requests a label ID
removeLabelIds[] A list IDs of labels to remove from this message.
I don't think new List { "UNREAD" }); is going to return the label id. try doing lables.list to find the labels and there ids
I wonder if anyone has got any further than me using the new Search Analytics functions of the Google Webmaster Tools API via .Net?
I am using the Google.Apis.Webmasters.v3 Nuget package and have got as far as authenticating and connecting (using a Service Account)
However I'm struggling to get anywhere with Search Analytics.
I couldn't find any code samples online so have been guided by the Class info at https://developers.google.com/resources/api-libraries/documentation/webmasters/v3/csharp/latest/annotated.html and a lot of guesswork.
Here is the code I am using:
SearchanalyticsResource mySearchanalyticsResource = new SearchanalyticsResource(service);
SearchAnalyticsQueryRequest myRequest = new SearchAnalyticsQueryRequest();
myRequest.StartDate = "2015-08-01";
myRequest.EndDate = "2015-08-31";
myRequest.RowLimit = 10;
SearchanalyticsResource.QueryRequest myQueryRequest = mySearchanalyticsResource.Query(myRequest, site.SiteUrl);
SearchAnalyticsQueryResponse myQueryResponse = myQueryRequest.Execute();
It runs OK until the Execute method when I get "An Error occurred, but the error response could not be deserialized". Exception detail below...
Newtonsoft.Json.JsonReaderException {"Error parsing NaN value. Path '', line 0, position 0."}
Any help or code samples would be very gratefully received!
This compiles but its not returning any data for me.
Auth:
public static WebmastersService WMAuthenticateOauth(string clientId, string clientSecret, string userName)
{
string[] scopes = new string[] { WebmastersService.Scope.Webmasters }; // View analytics data
try
{
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
, scopes
, userName
, CancellationToken.None
, new FileDataStore(".", true)).Result;
WebmastersService service = new WebmastersService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "WebMasters API Sample",
});
return service;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return null;
}
}
Request
var service = Authentcation.WMAuthenticateOauth(clientid, secret, "testmmm");
IList<string> newlist = new List<string> ();
newlist.Add("country");
newlist.Add("device");
SearchAnalyticsQueryRequest body = new SearchAnalyticsQueryRequest();
body.StartDate = "2015-04-01";
body.EndDate = "2015-05-01";
body.Dimensions = newlist;
var result = service.Searchanalytics.Query(body, "http://www.daimto.com/").Execute();
I have also tried testing using the try me at the bottom of this page. It doesn't return anything either.
Strange API this.
Update:
I finally got data back I set the dates to
body.StartDate = "2015-09-01";
body.EndDate = "2015-09-15";
I wonder if this thing has limited data, it only goes back so far.