Scene description:
When saving the mailbox configuration, it automatically detects whether the mailbox configuration parameters are correct. It is found that when detecting SMTP, the system reports the following exception:
Copy the code code as follows:
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)
However, when I changed to a Windows server, I found that there was no such problem. It could only be reproduced on a Linux server. It seemed intuitively that there was something wrong with some configuration of this Linux server.
Troubleshooting steps
1. Find a Linux server with the same operating system, verify the email configuration, OK, and eliminate problems with the particularity of the Linux operating system.
2. Use telnet directly on the Linux server to connect to the SMTP port of the opposite mail server. OK, troubleshoot the network problem of the server.
3. Find the HELO instruction explanation
Copy the code code as follows:
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.
It is found that the HELO command needs to be followed by the host name of the initiator to tell the SMTP server where the source of the message is.
Looking at the exception message "501 Command "HELO" requires an argument", it is obvious that the program did not pass the source host domain name during the interaction with the SMTP SERVER.
4. View JAVA MAIL source code
Find the HELO instruction, as follows:
Copy the code code as follows:
/**
* 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);
}
Find where the helo method is called and see how the domain is passed
Copy the code code as follows:
if (useEhlo)
succeed = ehlo(getLocalHost());
if (!succeed)
helo(getLocalHost());
Naturally, then look for the getLocalHost() method, which is defined as follows:
Copy the code code as follows:
/**
* 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;
}
You can see that the hostname can be obtained from the session attribute of the current connection, or from the hosts configuration of the current server. However, our program does not set the hostname in the session, so the reason must lie in the hosts file of the Linux server. was modified, causing the JAVA program to be unable to automatically obtain localhostName.
5. Check the /etc/hosts file, the situation is as follows:
Copy the code code as follows:
127.0.0.1 localhost.localdomain localhost
::1 localhost6.localdomain6 localhost6
Simply modify the hosts file as follows:
Copy the code code as follows:
127.0.0.1 localhost
::1 localhost6.localdomain6 localhost6
6. Retest and the problem is solved.
In fact, this situation can also be avoided through programming, that is, adding the hostname attribute of the current server to the session connection. Program example:
Copy the code code as follows:
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 server connection failed, please check whether the input information is correct");
} catch (NoSuchProviderException e) {
e.printStackTrace();
System.out.println("SMTP server connection failed, please check whether the input information is correct");
} catch (MessagingException e) {
e.printStackTrace();
System.out.println("SMTP server connection failed, please check whether the input information is correct");
}
}