501 Command "HELO" requires an argument问题的解决方法

场景描述:
保存邮箱配置时自动探测邮箱配置参数是否正确,结果发现在探测SMTP时,系统报出如下异常:


代码如下:

javax.mail.MessagingException: 501 Command "HELO" requires an argument
        at com.sun.mail.smtp.SMTPTransport.issueCommand(SMTPTransport.java:1363)
        at com.sun.mail.smtp.SMTPTransport.helo(SMTPTransport.java:838)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:375)
        at javax.mail.Service.connect(Service.java:275)

但是换一个windows服务器,发现就没这样的问题,仅在一台Linux服务器上可以重现,直观感觉就是这台Linux服务器某些配置有问题。

排查步骤
1. 找一台同样操作系统的Linux服务器,验证邮箱配置,ok,排除Linux操作系统特殊性的问题
2. 直接在Linux服务器上使用telnet连接对端邮件服务器的SMTP端口,OK,排除该服务器的网络问题
3. 查找HELO指令解释


代码如下:

HELO
-- Initiates a conversation with the mail server. When using this command you can specify your domain name so that the mail server knows who you are. For example, HELO mailhost2. cf.ac.uk.

发现HELO指令后面需要跟一个发起者的主机名,告诉SMTP服务器这个消息来源是哪里。
再看异常信息是"501 Command "HELO" requires an argument",很明显,程序在跟SMTP SERVER交互过程中没有传递源主机域名。

4. 查看JAVA MAIL源码
查找HELO指令,如下:


代码如下:

/**
         * Issue the <code>HELO</code> command.
         *
         * @param domain
         *            our domain
         *
         * @since JavaMail 1.4.1
         */
        protected void helo(String domain) throws MessagingException {
                if (domain != null)
                        issueCommand("HELO " + domain, 250);
                else
                        issueCommand("HELO", 250);
        }

查找helo方法在哪里被调用,看看domain如何被传递过来的


代码如下:

if (useEhlo)
                        succeed = ehlo(getLocalHost());
                if (!succeed)
                        helo(getLocalHost());

顺理成章,接着找getLocalHost()方法,定义如下:


代码如下:

/**
         * Get the name of the local host, for use in the EHLO and HELO commands.
         * The property mail.smtp.localhost overrides mail.smtp.localaddress, which
         * overrides what InetAddress would tell us.
         */
        public synchronized String getLocalHost() {
                try {
                        // get our hostname and cache it for future use
                        if (localHostName == null || localHostName.length() <= 0)
                                localHostName = session.getProperty("mail." + name + ".localhost");
                        if (localHostName == null || localHostName.length() <= 0)
                                localHostName = session.getProperty("mail." + name+ ".localaddress");
                        if (localHostName == null || localHostName.length() <= 0) {
                                InetAddress localHost = InetAddress.getLocalHost();
                                localHostName = localHost.getHostName();
                                // if we can't get our name, use local address literal
                                if (localHostName == null)
                                        // XXX - not correct for IPv6
                                        localHostName = "[" + localHost.getHostAddress() + "]";
                        }
                } catch (UnknownHostException uhex) {
                }
                return localHostName;
        }

可以看到hostname的获取可以通过当前连接的session属性中获取,也可以从当前服务器的hosts配置中获取,而我们程序是没有在session中设置hostname的,因此原因肯定在于该台Linux服务器的hosts文件被修改,造成JAVA程序无法自动获得localhostName。

5. 查看/etc/hosts文件,情况如下:


代码如下:

127.0.0.1              localhost.localdomain localhost
::1             localhost6.localdomain6 localhost6

简单的将hosts文件修改如下:


代码如下:

127.0.0.1       localhost
::1             localhost6.localdomain6 localhost6

6. 重新测试,问题解决了。
其实,这种情况也可以通过程序避免,即在session连接中加入当前服务器的hostname属性,程序示例:


代码如下:

public static void main(String[] args) {
                try {
                        int smtpport = 25;
                        String smtpserver = "219.147.xxx.xxx";
                        Properties prop = System.getProperties();
                        prop.put("mail.smtp.auth", "true");
                        prop.put("mail.smtp.localhost", "myMailServer");
                        Session mailSession = Session.getInstance(prop, null);
                        Transport transport = mailSession.getTransport("smtp");
                        transport.connect(smtpserver,smtpport, "username", "password");
                        System.out.println("connect ok");
                        transport.close();
                } catch (AuthenticationFailedException en) {
                        en.printStackTrace();
                        System.out.println("smtp服务器连接失败,请检查输入信息是否正确");
                } catch (NoSuchProviderException e) {
                        e.printStackTrace();
                        System.out.println("smtp服务器连接失败,请检查输入信息是否正确");
                } catch (MessagingException e) {
                        e.printStackTrace();
                        System.out.println("smtp服务器连接失败,请检查输入信息是否正确");
                }
        }

(0)

相关推荐

  • 501 Command "HELO" requires an argument问题的解决方法

    场景描述:保存邮箱配置时自动探测邮箱配置参数是否正确,结果发现在探测SMTP时,系统报出如下异常: 复制代码 代码如下: javax.mail.MessagingException: 501 Command "HELO" requires an argument        at com.sun.mail.smtp.SMTPTransport.issueCommand(SMTPTransport.java:1363)        at com.sun.mail.smtp.SMTPT

  • IE8提示Invalid procedure call or argument 异常的解决方法

    1. 环境: browser_info:"platform:Win32;msie;version:8.0;ie", navigator:"appCodeName:Mozilla;appName:Microsoft Internet Explorer;appMinorVersion:Release Candidate 1;cpuClass:x86;platform:Win32;systemLanguage:zh-cn;userLanguage:zh-cn;appVersion:

  • 关于jd-gui启动报This program requires Java 1.8+的错误问题及解决方法

    最近,在Mac使用上JD-GUI启动时,报了如下的错误: ERROR launching 'JD-GUI'No suitable Java version found on your system!This program requires Java 1.8+Make sure you install the required Java version. 解决方法: 在“访达”中,右击JD-GUI图标,点击“显示包内容”. 然后,打开“Contents/MacOS/universalJavaAp

  • ajax跨域访问报错501的解决方法

    问题:ajax跨域访问报错501 运行下面的代码会报错501 $.ajax({ type: "POST", url: "http://192.168.1.202/sensordata.php", contentType:'application/json; charset=utf-8', data: JSON.stringify(ajaxPostData), dataType:'json', success: function(data){ //On ajax su

  • bash scp command not found的解决方法

    安装了centos6.0,由于选择了最小安装,很多包没有安装,因此一些常用的命令也不支持,如下:# scp -bash: scp: command not found 我的解决方法是:在一台运行正常的CentOS 5.6服务器上找到scp所在的包:##---以下命令在运行正常的CentOS 5.6上执行 复制代码 代码如下: # which scp /usr/bin/scp # rpm -qf /usr/bin/scp openssh-clients-4.3p2-72.el5 这么看来scp所在

  • php下foreach提示Warning:Invalid argument supplied for foreach()的解决方法

    本文实例讲述了php下foreach()错误提示Warning: Invalid argument supplied for foreach() 的解决方法.分享给大家供大家参考.具体实现方法如下: 一.问题: php下foreach()错误提示Warning: Invalid argument supplied for foreach() 错误提示:Warning: Invalid argument supplied for foreach() in E:wampwwwmyshopcart.p

  • Android模拟器无法启动,报错:Cannot set up guest memory ‘android_arm’ Invalid argument的解决方法

    本文实例讲述了Android模拟器无法启动,报错:Cannot set up guest memory 'android_arm': Invalid argument的解决方法.分享给大家供大家参考,具体如下: [错误] 模拟器无法启动,报错:Cannot set up guest memory 'android_arm': Invalid argument [解决办法] 在AVD中(Android Virtual Device Manager)将模拟器的RAM调成512. 这里写图片描述 st

  • apache启动报 shmget() failed: Invalid argument的解决方法

    在用的apache服务器,启动报错: 复制代码 代码如下: shmget() failed:  Invalid argumentFailed to start up concurrent users module! 经检查为kernel.shmmax设置未生效(copy另一系统的,数值设置大了) 如下: 复制代码 代码如下: [root@localhost ~]# sysctl -a | grep shmmkernel.shmmni = 4096kernel.shmmax = 0 [root@l

  • 关于dockerfile build过程中报/bin/sh: pip: command not found的解决方法

    写好的dockerfile的内容是: FROM python:3.6.8 RUN pip install --upgrade pip WORKDIR /code ADD . /code RUN pip install -r requirements.txt ENTRYPOINT ["pytest"] 执行创建镜像到RUN pip install --upgrade pip的时候报/bin/sh: pip: command not found,发现报找不到pip: 发现调用的镜像找不到p

  • Pycharm下载pyinstaller报错:You should consider upgrading via the 'python -m pip install --upgrade pip' command的解决方法

    目录 问题描述: 解决方案: 总结 问题描述: 在使用Pycharm生成.exe文件的过程中,需要下载pyinstaller. 在终端中输入指令 pip install pyinstaller 后,报错: “You are using pip version 10.0.1, however version 20.0.2 is available.You should consider upgrading via the ‘python -m pip install --upgrade pip’

随机推荐