Can';t使用Javamail使用SMTP通过SSL或TLS发送邮件
新年快乐 我正在开发一个应用程序,在这个应用程序中,每当某个特定的触发器发生时,用户就会收到一封电子邮件 这是我用来发送电子邮件的功能:Can';t使用Javamail使用SMTP通过SSL或TLS发送邮件,java,ssl,smtp,Java,Ssl,Smtp,新年快乐 我正在开发一个应用程序,在这个应用程序中,每当某个特定的触发器发生时,用户就会收到一封电子邮件 这是我用来发送电子邮件的功能: public static void sendEmail(String host, String port, String useSSL, String useTLS, String useAuth, String user, String password, String subject, String content, String type, Strin
public static void sendEmail(String host, String port, String useSSL, String useTLS, String useAuth, String user, String password, String subject, String content, String type, String recipients)
throws NoSuchProviderException, AddressException, MessagingException {
final Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.smtp.host", host);
props.setProperty("mail.smtp.port", port);
if (useSSL != null && !useSSL.equals("false") && useSSL.equals("true")) {
props.setProperty("mail.smtp.ssl.enable", useSSL);
props.setProperty("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.port", port);
}
if (useTLS != null && !useTLS.equals("false") && useTLS.equals("true")) {
props.setProperty("mail.smtp.starttls.enable", useTLS);
props.setProperty("mail.smtp.socketFactory.fallback", "true");
}
props.setProperty("mail.smtp.auth", useAuth);
props.setProperty("mail.from", user);
props.setProperty("mail.smtp.user", user);
props.setProperty("mail.password", password);
Session mailSession = Session.getDefaultInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(props.getProperty("mail.smtp.user"), props
.getProperty("mail.password"));
}
});
Transport transport = mailSession.getTransport();
MimeMessage message = new MimeMessage(mailSession);
message.setHeader("Subject", subject);
message.setContent(content, type);
StringTokenizer tokenizer = new StringTokenizer(recipients, ";");
while (tokenizer.hasMoreTokens()) {
String recipient = tokenizer.nextToken();
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(recipient));
}
transport.connect();
transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
transport.close();
奇怪的是,每当我尝试使用main方法运行上述代码时,它都会成功地发送SSL和TLS协议的电子邮件
public static void main(String args[])
{
try {
Notifier.sendEmail("smtp.gmail.com", "587", "false", "true", "true","sender_email@gmail.com", "testpassword", "CHECKING SETTINGS", "CHECKING EMAIL FUNCTIONALITY", "text/html", "cc_email@gmail.com");
} catch (Exception ex) {
ex.printStackTrace();
}
}
但是,每当我试图通过web应用程序运行相同的代码时,它就会失败
通过SSL发送会引发以下错误:
com.sun.mail.smtp.SMTPSendFailedException: 530-5.5.1 Authentication Required. Learn more at
jvm 1 | 530 5.5.1 https://support.google.com/mail/answer/14257 f12sm88286300pat.20 - gsmtp
jvm 1 |
jvm 1 | at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2057)
javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 587;
jvm 1 | nested exception is:
jvm 1 | javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
jvm 1 | at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1934)
通过TLS发送会引发以下错误:
com.sun.mail.smtp.SMTPSendFailedException: 530-5.5.1 Authentication Required. Learn more at
jvm 1 | 530 5.5.1 https://support.google.com/mail/answer/14257 f12sm88286300pat.20 - gsmtp
jvm 1 |
jvm 1 | at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2057)
javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 587;
jvm 1 | nested exception is:
jvm 1 | javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
jvm 1 | at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1934)
感谢您的任何帮助
编辑1:
这是前端的tpl文件
<div class="label1"><h3 class="label">Host:</h3></div>
<div class="field1"><input type="text" class="input1" name="host" size="20" value="$HOST$"></div>
<div class="port"><h3 class="label">Port:</h3></div>
<div class="fieldport"><input type="text" class="fieldport" name="port" size="5" value="$PORT$"></div>
<div class="ssl">
<input type="radio" name="sslEnable" value="$SSLENABLE$">
Enable SSL?
</div>
<div class="tls">
<input type="radio" name="tlsEnable" value="$TLSENABLE$">
Enable TLS?
</div>
<div class="auth">
<input type="checkbox" name="auth"$AUTH$>
Enable Authentication?
</div>
<div class="label2"><h3 class="label">User:</h3></div>
<div class="field2"><input type="text" class="input1" name="user" size="20" value="$USER$"></div>
<div class="label3"><h3 class="label">Password:</h3></div>
<div class="field3"><input type="password" class="input1" name="password" size="20" value="$PASSWORD$"></div>
<div class="label4"><h3 class="label">Recipient(s):</h3></div>
<div class="field4"><input type="text" class="input1" name="recipients" size="50" value="$RECIPIENTS$"></div>
编辑2:
public static void sendEmail(String message)
throws NoSuchProviderException, AddressException, MessagingException
{
if (message == null || message.trim().equals("")) return;
StringBuffer content = new StringBuffer();
content.append(getHeader());
content.append(message);
content.append(getFooter());
String format = NotifyProps.getFormat();
String type = "text/plain";
if (format.equals(NotifyProps.HTML)) type = "text/html";
sendEmail(NotifyProps.getHost(), NotifyProps.getPort(), Boolean.toString(NotifyProps.getUseAuth()), Boolean.toString(NotifyProps.getUseSSL()), Boolean.toString(NotifyProps.getUseTLS()),NotifyProps.getUser(), NotifyProps.getPassword(),
"Transaction Processor Auto Notification", content.toString(), type,
NotifyProps.getRecipients())
}
这是设置和获取属性的类的名称:
谢谢。我们为TLS设置了更多的属性
props.put("mail.smtp.starttls.enable", "true");
props.setProperty("mail.smtp.ssl.enable", "true");
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
对于身份验证,请使用smtps而不是smtp
props.setProperty("mail.smtps.auth", useAuth);
在运输途中
session.getTransport("smtps");
再次在连接时传递主机电子邮件和密码
transport.connect("smtp.gmail.com", "user@email", "password");
用于调试
session.setDebug(true);
尽管代码看起来不错,但至少有一个大问题您正在尝试为TLS和SSL使用相同的端口(587)。我不确定TLS,但是如果您将请求发送到端口465,SSL代码应该可以工作。如文所述: 在端口465(带SSL)和端口587(带TLS)上配置SMTP服务器[…] 它们有自己的特定端口。SSL的错误:
Unrecognized SSL message, plaintext connection?
您的客户端是否不理解它接收到非SSL编码响应的事实(由于TLS端口未实现SSL)。请尝试以下代码,它对我有用
public void sendEmail(){
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("senderEmail@gmail.com","secret");
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("from-email@gmail.com"));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse("to-email@gmail.com"));
message.setSubject("This is testing message");
message.setText("Hi this is testing email....not spam");
Transport.send(message);
System.out.println("email successfully sent..");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
最近,gmail中有一个安全更新。您必须在页面中允许选项“允许不太安全的应用程序访问”。然后您可以从您的帐户发送邮件,而不会出现问题有一个简单的枚举,您可以使用它来指示SSL或TLS。这样,您就不必担心正确的属性:
Email email = new Email();
(...)
new Mailer("smtp.gmail.com", 25, "your user", "your password", TransportStrategy.SMTP_TLS).sendMail(email);
new Mailer("smtp.gmail.com", 587, "your user", "your password", TransportStrategy.SMTP_TLS).sendMail(email);
new Mailer("smtp.gmail.com", 465, "your user", "your password", TransportStrategy.SMTP_SSL).sendMail(email);
如果您启用了双因素登录,则需要从您的Google帐户生成一个新端口,以使此示例正常工作。两个协议使用的端口不同。我使用465用于SSL,587用于TLS。您能告诉我们实际产生错误的web代码吗?您包括了主方法版本,但已经可以使用了。根据错误消息,您正在尝试在TLS端口上启动SSL连接。您的Web应用程序中的参数列表可能有问题?如何读取该配置?前端代码与加载此配置的部分关系不大。这些配置条目(如端口)最终到达
sendMail
功能。这将是很好的,看看他们是否正确到达。您用于您的最后一个链接的网站正在返回HTTP 522,所以我无法检查。是否可以将参数记录在您的webapp中,以显示其获得的确切值?可能正在读取冲突参数,或返回默认值、缓存结果。。。各种各样的错误都可能导致最终传递错误的端口。令我惊讶的是,您说它在命令行测试中起作用。您应该将mail.smtp.socketFactory.class
设置为javax.net.ssl.SSLSocketFactory
,即使使用TLS,而不仅仅是ssl。但与此无关,我建议您使用Yoda条件检查字符串常量,如“true”.equals(sslStr)
。它是空安全的,并且有更少的混乱。