/* * Copyright 2009-2012 by KNURT Systeme (http://www.knurt.de) * * Licensed under the Creative Commons License Attribution-NonCommercial-ShareAlike 3.0 Unported; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://creativecommons.org/licenses/by-nc-sa/3.0/ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.knurt.fam.core.util.mail; import java.util.Calendar; import java.util.Date; import org.springframework.beans.factory.annotation.Required; import org.springframework.dao.DataIntegrityViolationException; import de.knurt.fam.connector.FamConnector; import de.knurt.fam.core.aspects.logging.FamLog; import de.knurt.fam.core.aspects.security.encoder.FamTmpAccessEncoderControl; import de.knurt.fam.core.model.config.Facility; import de.knurt.fam.core.model.persist.User; import de.knurt.fam.core.model.persist.UserMail; import de.knurt.fam.core.model.persist.booking.Booking; import de.knurt.fam.core.model.persist.booking.Cancelation; import de.knurt.fam.core.model.persist.booking.QueueBooking; import de.knurt.fam.core.model.persist.booking.TimeBooking; import de.knurt.fam.core.persistence.dao.FamDaoProxy; import de.knurt.fam.core.persistence.dao.UserDao; import de.knurt.fam.core.persistence.dao.config.FacilityConfigDao; import de.knurt.fam.core.util.mvc.QueryStringBuilder; import de.knurt.fam.core.util.mvc.RedirectResolver; import de.knurt.fam.core.view.text.FamDateFormat; import de.knurt.fam.core.view.text.FamText; import de.knurt.fam.template.util.TemplateHtml; /** * a mail box producing and insert messages.<br /> * <p> * this class has to tasks:<br /> * 1. produce {@link UserMail}s to send to {@link User}s<br /> * 2. store {@link UserMail}s for sending them yet or later. * </p> * all basics must be injected (see setters),<br /> * all specifics are part of the product (the mail). * * @see UserMailSender * @see UserMail * @see UserDao#insert(de.knurt.fam.core.model.persist.UserMail) * @author Daniel Oltmanns * @since 0.20090325 */ public class OutgoingUserMailBox { // INTLANG (entire class) /** * send a mail to confirm the registration of a user. this is sent if an * account is verified or the user is known and has been logged in the first * time. * * @param to * recipient of the mail */ public static void insert_Registration(User to) { insert(getInstance().getMail_Registration(to)); } public static void insert_BookingTransfer(User from, User receiver, Booking booking) { insert(getInstance().getMail_BookingTransfer(from, receiver, booking)); } private UserMail getMail_BookingTransfer(User from, User receiver, Booking booking) { String[] args = new String[4]; args[0] = receiver.getFullName(); args[1] = from.getFullName(); args[2] = booking.getFacility().getLabel(); args[3] = TemplateHtml.href("mybookings"); return this.getMailFromMessageSource(receiver, "transferedbooking", args, 0, null, null, null); } private static void insert_BookingReminder(Booking booking) { UserMail mail = getInstance().getMail_BookingReminder(booking); if (mail != null) { insert(mail); } } /** * send a mail to confirm a users booking. * * @param booking * confirmed in the mail */ public static void insert_BookingMade(TimeBooking booking) { insert(getInstance().getMail_BookingMade(booking)); insert_BookingReminder(booking); } /** * send a mail to confirm a users booking. * * @param booking * confirmed in the mail */ public static boolean insert_BookingMade(QueueBooking booking) { return insert(getInstance().getMail_BookingMade(booking)); } private static boolean insert(UserMail mail) { boolean result = FamDaoProxy.userDao().insert(mail); if (mail.mustBeSendNow()) { UserMailSender.sendUserMails(); } return result; } /** * insert a cancelation mail into the outbox. if the booking does not * contain a {@link Cancelation}, log it and do nothing. * * @param booking * that is canceled */ public static void insert_BookingCancelation(TimeBooking booking) { insert(getInstance().getMail_bookingCancelation(booking)); } /** * insert a cancelation mail into the outbox. if the booking does not * contain a {@link Cancelation}, log it and do nothing. * * @param booking * that is canceled */ public static void insert_BookingCancelation(QueueBooking booking) { insert(getInstance().getMail_bookingCancelation(booking)); } /** * send a mail to a user requested a new password. * * @param to * recipient of the mail */ public static void insert_ForgottenPassword(User to) { insert(getInstance().getMail_ForgottenPassword(to)); } /** * insert information mail when a booking has been processed. * * @param booking * information mail when a booking has been processed. */ public static void insert_BookingProcessed(Booking booking) { insert(getInstance().getMail_BookingProcessed(booking)); } private OutgoingUserMailBox() { } private volatile static OutgoingUserMailBox me; /** * return the one and only factory instance * * @return the one and only factory instance */ private static OutgoingUserMailBox getInstance() { if (me == null) { // no instance so far synchronized (OutgoingUserMailBox.class) { if (me == null) { // still no instance so far me = new OutgoingUserMailBox(); // the one and only } } } return me; } private int timeUnitsBaseInMinutes; private int timeUnitsSend_Registration, timeUnitsSend_BookingMade, timeUnitsSend_ApplicationConfirmation, timeUnitsSend_ForgottenPassword, timeUnitsSend_BookingCancelation; private UserMail getMail_BookingMade(TimeBooking booking) { String[] args = new String[4]; args[0] = booking.getUser().getFullName(); args[1] = booking.getFacility().getLabel(); // for facility args[2] = FamDateFormat.getDateFormattedWithTime(booking, false); args[3] = TemplateHtml.href("mybookings"); return this.getMailFromMessageSource(booking.getUser(), "bookingmade", args, this.timeUnitsSend_BookingMade, null, UserMail.TYPE_NEEDS_VALID_BOOKING, booking.getId()); } private UserMail getMail_BookingMade(QueueBooking booking) { String[] args = new String[4]; args[0] = booking.getUser().getFullName(); args[1] = booking.getFacility().getLabel(); // for facility args[2] = FamDateFormat.getDateFormattedWithTime(booking.getExpectedSessionTimeFrame(), false); // expected // time args[3] = TemplateHtml.href("mybookings"); return this.getMailFromMessageSource(booking.getUser(), "queueBookingmade", args, this.timeUnitsSend_BookingMade, null, UserMail.TYPE_NEEDS_VALID_BOOKING, booking.getId()); } private UserMail getMail_BookingReminder(Booking booking) { UserMail result = null; Calendar startOfSession = booking.getSessionTimeFrame().getCalendarStart(); if (startOfSession.get(Calendar.DAY_OF_YEAR) != Calendar.getInstance().get(Calendar.DAY_OF_YEAR) || startOfSession.get(Calendar.YEAR) != Calendar.getInstance().get(Calendar.YEAR)) { // ↖ session is not today today // ↓ set to send date Calendar mailToSendDate = booking.getSessionTimeFrame().getCalendarStart(); int reminderMailBeforeStarting = booking.getBookingRule().getSetOfRulesForARole(booking.getUser()).getReminderMailMinutesBeforeStarting(); if (reminderMailBeforeStarting != -1) { // ↖ reminder mail is configured mailToSendDate.add(Calendar.MINUTE, -reminderMailBeforeStarting); if (mailToSendDate.after(Calendar.getInstance())) { // ↖ mail is send in future // ↓ prepare mail String[] args = new String[4]; args[0] = booking.getUser().getFullName(); args[1] = booking.getFacility().getLabel(); // for facility args[2] = FamDateFormat.getDateFormattedWithTime(booking.getSessionTimeFrame().getDateStart()); args[3] = TemplateHtml.href("mybookings"); result = this.getMailFromMessageSource(booking.getUser(), "bookingreminder", args, 0, null, UserMail.TYPE_NEEDS_VALID_BOOKING, booking.getId()); result.setToSendDate(mailToSendDate.getTime()); } } } return result; } private UserMail getMail_ApplicationConfirmation(User to, Booking booking, String notification) { notification = notification.trim(); String[] args = new String[5]; args[0] = to.getFullName(); args[1] = booking.getFacility().getLabel(); // for facility args[2] = FamDateFormat.getDateFormattedWithTime(booking.getSessionTimeFrame(), false); args[3] = TemplateHtml.href("mybookings"); args[4] = notification.isEmpty() ? "" : "You got a notification with this confirmation: \"" + notification + "\""; // INTLANG if (booking.isQueueBased()) { args[2] += " (expected to be - real time may vary tremendously)"; } return this.getMailFromMessageSource(to, "applicationconfirmation", args, this.timeUnitsSend_ApplicationConfirmation, null, UserMail.TYPE_NEEDS_VALID_ACTIVE_USER, to.getId()); } private UserMail getMail_ForgottenPassword(User to) { String[] args = new String[4]; args[0] = to.getFullName(); args[1] = TemplateHtml.href("setnewpassword"); args[2] = FamTmpAccessEncoderControl.getInstance().encodePassword(to); args[3] = to.getUsername(); return this.getMailFromMessageSource(to, "forgottenpassword", args, this.timeUnitsSend_ForgottenPassword, null, UserMail.TYPE_NEEDS_VALID_ACTIVE_USER, to.getId()); } /** * send a mail to a user that there are applications for a facility. * * @param to * recipient of the mail * @param count * of applications for the facility * @param facility * the applications are for */ public static void sendMail_applicationsForResource(User to, Facility facility, int count) { String[] args = new String[3]; args[0] = count + ""; args[1] = facility.getLabel(); args[2] = TemplateHtml.href("systemmodifyapplications"); UserMail um = getInstance().getMailFromMessageSource(to, "applicationsforafacility", args, 0, null, UserMail.TYPE_NEEDS_VALID_ACTIVE_USER, to.getId()); insert(um); } /** * send a mail to a user, that there are applications for the system. * * @param to * recipient of the mail * @param count * of applications for the system */ public static void sendMail_applicationsForSystem(User to, int count) { String[] args = new String[2]; args[0] = count + ""; args[1] = TemplateHtml.href("users"); UserMail um = getInstance().getMailFromMessageSource(to, "applicationsforsystem", args, 0, null, UserMail.TYPE_NEEDS_VALID_ACTIVE_USER, to.getId()); insert(um); } private UserMail getMailFromMessageSource(User to, String key, String[] args4msg, int timeUnitsToSend, String msgAfterSent, Integer type, Integer fid) { String subject = FamText.message("mail." + key + ".subject"); String message = FamText.message("mail." + key + ".msg", args4msg); Calendar toSent = Calendar.getInstance(); toSent.add(Calendar.MINUTE, timeUnitsToSend * timeUnitsBaseInMinutes); return this.getMail(subject, message, to, toSent.getTime(), msgAfterSent, type, fid); } /** * return a email for notifying a registered user * * @param to * recipient user * @return a email for notifying a registered user */ private UserMail getMail_Registration(User to) { String[] args = new String[4]; args[0] = to.getFullName(); args[1] = TemplateHtml.href("corehome"); args[2] = to.getUsername(); args[3] = TemplateHtml.href("forgottenpassword"); return this.getMailFromMessageSource(to, "registration", args, this.getTimeUnitsSend_Registration(), null, UserMail.TYPE_NEEDS_VALID_ACTIVE_USER, to.getId()); } /** * return the configured {@link UserMail} * * @param subject * of the mail * @param message * of the mail * @param to * recipient of the mail * @param toSendDate * date of when the e-mail shall be sent * @param msgAfterSent * {@link UserMail#getMsgAfterSent()} * @param type * {@link UserMail#getType()} * @param fid * {@link UserMail#getFid()} * @return the configured mail */ private UserMail getMail(String subject, String message, User to, Date toSendDate, String msgAfterSent, Integer type, Integer fid) { UserMail result = new UserMail(); result.setMsg(message + FamText.message("mail.footer")); result.setSubject(subject); result.setUsername(to.getUsername()); result.setTo(to.getMail()); result.setToSendDate(toSendDate); result.setMsgAfterSent(msgAfterSent); result.setType(type); result.setFid(fid); return result; } /** * return the mail for a booking cancelation. if the booking does not * contain a {@link Cancelation}, log it and return null. * * @param booking * that is canceled. must contain a {@link Cancelation} * @return the mail for a booking cancelation. */ private UserMail getMail_bookingCancelation(TimeBooking booking) { if (!booking.isCanceled()) { DataIntegrityViolationException ex = new DataIntegrityViolationException("a canceled booking is needed here"); FamLog.logException(OutgoingUserMailBox.class, ex, "got an uncanceled booking " + booking + ".", 200908091609l); throw ex; } else { User to = booking.getUser(); String[] args = new String[4]; args[0] = to.getFullName(); args[1] = FacilityConfigDao.label(booking.getFacility()); // facility // name args[2] = booking.getCancelation().getReason(); // reason args[3] = FamDateFormat.getDateFormattedWithTime(booking, false); // from // to UserMail um = this.getMailFromMessageSource(to, "bookingCancelation", args, this.timeUnitsSend_BookingCancelation, null, UserMail.TYPE_NEEDS_VALID_ACTIVE_USER, to.getId()); return um; } } /** * return the mail for a booking cancelation. if the booking does not * contain a {@link Cancelation}, log it and return null. * * @param booking * that is canceled. must contain a {@link Cancelation} * @return the mail for a booking cancelation. */ private UserMail getMail_bookingCancelation(QueueBooking booking) { if (!booking.isCanceled()) { DataIntegrityViolationException ex = new DataIntegrityViolationException("a canceled booking is needed here"); FamLog.logException(OutgoingUserMailBox.class, ex, "got an uncanceled booking " + booking + ".", 200909270716l); throw ex; } else { User to = booking.getUser(); String[] args = new String[3]; args[0] = to.getFullName(); args[1] = FacilityConfigDao.label(booking.getFacility()); // facility // name args[2] = booking.getCancelation().getReason(); // reason UserMail um = this.getMailFromMessageSource(to, "queueBookingCancelation", args, this.timeUnitsSend_BookingCancelation, null, UserMail.TYPE_NEEDS_VALID_ACTIVE_USER, to.getId()); return um; } } private UserMail getMail_BookingProcessed(Booking booking) { if (booking.isCanceled()) { DataIntegrityViolationException ex = new DataIntegrityViolationException("an uncanceled booking is needed here"); FamLog.logException(OutgoingUserMailBox.class, ex, "an uncanceled booking is needed here " + booking + ".", 200909011059l); throw ex; } else { User to = booking.getUser(); String[] args = new String[2]; args[0] = to.getFullName(); args[1] = RedirectResolver.redirectLink("viewrequest", QueryStringBuilder.getQueryString(booking)); UserMail um = this.getMailFromMessageSource(to, "bookingProcessed", args, 0, null, UserMail.TYPE_NEEDS_VALID_ACTIVE_USER, to.getId()); return um; } } /** * insert the mail for an user applied for a facility that is sent from the * operator to say: "yes, you got it". * * @param user * receiving this mail * @param booking * of user * @param mailMessage * extended mail message from operator */ public static void insert_ApplicationConfirmation(User user, Booking booking, String mailMessage) { insert(getInstance().getMail_ApplicationConfirmation(user, booking, mailMessage)); } /** * @return the timeUnitsBaseInMinutes */ public int getTimeUnitsBaseInMinutes() { return timeUnitsBaseInMinutes; } /** * @param timeUnitsBaseInMinutes * the timeUnitsBaseInMinutes to set */ @Required public void setTimeUnitsBaseInMinutes(int timeUnitsBaseInMinutes) { this.timeUnitsBaseInMinutes = timeUnitsBaseInMinutes; } /** * @return the timeUnitsSend_BookingMade */ public int getTimeUnitsSend_BookingMade() { return timeUnitsSend_BookingMade; } /** * @param timeUnitsSend_BookingMade * the timeUnitsSend_BookingMade to set */ @Required public void setTimeUnitsSend_BookingMade(int timeUnitsSend_BookingMade) { this.timeUnitsSend_BookingMade = timeUnitsSend_BookingMade; } /** * @return the timeUnitsSend_ApplicationConfirmation */ public int getTimeUnitsSend_ApplicationConfirmation() { return timeUnitsSend_ApplicationConfirmation; } /** * @param timeUnitsSend_ApplicationConfirmation * the timeUnitsSend_ApplicationConfirmation to set */ @Required public void setTimeUnitsSend_ApplicationConfirmation(int timeUnitsSend_ApplicationConfirmation) { this.timeUnitsSend_ApplicationConfirmation = timeUnitsSend_ApplicationConfirmation; } /** * @return the timeUnitsSend_ForgottenPassword */ public int getTimeUnitsSend_ForgottenPassword() { return timeUnitsSend_ForgottenPassword; } /** * @param timeUnitsSend_ForgottenPassword * the timeUnitsSend_ForgottenPassword to set */ @Required public void setTimeUnitsSend_ForgottenPassword(int timeUnitsSend_ForgottenPassword) { this.timeUnitsSend_ForgottenPassword = timeUnitsSend_ForgottenPassword; } /** * @return the timeUnitsSend_BookingCancelation */ public int getTimeUnitsSend_BookingCancelation() { return timeUnitsSend_BookingCancelation; } /** * @param timeUnitsSend_BookingCancelation * the timeUnitsSend_BookingCancelation to set */ @Required public void setTimeUnitsSend_BookingCancelation(int timeUnitsSend_BookingCancelation) { this.timeUnitsSend_BookingCancelation = timeUnitsSend_BookingCancelation; } /** * @return the timeUnitsSend_Registration */ public int getTimeUnitsSend_Registration() { return timeUnitsSend_Registration; } /** * @param timeUnitsSend_Registration * the timeUnitsSend_Registration to set */ @Required public void setTimeUnitsSend_Registration(int timeUnitsSend_Registration) { this.timeUnitsSend_Registration = timeUnitsSend_Registration; } /** * send a password via email if administrator want that. use ***** for * password after email has been sent successfully * * @param to * recipient password is set for * @param newpass * password set to recipient * @return the usermail after sending */ public static UserMail sendMail_adminInitPassword(User to, String newpass) { String key = "admininitpassword"; String[] args = new String[3]; args[0] = to.getFullName(); args[1] = "********"; args[2] = TemplateHtml.href("changepassword"); String msgAfterSent = FamText.message("mail." + key + ".msg", args); args[1] = newpass; UserMail um = getInstance().getMailFromMessageSource(to, key, args, 0, msgAfterSent, null, null); insert(um); return FamDaoProxy.userDao().getUserMailWithId(um.getId()); } public static void sendMail_yourAccountExpired(User user) { String[] args = new String[2]; args[0] = user.getFullName(); args[1] = user.getAccountExpiresFormatted(); UserMail um = getInstance().getMailFromMessageSource(user, "youraccountexpired", args, 0, null, null, null); insert(um); // send somebody in bcc if configured String youraccountexpired_bcc = FamConnector.getGlobalProperty("mail_youraccountexpired_bcc"); if (youraccountexpired_bcc != null && !youraccountexpired_bcc.trim().isEmpty()) { User bccUser = FamDaoProxy.userDao().getUserFromUsername(youraccountexpired_bcc); if (bccUser != null) { UserMail um_blindcopy = getInstance().getMailFromMessageSource(bccUser, "youraccountexpired", args, 0, null, null, null); um_blindcopy.setMsg("A blindcopy for your information: " + um.getMsg()); insert(um_blindcopy); } } } public static void sendMail_expiredAccountReopened(User user) { String[] args = new String[2]; args[0] = user.getFullName(); args[1] = user.getAccountExpiresFormatted(); UserMail um = getInstance().getMailFromMessageSource(user, "expiredaccountreopened", args, 0, null, null, null); insert(um); } }