001/* 002 * Copyright 2018 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.workspaces.members; 017 018import java.io.IOException; 019import java.io.UnsupportedEncodingException; 020import java.net.URLEncoder; 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.Date; 024import java.util.HashMap; 025import java.util.List; 026import java.util.Map; 027import java.util.Set; 028 029import javax.jcr.RepositoryException; 030 031import org.apache.avalon.framework.component.Component; 032import org.apache.avalon.framework.configuration.Configurable; 033import org.apache.avalon.framework.configuration.Configuration; 034import org.apache.avalon.framework.configuration.ConfigurationException; 035import org.apache.avalon.framework.context.Context; 036import org.apache.avalon.framework.context.ContextException; 037import org.apache.avalon.framework.context.Contextualizable; 038import org.apache.avalon.framework.service.ServiceException; 039import org.apache.avalon.framework.service.ServiceManager; 040import org.apache.avalon.framework.service.Serviceable; 041import org.apache.cocoon.components.ContextHelper; 042import org.apache.cocoon.environment.Request; 043import org.apache.commons.lang3.StringUtils; 044 045import org.ametys.cms.languages.Language; 046import org.ametys.cms.languages.LanguagesManager; 047import org.ametys.cms.transformation.xslt.ResolveURIComponent; 048import org.ametys.core.ui.Callable; 049import org.ametys.core.user.CurrentUserProvider; 050import org.ametys.core.user.User; 051import org.ametys.core.user.UserIdentity; 052import org.ametys.core.user.UserManager; 053import org.ametys.core.user.directory.NotUniqueUserException; 054import org.ametys.core.user.population.PopulationContextHelper; 055import org.ametys.core.util.I18nUtils; 056import org.ametys.core.util.mail.SendMailHelper; 057import org.ametys.plugins.core.user.UserHelper; 058import org.ametys.plugins.repository.AmetysObjectIterable; 059import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 060import org.ametys.plugins.workspaces.members.MembersWorkspaceModule.Invitation; 061import org.ametys.plugins.workspaces.project.ProjectManager; 062import org.ametys.plugins.workspaces.project.modules.WorkspaceModuleExtensionPoint; 063import org.ametys.plugins.workspaces.project.objects.Project; 064import org.ametys.plugins.workspaces.project.rights.ProjectRightHelper; 065import org.ametys.runtime.i18n.I18nizableText; 066import org.ametys.runtime.i18n.I18nizableTextParameter; 067import org.ametys.runtime.plugin.component.AbstractLogEnabled; 068import org.ametys.runtime.plugin.component.PluginAware; 069import org.ametys.web.WebConstants; 070import org.ametys.web.WebHelper; 071import org.ametys.web.repository.page.Page; 072import org.ametys.web.repository.page.Zone; 073import org.ametys.web.repository.page.ZoneItem; 074import org.ametys.web.repository.page.ZoneItem.ZoneType; 075import org.ametys.web.repository.site.Site; 076import org.ametys.web.repository.site.SiteManager; 077import org.ametys.web.usermanagement.UserManagementException; 078import org.ametys.web.usermanagement.UserSignUpConfiguration; 079import org.ametys.web.usermanagement.UserSignupManager; 080 081import com.google.common.collect.Iterables; 082 083import jakarta.mail.MessagingException; 084 085/** 086 * Helper for invitations by email 087 * 088 */ 089public class ProjectInvitationHelper extends AbstractLogEnabled implements Serviceable, Component, Configurable, PluginAware, Contextualizable 090{ 091 /** The role */ 092 public static final String ROLE = ProjectInvitationHelper.class.getName(); 093 094 private static final String __MAIL_PROJECT_EMAIL_PATTERN = "${email}"; 095 private static final String __MAIL_PROJECT_TOKEN_PATTERN = "${token}"; 096 097 private ProjectManager _projectManager; 098 private UserSignUpConfiguration _signupConfig; 099 private UserSignupManager _signupManager; 100 private SiteManager _siteManager; 101 private WorkspaceModuleExtensionPoint _moduleEP; 102 private CurrentUserProvider _currentUserProvider; 103 private UserManager _userManager; 104 private UserHelper _userHelper; 105 private ProjectRightHelper _projectRightsHelper; 106 private ProjectMemberManager _projectMemberManager; 107 private PopulationContextHelper _populationContextHelper; 108 private LanguagesManager _languagesManager; 109 110 private String _subjectKeyForInvitation; 111 private String _textBodyKeyForInvitation; 112 private String _htmlBodyKeyForInvitation; 113 private String _subjectKeyForInvitationAccepted; 114 private String _textBodyKeyForInvitationAccepted; 115 private String _htmlBodyKeyForInvitationAccepted; 116 117 private I18nUtils _i18nUtils; 118 119 private String _pluginName; 120 121 private Context _context; 122 123 124 public void setPluginInfo(String pluginName, String featureName, String id) 125 { 126 _pluginName = pluginName; 127 } 128 129 public void contextualize(Context context) throws ContextException 130 { 131 _context = context; 132 } 133 134 @Override 135 public void service(ServiceManager serviceManager) throws ServiceException 136 { 137 _projectManager = (ProjectManager) serviceManager.lookup(ProjectManager.ROLE); 138 _projectRightsHelper = (ProjectRightHelper) serviceManager.lookup(ProjectRightHelper.ROLE); 139 _projectMemberManager = (ProjectMemberManager) serviceManager.lookup(ProjectMemberManager.ROLE); 140 _signupConfig = (UserSignUpConfiguration) serviceManager.lookup(UserSignUpConfiguration.ROLE); 141 _signupManager = (UserSignupManager) serviceManager.lookup(UserSignupManager.ROLE); 142 _siteManager = (SiteManager) serviceManager.lookup(SiteManager.ROLE); 143 _moduleEP = (WorkspaceModuleExtensionPoint) serviceManager.lookup(WorkspaceModuleExtensionPoint.ROLE); 144 _currentUserProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE); 145 _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE); 146 _userHelper = (UserHelper) serviceManager.lookup(UserHelper.ROLE); 147 _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE); 148 _populationContextHelper = (PopulationContextHelper) serviceManager.lookup(PopulationContextHelper.ROLE); 149 _languagesManager = (LanguagesManager) serviceManager.lookup(LanguagesManager.ROLE); 150 } 151 152 @Override 153 public void configure(Configuration configuration) throws ConfigurationException 154 { 155 _subjectKeyForInvitation = configuration.getChild("invitation-email-subject").getValue(null); 156 _textBodyKeyForInvitation = configuration.getChild("invitation-email-text-body").getValue(null); 157 _htmlBodyKeyForInvitation = configuration.getChild("invitation-email-html-body").getValue(null); 158 159 _subjectKeyForInvitationAccepted = configuration.getChild("invitation-accepted-email-subject").getValue(null); 160 _textBodyKeyForInvitationAccepted = configuration.getChild("invitation-accepted-email-text-body").getValue(null); 161 _htmlBodyKeyForInvitationAccepted = configuration.getChild("invitation-accepted-email-html-body").getValue(null); 162 } 163 164 /** 165 * Invite emails to be member of a project 166 * @param projectName The project name 167 * @param emails The emails 168 * @param allowedProfileByModule the allowed profiles by module 169 * @return The result 170 * @throws UserManagementException if failed to invit user 171 * @throws NotUniqueUserException if many users match the given email 172 * @throws IllegalAccessException If the user cannot execute this operation 173 */ 174 public Map<String, Object> inviteEmails(String projectName, List<String> emails, Map<String, String> allowedProfileByModule) throws UserManagementException, IllegalAccessException, NotUniqueUserException 175 { 176 Request request = ContextHelper.getRequest(_context); 177 String siteName = WebHelper.getSiteName(request); 178 String sitemapLanguage = (String) request.getAttribute(WebConstants.REQUEST_ATTR_SITEMAP_NAME); 179 180 Project project = _projectManager.getProject(projectName); 181 Map<String, String> emailConfiguration = _getInvitationEmailConfiguration(project, sitemapLanguage); 182 String mailSubject = emailConfiguration.get("subject"); 183 String mailBody = emailConfiguration.get("bodyText"); 184 185 return inviteEmails(projectName, siteName, sitemapLanguage, emails, allowedProfileByModule, mailSubject, mailBody); 186 } 187 /** 188 * Invite emails to be member of a project 189 * @param projectName The project name 190 * @param siteName The site name 191 * @param lang the current language 192 * @param emails The emails 193 * @param allowedProfileByModule the allowed profiles by module 194 * @param mailSubject The subject of mail 195 * @param mailBody The body of mail 196 * @return The result 197 * @throws UserManagementException if failed to invit user 198 * @throws NotUniqueUserException if many users match the given email 199 * @throws IllegalAccessException If the user cannot execute this operation 200 */ 201 @Callable 202 public Map<String, Object> inviteEmails(String projectName, String siteName, String lang, List<String> emails, Map<String, String> allowedProfileByModule, String mailSubject, String mailBody) throws UserManagementException, IllegalAccessException, NotUniqueUserException 203 { 204 Map<String, Object> result = new HashMap<>(); 205 206 result.put("existing-users", new ArrayList<Map<String, Object>>()); 207 result.put("email-success", new ArrayList<String>()); 208 result.put("email-error", new ArrayList<String>()); 209 210 Project project = _projectManager.getProject(projectName); 211 if (project != null) 212 { 213 MembersWorkspaceModule module = _moduleEP.getModule(MembersWorkspaceModule.MEMBERS_MODULE_ID); 214 if (module != null && _projectManager.isModuleActivated(project, module.getId())) 215 { 216 if (!_projectRightsHelper.canAddMember(project)) 217 { 218 throw new IllegalAccessException("User '" + _currentUserProvider.getUser() + "' tried to send invitations without sufficient right."); 219 } 220 221 String catalogSiteName = _projectManager.getCatalogSiteName(); 222 223 String userDirectoryAsStr = _getUserDirectoryForSignup(result, catalogSiteName, lang); 224 if (userDirectoryAsStr != null) 225 { 226 String populationId = StringUtils.substringBeforeLast(userDirectoryAsStr, "#"); 227 String userDirectoryId = StringUtils.substringAfterLast(userDirectoryAsStr, "#"); 228 229 for (String email : emails) 230 { 231 try 232 { 233 if (!_signupManager.userExists(email, catalogSiteName)) 234 { 235 _signupManager.temporarySignup(siteName, lang, email, populationId, userDirectoryId); 236 237 // Whatever or not the mail has already been invited, re-created the invitation 238 if (_addOrUpdateInvitation(project, catalogSiteName, module, email, allowedProfileByModule, populationId, userDirectoryId, mailSubject, mailBody)) 239 { 240 @SuppressWarnings("unchecked") 241 List<String> emailSuccess = (List<String>) result.get("email-success"); 242 emailSuccess.add(email); 243 244 } 245 else 246 { 247 @SuppressWarnings("unchecked") 248 List<String> emailErrors = (List<String>) result.get("email-error"); 249 emailErrors.add(email); 250 } 251 } 252 else 253 { 254 User user = _getUser(catalogSiteName, email); 255 256 Map<String, Object> user2json = _userHelper.user2json(user, true); 257 258 @SuppressWarnings("unchecked") 259 List<Map<String, Object>> existingUsers = (List<Map<String, Object>>) result.get("existing-users"); 260 existingUsers.add(user2json); 261 } 262 } 263 catch (UserManagementException e) 264 { 265 getLogger().error("Cannot invite " + email, e); 266 @SuppressWarnings("unchecked") 267 List<String> emailErrors = (List<String>) result.get("email-error"); 268 emailErrors.add(email); 269 } 270 } 271 272 @SuppressWarnings("unchecked") 273 List<String> emailSuccess = (List<String>) result.get("email-success"); 274 if (emailSuccess.size() == emails.size()) 275 { 276 result.put("success", true); 277 } 278 } 279 } 280 } 281 else 282 { 283 result.put("success", false); 284 result.put("unknown-project", projectName); 285 } 286 287 return result; 288 } 289 290 private User _getUser(String siteName, String email) throws NotUniqueUserException 291 { 292 Set<String> populations = _populationContextHelper.getUserPopulationsOnContexts(Arrays.asList("/sites/" + siteName, "/sites-fo/" + siteName), false); 293 for (String population : populations) 294 { 295 User user = _userManager.getUser(population, email); 296 if (user == null) 297 { 298 user = _userManager.getUserByEmail(population, email); 299 } 300 301 if (user != null) 302 { 303 return user; 304 } 305 } 306 307 return null; 308 } 309 310 /** 311 * Get the configuration to invite users by emails 312 * @param projectName The current project 313 * @param lang the current language 314 * @return the configuration for email invitations 315 */ 316 @Callable 317 public Map<String, Object> getInvitationConfiguration(String projectName, String lang) 318 { 319 Project project = _projectManager.getProject(projectName); 320 321 Map<String, Object> config = new HashMap<>(); 322 323 // Check the configuration is valid for invitations 324 String catalogSiteName = _projectManager.getCatalogSiteName(); 325 if (_getUserDirectoryForSignup(config, catalogSiteName, lang) == null) 326 { 327 config.remove("success"); 328 config.put("allowed", false); 329 return config; 330 } 331 332 // Check the current user has right to invite users 333 if (!_projectRightsHelper.canAddMember(project)) 334 { 335 config.put("allowed", false); 336 config.put("error", "no-right"); 337 return config; 338 } 339 340 config.put("allowed", true); 341 config.put("email", _getInvitationEmailConfiguration(project, lang)); 342 config.put("rights", _projectRightsHelper.getProjectRightsData(projectName)); 343 344 return config; 345 } 346 347 private Map<String, String> _getInvitationEmailConfiguration(Project project, String lang) 348 { 349 Map<String, String> emailConfig = new HashMap<>(); 350 351 Map<String, I18nizableTextParameter> i18nparams = new HashMap<>(); 352 i18nparams.put("projectTitle", new I18nizableText(project.getTitle())); 353 i18nparams.put("projectUrl", new I18nizableText(Iterables.getFirst(_projectManager.getProjectUrls(project), StringUtils.EMPTY))); 354 i18nparams.put("nbDays", new I18nizableText(String.valueOf(_signupConfig.getTokenValidity()))); 355 i18nparams.put("nbDays", new I18nizableText(String.valueOf(_signupConfig.getTokenValidity()))); 356 357 String catalogSiteName = _projectManager.getCatalogSiteName(); 358 Site catalogSite = _siteManager.getSite(catalogSiteName); 359 i18nparams.put("catalogSiteTitle", new I18nizableText(catalogSite.getTitle())); 360 i18nparams.put("catalogSiteUrl", new I18nizableText(catalogSite.getUrl())); 361 362 Page signupPage = _getSignupPage(_projectManager.getCatalogSiteName(), lang); 363 if (signupPage != null) 364 { 365 String signupUri = ResolveURIComponent.resolve("page", signupPage.getId(), false, true) + "?email=${email}&token=${token}"; 366 i18nparams.put("signupUri", new I18nizableText(signupUri)); 367 } 368 369 String subject = getSubjectForInvitationEmail(i18nparams, lang); 370 if (subject != null) 371 { 372 emailConfig.put("subject", subject); 373 } 374 String bodyTxt = getTextBodyForInvitationEmail(i18nparams, lang); 375 if (bodyTxt != null) 376 { 377 emailConfig.put("bodyText", bodyTxt); 378 } 379 String bodyHtml = getHtmlBodyForInvitationEmail(i18nparams, lang); 380 if (bodyHtml != null) 381 { 382 emailConfig.put("bodyHtml", bodyHtml); 383 } 384 385 return emailConfig; 386 } 387 388 private Page _getSignupPage(String catalogSiteName, String lang) 389 { 390 391 Page signupPage = _signupManager.getSignupPage(catalogSiteName, lang); 392 393 if (signupPage == null) 394 { 395 signupPage = _signupManager.getSignupPage(catalogSiteName, "en"); 396 } 397 398 if (signupPage == null) 399 { 400 Map<String, Language> availableLanguages = _languagesManager.getAvailableLanguages(); 401 for (Language availableLanguage : availableLanguages.values()) 402 { 403 if (signupPage == null) 404 { 405 signupPage = _signupManager.getSignupPage(catalogSiteName, availableLanguage.getCode()); 406 } 407 } 408 } 409 return signupPage; 410 } 411 412 private void _sendInvitationMail (String catalogSiteName, String email, String populationId, String userDirectoryId, String mailSubject, String mailBodyTpl) throws UserManagementException 413 { 414 String bodyTxt = mailBodyTpl; 415 416 String encodedEmail; 417 try 418 { 419 encodedEmail = URLEncoder.encode(email, "UTF-8"); 420 } 421 catch (UnsupportedEncodingException e) 422 { 423 // Should never happen. 424 throw new UserManagementException("Encoding error while sending a sign-up confirmation e-mail.", e); 425 } 426 427 String token = _signupManager.getToken(catalogSiteName, email, populationId, userDirectoryId); 428 429 bodyTxt = StringUtils.replace(bodyTxt, __MAIL_PROJECT_TOKEN_PATTERN, token); 430 bodyTxt = StringUtils.replace(bodyTxt, __MAIL_PROJECT_EMAIL_PATTERN, encodedEmail); 431 432 getLogger().debug("Sending signup invitation e-mail to {}", email); 433 434 Site site = _siteManager.getSite(catalogSiteName); 435 String from = site.getValue("site-mail-from"); 436 437 try 438 { 439 // Send the e-mail. 440 SendMailHelper.newMail() 441 .withSubject(mailSubject) 442 .withTextBody(bodyTxt) 443 .withSender(from) 444 .withRecipient(email) 445 .sendMail(); 446 } 447 catch (MessagingException | IOException e) 448 { 449 throw new UserManagementException("Error sending the sign-up confirmation mail.", e); 450 } 451 } 452 453 private boolean _addOrUpdateInvitation(Project project, String catalogSiteName, MembersWorkspaceModule module, String email, Map<String, String> allowedProfileByModules, String populationId, String userDirectoryId, String mailSubject, String mailBody) throws UserManagementException 454 { 455 try 456 { 457 // First remove invitation if exists 458 module.removeInvitation(project, email); 459 460 // Add invitations with temporary rights 461 module.addInvitation(project, new Date(), email, _currentUserProvider.getUser(), allowedProfileByModules); 462 463 project.saveChanges(); 464 465 _sendInvitationMail(catalogSiteName, email, populationId, userDirectoryId, mailSubject, mailBody); 466 467 return true; 468 } 469 catch (RepositoryException e) 470 { 471 getLogger().error("Fail to store invitation for email " + email, e); 472 return false; 473 } 474 } 475 476 private String _getUserDirectoryForSignup(Map<String, Object> result, String catalogSiteName, String lang) 477 { 478 if (catalogSiteName == null) 479 { 480 getLogger().error("The catalog's site name is not configured. User invitations can not be activated."); 481 result.put("success", false); 482 result.put("error", "invalid-configuration"); 483 return null; 484 } 485 486 if (!_signupManager.isPublicSignupAllowed(catalogSiteName)) 487 { 488 getLogger().warn("Public signup is disabled for the catalog's site."); 489 result.put("success", false); 490 return null; 491 } 492 493 Page signupPage = _getSignupPage(catalogSiteName, lang); 494 if (signupPage == null) 495 { 496 getLogger().error("The catalog's site does not contain the signup service for language " + lang + ". User invitations can not be activated."); 497 result.put("success", false); 498 result.put("error", "invalid-configuration"); 499 return null; 500 } 501 502 String userDirectoryAsStr = _getUserDirectoryForSignup(signupPage); 503 if (StringUtils.isEmpty(userDirectoryAsStr)) 504 { 505 getLogger().error("There is no user directory configured for users signup. Please check the sign up service of catalog's site."); 506 result.put("success", false); 507 result.put("error", "invalid-configuration"); 508 return null; 509 } 510 511 return userDirectoryAsStr; 512 513 } 514 515 private String _getUserDirectoryForSignup(Page signupPage) 516 { 517 for (Zone zone : signupPage.getZones()) 518 { 519 try (AmetysObjectIterable<? extends ZoneItem> zoneItems = zone.getZoneItems()) 520 { 521 for (ZoneItem zoneItem : zoneItems) 522 { 523 if (zoneItem.getType() == ZoneType.SERVICE && zoneItem.getServiceId().equals("org.ametys.web.service.UserSignup")) 524 { 525 return zoneItem.getServiceParameters().getValue("userdirectory"); 526 } 527 } 528 } 529 } 530 531 return null; 532 533 } 534 535 /** 536 * Add user as member of all project where it has been invited 537 * @param user the new user 538 */ 539 public void createMemberFromInvitations(User user) 540 { 541 Request request = ContextHelper.getRequest(_context); 542 String currentWorkspace = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 543 544 try 545 { 546 // Force default workspace 547 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, "default"); 548 549 MembersWorkspaceModule memberModule = (MembersWorkspaceModule) _moduleEP.getExtension(MembersWorkspaceModule.MEMBERS_MODULE_ID); 550 551 List<Invitation> invitations = memberModule.getInvitations(user.getEmail()); 552 553 for (Invitation invitation : invitations) 554 { 555 Map<String, String> allowedProfileByModules = invitation.getAllowedProfileByModules(); 556 String projectName = invitation.getProjectName(); 557 558 Project project = _projectManager.getProject(projectName); 559 560 561 _projectMemberManager.addOrUpdateProjectMember(project, user.getIdentity(), allowedProfileByModules); 562 563 // Notify author that invitation was accepted 564 UserIdentity author = invitation.getAuthor(); 565 sendInvitationAcceptedMail(project, _userManager.getUser(author), user); 566 567 try 568 { 569 // Remove invitation 570 memberModule.removeInvitation(project, invitation.getEmail()); 571 } 572 catch (RepositoryException e) 573 { 574 getLogger().error("Failed to remove invitation " + invitation, e); 575 } 576 } 577 } 578 finally 579 { 580 // Restore current workspace 581 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWorkspace); 582 } 583 584 } 585 586 /** 587 * Send email to the user who initiated the invitation 588 * @param project The project 589 * @param invitAuthor The author of invitation 590 * @param newMember The new member 591 */ 592 protected void sendInvitationAcceptedMail(Project project, User invitAuthor, User newMember) 593 { 594 if (invitAuthor != null) 595 { 596 Site site = project.getSites().iterator().next(); 597 String from = site.getValue("site-mail-from"); 598 String email = invitAuthor.getEmail(); 599 600 if (StringUtils.isNotEmpty(email)) 601 { 602 // Prepare mail. 603 Map<String, I18nizableTextParameter> i18nParams = new HashMap<>(); 604 i18nParams.put("projectTitle", new I18nizableText(project.getTitle())); 605 i18nParams.put("projectUrl", new I18nizableText(Iterables.getFirst(_projectManager.getProjectUrls(project), StringUtils.EMPTY))); 606 i18nParams.put("newMember", new I18nizableText(newMember.getFullName())); 607 i18nParams.put("newMemberMail", new I18nizableText(newMember.getEmail())); 608 609 Set<Page> memberPages = _projectManager.getModulePages(project, MembersWorkspaceModule.MEMBERS_MODULE_ID); 610 if (!memberPages.isEmpty()) 611 { 612 Page page = memberPages.iterator().next(); 613 i18nParams.put("membersPageUri", new I18nizableText(ResolveURIComponent.resolve("page", page.getId(), false, true))); 614 } 615 616 String subject = getSubjectForInvitationAcceptedEmail(i18nParams, null); 617 String textBody = getTextBodyForInvitationAcceptedEmail(i18nParams, null); 618 String htmlBody = getHtmlBodyForInvitationAcceptedEmail(i18nParams, null); 619 620 try 621 { 622 // Send the e-mail. 623 SendMailHelper.newMail() 624 .withSubject(subject) 625 .withHTMLBody(htmlBody) 626 .withTextBody(textBody) 627 .withSender(from) 628 .withRecipient(email) 629 .sendMail(); 630 } 631 catch (MessagingException | IOException e) 632 { 633 getLogger().error("Error sending the invitation accepted email.", e); 634 } 635 } 636 } 637 } 638 639 /** 640 * The email subject for invitation by email 641 * @param defaultI18nParams The default i18n parameters 642 * @param language the language 643 * @return the email subject for invitation by email 644 */ 645 public String getSubjectForInvitationEmail (Map<String, I18nizableTextParameter> defaultI18nParams , String language) 646 { 647 if (StringUtils.isNotBlank(_subjectKeyForInvitation)) 648 { 649 return _i18nUtils.translate(_getI18nizableText(_subjectKeyForInvitation, defaultI18nParams), language); 650 } 651 652 return null; 653 } 654 655 /** 656 * The email text body for invitation by email 657 * @param defaultI18nParams The default i18n parameters with : 658 * siteName the site name 659 * email the mail 660 * token the token 661 * confirmUri the confirmation uri 662 * siteTitle the site title 663 * siteUrl the site url 664 * @param language the language 665 * @return the email text for invitation by email 666 */ 667 public String getTextBodyForInvitationEmail(Map<String, I18nizableTextParameter> defaultI18nParams, String language) 668 { 669 if (StringUtils.isNotBlank(_textBodyKeyForInvitation)) 670 { 671 return _i18nUtils.translate(_getI18nizableText(_textBodyKeyForInvitation, defaultI18nParams), language); 672 } 673 674 return null; 675 } 676 677 /** 678 * The email html body for invitation by email 679 * @param defaultI18nParams The default i18n parameters with : 680 * siteName the site name 681 * email the mail 682 * token the token 683 * confirmUri the confirmation uri 684 * siteTitle the site title 685 * siteUrl the site url 686 * @param language the language 687 * @return the email html for invitation by email 688 */ 689 public String getHtmlBodyForInvitationEmail(Map<String, I18nizableTextParameter> defaultI18nParams, String language) 690 { 691 if (StringUtils.isNotBlank(_htmlBodyKeyForInvitation)) 692 { 693 return _i18nUtils.translate(_getI18nizableText(_htmlBodyKeyForInvitation, defaultI18nParams), language); 694 } 695 696 return null; 697 } 698 699 /** 700 * The email subject for invitation by email 701 * @param defaultI18nParams The default i18n parameters 702 * @param language the language 703 * @return the email subject for invitation by email 704 */ 705 public String getSubjectForInvitationAcceptedEmail (Map<String, I18nizableTextParameter> defaultI18nParams , String language) 706 { 707 if (StringUtils.isNotBlank(_subjectKeyForInvitationAccepted)) 708 { 709 return _i18nUtils.translate(_getI18nizableText(_subjectKeyForInvitationAccepted, defaultI18nParams), language); 710 } 711 712 return null; 713 } 714 715 /** 716 * The email text body for invitation by email 717 * @param defaultI18nParams The default i18n parameters with : 718 * @param language the language 719 * @return the email text for invitation by email 720 */ 721 public String getTextBodyForInvitationAcceptedEmail(Map<String, I18nizableTextParameter> defaultI18nParams, String language) 722 { 723 if (StringUtils.isNotBlank(_textBodyKeyForInvitationAccepted)) 724 { 725 return _i18nUtils.translate(_getI18nizableText(_textBodyKeyForInvitationAccepted, defaultI18nParams), language); 726 } 727 728 return null; 729 } 730 731 /** 732 * The email html body for invitation by email 733 * @param defaultI18nParams The default i18n parameters with : 734 * @param language the language 735 * @return the email html for invitation by email 736 */ 737 public String getHtmlBodyForInvitationAcceptedEmail(Map<String, I18nizableTextParameter> defaultI18nParams, String language) 738 { 739 if (StringUtils.isNotBlank(_htmlBodyKeyForInvitationAccepted)) 740 { 741 return _i18nUtils.translate(_getI18nizableText(_htmlBodyKeyForInvitationAccepted, defaultI18nParams), language); 742 } 743 744 return null; 745 } 746 747 /** 748 * Get the {@link I18nizableText} from the configured key and i18n parameters 749 * @param fullI18nKey the configured i18n key 750 * @param i18nParams the i18n parameters 751 * @return the i18nizable text 752 */ 753 protected I18nizableText _getI18nizableText(String fullI18nKey, Map<String, I18nizableTextParameter> i18nParams) 754 { 755 String catalogue = StringUtils.contains(fullI18nKey, ":") ? StringUtils.substringBefore(fullI18nKey, ":") : "plugin." + _pluginName; 756 String i18nKey = StringUtils.contains(fullI18nKey, ":") ? StringUtils.substringAfter(fullI18nKey, ":") : fullI18nKey; 757 758 return new I18nizableText(catalogue, i18nKey, i18nParams); 759 } 760 761}