我用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; }
[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")
}
因此,如您所见,我的表单调用HttpPost方法“ SendEmailAsync”,这在我的Home控制器中进行了描述:
[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);
}
我尝试使用
作为示例等待client.SendMailSync() 但您可能知道,异步调用消失了,再也没有返回(有关here的更多信息)
因此,我已经按照this stack-overflow article
的指示实施了这会一直执行方法(最后返回View),但是我的电子邮件永远不会进入我的收件箱?
也许Google有一些防火墙?
答案 0 :(得分:2)
这里发生的事情是您永远不会将smtp客户端连接到服务器。通常,这将引发异常,但是,您也尝试在没有适当的try / catch的情况下在线程池工作器中发送邮件。没有代码可以捕获您的异常,因此似乎什么也没发生。
也请参见下面的编辑内容,将SmtpClient
和MailMessage
放在using
块中,这样就不必手动调用.Dispose()
。这样即使在连接或发送消息时发生异常,也可以确保资源得到处理。
就像其他人提到的那样,不再维护内置的System.Net.Mail库。我建议使用MailKit(nuget link),因为它维护得很好并且所有者响应迅速。
[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);
}