C# 如何正确地异步发送电子邮件?邮件永远不会到达
我用C#创建了一个新的MVC5项目 我有一些模型:C# 如何正确地异步发送电子邮件?邮件永远不会到达,c#,asp.net-mvc,asynchronous,C#,Asp.net Mvc,Asynchronous,我用C#创建了一个新的MVC5项目 我有一些模型: public class EmailFormModel { [Required, Display(Name = "Your name")] public string FromName { get; set; } [Required, Display(Name = "Your email"), EmailAddress] public string FromEmail { get; set; } [Req
public class EmailFormModel
{
[Required, Display(Name = "Your name")]
public string FromName { get; set; }
[Required, Display(Name = "Your email"), EmailAddress]
public string FromEmail { get; set; }
[Required]
public string Message { get; set; }
}
我有一个Conctact.cshtml:
@model EMailSenderWebApp.Models.EmailFormModel
@{
ViewBag.Title = "Contact";
}
<h2>@ViewBag.Title.</h2>
@using (Html.BeginForm("SendEmailAsync", "Home", FormMethod.Post, new { role = "form contact-form", @id = "form-div" }))
{
@Html.AntiForgeryToken()
<h4>Send your comments.</h4>
<hr />
<div class="form-group">
@Html.LabelFor(m => m.FromName, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.FromName, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.FromName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.FromEmail, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.FromEmail, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.FromEmail)
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Message, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextAreaFor(m => m.Message, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Message)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Send" />
</div>
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
@model EMailSenderWebApp.Models.EmailFormModel
@{
ViewBag.Title=“联系人”;
}
@ViewBag.Title。
@使用(Html.BeginForm(“sendmailasync”、“Home”、FormMethod.Post、new{role=“form contact form”、@id=“form div”}))
{
@Html.AntiForgeryToken()
发送您的评论。
@LabelFor(m=>m.FromName,新的{@class=“col-md-2控制标签”})
@TextBoxFor(m=>m.FromName,新的{@class=“form control”})
@Html.ValidationMessageFor(m=>m.FromName)
@LabelFor(m=>m.FromEmail,新的{@class=“col-md-2控制标签”})
@TextBoxFor(m=>m.FromEmail,新的{@class=“form control”})
@Html.ValidationMessageFor(m=>m.FromEmail)
@LabelFor(m=>m.Message,新的{@class=“col-md-2控制标签”})
@text区域(m=>m.Message,新的{@class=“form control”})
@Html.ValidationMessageFor(m=>m.Message)
}
@节脚本{
@Scripts.Render(“~/bundles/jqueryval”)
}
因此,如您所见,我的表单调用HttpPost方法“SendEmailAsync”,这在我的主控制器中有描述:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SendEmailAsync(EmailFormModel model)
{
if (ModelState.IsValid)
{
SmtpClient client = new SmtpClient();
MailMessage message = new MailMessage();
var body = "<p>Email From: {0} ({1})</p><p>Message:</p><p>{2}</p>";
message.To.Add(new MailAddress("stefan.cv5@gmail.com")); // replace with valid value
message.From = new MailAddress("stefan.cv5@gmail.com"); // replace with valid value
message.Subject = "Your email subject";
message.Body = string.Format(body, model.FromName, model.FromEmail, model.Message);
message.IsBodyHtml = true;
client.Credentials = new NetworkCredential("", "");
client.Host = "smtp.gmail.com";
client.Port = 587;
client.EnableSsl = false;
client.SendCompleted += (s, e) =>
{
client.Dispose();
message.Dispose();
};
ThreadPool.QueueUserWorkItem(o =>
client.SendAsync(message, Tuple.Create(client, message)));
}
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
公共操作结果SendEmailAsync(EmailFormModel模型)
{
if(ModelState.IsValid)
{
SmtpClient=新的SmtpClient();
MailMessage=新的MailMessage();
var body=“电子邮件发件人:{0}({1})消息:{2}”;
message.To.Add(新邮件地址(“stefan。cv5@gmail.com“”);//替换为有效值
message.From=新邮件地址(“stefan。cv5@gmail.com“”;//替换为有效值
message.Subject=“您的电子邮件主题”;
message.Body=string.Format(Body,model.FromName,model.FromEmail,model.message);
message.IsBodyHtml=true;
client.Credentials=newnetworkcredential(“,”);
client.Host=“smtp.gmail.com”;
client.Port=587;
client.enablesl=false;
client.SendCompleted+=(s,e)=>
{
client.Dispose();
message.Dispose();
};
ThreadPool.QueueUserWorkItem(o=>
SendAsync(消息,元组。创建(客户端,消息));
}
返回视图(模型);
}
我试过举一些例子
等待client.SendMailSync()
但是,正如您可能知道的,异步调用消失了,并且永远不会返回(关于这一点的更多信息)
所以,我是这样实现的,由
这个方法一路执行(最后返回视图),但我的电子邮件从未进入我的收件箱
也许谷歌有防火墙?这里发生的事情是你从未将smtp客户端连接到服务器。通常情况下,这会引发异常,但是您也尝试在线程池工作线程中发送邮件消息,而没有正确的try/catch。任何地方都没有代码可以捕获异常,所以看起来好像什么都没有发生 另请参见下面我的编辑,使用块将
SmtpClient
和MailMessage
放入中,这样您就不必手动调用.Dispose()
。这确保即使在连接或发送消息时发生异常,也会释放资源
正如其他人提到的,不再维护内置的System.Net.Mail库。我建议使用(),因为它维护得非常好,而且所有者的反应非常迅速
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> SendEmailAsync(EmailFormModel model)
{
if (ModelState.IsValid)
{
// Create IDisposable inside `using` block so you aren't on the hook for calling Dispose()
// The same has been done with your MailMessage
using(SmtpClient client = new SmtpClient())
{
client.Credentials = new NetworkCredential("", "");
client.Host = "smtp.gmail.com";
client.Port = 587;
client.EnableSsl = false;
// You were missing this before which
// was causing the exception. But due
// to the thread your email was sent from
// the exception was not thrown from a context
// where you could know about it at all.
await client.ConnectAsync();
using(MailMessage message = new MailMessage())
{
var body = "<p>Email From: {0} ({1})</p><p>Message:</p><p>{2}</p>";
message.To.Add(new MailAddress("stefan.cv5@gmail.com")); // replace with valid value
message.From = new MailAddress("stefan.cv5@gmail.com"); // replace with valid value
message.Subject = "Your email subject";
message.Body = string.Format(body, model.FromName, model.FromEmail, model.Message);
message.IsBodyHtml = true;
await client.SendAsync(message);
}
}
}
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
公共异步任务SendEmailAsync(EmailFormModel模型)
{
if(ModelState.IsValid)
{
//在`using`block中创建IDisposable,这样您就不需要调用Dispose()了
//你的邮件信息也是如此
使用(SmtpClient=new SmtpClient())
{
client.Credentials=newnetworkcredential(“,”);
client.Host=“smtp.gmail.com”;
client.Port=587;
client.enablesl=false;
//你之前错过了这个
//是导致异常的原因。但由于
//发送电子邮件的线程
//异常不是从上下文中引发的
//在那里你可以知道一切。
等待client.ConnectAsync();
使用(MailMessage=newmailmessage())
{
var body=“电子邮件发件人:{0}({1})消息:{2}”;
message.To.Add(新邮件地址(“stefan。cv5@gmail.com“”);//替换为有效值
message.From=新邮件地址(“stefan。cv5@gmail.com“”;//替换为有效值
message.Subject=“您的电子邮件主题”;
message.Body=string.Format(Body,model.FromName,model.FromEmail,model.message);
message.IsBodyHtml=true;
等待client.sendaync(消息);
}
}
}
返回视图(模型);
}
这里有几件事。您可能希望使用的不是SmtpClient
,因为它已经过时了。如果必须使用SmtpClient
,我建议使用async/await和实际返回任务的方法
: