501 Command "HELO" requires an argument問題的解決方法
更新時間:2013年08月30日 09:07:30 作者:
換一個windows服務器,發(fā)現(xiàn)就沒這樣的問題,僅在一臺Linux服務器上可以重現(xiàn),直觀感覺就是這臺Linux服務器某些配置有問題
場景描述:
保存郵箱配置時自動探測郵箱配置參數(shù)是否正確,結(jié)果發(fā)現(xiàn)在探測SMTP時,系統(tǒng)報出如下異常:
復制代碼 代碼如下:
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服務器,發(fā)現(xiàn)就沒這樣的問題,僅在一臺Linux服務器上可以重現(xiàn),直觀感覺就是這臺Linux服務器某些配置有問題。
排查步驟
1. 找一臺同樣操作系統(tǒng)的Linux服務器,驗證郵箱配置,ok,排除Linux操作系統(tǒng)特殊性的問題
2. 直接在Linux服務器上使用telnet連接對端郵件服務器的SMTP端口,OK,排除該服務器的網(wǎng)絡問題
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.
發(fā)現(xiàn)HELO指令后面需要跟一個發(fā)起者的主機名,告訴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方法在哪里被調(diào)用,看看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服務器連接失敗,請檢查輸入信息是否正確");
}
}
相關(guān)文章
Java實現(xiàn)的時間戳與date對象相互轉(zhuǎn)換功能示例
這篇文章主要介紹了Java實現(xiàn)的時間戳與date對象相互轉(zhuǎn)換功能,結(jié)合具體實例形式分析了java日期與時間戳類型的表示與轉(zhuǎn)換相關(guān)操作技巧,需要的朋友可以參考下2017-06-06mybatis/mybatis-plus模糊查詢語句特殊字符轉(zhuǎn)義攔截器的實現(xiàn)
在開發(fā)中,我們通常會遇到這樣的情況。用戶在錄入信息是錄入了‘%’,而在查詢時無法精確匹配‘%’。究其原因,‘%’是MySQL的關(guān)鍵字,如果我們想要精確匹配‘%’,那么需要對其進行轉(zhuǎn)義,本文就詳細的介紹一下2021-11-11Spring Boot中使用Spring-Retry重試框架的實現(xiàn)
本文主要介紹了Spring Boot中使用Spring-Retry重試框架的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-04-04SpringBoot?項目的創(chuàng)建與啟動步驟詳解
這篇文章主要介紹了SpringBoot?項目的創(chuàng)建與啟動,本文分步驟給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03