Commit c4a30006 by Jan Hrabal

wip

parent a654450a
......@@ -90,12 +90,6 @@
<scope>provided</scope>
</dependency>
<!-- email configuration -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- handlebars -->
<dependency>
<groupId>com.github.jknack</groupId>
......
package com.jh.boot;
import com.jh.boot.template.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import com.jh.boot.email.LocalEmailService;
import com.jh.boot.security.utils.TemplateEmailAuthServiceListener;
import com.jh.boot.template.HibernateLoaderTemplateService;
import com.jh.boot.template.HibernateTemplateLoader;
import com.jh.boot.template.TemplateEngine;
import com.jh.boot.template.TemplateLoader;
import com.jh.boot.template.TemplateService;
import com.jh.boot.template.TemplateValuesConfig;
import com.jh.boot.template.handlebars.HandlebarsTemplateEngine;
public class JhBootApplication {
@Bean
@ConditionalOnProperty(value = "email.local.enabled", havingValue = "true", matchIfMissing = true)
public LocalEmailService emailService() {
return new LocalEmailService();
}
// @Bean
// @ConditionalOnProperty(value = "email.local.enabled", havingValue = "true", matchIfMissing = true)
// public LocalEmailService emailService() {
// return new LocalEmailService();
// }
@Bean
@ConditionalOnProperty(value = "auth.listener.email.enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnProperty(value = "auth.listener.email.enabled", havingValue = "true", matchIfMissing = false)
public TemplateEmailAuthServiceListener authServiceListener() {
return new TemplateEmailAuthServiceListener();
}
......
......@@ -2,64 +2,43 @@ package com.jh.boot.email;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.jh.boot.jpa.AbstractIdEntity;
/**
* The Class Email.
*/
@Entity
@Table(name = "EMAIL")
public class Email extends AbstractIdEntity {
public class Email {
/** The locked. */
@Column(name = "LOCKED")
private Boolean locked;
/** The email from. */
@Column(name = "EMAIL_FROM")
private String emailFrom;
/** The recipients. */
@OneToMany(mappedBy = "email", cascade = CascadeType.ALL)
private Set<EmailRecipient> recipients;
/** The subject. */
@Column(name = "SUBJECT")
private String subject;
/** The text. */
@Column(name = "TEXT_CONTENT")
private String text;
/** The html. */
@Column(name = "HTML_CONTENT")
private String html;
/** The to be sent. */
@Column(name = "TO_BE_SENT")
private Boolean toBeSent;
/** The status. */
@Column(name = "STATUS")
private String status;
/** The error. */
@Column(name = "ERROR")
private String error;
/** The receipt. */
@Column(name = "RECEIPT")
private Boolean receipt;
/** The attachments. */
@OneToMany(mappedBy = "email", cascade = CascadeType.ALL)
private Set<EmailAttachment> attachments;
/**
......
......@@ -7,45 +7,24 @@ package com.jh.boot.email;
import java.util.Base64;
import java.util.Base64.Encoder;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.jh.boot.jpa.AbstractIdEntity;
/**
* The Class EmailAttachment.
*
* @author Jan Hrabal
*/
@Entity
@Table(name = "EMAIL_ATTACHMENT")
public class EmailAttachment extends AbstractIdEntity {
public class EmailAttachment {
/** The name. */
@Column(name = "NAME")
private String name;
/** The mime type. */
@Column(name = "MIME_TYPE")
private String mimeType;
/** The data. */
//base 64
@Column(name = "DATA")
private String data;
/** The email. */
@ManyToOne @org.hibernate.annotations.NotFound(action = org.hibernate.annotations.NotFoundAction.IGNORE)
@JoinColumn(name = "EMAIL_ID")
@JsonIgnore
private Email email;
/** The cid. */
@Column(name = "CID")
private String cid;
/**
......@@ -118,24 +97,6 @@ public class EmailAttachment extends AbstractIdEntity {
}
/**
* Gets the email.
*
* @return the email
*/
public Email getEmail() {
return email;
}
/**
* Sets the email.
*
* @param email the new email
*/
public void setEmail(Email email) {
this.email = email;
}
/**
* Gets the cid.
*
* @return the cid
......
package com.jh.boot.email;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* The Class EmailConfig.
*/
@Configuration
@EnableScheduling
public class EmailConfig {
}
package com.jh.boot.email;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.jh.boot.jpa.AbstractIdEntity;
/**
* The Class EmailRecipient.
*/
@Entity
@Table(name = "EMAIL_RECIPIENT")
public class EmailRecipient extends AbstractIdEntity {
/** The email. */
@JsonIgnore
@ManyToOne @org.hibernate.annotations.NotFound(action = org.hibernate.annotations.NotFoundAction.IGNORE)
@JoinColumn(name = "EMAIL_ID")
private Email email;
public class EmailRecipient {
/** The address. */
@Column(name = "ADDRESS")
private String address;
/** The recipient type. */
@Column(name = "RECIPIENT_TYPE")
@Enumerated(EnumType.STRING)
private RecipientType recipientType;
/**
......@@ -51,25 +29,6 @@ public class EmailRecipient extends AbstractIdEntity {
this.recipientType = recipientType;
}
/**
* Gets the email.
*
* @return the email
*/
public Email getEmail() {
return email;
}
/**
* Sets the email.
*
* @param email the new email
*/
public void setEmail(Email email) {
this.email = email;
}
/**
* Gets the address.
*
......
package com.jh.boot.email;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.persistence.Query;
import org.hibernate.query.NativeQuery;
import org.springframework.stereotype.Repository;
import com.jh.boot.jpa.AbstractHibernateRepository;
/**
* The Class EmailRepository.
*/
@Repository
public class EmailRepository extends AbstractHibernateRepository {
/**
* Fetch emails to send.
*
* @return the list
*/
@SuppressWarnings("unchecked")
public List<Email> fetchEmailsToSend() {
String sql = "select ID from EMAIL where LOCKED<>true and TO_BE_SENT=true for update limit 100";
NativeQuery<Number> nq = nativeQuery(sql);
//fetch ids
List<Number> result = nq.getResultList();
List<Long> ids = result.stream().map((n) -> n.longValue()).collect(Collectors.toList());
if (!ids.isEmpty()) {
lockEmails(ids, true);
Query q = entityManager.createQuery("select distinct e from Email e left join fetch e.attachments left join fetch e.recipients where e.id in (:ids)");
q.setParameter("ids", ids);
return q.getResultList();
}
return Collections.emptyList();
}
/**
* Lock emails.
*
* @param ids the ids
* @param locked the locked
*/
public void lockEmails(Collection<Long> ids, boolean locked) {
if (ids == null || ids.isEmpty()) {
return;
}
String hql = "update Email e set e.locked=:locked where e.id in (:ids)";
Query q = entityManager.createQuery(hql);
q.setParameter("locked", locked);
q.setParameter("ids", ids);
q.executeUpdate();
}
}
package com.jh.boot.email;
/**
* The Interface EmailService.
*/
......
package com.jh.boot.email;
import org.springframework.context.annotation.Bean;
//TODO
public class JhMailConfig {
@Bean
public EmailService emailService() {
return new LocalEmailService();
}
}
package com.jh.boot.email;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Objects;
import javax.mail.internet.MimeMessage;
import javax.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.StringUtils;
/**
* The Class LocalEmailService.
*/
public class LocalEmailService implements EmailService {
/** The Constant LOG. */
private static final Logger LOG = LoggerFactory.getLogger(LocalEmailService.class);
/** The repo. */
@Autowired
private EmailRepository repo;
/** The mail sender. */
@Autowired
private JavaMailSender mailSender;
/** The email sender address. */
@Value("${email.sender.from:}")
private String emailSenderAddress;
/**
* @param email
* @return
* @see com.jh.module.email.EmailService#sendEmail(com.jh.module.email.Email)
*/
@Override
@Transactional
public Email sendEmail(Email email) {
email.setToBeSent(true);
email.setLocked(false);
if (!StringUtils.hasText(email.getEmailFrom())) {
email.setEmailFrom(emailSenderAddress);
}
if (email.getRecipients() != null) {
for (EmailRecipient er : email.getRecipients()) {
er.setEmail(email);
}
}
if (email.getAttachments() != null) {
for (EmailAttachment ea : email.getAttachments()) {
ea.setEmail(email);
}
}
repo.save(email);
//TODO
doSendEmail(email);
return email;
}
// @Scheduled(fixedDelayString = "${localEmail.scheduled.interval.ms:120000}")
// @Transactional
// public void scheduled() {
// List<Email> emails = repo.fetchEmailsToSend();
// if (emails == null || emails.isEmpty()) {
// return;
// }
// LOG.info("Going to send {} emails", emails.size());
// for (Email email : emails) {
// doSendEmail(email);
// }
// }
/**
* TODO.
*
* @param email the email
*/
private void doSendEmail(Email email) {
MimeMessage msg = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(msg, true);
//send receipt?
if (Objects.equals(email.getReceipt(), true)) {
msg.addHeader("Disposition-Notification-To", email.getEmailFrom());
}
//TODO add tracking-number
msg.addHeader("X-Email-RefId", String.valueOf(email.getId()));
//use properly configured (reverse DNS) sender address?
if (StringUtils.hasText(emailSenderAddress)) {
helper.setFrom(emailSenderAddress);
if (StringUtils.hasText(email.getFrom())) {
helper.setReplyTo(email.getFrom());
}
} else {
helper.setFrom(email.getFrom());
}
List<String> to = new ArrayList<>();
List<String> cc = new ArrayList<>();
List<String> bcc = new ArrayList<>();
if (email.getRecipients() != null) {
for (EmailRecipient r : email.getRecipients()) {
RecipientType rt = r.getRecipientType();
switch(rt) {
case BCC:
bcc.add(r.getAddress());
break;
case CC:
cc.add(r.getAddress());
break;
case TO:
default:
to.add(r.getAddress());
}
}
}
String[] s = new String[0];
helper.setTo(to.toArray(s));
helper.setCc(cc.toArray(s));
helper.setBcc(bcc.toArray(s));
helper.setSubject(email.getSubject());
helper.setText(email.getText());
if (StringUtils.hasText(email.getHtml())) {
helper.setText(email.getHtml(), true);
}
if (email.getAttachments() != null) {
for (EmailAttachment a : email.getAttachments()) {
if (a.getData() != null) {
byte[] bytes = Base64.getDecoder().decode(a.getData().getBytes());
if (StringUtils.hasText(a.getCid())) {
helper.addInline(a.getCid(), new ByteArrayResource(bytes), a.getMimeType());
} else {
helper.addAttachment(a.getName(), new ByteArrayResource(bytes), a.getMimeType());
}
}
}
}
mailSender.send(msg);
email.setStatus("SENT");
} catch (Exception e) {
e.printStackTrace();
email.setStatus("FAILED");
email.setError(e.getMessage());
}
email.setToBeSent(false);
email.setLocked(false);
}
}
......@@ -11,6 +11,7 @@ import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
/**
* The Class RestEmailService.
*/
......@@ -49,7 +50,7 @@ public class RestEmailService implements EmailService {
/**
* {@inheritDoc}
* @see com.jh.module.email.EmailService#sendEmail(com.jh.module.email.Email)
* @see com.jh.module.email.EmailService#sendEmail(com.jh.emailer.model.email.Email)
*/
@Override
public Email sendEmail(Email email) {
......
......@@ -16,7 +16,6 @@ import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.hibernate.query.NativeQuery;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment