using Revalee.client to send email at background - asp.net-mvc-4

Where should I call the revalee method to send mail email at background? What I am trying to achieve is to send email to the client if the expiration date is coming. I have follow the link: http://www.codeproject.com/Articles/738753/Scheduling-tasks-with-Revalee-and-MVC
My actionmethod is as follows:
public ActionResult SendExpirationMessage(int VehicleID)
{
// Validate the incoming request to ensure that this web app requested this callback
if (!RevaleeRegistrar.ValidateCallback(this.Request))
{
// Return a '401 Unauthorized' response to the Revalee service if the callback doesn't validate
return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
}
ApplicationDbContext db = new ApplicationDbContext();
var user = db.UserVehicleViewModels.Find(VehicleID);
var span = user.TaxDate.AddYears(1).Subtract(DateTime.Now);
int days = span.Days;
if (days >= 7)
{
System.Net.Mail.MailMessage m = new System.Net.Mail.MailMessage(
new System.Net.Mail.MailAddress("abc#abc.com", "Web Registration"),
new System.Net.Mail.MailAddress(user.Email));
m.Subject = "Tax Notification";
m.Body = string.Format("Dear {0} <BR/>This is an email to notify you about the due tax date of your vehicle, please pay tax on time. Thank you\" title=\"User Email Confirm\"></a>",
user.UserName);
m.IsBodyHtml = true;
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.gmail.com");
smtp.Credentials = new System.Net.NetworkCredential("abc#abc.com", "password");
smtp.EnableSsl = true;
smtp.Send(m);
}
the helper method is:
private void ScheduleExpirationMessage(int VehicleID)
{
// The server address where the Revalee service is installed
string revaleeServiceHost = "192.168.1.4";
// The callback will occur 27 days from now
DateTimeOffset callbackTime = DateTimeOffset.Now.AddMinutes(1.0);
// The url that will be called back, including userId
Uri callbackUrl = new Uri(
string.Format("http://localhost/UserVehicle/SendExpirationMessage/{0}", VehicleID));
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(revaleeServiceHost, callbackTime, callbackUrl);
}

Related

Sending mail multiple times by Microsoft Graph

Blazor server application
I have a web appliction that is using AzureAd and OpenIdConnect to login to this application.
I am sending mail by using Microsoft graph and I am using the example in Microsoft doc with some changes like this:
#inject Microsoft.Graph.GraphServiceClient GraphServiceClient
#inject MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler
var message = new Message
{
Subject = "Meet for lunch?",
Body = new ItemBody
{
ContentType = BodyType.Text,
Content = "The new cafeteria is open."
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "fannyd#contoso.onmicrosoft.com"
}
}
},
CcRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "danas#contoso.onmicrosoft.com"
}
}
}
};
var saveToSentItems = false;
try
{
await GraphServiceClient.Me
.SendMail(message,saveToSentItems)
.Request()
.PostAsync();
}
catch(Exception ex)
{
ConsentHandler.HandleException(ex);
}
Scenario of the error
This works perfect but just for one time , if I try to send the same email again it doesn't work and I got no error but just redirect me to empty page.
If I logout and login again, then it works fine.
The error that I got in the second time:
Message = "IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent. "
MsalUiRequiredException = {"No account or login hint was passed to the AcquireTokenSilent call. "}
My Question
How can fix the code up to send multi emails?. I think that I have a problem with token but I don't know where should I start?.
Thanks
Add the other catch block to retrieve the specific issue if we have any related to permissions or other ServiceExceptions.
try
{
SendMail(); // Sending mail code here.
}
catch (Microsoft.Graph.ServiceException e)
{
// get the error here if we have any.
}
After some search, I think that I have to move the the permission Delegated permissions to Application Permissions like this:
Why should I use application permission?
In my case the user logged in for the first time and clicked on the button then the email will be send, but in the second time the application has to communicate with API graph without interaction from the user, that means without user and this exactly what I need(application permission).
I adjust the code like the following:
Client credentials provider:
The client credential flow enables service applications to run without user interaction. Access is based on the identity of the application. this is from Microsoft doc
private GraphServiceClient CreateGraphServiceClient()
{
// The client credentials flow requires that you request the
// /.default scope, and preconfigure your permissions on the
// app registration in Azure. An administrator must grant consent
// to those permissions beforehand.
var scopes = new[] { "https://graph.microsoft.com/.default" };
// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";
// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";
// using Azure.Identity;
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret, options);
return new GraphServiceClient(clientSecretCredential, scopes);
}
Send mail with UserId, you can see the code in Microsoft doc:
puplic SendMyEmail()
{
GraphServiceClient graphClient = CreateGraphServiceClient;
var message = new Message
{
Subject = "Meet for lunch?",
Body = new ItemBody
{
ContentType = BodyType.Text,
Content = "The new cafeteria is open."
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "fannyd#contoso.onmicrosoft.com"
}
}
},
CcRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "danas#contoso.onmicrosoft.com"
}
}
}
};
var saveToSentItems = false;
//See GetUserId down
string userId = await GetUserId();
await graphClient.Users[UserId]
.SendMail(message,saveToSentItems)
.Request()
.PostAsync();
}
}
UserId:
To get user Id you need AuthenticationStateProvider, this has to inject in the service of your application and then add to the constructor of your class, then you can use it.
puplic class MyClass
{
private readonly MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler;
private readonly AuthenticationStateProvider authenticationState;
puplic MyClass(
MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler,
AuthenticationStateProvider authenticationState)
{
this.authenticationState = authenticationState;
this.ConsentHandler = ConsentHandler;
}
public async Task<string> GetUserId()
{
var authSate = await authenticationState.GetAuthenticationStateAsync();
return authSate.User.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");
}
//Here your
private GraphServiceClient CreateGraphServiceClient() { ...}
puplic SendMyEmail() {....}
}

Getting SendGrid Server Results in ASP.Net Core

Here's my code to send email via SendGrid.
public Task<Result> Execute(string apiKey, string subject, string message, string email)
{
var client = new SendGridClient(apiKey);
string senderEmail = this.Configuration["Email:Address"];
string senderName = this.Configuration["Email:Name"];
var msg = new SendGridMessage()
{
From = new EmailAddress(senderEmail, senderName),
Subject = subject,
PlainTextContent = message,
HtmlContent = message
};
msg.AddTo(new EmailAddress(email));
var response = client.SendEmailAsync(msg);
return response;
}
It is able to send email confirmation and password reset emails, when invoked by ASP.Net Core Identity code.
However, when I try to send email using my own controller action (for a Contact Us feature), nothing happens.
This is the controller action.
public async Task<JsonResult> SendContactEmail(int id, string message)
{
Page page = await this.Get(id);
var result = _emailSender.SendEmailAsync(page.Email, page.Subject, message);
return new JsonResult(result);
}
Is there a way to troubleshoot this? I don't get any exceptions and the response object doesn't seem to have any useful property like a message from the SendGrid server.
UPDATE:
SendGrid's API does return an informative result. I have updated my code to return this.
https://github.com/sendgrid/sendgrid-csharp/blob/master/src/SendGrid/Response.cs

How to send 1 million of push notification (APNS) within few second using PushSharp as webservice?

to do that i made a web service to send push (by referencing PushSharp library). I request web service through my web application. i retrieve list of device token from database(using web application) send to web service using for loop to send push. and get result/exception for each one. This process is very slow and take long long time to send notification. If anybody suggest me to what should i do i will be grateful to you.
public ActionResult SendNowToken(int certificateInfoId, string message, string certificate, int badgeNo, int pushtype, string password, string countryJsonString)
{
if (IsPushParameterValid(certificateInfoId, message, certificate, badgeNo, pushtype, password, countryJsonString))
{
var countryObject = new JavaScriptSerializer().Deserialize<Country>(countryJsonString);
var errorList = new List<ErrorList>();
byte[] certificatePath = System.IO.File.ReadAllBytes(HttpContext.Server.MapPath("~/Content/certificate/" + certificate));
foreach (var aDeviceToken in countryObject.DeviceTokens)
{
try
{
var serviceClient = new PushServiceSoapClient();
string serviceResult = serviceClient.SendPushNotification(message, badgeNo, pushtype, aDeviceToken.Token, certificatePath, password);
if (serviceResult != "Sent Notification")
{
var delimiters = new[] { ' ' };
string[] errorResult = serviceResult.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
string errorMessage = ConvertErrorCodeToErrorMessage(errorResult[0]);
var error = new ErrorList
{
CountryName = countryObject.CountryName,
ErrorTime = DateTime.Now,
ErrorMessage = errorMessage,
Token = aDeviceToken.Token
};
errorList.Add(error);
}
}
catch (Exception ex)
{
var error = new ErrorList
{
CountryName = countryObject.CountryName,
ErrorTime = DateTime.Now,
ErrorMessage = ex.Message,
Token = aDeviceToken.Token
};
errorList.Add(error);
}
}
if (errorList.Count != 0)
{
ViewBag.Message = "Push Notification does not send to country... ";
return PartialView("_SendAllError", errorList.ToList());
}
errorList.Clear();
}
return View();
}

Google Auth token gets expired within windows service

I implemented a windows service which downloads DoubleClick report data for several DFA accounts. The windows service is installed twice on the same server but the services import the downloaded reports into different SQL server (dev and live). Both services run daily at a specific time but not parallel. The windows service uses the the DFA Reporting API 1.3. and the Google APIs Client Library 1.7 (beta).
The first day after restarting the windows services all data will be loaded without any errors but the next days I get an "Authentication token has expired" error. This is the code
public ImportData(string loginUserName, string sourceName)
{
Logger.Info(string.Format("Import for Source {0} started.", sourceName));
this.dbContext = new DatabaseContext();
// Create new log item
this.importExportLog = this.dbContext.ImportExportLogs.Create();
this.importExportLog.SetData("DoubleClick " + sourceName, DateTime.Now);
this.dbContext.ImportExportLogs.Add(this.importExportLog);
this.dbContext.SaveChanges();
this.StartDate = DateTime.Today.AddDays(0 - DoubleClickImporterSettings.Default.ImportDataForDays);
this.EndDate = DateTime.Today;
this.userName = loginUserName;
this.sourceName = sourceName;
// Reset report data
campaignObjs = new List<Campaign>();
clientObjs = new List<Advertiser>();
siteObjs = new List<DfaSite>();
adObjs = new List<AdBase>();
this.user = new DfaUser();
ClientSecrets secret = new ClientSecrets();
secret.ClientId = this.user.Config.OAuth2ClientId;
secret.ClientSecret = this.user.Config.OAuth2ClientSecret;
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(secret, new string[] { DfaReportingScope }, this.user.Config.OAuth2PrnEmail, CancellationToken.None, new FileDataStore(DoubleClickImporterSettings.Default.OAuthStorePath)).Result;
// Keep auth toke for 6 hours
credential.Token.ExpiresInSeconds = 21600;
// Create the dfa reporting service.
DfareportingService dfars = new DfareportingService(new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "Double Click Importer",
});
// log in for dfa api
if ((user.Config as DfaAppConfig).AuthorizationMethod == DfaAuthorizationMethod.OAuth2)
{
// Set the OAuth2 scope.
user.Config.OAuth2Scope = DfaReportingScope;
// Since we are using a console application, set the callback url to null.
user.Config.OAuth2RedirectUri = null;
}
else
{
throw new Exception("Authorization mode is not OAuth2.");
}
// Set the username. This is required for the LoginService to work
// correctly when authenticating using OAuth2.
(user.Config as DfaAppConfig).DfaUserName = userName;
this.user.OAuthProvider.RefreshAccessToken();
startDateTime = DateTime.Now;
ImportReportData(dfars);
this.user.OAuthProvider.RefreshAccessToken();
while (!ImportClientData(user))
{
System.Threading.Thread.Sleep(waitUntilNextTry);
this.user.OAuthProvider.RefreshAccessToken();
}
this.user.OAuthProvider.RefreshAccessToken();
while (!ImportAdvertiserData(user))
{
System.Threading.Thread.Sleep(waitUntilNextTry);
this.user.OAuthProvider.RefreshAccessToken();
}
// Import other data...
}
Why the error doesn't occur on first day but occur on the other days?

Asp.Net Mvc Receive Mail Issue

I have one problem about receive email. Now, I write Contact page in my project. If some user wanna send email, he/she write email adress and message and click Send buttom. My code send from berdankoca#gmail.com to berdankoca#gmail.com. I couldn't understand why it didn't sent from email area to berdankoca#gmail.com
My Code
[HttpPost]
public ActionResult About(string name, string email, string message)
{
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress(email);
mailMessage.To.Add(new MailAddress("berdankoca#gmail.com"));
mailMessage.Subject = "Deneme";
mailMessage.SubjectEncoding = System.Text.Encoding.Default;
mailMessage.Body = message;
mailMessage.BodyEncoding = System.Text.Encoding.Default;
SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
client.Credentials = new System.Net.NetworkCredential("berdankoca#gmail.com", "xxxx");
client.EnableSsl = true;
client.Send(mailMessage);
return View();
}
I hope I can explain. Thanks for all replies.