如何正确发送电子邮件-异步发送?邮件永远不会到达

时间:2018-09-25 14:13:14

标签: 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; }
    [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有一些防火墙?

1 个答案:

答案 0 :(得分:2)

这里发生的事情是您永远不会将smtp客户端连接到服务器。通常,这将引发异常,但是,您也尝试在没有适当的try / catch的情况下在线程池工作器中发送邮件。没有代码可以捕获您的异常,因此似乎什么也没发生。

也请参见下面的编辑内容,将SmtpClientMailMessage放在using块中,这样就不必手动调用.Dispose()。这样即使在连接或发送消息时发生异常,也可以确保资源得到处理。

就像其他人提到的那样,不再维护内置的System.Net.Mail库。我建议使用MailKitnuget 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);
}