001/* 002 * Copyright 2020 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.schedule; 017 018import java.util.Optional; 019 020import javax.mail.MessagingException; 021 022import org.apache.avalon.framework.activity.Initializable; 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.commons.lang3.StringUtils; 026import org.quartz.JobExecutionContext; 027 028import org.ametys.core.user.CurrentUserProvider; 029import org.ametys.core.user.User; 030import org.ametys.core.util.I18nUtils; 031import org.ametys.core.util.mail.SendMailHelper; 032import org.ametys.plugins.core.impl.schedule.AbstractStaticSchedulable; 033import org.ametys.plugins.core.user.UserHelper; 034import org.ametys.runtime.config.Config; 035import org.ametys.runtime.i18n.I18nizableText; 036 037/** 038 * Abstract schedulable that send an email at the end of the execution 039 * By default, the email is sent to the user that launched the schedulable. This behavior can be overridden thanks to the {@link #_getRecipient(JobExecutionContext)} method 040 * If this user has no email address and there is an error during the execution, an email is sent to the system administrator 041 */ 042public abstract class AbstractSendingMailSchedulable extends AbstractStaticSchedulable implements Initializable 043{ 044 /** The utils for i18n */ 045 protected I18nUtils _i18nUtils; 046 /** Mail sender */ 047 protected String _mailSender; 048 /** Sys admin mail */ 049 protected String _sysadminMail; 050 /** Current user provider */ 051 protected CurrentUserProvider _currentUserProvider; 052 /** User helper */ 053 protected UserHelper _userHelper; 054 055 @Override 056 public void service(ServiceManager manager) throws ServiceException 057 { 058 super.service(manager); 059 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 060 _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 061 _userHelper = (UserHelper) manager.lookup(UserHelper.ROLE); 062 } 063 064 public void initialize() throws Exception 065 { 066 _mailSender = Config.getInstance().getValue("smtp.mail.from"); 067 _sysadminMail = Config.getInstance().getValue("smtp.mail.sysadminto"); 068 } 069 070 @Override 071 public void execute(JobExecutionContext context) throws Exception 072 { 073 Optional<String> recipient = _getRecipient(context); 074 075 I18nizableText mailSubject = null; 076 I18nizableText mailBody = null; 077 try 078 { 079 _doExecute(context); 080 081 mailSubject = _getSuccessMailSubject(context); 082 mailBody = _getSuccessMailBody(context); 083 } 084 catch (Exception e) 085 { 086 if (recipient.isEmpty()) 087 { 088 recipient = Optional.ofNullable(_sysadminMail) 089 .filter(StringUtils::isNotEmpty); 090 } 091 092 mailSubject = _getErrorMailSubject(context); 093 mailBody = _getErrorMailBody(context, e); 094 095 throw e; 096 } 097 finally 098 { 099 if (recipient.isPresent()) 100 { 101 _sendMail(mailSubject, mailBody, recipient.get(), context); 102 } 103 } 104 } 105 106 /** 107 * Executes the schedulable. 108 * @param context the context 109 * @throws Exception if an error occurred 110 */ 111 protected abstract void _doExecute(JobExecutionContext context) throws Exception; 112 113 /** 114 * Retrieves the optional recipient of the mail 115 * @param context the context 116 * @return the optional recipient of the mail 117 */ 118 protected Optional<String> _getRecipient(JobExecutionContext context) 119 { 120 return Optional.of(_currentUserProvider) 121 .map(CurrentUserProvider::getUser) 122 .map(_userManager::getUser) 123 .map(User::getEmail) 124 .filter(StringUtils::isNotEmpty); 125 } 126 127 /** 128 * Determines if the mail body is in HTML 129 * @param context the context 130 * @return <code>true</code> if the mail body is in HTML, <code>false</code> otherwise 131 * @throws Exception If an error occurs while retrieving if mail body should be HTML 132 */ 133 protected boolean _isMailBodyInHTML(JobExecutionContext context) throws Exception 134 { 135 return false; 136 } 137 138 /** 139 * Retrieves the subject of the success mail 140 * @param context the context 141 * @return the subject of the success mail 142 * @throws Exception If an error occurs while building the mail subject 143 */ 144 protected abstract I18nizableText _getSuccessMailSubject(JobExecutionContext context) throws Exception; 145 146 /** 147 * Retrieves the body of the success mail 148 * @param context the context 149 * @return the body of the success mail 150 * @throws Exception If an error occurs while building the mail body 151 */ 152 protected abstract I18nizableText _getSuccessMailBody(JobExecutionContext context) throws Exception; 153 154 /** 155 * Retrieves the subject of the error mail 156 * @param context the context 157 * @return the subject of the error mail 158 * @throws Exception If an error occurs while building the mail subject 159 */ 160 protected abstract I18nizableText _getErrorMailSubject(JobExecutionContext context) throws Exception; 161 162 /** 163 * Retrieves the body of the error mail 164 * @param context the context 165 * @param throwable the error 166 * @return the body of the error mail 167 * @throws Exception If an error occurs while building the mail body 168 */ 169 protected abstract I18nizableText _getErrorMailBody(JobExecutionContext context, Throwable throwable) throws Exception; 170 171 /** 172 * Send an email 173 * @param subject the email's subject 174 * @param body the email's body 175 * @param recipient the recipient address 176 * @param context the context 177 */ 178 protected void _sendMail (I18nizableText subject, I18nizableText body, String recipient, JobExecutionContext context) 179 { 180 try 181 { 182 if (_isMailBodyInHTML(context)) 183 { 184 SendMailHelper.sendMail(_i18nUtils.translate(subject), _i18nUtils.translate(body), null, recipient, _mailSender); 185 } 186 else 187 { 188 SendMailHelper.sendMail(_i18nUtils.translate(subject), null, _i18nUtils.translate(body), recipient, _mailSender); 189 } 190 } 191 catch (MessagingException e) 192 { 193 if (getLogger().isWarnEnabled()) 194 { 195 getLogger().warn("Unable to send the e-mail '" + subject + "' to '" + recipient + "'", e); 196 } 197 } 198 catch (Exception e) 199 { 200 getLogger().error("An unknown error has occured while sending the mail.", e); 201 } 202 } 203}