mirror of https://github.com/halo-dev/halo
Refactor email service and remove oh-my-email dependency (#584)
* Refactor email service * Remove oh-my-email dependency * Add mail dependency * Provide connection test with email server * Enable send message asynchronously * Make more friendly information.pull/587/head
parent
4092ed1633
commit
b7b11e2c8f
|
@ -42,7 +42,6 @@ bootJar {
|
|||
}
|
||||
|
||||
ext {
|
||||
ohMyEmailVersion = '0.0.4'
|
||||
hutoolVersion = '5.0.3'
|
||||
upyunSdkVersion = '4.0.1'
|
||||
qiniuSdkVersion = '7.2.18'
|
||||
|
@ -72,8 +71,8 @@ dependencies {
|
|||
implementation 'org.springframework.boot:spring-boot-starter-undertow'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-freemarker'
|
||||
implementation "kr.pe.kwonnam.freemarker:freemarker-template-inheritance:$templateInheritance"
|
||||
implementation "com.sun.mail:jakarta.mail"
|
||||
|
||||
implementation "io.github.biezhi:oh-my-email:$ohMyEmailVersion"
|
||||
implementation "cn.hutool:hutool-core:$hutoolVersion"
|
||||
implementation "cn.hutool:hutool-crypto:$hutoolVersion"
|
||||
implementation "cn.hutool:hutool-extra:$hutoolVersion"
|
||||
|
@ -110,7 +109,7 @@ dependencies {
|
|||
|
||||
implementation "org.json:json:$jsonVersion"
|
||||
implementation "com.alibaba:fastjson:$fastJsonVersion"
|
||||
|
||||
|
||||
implementation "org.iq80.leveldb:leveldb:$levelDbVersion"
|
||||
runtimeOnly "com.h2database:h2:$h2Version"
|
||||
runtimeOnly 'mysql:mysql-connector-java'
|
||||
|
|
|
@ -5,9 +5,9 @@ import org.springframework.web.bind.annotation.PostMapping;
|
|||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import run.halo.app.mail.MailService;
|
||||
import run.halo.app.model.params.MailParam;
|
||||
import run.halo.app.model.support.BaseResponse;
|
||||
import run.halo.app.service.MailService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
|
@ -29,8 +29,16 @@ public class MailController {
|
|||
|
||||
@PostMapping("test")
|
||||
@ApiOperation("Tests the SMTP service")
|
||||
public BaseResponse testMail(@Valid @RequestBody MailParam mailParam) {
|
||||
mailService.sendMail(mailParam.getTo(), mailParam.getSubject(), mailParam.getContent());
|
||||
return BaseResponse.ok("发送成功");
|
||||
public BaseResponse<String> testMail(@Valid @RequestBody MailParam mailParam) {
|
||||
mailService.sendTextMail(mailParam.getTo(), mailParam.getSubject(), mailParam.getContent());
|
||||
return BaseResponse.ok("已发送,请查收。若确认没有收到邮件,请检查服务器日志");
|
||||
}
|
||||
|
||||
@PostMapping("test/connection")
|
||||
@ApiOperation("Test connection with email server")
|
||||
public BaseResponse<String> testConnection() {
|
||||
mailService.testConnection();
|
||||
return BaseResponse.ok("您和邮箱服务器的连接通畅");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.springframework.stereotype.Component;
|
|||
import run.halo.app.event.comment.CommentNewEvent;
|
||||
import run.halo.app.event.comment.CommentReplyEvent;
|
||||
import run.halo.app.exception.ServiceException;
|
||||
import run.halo.app.mail.MailService;
|
||||
import run.halo.app.model.entity.*;
|
||||
import run.halo.app.model.properties.CommentProperties;
|
||||
import run.halo.app.service.*;
|
||||
|
@ -141,7 +142,7 @@ public class CommentEventListener {
|
|||
/**
|
||||
* Received a new reply comment event.
|
||||
*
|
||||
* @param newEvent reply comment event.
|
||||
* @param replyEvent reply comment event.
|
||||
*/
|
||||
@Async
|
||||
@EventListener
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
package run.halo.app.mail;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
import org.springframework.util.Assert;
|
||||
import run.halo.app.exception.EmailException;
|
||||
import run.halo.app.model.properties.EmailProperties;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Abstract mail service.
|
||||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractMailService implements MailService {
|
||||
|
||||
private static final int DEFAULT_POOL_SIZE = 5;
|
||||
|
||||
private JavaMailSender cachedMailSender;
|
||||
|
||||
private MailProperties cachedMailProperties;
|
||||
|
||||
private String cachedFromName;
|
||||
|
||||
protected final OptionService optionService;
|
||||
|
||||
@Nullable
|
||||
private ExecutorService executorService;
|
||||
|
||||
protected AbstractMailService(OptionService optionService) {
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
public void setExecutorService(ExecutorService executorService) {
|
||||
this.executorService = executorService;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ExecutorService getExecutorService() {
|
||||
if (this.executorService == null) {
|
||||
this.executorService = Executors.newFixedThreadPool(DEFAULT_POOL_SIZE);
|
||||
}
|
||||
return executorService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test connection with email server.
|
||||
*/
|
||||
public void testConnection() {
|
||||
JavaMailSender javaMailSender = getMailSender();
|
||||
if (javaMailSender instanceof JavaMailSenderImpl) {
|
||||
JavaMailSenderImpl mailSender = (JavaMailSenderImpl) javaMailSender;
|
||||
try {
|
||||
mailSender.testConnection();
|
||||
} catch (MessagingException e) {
|
||||
throw new EmailException("无法连接到邮箱服务器,请检查邮箱配置.[" + e.getMessage() + "]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail template.
|
||||
*
|
||||
* @param callback mime message callback.
|
||||
*/
|
||||
protected void sendMailTemplate(@Nullable Callback callback) {
|
||||
if (callback == null) {
|
||||
log.info("Callback is null, skip to send email");
|
||||
return;
|
||||
}
|
||||
|
||||
// check if mail is enable
|
||||
Boolean emailEnabled = optionService.getByPropertyOrDefault(EmailProperties.ENABLED, Boolean.class);
|
||||
|
||||
if (!emailEnabled) {
|
||||
// If disabled
|
||||
log.info("Email has been disabled by yourself, you can re-enable it through email settings on admin page.");
|
||||
return;
|
||||
}
|
||||
|
||||
// get mail sender
|
||||
JavaMailSender mailSender = getMailSender();
|
||||
printMailConfig();
|
||||
|
||||
// create mime message helper
|
||||
MimeMessageHelper messageHelper = new MimeMessageHelper(mailSender.createMimeMessage());
|
||||
|
||||
try {
|
||||
// set from-name
|
||||
messageHelper.setFrom(getFromAddress(mailSender));
|
||||
// handle message set separately
|
||||
callback.handle(messageHelper);
|
||||
|
||||
// get mime message
|
||||
MimeMessage mimeMessage = messageHelper.getMimeMessage();
|
||||
// send email
|
||||
mailSender.send(mimeMessage);
|
||||
|
||||
log.info("Sent an email to [{}] successfully, subject: [{}], sent date: [{}]",
|
||||
Arrays.toString(mimeMessage.getAllRecipients()),
|
||||
mimeMessage.getSubject(),
|
||||
mimeMessage.getSentDate());
|
||||
} catch (Exception e) {
|
||||
throw new EmailException("邮件发送失败,请检查 SMTP 服务配置是否正确", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail template if executor service is enable.
|
||||
*
|
||||
* @param callback callback message handler
|
||||
* @param tryToAsync if the send procedure should try to asynchronous
|
||||
*/
|
||||
protected void sendMailTemplate(boolean tryToAsync, @Nullable Callback callback) {
|
||||
ExecutorService executorService = getExecutorService();
|
||||
if (tryToAsync && executorService != null) {
|
||||
// send mail asynchronously
|
||||
executorService.execute(() -> sendMailTemplate(callback));
|
||||
} else {
|
||||
// send mail synchronously
|
||||
sendMailTemplate(callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get java mail sender.
|
||||
*
|
||||
* @return java mail sender
|
||||
*/
|
||||
@NonNull
|
||||
private synchronized JavaMailSender getMailSender() {
|
||||
if (this.cachedMailSender == null) {
|
||||
// create mail sender factory
|
||||
MailSenderFactory mailSenderFactory = new MailSenderFactory();
|
||||
// get mail sender
|
||||
this.cachedMailSender = mailSenderFactory.getMailSender(getMailProperties());
|
||||
}
|
||||
|
||||
return this.cachedMailSender;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get from-address.
|
||||
*
|
||||
* @param javaMailSender java mail sender.
|
||||
* @return from-name internet address
|
||||
* @throws UnsupportedEncodingException throws when you give a wrong character encoding
|
||||
*/
|
||||
private synchronized InternetAddress getFromAddress(@NonNull JavaMailSender javaMailSender) throws UnsupportedEncodingException {
|
||||
Assert.notNull(javaMailSender, "Java mail sender must not be null");
|
||||
|
||||
if (StringUtils.isBlank(this.cachedFromName)) {
|
||||
// set personal name
|
||||
this.cachedFromName = optionService.getByPropertyOfNonNull(EmailProperties.FROM_NAME).toString();
|
||||
}
|
||||
|
||||
if (javaMailSender instanceof JavaMailSenderImpl) {
|
||||
// get user name(email)
|
||||
JavaMailSenderImpl mailSender = (JavaMailSenderImpl) javaMailSender;
|
||||
String username = mailSender.getUsername();
|
||||
|
||||
// build internet address
|
||||
return new InternetAddress(username, this.cachedFromName, mailSender.getDefaultEncoding());
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Unsupported java mail sender: " + javaMailSender.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mail properties.
|
||||
*
|
||||
* @return mail properties
|
||||
*/
|
||||
@NonNull
|
||||
private synchronized MailProperties getMailProperties() {
|
||||
if (cachedMailProperties == null) {
|
||||
// create mail properties
|
||||
MailProperties mailProperties = new MailProperties(log.isDebugEnabled());
|
||||
|
||||
// set properties
|
||||
mailProperties.setHost(optionService.getByPropertyOrDefault(EmailProperties.HOST, String.class));
|
||||
mailProperties.setPort(optionService.getByPropertyOrDefault(EmailProperties.SSL_PORT, Integer.class));
|
||||
mailProperties.setUsername(optionService.getByPropertyOrDefault(EmailProperties.USERNAME, String.class));
|
||||
mailProperties.setPassword(optionService.getByPropertyOrDefault(EmailProperties.PASSWORD, String.class));
|
||||
mailProperties.setProtocol(optionService.getByPropertyOrDefault(EmailProperties.PROTOCOL, String.class));
|
||||
this.cachedMailProperties = mailProperties;
|
||||
}
|
||||
|
||||
return this.cachedMailProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print mail configuration.
|
||||
*/
|
||||
private void printMailConfig() {
|
||||
if (!log.isDebugEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get mail properties
|
||||
MailProperties mailProperties = getMailProperties();
|
||||
log.debug(mailProperties.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cached instance.
|
||||
*/
|
||||
protected void clearCache() {
|
||||
this.cachedMailSender = null;
|
||||
this.cachedFromName = null;
|
||||
this.cachedMailProperties = null;
|
||||
log.debug("Cleared all mail caches");
|
||||
}
|
||||
|
||||
/**
|
||||
* Message callback.
|
||||
*/
|
||||
protected interface Callback {
|
||||
/**
|
||||
* Handle message set.
|
||||
*
|
||||
* @param messageHelper mime message helper
|
||||
* @throws Exception if something goes wrong
|
||||
*/
|
||||
void handle(@NonNull MimeMessageHelper messageHelper) throws Exception;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package run.halo.app.mail;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Mail properties.
|
||||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
public class MailProperties extends org.springframework.boot.autoconfigure.mail.MailProperties {
|
||||
|
||||
private Map<String, String> properties;
|
||||
|
||||
public MailProperties() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public MailProperties(boolean needDebug) {
|
||||
// set some default properties
|
||||
addProperties("mail.debug", Boolean.toString(needDebug));
|
||||
addProperties("mail.smtp.auth", Boolean.TRUE.toString());
|
||||
addProperties("mail.smtp.ssl.enable", Boolean.TRUE.toString());
|
||||
addProperties("mail.smtp.timeout", "10000");
|
||||
}
|
||||
|
||||
public void addProperties(String key, String value) {
|
||||
if (properties == null) {
|
||||
properties = new HashMap<>();
|
||||
}
|
||||
properties.put(key, value);
|
||||
}
|
||||
|
||||
public void setProperties(Map<String, String> properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final String lineSuffix = ",\n";
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
sb.append("MailProperties{").append(lineSuffix);
|
||||
sb.append("host=").append(getHost()).append(lineSuffix);
|
||||
sb.append("username=").append(getUsername()).append(lineSuffix);
|
||||
sb.append("password=").append(StringUtils.isBlank(getPassword()) ? "<null>" : "<non-null>");
|
||||
sb.append("port=").append(getPort()).append(lineSuffix);
|
||||
sb.append("protocol=").append(getProtocol()).append(lineSuffix);
|
||||
sb.append("defaultEncoding=").append(getDefaultEncoding()).append(lineSuffix);
|
||||
sb.append("properties=").append(properties).append(lineSuffix);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package run.halo.app.mail;
|
||||
|
||||
import org.springframework.boot.autoconfigure.mail.MailProperties;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Java mail sender factory.
|
||||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
public class MailSenderFactory {
|
||||
|
||||
/**
|
||||
* Get mail sender.
|
||||
*
|
||||
* @param mailProperties mail properties must not be null
|
||||
* @return java mail sender
|
||||
*/
|
||||
@NonNull
|
||||
public JavaMailSender getMailSender(@NonNull MailProperties mailProperties) {
|
||||
Assert.notNull(mailProperties, "Mail properties must not be null");
|
||||
|
||||
// create mail sender
|
||||
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
|
||||
// set properties
|
||||
setProperties(mailSender, mailProperties);
|
||||
|
||||
return mailSender;
|
||||
}
|
||||
|
||||
private void setProperties(@NonNull JavaMailSenderImpl mailSender, @NonNull MailProperties mailProperties) {
|
||||
mailSender.setHost(mailProperties.getHost());
|
||||
mailSender.setPort(mailProperties.getPort());
|
||||
mailSender.setUsername(mailProperties.getUsername());
|
||||
mailSender.setPassword(mailProperties.getPassword());
|
||||
mailSender.setProtocol(mailProperties.getProtocol());
|
||||
mailSender.setDefaultEncoding(mailProperties.getDefaultEncoding().name());
|
||||
|
||||
if (!CollectionUtils.isEmpty(mailProperties.getProperties())) {
|
||||
Properties properties = new Properties();
|
||||
properties.putAll(mailProperties.getProperties());
|
||||
mailSender.setJavaMailProperties(properties);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package run.halo.app.service;
|
||||
package run.halo.app.mail;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -17,7 +17,7 @@ public interface MailService {
|
|||
* @param subject subject
|
||||
* @param content content
|
||||
*/
|
||||
void sendMail(String to, String subject, String content);
|
||||
void sendTextMail(String to, String subject, String content);
|
||||
|
||||
/**
|
||||
* Send a email with html
|
||||
|
@ -36,7 +36,12 @@ public interface MailService {
|
|||
* @param subject subject
|
||||
* @param content content
|
||||
* @param templateName template name
|
||||
* @param attachFilename attachment path
|
||||
* @param attachFilePath attachment full path name
|
||||
*/
|
||||
void sendAttachMail(String to, String subject, Map<String, Object> content, String templateName, String attachFilename);
|
||||
void sendAttachMail(String to, String subject, Map<String, Object> content, String templateName, String attachFilePath);
|
||||
|
||||
/**
|
||||
* Test email server connection.
|
||||
*/
|
||||
void testConnection();
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package run.halo.app.mail;
|
||||
|
||||
import freemarker.template.Template;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
|
||||
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
||||
import run.halo.app.event.options.OptionUpdatedEvent;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Mail service implementation.
|
||||
*
|
||||
* @author ryanwang
|
||||
* @author johnniang
|
||||
* @date 2019-03-17
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MailServiceImpl extends AbstractMailService implements ApplicationListener<OptionUpdatedEvent> {
|
||||
|
||||
private final FreeMarkerConfigurer freeMarker;
|
||||
|
||||
public MailServiceImpl(FreeMarkerConfigurer freeMarker,
|
||||
OptionService optionService) {
|
||||
super(optionService);
|
||||
this.freeMarker = freeMarker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTextMail(String to, String subject, String content) {
|
||||
sendMailTemplate(true, messageHelper -> {
|
||||
messageHelper.setSubject(subject);
|
||||
messageHelper.setTo(to);
|
||||
messageHelper.setText(content);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTemplateMail(String to, String subject, Map<String, Object> content, String templateName) {
|
||||
sendMailTemplate(true, messageHelper -> {
|
||||
// build message content with freemarker
|
||||
Template template = freeMarker.getConfiguration().getTemplate(templateName);
|
||||
String contentResult = FreeMarkerTemplateUtils.processTemplateIntoString(template, content);
|
||||
|
||||
messageHelper.setSubject(subject);
|
||||
messageHelper.setTo(to);
|
||||
messageHelper.setText(contentResult, true);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAttachMail(String to, String subject, Map<String, Object> content, String templateName, String attachFilePath) {
|
||||
sendMailTemplate(true, (messageHelper) -> {
|
||||
messageHelper.setSubject(subject);
|
||||
messageHelper.setTo(to);
|
||||
Path attachmentPath = Paths.get(attachFilePath);
|
||||
messageHelper.addAttachment(attachmentPath.getFileName().toString(), attachmentPath.toFile());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testConnection() {
|
||||
super.testConnection();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(OptionUpdatedEvent event) {
|
||||
// clear the cached java mail sender
|
||||
clearCache();
|
||||
}
|
||||
}
|
|
@ -19,6 +19,41 @@ import java.util.Map;
|
|||
*/
|
||||
public interface PropertyEnum extends ValueEnum<String> {
|
||||
|
||||
|
||||
/**
|
||||
* Get property type.
|
||||
*
|
||||
* @return property type
|
||||
*/
|
||||
Class<?> getType();
|
||||
|
||||
/**
|
||||
* Default value.
|
||||
*
|
||||
* @return default value
|
||||
*/
|
||||
@Nullable
|
||||
String defaultValue();
|
||||
|
||||
/**
|
||||
* Default value with given type.
|
||||
*
|
||||
* @param propertyType property type must not be null
|
||||
* @param <T> property type
|
||||
* @return default value with given type
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T defaultValue(Class<T> propertyType) {
|
||||
// Get default value
|
||||
String defaultValue = defaultValue();
|
||||
if (defaultValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert to the given type
|
||||
return PropertyEnum.convertTo(defaultValue, propertyType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to value with corresponding type
|
||||
*
|
||||
|
@ -173,17 +208,4 @@ public interface PropertyEnum extends ValueEnum<String> {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property type.
|
||||
*
|
||||
* @return property type
|
||||
*/
|
||||
Class<?> getType();
|
||||
|
||||
/**
|
||||
* Default value.
|
||||
*
|
||||
* @return default value
|
||||
*/
|
||||
String defaultValue();
|
||||
}
|
||||
|
|
|
@ -196,6 +196,18 @@ public interface OptionService extends CrudService<Option, Integer> {
|
|||
*/
|
||||
<T> T getByPropertyOrDefault(@NonNull PropertyEnum property, @NonNull Class<T> propertyType, T defaultValue);
|
||||
|
||||
/**
|
||||
* Gets property value by blog property.
|
||||
* <p>
|
||||
* Default value from property default value.
|
||||
*
|
||||
* @param property blog property must not be null
|
||||
* @param propertyType property type must not be null
|
||||
* @param <T> property type
|
||||
* @return property value
|
||||
*/
|
||||
<T> T getByPropertyOrDefault(@NonNull PropertyEnum property, @NonNull Class<T> propertyType);
|
||||
|
||||
/**
|
||||
* Gets property value by blog property.
|
||||
*
|
||||
|
|
|
@ -18,6 +18,7 @@ import run.halo.app.event.logger.LogEvent;
|
|||
import run.halo.app.exception.BadRequestException;
|
||||
import run.halo.app.exception.NotFoundException;
|
||||
import run.halo.app.exception.ServiceException;
|
||||
import run.halo.app.mail.MailService;
|
||||
import run.halo.app.model.dto.EnvironmentDTO;
|
||||
import run.halo.app.model.dto.StatisticDTO;
|
||||
import run.halo.app.model.entity.User;
|
||||
|
@ -228,7 +229,7 @@ public class AdminServiceImpl implements AdminService {
|
|||
|
||||
// Send email to administrator.
|
||||
String content = "您正在进行密码重置操作,如不是本人操作,请尽快做好相应措施。密码重置验证码如下(五分钟有效):\n" + code;
|
||||
mailService.sendMail(param.getEmail(), "找回密码验证码", content);
|
||||
mailService.sendTextMail(param.getEmail(), "找回密码验证码", content);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
package run.halo.app.service.impl;
|
||||
|
||||
import cn.hutool.core.text.StrBuilder;
|
||||
import freemarker.template.Template;
|
||||
import io.github.biezhi.ome.OhMyEmail;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
|
||||
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
||||
import run.halo.app.exception.EmailException;
|
||||
import run.halo.app.model.properties.EmailProperties;
|
||||
import run.halo.app.service.MailService;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Mail service implementation.
|
||||
*
|
||||
* @author ryanwang
|
||||
* @date 2019-03-17
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MailServiceImpl implements MailService {
|
||||
|
||||
private final FreeMarkerConfigurer freeMarker;
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
public MailServiceImpl(FreeMarkerConfigurer freeMarker,
|
||||
OptionService optionService) {
|
||||
this.freeMarker = freeMarker;
|
||||
this.optionService = optionService;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMail(String to, String subject, String content) {
|
||||
loadConfig();
|
||||
|
||||
String fromUsername = optionService.getByPropertyOfNonNull(EmailProperties.FROM_NAME).toString();
|
||||
|
||||
try {
|
||||
OhMyEmail.subject(subject)
|
||||
.from(fromUsername)
|
||||
.to(to)
|
||||
.text(content)
|
||||
.send();
|
||||
} catch (Exception e) {
|
||||
log.debug("Email properties: to username: [{}], from username: [{}], subject: [{}], content: [{}]",
|
||||
to, fromUsername, subject, content);
|
||||
throw new EmailException("发送邮件到 " + to + " 失败,请检查 SMTP 服务配置是否正确", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTemplateMail(String to, String subject, Map<String, Object> content, String templateName) {
|
||||
loadConfig();
|
||||
|
||||
String fromUsername = optionService.getByPropertyOfNonNull(EmailProperties.FROM_NAME).toString();
|
||||
|
||||
try {
|
||||
StrBuilder text = new StrBuilder();
|
||||
Template template = freeMarker.getConfiguration().getTemplate(templateName);
|
||||
text.append(FreeMarkerTemplateUtils.processTemplateIntoString(template, content));
|
||||
OhMyEmail.subject(subject)
|
||||
.from(fromUsername)
|
||||
.to(to)
|
||||
.html(text.toString())
|
||||
.send();
|
||||
} catch (Exception e) {
|
||||
log.debug("Email properties: to username: [{}], from username: [{}], subject: [{}], template name: [{}], content: [{}]",
|
||||
to, fromUsername, subject, templateName, content);
|
||||
throw new EmailException("发送模板邮件到 " + to + " 失败,请检查 SMTP 服务配置是否正确", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAttachMail(String to, String subject, Map<String, Object> content, String templateName, String attachFilename) {
|
||||
loadConfig();
|
||||
|
||||
String fromUsername = optionService.getByPropertyOfNonNull(EmailProperties.FROM_NAME).toString();
|
||||
|
||||
File file = new File(attachFilename);
|
||||
|
||||
try {
|
||||
Template template = freeMarker.getConfiguration().getTemplate(templateName);
|
||||
OhMyEmail.subject(subject)
|
||||
.from(fromUsername)
|
||||
.to(to)
|
||||
.html(FreeMarkerTemplateUtils.processTemplateIntoString(template, content))
|
||||
.attach(file, file.getName())
|
||||
.send();
|
||||
} catch (Exception e) {
|
||||
log.debug("Email properties: to username: [{}], from username: [{}], subject: [{}], template name: [{}], attachment: [{}], content: [{}]",
|
||||
to, fromUsername, subject, templateName, attachFilename, content);
|
||||
throw new EmailException("发送附件邮件到 " + to + " 失败,请检查 SMTP 服务配置是否正确", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads email config.
|
||||
*/
|
||||
private void loadConfig() {
|
||||
// Get default properties
|
||||
Properties defaultProperties = OhMyEmail.defaultConfig(log.isDebugEnabled());
|
||||
|
||||
// Set smtp host
|
||||
defaultProperties.setProperty("mail.smtp.host", optionService.getByPropertyOfNonNull(EmailProperties.HOST).toString());
|
||||
defaultProperties.setProperty("mail.transport.protocol", optionService.getByPropertyOrDefault(EmailProperties.PROTOCOL, String.class, EmailProperties.PROTOCOL.defaultValue()));
|
||||
defaultProperties.setProperty("mail.smtp.port", optionService.getByPropertyOrDefault(EmailProperties.SSL_PORT, String.class, EmailProperties.SSL_PORT.defaultValue()));
|
||||
|
||||
// Config email
|
||||
OhMyEmail.config(defaultProperties,
|
||||
optionService.getByPropertyOfNonNull(EmailProperties.USERNAME).toString(),
|
||||
optionService.getByPropertyOfNonNull(EmailProperties.PASSWORD).toString());
|
||||
}
|
||||
|
||||
}
|
|
@ -322,6 +322,11 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
|
|||
return getByProperty(property, propertyType).orElse(defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getByPropertyOrDefault(PropertyEnum property, Class<T> propertyType) {
|
||||
return getByProperty(property, propertyType).orElse(property.defaultValue(propertyType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Optional<T> getByProperty(PropertyEnum property, Class<T> propertyType) {
|
||||
return getByProperty(property).map(propertyValue -> PropertyEnum.convertTo(propertyValue.toString(), propertyType));
|
||||
|
|
Loading…
Reference in New Issue