I'm trying to read an email using gmail api. But the format of the body message is unreadable.
static void Main(string[] args)
{
UserCredential credential;
using (var stream =
new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
// Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
UsersResource.MessagesResource.ListRequest request = service.Users.Messages.List("me");
IList<Message> messages = request.Execute().Messages;
if (messages != null && messages.Count > 0)
{
foreach (var messageItem in messages)
{
var readMessage = service.Users.Messages.Get("me", messageItem.Id).Execute();
var body = readMessage.Payload.Parts[0].Body.Data;
}
} }
When I debug my test application, the body variable gets the value:
body "DQpLaW5kIFJlZ2FyZHMsDQoNCldpbGwNCg0KV2lsbCBLZWx0eQ0KMzIzLjI1Mi44Njk5DQp3a2VsdHlAZ21haWwuY29tIDxtYWlsdG86d2tlbHR5QGdtYWlsLmNvbT4NCmh0dHBzOi8vd3d3LmZhY2Vib29rLmNvbS9iaWdibHVlZG93bnRvd24gPGh0dHBzOi8vd3d3LmZhY2Vib29rLmNvbS9iaWdibHVlZG93bnRvd24-DQp3d3cubWV0cm9saWZlcHJvcGVydGllcy5jb20gPGh0dHA6Ly93d3cubWV0cm9saWZlcHJvcGVydGllcy5jb20vPg0KDQpCZWdpbiBmb3J3YXJkZWQgbWVzc2FnZToNCg0KRnJvbTogIkNSRVhpIiA8bm90aWZpY2F0aW9uc0BjcmV4aS5jb20-DQpTdWJqZWN0OiBJbmR1c3RyaWFsIENSRSBBc3NldHMgRm9yIFNhbGUgfCBHcmVhdCBPaGlvIExvY2F0aW9ucyB8IEVhc3kgQWNjZXNzIHwgTkFJIFNwcmluZw0KRGF0ZTogSnVseSAxNCwgMjAxNyBhdCA5OjAxOjQwIEFNIFBEVA0KVG86IHdrZWx0eUBnbWFpbC5jb20NClJlcGx5LVRvOiBpbmZvQGNyZXhpLmNvbQ0KDQogPGh0dHA6Ly9lbWFpbC1saW5rcy5jcmV4aS5jb20vd2YvY2xpY2s_dXBuPWpvS3FmZnZFU3Y1RDU2eXI3cmpPd2lBREcwN3p4ek1EdnI0ZnNsdEY5QWJIT1Z1V2JrU0ZhWXN4aTNXY2hucE11SmhUTUlDZjQ3WVo5bDBoY0RtSGZ2NFl0VXJoN1g2TDh2ZzdMQnlkZi0yQmZzOFZSYVk5UGJyYzg4YjdsT1NRUDZfMGxhbklERktDMWU0bHUtMkZZZjdLNjA1d2ZJOWZHdXp2amlNdjYwUERQNFVCTzd5cjRBTHVjTW8tMkZpRDFadXFSTUV5Z2RISVBhRGU3M2FGeGhLS1hBaS0yRlo5UlVzVFhzampqVS0yRndZN1lIa045M1BQRnlaNEQ1QTBQRHlzSElxMWdIYlQtMkJJRWYtMkZRMDBUQU8yV0lMNC0yQlFVU2hueDlhVnhWSXc5NjRFYmNta0FVVDB5SWhqTXl5Mm9na29FWTR5QWZ1czhUQWVJZDBsU0RXMVBMQi0yQmctMkYxMUJRY3gzYWRoYmJxcG1Ma2FGdTdXU3U1STFkQmJjaXN5bW5tcHIyWXVpdTNOdHdiOFpsTm5jLTJGSDdrdThYU3FxTVdIOHhsWFA2Ykp0VTdVYVN4M2IxcVBITlNDblNDYWRhSkEyeEw0MVlGMjFlTm8wcEZXWTVVQk9LengzYkctMkI4V0g2QXpNR1FkNDJhZS0yRkFMN3c1VkxrSlZ1LTJGdTFlR0lNYjBkV3VmdnZkemlXVjgtMkZHcy0yQks1a3BYUi0yQmJhTUwzUE5NTFhpMWRHUjhEWEZndzh1WGZMSFdNUmc0R2Y2MWMwb2JNUEQtMkI4c1QtMkJ1NTFtRj4JDQogDQogPGh0dHA6Ly9lbWFpbC1saW5rcy5jcmV4aS5jb20vd2YvY2xpY2s_dXBuPVVnWW9yUXo0" string
Does anyone know why?
Thanks
Change this line
var body = readMessage.Payload.Parts[0].Body.Data;
to
var body = Base64UrlDecode(readMessage.Payload.Parts[0].Body.Data);
And add this method in your code:
public static string Base64UrlDecode(string input)
{
if (string.IsNullOrWhiteSpace(input))
return "<strong>Message body was not returned from Google</strong>";
string InputStr = input.Replace("-", "+").Replace("_", "/");
return System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(InputStr));
}
Also, to handle multiparts and no multiparts returns, you may use this code:
if (ml.Payload.Parts != null) {
foreach (void bParts_loopVariable in ml.Payload.Parts) {
bParts = bParts_loopVariable;
if (bParts.MimeType == "text/html") {
if (bParts.Body != null) {
dynamic mp = bParts.Body;
if (mp != null) {
return Base64UrlDecode(mp.Data);
}
}
}
}
} else {
return Base64UrlDecode(ml.Payload.Body.Data);
}
The body is Base64 encoded.
You need to call Convert.FromBase64String(string) to get the plain text.
You should use readMessage.GetRaw() method. See below how to decode the base64 string:
byte[] data = Convert.FromBase64String(readMessage.GetRaw());
string messageString = Encoding.UTF8.GetString(data);
see ref https://developers.google.com/gmail/api/v1/reference/users/messages/get
Related
I am new to google cloud / gmail API. In c# I would like to use their gmail api to:
logon to google cloud - works
read List items - works
send email - does not work
The Api in step 3 Returns Insufficient Request Scopes (403) I feel confident I am logged on to my cloud account: The line of code i suspect most is this:
static string[] Scopes = { GmailService.Scope.GmailAddonsCurrentActionCompose, GmailService.Scope.GmailAddonsCurrentMessageAction };
I am getting this error
Request had insufficient authentication scopes. [403]
Errors [
Message[Insufficient Permission] Location[ - ] Reason[insufficientPermissions] Domain[global]
]
// Code
class Program
{
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/gmail-dotnet-quickstart.json
static string[] Scopes = { GmailService.Scope.GmailAddonsCurrentActionCompose, GmailService.Scope.GmailAddonsCurrentMessageAction };
static string ApplicationName = "Gmail API .NET Quickstart";
static void Main(string[] args)
{
UserCredential credential;
using (var stream =
new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
{
// The file token.json stores the user's access and refresh tokens, and is created
// automatically when the authorization flow completes for the first time.
string credPath = "token.json";
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
// Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
// Define parameters of request.
UsersResource.LabelsResource.ListRequest request = service.Users.Labels.List("me");
// List labels.
IList<Label> labels = request.Execute().Labels;
Console.WriteLine("Labels:");
if (labels != null && labels.Count > 0)
{
foreach (var labelItem in labels)
{
Console.WriteLine("{0}", labelItem.Name);
}
}
else
{
Console.WriteLine("No labels found.");
}
string plainText = "Body Test";
var newMsg = new Google.Apis.Gmail.v1.Data.Message();
newMsg.Raw = Program.Base64UrlEncode(plainText.ToString());
try
{
service.Users.Messages.Send(newMsg, "me").Execute();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
/*
{"Google.Apis.Requests.RequestError\r\nRequest had insufficient authentication scopes.
[403]\r\nErrors [\r\n\tMessage[Insufficient Permission] Location[ - ] Reason[insufficientPermissions] Domain[global]\r\n]\r\n"} Google.GoogleApiException
*/
Console.Read();
}
public static string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
return Convert.ToBase64String(inputBytes).Replace("+", "-").Replace("/", "_").Replace("=", "");
}
}
//Output from above
Credential file saved to: token.json
Labels:
CHAT
SENT
INBOX
IMPORTANT
TRASH
DRAFT
SPAM
CATEGORY_FORUMS
CATEGORY_UPDATES
CATEGORY_PERSONAL
CATEGORY_PROMOTIONS
CATEGORY_SOCIAL
STARRED
UNREAD
Sent Messages
Pa0
P
Insurance
Junk E-mail
Licenses
Notes
Personal
Receipts
Travel
Work
Tickets
**Google.Apis.Requests.RequestError
Request had insufficient authentication scopes. [403]
Errors [
Message[Insufficient Permission] Location[ - ] Reason[insufficientPermissions] Domain[global]
]**
Okay:
I decided to take the credentials file provided by GMAIL.API and put into a single line Environment Variable and Do a JSON Convert to a GoogleClientSecrets:
private static GoogleClientSecrets GetSecretsFromEnvironment()
{
var environmentConfiguration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
var secretsEnv = environmentConfiguration["GoogleSecrets"];
var secrets = JsonConvert.DeserializeObject<GoogleClientSecrets>(secretsEnv);
return secrets;
}
the appsettings.json
{
"MailSettings": {
"account": "mark.d.wardell#gmail.com",
"subject": "Please Confirm Account",
"from": "mark.d.wardell#gmail.com",
"HTML": "<b>Hello {0}</b>"
}
}
credentials.json as provided by google cloud console. I made into a single line string and added to EnvironmentVariable
And the calling code:
using Google.Apis.Auth.OAuth2;
using Google.Apis.Gmail.v1;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Threading;
using System.Threading.Tasks;
namespace SendMail
{
class Program
{
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/gmail-dotnet-quickstart.json
static string[] Scopes = { GmailService.Scope.GmailAddonsCurrentActionCompose, GmailService.Scope.GmailAddonsCurrentMessageAction, GmailService.Scope.GmailSend };
static string ApplicationName = "Restful Resting Place";
static async Task Main(params string[] args)
{
try
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
Dictionary<string, string> MailSettings;
MailSettings = configuration.GetSection("MailSettings").GetChildren().ToDictionary(x => x.Key, x => x.Value);
MailSettings.Add("to", args[0]);
MailSettings.Add("link", args[1]);
GoogleClientSecrets gSecrets = GetSecretsFromEnvironment();
string credPath = "token.json";
UserCredential gcredential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
gSecrets.Secrets,
Scopes,
MailSettings["account"],
CancellationToken.None,
new FileDataStore(credPath, true));
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = gcredential,
ApplicationName = ApplicationName,
});
SendItTwo(service, MailSettings);
Console.WriteLine()
}catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static GoogleClientSecrets GetSecretsFromEnvironment()
{
var environmentConfiguration = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
var secretsEnv = environmentConfiguration["GoogleSecrets"];
var secrets = JsonConvert.DeserializeObject<GoogleClientSecrets>(secretsEnv);
return secrets;
}
public static void SendItTwo(GmailService gmail, Dictionary<string,string> dict)
{
MailMessage mailmsg = new MailMessage();
{
mailmsg.Subject = dict["subject"];
mailmsg.Body = string.Format(dict["HTML"],dict["link"]);
mailmsg.From = new MailAddress(dict["from"]);
mailmsg.To.Add(new MailAddress(dict["to"]));
mailmsg.IsBodyHtml = true;
}
////add attachment if specified
if (dict.ContainsKey("attachement"))
{
if (File.Exists(dict["attachment"]))
{
Attachment data = new Attachment(dict["attachment"]);
mailmsg.Attachments.Add(data);
}else
{
Console.WriteLine("Error: Invalid Attachemnt");
}
}
//Make mail message a Mime message
MimeKit.MimeMessage mimemessage = MimeKit.MimeMessage.CreateFromMailMessage(mailmsg);
Google.Apis.Gmail.v1.Data.Message finalmessage = new Google.Apis.Gmail.v1.Data.Message();
finalmessage.Raw = Base64UrlEncode(mimemessage.ToString());
var result = gmail.Users.Messages.Send(finalmessage, "me").Execute();
}
public static string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
return Convert.ToBase64String(inputBytes).Replace("+", "-").Replace("/", "_").Replace("=", "");
}
}
}
we cannot anderstand why we upload docx-file via Google Drive API v3, it compleete success. But after we upload docx we try open file and cannot open it, thre is error in error
But when open our disk in browser (Google Chrome) and try upload docx again it opens fine, without any error.
Can you please tell what is wrong we made.
Code example
class Program
{
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/drive-dotnet-quickstart.json
static string[] Scopes = { DriveService.Scope.DriveMetadata };
static string ApplicationName = "Drive API .NET Quickstart";
static void Main(string[] args)
{
UserCredential credential;
using (var stream =
new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
{
// The file token.json stores the user's access and refresh tokens, and is created
// automatically when the authorization flow completes for the first time.
var clientSecrets = new ClientSecrets();
clientSecrets.ClientId = "";
clientSecrets.ClientSecret = "";
string credPath = "token.json";
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
clientSecrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
// Create Drive API service.
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
Google.Apis.Drive.v3.Data.File fileMetadata = new Google.Apis.Drive.v3.Data.File();
// fileMetadata.Name = #"excel1.xlsx";
fileMetadata.Name = #"word22222.docx";
// fileMetadata.Name = #"present1.pptx";
// var fileStream = File.Open(#"c:\temp\present.pptx", FileMode.Open);
string fileId = string.Empty;
using (var fileStream = File.Open(#"c:\temp\word3.docx", FileMode.Open))
{
// var fileStream = File.Open(#"c:\temp\excel1.xlsx", FileMode.Open);
var fileUpload = service.Files.Create(fileMetadata, fileStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
// var fileUpload = service.Files.Create(fileMetadata, fileStream, "application/vnd.openxmlformats-officedocument.presentationml.presentation");
fileUpload.Fields = "id";
// var fileUpload = service.Files.Create(fileMetadata);
// fileMetadata.MimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
// var fileUpload = service.Files.Create(fileMetadata, fileStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
IUploadProgress progress = fileUpload.Upload();
if (progress.Status == UploadStatus.Failed)
{
Console.WriteLine(progress.Exception);
}
else
{
fileId = fileUpload.ResponseBody.Id;
Console.WriteLine("File ID: " + fileUpload.ResponseBody.Id);
}
}
Console.ReadKey();
var permission = new Google.Apis.Drive.v3.Data.Permission();
permission.Type = "anyone";
permission.Role = "writer";
permission.PermissionDetails = new List<PermissionDetailsData>();
var perm = service.Permissions.Create(permission, fileId);
perm.Execute();
Console.WriteLine("Premission created!");
Console.ReadKey();
Process.Start("explorer.exe", "https://docs.google.com/document/d/" + fileId + "/edit");
// Process.Start("explorer.exe", "https://docs.google.com/spreadsheets/d/" + fileId + "/edit");
// Process.Start("explorer.exe", "https://docs.google.com/presentation/d/" + fileId + "/edit");
Console.WriteLine("Redirected to browser!");
Console.ReadKey();
}
}
Consideration
According to the documentation and to my tests you cannot create a file with the metadata scope only.
Using this scope will result in a permission error. Please try to use a more restricted scope to perform this operation.
Insufficient Permission: Request had insufficient authentication scopes. [403]
Solution
You can use one of these:
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.file
https://www.googleapis.com/auth/drive.appdata
In C# this translates in one of these statements:
static string[] Scopes = { DriveService.Scope.Drive };
// OR
static string[] Scopes = { DriveService.Scope.DriveAppdata };
// OR
static string[] Scopes = { DriveService.Scope.DriveFile };
Reference
Drive Files Create
I'm attempting to download a file from Google Drive using C# & Google.Apis.Drive.v3 and I'm getting an empty, zero-byte file (see code below). I'm uploading files OK, but can't get the download to work. Any help would be greatly appreciated.
code
static string[] Scopes = { DriveService.Scope.Drive };
static string ApplicationName = "Test001";
private DriveService _service = null;
public async Task downloadFile(string url, string lstrDownloadFile)
{
// Authorize API access
UserCredential credential;
using (var stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
{
// The file token.json stores the user's access and refresh tokens, and is created
// automatically when the authorization flow completes for the first time.
string credPath = "token.json";
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Debug.WriteLine("Credential file saved to: " + credPath);
}
// Create Drive API service.
_service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
// Attempt download
// Iterate through file-list and find the relevant file
FilesResource.ListRequest listRequest = _service.Files.List();
listRequest.Fields = "nextPageToken, files(id, name, mimeType, originalFilename, size)";
Google.Apis.Drive.v3.Data.File lobjGoogleFile = null;
foreach (var item in listRequest.Execute().Files)
{
if (url.IndexOf(string.Format("id={0}", item.Id)) > -1)
{
Debug.WriteLine(string.Format("{0}: {1}", item.OriginalFilename, item.MimeType));
lobjGoogleFile = item;
break;
}
}
FilesResource.ExportRequest request = _service.Files.Export(lobjGoogleFile.Id, lobjGoogleFile.MimeType);
Debug.WriteLine(request.MimeType);
MemoryStream lobjMS = new MemoryStream();
await request.DownloadAsync(lobjMS);
// At this point the MemoryStream has a length of zero?
lobjMS.Position = 0;
var lobjFS = new System.IO.FileStream(lstrDownloadFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);
await lobjMS.CopyToAsync(lobjFS);
}
It's possible that it's something as simple as not having enabled the Drive API on your project.
I recommend you add the following code. There's likely a download error which is preventing the stream from being filled.
FilesResource.ExportRequest request = ...
request.MediaDownloader.ProgressChanged += progress =>
{
switch (progress.Status)
{
case DownloadStatus.Failed:
{
Console.WriteLine("Failed: " + progress.Exception?.Message);
break;
}
// other status case statements if you need them
}
};
MemoryStream lobjMS = ...
Then you can drop a breakpoint into the Failed case or look at the exception in the console.
I have two methods. One is to read data from Google Sheets and the other is to add a value to a single cell (But I actually want to append data to the last row but, I'm gonna start with just 1 record first). The btnLoadAttendance works perfectly but when I input something in the textbox1.Text, in the "UpdateValuesResponse result2 = update.Execute();" I get an error like so:
Request had insufficient authentication scopes. [403]
I found an answer here "Request had insufficient authentication scopes [403] when update cell spreadsheet" that says about commenting some lines. I tried commenting that line but it doesn't work for me. I still get the same error. Below is my code:
WORKING
private void btnLoadAttendance_Click(object sender, EventArgs e)
{
UserCredential credential;
using (var stream =
new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/sheets.googleapis.com-dotnet-quickstart.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
var service = new SheetsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
String spreadsheetId = "1b64mhUgdeRzGyJF4NfAPhkFY7br3c0o9rJ9mMnDBTR8";
String range = "Sheet1!A2:D";
SpreadsheetsResource.ValuesResource.GetRequest request =
service.Spreadsheets.Values.Get(spreadsheetId, range);
ValueRange response = request.Execute();
IList<IList<Object>> values = response.Values;
if (values != null && values.Count > 0)
{
foreach (var x in values)
{
dgvAttendance.Rows.Add(x[0], x[1], x[2], x[3]);
}
}
else
{
MessageBox.Show("No data found.");
}
}
NOT WORKING
private void btnAddData_Click(object sender, System.EventArgs e)
{
string[] Scopes = { SheetsService.Scope.SpreadsheetsReadonly };
UserCredential credential;
using (var stream =
new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/sheets.googleapis.com-dotnet-quickstart.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
var service = new SheetsService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
String spreadsheetId = "1b64mhUgdeRzGyJF4NfAPhkFY7br3c0o9rJ9mMnDBTR8/edit";
String range = "Sheet1!F5"; // update the F5 cell
//ValueRange response = request.Execute();
ValueRange valueRange = new ValueRange();
valueRange.MajorDimension = "COLUMNS"; //Rows or Columns
var oblist = new List<object>() { textBox1.Text };
valueRange.Values = new List<IList<object>> { oblist };
SpreadsheetsResource.ValuesResource.UpdateRequest update =
service.Spreadsheets.Values.Update(valueRange, spreadsheetId, range);
update.ValueInputOption = SpreadsheetsResource.ValuesResource.UpdateRequest.ValueInputOptionEnum.RAW;
UpdateValuesResponse result2 = update.Execute();
}
You help is very much appreciated.
Firstly delete the credentials files .credentials/sheets.googleapis.com-dotnet-quickstart.json stored at c:\user\Documents.credentials.
Change the scope variable used for reading cells from Google Spreadsheets from
string[] Scopes = { SheetsService.Scope.SpreadsheetsReadonly };
to
static string[] Scopes = { SheetsService.Scope.Spreadsheets };
After execution of code, API will authenticate again and then issue will be resolved.
I just needed to change:
string[] Scopes = { SheetsService.Scope.SpreadsheetsReadonly };
to
static string[] Scopes = { SheetsService.Scope.Spreadsheets };
and it took me all day!
i was trying to create and run the sample project given in this link.
here is the code:
namespace GmailQuickstart
{
class Program
{
static string[] Scopes = { GmailService.Scope.GmailReadonly };
static string ApplicationName = "Gmail API Quickstart";
static void Main(string[] args)
{
UserCredential credential;
using (var stream =
new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
// Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
// Define parameters of request.
UsersResource.LabelsResource.ListRequest request = service.Users.Labels.List("me");
// List labels.
IList<Label> labels= request.Execute().Labels;
Console.WriteLine("Labels:");
if (labels != null && labels.Count > 0)
{
foreach (var labelItem in labels)
{
Console.WriteLine("{0}", labelItem.Name);
}
}
else
{
Console.WriteLine("No labels found.");
}
Console.Read();
}
}
}
after i have done everything stated in google's documentation, including issuing a secrets.json file for my application/product, i ran it.
It fails with an exception, containing a "An invalid argument was supplied" inner exception.
I have retried everything with a new acocunt given new api credentials, etc., and still same error occurs. what am i doing wrong?
Try this
ClientSecrets secrets = new ClientSecrets()
{
ClientId = CLIENT_ID,
ClientSecret = CLIENT_SECRET
};
var token = new TokenResponse { RefreshToken = REFRESH_TOKEN };
var credentials = new UserCredential(new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = secrets
}),
"user",
token);
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials,
ApplicationName = "ApplicationName"
});