Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何正确地异步发送电子邮件?邮件永远不会到达_C#_Asp.net Mvc_Asynchronous - Fatal编程技术网

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

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

我用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")
}
@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和实际返回
任务的方法