diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java index ef4aa05bbd..755a397611 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java @@ -25,6 +25,7 @@ import org.springframework.context.MessageSource; import org.springframework.context.annotation.Lazy; import org.springframework.core.NestedRuntimeException; import org.springframework.core.io.InputStreamSource; +import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; @@ -235,9 +236,18 @@ public class DefaultMailService implements MailService { @Override public void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map images) throws ThingsboardException { + sendMail(tenantId, from, to, cc, bcc, subject, body, isHtml, images, this.mailSender); + } + + @Override + public void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map images, JavaMailSender javaMailSender) throws ThingsboardException { + sendMail(tenantId, from, to, cc, bcc, subject, body, isHtml, images, javaMailSender); + } + + private void sendMail(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map images, JavaMailSender javaMailSender) throws ThingsboardException { if (apiUsageStateService.getApiUsageState(tenantId).isEmailSendEnabled()) { try { - MimeMessage mailMsg = mailSender.createMimeMessage(); + MimeMessage mailMsg = javaMailSender.createMimeMessage(); boolean multipart = (images != null && !images.isEmpty()); MimeMessageHelper helper = new MimeMessageHelper(mailMsg, multipart, "UTF-8"); helper.setFrom(StringUtils.isBlank(from) ? mailFrom : from); @@ -251,7 +261,7 @@ public class DefaultMailService implements MailService { helper.setSubject(subject); helper.setText(body, isHtml); - if (images != null && images.size() > 0) { + if (multipart) { for (String imgId : images.keySet()) { String imgValue = images.get(imgId); String value = imgValue.replaceFirst("^data:image/[^;]*;base64,?", ""); @@ -261,7 +271,7 @@ public class DefaultMailService implements MailService { helper.addInline(imgId, iss, contentType); } } - mailSender.send(helper.getMimeMessage()); + javaMailSender.send(helper.getMimeMessage()); apiUsageClient.report(tenantId, ApiUsageRecordKey.EMAIL_EXEC_COUNT, 1); } catch (Exception e) { throw handleException(e); diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java index e125927af4..590c864787 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.api; import com.fasterxml.jackson.databind.JsonNode; +import org.springframework.mail.javamail.JavaMailSender; import org.thingsboard.server.common.data.ApiFeature; import org.thingsboard.server.common.data.ApiUsageStateMailMessage; import org.thingsboard.server.common.data.ApiUsageStateValue; @@ -44,5 +45,7 @@ public interface MailService { void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map images) throws ThingsboardException; + void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map images, JavaMailSender javaMailSender) throws ThingsboardException; + void sendApiFeatureStateEmail(ApiFeature apiFeature, ApiUsageStateValue stateValue, String email, ApiUsageStateMailMessage msg) throws ThingsboardException; } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java index c9da3cc81a..6e89140ea7 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java @@ -32,7 +32,6 @@ import org.thingsboard.server.common.msg.TbMsg; import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.regex.Pattern; import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; import static org.thingsboard.rule.engine.mail.TbSendEmailNode.SEND_EMAIL_TYPE; @@ -52,19 +51,18 @@ import static org.thingsboard.rule.engine.mail.TbSendEmailNode.SEND_EMAIL_TYPE; public class TbMsgToEmailNode implements TbNode { private static final ObjectMapper MAPPER = new ObjectMapper(); - - private static final String ATTACHMENTS = "attachments"; private static final String IMAGES = "images"; - private static final String EMAIL_TIMEZONE = "emailTimezone"; - - private static final Pattern dateVarPattern = Pattern.compile("%d\\{([^\\}]*)\\}"); private TbMsgToEmailNodeConfiguration config; + private boolean isDynamicHtmlTemplate = false; @Override public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { this.config = TbNodeUtils.convert(configuration, TbMsgToEmailNodeConfiguration.class); - } + if(this.config.getMailBodyType().equals("dynamic")) { + this.isDynamicHtmlTemplate = true; + } + } @Override public void onMsg(TbContext ctx, TbMsg msg) { @@ -89,7 +87,11 @@ public class TbMsgToEmailNode implements TbNode { builder.to(fromTemplate(this.config.getToTemplate(), msg)); builder.cc(fromTemplate(this.config.getCcTemplate(), msg)); builder.bcc(fromTemplate(this.config.getBccTemplate(), msg)); - builder.html(Boolean.parseBoolean(fromTemplate(this.config.getIsHtmlTemplate(), msg))); + if(isDynamicHtmlTemplate) { + builder.html(Boolean.parseBoolean(fromTemplate(this.config.getIsHtmlTemplate(), msg))); + } else { + builder.html(Boolean.parseBoolean(this.config.getMailBodyType())); + } builder.subject(fromTemplate(this.config.getSubjectTemplate(), msg)); builder.body(fromTemplate(this.config.getBodyTemplate(), msg)); String imagesStr = msg.getMetaData().getValue(IMAGES); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeConfiguration.java index 0ac1a379ec..7ad2391c87 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeConfiguration.java @@ -28,6 +28,7 @@ public class TbMsgToEmailNodeConfiguration implements NodeConfiguration { private String subjectTemplate; private String bodyTemplate; private String isHtmlTemplate; + private String mailBodyType; @Override public TbMsgToEmailNodeConfiguration defaultConfiguration() { @@ -37,6 +38,7 @@ public class TbMsgToEmailNodeConfiguration implements NodeConfiguration { configuration.subjectTemplate = "Device ${deviceType} temperature high"; configuration.bodyTemplate = "Device ${deviceName} has high temperature ${temp}"; configuration.isHtmlTemplate = "${isHtml}"; + configuration.mailBodyType = "dynamic"; return configuration; } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java index 543e68e1b3..fc9842da63 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java @@ -18,9 +18,7 @@ package org.thingsboard.rule.engine.mail; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.core.io.InputStreamSource; import org.springframework.mail.javamail.JavaMailSenderImpl; -import org.springframework.mail.javamail.MimeMessageHelper; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; @@ -30,10 +28,7 @@ import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; -import javax.mail.internet.MimeMessage; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.util.Map; import java.util.Properties; import static org.thingsboard.common.util.DonAsynchron.withCallback; @@ -93,31 +88,8 @@ public class TbSendEmailNode implements TbNode { ctx.getMailService().send(ctx.getTenantId(), email.getFrom(), email.getTo(), email.getCc(), email.getBcc(), email.getSubject(), email.getBody(), email.isHtml(), email.getImages()); } else { - MimeMessage mailMsg = mailSender.createMimeMessage(); - boolean multipart = (email.getImages() != null && !email.getImages().isEmpty()); - MimeMessageHelper helper = new MimeMessageHelper(mailMsg, multipart, "UTF-8"); - helper.setFrom(email.getFrom()); - helper.setTo(email.getTo().split("\\s*,\\s*")); - if (!StringUtils.isBlank(email.getCc())) { - helper.setCc(email.getCc().split("\\s*,\\s*")); - } - if (!StringUtils.isBlank(email.getBcc())) { - helper.setBcc(email.getBcc().split("\\s*,\\s*")); - } - helper.setSubject(email.getSubject()); - helper.setText(email.getBody(), email.isHtml()); - if (email.getImages() != null && email.getImages().size() > 0) { - Map images = email.getImages(); - for (String imgId : images.keySet()) { - String imgValue = images.get(imgId); - String value = imgValue.replaceFirst("^data:image/[^;]*;base64,?", ""); - byte[] bytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(value); - String contentType = helper.getFileTypeMap().getContentType(imgId); - InputStreamSource iss = () -> new ByteArrayInputStream(bytes); - helper.addInline(imgId, iss, contentType); - } - } - mailSender.send(helper.getMimeMessage()); + ctx.getMailService().send(ctx.getTenantId(), email.getFrom(), email.getTo(), email.getCc(), + email.getBcc(), email.getSubject(), email.getBody(), email.isHtml(), email.getImages(), this.mailSender); } }