I have problem with delete message from gmail server using google.apis
I can login and read messages but when I use
GmailService.Users.Messages.Delete("my-email#gmail.com", email.Id);
GmailService.Users.Threads.Delete("my-email#gmail.com", email.ThreadId);
i only delete message 'localy' in instance GmailService. When I repeat checking mail, messagess still they are...
email.Id and email.ThreadId are ok, I can read messages.
I have fully rights. When I loading .json (first clean run) to authorize, gmail give me a full access.
"Read, compose, send and permanently delete all emails from Gmail."
Any ideas? Some code..
private static readonly string[] Scopes = { GmailService.Scope.MailGoogleCom};
....
GmailService GmailService = new();
using (FileStream stream = new("client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
credPath = System.IO.Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart.json");
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.FromStream(stream).Secrets, Scopes, "ma-email#gmail.com", CancellationToken.None, new FileDataStore(credPath, true)).Result;
this.GmailService = new(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "AppName"
});
}
...
UsersResource.MessagesResource.ListRequest inboxlistRequest = GmailService.Users.Messages.List("my-email#gmail.com");
inboxlistRequest.LabelIds = "INBOX";
inboxlistRequest.IncludeSpamTrash = false;
ListMessagesResponse EmailListResponse = inboxlistRequest.Execute();
So i have 'email.Id' and 'email.ThreadId', but why i can't pernamently delete these messagess?
Any ideas?
These calls:
GmailService.Users.Messages.Delete("my-email#gmail.com", email.Id);
GmailService.Users.Threads.Delete("my-email#gmail.com", email.ThreadId);
... create requests, but don't execute them. Try:
GmailService.Users.Messages.Delete("my-email#gmail.com", email.Id).Execute();
GmailService.Users.Threads.Delete("my-email#gmail.com", email.ThreadId).Execute();
Related
I'm new to C# and I'm creating a WPF C# app. I want use Google Drive Rest API to send backup file to Google Drive. But this isn't problem. When I wrote Android app in Java, getting account name was very easy. But in C# and my desktop app, I don't now how do this. I read many topic and Google documentation, but I didn't find answer.
Here is my code for Helper class. I only want to get the account name or address and display it in the main window.
I found a solution with Google+ API, but now it doesn't work because Google+ doesn't exist.
Is there any way to do this?
UserCredential credential;
public DriveService GetGoogleDriveService()
{
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 = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/menadzer_zespolow_token.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
return service;
}
}
public String GetAccountEmail()
{
// code to get account name or email there
return accountNameOrEmail;
}
I get credentials using code
static string[] Scopes = { "https://www.googleapis.com/auth/userinfo.email" };
private static UserCredential GenerateCredential()
{
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);
}
return credential;
}
How to get email from this credential? I've tried code
private string GetEmailFromCredentials(UserCredential credential)
{
var plusService = new PlusService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "My Application",
});
var me = plusService.People.Get("me").Execute();
var useremail = me.Emails.FirstOrDefault().Value;
return useremail;
}
but it looks like that People.Get("me") is not possibe anymore. I'm getting error "Google.Apis.Requests.RequestError
Legacy People API has not been used in project 618254727025 before or it is disabled"
solution is to get access token and try https://www.googleapis.com/oauth2/v2/userinfo?access_token=
In your scopes variable. Try and just use the value "email" not the
full https address. Scope keywords in the web link are separated by spaces. Here is a way that I do this to obtain the scopes: profile email openid.
To test this approach, you can manually paste the below weblink into a browser after obtaining the access code:
https://www.googleapis.com/oauth2/v2/userinfo?access_token=[PASTE ACCESS CODE HERE]&[PASTE VALUE FROM THE BELOW VARIABLE authorizationRequest HERE]
fyi: I was ammending the demonstration code available: https://github.com/googlesamples/oauth-apps-for-windows.
// Creates the OAuth 2.0 authorization request.
string authorizationRequest = string.Format("{0}?response_type=code&scope=openid%20profile%20email&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}",
authorizationEndpoint,
System.Uri.EscapeDataString(redirectURI),
clientID,
state,
code_challenge,
code_challenge_method);
You can use the users.getprofile it will return the email address of the user who is currently authenticated.
request
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "My Application",
});
var user = service.Users.GetProfile("me").Execute;
response
{
"emailAddress": "xxxx1#gmail.com",
"messagesTotal": 8394,
"threadsTotal": 1494,
"historyId": "605503"
}
People me
The correct usage of people.get is "people/me"
var request = plusService.People.Get("people/me")
request.PersonFields("emailAddresses");
var response = request.Execute();
I have been stuck on this issue for several days. And finally, thanks to this link (Check if user is already logged in), I learned that the parameter input, "user", to be the key issue. This "user" should be the windows login user (you can use Enviroment.Username), not the programmer or APP user. The GoogleWebAuthorizationBroker.AuthorizeAsync uses this username to save its credential in the location:
C:\Users[username]\AppData\Roaming\Google.Apis.Auth\Google.Apis.Auth.OAuth2.Responses.TokenResponse-[username]
(something like this).
So if you feed "user" to AuthorizeAsync, the credential saving could be a problem, and your app will hang or lag seriously. And, later when you want to use the cred file to get userinfo and email, it will be problematic (lag seriously). In my case, user info will be all missing, leaving only an email address. Also, you have to include the required two scopes: "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile". Hope these helps.
Add 'https://www.googleapis.com/auth/userinfo.email' in scopes.
In callback you will code. Get tokens json from this code using
oauth2Client.
This json contains id_token which is basically a jwt
token, parse it u will get email.
I'm trying the code below, obtained from their docs here. I'm unable to compile, I get an exception message:
Maybe I'm not understanding the TeamDrive concept correctly?
I'm not sure where the issue is. Below is the code snippet I have:
var teamDriveMetadata = new TeamDrive()
{
Name = "Project Resources"
};
var requestId = System.Guid.NewGuid().ToString();
var request = service.Teamdrives.Create(teamDriveMetadata, requestId);
request.Fields = "id";
var teamDrive = request.Execute();
Console.WriteLine("Team Drive ID: " + teamDrive.Id);
Console.WriteLine("Done.");
Console.Read();
Below is the auth setup:
using (var stream =
new FileStream("client_secret.json", FileMode.Open, FileAccess.ReadWrite))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/drive-dotnet-quickstart.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"MyKey",
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
});
FYI: I ran the sample code linked without issue. I have a test project that has the proper permissions already established. I pasted the linked code into that project, and had to resolve "var request" conflicting with the same in my existing code. Once resolved the code ran without issue.
As previously suggested I would recommend focusing on resolving your permissions/scopes.
im working on a project that need to access Gmail using Gmail API .
but i keep getting this error when trying to login Imap:
{"status":"400","schemes":"Bearer","scope":"https://mail.google.com/"}
i sew here OAuth 2 SASL string error ,that someone asked about this issue and said that it solved by puting the right token scope
in my case it didnt work , the error is still popping .
static string[] Scopes = { GmailService.Scope.GmailReadonly };
static string ApplicationName = "Gmail API .NET 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/gmail-dotnet-quickstart.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets, Scopes, "Sapir", 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");
credential.Token.Scope = "https://mail.google.com/";
ImapClient ic = new ImapClient("imap.gmail.com","astechnetivot#gmail.com", credential.Token.AccessToken,AuthMethods.SaslOAuth, 993, true);
ic.SelectMailbox("INBOX");
Console.WriteLine(ic.GetMessageCount());
MailMessage[] mm = ic.GetMessages(0, 1);
foreach (MailMessage m in mm)
{
Console.WriteLine(m.Subject + " " + m.Date.ToString());
}
ic.Dispose();
Console.Read();
}
Error message seems to happen when you use an expired access token, check your access token and make sure that it is not expired. Here's a related issue having status 400: Gmail XOAUTH 2.0, IMAP AUTHENTICATE returns "status":"400"
I'm using Google's Oauth 2.0 to upload videos to Youtube via our server.
My client ID is a "service account". I downloaded the json key and added it to my solution.
Here is the relevant code:
private async Task Run(string filePath)
{
UserCredential credential;
var keyUrl = System.Web.HttpContext.Current.Server.MapPath("~/content/oauth_key.json");
using (var stream = new FileStream(keyUrl, FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows an application to upload files to the
// authenticated user's YouTube channel, but doesn't allow other types of access.
new[] { YouTubeService.Scope.YoutubeUpload },
"user",
CancellationToken.None
);
}
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
});
When I run it, I get this error: At least one client secrets (Installed or Web) should be set.
However, in my json there is no "client secret":
{
"private_key_id": "9d98c06b3e730070806dcf8227578efd0ba9989b",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIICdQIBADANBgkqhk etc,
"client_email": "546239405652-8igo05a5m8cutggehk3rk3hspjfm3t04#developer.gserviceaccount.com",
"client_id": "546239405652-8igo05a5m8cutggehk3rk3hspjfm3t04.apps.googleusercontent.com",
"type": "service_account"
}
so I assume I overlooked something.
Maybe I can't use the "service account" ? don't know...
The solution that uses json file is quite similar.
Here is sample that create VisionService using GoogleCredential object created from json file with ServiceAccountCredential.
GoogleCredential credential;
using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped(VisionService.Scope.CloudPlatform);
}
var service = new VisionService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "my-app-name",
});
this sample require two NuGet packages:
Google.Apis.Vision.v1
Google.Apis.Oauth2.v2
I managed to get a service account to work with a P12 file, But would like to know how to use with the JSON file, Or just value from the JSON file to create the certificate.
To get the token
private static String GetOAuthCredentialViaP12Key()
{
const string serviceAccountEmail = SERVICE_ACCOUNT_EMAIL;
var certificate = new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret", X509KeyStorageFlags.Exportable);
var scope = DriveService.Scope.Drive + " https://spreadsheets.google.com/feeds";
var credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { scope }
}.FromCertificate(certificate) );
if (credential.RequestAccessTokenAsync(CancellationToken.None).Result == false)
{
return null;
}
return credential.Token.AccessToken;
}
And this is how I used the token I got
// Initialize the variables needed to make the request
OAuth2Parameters parameters = new OAuth2Parameters {AccessToken = token};
GOAuth2RequestFactory requestFactory = new GOAuth2RequestFactory(null, "MySpreadsheetIntegration-v1", parameters);
SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");
service.RequestFactory = requestFactory;
Not an expert on C# but it looks like you were trying to use the service account to do the OAuth2 web server flow, which shouldn't work.
You probably want to use ServiceAccountCredential instead.
For more information about different Google OAuth2 flows, please refer to the doc for web server, service account, etc.