I need some help. Probably it is easy, but I don't get it.
In our firestation is a screen where the alerts are shown (address, keyword, ...). When there is no alert I'd like to show upcoming events like birthdays, etc. The software running the screen needs ".txt"-files for input.
So what I want to do is: I create a google calendar and put all the events in it. Every night the task scheduler runns a little piece of software and downloads the events from google, writes everything in one file and the alert-software reads this file.
Until now I got so far:
I created a google calendar api.
I downloaded a code sample from google and got it working with two calendars.
And that's it. Now I got stuck all day long and I guess I'm a better firefighter than programmer. So I need help. Please give me some hints how to do it.
using Google.Apis.Auth.OAuth2;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CalendarQuickstart
{
class Program
{
static string[] Scopes = { CalendarService.Scope.CalendarReadonly };
static string ApplicationName = "Google Calendar 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 Google Calendar API service.
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
// Define parameters of request. CALENDAR
EventsResource.ListRequest request = service.Events.List("primary");
request.TimeMin = DateTime.Now;
request.ShowDeleted = false;
request.SingleEvents = true;
request.MaxResults = 10;
request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;
// END REQUEST
// Define parameters of request. BIRTHDAY
EventsResource.ListRequest request1 = service.Events.List("#contacts#group.v.calendar.google.com");
request1.TimeMin = DateTime.Now;
request1.ShowDeleted = false;
request1.SingleEvents = true;
request1.MaxResults = 10;
request1.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;
// END REQUEST
// List events. CALENDAR
Events events = request.Execute();
Console.WriteLine("Upcoming events:");
if (events.Items != null && events.Items.Count > 0)
{
foreach (var eventItem in events.Items)
{
string when = eventItem.Start.DateTime.ToString();
if (String.IsNullOrEmpty(when))
{
when = eventItem.Start.Date;
}
Console.WriteLine("{0} ({1})", eventItem.Summary, when);
}
} // END LISTE
// List events. BIRTHDAY
Events events1 = request1.Execute();
Console.WriteLine("Upcoming events:");
if (events1.Items != null && events1.Items.Count > 0)
{
foreach (var eventItem in events1.Items)
{
string when = eventItem.Start.DateTime.ToString();
if (String.IsNullOrEmpty(when))
{
when = eventItem.Start.Date;
}
Console.WriteLine("{0} ({1})", eventItem.Summary, when);
}
} // END LISTE
else
{
Console.WriteLine("No upcoming events found.");
}
Console.Read();
}
}
}
I would suggest you to create a List<String> object (possibly named ListOfLines, initially empty, and then go on adding one string for each line you'd like your file to have. Then, when you already have all your lines in the list (in appropriate order), you just use File.WriteAllLines(filename, ListOfStrings), and a file will be created with the given filename, whose lines will be the strings in the list.
From what I have seen, you'd just replace Console.Writeline(somestring) by ListOfLines.Add(somestring) on your current code.
Also, mind that you don't need to explicitly add a newline to your strings, File.WriteLines does that for you.
Related
Previously, I developed an application which downloaded a file from a corporate Sharepoint site and then performed some magic with it.
The powers that be have since migrated to MS Teams and I'm trying to update the application to use the new platform. However, I'm having all sorts of issues getting the file to download.
My old (working for Sharepoint) code uses a WebClient to retrieve the file based on credentials previously provided by the user:
private string GetSchedule(string username, string password, string domain)
{
string tempPath = Path.GetTempFileName().Replace(".tmp", ".xlsm");
using (WebClient client = new WebClient())
{
client.Credentials = new NetworkCredential(username, password, domain);
try
{
client.DownloadFile(_networkSchedulePath, tempPath);
}
catch (WebException e)
{
if (e.Message.Contains("401"))
{
StatusUpdated?.Invoke(this, new EventArgs<string>("Invalid Credentials Provided"));
Finished?.Invoke(this, null);
return null;
}
if (e.Message.Contains("404"))
{
StatusUpdated?.Invoke(this, new EventArgs<string>("File Not Found"));
Finished?.Invoke(this, null);
return null;
}
else
{
StatusUpdated?.Invoke(this, new EventArgs<string>(e.Message));
Finished?.Invoke(this, null);
return null;
}
}
}
return tempPath;
}
However, when I use this with the new teams link I'm getting a 403 Forbidden error. So is there any way to programmatically retrieve a file from MS Teams?
I was mistaken in the comments. Simply replacing the NetworkCredentials with SharePointOnlineCredentials is not the solution.
I'm not sure if the following is the "right" approach, but it works and seems pretty solid. Please give it a try:
private static string GetFile(string path, string username, string password, string domain)
{
var secureString = new SecureString();
foreach (var ch in password)
{
secureString.AppendChar(ch);
}
string tempPath = Path.GetTempFileName().Replace(".tmp", ".xlsm");
using (WebClient client = new WebClient())
{
var credentials = new SharePointOnlineCredentials(username, secureString);
client.Headers[HttpRequestHeader.Cookie] = credentials.GetAuthenticationCookie(new Uri(path));
try
{
client.DownloadFile(path, tempPath);
}
catch (WebException e)
{
// Error Handling
}
}
return tempPath;
}
Another option is to use the CSOM rather than using a webclient directly. n.b., I encountered errors at the OpenBinaryDirect() call when using the Microsoft.SharePoint.Client NuGet package and it looks like this package is wildly out of date. It appears that the one to use now is Microsoft.SharePointOnline.CSOM or Microsoft.SharePoint2019.CSOM:
private static string GetFileWithClientContext(string path, string username, string password, string domain)
{
var secureString = new SecureString();
foreach (var ch in password)
{
secureString.AppendChar(ch);
}
string tempPath = Path.GetTempFileName().Replace(".tmp", Path.GetExtension(path));
using (var context = new ClientContext(path))
{
context.Credentials = new SharePointOnlineCredentials(username, secureString);
try
{
using (var file = Microsoft.SharePoint.Client.File.OpenBinaryDirect(context, new Uri(path).AbsolutePath))
using (var outFile = System.IO.File.OpenWrite(tempPath))
{
file.Stream.CopyTo(outFile);
}
}
catch (WebException e)
{
// Error Handling
}
}
return tempPath;
}
Thanks to JLRishe for the help his answer and comments provided. However, the final solution varied from the one in his answer, which is why I'm posting it here:
The OfficeDevPnP.Core package is used extensively for this.
Firstly, the AuthenticationManager is used to get a ClientContext in terms of the specific sharepoint site that needs to be accessed. This pops a window up to allow for the MFA. Then various components are loaded in via the ClientContext object. From here, the file is fetched via Guid and dumped to disk.
private string GetSchedule()
{
string tempPath = Path.GetTempFileName().Replace(".tmp", ".xlsm");
try
{
AuthenticationManager authManager = new OfficeDevPnP.Core.AuthenticationManager();
ClientContext ctx = authManager.GetWebLoginClientContext("https://oursite.sharepoint.com/sites/ourspecificsite/");
Web web = ctx.Web;
Microsoft.SharePoint.Client.File schedule = web.GetFileById(new Guid("ourguid"));
ctx.Load(web);
ctx.Load(schedule);
ctx.ExecuteQuery();
FileInformation fInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(ctx, schedule.ServerRelativeUrl);
using (var fileStream = File.Create(tempPath))
{
fInfo.Stream.CopyTo(fileStream);
}
}
catch (WebException e)
{
StatusUpdated?.Invoke(this, new EventArgs<string>(e.Message));
return null;
}
return tempPath;
}
using Microsoft.Graph;
using Microsoft.Graph.Auth;
using Microsoft.Identity.Client;
using System.IO;
using System.Linq;
namespace Answer
{
class Answer
{
static void Main(string[] args)
{
// Create Confidential Application
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create("<My_Azure_Application_Client_ID>")
.WithTenantId("<My_Azure_Tenant_ID>")
.WithClientSecret("<My_Azure_Application_Client_Secret>")
.Build();
// Create an authentication provider.
ClientCredentialProvider authenticationProvider = new ClientCredentialProvider(confidentialClientApplication);
// Configure GraphServiceClient with provider.
GraphServiceClient graphServiceClient = new GraphServiceClient(authenticationProvider);
// Get a user
var user = graphServiceClient.Users["<My_Azure_User_Name>"].Request().GetAsync().Result;
// Get the teams the user is member of
var joinedTeams = graphServiceClient.Users[user.Id].JoinedTeams.Request().GetAsync().Result;
// Get the team we are intereseted in
var team1 = joinedTeams.FirstOrDefault(t => t.DisplayName == "<TeamName_Of_Interest>");
// Get the main folders
var folders = graphServiceClient.Groups[team1.Id].Drive.Root.Children
.Request()
.GetAsync().Result;
// Get the files in the first main folder
var files = graphServiceClient.Groups[team1.Id].Drive.Items[folders[0].Id].Children
.Request()
.GetAsync().Result;
// Get the file-Data of the first file
MemoryStream fileData = graphServiceClient.Groups[team1.Id].Drive.Items[files[0].Id].Content
.Request()
.GetAsync().Result as MemoryStream;
// Save the file to the hard-disc
System.IO.File.WriteAllBytes($"C:\\{files[0].Name}", fileData.ToArray());
}
}
}
I have 3000 emails in my gmail account. I want to create an aggregated list of all the senders so that I can more effectively clean up my inbox. I dont need to download the message bodys or the attachments.
I used this sample to get me started (https://developers.google.com/gmail/api/quickstart/dotnet) althought now I cant figure out how to return more than 100 message ids when i execute this code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Gmail.v1;
using Google.Apis.Gmail.v1.Data;
using Google.Apis.Requests;
using Google.Apis.Services;
using Google.Apis.Util;
using Google.Apis.Util.Store;
namespace GmailQuickstart
{
class Program
{
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("credentials.json", FileMode.Open, FileAccess.Read))
{
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,
});
////get all of the message ids for the messages in the inbox
var messageRequest = service.Users.Messages.List("me");
messageRequest.LabelIds = "INBOX";
var messageList = new List<Message>();
ListMessagesResponse messageResponse1 = new ListMessagesResponse();
var k = 0;
do
{
messageResponse1 = messageRequest.Execute();
messageList.AddRange(messageResponse1.Messages);
var output = $"Request {k} - Message Count: {messageList.Count()} Page Token: {messageRequest.PageToken} - Next Page Token: {messageResponse1.NextPageToken}";
Console.WriteLine(output);
System.IO.File.AppendAllText(#"C:\000\log.txt", output);
messageRequest.PageToken = messageResponse1.NextPageToken;
k++;
//this switch allowed me to walk through getting multiple pages of emails without having to get them all
//if (k == 5)
//{
// break;
//}
} while (!String.IsNullOrEmpty(messageRequest.PageToken));
//once i created the list of all the message ids i serialized the list to JSON and wrote it to a file
//so I could test the next portions without having to make the calls against the above each time
var serializedMessageIdList = Newtonsoft.Json.JsonConvert.SerializeObject(messageList);
System.IO.File.WriteAllText(#"C:\000\MessageIds.json", serializedMessageIdList);
//read in the serialized list and rehydrate it to test the next portion
var mIdList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Message>>(System.IO.File.ReadAllText(#"C:\000\MessageIds.json"));
//this method takes those message ids and gets the message object from the api for each of them
//1000 is the maximum number of requests google allows in a batch request
var messages = BatchDownloadEmails(service, mIdList.Select(m => m.Id), 1000);
//again i'm serializing the message list and writing them to a file
var serializedMessageList = Newtonsoft.Json.JsonConvert.SerializeObject(messages);
System.IO.File.WriteAllText(#"C:\000\Messages.json", serializedMessageList);
//and then reading them in and rehydrating the list to test the next portion
var mList = Newtonsoft.Json.JsonConvert.DeserializeObject<IList<Message>>(System.IO.File.ReadAllText(#"C:\000\Messages.json"));
//then i loop through each message and pull the values out of the payload header i'm looking for
var emailList = new List<EmailItem>();
foreach (var message in mList)
{
if (message != null)
{
var from = message.Payload.Headers.SingleOrDefault(h => h.Name == "From")?.Value;
var date = message.Payload.Headers.SingleOrDefault(h => h.Name == "Date")?.Value;
var subject = message.Payload.Headers.SingleOrDefault(h => h.Name == "Subject")?.Value;
emailList.Add(new EmailItem() { From = from, Subject = subject, Date = date });
}
}
//i serialized this list as well
var serializedEmailItemList = Newtonsoft.Json.JsonConvert.SerializeObject(emailList);
System.IO.File.WriteAllText(#"C:\000\EmailItems.json", serializedEmailItemList);
//rehydrate for testing
var eiList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<EmailItem>>(System.IO.File.ReadAllText(#"C:\000\EmailItems.json"));
//here is where i do the actual aggregation to determine which senders i have the most email from
var senderSummary = eiList.GroupBy(g => g.From).Select(g => new { Sender = g.Key, Count = g.Count() }).OrderByDescending(g => g.Count);
//serialize and output the results
var serializedSummaryList = Newtonsoft.Json.JsonConvert.SerializeObject(senderSummary);
System.IO.File.WriteAllText(#"C:\000\SenderSummary.json", serializedSummaryList);
}
public static IList<Message> BatchDownloadEmails(GmailService service, IEnumerable<string> messageIds, int chunkSize)
{
// Create a batch request.
var messages = new List<Message>();
//because the google batch request will only allow 1000 requests per batch the list needs to be split
//based on chunk size
var lists = messageIds.ChunkBy(chunkSize);
//double batchRequests = (2500 + 999) / 1000;
//for each list create a request with teh message id and add it to the batch request queue
for (int i = 0; i < lists.Count(); i++)
{
var list = lists.ElementAt(i);
Console.WriteLine($"list: {i}...");
var request = new BatchRequest(service);
foreach (var messageId in list)
{
//Console.WriteLine($"message id: {messageId}...");
var messageBodyRequest = service.Users.Messages.Get("me", messageId);
//messageBodyRequest.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Metadata;
request.Queue<Message>(messageBodyRequest,
(content, error, index, message) =>
{
messages.Add(content);
});
}
Console.WriteLine("");
Console.WriteLine("ExecuteAsync");
//execute all the requests in the queue
request.ExecuteAsync().Wait();
System.Threading.Thread.Sleep(5000);
}
return messages;
}
}
public class EmailItem
{
public string From { get; set; }
public string Subject { get; set; }
public string Date { get; set; }
}
public static class IEnumerableExtensions
{
public static IEnumerable<IEnumerable<T>> ChunkBy<T>(this IEnumerable<T> source, int chunkSize)
{
return source
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / chunkSize)
.Select(x => x.Select(v => v.Value));
}
}
}
The research I've done says I need to use a batch request and based on the information I've found Im not able to adapt it to what I'm trying to accomplish. My understanding is that I would use the batch request to get all of the message ids and then 3000 individual calls to get the actual from, subject, and date received from each email in my inbox??
You can use paging to get a full list.
Pass the page token from the previous page to get the next call to Users.Messages.List (don't pass into the first call to get things started). Detect the end when the result contains no messages.
This allows you to get all the messages in the mailbox.
NB. I suggest you make the code async: if there are more than a few messages to read, it can take an appreciable time to get them all.
You can also use PageStreamer to get the remainder of the results.
var pageStreamer = new PageStreamer<Google.Apis.Gmail.v1.Data.Message, UsersResource.MessagesResource.ListRequest, ListMessagesResponse, string>(
(request, token) => request.PageToken = token,
response => response.NextPageToken,
response => response.Messages);
var req = service.Users.Messages.List("me");
req.MaxResults = 1000;
foreach (var result in pageStreamer.Fetch(req))
{
Console.WriteLine(result.Id);
}
This code will continue to run as long as there are additional results to request. Batching isnt really going to help you here as there is no way to know what the next page token will be.
How do I specify an email address for GoogleCalendar API notifications?
I need to programatically manipulate my Google Calendar via the Google API using C# dot-net. I've been able to create, delete and modify events successfully, but I'd like some control over notifications. Currently only email and UI popup options are available, and email defaults to the Google email account.
What I'm thinking is that if I can manipulate the email address used, I can send email to my Verizon email-to-SMS address, and send a text message instead of email (SMS is an option only for Government accounts). Or possibly to a dummy email that interfaces to an SMS service like Twilio. Bottom line is I would like to send email notifications to one or more email addresses of my choosing.
The only option for email is in a constructor for an EventReminder override:
new EventReminder{Method="email",Minutes=60};
Here's my working code:
namespace stuff
{
class Program
{
static string[] Scopes = { CalendarService.Scope.Calendar };
static string ApplicationName = "Google Calendar API .NET Quickstart";
static string _Chelle = "fake_id#gmail.com";
static string _EventCalendar = "jwejq36jjgwijg54iw7yjs7j7e#group.calendar.google.com";
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/calendar-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 Google Calendar API service.
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
EventsResource.ListRequest request = service.Events.List(_EventCalendar);
request.TimeMin = DateTime.Now;
request.TimeMax = DateTime.Now.AddDays(30);
request.ShowDeleted = false;
Events events = request.Execute();
if (events.Items != null && events.Items.Count > 0)
{
foreach (var eventItem in events.Items)
{
// add new reminders
eventItem.Reminders = new Event.RemindersData
{
UseDefault = false,
Overrides = new[]
{
new EventReminder {Method="popup",Minutes=((60*24*7) - (60*9)) }, // one week before # 0900
new EventReminder {Method="email",Minutes=((60*24*7) - (60*9)) }
}
};
try
{
service.Events.Update(eventItem, _EventCalendar, eventItem.Id).Execute();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Thread.Sleep(1000);
}
}
else
{
Console.WriteLine("No events found.");
}
Console.Read();
}
}
}
I'm getting this error while trying to run my c# console application... I am trying to call google calender api v3 to fetch calender and add event to calender. According to the sample code from google-api-dotnet-client I am doing this.( https://code.google.com/p/google-api-dotnet-client/source/browse/Calendar.VB.ConsoleApp/Program.vb?repo=samples ) Here is the vb.net code. I am using this sample after converting it to c# code.
Here is my code:
class Program
{
static void Main(string[] args)
{
try
{
new Program().Run().Wait();
}
catch (AggregateException ex)
{
foreach (var e in ex.InnerExceptions)
{
Console.WriteLine("ERROR: " + e.Message);
}
}
}
private async Task Run()
{
UserCredential credential;
IList<string> scopes = new List<string>();
CalendarService service;
scopes.Add(CalendarService.Scope.Calendar);
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
// problem occuring during executing this statement.
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
scopes,
"user", CancellationToken.None, new FileDataStore("Calender.SampleApp") );
}
BaseClientService.Initializer initializer = new BaseClientService.Initializer();
initializer.HttpClientInitializer = credential;
initializer.ApplicationName = "C# Calendar Sample";
service = new CalendarService(initializer);
Event newEvent = new Event();
newEvent.Summary = "Appointment";
newEvent.Description = "Need to meet my Uncle";
IList<EventReminder> reminders = new List<EventReminder>();
reminders.Add(new EventReminder { Method = "sms", Minutes = 10 });
newEvent.Reminders = new Event.RemindersData { UseDefault = false, Overrides = reminders };
newEvent.Recurrence = new String[] { "DTSTART;TZID=Bangladesh Standard Time:20140124T163000;RRULE:FREQ=DAILY" };
IList<EventAttendee> attendees = new List<EventAttendee>();
attendees.Add(new EventAttendee { Email = "hannan.cse.m#gmail.com", Organizer = true, DisplayName = "Hannan" });
newEvent.Attendees = attendees;
newEvent.GuestsCanInviteOthers = false;
newEvent.GuestsCanModify = false;
newEvent.GuestsCanSeeOtherGuests = false;
newEvent.Location = "Dhaka, Bangladesh";
newEvent.Start = new EventDateTime { DateTime = DateTime.Now, TimeZone = "Bangladesh Standard Time" };
Event recurringEvent = service.Events.Insert(newEvent, "primary").Execute();
var list = await service.CalendarList.List().ExecuteAsync();
}
}
This is my redirect URIs in my GoogleDevelopers Console project.
Redirect URIs: http://localhost:7744/authorize/
And this is the error message shown in browser.
I couldn't find any way to resolve this problem. Some help will be appreciable. I also search all the realted post in stackoverflow. But I couldn't find it's solution.
I think you are doing something wrong while "create client id" in GoogleDevelopers Console. Make sure that you have chosed "Installed application" in application type to access your project from console application.
Have a look in the attached image. According to request type you must create clientid
and credintials in your registered application in Google Developers Console.
You don't need to define redirect uri in console application while authenticating.
I was having this error on a simple test program (https://ctrlq.org/google.apps.script/docs/guides/rest/quickstart/dotnet.html), and it happens to be the client_secret.json was th wrong one, download it again and it worked.
I'm trying to use Google Directory API Library for .NET to maintain email addresses for a domain. The latest library is google-admin-directory_v1-rev6-csharp-1.4.0-beta. The best and farthest I've gotten so far is to receive a 403 error (Not Authorized to access this resource/api).
Has anyone out there successfully used it? If so, could you share some code, tips, or tricks?
I have used it and got some success in creating a console-application.
At the moment I'm trying to find a way to skip the copy/paste of the authorization code.
Don't forget to turn on API access in your APIs Console.
I'll show you a small sample:
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using DotNetOpenAuth.OAuth2;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using Google.Apis.Samples.Helper;
using Google.Apis.Services;
using Google.Apis.Util;
using Google.Apis.Admin.directory_v1;
using Google.Apis.Admin.directory_v1.Data;
namespace Bergstedts.CreateNewUser
{
public class Program
{
static void Main(string[] args)
{
// Display the header and initialize the sample.
CommandLine.EnableExceptionHandling();
Console.WriteLine("Create users in a google apps domain!");
Console.WriteLine("by Jonas Bergstedt 2013");
// Get the user data and store in user object
Console.Write("Email: ");
string userId = Console.ReadLine();
Console.Write("Givenname: ");
string GivenName = Console.ReadLine();
Console.Write("Familyname: ");
string FamilyName = Console.ReadLine();
Console.Write("Password: ");
string Password = Console.ReadLine();
User newuserbody = new User();
UserName newusername = new UserName();
newuserbody.PrimaryEmail = userId;
newusername.GivenName = GivenName;
newusername.FamilyName = FamilyName;
newuserbody.Name = newusername;
newuserbody.Password = Password;
// Register the authenticator.
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description)
{
ClientIdentifier = "<your clientId from Google APIs Console>",
ClientSecret = "<your clientsecret from Google APIs Console>",
};
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
// Create the service.
var service = new DirectoryService(new BaseClientService.Initializer()
{
Authenticator = auth,
ApplicationName = "Create User",
ApiKey = "<your API Key from Google APIs console> (not sure if needed)"
});
User results = service.Users.Insert(newuserbody).Execute();
Console.WriteLine("User :" + results.PrimaryEmail + " is created");
Console.WriteLine("Press any key to continue!");
Console.ReadKey();
}
private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
// Get the auth URL:
IAuthorizationState state = new AuthorizationState(new[] { DirectoryService.Scopes.AdminDirectoryUser.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
Uri authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
Console.WriteLine();
Console.Write("Authorization Code: ");
string authCode = Console.ReadLine();
// Retrieve the access token by using the authorization code:
return arg.ProcessUserAuthorization(authCode, state);
}
}
}