Merging feature/html-emails from CE
This commit is contained in:
		
							parent
							
								
									ae5632f8ab
								
							
						
					
					
						commit
						6ab586b0b1
					
				@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
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.JavaMailSenderImpl;
 | 
			
		||||
import org.springframework.mail.javamail.MimeMessageHelper;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
@ -44,8 +45,8 @@ import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
 | 
			
		||||
import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.PostConstruct;
 | 
			
		||||
import javax.mail.MessagingException;
 | 
			
		||||
import javax.mail.internet.MimeMessage;
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
@ -233,22 +234,38 @@ public class DefaultMailService implements MailService {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body) throws MessagingException {
 | 
			
		||||
    public void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map<String, String> images) throws ThingsboardException {
 | 
			
		||||
        if (apiUsageStateService.getApiUsageState(tenantId).isEmailSendEnabled()) {
 | 
			
		||||
            MimeMessage mailMsg = mailSender.createMimeMessage();
 | 
			
		||||
            MimeMessageHelper helper = new MimeMessageHelper(mailMsg, "UTF-8");
 | 
			
		||||
            helper.setFrom(StringUtils.isBlank(from) ? mailFrom : from);
 | 
			
		||||
            helper.setTo(to.split("\\s*,\\s*"));
 | 
			
		||||
            if (!StringUtils.isBlank(cc)) {
 | 
			
		||||
                helper.setCc(cc.split("\\s*,\\s*"));
 | 
			
		||||
            try {
 | 
			
		||||
                MimeMessage mailMsg = mailSender.createMimeMessage();
 | 
			
		||||
                boolean multipart = (images != null && !images.isEmpty());
 | 
			
		||||
                MimeMessageHelper helper = new MimeMessageHelper(mailMsg, multipart, "UTF-8");
 | 
			
		||||
                helper.setFrom(StringUtils.isBlank(from) ? mailFrom : from);
 | 
			
		||||
                helper.setTo(to.split("\\s*,\\s*"));
 | 
			
		||||
                if (!StringUtils.isBlank(cc)) {
 | 
			
		||||
                    helper.setCc(cc.split("\\s*,\\s*"));
 | 
			
		||||
                }
 | 
			
		||||
                if (!StringUtils.isBlank(bcc)) {
 | 
			
		||||
                    helper.setBcc(bcc.split("\\s*,\\s*"));
 | 
			
		||||
                }
 | 
			
		||||
                helper.setSubject(subject);
 | 
			
		||||
                helper.setText(body, isHtml);
 | 
			
		||||
 | 
			
		||||
                if (images != null && images.size() > 0) {
 | 
			
		||||
                    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());
 | 
			
		||||
                apiUsageClient.report(tenantId, ApiUsageRecordKey.EMAIL_EXEC_COUNT, 1);
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                throw handleException(e);
 | 
			
		||||
            }
 | 
			
		||||
            if (!StringUtils.isBlank(bcc)) {
 | 
			
		||||
                helper.setBcc(bcc.split("\\s*,\\s*"));
 | 
			
		||||
            }
 | 
			
		||||
            helper.setSubject(subject);
 | 
			
		||||
            helper.setText(body);
 | 
			
		||||
            mailSender.send(helper.getMimeMessage());
 | 
			
		||||
            apiUsageClient.report(tenantId, ApiUsageRecordKey.EMAIL_EXEC_COUNT, 1);
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new RuntimeException("Email sending is disabled due to API limits!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.ApiUsageStateValue;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
 | 
			
		||||
import javax.mail.MessagingException;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
public interface MailService {
 | 
			
		||||
 | 
			
		||||
@ -40,9 +40,9 @@ public interface MailService {
 | 
			
		||||
 | 
			
		||||
    void sendPasswordWasResetEmail(String loginLink, String email) throws ThingsboardException;
 | 
			
		||||
 | 
			
		||||
    void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body) throws MessagingException;
 | 
			
		||||
 | 
			
		||||
    void sendAccountLockoutEmail( String lockoutEmail, String email, Integer maxFailedLoginAttempts) throws ThingsboardException;
 | 
			
		||||
 | 
			
		||||
    void send(TenantId tenantId, String from, String to, String cc, String bcc, String subject, String body, boolean isHtml, Map<String, String> images) throws ThingsboardException;
 | 
			
		||||
 | 
			
		||||
    void sendApiFeatureStateEmail(ApiFeature apiFeature, ApiUsageStateValue stateValue, String email, ApiUsageStateMailMessage msg) throws ThingsboardException;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,8 @@ package org.thingsboard.rule.engine.mail;
 | 
			
		||||
import lombok.Builder;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@Builder
 | 
			
		||||
class EmailPojo {
 | 
			
		||||
@ -28,5 +30,7 @@ class EmailPojo {
 | 
			
		||||
    private final String bcc;
 | 
			
		||||
    private final String subject;
 | 
			
		||||
    private final String body;
 | 
			
		||||
    private final Map<String, String> images;
 | 
			
		||||
    private final boolean html;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@
 | 
			
		||||
package org.thingsboard.rule.engine.mail;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.core.JsonProcessingException;
 | 
			
		||||
import com.fasterxml.jackson.core.type.TypeReference;
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.util.StringUtils;
 | 
			
		||||
@ -27,9 +28,11 @@ import org.thingsboard.rule.engine.api.TbNodeException;
 | 
			
		||||
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.plugin.ComponentType;
 | 
			
		||||
import org.thingsboard.server.common.msg.TbMsg;
 | 
			
		||||
import org.thingsboard.server.common.msg.TbMsgMetaData;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
@ -50,6 +53,12 @@ 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;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@ -80,8 +89,14 @@ 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)));
 | 
			
		||||
        builder.subject(fromTemplate(this.config.getSubjectTemplate(), msg));
 | 
			
		||||
        builder.body(fromTemplate(this.config.getBodyTemplate(), msg));
 | 
			
		||||
        String imagesStr = msg.getMetaData().getValue(IMAGES);
 | 
			
		||||
        if (!StringUtils.isEmpty(imagesStr)) {
 | 
			
		||||
            Map<String, String> imgMap = MAPPER.readValue(imagesStr, new TypeReference<HashMap<String, String>>() {});
 | 
			
		||||
            builder.images(imgMap);
 | 
			
		||||
        }
 | 
			
		||||
        return builder.build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ public class TbMsgToEmailNodeConfiguration implements NodeConfiguration {
 | 
			
		||||
    private String bccTemplate;
 | 
			
		||||
    private String subjectTemplate;
 | 
			
		||||
    private String bodyTemplate;
 | 
			
		||||
    private String isHtmlTemplate;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public TbMsgToEmailNodeConfiguration defaultConfiguration() {
 | 
			
		||||
@ -35,6 +36,7 @@ public class TbMsgToEmailNodeConfiguration implements NodeConfiguration {
 | 
			
		||||
        configuration.toTemplate = "${userEmail}";
 | 
			
		||||
        configuration.subjectTemplate = "Device ${deviceType} temperature high";
 | 
			
		||||
        configuration.bodyTemplate = "Device ${deviceName} has high temperature ${temp}";
 | 
			
		||||
        configuration.isHtmlTemplate = "${isHtml}";
 | 
			
		||||
        return configuration;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -18,6 +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;
 | 
			
		||||
@ -26,12 +27,13 @@ import org.thingsboard.rule.engine.api.TbNode;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeException;
 | 
			
		||||
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.ApiUsageRecordKey;
 | 
			
		||||
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;
 | 
			
		||||
@ -89,10 +91,11 @@ public class TbSendEmailNode implements TbNode {
 | 
			
		||||
    private void sendEmail(TbContext ctx, EmailPojo email) throws Exception {
 | 
			
		||||
        if (this.config.isUseSystemSmtpSettings()) {
 | 
			
		||||
            ctx.getMailService().send(ctx.getTenantId(), email.getFrom(), email.getTo(), email.getCc(),
 | 
			
		||||
                    email.getBcc(), email.getSubject(), email.getBody());
 | 
			
		||||
                    email.getBcc(), email.getSubject(), email.getBody(), email.isHtml(), email.getImages());
 | 
			
		||||
        } else {
 | 
			
		||||
            MimeMessage mailMsg = mailSender.createMimeMessage();
 | 
			
		||||
            MimeMessageHelper helper = new MimeMessageHelper(mailMsg, "UTF-8");
 | 
			
		||||
            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())) {
 | 
			
		||||
@ -102,7 +105,18 @@ public class TbSendEmailNode implements TbNode {
 | 
			
		||||
                helper.setBcc(email.getBcc().split("\\s*,\\s*"));
 | 
			
		||||
            }
 | 
			
		||||
            helper.setSubject(email.getSubject());
 | 
			
		||||
            helper.setText(email.getBody());
 | 
			
		||||
            helper.setText(email.getBody(), email.isHtml());
 | 
			
		||||
            if (email.getImages() != null && email.getImages().size() > 0) {
 | 
			
		||||
                Map<String, String> 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());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user