using System; using Google.Apis.Auth.OAuth2; using Google.Apis.Gmail.v1; using Google.Apis.Gmail.v1.Data; using Google.Apis.Services; using Google.Apis.Util.Store; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; using System.Linq; using System.Text.RegularExpressions; using System.Runtime.Remoting.Messaging; namespace cdrtool { class Gmail { static string[] Scopes = { GmailService.Scope.GmailReadonly }; static string ApplicationName = "Gmail API .NET Quickstart"; public static async Task GetMail() { UserCredential credential; string mfa_code = ""; using (var stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read)) { string credPath = "token.json"; credential = await GoogleWebAuthorizationBroker.AuthorizeAsync( GoogleClientSecrets.FromStream(stream).Secrets, Scopes, "user", CancellationToken.None, new FileDataStore(credPath, true)); //Console.WriteLine("Credential file saved to: " + credPath); } // Create Gmail API service. var service = new GmailService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = ApplicationName, }); // Define the timestamp after which we want to find emails (in Unix time format). DateTime afterTimestamp = new DateTime(2024, 01, 01); // Use this when you cannot generate a new mfs email to test with afterTimestamp = DateTime.Now; // We do this to ensure we get the latest auth email, usually 2-3 seconds after this fires long afterUnixTimestamp = ((DateTimeOffset)afterTimestamp).ToUnixTimeSeconds(); Logger.Log(1,"Awaiting MFA email (max {0}s)", cdrtool.mfa_delay); bool repeat = false; int count = cdrtool.mfa_delay; do { // Fetch emails received after the given timestamp var request = service.Users.Messages.List("me"); request.Q = $"after:{afterUnixTimestamp} from:\"Rogers SIP Portal\" "; //refinement added Sep16 2024 ListMessagesResponse response = await request.ExecuteAsync(); var messages = response.Messages?.OrderByDescending(m => m.InternalDate).ToList(); repeat = (messages == null); //Console.WriteLine("Messages count: {0}", (messages != null) ? messages.Count : 0 ); if (messages != null && messages.Any()) { //Console.WriteLine("Messages count: {0}",messages.Count); var mostRecentMessage = messages.First(); Message message = await service.Users.Messages.Get("me", mostRecentMessage.Id).ExecuteAsync(); try { Regex word = new Regex(@".*Your Portal.+([0-9]{6})"); // MFA looking for 6 digit code //refinement added Sep16 2024 Match m = word.Match(message.Snippet); // .Snippet easily grabs enough plain text to find the MFA code if (m.Success) { Group g = m.Groups[1]; //Capture c = g.Captures[0]; Logger.Log(6, "Regex Match {0} / Group Count {1} / Captures Count {2} / result={3}", m.Success, m.Groups.Count, m.Captures.Count, g.Value); int code = Convert.ToInt32(g.Value); if ((code >= 0) && (code <= 999999)) Logger.Log(5, "Code found successfully {0}", code); mfa_code = g.Value; repeat = false; } else { Logger.Log(1, "No code found in email."); } } catch (Exception e) { Logger.Log(0, "Error parsing Gmail. {0}", e.Message); } } else { int incr = 1; if (count <= (cdrtool.mfa_delay - 5) ) incr = 5; count-= incr; System.Threading.Thread.Sleep(1000 * incr); Logger.Log(1, "No message found for {0}s", cdrtool.mfa_delay - count); } } while (repeat && (count > 0) ); Logger.Log(0, "Emailed MFA Code : {0}", mfa_code); return mfa_code; } static string GetPlainTextFromMessageParts(IList parts) { if (parts == null) return string.Empty; foreach (var part in parts) { //Console.WriteLine("email: type:{0}\nbody:\n{1}", part.MimeType, part.Body.Data); if (part.MimeType == "text/plain" && part.Body != null && part.Body.Data != null) { return Base64UrlDecode(part.Body.Data); } else if (part.Parts != null) { string text = GetPlainTextFromMessageParts(part.Parts); if (!string.IsNullOrEmpty(text)) return text; } } return string.Empty; } static string Base64UrlDecode(string input) { string s = input.Replace('-', '+').Replace('_', '/'); switch (s.Length % 4) { case 2: s += "=="; break; case 3: s += "="; break; } var bytes = Convert.FromBase64String(s); return System.Text.Encoding.UTF8.GetString(bytes); } } }