001/* 002 * Copyright 2021 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.plugins.joboffer.workflow; 017 018import java.io.IOException; 019import java.io.InputStreamReader; 020import java.io.Reader; 021import java.util.ArrayList; 022import java.util.HashMap; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.components.ContextHelper; 030import org.apache.cocoon.environment.Request; 031import org.apache.commons.io.IOUtils; 032import org.apache.commons.lang3.StringUtils; 033import org.apache.excalibur.source.Source; 034 035import org.ametys.cms.data.ContentValue; 036import org.ametys.cms.repository.Content; 037import org.ametys.cms.repository.WorkflowAwareContent; 038import org.ametys.core.ui.mail.StandardMailBodyHelper; 039import org.ametys.core.ui.mail.StandardMailBodyHelper.MailBodyBuilder; 040import org.ametys.core.user.User; 041import org.ametys.core.user.UserIdentity; 042import org.ametys.core.util.mail.SendMailHelper; 043import org.ametys.plugins.joboffer.JobOfferConstants; 044import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 045import org.ametys.runtime.config.Config; 046import org.ametys.runtime.i18n.I18nizableText; 047import org.ametys.web.WebHelper; 048import org.ametys.web.renderingcontext.RenderingContext; 049import org.ametys.web.renderingcontext.RenderingContextHandler; 050import org.ametys.web.repository.content.WebContent; 051import org.ametys.web.repository.site.Site; 052import org.ametys.web.workflow.SendMailFunction; 053 054import com.opensymphony.workflow.WorkflowException; 055 056import jakarta.mail.MessagingException; 057 058/** 059 * OS workflow function to send mail to person(s) in charge when a new application was submitted. 060 */ 061public class SendMailToPersonInChargeFunction extends SendMailFunction 062{ 063 private RenderingContextHandler _renderingContextHandler; 064 065 @Override 066 public void service(ServiceManager smanager) throws ServiceException 067 { 068 super.service(smanager); 069 _renderingContextHandler = (RenderingContextHandler) smanager.lookup(RenderingContextHandler.ROLE); 070 } 071 072 073 @Override 074 protected Set<UserIdentity> _getUsers(WorkflowAwareContent content, Set<String> rights) throws WorkflowException 075 { 076 if (content.hasDefinition(JobOfferConstants.JOB_APPLICATION_ATTRIBUTE_PATH_PERSON_IN_CHARGE)) 077 { 078 UserIdentity[] personIncharge = content.getValue(JobOfferConstants.JOB_APPLICATION_ATTRIBUTE_PATH_PERSON_IN_CHARGE); 079 return personIncharge != null ? Set.of(personIncharge) : Set.of(); 080 } 081 082 return Set.of(); 083 } 084 085 086 087 @Override 088 protected String getSender(Map transientVars, WorkflowAwareContent content) throws WorkflowException 089 { 090 if (content instanceof WebContent) 091 { 092 Site site = ((WebContent) content).getSite(); 093 return site.getValue("site-mail-from", false, Config.getInstance().getValue("smtp.mail.from")); 094 } 095 else 096 { 097 return Config.getInstance().getValue("smtp.mail.from"); 098 } 099 } 100 101 @Override 102 protected List<String> getSubjectI18nParams(User user, WorkflowAwareContent content) 103 { 104 ContentValue value = content.getValue(JobOfferConstants.JOB_APPLICATION_ATTRIBUTE_PATH_JOB_OFFER); 105 Content jobOffer = value.getContent(); 106 107 List<String> i18nParams = new ArrayList<>(); 108 i18nParams.add(jobOffer.getTitle()); // {0} 109 i18nParams.add(jobOffer.getValue(JobOfferConstants.JOB_OFFER_ATTRIBUTE_PATH_REF_ID, false, "")); // {1} 110 111 return i18nParams; 112 } 113 114 @Override 115 protected String getMailBody(String subjectI18nKey, String bodyI18nKey, User user, WorkflowAwareContent content, Map transientVars) 116 { 117 Source src = null; 118 119 Request request = _getRequest(); 120 String currentWorkspace = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 121 RenderingContext currentContext = _renderingContextHandler.getRenderingContext(); 122 123 try 124 { 125 // Force default workspace and BACK rendering context to resolve uri (application contents are never published in live) 126 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, "default"); 127 _renderingContextHandler.setRenderingContext(RenderingContext.PREVIEW); 128 129 request.setAttribute("_baseServerPath", _getRequestUri()); 130 131 ContentValue jobOffer = content.getValue(JobOfferConstants.JOB_APPLICATION_ATTRIBUTE_PATH_JOB_OFFER); 132 Content jobOfferContent = jobOffer.getContent(); 133 134 Site site = _getSite(content); 135 String jobApplicationUri = _getContentUri(content, null, site); 136 137 List<String> i18nParams = List.of(jobOfferContent.getTitle(), jobOfferContent.getValue(JobOfferConstants.JOB_OFFER_ATTRIBUTE_PATH_REF_ID, false, StringUtils.EMPTY)); 138 139 MailBodyBuilder bodyBuilder = StandardMailBodyHelper.newHTMLBody() 140 .withTitle(getMailSubject(subjectI18nKey, user, content, transientVars)) 141 .addMessage(new I18nizableText("plugin.job-offer", "PLUGINS_JOB_OFFER_WORKFLOW_MAIL_BODY_INTRO", i18nParams)) 142 .addMessage(new I18nizableText("plugin.job-offer", "PLUGINS_JOB_OFFER_WORKFLOW_MAIL_BODY_JOB_APPLICATION_LINK", List.of(jobApplicationUri))) 143 .addMessage(new I18nizableText("plugin.job-offer", "PLUGINS_JOB_OFFER_WORKFLOW_MAIL_BODY_TOOL_LINK", List.of(_getToolUri(site)))) 144 .withLink(jobApplicationUri, new I18nizableText("plugin.job-offer", "PLUGINS_JOB_OFFER_WORKFLOW_MAIL_BODY_JOB_APPLICATION_LINK_TITLE")); 145 146 String uri = "cocoon:/apply/mail.html"; 147 Map<String, Object> parameters = new HashMap<>(); 148 parameters.put("content", content); 149 parameters.put("uriPrefix", _getRequestUri()); 150 parameters.put("siteName", _getSite(content).getName()); 151 152 src = _sourceResolver.resolveURI(uri, null, parameters); 153 Reader reader = new InputStreamReader(src.getInputStream(), "UTF-8"); 154 String details = IOUtils.toString(reader); 155 156 bodyBuilder.withDetails(new I18nizableText("plugin.job-offer", "PLUGINS_JOB_OFFER_WORKFLOW_MAIL_BODY_JOB_APPLICATION"), details, false); 157 158 return bodyBuilder.build(); 159 } 160 catch (IOException e) 161 { 162 _logger.warn("Failed to get HTML body for mail notification for new application " + content.getId(), e); 163 return null; 164 } 165 finally 166 { 167 _sourceResolver.release(src); 168 169 _renderingContextHandler.setRenderingContext(currentContext); 170 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWorkspace); 171 } 172 } 173 174 /** 175 * Get the tool uri 176 * @param site the current site 177 * @return the tool uri 178 */ 179 protected String _getToolUri(Site site) 180 { 181 String siteName; 182 if (site != null) 183 { 184 siteName = site.getName(); 185 } 186 else 187 { 188 // fallback to the current site if no site is provided 189 siteName = WebHelper.getSiteName(ContextHelper.getRequest(_context)); 190 } 191 192 return _getRequestUri() + "/" + siteName + "/index.html?uitool=uitool-application-search,id:%27search-ui.job-applications%27"; 193 } 194 195 @Override 196 protected void _sendMails(String subject, String body, Set<String> recipients, String from) 197 { 198 if (body != null) 199 { 200 for (String recipient : recipients) 201 { 202 try 203 { 204 SendMailHelper.newMail() 205 .withSubject(subject) 206 .withHTMLBody(body) 207 .withSender(from) 208 .withRecipient(recipient) 209 .withAsync(true) 210 .sendMail(); 211 } 212 catch (MessagingException | IOException e) 213 { 214 _logger.warn("Could not send a workflow notification mail to " + recipient, e); 215 } 216 } 217 } 218 } 219 220 @Override 221 public I18nizableText getLabel() 222 { 223 return new I18nizableText("plugin.job-offer", "PLUGINS_JOB_OFFER_SEND_MAIL_TO_PERSON_IN_CHARGE_FUNCTION_LABEL"); 224 } 225 226}