Using Gmail SMTP OAUTH2 to send email: error JWT has expired - c#

I created a ClientID & Client Secret (using this guide) to authenticate a desktop application (C#/.NET) to send emails from a Gmail account, with Gmail SMTP OAUTH because Google will no longer support less secure apps to send e-mail.
The first time application ran, browser was open and i had need to enter on accounts.google.com with my credential and mail has been sent.
After i receveid an Error "JWT is expired" when i try to execute
var jwtPayload = GoogleJsonWebSignature.ValidateAsync(asyncUserCredential.Token.IdToken).Result;
I can't able to understand how it works and how i can obtain a refreshed token for passing to ValidateAsync method.
This is code used:
private async Task AuthenticateAsync()
{
bool expired;
string mytoken;
try
{
string CLIENT_ID = "41527eeeeee489-xxxxxxxxxxxxxxxxxxxusercontent.com";
asyncUserCredential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = CLIENT_ID,
ClientSecret = "GOCXXXXXXXXXXXXXXXXXXX"
},
new[] { "email", "profile", "https://mail.google.com/" },
"user",
CancellationToken.None
);
var sFromMailAddress = "office#gmail.com";
var jwtPayload = GoogleJsonWebSignature.ValidateAsync(asyncUserCredential.Token.IdToken).Result;
var mailMessage = new MimeMessage();
mailMessage.From.Add(new MailboxAddress("Office", sFromMailAddress));
mailMessage.To.Add(new MailboxAddress("Frank", "someone#gmail.com"));
mailMessage.Subject = "Automated Mail with OAuth";
mailMessage.Body = new TextPart("plain")
{
Text = "Hello"
};
using (var client = new SmtpClient())
{
client.Connect("smtp.gmail.com", 587, SecureSocketOptions.StartTls);
// use the access token
var oauth2 = new SaslMechanismOAuth2(sFromMailAddress, asyncUserCredential.Token.AccessToken);
client.Authenticate(oauth2);
client.Send(mailMessage);
client.Disconnect(true);
}
}
catch (Exception ex)
{
string msg = ex.Message;
if (ex.InnerException != null)
msg = ex.InnerException.Message;
if (msg.Contains("JWT has expired"))
{
expired = true;
}
else if (msg.Contains("JWT invalid"))
{
//XtraMessageBox.Show("JWT invalid" , "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
//XtraMessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
//return string.Empty;
}
}
For sending email used:
using MailKit.Net.Smtp;
using MimeKit;
using MailKit.Security;

Related

C# SmtpException - problem with sending mails

Sending mails doesn't work. I'm not sure if it's something with client settings or mail server...
When using Gmail SMTP server I got "Connection closed" exception, when changing port to 587 I get "Authentication required" message. What's more interesting when changing SMTP server to something different (smtp.poczta.onet.pl) I get "Time out" exception after ~100s
Here's the code:
protected void SendMessage(object sender, EventArgs e)
{
// receiver address
string to = "******#student.uj.edu.pl";
// mail (sender) address
string from = "******#gmail.com";
// SMTP server address
string server = "smtp.gmail.com";
// mail password
string password = "************";
MailMessage message = new MailMessage(from, to);
// message title
message.Subject = TextBox1.Text;
// message body
message.Body = TextBox3.Text + " otrzymane " + DateTime.Now.ToString() + " od: " + TextBox2.Text;
SmtpClient client = new SmtpClient(server, 587);
client.Credentials = new System.Net.NetworkCredential(from, password);
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.EnableSsl = true;
try
{
client.Send(message);
// ui confirmation
TextBox3.Text = "Wysłano wiadmość!";
// disable button
Button1.Enabled = false;
}
catch (Exception ex)
{
// error message
TextBox3.Text = "Problem z wysłaniem wiadomości (" + ex.ToString() + ")";
}
}
I've just read that google don't support some less secure apps (3rd party apps to sign in to Google Account using username and password only) since 30/05/22. Unfortunately can't change it because I have two-stage verification account. Might it be connected? Or is it something with my code?
Gmail doesn't allow, or want you to do that with passwords anymore. They ask you to create a credentials files and then use a token.json to send email.
Using their API from Google.Apis.Gmail.v1 - from Nuget. Here is a method I made and test that is working with gmail.
void Main()
{
UserCredential credential;
using (var stream =
new FileStream(#"C:\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.");
}
//Console.Read();
var msg = new Google.Apis.Gmail.v1.Data.Message();
MimeMessage message = new MimeMessage();
message.To.Add(new MailboxAddress("", "toemail.com"));
message.From.Add(new MailboxAddress("Some Name", "YourGmailGoesHere#gmail.com"));
message.Subject = "Test email with Mime Message";
message.Body = new TextPart("html") {Text = "<h1>This</h1> is a body..."};
var ms = new MemoryStream();
message.WriteTo(ms);
ms.Position = 0;
StreamReader sr = new StreamReader(ms);
string rawString = sr.ReadToEnd();
byte[] raw = System.Text.Encoding.UTF8.GetBytes(rawString);
msg.Raw = System.Convert.ToBase64String(raw);
var res = service.Users.Messages.Send(msg, "me").Execute();
res.Dump();
}
static string[] Scopes = { GmailService.Scope.GmailSend, GmailService.Scope.GmailLabels, GmailService.Scope.GmailCompose, GmailService.Scope.MailGoogleCom};
static string ApplicationName = "Gmail API Send Email";
Enable 2FA on your email and generate a password for your application using the link. As far as I know, login and password authorization using unauthorized developer programs is no longer supported by Google.
Can you ping the smpt server from your machine or the machine you deploy the code from? THis could be a DNS issue.

Sending emails consistently returns 5.7.3 Authentication unsuccessful code or some variation of an authentication failure

I can't for the life of me figure this out. Currently using MailKit + Godaddy email accounts (through Office365).
I don't have 2FA enabled, user/pass is correct. No matter what combination of settings I do, email doesn't work.
This is the code I'm using currently (I've also tried System.Net's SmtpClient using a ton of different setups, and nothing works)-
public async Task SendEmailAsync(string email, string subject, string htmlMessage)
{
using var client = new SmtpClient();
await client.ConnectAsync(Host, Port, SecureSocketOptions.StartTls);
await client.AuthenticateAsync(User, Pass);
var message = new MimeMessage();
message.From.Add(new MailboxAddress("", FromAddress));
message.To.Add(new MailboxAddress("", email));
message.Subject = subject;
message.Body = new TextPart(MimeKit.Text.TextFormat.Html) { Text = htmlMessage };
try
{
await client.SendAsync(message);
await client.DisconnectAsync(true);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
throw;
}
}

Failed to send email using outlook office365 c# code

I have written below code to send email using Outlook Office365.
ExchangeService myService = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
myService.Credentials = new WebCredentials(sender_mailId,sender_password);
try
{
string serviceUrl = <<service url>> // This URL
myService.Url = new Uri(serviceUrl);
EmailMessage emailMessage = new EmailMessage(myservice);
emailMessage.Subject = "Subject test ";
emailMessage.Body = new MessageBody("Testing Exchange Web Service API");
emailMessage.ToRecipients.Add(to_email_id);
emailMessage.Send();
}
catch (SmtpException exception)
{
string msg = "Mail cannot be sent (SmtpException):";
msg += exception.Message;
throw new Exception(msg);
}
What web service URL should be used?
The below code is worked to send or save to email draft.
static void CheckEmail()
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = new WebCredentials(senderEmailId, password);
service.AutodiscoverUrl(senderEmailId, RedirectionUrlValidationCallback);
EmailMessage emailMessage = new EmailMessage(service);
emailMessage.Subject = "Test office 365 project draft ";
emailMessage.Body = new MessageBody("Testing Exchange Web Service API");
emailMessage.ToRecipients.Add(emailTo);
//send email
emailMessage.Send();
//save to draft
emailMessage.Save(WellKnownFolderName.Drafts);
}
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}

Email cannot be sent with sendgrid(C#) and no trace of Exceptions

I use the SendAsync method in my code to trigger Emails. The Email Code is printed below.
public async Task SendAsync(IdentityMessage message) {
if (message.Destination != null)
await configSendGridasync(message);
}
private async Task configSendGridasync(IdentityMessage message) {
var myMessage = new SendGridMessage();
myMessage.AddTo(message.Destination);
myMessage.From = new MailAddress(ConfigurationManager.AppSettings["mailAccount"], "XYC Social");
myMessage.Subject = message.Subject;
myMessage.Text = message.Body;
myMessage.Html = message.Body;
var credentials = new NetworkCredential(
ConfigurationManager.AppSettings["mailAccount"],
ConfigurationManager.AppSettings["mailPassword"]
);
// Create a Web transport for sending email.
var transportWeb = new Web(credentials);
// Send the email.
if (transportWeb != null) {
await transportWeb.DeliverAsync(myMessage);
} else {
Trace.TraceError("Failed to create Web transport.");
await Task.FromResult(0);
}
}
In the controller I use below code to trigger the Email.
public async Task < ActionResult > ForgotPassword(XYCSocial.Models.ManageUserViewModel model) {
IdentityMessage msg = new IdentityMessage {
" Message",
Subject = "Reset Password",
Destination = result.Email
};
try {
await _emailService.SendAsync(msg);
} catch (Exception ex) {
ViewBag.Status = "Error : " + ex.Message;
throw;
}
TempData["Success"] = " Some Message";
return RedirectToAction("Login");
}
} else {
TempData["Failed"] = "Please enter valid User name";
return RedirectToAction("Login");
}
} catch (Exception) {
TempData["Failed"] = "Email Send Failed..Please Try After Some Time";
return RedirectToAction("Login");
However When I call the SendAsync method in the controller for triggering emails it just executes without an error but the Email Is never sent.
Finally after a long time it says:
Email Send Failed
From the above TempData["Failed"] tag. I had verified the suppressions folder in the sendgrid account but there is no sign of Spam, or bad email address, or block, etc.
This same code was working until Feb 17th, 2017 but just doesn't work after that.
I too had the same issues using similar code. What I found tonight was an updated sample on the sendgrid GitHub page https://github.com/sendgrid/sendgrid-csharp
This is for the V3 version of Sendgrid Mail.
I can confirm that using this code with an Azure hosted MVC 5 solution works:
var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY");
var client = new SendGridClient(apiKey);
var from = new EmailAddress("test#example.com", "Example User");
var subject = "Hello World from the SendGrid CSharp SDK!";
var to = new EmailAddress("test#example.com", "Example User");
var plainTextContent = "Hello, Email!";
var htmlContent = "<strong>Hello, Email!</strong>";
var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
var response = await client.SendEmailAsync(msg);
You would need to replace your entire Config method and add your environment variable inside the Azure portal manager (which you need to get from the Sendgrid site)

Make a asp.net mail App in C# with Gmail

I have tried many times to make an email app using gmail.
I am truly desperate, I have visited the entire Internet even in other languages but I found nothing.
How can I make a email web app in Asp.net c# using gmail?
This is the last code I applied.
try
{
MailMessage ms = new MailMessage();
ms.From = new MailAddress("myemail#gmail.com");
ms.To.Add("fillocj#hotmail.it");
ms.Body = txtTexto.Text;
ms.IsBodyHtml = true;
SmtpClient sm = new SmtpClient();
sm.Host = "smtp.gmail.com";
NetworkCredential nt = new NetworkCredential();
nt.UserName = "myemail#gmail.com";
nt.Password = "myPassword";
sm.UseDefaultCredentials = true;
sm.Credentials = nt;
sm.Port = 465;
sm.EnableSsl = true;
sm.Send(ms);
LabelError.Text = "Sent";
}
catch
{
LabelError.Text = "Error";
}
I always fail over and over again.
I tried with port: 25, also with 465 and 587. But any of them works fine. I do not know what the problem is.
Please help with this issue.
You also might have to configure your gmail account to allow "less secure apps".
See here: https://support.google.com/accounts/answer/6010255?hl=en
I had the same issues using an ASP.NET program to send e-mail via Gmail and it did not work until I did this.
This works on my computer using my email and login credentials for that email. If this doesn't work on yours, it is possible that it is a networking issue as indicated in the comment above.
MailMessage mM = new MailMessage();
mM.From = new MailAddress("myemail#gmail.com");
mM.To.Add("youremail#gmail.com");
mM.Subject = "your subject line will go here";
mM.Body = "Body of the email";
mM.IsBodyHtml = true;
SmtpClient sC = new SmtpClient("smtp.gmail.com") {Port = 587, Credentials = new NetworkCredential("myemail#gmail.com", "password"), EnableSsl = true};
sC.Send(mM);
Download Google.Apis.Gmail.v1 in nuget.
Create a project in https://console.developers.google.com/.
Inside your project navigate to Apis & auth > Apis (enable gmail api)
Navigate to Apis & auth > Credentials (create new client id)
Then copy your client id and client secret.
Here's the code in sending email using Gmail Api.
public class Gmail
{
public Gmail(ClientSecrets secrets, string appName)
{
applicationName = appName;
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(secrets,
new[] { GmailService.Scope.MailGoogleCom, GmailService.Scope.GmailCompose, GmailService.Scope.GmailReadonly },
"user", CancellationToken.None).Result;
service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = applicationName,
});
}
public void SendEmail(System.Net.Mail.MailMessage mail)
{
var mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mail);
Message msg = new Message()
{
Raw = Base64UrlEncode(mimeMessage.ToString())
};
SendMessage(service, msg);
}
private Message SendMessage(GmailService service, Message msg)
{
try
{
return service.Users.Messages.Send(msg, userid).Execute();
}
catch (Exception ex)
{
throw ex;
}
}
private string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
// Special "url-safe" base64 encode.
return Convert.ToBase64String(inputBytes)
.Replace('+', '-')
.Replace('/', '_')
.Replace("=", "");
}
}
UPDATE:
In your controller:
public ActionResult SendEmail()
{
MailMessage msg = new MailMessage()
{
Subject = "Your Subject",
Body = "<html><body><table border='1'><tr>Hello, World, from Gmail API!<td></td></tr></table></html></body>",
From = new MailAddress("from#email.com")
};
msg.To.Add(new MailAddress("to#email.com"));
msg.ReplyToList.Add(new MailAddress("to#email.com")); // important! if no ReplyTo email will bounce back to the sender.
Gmail gmail = new Gmail(new ClientSecrets() { ClientId = "client_id", ClientSecret = "client_secret" }, "your project name");
gmail.SendEmail(msg);
}

Categories

Resources