出现ASP错误:邮箱不可用。服务器响应为:访问被拒绝-无效的HELO名称(请参阅RFC2821 4.1.1.1)

 可心 发布于 2023-01-01 11:37

您遇到的问题是SmtpClient正在使用服务器拒绝SMTP的主机名/域字符串发出HELOEHLO命令。

我显然不知道Microsoft的SmtpClient实现的内部逻辑,但是我怀疑您可能在NAT的后面,这意味着SmtpClient无法解析您的计算机在世界范围内可见的完全限定域名。它只能解析“内部网络”上计算机的FQDN(实际上,它甚至可能无法解析为实际的FQDN,它可能必须满足内部网络IP地址)。

所以... SmtpClient可能正在发送类似EHLO [192.168.1.100](或任何本地IP)的消息,并且服务器拒绝了它,因为那不是它从其接收数据包的IP地址。

您需要做的是通过访问http://www.whatismyip.com/等站点或使用http://www.displaymyhostname.com/等站点检测到的主机名来找到外部IP地址。

为了说明我在说什么,这里有一个演示程序:

using System;
using System.Net;
using System.Linq;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Net.NetworkInformation;

namespace LocalHostName
{
    class Program
    {
        static void Main (string[] args)
        {
            var ipAddresses = Dns.GetHostAddresses ("www.google.com");
            Socket socket;

            for (int i = 0; i < ipAddresses.Length; i++) {
                socket = new Socket (ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                try {
                    socket.Connect (ipAddresses[i], 80);
                    Console.WriteLine ("LocalEndPoint: {0}", socket.LocalEndPoint);
                    break;
                } catch {
                    socket.Dispose ();
                    socket = null;

                    if (i + 1 == ipAddresses.Length)
                        throw;
                }
            }

            Console.ReadLine ();
        }
    }
}

它打印出的任何IP地址都可能是SmtpClient在其HELO/ EHLO命令中使用的IP地址。

坏消息是System.Net.Mail.SmtpClient无法解决此问题。

好消息是,我节省了15%的汽车保险...嗯,我的意思是,我已经编写了自己的电子邮件库,名为MimeKit和MailKit,可以解决此问题。

还有一些好消息是,您可以轻松地将System.Net.Mail.MailMessage对象转换为MimeKit.MimeMessage对象(尽管显然,最好完全切换到MimeKit和MailKit)。

var mimeMessage = (MimeMessage) mailMessage;

这是使用MimeKit和MailKit重新编写的SMTPMailHelper类的样子:

using System;
using MimeKit;
using MailKit.Net.Smtp;

public class SMTPMailHelper
{
    const string SMTPServer = "mail.mydomain.com";
    const string SMTPUserId = "myemail@mydomain.com";
    const string SMTPPassword = "MyPasswordHidden";
    const int SMTPPort = 25;

    public static void SendMail(string sendFrom, string sendTo, string subject, string body)
    {
        MimeMessage message = new MimeMessage ();
        TextPart text;

        message.From.Add (new MailboxAddress ("", sendFrom));
        message.To.Add (new MailboxAdress ("", sendTo));
        message.Subject = subject;

        if (body.ToLower ().Contains (""))
            text = new TextPart ("html") { Text = text };
        else
            text = new TextPart ("plain") { Text = text };

        message.Body = text;

        using (var smtp = new SmtpClient ()) {
            // use the IP address gotten from http://www.whatismyip.com/
            // or the hostname gotten from http://www.displaymyhostname.com/
            smtp.LocalDomain = "c-24-71-150-91.hsd1.ga.comcast.net";

            smtp.Connect (SMTPServer, SMTPPort, false);
            smtp.Authenticate (SMTPUserId, SMTPPassword);
            smtp.Send (message);
            smtp.Disconnect (true);
        }
    }
}

重要的是将SmtpClient的LocalDomain属性设置为的字符串。

1 个回答
  • 您遇到的问题是SmtpClient正在使用服务器拒绝SMTP的主机名/域字符串发出HELOEHLO命令。

    我显然不知道Microsoft的SmtpClient实现的内部逻辑,但是我怀疑您可能在NAT的后面,这意味着SmtpClient无法解析您的计算机在世界范围内可见的完全限定域名。它只能解析“内部网络”上计算机的FQDN(实际上,它甚至可能无法解析为实际的FQDN,它可能必须满足内部网络IP地址)。

    所以... SmtpClient可能正在发送类似EHLO [192.168.1.100](或任何本地IP)的消息,并且服务器拒绝了它,因为那不是它从其接收数据包的IP地址。

    您需要做的是通过访问http://www.whatismyip.com/等站点或使用http://www.displaymyhostname.com/等站点检测到的主机名来找到外部IP地址。

    为了说明我在说什么,这里有一个演示程序:

    using System;
    using System.Net;
    using System.Linq;
    using System.Net.Sockets;
    using System.Collections.Generic;
    using System.Net.NetworkInformation;
    
    namespace LocalHostName
    {
        class Program
        {
            static void Main (string[] args)
            {
                var ipAddresses = Dns.GetHostAddresses ("www.google.com");
                Socket socket;
    
                for (int i = 0; i < ipAddresses.Length; i++) {
                    socket = new Socket (ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp);
    
                    try {
                        socket.Connect (ipAddresses[i], 80);
                        Console.WriteLine ("LocalEndPoint: {0}", socket.LocalEndPoint);
                        break;
                    } catch {
                        socket.Dispose ();
                        socket = null;
    
                        if (i + 1 == ipAddresses.Length)
                            throw;
                    }
                }
    
                Console.ReadLine ();
            }
        }
    }
    

    它打印出的任何IP地址都可能是SmtpClient在其HELO/ EHLO命令中使用的IP地址。

    坏消息是System.Net.Mail.SmtpClient无法解决此问题。

    好消息是,我节省了15%的汽车保险...嗯,我的意思是,我已经编写了自己的电子邮件库,名为MimeKit和MailKit,可以解决此问题。

    还有一些好消息是,您可以轻松地将System.Net.Mail.MailMessage对象转换为MimeKit.MimeMessage对象(尽管显然,最好完全切换到MimeKit和MailKit)。

    var mimeMessage = (MimeMessage) mailMessage;
    

    这是使用MimeKit和MailKit重新编写的SMTPMailHelper类的样子:

    using System;
    using MimeKit;
    using MailKit.Net.Smtp;
    
    public class SMTPMailHelper
    {
        const string SMTPServer = "mail.mydomain.com";
        const string SMTPUserId = "myemail@mydomain.com";
        const string SMTPPassword = "MyPasswordHidden";
        const int SMTPPort = 25;
    
        public static void SendMail(string sendFrom, string sendTo, string subject, string body)
        {
            MimeMessage message = new MimeMessage ();
            TextPart text;
    
            message.From.Add (new MailboxAddress ("", sendFrom));
            message.To.Add (new MailboxAdress ("", sendTo));
            message.Subject = subject;
    
            if (body.ToLower ().Contains ("<html>"))
                text = new TextPart ("html") { Text = text };
            else
                text = new TextPart ("plain") { Text = text };
    
            message.Body = text;
    
            using (var smtp = new SmtpClient ()) {
                // use the IP address gotten from http://www.whatismyip.com/
                // or the hostname gotten from http://www.displaymyhostname.com/
                smtp.LocalDomain = "c-24-71-150-91.hsd1.ga.comcast.net";
    
                smtp.Connect (SMTPServer, SMTPPort, false);
                smtp.Authenticate (SMTPUserId, SMTPPassword);
                smtp.Send (message);
                smtp.Disconnect (true);
            }
        }
    }
    

    重要的是将SmtpClient的LocalDomain属性设置为的字符串。

    2023-01-01 11:40 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有