I would like to implement the functionality that on my page there is an area where users can enter their email with a question and automatically that email reaches a certain email account (mine). So far it always comes from the same person and not from the person who puts your email in that field
[HttpPost]
public async Task<IActionResult> EnviarMail(MandarMailViewModel model)
{
if (ModelState.IsValid)
{
try
{
Email email = new Email()
{
From = model.From,
Subject = model.Subject,
Body = model.Body
};
MailMessage mm = new MailMessage();
mm.To.Add(my email);
mm.Subject = email.Subject;
mm.Body = email.Body;
mm.IsBodyHtml = false;
mm.From = new MailAddress(email.From);
SmtpClient smtp = new SmtpClient("smtp.gmail.com");
smtp.Port = 587;
smtp.UseDefaultCredentials = false;
smtp.EnableSsl = true;
smtp.Credentials = new System.Net.NetworkCredential(my email, my password);
await smtp.SendMailAsync(mm);
return RedirectToAction("EnvioExitoso");
}catch(Exception error)
{
ViewBag["Error"] = error.Message;
}
}
return View(model);
}
This is the line that specifies the account that is sending the email:
smtp.Credentials = new System.Net.NetworkCredential(my email, my password);
If you want the sender email address to be the visitors address, you have to ask them to put their passwords as well to authenticate their accounts, but regardless that most people will not give their passwords, this is not how you should do it!
Below is the recommended way:
Create an email account just for sending emails from your page e.g. noreply#domain.com
Create another email just to recieve the emails coming from the page e.g. support#domian.com
Keep the users email address in the CC so they receive a copy of the email and feel confident that the message was received on your side as well, and on the other side you can see that address in the CC as well.
Related
I am using the scaffolded Identity with .NET 5. I tried the "Forgot Password" link on the login page. This works in that the email is sent with the link to reset the password.
However, clicking on the link in the email leads to an error relating to the base 64 code being malformed. Malformed input: 321 is an invalid input.
The base 64 code is there but there's an issue with it. The base 64 code is generated with this:
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ResetPassword",
pageHandler: null,
values: new { area = "Identity", code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(
Input.Email,
"Reset Password",
$"Please reset your password by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
It breaks on the ResetPassword.cshtml.cs GET.
if (code == null)
{
return BadRequest("A code must be supplied for password reset.");
}
else
{
Input = new InputModel
{
Code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code))
};
return Page();
}
Can anyone point me in the right direction to fixing this? I am not sure it's relevant but I am using SendGrid's SMTP server.
UPDATE. I spotted that there is a trailing inverted comma at the end of the code. Removing this fixes the issue.
code = code.Replace("'", "");
Now I just need to find out how it's getting there.
Tried and ruled out the following.
Turned off SendGrid link tracking.
Turned off Outlook safelinks.
The above made no difference.
Then it dawned on me that the email link was not rendering as HTML. i.e. it was showing the link text and not just the "click here".
Then I read that smtp client is now obsolete and MS recommends using MailKit instead.
So I decided to replace my email sender code with the following using Mailkit and the issue went away.
public Task SendEmailAsync(string email, string subject, string htmlMessage)
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("(Admin)", "test#test.com"));
message.To.Add(new MailboxAddress("Recipient Name", email));
message.Subject = subject;
message.Body = new TextPart("html")
{
Text = htmlMessage
};
string Username = _config["MailSettings:Username"];
string Password = _config["MailSettings:Password"];
var port = Convert.ToInt32(_config["MailSettings:Port"]);
using var client = new SmtpClient();
client.Connect(_config["MailSettings:Host"], port, false);
client.Authenticate(Username, Password);
try
{
client.Send(message);
client.Disconnect(true);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
return Task.CompletedTask;
}
I think this is the part that saved the day:
message.Body = new TextPart("html")
{
Text = htmlMessage
};
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
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);
}
I am storing the email of the user in session
var v = //login query
Session["LoggedUserEmail"] = v.email.ToString();
Then after login I want to send an email to the current logged in user and for that purpose I am passing Session["LoggedUserEmail"] in Msg.To.Add but its not working.
This is what I am doing
public void Execute(IJobExecutionContext context)
{
System.Net.Mail.MailMessage Msg = new System.Net.Mail.MailMessage();
Msg.From = new MailAddress("abc#gmail.com");
Msg.To.Add(Session["LoggedUserEmail"].ToString());
Msg.Subject = "Email";
Msg.Body = "Hi";
Msg.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.Credentials = new System.Net.NetworkCredential("abc#gmail.com", "xxxxxxx");
smtp.EnableSsl = true;
smtp.Send(Msg);
Response.Write("Email Sent");
}
Am I doing something wrong? if yes, then is there any other way to get the job done?
I am using quartz.net and implemented IJob interface in my mvc controller.
The job executes on a different thread than the one that schedules it. You must pass in any data you need by using the JobDataMap when creating/scheduling the job.
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.