【问题标题】:Sending mail using SmtpClient in .net在 .net 中使用 SmtpClient 发送邮件
【发布时间】:2011-01-29 01:31:37
【问题描述】:

我无法使用 smtp 客户端发送邮件。 这是代码:

SmtpClient client=new SmtpClient("Host");
client.Credentials=new NetworkCredential("username", "password");
MailMessage mailMessage = new MailMessage();
mailMessage.from="sender@gmail.com";
mailMessage.To.Add("recipient@gmail.com");
mailMessage.body="body";
mailMessage.subject="subject";
client.Send(mailMessage);

问题是当我在 ASP.NET 应用程序中使用此代码时,我没有收到任何邮件。在 asp.net 中,我将邮件地址更改为 NetworkCredential 中给出的用户名,我会收到邮件。

但在 C# windows 应用程序中,我可以收到电子邮件,即使发件人的电子邮件地址无效。

【问题讨论】:

  • 这可能与服务器上的配置与您的开发机器上的配置有关。
  • 您似乎在“发件人”字段中使用了 gmail 地址。您是否确保所有设置都按照他们的说明进行设置?

标签: c# .net asp.net smtpclient


【解决方案1】:

我发现在设置“UseDefaultCredentials = false”UseDefaultCredentials = false 之前设置 SmtpClient Credentials 属性会导致凭据被忽略。

失败:

SmtpClient smtp = new SmtpClient;
smtp.Credentials = new NetworkCredential("user","pass");
smtp.UseDefaultCredentials = false;

作品:

SmtpClient smtp = new SmtpClient;
smtp.UseDefaultCredentials = false;
smtp.Credentials = new NetworkCredential("user","pass");

去看看。

** 更新 **

这里顺序很重要的原因是UseDefaultCredentials 属性上的设置器实际上通过反编译代码将Credentials 设置为null

/// <summary>Gets or sets a <see cref="T:System.Boolean" /> value that controls whether the <see cref="P:System.Net.CredentialCache.DefaultCredentials" /> are sent with requests.</summary>
/// <returns>
/// <see langword="true" /> if the default credentials are used; otherwise <see langword="false" />. The default value is <see langword="false" />.</returns>
/// <exception cref="T:System.InvalidOperationException">You cannot change the value of this property when an e-mail is being sent.</exception>
public bool UseDefaultCredentials
{
  get
  {
    return this.transport.Credentials is SystemNetworkCredential;
  }
  set
  {
    if (this.InCall)
      throw new InvalidOperationException(SR.GetString("SmtpInvalidOperationDuringSend"));
    this.transport.Credentials = value ? (ICredentialsByHost) CredentialCache.DefaultNetworkCredentials : (ICredentialsByHost) null;
  }
}

【讨论】:

  • 这没有意义,因为两个代码 sn-ps 几乎相同。唯一的区别是 NetworkCredential 类的实例化发生在第二个 sn-p 的 using 块内。也许这有意想不到的副作用?
  • 你是对的。意想不到的效果是,在设置 UseDefaultCredentials = false 之前设置 Credentials 是导致这种情况发生的原因。我会编辑帖子。
  • 我终于从 web.config 获得了凭据。哇!多么美好的一天。
  • 我没有意识到设置主机和端口就像在 web.config smtp/network 条目中查找一样。一旦找到匹配项,它将提取用户和密码并使用它们。希望这对其他人有帮助。
  • 感谢您的解决方案。我已经用示例代码更新了答案,说明了为什么顺序很重要。
【解决方案2】:

简短的回答:不要使用 .net 内部 SMTP 客户端类 - 使用 MailKit

长答案:

  1. 标记为obsolete in MS docs

[System.Obsolete("SmtpClient 及其网络类型设计不佳,我们强烈建议您改用https://github.com/jstedfast/MailKithttps://github.com/jstedfast/MimeKit")] 公共类 SmtpClient : IDisposable

  1. 使用oss库MailKit
  2. 详细说明:因为您迟早会面对它的不足之处。 Read here 或在互联网上阅读。
  3. 这是sending 普通消息和multipart 消息的示例。

我故意没有从此处复制粘贴文档中的示例,因为文档可能会随着时间而改变,最好阅读 .

【讨论】:

    【解决方案3】:

    这意味着您的邮件服务器不允许邮件中继。您的邮件服务器只允许您从经过身份验证的电子邮件 ID 作为用户名发送邮件。通常这样做是为了防止邮件以经过身份验证的身份以外的不同身份发送。

    【讨论】:

    • 邮件服务器在 Windows 和 ASP.NET 应用程序中是相同的。同样的代码在 ASP.NET 应用程序的其他页面中也可以正常工作。它在 ASP.NET 应用程序的登录页面中不起作用。可能是什么问题?
    • 您的应用程序的身份验证模式是什么?请提供有关您的问题场景的更多详细信息..
    • 在asp.net认证模式设置为forms。
    【解决方案4】:

    试试这个:

    MailMessage mail = new MailMessage("emailfrom","emailto");
    
    mail.From = new MailAddress("emailfrom");
    mail.Subject = txtsbjct.Text;
    string Body = txtmsg.Text;
    mail.Body = Body;
    
    mail.IsBodyHtml = true;
    SmtpClient smtp = new SmtpClient();
    smtp.Host = "smtp.gmail.com"; //Or Your SMTP Server Address
    smtp.Credentials = new System.Net.NetworkCredential("youremail", "yourpassword");
    
    smtp.EnableSsl = true;
    smtp.Send(mail);
    txtemail.Text = "";
    txtmsg.Text = "";
    txtsbjct.Text = "";
    Label1.Text = "your email has been send";
    mail = null;
    smtp = null;
    

    【讨论】:

      【解决方案5】:
      void sendEmail(string strFrom
                              , string strTo
                              , string strSubject
                              , string strBody)
         {
      
             MailMessage objMailMessage = new MailMessage();
             System.Net.NetworkCredential objSMTPUserInfo =
                 new System.Net.NetworkCredential();
             SmtpClient objSmtpClient = new SmtpClient();
      
             try
             {
                 objMailMessage.From = new MailAddress(strFrom);
                 objMailMessage.To.Add(new MailAddress(strTo));
                 objMailMessage.Subject = strSubject;
                 objMailMessage.Body = strBody;
      
                 objSmtpClient = new SmtpClient("172.0.0.1"); /// Server IP
                 objSMTPUserInfo = new System.Net.NetworkCredential
                 ("User name", "Password","Domain");
                 objSmtpClient.Credentials = objSMTPUserInfo;
                 objSmtpClient.UseDefaultCredentials = false;
                 objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
      
                 objSmtpClient.Send(objMailMessage);
             }
             catch (Exception ex)
             { throw ex; }
      
             finally
             {
                 objMailMessage = null;
                 objSMTPUserInfo = null;
                 objSmtpClient = null;
             }
         }
      

      【讨论】:

      • 您的错误处理实际上是一个非常糟糕的做法,因为您正在丢失堆栈跟踪 (cf stackoverflow.com/a/730255/474763) ...此外,在这种情况下,省略 catch 子句本来是一种方式去
      • 确实如此。如果你想catch (Exception ex) 然后throw 它,只需使用throw; 而不是throw ex; 并且将保留堆栈跟踪。但是,这仅在您在重新throwing 异常之前正在做其他事情时才有用,例如记录它。但是,在这种情况下,完全省略 catch 子句会产生相同的效果。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-04
      • 2019-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-09
      • 1970-01-01
      相关资源
      最近更新 更多