如何让 JavaMailSender 不会因错误的邮件密码而使应用程序上下文加载失败?
How to have JavaMailSender not fail the application context loading on a wrong mail password?
我在 Sring Boot 应用程序中使用 JavaMailSender,如果 属性 例如密码错误以防止登录邮件网关,那么它无法自动装配 bean 和应用程序上下文无法加载。
Spring 邮件属性:
spring.mail.host=smtp.gmail.com
spring.mail.port=465
spring.mail.protocol=smtp
spring.mail.username=xxx@gmail.com
spring.mail.password=xxx
spring.mail.from=xxx@gmail.com
属性由 属性 reader:
加载
public abstract class AbstractUserProperties implements ApplicationProperties {
@Value("${" + PropertyNames.CONFIG_AUTH_TOKEN_PRIVATE_KEY + "}")
private String authenticationTokenPrivateKey;
@Value("${" + PropertyNames.CONFIG_MAIL_HOST + "}")
private String host;
@Value("${" + PropertyNames.CONFIG_MAIL_PORT + "}")
private String port;
@Value("${" + PropertyNames.CONFIG_MAIL_PROTOCOL + "}")
private String protocol;
@Value("${" + PropertyNames.CONFIG_MAIL_USERNAME + "}")
private String username;
@Value("${" + PropertyNames.CONFIG_MAIL_PASSWORD + "}")
private String password;
@Value("${" + PropertyNames.CONFIG_MAIL_FROM + "}")
private String mailFrom;
@Value("${" + PropertyNames.CONFIG_MAIL_TEST_CONNECTION + "}")
private boolean mailTestConnection;
@Value("${" + PropertyNames.CONFIG_MAILING_ENABLED + "}")
private boolean mailingEnabled;
public String getAuthenticationTokenPrivateKey() {
return authenticationTokenPrivateKey;
}
@Override
public String getHost() {
return host;
}
@Override
public String getPort() {
return port;
}
@Override
public String getProtocol() {
return protocol;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getMailFrom() {
return mailFrom;
}
@Override
public boolean getMailTestConnection() {
return mailTestConnection;
}
@Override
public boolean getMailingEnabled() {
return mailingEnabled;
}
}
如何才能使错误的邮件密码不会阻止应用程序启动?
依赖项:
<version>2.0.3.RELEASE</version>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
我在 Spring Boot 2.0.3
.
这里是应用程序的邮件配置:
@Configuration
public class MailConfig {
@Autowired
private ApplicationProperties applicationProperties;
@Bean
public JavaMailSender javaMailSender() {
String host = applicationProperties.getHost();
String port = applicationProperties.getPort();
String protocol = applicationProperties.getProtocol();
String username = applicationProperties.getUsername();
String password = applicationProperties.getPassword();
if (!password.isEmpty() && !username.isEmpty() && !protocol.isEmpty() && !port.isEmpty() && !host.isEmpty()) {
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost(host);
javaMailSender.setPort(Integer.parseInt(port));
javaMailSender.setProtocol(protocol);
javaMailSender.setUsername(username);
javaMailSender.setPassword(password);
javaMailSender.setJavaMailProperties(getMailProperties());
return javaMailSender;
} else {
return null;
}
}
@Bean
public SimpleMailMessage simpleMailMessage() {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(applicationProperties.getMailFrom());
return simpleMailMessage;
}
private Properties getMailProperties() {
Properties properties = new Properties();
properties.setProperty("mail.smtp.auth", "true");
properties.setProperty("mail.smtp.starttls.enable", "false");
properties.setProperty("mail.smtp.quitwait", "false");
properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.smtp.socketFactory.fallback", "false");
properties.setProperty("mail.debug", "true");
return properties;
}
}
更新:
我已将 spring.mail.test-connection=false
属性 放入 application.properties
文件中,控制台日志显示它已被复制:
[INFO] Copying 1 resource
[DEBUG] Copying file application.properties
我也删除了 MailConfig
class 以便默认使用 Spring 提供的那个。
错误消息仍然相同。
作为旁注,我想知道如何在我自己的 bean 配置中使用 属性 而不是必须使用默认的 Spring bean。
更新:
我可以在我的配置 bean 中添加 mail.test-connection
属性,如:
private Properties getMailProperties() {
Properties properties = new Properties();
properties.setProperty("mail.smtp.auth", "true");
properties.setProperty("mail.smtp.starttls.enable", "false");
properties.setProperty("mail.smtp.quitwait", "false");
properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.smtp.socketFactory.fallback", "false");
properties.setProperty("mail.debug", "true");
properties.setProperty("mail.test-connection", String.valueOf(applicationProperties.getMailTestConnection()));
return properties;
}
@Bean
public JavaMailSender javaMailSender() {
String host = applicationProperties.getHost();
String port = applicationProperties.getPort();
String protocol = applicationProperties.getProtocol();
String username = applicationProperties.getUsername();
String password = applicationProperties.getPassword();
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost(host);
javaMailSender.setPort(Integer.parseInt(port));
javaMailSender.setProtocol(protocol);
javaMailSender.setUsername(username);
javaMailSender.setPassword(password);
javaMailSender.setJavaMailProperties(getMailProperties());
return javaMailSender;
}
现在,即使不提供密码,不检查连接,应用程序上下文也可以正常加载。
您可以将以下行添加到您的 application.properties
文件中,以便在应用程序启动时不测试邮件连接:
spring.mail.test-connection=false
使用此配置,如果您第一次尝试发送邮件,例如您的密码不正确引发异常。
但我不确定你为什么要这样做 :D
UPDATE:如果您想知道 Spring Boot 是如何做到的,请查看 XYZAutoConfiguration
类 MailSender
他们使用以下代码测试连接:
/**
* {@link EnableAutoConfiguration Auto configuration} for testing mail service
* connectivity on startup.
*
* @author Eddú Meléndez
* @author Stephane Nicoll
* @since 1.3.0
*/
@Configuration
@AutoConfigureAfter(MailSenderAutoConfiguration.class)
@ConditionalOnProperty(prefix = "spring.mail", value = "test-connection")
@ConditionalOnSingleCandidate(JavaMailSenderImpl.class)
public class MailSenderValidatorAutoConfiguration {
private final JavaMailSenderImpl mailSender;
public MailSenderValidatorAutoConfiguration(JavaMailSenderImpl mailSender) {
this.mailSender = mailSender;
}
@PostConstruct
public void validateConnection() {
try {
this.mailSender.testConnection();
}
catch (MessagingException ex) {
throw new IllegalStateException("Mail server is not available", ex);
}
}
}
我在 Sring Boot 应用程序中使用 JavaMailSender,如果 属性 例如密码错误以防止登录邮件网关,那么它无法自动装配 bean 和应用程序上下文无法加载。
Spring 邮件属性:
spring.mail.host=smtp.gmail.com
spring.mail.port=465
spring.mail.protocol=smtp
spring.mail.username=xxx@gmail.com
spring.mail.password=xxx
spring.mail.from=xxx@gmail.com
属性由 属性 reader:
加载public abstract class AbstractUserProperties implements ApplicationProperties {
@Value("${" + PropertyNames.CONFIG_AUTH_TOKEN_PRIVATE_KEY + "}")
private String authenticationTokenPrivateKey;
@Value("${" + PropertyNames.CONFIG_MAIL_HOST + "}")
private String host;
@Value("${" + PropertyNames.CONFIG_MAIL_PORT + "}")
private String port;
@Value("${" + PropertyNames.CONFIG_MAIL_PROTOCOL + "}")
private String protocol;
@Value("${" + PropertyNames.CONFIG_MAIL_USERNAME + "}")
private String username;
@Value("${" + PropertyNames.CONFIG_MAIL_PASSWORD + "}")
private String password;
@Value("${" + PropertyNames.CONFIG_MAIL_FROM + "}")
private String mailFrom;
@Value("${" + PropertyNames.CONFIG_MAIL_TEST_CONNECTION + "}")
private boolean mailTestConnection;
@Value("${" + PropertyNames.CONFIG_MAILING_ENABLED + "}")
private boolean mailingEnabled;
public String getAuthenticationTokenPrivateKey() {
return authenticationTokenPrivateKey;
}
@Override
public String getHost() {
return host;
}
@Override
public String getPort() {
return port;
}
@Override
public String getProtocol() {
return protocol;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getMailFrom() {
return mailFrom;
}
@Override
public boolean getMailTestConnection() {
return mailTestConnection;
}
@Override
public boolean getMailingEnabled() {
return mailingEnabled;
}
}
如何才能使错误的邮件密码不会阻止应用程序启动?
依赖项:
<version>2.0.3.RELEASE</version>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
我在 Spring Boot 2.0.3
.
这里是应用程序的邮件配置:
@Configuration
public class MailConfig {
@Autowired
private ApplicationProperties applicationProperties;
@Bean
public JavaMailSender javaMailSender() {
String host = applicationProperties.getHost();
String port = applicationProperties.getPort();
String protocol = applicationProperties.getProtocol();
String username = applicationProperties.getUsername();
String password = applicationProperties.getPassword();
if (!password.isEmpty() && !username.isEmpty() && !protocol.isEmpty() && !port.isEmpty() && !host.isEmpty()) {
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost(host);
javaMailSender.setPort(Integer.parseInt(port));
javaMailSender.setProtocol(protocol);
javaMailSender.setUsername(username);
javaMailSender.setPassword(password);
javaMailSender.setJavaMailProperties(getMailProperties());
return javaMailSender;
} else {
return null;
}
}
@Bean
public SimpleMailMessage simpleMailMessage() {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(applicationProperties.getMailFrom());
return simpleMailMessage;
}
private Properties getMailProperties() {
Properties properties = new Properties();
properties.setProperty("mail.smtp.auth", "true");
properties.setProperty("mail.smtp.starttls.enable", "false");
properties.setProperty("mail.smtp.quitwait", "false");
properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.smtp.socketFactory.fallback", "false");
properties.setProperty("mail.debug", "true");
return properties;
}
}
更新:
我已将 spring.mail.test-connection=false
属性 放入 application.properties
文件中,控制台日志显示它已被复制:
[INFO] Copying 1 resource
[DEBUG] Copying file application.properties
我也删除了 MailConfig
class 以便默认使用 Spring 提供的那个。
错误消息仍然相同。
作为旁注,我想知道如何在我自己的 bean 配置中使用 属性 而不是必须使用默认的 Spring bean。
更新:
我可以在我的配置 bean 中添加 mail.test-connection
属性,如:
private Properties getMailProperties() {
Properties properties = new Properties();
properties.setProperty("mail.smtp.auth", "true");
properties.setProperty("mail.smtp.starttls.enable", "false");
properties.setProperty("mail.smtp.quitwait", "false");
properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.smtp.socketFactory.fallback", "false");
properties.setProperty("mail.debug", "true");
properties.setProperty("mail.test-connection", String.valueOf(applicationProperties.getMailTestConnection()));
return properties;
}
@Bean
public JavaMailSender javaMailSender() {
String host = applicationProperties.getHost();
String port = applicationProperties.getPort();
String protocol = applicationProperties.getProtocol();
String username = applicationProperties.getUsername();
String password = applicationProperties.getPassword();
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost(host);
javaMailSender.setPort(Integer.parseInt(port));
javaMailSender.setProtocol(protocol);
javaMailSender.setUsername(username);
javaMailSender.setPassword(password);
javaMailSender.setJavaMailProperties(getMailProperties());
return javaMailSender;
}
现在,即使不提供密码,不检查连接,应用程序上下文也可以正常加载。
您可以将以下行添加到您的 application.properties
文件中,以便在应用程序启动时不测试邮件连接:
spring.mail.test-connection=false
使用此配置,如果您第一次尝试发送邮件,例如您的密码不正确引发异常。
但我不确定你为什么要这样做 :D
UPDATE:如果您想知道 Spring Boot 是如何做到的,请查看 XYZAutoConfiguration
类 MailSender
他们使用以下代码测试连接:
/**
* {@link EnableAutoConfiguration Auto configuration} for testing mail service
* connectivity on startup.
*
* @author Eddú Meléndez
* @author Stephane Nicoll
* @since 1.3.0
*/
@Configuration
@AutoConfigureAfter(MailSenderAutoConfiguration.class)
@ConditionalOnProperty(prefix = "spring.mail", value = "test-connection")
@ConditionalOnSingleCandidate(JavaMailSenderImpl.class)
public class MailSenderValidatorAutoConfiguration {
private final JavaMailSenderImpl mailSender;
public MailSenderValidatorAutoConfiguration(JavaMailSenderImpl mailSender) {
this.mailSender = mailSender;
}
@PostConstruct
public void validateConnection() {
try {
this.mailSender.testConnection();
}
catch (MessagingException ex) {
throw new IllegalStateException("Mail server is not available", ex);
}
}
}