使用MS Exchange的JavaMail:服务器和客户端均不支持身份validation机制

我几天来一直试图从Grails应用程序发送邮件但没有成功。 我在用着:

  • grails 1.3.7
  • 邮件1.0插件
  • spring-security-core 1.2.6插件
  • tomcat 7.0.23

Specifficaly我正在尝试使用部署在Tomcat服务器上的应用程序发送邮件,该端口25没有身份validation,没有SSL。

我已经尝试从部署了应用程序的VMWare虚拟机发送带有telnet的消息并且它已经通过了。

这是我发送邮件的课程:

public boolean sendMessage(String to, String msgSubject, String msgText) { String host = "mail.mydomain.com"; String username = "myuser@mydomain.com"; // your authsmtp username String password = "mypassword" // your authsmtp password String from = "myuser@mydomain.com"; Properties props = System.getProperties(); props.put("mail.smtp.host", host); props.put("mail.smtp.user", username); props.put("mail.smtp.password", password); props.put("mail.smtp.port", "25"); // thish is the port recommended by authsmtp props.put("mail.smtp.auth", "false"); Session session = Session.getDefaultInstance(props, null); MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); InternetAddress to_address = new InternetAddress(to); message.addRecipient(Message.RecipientType.TO, to_address); message.setSubject(msgSubject); message.setText(msgText); Transport transport = session.getTransport("smtp"); transport.connect(host, username, password); transport.sendMessage(message, message.getAllRecipients()); transport.close(); return true; } 

这是错误堆栈跟踪:

 javax.mail.AuthenticationFailedException: No authentication mechansims supported by both server and client at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:590) at javax.mail.Service.connect(Service.java:291) at javax.mail.Service.connect(Service.java:172) at javax.mail.Service$connect.call(Unknown Source) at org.helpdesk.MymailService.sendMessage(MymailService.groovy:37) at org.helpdesk.MymailService$sendMessage.call(Unknown Source) at org.helpdesk.RequestController$_closure13.doCall(RequestController.groovy:247) at org.helpdesk.RequestController$_closure13.doCall(RequestController.groovy) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) 

我已经阅读了几十个post,考虑到这样的问题,但我仍然无法解决问题。 任何帮助表示赞赏。

* 编辑: *如果没有身份validation,是否可能在使用带有Exchange服务器SMTP的javaMail发送邮件时出现问题?

如果您尝试在未经身份validation的情况下连接到邮件服务器,请调用带用户名和密码的connect方法。 如果您传递用户名和密码,它认为您确实要进行身份validation,并且由于无法找到服务器支持的身份validation机制,因此无法进行身份validation。

在我的情况下,我必须设置属性

 "mail.smtp.ehlo" 

为了"false"

(除了添加将属性"mail.smtp.auth"设置为"false" ,但根据此链接似乎是默认值)

在将"mail.smtp.ehlo"设置为"false"我看到了以下调试输出(通过将属性"mail.debug""true"来启用):

 DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM DEBUG SMTP: mechanism LOGIN not supported by server DEBUG SMTP: mechanism PLAIN not supported by server DEBUG SMTP: mechanism DIGEST-MD5 not supported by server DEBUG SMTP: mechanism NTLM not supported by server 

然后得到相同的javax.mail.AuthenticationFailedException

(在这种情况下,SMTP服务器是Microsoft服务器)

好吧,看起来我几乎没有问题。 起初,Exchange未正确设置。 然后我似乎尝试了所有可能的配置,但是正确的配置。 这有效:

 class MymailService { boolean transactional = false public sendMessage(String to, String cc, String msgSubject, String msgText) { String host = "mail.mailserver.com"; String username = "myusername@mymailserver.com"; String password = "xxx"; String from = "myusername@mymailserver.com"; String port = "25"; Properties props = System.getProperties(); props.put("mail.smtp.host", host); props.put("mail.smtp.port", port); props.put("mail.smtp.auth", "false"); Transport transport = null; try{ Session session = Session.getDefaultInstance(props, null); MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); InternetAddress to_address = new InternetAddress(to); message.addRecipient(Message.RecipientType.TO, to_address); InternetAddress cc_address = new InternetAddress(cc); message.addRecipient(Message.RecipientType.CC, cc_address); message.setSubject(msgSubject); message.setText(msgText); transport = session.getTransport("smtp"); transport.connect(); transport.sendMessage(message, message.getAllRecipients()); } finally { if (transport != null) try { transport.close(); } catch (MessagingException logOrIgnore){} } } } 

最后的线索是Bill Shannon的post。 谢谢比尔!

  1. 检查您要服务的服务器是否要求进行身份validation。 在代码中更多关于此。

  2. 请在属性中放置mail.debug,以了解代码与邮件服务器之间究竟发生了什么。 在代码中更多关于此。

这是一个简单的代码,适用于我公司的邮件服务器:

  package com.datereminder.service; import java.util.Properties; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; public class ReminderDaemonService2 { /** * @param args */ public static void main(String[] args) { Properties props = new Properties(); props.put("mail.smtp.host", "mail.mycompany123.com"); // this mandates authentication at the mailserver props.put("mail.smtp.auth", "true"); // this is for printing debugs props.put("mail.debug", "true"); Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("sadique.khan@mycompany123.com","xxxxxxxxxxx"); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress("sadique.khan@mycompany123.com")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("my.bestfriend@mycompany123.com")); message.setSubject("Testing Subject"); message.setText("Dear Friend," + "\n\n This is a Test mail!"); Transport.send(message); } catch (MessagingException e) { throw new RuntimeException(e); } } } 

这是我的解决方案,也许这不是最好的方式,但它对我有用……

在mail-config.xml中:

           ${mail.auth}    

这是设置:

 mail.from=XXX Team  mail.host=exchange.xxx.com mail.port=25 mail.protocol=smtp mail.auth=false mail.username= mail.password= 

最后,代码:

 package com.xxx.service; import org.springframework.mail.javamail.JavaMailSenderImpl; public class MailSender extends JavaMailSenderImpl { private boolean authRequired; @Override public String getUsername() { if (!authRequired) { return null; } return super.getUsername(); } @Override public String getPassword() { if (!authRequired) { return null; } return super.getPassword(); } public boolean isAuthRequired() { return authRequired; } public void setAuthRequired(boolean authRequired) { this.authRequired = authRequired; } } 

如果您希望您的应用程序登录到SMTP服务器(因为您提供身份validation详细信息)。 只是改变

 props.put("mail.smtp.auth", false); 

 props.put("mail.smtp.auth", true);