我正在使用JavaMail编写一个小型Java应用程序,向用户发送自动电子邮件。他们可以选择(现在)两个端口:25和587.可以通过GUI上的单选按钮选择端口。
我添加了一个测试按钮,允许用户测试电子邮件设置(包括端口)。但是,由于某种原因,一旦用户尝试发送测试电子邮件,端口就无法更改。 Javamail将始终使用原始测试电子邮件的端口。
示例:用户尝试在端口25上发送电子邮件,JavaMail表示无法在端口25上连接(例如,SMTP主机使用其他端口)。用户单击端口587,并尝试发送新电子邮件。 JavaMail抛出错误,说它无法再次在端口25上连接。
我有点难过为什么。每次发送新的测试电子邮件时,都会创建一个全新的SendMailUsingAuthentication对象。在该类中,属性始终重置为正确的端口。每当我调试时,据我所知,所有变量都是正确的,并与正确的端口相关联。我错过了运输内部的东西吗?
在前端GUI中:
private void testButtonActionPerformed(java.awt.event.ActionEvent evt) {
int port = port25RadioButton.isSelected() ? PORT_25 : PORT_587;
notifier = new SendMailUsingAuthentication(hostNameTextField.getText(),
userTextField.getText(), getPassword(), emailTextField.getText().split(","),port);
Thread wait = new Thread(new Runnable() {
public void run() {
try {
changeStatusText("Sending test email...");
notifier.postTestMail();
changeStatusText("Test email sent.");
} catch (AddressException ex) {
changeStatusText("Error. Invalid email address name.");
} catch (MessagingException ex) {
changeStatusText("SMTP host connection refused.");
System.err.println(ex.getMessage());
} catch (Exception ex) {
System.err.println(ex);
}
}
});
wait.start();
}
在电子邮件发件人类中:
public void postTestMail() throws MessagingException, AddressException{
String[] testReciever = new String[1];
testReciever[0] = emailList[0];
postMail(testReciever, "Test email.", "Your email settings are successfully set up.", emailFromAddress);
}
private void postMail(String recipients[], String subject,
String message, String from) throws MessagingException, AddressException {
//Set the host smtp address
Properties props = new Properties();
props.put("mail.smtp.port", smtpPort);
props.put("mail.smtp.host", smtpHostName);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", true);
Authenticator auth = new SMTPAuthenticator();
Session session = Session.getDefaultInstance(props, auth);
session.setDebug(false);
// create a message
Message msg = new MimeMessage(session);
// set the from and to address
InternetAddress addressFrom = new InternetAddress(from);
msg.setFrom(addressFrom);
InternetAddress[] addressTo = new InternetAddress[recipients.length];
for (int i = 0; i < recipients.length; i++) {
addressTo[i] = new InternetAddress(recipients[i]);
}
msg.setRecipients(Message.RecipientType.TO, addressTo);
// Setting the Subject and Content Type
msg.setSubject(subject);
msg.setContent(message, "text/plain");
Transport.send(msg);
}
答案 0 :(得分:23)
这是因为您使用了getDefaultInstance()
:
Properties
获取默认的Session对象。如果尚未设置默认值,则会创建一个新的Session对象并将其安装为默认值。
并且getDefaultInstance
参数“仅在创建新的Session对象时使用。”
因此,当您第一次调用Session
时,它会使用您指定的端口。之后,getDefaultInstance
已经创建,后续对Session.getInstance()
的调用将返回相同的会话,并忽略更改的属性。
尝试使用getDefaultInstance()
代替Session
,每次使用提供的属性创建新的{{1}}。
非常仔细地阅读javadoc是值得的。
答案 1 :(得分:3)
我认为“Transport.send(msg)”不会考虑您在属性中提供的连接详细信息。它将使用默认定义的连接。
java doc说
“请注意,send是一种静态方法,用于创建和管理自己的连接。**与用于调用此方法的任何传输实例关联的任何连接都将被忽略并且不会被使用。此方法仅应该使用表单Transport.send(msg);调用,不应该使用实例变量调用。“**
相反,我尝试使用Transport.connect(smtphost,smtpport,用户,密码),它运行良好。
答案 2 :(得分:2)
Plz比较Session类的两种方法:Session.getDefaultInstance(Properties, Authenticator)和Session.getInstance(Properties, Authenticator)
答案 3 :(得分:0)
提示仍然存在问题的其他人,我们使用的是 Session.getInstance
,端口仍然默认为25。
结果是,我们在需要将prop值设置为 Long
String
它没有错误,警告或记录,只是默认为25。