Project

General

Profile

1
package eu.dnetlib.msro.notification;
2

    
3
import java.io.StringReader;
4
import java.util.Date;
5
import java.util.HashMap;
6
import java.util.Map;
7
import java.util.Properties;
8
import java.util.concurrent.BlockingQueue;
9
import java.util.concurrent.LinkedBlockingQueue;
10
import javax.mail.*;
11
import javax.mail.internet.InternetAddress;
12
import javax.mail.internet.MimeMessage;
13

    
14
import com.google.common.base.Splitter;
15
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
16
import eu.dnetlib.msro.workflows.procs.WorkflowProcess;
17
import eu.dnetlib.msro.workflows.procs.WorkflowProcess.Status;
18
import eu.dnetlib.rmi.enabling.ISLookUpService;
19
import org.antlr.stringtemplate.StringTemplate;
20
import org.apache.commons.lang3.StringUtils;
21
import org.apache.commons.logging.Log;
22
import org.apache.commons.logging.LogFactory;
23
import org.dom4j.Document;
24
import org.dom4j.io.SAXReader;
25
import org.springframework.beans.factory.annotation.Autowired;
26
import org.springframework.beans.factory.annotation.Required;
27

    
28
public class EmailDispatcher {
29

    
30
	private static final Log log = LogFactory.getLog(EmailDispatcher.class);
31
	private final BlockingQueue<Message> queue = new LinkedBlockingQueue<Message>();
32
	private String from;
33
	private String fromName;
34
	private String cc;
35
	private String smtpHost;
36
	private int smtpPort = 587;
37
	private String smtpUser;
38
	private String smtpPassword;
39
	private String baseUrl;
40
	private String infrastructure;
41
	@Autowired
42
	private UniqueServiceLocator serviceLocator;
43

    
44
	public void sendMail(final String to, final String subject, final String message) {
45
		try {
46
			final Session session = Session.getInstance(obtainProperties(), obtainAuthenticator());
47

    
48
			final MimeMessage mimeMessage = new MimeMessage(session);
49
			mimeMessage.setFrom(new InternetAddress(this.from, this.fromName));
50
			mimeMessage.setSubject(subject);
51
			mimeMessage.setContent(message, "text/html; charset=utf-8");
52
			mimeMessage.setSentDate(new Date());
53

    
54
			mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
55

    
56
			if ((this.cc != null) && !this.cc.isEmpty()) {
57
				for (final String aCC : Splitter.on(",").omitEmptyStrings().trimResults().split(getCc())) {
58
					mimeMessage.addRecipient(Message.RecipientType.CC, new InternetAddress(aCC));
59
				}
60
			}
61

    
62
			this.queue.add(mimeMessage);
63

    
64
			log.info("Mail to " + to + " in queue");
65
		} catch (final Exception e) {
66
			log.error("Error sending mail", e);
67
		}
68
	}
69

    
70
	private String applyTemplate(final String template, final WorkflowProcess proc) {
71
		final StringTemplate st = new StringTemplate(template);
72
		st.setAttribute("proc", proc);
73
		st.setAttribute("baseUrl", this.baseUrl);
74
		st.setAttribute("infrastructure", this.infrastructure);
75
		return st.toString();
76
	}
77

    
78
	public void processMailQueue() {
79
		while (true) {
80
			final Message message = this.queue.poll();
81
			if (message == null) {
82
				return;
83
			} else {
84
				try {
85
					log.info("Sending mail...");
86
					Transport.send(message);
87
					log.info("...sent");
88
				} catch (final MessagingException e) {
89
					log.error("Error sending email", e);
90
					this.queue.add(message);
91
					return;
92
				}
93
			}
94
		}
95
	}
96

    
97
	public void sendMails(final WorkflowProcess proc) {
98

    
99
		final SAXReader reader = new SAXReader();
100
		final Map<String, Document> emailProfiles = new HashMap<>();
101

    
102
		try {
103

    
104
			this.serviceLocator
105
					.getService(ISLookUpService.class)
106
					.quickSearchProfile("for $x in collection('/db/DRIVER/WorkflowDSResources/WorkflowDSResourceType') " +
107
							"where $x//RESOURCE_IDENTIFIER/@value='" + proc.getProfileId() + "' " +
108
							"or $x//RESOURCE_IDENTIFIER/@value='" + proc.getParentProfileId() + "' " +
109
							"return $x//NOTIFICATIONS/EMAIL/concat(@condition , ' @@@ ',  @messageProfileId, ' @@@ ', @address)")
110
					.forEach(s -> {
111
						final String[] arr = s.split("@@@");
112
						if (StringUtils.isNoneBlank(arr[0].trim())) {
113
							final NotificationCondition condition = NotificationCondition.valueOf(arr[0].trim());
114
							final String emailProfileId = arr[1].trim();
115
							final String to = arr[2].trim();
116

    
117
							if (condition == NotificationCondition.ALWAYS ||
118
									(condition == NotificationCondition.ONLY_FAILED && proc.getStatus() == Status.FAILURE) ||
119
									(condition == NotificationCondition.ONLY_SUCCESS && proc.getStatus() == Status.SUCCESS)) {
120
								try {
121
									if (!emailProfiles.containsKey(emailProfileId)) {
122
										final String profile = this.serviceLocator.getService(ISLookUpService.class).getResourceProfile(emailProfileId);
123
										final Document doc = reader.read(new StringReader(profile));
124
										emailProfiles.put(emailProfileId, doc);
125
									}
126
									final String subject = applyTemplate(emailProfiles.get(emailProfileId).valueOf("//SUBJECT_TEMPLATE").trim(), proc);
127
									final String message = applyTemplate(emailProfiles.get(emailProfileId).valueOf("//EMAIL_TEMPLATE").trim(), proc);
128

    
129
									sendMail(to, subject, message);
130

    
131
								} catch (final Exception e) {
132
									log.error("Error sending mail to " + to, e);
133
								}
134
							}
135
						}
136
					});
137
		} catch (final Throwable e) {
138
			log.error("Error generating sending mails for process: " + proc.getId(), e);
139
		}
140

    
141
	}
142

    
143
	private Properties obtainProperties() {
144
		final Properties props = new Properties();
145
		props.put("mail.transport.protocol", "smtp");
146
		props.put("mail.smtp.host", this.smtpHost);
147
		props.put("mail.smtp.port", this.smtpPort);
148
		props.put("mail.smtp.auth", Boolean.toString((this.smtpUser != null) && !this.smtpUser.isEmpty()));
149
		return props;
150
	}
151

    
152
	private Authenticator obtainAuthenticator() {
153
		if ((this.smtpUser == null) || this.smtpUser.isEmpty()) { return null; }
154

    
155
		return new Authenticator() {
156

    
157
			private final PasswordAuthentication authentication = new PasswordAuthentication(EmailDispatcher.this.smtpUser, EmailDispatcher.this.smtpPassword);
158

    
159
			@Override
160
			protected PasswordAuthentication getPasswordAuthentication() {
161
				return this.authentication;
162
			}
163

    
164
		};
165
	}
166

    
167
	public String getFrom() {
168
		return this.from;
169
	}
170

    
171
	@Required
172
	public void setFrom(final String from) {
173
		this.from = from;
174
	}
175

    
176
	public String getFromName() {
177
		return this.fromName;
178
	}
179

    
180
	@Required
181
	public void setFromName(final String fromName) {
182
		this.fromName = fromName;
183
	}
184

    
185
	public String getCc() {
186
		return this.cc;
187
	}
188

    
189
	@Required
190
	public void setCc(final String cc) {
191
		this.cc = cc;
192
	}
193

    
194
	public String getSmtpHost() {
195
		return this.smtpHost;
196
	}
197

    
198
	@Required
199
	public void setSmtpHost(final String smtpHost) {
200
		this.smtpHost = smtpHost;
201
	}
202

    
203
	public int getSmtpPort() {
204
		return this.smtpPort;
205
	}
206

    
207
	public void setSmtpPort(final int smtpPort) {
208
		this.smtpPort = smtpPort;
209
	}
210

    
211
	public String getSmtpUser() {
212
		return this.smtpUser;
213
	}
214

    
215
	public void setSmtpUser(final String smtpUser) {
216
		this.smtpUser = smtpUser;
217
	}
218

    
219
	public String getSmtpPassword() {
220
		return this.smtpPassword;
221
	}
222

    
223
	public void setSmtpPassword(final String smtpPassword) {
224
		this.smtpPassword = smtpPassword;
225
	}
226

    
227
	public String getBaseUrl() {
228
		return this.baseUrl;
229
	}
230

    
231
	@Required
232
	public void setBaseUrl(final String baseUrl) {
233
		this.baseUrl = baseUrl;
234
	}
235

    
236
	public String getInfrastructure() {
237
		return this.infrastructure;
238
	}
239

    
240
	@Required
241
	public void setInfrastructure(final String infrastructure) {
242
		this.infrastructure = infrastructure;
243
	}
244

    
245
}
(1-1/2)