View Javadoc
1   package ca.uhn.fhir.jpa.subscription.email;
2   
3   /*-
4    * #%L
5    * HAPI FHIR JPA Server
6    * %%
7    * Copyright (C) 2014 - 2018 University Health Network
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   * 
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   * 
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  import ca.uhn.fhir.util.StopWatch;
24  import ca.uhn.fhir.rest.api.Constants;
25  import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
26  import org.apache.commons.lang3.StringUtils;
27  import org.apache.commons.lang3.Validate;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  import org.springframework.mail.javamail.JavaMailSenderImpl;
31  import org.thymeleaf.context.Context;
32  import org.thymeleaf.spring4.SpringTemplateEngine;
33  import org.thymeleaf.spring4.dialect.SpringStandardDialect;
34  import org.thymeleaf.templatemode.TemplateMode;
35  import org.thymeleaf.templateresolver.StringTemplateResolver;
36  
37  import javax.annotation.PostConstruct;
38  import javax.mail.Message;
39  import javax.mail.MessagingException;
40  import javax.mail.internet.MimeMessage;
41  import java.util.ArrayList;
42  import java.util.Date;
43  import java.util.List;
44  
45  import static org.apache.commons.lang3.StringUtils.isNotBlank;
46  import static org.apache.commons.lang3.StringUtils.trim;
47  
48  public class JavaMailEmailSender implements IEmailSender {
49  
50  	private static final Logger ourLog = LoggerFactory.getLogger(JavaMailEmailSender.class);
51  	private String mySmtpServerHostname;
52  	private int mySmtpServerPort = 25;
53  	private JavaMailSenderImpl mySender;
54  	private String mySmtpServerUsername;
55  	private String mySmtpServerPassword;
56  
57  	public String getSmtpServerHostname() {
58  		return mySmtpServerHostname;
59  	}
60  
61  	/**
62  	 * Set the SMTP server host to use for outbound mail
63  	 */
64  	public void setSmtpServerHostname(String theSmtpServerHostname) {
65  		mySmtpServerHostname = theSmtpServerHostname;
66  	}
67  
68  	public String getSmtpServerPassword() {
69  		return mySmtpServerPassword;
70  	}
71  
72  	public void setSmtpServerPassword(String theSmtpServerPassword) {
73  		mySmtpServerPassword = theSmtpServerPassword;
74  	}
75  
76  	public int getSmtpServerPort() {
77  		return mySmtpServerPort;
78  	}
79  
80  	/**
81  	 * Set the SMTP server port to use for outbound mail
82  	 */
83  	public void setSmtpServerPort(int theSmtpServerPort) {
84  		mySmtpServerPort = theSmtpServerPort;
85  	}
86  
87  	public String getSmtpServerUsername() {
88  		return mySmtpServerUsername;
89  	}
90  
91  	public void setSmtpServerUsername(String theSmtpServerUsername) {
92  		mySmtpServerUsername = theSmtpServerUsername;
93  	}
94  
95  	@Override
96  	public void send(EmailDetails theDetails) {
97  		String subscriptionId = theDetails.getSubscription().toUnqualifiedVersionless().getValue();
98  		StopWatch sw = new StopWatch();
99  
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 }