How to send email from controller in MVC 4 .net? - asp.net-mvc

I have following code which works fine if I host the website in IIS of my local system. But if I host the website on my Windows Server, it doesn't send mail.
Code of Controller:
[HttpPost]
public ActionResult Index()
{
string tomail = "test#godaddyserver.com";
string SMTPServer = "smtpout.secureserver.net";
string SMTPUserName = "test#godaddyserver.com";
string SMTPPassword = "test123456";
string strMailTitle = "Inquiry Mail";
MailMessage mail = new MailMessage();
SmtpClient SmtpServer = new SmtpClient(SMTPServer);
SmtpServer.Credentials = new NetworkCredential(SMTPUserName, SMTPPassword);
mail.From = new MailAddress(tomail, strMailTitle);
SmtpServer.Port = 25;
mail.To.Add(tomail);
mail.Subject = "Inquiry Mail";
mail.IsBodyHtml = true;
string mailTemplatePath = Server.MapPath("~/template/AdminContactUs.html");
StringBuilder MyStringBuilder = new StringBuilder();
if (System.IO.File.Exists(mailTemplatePath))
MyStringBuilder.Append(System.IO.File.ReadAllText(mailTemplatePath));
mail.Body = MyStringBuilder.ToString();
try
{
SmtpServer.ServicePoint.MaxIdleTime = 1;
SmtpServer.Send(mail);
}
catch (Exception e)
{
}
}
One thing I forgot to add is that it is working fine with Exchange Server email(test#mydomain.com) and SMTP(smtp1.mydomain.com). Current email and SMTP is of Godaddy. However, it is not working with Godaddy, Hostgator or Gmail.
Can anybody please suggest me if I am missing anything?

Related

Email view not found for 'model' in Postal.MVC

I am using Postal.MVC5 in my ASP MVC5 project. Initially i had my smtp configuration in web.config so this piece of code was working just fine and was able to send email successfully.
public async Task<ActionResult>SendEmail(EmployeeViewModel emailModel)
{
string _errorMessage;
emailModel.To = "john#outlook.com";
emailModel.Subject = "Test Subject";
emailModel.Message = "Test Message";
await emailModel.SendAsync();
return Json(new {ErrorMessage = _errorMessage});
}
Now, i need to setup Smtpclient during runtime and followed steps shown in this stackoverflow post: How to Set SMTP Client in POSTAL MVC not in WEB.Config
public async Task<ActionResult>SendEmail(EmployeeEmailViewModel emailModel)
{
string _errorMessage;
emailModel.To = "john#outlook.com";
emailModel.Subject = "Test Subject";
emailModel.Message = "Test Message";
//new code
SmtpClient client = new SmtpClient("smtp.test.com");
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential("secretId", "notSecretPassword");
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Port = 111;
client.EnableSsl = true;
Postal.EmailService emailService = new EmailService(new ViewEngineCollection(), () => client);
await emailService.SendAsync(emailModel);
return Json(new {ErrorMessage = _errorMessage});
}
Now this code throws an error something like this:
System.Exception: Email view not found for EmployeeEmailViewModel. Locations searched:
at Postal.EmailViewRenderer.CreateView(String viewName, ControllerContext controllerContext)
at Postal.EmailViewRenderer.Render(Email email, String viewName)
I do have 'EmployeeEmailViewModel' view in ~/Views/Emails/EmployeeEmailViewModel.cshtml .
Any idea why i am getting this error message or how i can resolve it?
Thanks
Sanjeev

.NET MVC Contact Form Fails to Send Email on Server

I am using .NET MVC to send a contact form to my work email. The code runs with no errors, but the email never arrives. It works on my local server when using a gmail account, but fails on my server when trying to use my work email. To temporarily fix this issue, I have successfully added .aspx version of the contact form and it works fine. Any ideas why MVC in particular doesn't work on the server? Thanks in advance for your help.
using System;
using System.Web.Mvc;
using Eclipse.Models;
using System.Net.Mail;
namespace Eclipse.Controllers
{
public class HomeController : Controller
{
private void SendEmail(string subjectText, string bodyText)
{
MailMessage message = new MailMessage();
message.To.Add("info#emaildomain.com");
message.From = new MailAddress("noreply#emaildomain.com",
"My Company Inc.");
message.Subject = subjectText;
message.Body = bodyText;
message.IsBodyHtml = false;
SmtpClient client = new SmtpClient("mail.emaildomain.com");
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Port = 25;
client.EnableSsl = false;
client.Credentials = new System.Net.NetworkCredential("noreply#emaildomain.com",
"password");
client.Send(message);
client.Dispose();
}
[Route("~/Contact")]
public ActionResult Contact()
{
if (TempData["FormMessage"] != null)
{
ViewBag.Message = TempData["FormMessage"].ToString();
TempData.Remove("FormMessage");
}
return View();
}
[Route("~/ResultQuestion")]
[HttpPost]
public ActionResult ResultQuestion(ResultContact form)
{
if (ModelState.IsValid)
{
try
{
System.Text.StringBuilder builder = new System.Text.StringBuilder();
builder.Append("Contact Information\n");
builder.AppendFormat("Contact Name: {0}\n", form.Name);
builder.AppendFormat("Contact Email: {0}\n", form.Email);
builder.AppendFormat("Contact Phone: {0}\n", form.Phone);
builder.AppendFormat("Gender: {0}\n", form.Gender);
builder.AppendFormat("Age: {0}\n", form.Age);
builder.AppendFormat("Event: {0}\n", form.Event);
builder.AppendFormat("Bib: {0}\n", form.Bib);
builder.Append("\nQuestions\n");
builder.Append(form.Question);
SendEmail("Result Question from web site", builder.ToString());
ModelState.Clear();
}
catch (Exception error)
{
ModelState.Clear();
TempData["FormMessage"] = string.Format("We're sorry but an error occurred while submitting your request! {0}",
error.Message);
}
}
TempData["FormMessage"] = "Thank you for contacting us. We will be in contact with you soon.";
return RedirectToAction("Contact");
}
[Route("~/EventInquiry")]
[HttpPost]
public ActionResult EventInquiry(EventContact form)
{
if (ModelState.IsValid)
{
try
{
System.Text.StringBuilder builder = new System.Text.StringBuilder();
builder.Append("Contact Information\n");
builder.AppendFormat("Contact Name: {0}\n", form.Name);
builder.AppendFormat("Contact Email: {0}\n", form.Email);
builder.AppendFormat("Contact Phone: {0}\n", form.Phone);
builder.Append("\nEvent Information\n");
builder.AppendFormat("Event Name: {0}\n", form.Event);
builder.AppendFormat("Event Date: {0}\n", form.Date);
builder.AppendFormat("Location: {0}, {1}\n", form.City, form.State);
builder.AppendFormat("Sport: {0}\n", form.Sport);
builder.AppendFormat("Expected Participants: {0}\n", form.Participants);
builder.Append("\nComments\n");
builder.Append(form.Comments);
SendEmail("Event Inquiry from web site", builder.ToString());
ModelState.Clear();
}
catch (Exception error)
{
ModelState.Clear();
TempData["FormMessage"] = string.Format("We're sorry but an error occurred while submitting your request! {0}",
error.Message);
}
}
TempData["FormMessage"] = "Thank you for contacting us. We will be in contact with you soon.";
return RedirectToAction("Contact");
}
}
}
Likely your email server is blocking the access. To make it work with gmail you had to change a setting in gmail to allow applications to send on behalf of the account. I think you'll need to do something similar with your email server but without more information it's hard to say.

How to authorize in Azure Active Directory without using dialog?

My application shows dashboard of my power bi account for all users, I am authorizing the Azure Active Directory through a dialog to get an access token. Can I hard code my credentials and get access token without using the authorization dialog.
Code. It works but it is using the authorization dialog.
var #params = new NameValueCollection
{
{"response_type", "code"},
{"client_id", Properties.Settings.Default.ClientID},
{"resource", "https://analysis.windows.net/powerbi/api"},
{"redirect_uri", "http://localhost:13526/Redirect"}
};
var queryString = HttpUtility.ParseQueryString(string.Empty);
queryString.Add(#params);
string authorityUri = "https://login.windows.net/common/oauth2/authorize/";
var authUri = String.Format("{0}?{1}", authorityUri, queryString);
Response.Redirect(authUri);
Redirect.aspx
string redirectUri = "http://localhost:13526/Redirect";
string authorityUri = "https://login.windows.net/common/oauth2/authorize/";
string code = Request.Params.GetValues(0)[0];
TokenCache TC = new TokenCache();
AuthenticationContext AC = new AuthenticationContext(authorityUri, TC);
ClientCredential cc = new ClientCredential
(Properties.Settings.Default.ClientID,
Properties.Settings.Default.ClientSecret);
AuthenticationResult AR = AC.AcquireTokenByAuthorizationCode(code, new Uri(redirectUri), cc);
Session[_Default.authResultString] = AR;
Response.Redirect("/Default.aspx");
Default.aspx
string responseContent = string.Empty;
System.Net.WebRequest request = System.Net.WebRequest.Create(String.Format("{0}dashboards", baseUri)) as System.Net.HttpWebRequest;
request.Method = "GET";
request.ContentLength = 0;
request.Headers.Add("Authorization", String.Format("Bearer {0}", authResult.AccessToken));
using (var response = request.GetResponse() as System.Net.HttpWebResponse)
{
using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
{
responseContent = reader.ReadToEnd();
PBIDashboards PBIDashboards = JsonConvert.DeserializeObject<PBIDashboards>(responseContent);
}
}
I did this once without using ADAL. For Power BI as well, since they don't offer application permissions, only delegated.
Note: This method won't work if the user has MFA enabled, their password has expired etc.
In general you'll want to use interactive flows.
You can even have a bootstrapping process where the user logs in interactively and you store the refresh token received.
That refresh token can then be used in the background as long as it works.
What you need to is call the AAD token endpoint with grant_type=password. You will specify the username and password, as well as the client id, client secret and resource URI in form parameters.
Here is the function I wrote:
private async Task<string> GetAccessToken()
{
string tokenEndpointUri = Authority + "oauth2/token";
var content = new FormUrlEncodedContent(new []
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", Username),
new KeyValuePair<string, string>("password", Password),
new KeyValuePair<string, string>("client_id", ClientId),
new KeyValuePair<string, string>("client_secret", ClientSecret),
new KeyValuePair<string, string>("resource", PowerBiResourceUri)
}
);
using (var client = new HttpClient())
{
HttpResponseMessage res = await client.PostAsync(tokenEndpointUri, content);
string json = await res.Content.ReadAsStringAsync();
AzureAdTokenResponse tokenRes = JsonConvert.DeserializeObject<AzureAdTokenResponse>(json);
return tokenRes.AccessToken;
}
}
Authority here is https://login.microsoftonline.com/tenant-id/. Here is the response class I'm using:
class AzureAdTokenResponse
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
}
I hope using UserCreadential you have give username and password of azure subscription and you can get AccessToken and call your api. i hope it should helps you.
string ResourceUrl="https://analysis.windows.net/powerbi/api";
string ClientId=Properties.Settings.Default.ClientID;//as per your code
AuthenticationContext authenticationContext = new AuthenticationContext(Constants.AuthString, false);
UserCredential csr = new UserCredential("your-username", "password");
AuthenticationResult authenticationResult = authenticationContext.AcquireToken(ResourceUrl,ClientId, usr);
string token = authenticationResult.AccessToken;

GeneratePasswordToken throws odd error in MVC 5 (asp.net Identity) - Lost Password

I am creating a LostPassword function using the code below. When users enter their email and they get a password with link containing the token to reset. In my controller I have the GenerateTokenPassword method (under WebSecurity), but it is throwing this error:
Error: Cannot convert type 'string' to 'int'
Line: var token = WebSecurity.GeneratePasswordResetToken((foundUserName).ToString(), 1440);
When I debug, I get my username in the foundUserName field and it is a string. The 1440 is the timeout on token expiration, and I am supplying an int to begin with. What int is it looking?
Any ideas what this might be?
Thanks,
Sanjeev
// POST: Account/LostPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult LostPassword(LostPasswordModel model)
{
ApplicationUser user;
using (var db = new MyDbContext())
{
var foundUserName = (db.People.Where(p => p.Email == model.Email).FirstOrDefault().UserName);
user = UserManager.FindByName(foundUserName.ToString());
// user = Membership.GetUser(foundUserName);
//Generate password token that will be used in the email link to authenticate user
WebSecurity.InitializeDatabaseConnection("", "System.Data.SqlClient", "AspNetUsers", "Id", "UserName", false);
var token = WebSecurity.GeneratePasswordResetToken((foundUserName).ToString(), 1440);
// Generate the html link sent via email
var code = UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
string resetLink = "<a href='"
+ Url.Action("ResetPassword", "Account", new { rt = token }, "http")
+ "'>Reset Password Link</a>";
//Email stuff
string emailsubject = "Reset your account password.";
string emailbody = "Please click this link to reset your account password: " + resetLink;
string emailfrom = "mymail#mymail.edu";
string emailto = model.Email;
MailMessage message = new MailMessage();
message.To.Add(emailto);
message.From = new MailAddress(emailfrom);
message.Subject = emailsubject;
message.Body = emailbody;
message.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.UseDefaultCredentials = false;
smtp.Credentials = new System.Net.NetworkCredential("mymail", "mypass");
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.EnableSsl = true;
smtp.Send(message);
return View();
}
}
It would appear that the compiler is interpreting the 1440 value as a string, you could try declaring an explicit int variable for it and passing that instead.
Alternatively, given tokenExpirationInMinutesFromNow is an optional parameter which defaults already to 1440 then you can omit it entirely
var token = WebSecurity.GeneratePasswordResetToken((foundUserName).ToString());

MVC 4 Password Recovery

First I am quite new to MVC and I am trying to implement a password recovery functionality for MVC 4. I am implementing this using this technique posted here: Where to find C# sample code to implement password recovery in ASP .NET MVC2
I understood the way it works however there is missing a helper class that I try to implement right now. I am talking about the class: NotificationsHelper.SendPasswordRetrieval(model.Email, this.ControllerContext);
The RetrievePassword acction controller on the controller has a parameter PasswordRetrievalModel model. I guess that this is a class model that connects to db and implements some properties among theme is a string property called Email. Is this correct?
Than, the NotificationsHelper.SendPasswordRetrieval(model.Email, this.ControllerContext); static class implements this static method SendPasswordRetrievla with 2 paramateres: model.Email that is the string property frrom the PasswordRetrievalModel model class, so this will be the user email to which we will send the email. Than the second parameter is this.ControllerContext. What is the point of this parameter what values will contain that are sent to the SendPasswordRetrieval method?
Than I implemented the class like this:
public static class NotificationsHelper
{
public static bool SendPasswordRetrieval(string emailAddress, ControllerContext ctx)
{
try
{
StringBuilder emailMessage = new StringBuilder();
emailMessage.Append("<br />");
emailMessage.Append("Hello,");
emailMessage.Append("You have requested a password recovery.");
emailMessage.Append("<br />");
emailMessage.Append("Please click the link below to change your password: <br />");
emailMessage.Append("<br />");
emailMessage.Append(string.Format("http://www.example.com/Account/Validate?email={0}&token={1}", emailAddress, "**345982374532453435345**"));
emailMessage.Append("<br />");
MailMessage email = new MailMessage();
email.From = new MailAddress("noreplay#example.com");
email.To.Add(new MailAddress(emailAddress));
email.Subject = "domain.com Password Recovery";
email.Body = emailMessage.ToString();
email.IsBodyHtml = true;
SmtpClient smtpServer = new SmtpClient();
smtpServer.Host = "smtp.gmail.com";
smtpServer.Port = 587;
smtpServer.Credentials = new NetworkCredential("username", "password");
smtpServer.EnableSsl = true;
smtpServer.Send(email);
return true;
}
catch (Exception e)
{
Trace.WriteLine(String.Format("Failure to send email to {0}.", emailAddress));
return false;
}
}
}
In the code above I listed the line where the url is formatted, how do I bring there the token using the code #agarcian provided? Is the token coming from the second parameter ControllerContext? If yes how do i get it from there?
Add new column for usertable name it pwdresetTocket, when user request to reset password insert Guid.NewGuid() in pwdresetTocket field for that user, append the same in callback URL
if you don't want to add column to existing table, you can create a new table and map it to user Table.
Then your method looks like this.
public static bool SendPasswordRetrieval(string emailAddress, ControllerContext ctx)
{
try
{
StringBuilder emailMessage = new StringBuilder();
string token = Guid.NewGuid();
// call to a method that will update the table with token
updateUsertablewithResetTocket(tocken);
emailMessage.Append("<br />");
emailMessage.Append("Hello,");
emailMessage.Append("You have requested a password recovery.");
emailMessage.Append("<br />");
emailMessage.Append("Please click the link below to change your password: <br />");
emailMessage.Append("<br />");
emailMessage.Append(string.Format("http://www.example.com/Account/Validate?email={0}&token={1}", emailAddress, token));
emailMessage.Append("<br />");
MailMessage email = new MailMessage();
email.From = new MailAddress("noreplay#example.com");
email.To.Add(new MailAddress(emailAddress));
email.Subject = "domain.com Password Recovery";
email.Body = emailMessage.ToString();
email.IsBodyHtml = true;
SmtpClient smtpServer = new SmtpClient();
smtpServer.Host = "smtp.gmail.com";
smtpServer.Port = 587;
smtpServer.Credentials = new NetworkCredential("username", "password");
smtpServer.EnableSsl = true;
smtpServer.Send(email);
return true;
}
catch (Exception e)
{
Trace.WriteLine(String.Format("Failure to send email to {0}.", emailAddress));
return false;
}
}
once user resets the password, empty the reset token field

Resources