001package ca.uhn.fhir.jpa.subscription.module.subscriber.email; 002 003/*- 004 * #%L 005 * HAPI FHIR Subscription Server 006 * %% 007 * Copyright (C) 2014 - 2020 University Health Network 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.rest.api.Constants; 024import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 025import ca.uhn.fhir.util.StopWatch; 026import org.apache.commons.lang3.StringUtils; 027import org.apache.commons.lang3.Validate; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030import org.springframework.mail.javamail.JavaMailSenderImpl; 031import org.thymeleaf.context.Context; 032import org.thymeleaf.spring5.SpringTemplateEngine; 033import org.thymeleaf.spring5.dialect.SpringStandardDialect; 034import org.thymeleaf.templatemode.TemplateMode; 035import org.thymeleaf.templateresolver.StringTemplateResolver; 036 037import javax.annotation.PostConstruct; 038import javax.mail.Message; 039import javax.mail.MessagingException; 040import javax.mail.internet.MimeMessage; 041import java.util.ArrayList; 042import java.util.Date; 043import java.util.List; 044 045import static org.apache.commons.lang3.StringUtils.isNotBlank; 046import static org.apache.commons.lang3.StringUtils.trim; 047 048public class JavaMailEmailSender implements IEmailSender { 049 050 private static final Logger ourLog = LoggerFactory.getLogger(JavaMailEmailSender.class); 051 private String mySmtpServerHostname; 052 private int mySmtpServerPort = 25; 053 private JavaMailSenderImpl mySender; 054 private String mySmtpServerUsername; 055 private String mySmtpServerPassword; 056 057 public String getSmtpServerHostname() { 058 return mySmtpServerHostname; 059 } 060 061 /** 062 * Set the SMTP server host to use for outbound mail 063 */ 064 public void setSmtpServerHostname(String theSmtpServerHostname) { 065 mySmtpServerHostname = theSmtpServerHostname; 066 } 067 068 public String getSmtpServerPassword() { 069 return mySmtpServerPassword; 070 } 071 072 public void setSmtpServerPassword(String theSmtpServerPassword) { 073 mySmtpServerPassword = theSmtpServerPassword; 074 } 075 076 public int getSmtpServerPort() { 077 return mySmtpServerPort; 078 } 079 080 /** 081 * Set the SMTP server port to use for outbound mail 082 */ 083 public void setSmtpServerPort(int theSmtpServerPort) { 084 mySmtpServerPort = theSmtpServerPort; 085 } 086 087 public String getSmtpServerUsername() { 088 return mySmtpServerUsername; 089 } 090 091 public void setSmtpServerUsername(String theSmtpServerUsername) { 092 mySmtpServerUsername = theSmtpServerUsername; 093 } 094 095 @Override 096 public void send(EmailDetails theDetails) { 097 String subscriptionId = theDetails.getSubscription().toUnqualifiedVersionless().getValue(); 098 StopWatch sw = new StopWatch(); 099 100 StringTemplateResolver templateResolver = new StringTemplateResolver(); 101 templateResolver.setTemplateMode(TemplateMode.TEXT); 102 103 SpringStandardDialect dialect = new SpringStandardDialect(); 104 dialect.setEnableSpringELCompiler(true); 105 106 SpringTemplateEngine engine = new SpringTemplateEngine(); 107 engine.setDialect(dialect); 108 engine.setEnableSpringELCompiler(true); 109 engine.setTemplateResolver(templateResolver); 110 111 Context context = new Context(); 112 113 String body = engine.process(theDetails.getBodyTemplate(), context); 114 String subject = engine.process(theDetails.getSubjectTemplate(), context); 115 116 MimeMessage email = mySender.createMimeMessage(); 117 118 String from = trim(theDetails.getFrom()); 119 ourLog.info("Sending email for subscription {} from [{}] to recipients: [{}]", subscriptionId, from, theDetails.getTo()); 120 121 try { 122 email.setFrom(from); 123 email.setRecipients(Message.RecipientType.TO, toTrimmedCommaSeparatedString(theDetails.getTo())); 124 email.setSubject(subject); 125 email.setText(body); 126 email.setSentDate(new Date()); 127 email.addHeader("X-FHIR-Subscription", subscriptionId); 128 } catch (MessagingException e) { 129 throw new InternalErrorException("Failed to create email message", e); 130 } 131 132 mySender.send(email); 133 134 ourLog.info("Done sending email (took {}ms)", sw.getMillis()); 135 } 136 137 @PostConstruct 138 public void start() { 139 Validate.notBlank(mySmtpServerHostname, "No SMTP host defined"); 140 141 mySender = new JavaMailSenderImpl(); 142 mySender.setHost(getSmtpServerHostname()); 143 mySender.setPort(getSmtpServerPort()); 144 mySender.setUsername(getSmtpServerUsername()); 145 mySender.setPassword(getSmtpServerPassword()); 146 mySender.setDefaultEncoding(Constants.CHARSET_UTF8.name()); 147 } 148 149 private static String toTrimmedCommaSeparatedString(List<String> theTo) { 150 List<String> to = new ArrayList<>(); 151 for (String next : theTo) { 152 if (isNotBlank(next)) { 153 to.add(next); 154 } 155 } 156 157 return StringUtils.join(to, ","); 158 } 159}