diff --git a/src/main/java/com/frentix/olat/vitero/ui/ViteroUserToGroupController.java b/src/main/java/com/frentix/olat/vitero/ui/ViteroUserToGroupController.java index 04a35ff6272cdfc349e178c63ffc5ad7af8fde07..9f657b2639c130d01438b034686adf35421981b0 100644 --- a/src/main/java/com/frentix/olat/vitero/ui/ViteroUserToGroupController.java +++ b/src/main/java/com/frentix/olat/vitero/ui/ViteroUserToGroupController.java @@ -249,6 +249,15 @@ public class ViteroUserToGroupController extends BasicController { List<Identity> repoOwners = securityManager.getIdentitiesOfSecurityGroup(repoEntry.getOwnerGroup()); owners.addAll(repoOwners); + + if(repoEntry.getParticipantGroup() != null) { + List<Identity> repoParticipants = securityManager.getIdentitiesOfSecurityGroup(repoEntry.getParticipantGroup()); + participants.addAll(repoParticipants); + } + if(repoEntry.getTutorGroup() != null) { + List<Identity> repoTutors = securityManager.getIdentitiesOfSecurityGroup(repoEntry.getTutorGroup()); + coaches.addAll(repoTutors); + } } return new ResourceMembers(owners, coaches, participants); } diff --git a/src/main/java/de/bps/course/assessment/AssessmentMainController.java b/src/main/java/de/bps/course/assessment/AssessmentMainController.java index c75aec78bd109b7ae66e89b4f02da1bb9a3032a4..f0b1c4a8946ab02f135be8efc178a28f7141e0ea 100644 --- a/src/main/java/de/bps/course/assessment/AssessmentMainController.java +++ b/src/main/java/de/bps/course/assessment/AssessmentMainController.java @@ -104,6 +104,8 @@ import org.olat.course.run.userview.UserCourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironmentImpl; import org.olat.group.BusinessGroup; import org.olat.group.ui.context.BGContextTableModel; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryManager; import org.olat.user.UserManager; import de.bps.onyx.plugin.OnyxModule; @@ -708,6 +710,15 @@ AssessmentMainController(UserRequest ureq, WindowControl wControl, OLATResourcea } } } + //fxdiff VCRP-1,2: access control of resources + RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntry(ores, false); + if(re.getParticipantGroup() != null) { + for (Identity identity : secMgr.getIdentitiesOfSecurityGroup(re.getParticipantGroup())) { + if (!PersistenceHelper.listContainsObjectByKey(allUsersList, identity)) { + allUsersList.add(identity); + } + } + } return allUsersList; } diff --git a/src/main/java/de/bps/course/nodes/den/DENManageParticipantsController.java b/src/main/java/de/bps/course/nodes/den/DENManageParticipantsController.java index 26a7c6a60eba7722351e9261af108e4b6070c50a..e574fb83f47a3207952958701fdf32aab3587809 100644 --- a/src/main/java/de/bps/course/nodes/den/DENManageParticipantsController.java +++ b/src/main/java/de/bps/course/nodes/den/DENManageParticipantsController.java @@ -39,6 +39,8 @@ import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.ContactMessage; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailNotificationEditController; import org.olat.core.util.mail.MailTemplate; @@ -239,7 +241,9 @@ public class DENManageParticipantsController extends BasicController { } else { ccIdentities = null; } - MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(added, null, null, addedNotificationCtr.getMailTemplate(), ureq.getIdentity()); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString()); + MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(context, added, null, null, addedNotificationCtr.getMailTemplate(), ureq.getIdentity()); MailHelper.printErrorsAndWarnings(mailerResult, getWindowControl(), ureq.getLocale()); } notificationCmc.deactivate(); @@ -252,7 +256,9 @@ public class DENManageParticipantsController extends BasicController { } else { ccIdentities = null; } - MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(added, null, null, addedNotificationCtr.getMailTemplate(), ureq.getIdentity()); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString()); + MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(context, added, null, null, addedNotificationCtr.getMailTemplate(), ureq.getIdentity()); MailHelper.printErrorsAndWarnings(mailerResult, getWindowControl(), ureq.getLocale()); } notificationCmc.deactivate(); diff --git a/src/main/java/de/bps/ims/qti/repository/handlers/QTITestHandlerOnyx.java b/src/main/java/de/bps/ims/qti/repository/handlers/QTITestHandlerOnyx.java index 1226c88338ae0ff0c6efe5363f55e56d43bcb79a..b5a129d67e306168e063d03bc36bd30be417892d 100644 --- a/src/main/java/de/bps/ims/qti/repository/handlers/QTITestHandlerOnyx.java +++ b/src/main/java/de/bps/ims/qti/repository/handlers/QTITestHandlerOnyx.java @@ -47,6 +47,7 @@ import org.olat.repository.controllers.IAddController; import org.olat.repository.controllers.RepositoryAddCallback; import org.olat.repository.controllers.RepositoryAddController; import org.olat.repository.controllers.WizardCloseResourceController; +import org.olat.resource.accesscontrol.ui.RepositoryMainAccessControllerWrapper; import org.olat.resource.references.ReferenceManager; import de.bps.onyx.plugin.OnyxModule; @@ -107,7 +108,10 @@ public class QTITestHandlerOnyx extends QTITestHandler { } public MainLayoutController createLaunchController(OLATResourceable res, String initialViewIdentifier, UserRequest ureq, WindowControl wControl) { - return (MainLayoutController) getLaunchController( res, ureq, wControl); + MainLayoutController layoutCtr = (MainLayoutController) getLaunchController( res, ureq, wControl); + //fxdiff VCRP-1: access control of learn resources + RepositoryMainAccessControllerWrapper wrapper = new RepositoryMainAccessControllerWrapper(ureq, wControl, res, layoutCtr); + return wrapper; } /** diff --git a/src/main/java/de/bps/olat/modules/cl/ChecklistManageCheckpointsController.java b/src/main/java/de/bps/olat/modules/cl/ChecklistManageCheckpointsController.java index 953eced52706f7500361a9bee2153b862400183d..a9874debf00838c9efc83008c9ce358bceb87c2d 100644 --- a/src/main/java/de/bps/olat/modules/cl/ChecklistManageCheckpointsController.java +++ b/src/main/java/de/bps/olat/modules/cl/ChecklistManageCheckpointsController.java @@ -119,6 +119,8 @@ public class ChecklistManageCheckpointsController extends BasicController { // collect all identities in learning groups HashSet<Identity> identitiesInGroups = new HashSet<Identity>(); identitiesInGroups.addAll(cgm.getParticipantsFromLearningGroup(null)); + //fxdiff VCRP-1,2: access control of resources + identitiesInGroups.addAll(cgm.getParticipants()); // all identities with result and/or in learning groups HashSet<Identity> identitiesAll = new HashSet<Identity>(); @@ -138,6 +140,8 @@ public class ChecklistManageCheckpointsController extends BasicController { // collect all identities in learning groups HashSet<Identity> identitiesInGroups = new HashSet<Identity>(); identitiesInGroups.addAll(cgm.getParticipantsFromLearningGroup(null)); + //fxdiff VCRP-1,2: access control of resources + identitiesInGroups.addAll(cgm.getParticipants()); allIdentities.addAll(identitiesInGroups); // collect all learning groups diff --git a/src/main/java/de/bps/olat/portal/institution/InstitutionPortletRunController.java b/src/main/java/de/bps/olat/portal/institution/InstitutionPortletRunController.java index b35029907fc5275df3ad90c7131e38fb942c4e9d..94b484719cb854f94d2e0c8ea783866a4ed6503d 100644 --- a/src/main/java/de/bps/olat/portal/institution/InstitutionPortletRunController.java +++ b/src/main/java/de/bps/olat/portal/institution/InstitutionPortletRunController.java @@ -183,7 +183,7 @@ public class InstitutionPortletRunController extends BasicController { DTab dt = dts.getDTab(ores); if (dt == null) { // does not yet exist -> create and add - dt = dts.createDTab(ores, re.getDisplayname()); + dt = dts.createDTab(ores, re, re.getDisplayname()); if (dt == null) return; Controller launchController = ControllerFactory.createLaunchController(ores, null, ureq, dt.getWindowControl(), true); dt.setController(launchController); diff --git a/src/main/java/de/bps/olat/user/ChangeEMailController.java b/src/main/java/de/bps/olat/user/ChangeEMailController.java index 95d709acbbf7ce9bd66d4861b2412138585eed05..21c322dde4a0fc28df1c8c08d564b55bb19165d8 100644 --- a/src/main/java/de/bps/olat/user/ChangeEMailController.java +++ b/src/main/java/de/bps/olat/user/ChangeEMailController.java @@ -45,7 +45,7 @@ public class ChangeEMailController extends DefaultController { protected static final String PACKAGE = ProfileAndHomePageEditController.class.getPackage().getName(); protected static final String CHANGE_EMAIL_ENTRY = "change.email.login"; - public static final int TIME_OUT = 3; + public static int TIME_OUT = 3; protected Translator pT; protected String emKey; diff --git a/src/main/java/de/bps/onyx/plugin/course/nodes/iq/IQEditReplaceWizard.java b/src/main/java/de/bps/onyx/plugin/course/nodes/iq/IQEditReplaceWizard.java index 90df410f3332d9f9d44e68d680e50a33a35e6ef7..0e3daea45d9d5efce3ef76e1f765d5f51d1de944 100644 --- a/src/main/java/de/bps/onyx/plugin/course/nodes/iq/IQEditReplaceWizard.java +++ b/src/main/java/de/bps/onyx/plugin/course/nodes/iq/IQEditReplaceWizard.java @@ -32,6 +32,8 @@ import org.olat.core.gui.control.generic.wizard.WizardController; import org.olat.core.helpers.Settings; import org.olat.core.id.Identity; import org.olat.core.logging.OLATRuntimeException; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailNotificationEditController; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerWithTemplate; @@ -147,7 +149,9 @@ public class IQEditReplaceWizard extends WizardController { recipientsCC = new ArrayList<Identity>(); recipientsCC.add(ureq.getIdentity()); } - MailerWithTemplate.getInstance().sendMailAsSeparateMails(learners, recipientsCC, null, mailCtr.getMailTemplate(), ureq.getIdentity()); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(wControl.getBusinessControl().getAsString()); + MailerWithTemplate.getInstance().sendMailAsSeparateMails(context, learners, recipientsCC, null, mailCtr.getMailTemplate(), ureq.getIdentity()); } fireEvent(ureq, Event.DONE_EVENT); } else if (source == searchCtr && event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) { diff --git a/src/main/java/de/tuchemnitz/wizard/workflows/coursecreation/CourseCreationMailHelper.java b/src/main/java/de/tuchemnitz/wizard/workflows/coursecreation/CourseCreationMailHelper.java index d4113604899b629c1b5c4ef0649f3bec5f8b2456..d3816d101187bf07973bd6af7f0bebef456bf4fb 100644 --- a/src/main/java/de/tuchemnitz/wizard/workflows/coursecreation/CourseCreationMailHelper.java +++ b/src/main/java/de/tuchemnitz/wizard/workflows/coursecreation/CourseCreationMailHelper.java @@ -33,6 +33,8 @@ import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; import org.olat.core.logging.Tracing; import org.olat.core.util.Util; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerResult; import org.olat.core.util.mail.MailerWithTemplate; @@ -105,7 +107,8 @@ public class CourseCreationMailHelper { // nothing to do } }; - return MailerWithTemplate.getInstance().sendMail(ureq.getIdentity(), null, null, template, null); + //fxdiff VCRP-16: intern mail system + return MailerWithTemplate.getInstance().sendRealMail(ureq.getIdentity(), template); } } diff --git a/src/main/java/org/olat/admin/user/SendTokenToUserForm.java b/src/main/java/org/olat/admin/user/SendTokenToUserForm.java index 33d3a0df0547a22aaafb7f307e8cb239f8a7956c..8e11435b514c092965b36861c422d7c553361f87 100644 --- a/src/main/java/org/olat/admin/user/SendTokenToUserForm.java +++ b/src/main/java/org/olat/admin/user/SendTokenToUserForm.java @@ -163,8 +163,8 @@ public class SendTokenToUserForm extends FormBasicController { // nothing to do } }; - - MailerResult result = MailerWithTemplate.getInstance().sendMail(user, null, null, mailTempl, null); + //fxdiff VCRP-16: intern mail system + MailerResult result = MailerWithTemplate.getInstance().sendRealMail(user, mailTempl); if(result.getReturnCode() == 0) { showInfo("email.sent"); } else { diff --git a/src/main/java/org/olat/admin/user/delete/BulkDeleteController.java b/src/main/java/org/olat/admin/user/delete/BulkDeleteController.java index 3cc97216a69b0a80c4fbf1c476877d04716ee833..60859f9d370b05afd9fbad8a7ec1bdb74bacf0f8 100644 --- a/src/main/java/org/olat/admin/user/delete/BulkDeleteController.java +++ b/src/main/java/org/olat/admin/user/delete/BulkDeleteController.java @@ -151,7 +151,8 @@ public class BulkDeleteController extends BasicController { Emailer mailer = new Emailer(ureq.getLocale()); try { - mailer.sendEmail(lstAddrTO, subject, body); + //fxdiff VCRP-16: intern mail system + mailer.sendEmail(null, lstAddrTO, subject, body); } catch (AddressException e) { Tracing.createLoggerFor(BulkDeleteController.class).error("Notificatoin mail for bulk deletion could not be sent"); } catch (MessagingException e) { diff --git a/src/main/java/org/olat/commons/info/manager/InfoMessageFrontendManagerImpl.java b/src/main/java/org/olat/commons/info/manager/InfoMessageFrontendManagerImpl.java index e1cd35ca4a030697d84207d8a65631334a4e025f..9c9fad087e032ac9b1032e84b2a78deb0462bc2f 100644 --- a/src/main/java/org/olat/commons/info/manager/InfoMessageFrontendManagerImpl.java +++ b/src/main/java/org/olat/commons/info/manager/InfoMessageFrontendManagerImpl.java @@ -40,6 +40,8 @@ import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.event.MultiUserEvent; import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.Emailer; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; /** * @@ -124,7 +126,9 @@ public class InfoMessageFrontendManagerImpl extends InfoMessageFrontendManager { if(!StringHelper.containsNonWhitespace(body)) { body = infoMessage.getMessage(); } - send = mailer.sendEmail(contacts, subject, body); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(mailFormatter.getBusinessPath()); + send = mailer.sendEmail(context, contacts, subject, body); } catch (AddressException e) { logError("Cannot send info messages", e); } catch (MessagingException e) { diff --git a/src/main/java/org/olat/commons/info/manager/MailFormatter.java b/src/main/java/org/olat/commons/info/manager/MailFormatter.java index 3514e93a9cfc7083abe552a95455a7c65641d1f9..786d99224e3a3885d61aa69d132a0c702ba32b64 100644 --- a/src/main/java/org/olat/commons/info/manager/MailFormatter.java +++ b/src/main/java/org/olat/commons/info/manager/MailFormatter.java @@ -38,4 +38,6 @@ public interface MailFormatter { public String getSubject(InfoMessage msg); public String getBody(InfoMessage msg); + //fxdiff VCRP-16: intern mail system + public String getBusinessPath(); } diff --git a/src/main/java/org/olat/commons/info/ui/InfoCourseNodeResourceable.java b/src/main/java/org/olat/commons/info/ui/InfoCourseNodeResourceable.java new file mode 100644 index 0000000000000000000000000000000000000000..af9561e7bb4ecf30fad390d067485de68ca96584 --- /dev/null +++ b/src/main/java/org/olat/commons/info/ui/InfoCourseNodeResourceable.java @@ -0,0 +1,23 @@ +package org.olat.commons.info.ui; + +import org.olat.core.id.OLATResourceable; +import org.olat.core.util.resource.OresHelper; +import org.olat.course.CourseModule; + +public class InfoCourseNodeResourceable implements OLATResourceable { + private final Long resId; + + public InfoCourseNodeResourceable(Long resId) { + this.resId = resId; + } + + @Override + public String getResourceableTypeName() { + return OresHelper.calculateTypeName(CourseModule.class); + } + + @Override + public Long getResourceableId() { + return resId; + } +} diff --git a/src/main/java/org/olat/commons/info/ui/InfoDisplayHelper.java b/src/main/java/org/olat/commons/info/ui/InfoDisplayHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..439ad96ba7abd5829601c5b12cad502c5d5a6b18 --- /dev/null +++ b/src/main/java/org/olat/commons/info/ui/InfoDisplayHelper.java @@ -0,0 +1,89 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) frentix GmbH<br> + * http://www.frentix.com<br> + * <p> + */ + +package org.olat.commons.info.ui; + +import java.text.DateFormat; + +import org.olat.commons.info.model.InfoMessage; +import org.olat.core.gui.translator.Translator; +import org.olat.core.id.User; +import org.olat.core.id.UserConstants; +import org.olat.core.util.Formatter; +import org.olat.core.util.StringHelper; + +/** + * + * Description:<br> + * Small helper class to format some datas of the InfoMessage for display. + * + * <P> + * Initial Date: 28 jul. 2010 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class InfoDisplayHelper { + + private final DateFormat formatter; + private final Translator translator; + + public InfoDisplayHelper(Translator translator) { + this.formatter = DateFormat.getDateInstance(DateFormat.MEDIUM, translator.getLocale()); + this.translator = translator; + } + + public String getAuthor(InfoMessage info) { + User user = info.getAuthor().getUser(); + String formattedName = user.getProperty(UserConstants.FIRSTNAME, null) + + " " + user.getProperty(UserConstants.LASTNAME, null); + return formattedName; + } + + + public String getInfos(InfoMessage info) { + String formattedName = getAuthor(info); + String creationDate = formatter.format(info.getCreationDate()); + String msgAddInfos = translator.translate("display.info", new String[]{formattedName, creationDate}); + return msgAddInfos; + } + + public boolean isModified(InfoMessage info) { + return info.getModifier() != null; + } + + public String getModifier(InfoMessage info) { + if(info.getModifier() == null) return "";//return empty string for velocity + + User user = info.getModifier().getUser(); + String formattedName = user.getProperty(UserConstants.FIRSTNAME, null) + + " " + user.getProperty(UserConstants.LASTNAME, null); + String creationDate = formatter.format(info.getModificationDate()); + String msgAddInfos = translator.translate("display.modifier", new String[]{formattedName, creationDate}); + return msgAddInfos; + } + + public String getMessage(InfoMessage info) { + String message = info.getMessage(); + if(StringHelper.containsNonWhitespace(message)) { + return Formatter.escWithBR(message).toString(); + } + return ""; + } +} diff --git a/src/main/java/org/olat/core/commons/persistence/DB.java b/src/main/java/org/olat/core/commons/persistence/DB.java index 6cffbb0defc4ee509f41da4b169533ca994d44d8..528e5c7b98681753d16d9b5530ff7e1dcb0b567b 100644 --- a/src/main/java/org/olat/core/commons/persistence/DB.java +++ b/src/main/java/org/olat/core/commons/persistence/DB.java @@ -24,6 +24,7 @@ package org.olat.core.commons.persistence; import java.util.List; +import org.hibernate.Query; import org.hibernate.stat.Statistics; import org.hibernate.type.Type; import org.olat.core.id.Persistable; @@ -221,4 +222,22 @@ public interface DB { * @return True if any errors occured in the previous DB call. */ public boolean isError(); + + + // + // fxdiff + // Extensions used for native SQL queries + // + /** + * Create a named hibernate query for the given name. Optionally the database + * vendor is prepended to load database specific queries if available. Use + * this only when absolutely necessary. + * + * @param queryName The query name + * @param vendorSpecific true: prepend the database vendor name to the query + * name, e.g. mysql_queryName; false: use queryName as is + * @return the query or NULL if no such named query exists + */ + public DBQuery createNamedQuery(final String queryName, boolean vendorSpecific); + } \ No newline at end of file diff --git a/src/main/java/org/olat/core/commons/persistence/DBImpl.java b/src/main/java/org/olat/core/commons/persistence/DBImpl.java index 0d4493290e6bee529ae9acbe3e33d1394423abb4..e9046e6b5c66b4d68c385d236b7f0b49645e93f8 100644 --- a/src/main/java/org/olat/core/commons/persistence/DBImpl.java +++ b/src/main/java/org/olat/core/commons/persistence/DBImpl.java @@ -39,7 +39,6 @@ import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; -import javax.security.auth.DestroyFailedException; import org.hibernate.HibernateException; import org.hibernate.Session; @@ -888,4 +887,36 @@ public class DBImpl extends LogDelegator implements DB, Destroyable { } } } + + // + // fxdiff qti-statistics (praktikum MK) + // Extensions used for native SQL queries + // + String dbVendor = null; + /** + * [used by spring] + * @param dbVendor + */ + public void setDbvendor(String dbVendor) { + this.dbVendor = dbVendor; + } + + /** + * Create a named hibernate query for the given name. Optionally the database + * vendor is prepended to load database specific queries if available. Use + * this only when absolutely necessary. + * + * @param queryName The query name + * @param vendorSpecific true: prepend the database vendor name to the query + * name, e.g. mysql_queryName; false: use queryName as is + * @return the query or NULL if no such named query exists + */ + public DBQuery createNamedQuery(final String queryName, boolean vendorSpecific) { + if (queryName == null) { + throw new AssertException("queryName must not be NULL"); + } + + beginTransaction(queryName); + return getDBManager().createNamedQuery(queryName, dbVendor, vendorSpecific); + } } diff --git a/src/main/java/org/olat/core/commons/persistence/DBManager.java b/src/main/java/org/olat/core/commons/persistence/DBManager.java index 42c11362dbad01cf75549a23f653b0fafd6da194..127b3b64c429281080ded44ef7a82f23c21e12e6 100644 --- a/src/main/java/org/olat/core/commons/persistence/DBManager.java +++ b/src/main/java/org/olat/core/commons/persistence/DBManager.java @@ -28,6 +28,7 @@ import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.type.Type; +import org.olat.core.logging.AssertException; import org.olat.core.logging.DBRuntimeException; import org.olat.core.logging.Tracing; import org.olat.core.manager.BasicManager; @@ -273,6 +274,34 @@ class DBManager extends BasicManager { return dbq; } + DBQuery createNamedQuery(final String queryName, String dbVendor, boolean vendorSpecific) { + if (queryName == null) { + throw new AssertException("queryName must not be NULL"); + } + Query q= null; + DBQuery dbq = null; + if (vendorSpecific) { + String finalQueryName = vendorSpecific ? dbVendor + "_" + queryName : queryName; + q = this.getSession().getNamedQuery(finalQueryName); + if (q == null) { + // try fallback with normal query + q = this.getSession().getNamedQuery(queryName); + } + if (q == null) { + String msg = "Can not create namedQuery::" + finalQueryName; + if (vendorSpecific) { + msg += " for dbvendor::" + dbVendor + " and non db specific::" + queryName; + } + msg += ", named query does not exist"; + logError(msg, null); + } else { + + dbq = new DBQueryImpl(q); + } + } + return dbq; + } + /** * @param session */ diff --git a/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml b/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml index f79e4beaa4fd009bdfd87e0eba5bb1fc0f5f657f..a4e56696fef4045ffd472afeb1291b2e722ba92d 100644 --- a/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml +++ b/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml @@ -16,7 +16,8 @@ <!-- Hibernate SessionFactory --> <!-- taken from: http://www.shoesobjects.com/blog/2004/11/21/1101083542880.html --> - <bean id="sessionFactory" class="org.olat.core.commons.persistence.OLATLocalSessionFactoryBean"> + <bean id="sessionFactory" class="org.olat.core.commons.persistence.OLATLocalSessionFactoryBean" + depends-on="databaseUpgrader"> <!-- Setting datasource let Spring using the LocalDataSourceConnectionProvider. Some JUnit Tests fail if not the hibernate C3P0ConnectionProvider is used. Not using the dataSource property in the sessionFactory means setting the connection in the hibernateProperties. DataSources are still defined for the Upgrader and the Statistics feature. @@ -93,6 +94,7 @@ <bean id="database" class="org.olat.core.commons.persistence.DBImpl" destroy-method="destroy"> <property name="sessionFactory" ref="sessionFactory"/> + <property name="dbvendor" value="${db.vendor}" /> </bean> <bean id="persistenceHelper" class="org.olat.core.commons.persistence.PersistenceHelper"> diff --git a/src/main/java/org/olat/core/dispatcher/ErrorFeedbackMailer.java b/src/main/java/org/olat/core/dispatcher/ErrorFeedbackMailer.java index ffa47b7d30ecd3cf66ae389dee15f00e7a94a4d8..c339033b861e4c50ac275b59d766da09c3e4d8b0 100644 --- a/src/main/java/org/olat/core/dispatcher/ErrorFeedbackMailer.java +++ b/src/main/java/org/olat/core/dispatcher/ErrorFeedbackMailer.java @@ -39,7 +39,7 @@ import org.olat.core.logging.AssertException; import org.olat.core.logging.LogFileParser; import org.olat.core.logging.Tracing; import org.olat.core.util.WebappHelper; -import org.olat.core.util.mail.Emailer; +import org.olat.core.util.mail.manager.MailManager; /** * Description:<br> @@ -54,7 +54,7 @@ public class ErrorFeedbackMailer implements Dispatcher { private static final ErrorFeedbackMailer INSTANCE = new ErrorFeedbackMailer(); private ErrorFeedbackMailer() { - // private since singleton + // private since singleton } protected static ErrorFeedbackMailer getInstance() { @@ -71,67 +71,43 @@ public class ErrorFeedbackMailer implements Dispatcher { String errorNr = feedback.substring(0, feedback.indexOf("\n") - 1); String username = request.getParameter("username"); try { - IdentityManager im = (IdentityManager)CoreSpringFactory.getBean("core.id.IdentityManager"); + IdentityManager im = (IdentityManager) CoreSpringFactory.getBean("core.id.IdentityManager"); Identity ident = im.findIdentityByName(username); - //if null, user may crashed befor getting a valid session, try with guest user instead - if (ident == null) ident = im.findIdentityByName("guest"); - Emailer emailer = new Emailer(ident, false); - String errorNum = parseErrorNumber(errorNr); - Collection logFileEntries = LogFileParser.getErrorToday(errorNum, false); + // if null, user may crashed befor getting a valid session, try with + // guest user instead + if (ident == null) + ident = im.findIdentityByName("guest"); + Collection<String> logFileEntries = LogFileParser.getErrorToday(errorNr, false); StringBuilder out = new StringBuilder(); if (logFileEntries != null) { - for (Iterator iter = logFileEntries.iterator(); iter.hasNext();) { - out.append((String) iter.next()); + for (Iterator<String> iter = logFileEntries.iterator(); iter.hasNext();) { + out.append(iter.next()); } } - emailer.sendEmail(WebappHelper.getMailConfig("mailSupport"), "Feedback from Error Nr.: " + errorNr, request.getParameter("textarea") - + "\n------------------------------------------\n\n --- from user: "+username+" ---" + out.toString()); - } catch (AddressException e) { + String to = WebappHelper.getMailConfig("mailSupport"); + String subject = "Feedback from Error Nr.: " + errorNr; + String body = feedback + "\n------------------------------------------\n\n --- from user: " + username + + " ---" + out.toString(); + MailManager.getInstance().sendExternMessage(ident, null, null, to, null, null, null, subject, body, null, null); + } catch (Exception e) { // error in recipient email address(es) handleException(request, e); return; - } catch (SendFailedException e) { - // error in sending message - // CAUSE: sender email address invalid - handleException(request, e); - return; - } catch (MessagingException e) { - // error in message-subject || .-body - handleException(request, e); - return; - } catch (AssertException e) { - handleException(request, e); - return; - } catch (NullPointerException e) { - handleException(request, e); - return; } - } - private String parseErrorNumber(String errorNr) { - // try with format N<nodeId>-E<errorCode> first - Pattern r1 = Pattern.compile("N[0-9]+-E[0-9]+"); - Matcher m1 = r1.matcher(errorNr); - if (m1.find()) return m1.group(); - - Pattern r2 = Pattern.compile("E[0-9]+"); - Matcher m2 = r2.matcher(errorNr); - if (m2.find()) return m2.group(); - return ""; - - } private void handleException(HttpServletRequest request, Exception e) { String feedback = request.getParameter("textarea"); String username = request.getParameter("username"); - Tracing.logError("Error sending error feedback mail to olat support (" + WebappHelper.getMailConfig("mailSupport") - + ") from: " + username + " with content: " + feedback, e, this.getClass()); + Tracing.logError("Error sending error feedback mail to olat support (" + WebappHelper.getMailConfig("mailSupport") + ") from: " + + username + " with content: " + feedback, e, this.getClass()); } /** - * @see org.olat.core.dispatcher.Dispatcher#execute(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String) + * @see org.olat.core.dispatcher.Dispatcher#execute(javax.servlet.http.HttpServletRequest, + * javax.servlet.http.HttpServletResponse, java.lang.String) */ public void execute(HttpServletRequest request, HttpServletResponse response, String uriPrefix) { sendMail(request); diff --git a/src/main/java/org/olat/core/id/Preferences.java b/src/main/java/org/olat/core/id/Preferences.java index fbcb2273d25ff313dd4ad7c319bd555e7f0d8801..8acd553e10267d19743dda19fcd7f4ad23405eac 100644 --- a/src/main/java/org/olat/core/id/Preferences.java +++ b/src/main/java/org/olat/core/id/Preferences.java @@ -76,6 +76,20 @@ public interface Preferences extends Serializable { */ public void setInformSessionTimeout(boolean b); + /** + * @return True if the user wants to receive a real e-mail too and not only a message in + * the OLAT Inbox + */ + //fxdiff VCRP-16: intern mail system + public String getReceiveRealMail(); + + /** + * @param receiveRealMail Set if the user wants to receive a real e-mail + * and not only a message in the OLAT intern Inbox. + */ + //fxdiff VCRP-16: intern mail system + public void setReceiveRealMail(String receiveRealMail); + /** * Instant Messaging preferences * When enabled the presence messages are shown public diff --git a/src/main/java/org/olat/core/util/mail/ContactList.java b/src/main/java/org/olat/core/util/mail/ContactList.java index 634d08abbc6c6e61a5096eb152f24b8fcef18bb0..58ba292443df8b90cfae7590c6b79b8b10354f1b 100644 --- a/src/main/java/org/olat/core/util/mail/ContactList.java +++ b/src/main/java/org/olat/core/util/mail/ContactList.java @@ -22,17 +22,17 @@ package org.olat.core.util.mail; import java.util.ArrayList; -import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import org.olat.core.id.Identity; import org.olat.core.id.UserConstants; -import org.olat.core.logging.Tracing; +import org.olat.core.logging.LogDelegator; import org.olat.core.util.StringHelper; /** @@ -50,14 +50,13 @@ import org.olat.core.util.StringHelper; * @author patrick */ -public class ContactList { - +public class ContactList extends LogDelegator { private String name; private String description; //container for addresses contributed as strings - private Hashtable stringEmails = new Hashtable(); + private Map<String, String> stringEmails = new Hashtable<String, String>(); //container for addresses contributed as identites - private Hashtable identiEmails = new Hashtable(); + private Map<String, Identity> identiEmails = new Hashtable<String, Identity>(); private boolean emailPrioInstitutional = false; /** @@ -116,11 +115,21 @@ public class ContactList { */ public void add(Identity identity) { String email = identity.getUser().getProperty(UserConstants.EMAIL, null); + //fxdiff VCRP-5 + if (email == null) { + logError("No email available for identity::" + identity.getName() + " - can not add to contact list", null); + return; + } identiEmails.put(keyFrom(email), identity); } public void remove(Identity identity) { String email = identity.getUser().getProperty(UserConstants.EMAIL, null); + //fxdiff VCRP-5 + if (email == null) { + logError("No email available for identity::" + identity.getName() + " - can not remove from contact list", null); + return; + } identiEmails.remove(keyFrom(email)); } @@ -133,24 +142,45 @@ public class ContactList { return name; } + /** + * ContactList-name as String encoded according to + * http://www.ietf.org/rfc/rfc2047.txt + * + * @return String encoded according to RFC2047 + */ + public String getRFC2047Name() { + String rfc2047name; + // try to MIME-encode the name, if this fails, return the name un-encoded + try { + rfc2047name = javax.mail.internet.MimeUtility.encodeWord(name, "UTF-8", null); + } + catch (java.io.UnsupportedEncodingException e) { + logWarn("Error MIME-encoding name: " + e, e); + rfc2047name = name; + } + + return rfc2047name; + } + + /** * ContactList-name as String formatted according to <a href = - * "http://www.rfc.net/rfc2822.html"> RFC2822 </a> + * "http://www.ietf.org/rfc/rfc2822.txt"> RFC2822 </a> * * @return */ public String getRFC2822Name() { - return name + ":"; + return getRFC2047Name() + ":"; } /** * ContactList-name and e-mail adresses as String formatted according to - * http://www.rfc.net/rfc2822.html + * http://www.ietf.org/rfc/rfc2822.txt * * @return */ public String getRFC2822NameWithAddresses() { - return name + ":" + toString() + ";"; + return getRFC2822Name() + toString() + ";"; } /** @@ -168,30 +198,30 @@ public class ContactList { * * @return */ - public ArrayList getEmailsAsStrings() { - ArrayList ret = new ArrayList(stringEmails.values()); + //fxdiff VCRP-16: intern mail system + public List<String> getEmailsAsStrings() { + List<String> ret = new ArrayList<String>(stringEmails.values()); /* * if priority is on institutional email get all the institutional emails * first, if they are present, remove the identity from the hashtable. If * they were not present, the user email is used in the next loop. */ - Enumeration enumeration = identiEmails.elements(); + List<Identity> copy = new ArrayList<Identity>(identiEmails.values()); String addEmail = null; if (emailPrioInstitutional) { - while (enumeration.hasMoreElements()) { - Identity tmp = (Identity) enumeration.nextElement(); + for (Iterator<Identity> it=copy.iterator(); it.hasNext(); ) { + Identity tmp = it.next(); addEmail = tmp.getUser().getProperty(UserConstants.INSTITUTIONALEMAIL, null); if (addEmail != null) { ret.add(addEmail); - identiEmails.remove(tmp); + it.remove(); } } } /* * loops over the (remaining) identities, fetches the user email. */ - while (enumeration.hasMoreElements()) { - Identity tmp = (Identity) enumeration.nextElement(); + for (Identity tmp : copy){ ret.add(tmp.getUser().getProperty(UserConstants.EMAIL, null)); } return ret; @@ -215,13 +245,12 @@ public class ContactList { * * @see java.lang.Object#toString() */ + @Override public String toString() { String retVal = ""; String sep = ""; - ArrayList emails = getEmailsAsStrings(); - Iterator iter = emails.iterator(); - while (iter.hasNext()) { - retVal += sep + (String) iter.next(); + for (String email:getEmailsAsStrings()) { + retVal += sep + email; sep = ", "; } return retVal; @@ -232,10 +261,9 @@ public class ContactList { * * @param listOfIdentity List containing Identites */ - public void addAllIdentites(List listOfIdentity) { - Iterator iter = listOfIdentity.iterator(); - while (iter.hasNext()) { - add((Identity) iter.next()); + public void addAllIdentites(List<Identity> listOfIdentity) { + for (Identity identity:listOfIdentity) { + add(identity); } } @@ -250,11 +278,11 @@ public class ContactList { return InternetAddress.parse(toString()); } - Hashtable getStringEmails() { + public Map<String,String> getStringEmails() { return stringEmails; } - Hashtable getIdentiEmails() { + public Map<String,Identity> getIdentiEmails() { return identiEmails; } @@ -265,7 +293,7 @@ public class ContactList { private void setName(String nameP) { if (!StringHelper.containsNoneOfCoDouSemi(nameP)){ - Tracing.logWarn("Contact list name \"" + nameP + "\" doesn't match "+ StringHelper.ALL_WITHOUT_COMMA_2POINT_STRPNT,null,ContactList.class); + logWarn("Contact list name \"" + nameP + "\" doesn't match "+ StringHelper.ALL_WITHOUT_COMMA_2POINT_STRPNT, null); //replace bad chars with bad char in rfc compliant comments nameP = nameP.replaceAll(":","¦"); nameP = nameP.replaceAll(";","_"); diff --git a/src/main/java/org/olat/core/util/mail/ContactMessage.java b/src/main/java/org/olat/core/util/mail/ContactMessage.java index 7e4cc33f8a1bab27aac611dc2107de89ac7cf8fc..bbcb1eba3d7c2258d434a40d4b297f7a44b8240d 100644 --- a/src/main/java/org/olat/core/util/mail/ContactMessage.java +++ b/src/main/java/org/olat/core/util/mail/ContactMessage.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; +import java.util.Map; import org.olat.core.id.Identity; @@ -98,11 +99,8 @@ public class ContactMessage { } private ContactList cleanEMailList(ContactList emailList) { - Hashtable identityEmails = emailList.getIdentiEmails(); - Enumeration enumeration = identityEmails.elements(); String value = ""; - while (enumeration.hasMoreElements()) { - Identity identity = (Identity) enumeration.nextElement(); + for (Identity identity: emailList.getIdentiEmails().values()) { List<Identity> singleIdentityList = new ArrayList<Identity>(); singleIdentityList.add(identity); MailerResult result = new MailerResult(); diff --git a/src/main/java/org/olat/core/util/mail/Emailer.java b/src/main/java/org/olat/core/util/mail/Emailer.java index ee1467d03fa6a15aecf829b61c6605d6434f9dac..a3a8700eeb9ae2b633da79ee055fb185408266ef 100644 --- a/src/main/java/org/olat/core/util/mail/Emailer.java +++ b/src/main/java/org/olat/core/util/mail/Emailer.java @@ -23,16 +23,12 @@ package org.olat.core.util.mail; import java.io.File; -import java.util.Date; import java.util.List; import java.util.Locale; import javax.mail.MessagingException; import javax.mail.SendFailedException; -import javax.mail.Message.RecipientType; import javax.mail.internet.AddressException; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; import org.olat.core.gui.translator.PackageTranslator; import org.olat.core.helpers.Settings; @@ -43,6 +39,7 @@ import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; +import org.olat.core.util.mail.manager.MailManager; /** * @@ -54,6 +51,7 @@ import org.olat.core.util.i18n.I18nManager; */ public class Emailer { private String mailfrom; + private Identity mailFromIdentity; private String footer; // footer appended to the end of the mail /** @@ -63,12 +61,21 @@ public class Emailer { * @param locale locale that should be used for message localization */ public Emailer(Locale locale) { - this.mailfrom = WebappHelper.getMailConfig("mailFrom"); + this.mailfrom = WebappHelper.getMailConfig("mailReplyTo"); // initialize the mail footer with info about this OLAt installation PackageTranslator trans = new PackageTranslator(Util.getPackageName(Emailer.class), locale); footer = trans.translate("footer.no.userdata", new String[] { Settings.getServerContextPathURI() }); } + //fxdiff + public String getFooter() { + return footer; + } + + public void setFooter(String footer) { + this.footer = footer; + } + /** * Constructs an Emailer which derives its <b>mail from address </b> from the * given <code>Identity</code>. The <b>mail host </b> used to send the @@ -102,17 +109,12 @@ public class Emailer { } } this.mailfrom = myMailfrom; + //fxdiff VCRP-16: intern mail system + this.mailFromIdentity = mailFromIdentity; // initialize the mail footer with infos about this OLAT installation and the user who sent the mail User user = mailFromIdentity.getUser(); - Locale locale = I18nManager.getInstance().getLocaleOrDefault(user.getPreferences().getLanguage()); - - PackageTranslator trans = new PackageTranslator(Util.getPackageName(Emailer.class), locale); - String institution = user.getProperty(UserConstants.INSTITUTIONALNAME, null); - if (institution == null) institution = ""; - footer = trans.translate("footer.with.userdata", new String[] { user.getProperty(UserConstants.FIRSTNAME, null), user.getProperty(UserConstants.LASTNAME, null), mailFromIdentity.getName(), - institution, Settings.getServerContextPathURI() }); - + footer = MailHelper.getMailFooter(locale, mailFromIdentity); } /** @@ -133,59 +135,20 @@ public class Emailer { * @throws AddressException * @throws MessagingException */ - public boolean sendEmail(List<ContactList> listOfContactLists, String subject, String body) throws AddressException, MessagingException { - return sendEmail(listOfContactLists, subject, body, null); + //fxdiff VCRP-16: intern mail system + public boolean sendEmail(MailContext context, List<ContactList> listOfContactLists, String subject, String body) throws AddressException, MessagingException { + return sendEmail(context, listOfContactLists, subject, body, null); } - - public boolean sendEmail(List<ContactList> listOfContactLists, String subject, String body, List<File> attachments) throws AddressException, MessagingException { - /* - * if the mailhost was not set in the olat.local.properties, we assume that no - * emailing is wished. - */ - if (MailHelper.getMailhost() == null || MailHelper.getMailhost().equals("") || ((MailHelper.getMailhost() instanceof String) && ((String)MailHelper.getMailhost()).equalsIgnoreCase("disabled"))) return false; - MimeMessage msg = MailHelper.createMessage(); - msg.setFrom(new InternetAddress(this.mailfrom)); - msg.setSubject(subject, "utf-8"); - msg.setText(body + footer, "utf-8"); - msg.setSentDate(new Date()); - for (ContactList tmp : listOfContactLists) { - InternetAddress groupName[] = InternetAddress.parse(tmp.getRFC2822Name() + ";"); - InternetAddress members[] = tmp.getEmailsAsAddresses(); - msg.addRecipients(RecipientType.TO, groupName); - msg.addRecipients(RecipientType.BCC, members); - } - msg.saveChanges(); - - File[] attachmentsArray = null; - if(attachments != null && !attachments.isEmpty()) { - attachmentsArray = attachments.toArray(new File[attachments.size()]); - } - - MailerResult result = new MailerResult(); - MailHelper.sendMessage(msg.getFrom()[0], msg.getRecipients(RecipientType.TO), msg.getRecipients(RecipientType.CC), msg - .getRecipients(RecipientType.BCC), body + footer, subject, attachmentsArray, result); + //fxdiff VCRP-16: intern mail system + public boolean sendEmail(MailContext context, List<ContactList> listOfContactLists, String subject, String body, List<File> attachments) throws AddressException, MessagingException { + body += footer; + MailerResult result = MailManager.getInstance().sendMessage(context, mailFromIdentity, mailfrom, null, null, null, null, listOfContactLists, null, subject, body, attachments); return result.getReturnCode() == MailerResult.OK; } - - public boolean sendEmailCC(String cc, String subject, String body, List<File> attachments) throws AddressException, MessagingException { - if (MailHelper.getMailhost() == null || MailHelper.getMailhost().equals("") || ((MailHelper.getMailhost() instanceof String) && ((String)MailHelper.getMailhost()).equalsIgnoreCase("disabled"))) return false; - MimeMessage msg = MailHelper.createMessage(); - msg.setFrom(new InternetAddress(mailfrom)); - msg.setRecipients(RecipientType.CC, InternetAddress.parse(cc)); - msg.setSubject(subject, "utf-8"); - msg.setText(body + footer, "utf-8"); - msg.setSentDate(new Date()); - msg.saveChanges(); - MailerResult result = new MailerResult(); - - File[] attachmentsArray = null; - if(attachments != null && !attachments.isEmpty()) { - attachmentsArray = attachments.toArray(new File[attachments.size()]); - } - - MailHelper.sendMessage(msg.getFrom()[0], msg.getRecipients(RecipientType.TO), msg.getRecipients(RecipientType.CC), msg - .getRecipients(RecipientType.BCC), body + footer, subject, attachmentsArray, result); - return true; + //fxdiff VCRP-16: intern mail system + public boolean sendEmailCC(MailContext context, Identity cc, String subject, String body, List<File> attachments) throws AddressException, MessagingException { + MailerResult result = MailManager.getInstance().sendMessage(context, mailFromIdentity, mailfrom, null, null, cc, null, null, null, subject, body, attachments); + return result.getReturnCode() == MailerResult.OK; } /** @@ -198,37 +161,12 @@ public class Emailer { * @throws MessagingException * TODO:gs handle exceptions internally and may return some error codes or so to get rid of dependecy of mail/activatoin jars in olat */ + //fxdiff VCRP-16: intern mail system public boolean sendEmail(String mailto, String subject, String body) throws AddressException, SendFailedException, MessagingException { - return sendEmail(mailfrom, mailto, subject, body); - } - - private boolean sendEmail(String from, String mailto, String subject, String body) throws AddressException, SendFailedException, - MessagingException { - /* - * if the mailhost was not set in the olat.local.properties, we assume that no - * emailing is wished. - */ - if (MailHelper.getMailhost() == null || MailHelper.getMailhost().equals("") || ((MailHelper.getMailhost() instanceof String) && ((String)MailHelper.getMailhost()).equalsIgnoreCase("disabled"))) return false; - MimeMessage msg = MailHelper.createMessage(); - msg.setFrom(new InternetAddress(from)); - msg.setRecipients(RecipientType.TO, InternetAddress.parse(mailto)); - msg.setSubject(subject, "utf-8"); - msg.setText(body + footer, "utf-8"); - msg.setSentDate(new Date()); - msg.saveChanges(); - MailerResult result = new MailerResult(); - MailHelper.sendMessage(msg.getFrom()[0], msg.getRecipients(RecipientType.TO), msg.getRecipients(RecipientType.CC), msg - .getRecipients(RecipientType.BCC), body + footer, subject, null, result); - return true; - } - - static InternetAddress asInternetAddressArray(String address) { - InternetAddress ia = null; - try { - ia = new InternetAddress(address); - } catch (AddressException ae) { - throw new RuntimeException("Error in InternetAddress : " + address); - } - return ia; + //OK context + body += footer; + //TO + MailerResult result = MailManager.getInstance().sendMessage(null, mailFromIdentity, mailfrom, null, mailto, null, null, null, null, subject, body, null); + return result.getReturnCode() == MailerResult.OK; } } \ No newline at end of file diff --git a/src/main/java/org/olat/core/util/mail/MailContextImpl.java b/src/main/java/org/olat/core/util/mail/MailContextImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..fbde6c23f4875d5def8580c861af79dd2fd165ce --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/MailContextImpl.java @@ -0,0 +1,119 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail; + +import org.olat.core.id.OLATResourceable; + + +/** + * + * Description:<br> + * A default implementation of the mail context + * + * <P> + * Initial Date: 30 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailContextImpl implements MailContext { + + private String resourseableTypeName; + private Long resourceableId; + private String resSubPath; + private String businessPath; + + public MailContextImpl() { + // + } + + public MailContextImpl(OLATResourceable ores) { + this(ores, null, null); + } + + public MailContextImpl(String businessPath) { + this(null, null, businessPath); + } + + public MailContextImpl(OLATResourceable ores, String resSubPath, String businessPath) { + setOLATResourceable(ores); + this.resSubPath = resSubPath; + this.businessPath = businessPath; + } + + @Override + public OLATResourceable getOLATResourceable() { + final Long id = resourceableId; + final String name = resourseableTypeName; + if(id == null || name == null) return null; + + return new OLATResourceable() { + @Override + public Long getResourceableId() { + return id; + } + + @Override + public String getResourceableTypeName() { + return name; + } + }; + } + + public void setOLATResourceable(OLATResourceable ores) { + if(ores != null) { + resourseableTypeName = ores.getResourceableTypeName(); + resourceableId = ores.getResourceableId(); + } + } + + @Override + public String getResSubPath() { + return resSubPath; + } + + public void setResSubPath(String resSubPath) { + this.resSubPath = resSubPath; + } + + @Override + public String getBusinessPath() { + return businessPath; + } + + public void setBusinessPath(String businessPath) { + this.businessPath = businessPath; + } + + public String getResourseableTypeName() { + return resourseableTypeName; + } + + public void setResourseableTypeName(String resourseableTypeName) { + this.resourseableTypeName = resourseableTypeName; + } + + public Long getResourceableId() { + return resourceableId; + } + + public void setResourceableId(Long resourceableId) { + this.resourceableId = resourceableId; + } +} diff --git a/src/main/java/org/olat/core/util/mail/MailHelper.java b/src/main/java/org/olat/core/util/mail/MailHelper.java index b90605f4b8875f7db6564d86b21ec95afffe416f..dcf49f34a9de49545221034d0e3cc90cbeee955d 100644 --- a/src/main/java/org/olat/core/util/mail/MailHelper.java +++ b/src/main/java/org/olat/core/util/mail/MailHelper.java @@ -22,27 +22,16 @@ package org.olat.core.util.mail; import java.io.File; -import java.util.Date; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Properties; -import javax.activation.DataHandler; -import javax.activation.DataSource; -import javax.activation.FileDataSource; import javax.mail.Address; import javax.mail.Authenticator; -import javax.mail.BodyPart; -import javax.mail.MessagingException; -import javax.mail.Multipart; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.Message.RecipientType; -import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.translator.PackageTranslator; @@ -52,10 +41,13 @@ import org.olat.core.id.Identity; import org.olat.core.id.User; import org.olat.core.id.UserConstants; import org.olat.core.logging.Tracing; +import org.olat.core.util.ArrayHelper; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nModule; +import org.olat.user.UserManager; +import org.olat.user.propertyhandlers.UserPropertyHandler; /** * Description:<br> @@ -111,27 +103,8 @@ public class MailHelper { * * @return MimeMessage */ - public static MimeMessage createMessage() { - Properties p = new Properties(); - p.put("mail.smtp.host", mailhost); - p.put("mail.smtp.timeout", mailhostTimeout); - p.put("mail.smtp.connectiontimeout", mailhostTimeout); - p.put("mail.smtp.ssl.enable", sslEnabled); - p.put("mail.smtp.ssl.checkserveridentity", sslCheckCertificate); - Session mailSession; - if (smtpAuth == null) { - mailSession = javax.mail.Session.getInstance(p); - } else { - // use smtp authentication from configuration - p.put("mail.smtp.auth", "true"); - mailSession = Session.getDefaultInstance(p, smtpAuth); - } - if (Tracing.isDebugEnabled(MailHelper.class)) { - // enable mail session debugging on console - mailSession.setDebug(true); - } - return new MimeMessage(mailSession); - } +//fxdiff VCRP-16: intern mail system + //public static MimeMessage createMessage() /** * create MimeMessage from given fields, this may be used for creation of @@ -146,70 +119,17 @@ public class MailHelper { * @param result * @return */ - public static MimeMessage createMessage(Address from, Address[] recipients, Address[] recipientsCC, Address[] recipientsBCC, String body, - String subject, File[] attachments, MailerResult result) { - if (Tracing.isDebugEnabled(MailHelper.class)) { - doDebugMessage(from, recipients, recipientsCC, recipientsBCC, body, subject, attachments); - } - - MimeMessage msg = MailHelper.createMessage(); - try { - // TO, CC and BCC - msg.setFrom(from); - msg.setRecipients(RecipientType.TO, recipients); - if (recipientsCC != null) { - msg.setRecipients(RecipientType.CC, recipientsCC); - } - if (recipientsBCC != null) { - msg.setRecipients(RecipientType.BCC, recipientsBCC); - } - // message data - msg.setSubject(subject, "utf-8"); + //fxdiff VCRP-16: intern mail system + //protected static MimeMessage createMessage(Address from, Address[] recipients, Address[] recipientsCC, Address[] recipientsBCC, String body, - if (attachments != null && attachments.length > 0) { - // with attachment use multipart message - Multipart multipart = new MimeMultipart(); - // 1) add body part - BodyPart messageBodyPart = new MimeBodyPart(); - messageBodyPart.setText(body); - multipart.addBodyPart(messageBodyPart); - // 2) add attachments - for (File attachmentFile : attachments) { - // abort if attachment does not exist - if (attachmentFile == null || !attachmentFile.exists()) { - result.setReturnCode(MailerResult.ATTACHMENT_INVALID); - Tracing.logError("Tried to send mail wit attachment that does not exist::" - + (attachmentFile == null ? null : attachmentFile.getAbsolutePath()), MailHelper.class); - return msg; - } - messageBodyPart = new MimeBodyPart(); - DataSource source = new FileDataSource(attachmentFile); - messageBodyPart.setDataHandler(new DataHandler(source)); - messageBodyPart.setFileName(attachmentFile.getName()); - multipart.addBodyPart(messageBodyPart); - } - // Put parts in message - msg.setContent(multipart); - } else { - // without attachment everything is easy, just set as text - msg.setText(body, "utf-8"); - } - msg.setSentDate(new Date()); - msg.saveChanges(); - } catch (MessagingException e) { - result.setReturnCode(MailerResult.SEND_GENERAL_ERROR); - Tracing.logWarn("Could not create MimeMessage", e, MailHelper.class); - } - // - return msg; - } /** * Send an email message to the given TO, CC and BCC address. The result will * be stored in the result object. The message can contain attachments.<br> * At this point HTML mails are not supported. * - * @param from Address used as sender address. Must not be NULL + * fxdiff: change from/replyto, see FXOLAT-74 + * @param replyTo Address used as reply-to address. The real sender is a no-reply-adress (see config: mailFrom). Must not be NULL * @param recipients Address array used as sender addresses. Must not be NULL * and contain at lease one address * @param recipientsCC Address array used as CC addresses. Can be NULL @@ -218,34 +138,10 @@ public class MailHelper { * @param subject Subject text of message. Must not be NULL * @param attachments File array used as attachments. Can be NULL * @param result MailerResult object that stores the result code - */ - public static void sendMessage(Address from, Address[] recipients, Address[] recipientsCC, Address[] recipientsBCC, String body, - String subject, File[] attachments, MailerResult result) { - // - MimeMessage msg = createMessage(from, recipients, recipientsCC, recipientsBCC, body, subject, attachments, result); - sendMessage(msg, result); - } - /** - * send email with MimeMessage available - * @param msg - * @param result - */ - public static void sendMessage(MimeMessage msg, MailerResult result){ - try{ - if (mailhost==null || mailhost.length()==0 || mailhost.equalsIgnoreCase("disabled")) { - result.setReturnCode(MailerResult.MAILHOST_UNDEFINED); - Tracing.logInfo("Did not send mail, mailhost undefined", MailHelper.class); - return; - } - if (result.getReturnCode() == MailerResult.OK) { - // now send the mail - Transport.send(msg); - } - } catch (MessagingException e) { - result.setReturnCode(MailerResult.SEND_GENERAL_ERROR); - Tracing.logWarn("Could not send mail", e, MailHelper.class); - } - } + + //fxdiff VCRP-16: intern mail system + //private static void sendMessage(Address from, Address[] recipients, Address[] recipientsCC, Address[] recipientsBCC, String body, + // String subject, File[] attachments, MailerResult result) /** * @return the maximum size allowed for attachements in MB (default 5MB) @@ -282,11 +178,27 @@ public class MailHelper { } // mail sent by a system user User user = sender.getUser(); - String institution = user.getProperty(UserConstants.INSTITUTIONALNAME, null); - if (institution == null) institution = ""; - return trans.translate("footer.with.userdata", new String[] { user.getProperty(UserConstants.FIRSTNAME, null), user.getProperty(UserConstants.LASTNAME, null), sender.getName(), - institution, Settings.getServerContextPathURI() }); + // FXOLAT-356: separate context for mail footer + // username / server-url are always first [0], [1]. + UserManager um = UserManager.getInstance(); + List<UserPropertyHandler> userPropertyHandlers = um.getUserPropertyHandlersFor(MailHelper.class.getCanonicalName(), false); + ArrayList<String> uProps = new ArrayList<String>(userPropertyHandlers.size()+2); + uProps.add(sender.getName()); + uProps.add(Settings.getServerContextPathURI()); + + for (Iterator<UserPropertyHandler> iterator = userPropertyHandlers.iterator(); iterator.hasNext();) { + UserPropertyHandler handler = iterator.next(); + uProps.add(handler.getUserProperty(user, locale)); + } + // add empty strings to prevent non-replaced wildcards like "{5}" etc. in emails. + while (uProps.size() < 15){ + uProps.add(""); + } + + String[] userProps = new String[]{}; + userProps = ArrayHelper.toArray(uProps); + return trans.translate("footer.with.userdata", userProps); } public static String getTitleForFailedUsersError(Locale locale) { diff --git a/src/main/java/org/olat/core/util/mail/MailModule.java b/src/main/java/org/olat/core/util/mail/MailModule.java new file mode 100644 index 0000000000000000000000000000000000000000..7ff60fe87500838d2a73f52e1921dbe6b1d25d40 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/MailModule.java @@ -0,0 +1,155 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ +package org.olat.core.util.mail; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.configuration.AbstractOLATModule; +import org.olat.core.configuration.PersistedProperties; +import org.olat.core.extensions.action.GenericActionExtension; +import org.olat.core.gui.control.Event; +import org.olat.core.util.StringHelper; +import org.olat.core.util.WebappHelper; +import org.olat.core.util.event.FrameworkStartedEvent; +import org.olat.core.util.event.FrameworkStartupEventChannel; + +/** + * + * Description:<br> + * + * + * <P> + * Initial Date: 24 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http.//www.frentix.com + */ +public class MailModule extends AbstractOLATModule { + + private static final String INTERN_MAIL_SYSTEM = "internSystem"; + private static final String RECEIVE_REAL_MAIL_USER_DEFAULT_SETTING = "receiveRealMailUserDefaultSetting"; + + private boolean internSystem; + private boolean receiveRealMailUserDefaultSetting; + + private WebappHelper webappHelper; + + public MailModule() { + //make Spring happy + FrameworkStartupEventChannel.registerForStartupEvent(this); + } + + /** + * [used by Spring] + * @param webappHelper + */ + public void setWebappHelper(WebappHelper webappHelper) { + this.webappHelper = webappHelper; + } + + /** + * [used by Spring] + * @see org.olat.core.configuration.AbstractOLATModule#setPersistedProperties(org.olat.core.configuration.PersistedProperties) + */ + @Override + public void setPersistedProperties(PersistedProperties persistedProperties) { + this.moduleConfigProperties = persistedProperties; + } + + @Override + public void init() { + String internSystemValue = getStringPropertyValue(INTERN_MAIL_SYSTEM, true); + if(StringHelper.containsNonWhitespace(internSystemValue)) { + internSystem = "true".equalsIgnoreCase(internSystemValue); + } + + String receiveRealMailUserDefaultSettingValue = getStringPropertyValue(RECEIVE_REAL_MAIL_USER_DEFAULT_SETTING, true); + if(StringHelper.containsNonWhitespace(receiveRealMailUserDefaultSettingValue)) { + receiveRealMailUserDefaultSetting = "true".equalsIgnoreCase(receiveRealMailUserDefaultSettingValue); + } + } + + @Override + protected void initDefaultProperties() { + internSystem = getBooleanConfigParameter(INTERN_MAIL_SYSTEM, false); + receiveRealMailUserDefaultSetting = getBooleanConfigParameter(RECEIVE_REAL_MAIL_USER_DEFAULT_SETTING, true); + } + + @Override + protected void initFromChangedProperties() { + init(); + } + + /** + * Used the intern mail system. + * @return + */ + public boolean isInternSystem() { + return internSystem; + } + + /** + * @param internSystem + */ + public void setInterSystem(boolean internSystem) { + String internSystemStr = internSystem ? "true" : "false"; + enableExtensions(internSystem); + setStringProperty(INTERN_MAIL_SYSTEM, internSystemStr, true); + } + + private void enableExtensions(boolean enabled){ + try { + ((GenericActionExtension)CoreSpringFactory.getBean("mailAEparent")).setEnabled(enabled); + ((GenericActionExtension)CoreSpringFactory.getBean("mailAEinbox")).setEnabled(enabled); + ((GenericActionExtension)CoreSpringFactory.getBean("mailAEoutbox")).setEnabled(enabled); + } catch (Exception e) { + // do nothing when extension don't exist. + } + } + + @Override + public void event(Event event) { + if(event instanceof FrameworkStartedEvent) { + enableExtensions(isInternSystem()); + } else { + super.event(event); + } + } + + /** + * Users can receive real e-mail too. This setting is the default for + * users. They can change it in Preferences Panel. + * @return + */ + public boolean isReceiveRealMailUserDefaultSetting() { + return receiveRealMailUserDefaultSetting; + } + + public void setReceiveRealMailUserDefaultSetting(boolean realMail) { + String realMailStr = realMail ? "true" : "false"; + setStringProperty(RECEIVE_REAL_MAIL_USER_DEFAULT_SETTING, realMailStr, true); + } + + /** + * Check if the mail host is configured + * @return + */ + public boolean isMailHostEnabled() { + String mailhost = WebappHelper.getMailConfig("mailhost"); + return (StringHelper.containsNonWhitespace(mailhost) && !mailhost.equalsIgnoreCase("disabled")); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/util/mail/MailUIFactory.java b/src/main/java/org/olat/core/util/mail/MailUIFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..0fbf6510c552aeff9aa5d5de026f200b8cbb7834 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/MailUIFactory.java @@ -0,0 +1,60 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.mail.ui.MailContextResolver; +import org.olat.core.util.mail.ui.MailListController; + +/** + * + * Description:<br> + * + * <P> + * Initial Date: 25 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailUIFactory { + + public static Controller createInboxController(UserRequest ureq, WindowControl wControl, MailContextResolver resolver) { + return new MailListController(ureq, wControl, false, resolver); + } + + public static Controller createOutboxController(UserRequest ureq, WindowControl wControl, MailContextResolver resolver) { + return new MailListController(ureq, wControl, true, resolver); + } + + //fxdiff :: FXOLAT-250 we need factory-methods with standard params to create inbox/outbox controllers with the <code>FactoryControllerCreator</code> + // (used for minimalHome / genericmaincontroller) + public static Controller createInboxController(UserRequest ureq, WindowControl wControl){ + MailContextResolver resolver = (MailContextResolver)CoreSpringFactory.getBean("mailBoxExtension"); + return MailUIFactory.createInboxController(ureq, wControl, resolver); + } + + public static Controller createOutboxController(UserRequest ureq, WindowControl wControl){ + MailContextResolver resolver = (MailContextResolver)CoreSpringFactory.getBean("mailBoxExtension"); + return MailUIFactory.createOutboxController(ureq, wControl, resolver); + } + +} diff --git a/src/main/java/org/olat/core/util/mail/MailerResult.java b/src/main/java/org/olat/core/util/mail/MailerResult.java index 15a5d11def8b7826a68638aa6e7d9d8b5bbed5d0..07e0947b5dfda744ba9c589f38a122de3a2e4e59 100644 --- a/src/main/java/org/olat/core/util/mail/MailerResult.java +++ b/src/main/java/org/olat/core/util/mail/MailerResult.java @@ -69,7 +69,7 @@ public class MailerResult { * * @param failedIdentity */ - void addFailedIdentites(Identity failedIdentity) { + public void addFailedIdentites(Identity failedIdentity) { this.failedIdentites.add(failedIdentity); } @@ -78,7 +78,7 @@ public class MailerResult { * * @param returnCode */ - void setReturnCode(int returnCode) { + public void setReturnCode(int returnCode) { this.returnCode = returnCode; } diff --git a/src/main/java/org/olat/core/util/mail/MailerWithTemplate.java b/src/main/java/org/olat/core/util/mail/MailerWithTemplate.java index e2506fc3bfda19823a05816f4d04912bcd9decaa..466c61060f7291e9e8843b4e3660d6037b311061 100644 --- a/src/main/java/org/olat/core/util/mail/MailerWithTemplate.java +++ b/src/main/java/org/olat/core/util/mail/MailerWithTemplate.java @@ -21,18 +21,18 @@ */ package org.olat.core.util.mail; +import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Properties; +import java.util.UUID; import javax.mail.Address; -import javax.mail.MessagingException; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; @@ -44,8 +44,8 @@ import org.apache.velocity.runtime.RuntimeConstants; import org.olat.core.id.Identity; import org.olat.core.id.UserConstants; import org.olat.core.logging.Tracing; -import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; +import org.olat.core.util.mail.manager.MailManager; /** * Description:<br> @@ -104,7 +104,8 @@ public class MailerWithTemplate { public MailerResult sendMailUsingTemplateContext(Identity recipientTO, List<Identity> recipientsCC, List<Identity> recipientsBCC, MailTemplate template, Identity sender) { MailerResult result = new MailerResult(); - sendWithContext(template.getContext(), recipientTO, recipientsCC, recipientsBCC, template, sender, result); + //fxdiff VCRP-16: intern mail system + sendWithContext(template.getContext(), null, null, recipientTO, recipientsCC, recipientsBCC, template, sender, result); return result; } @@ -123,22 +124,10 @@ public class MailerWithTemplate { VelocityContext context = new VelocityContext(); template.putVariablesInMailContext(context, recipientTO); - - MimeMessage msg = createWithContext(context, recipientTO, recipientsCC, recipientsBCC, template, sender, result); - String subject=null; - String body=null; - try { - subject = msg.getSubject(); - // - //assume String because the body text is set via setText(..,"utf-8") - //in the MailHelper - //see also http://java.sun.com/j2ee/1.4/docs/api/javax/mail/internet/MimeMessage.html#getContent() - body = (String)msg.getContent(); - } catch (MessagingException e) { - result.setReturnCode(MailerResult.TEMPLATE_GENERAL_ERROR); - } catch (IOException e) { - result.setReturnCode(MailerResult.TEMPLATE_GENERAL_ERROR); - } + //fxdiff VCRP-16: intern mail system + MessageContent msg = createWithContext(context, recipientTO, recipientsCC, recipientsBCC, template, sender, result); + String subject = msg.getSubject(); + String body = msg.getBody(); return new String[]{subject, body}; } @@ -159,11 +148,25 @@ public class MailerWithTemplate { * @return MailerResult with status and list of identites that could not be * mailed to */ - public MailerResult sendMail(Identity recipientTO, List<Identity> recipientsCC, List<Identity> recipientsBCC, MailTemplate template, + //fxdiff VCRP-16: intern mail system + public MailerResult sendRealMail(Identity recipientTO, MailTemplate template) { + MailerResult result = new MailerResult(); + VelocityContext context = new VelocityContext(); + MessageContent msg = createWithContext(context, recipientTO, null, null, template, null, result); + if(result.getReturnCode() != MailerResult.OK) { + return result; + } + + MailManager.getInstance().sendExternMessage(null, null, recipientTO, null, null, null, null, msg.getSubject(), msg.getBody(), null, result); + return result; + } + + //fxdiff VCRP-16: intern mail system + public MailerResult sendMail(MailContext mCtxt, Identity recipientTO, List<Identity> recipientsCC, List<Identity> recipientsBCC, MailTemplate template, Identity sender) { List<Identity> recipientsTO = new ArrayList<Identity>(); recipientsTO.add(recipientTO); - return sendMailAsSeparateMails(recipientsTO, recipientsCC, recipientsBCC, template, sender); + return sendMailAsSeparateMails(mCtxt, recipientsTO, recipientsCC, recipientsBCC, template, sender); } /** @@ -189,6 +192,13 @@ public class MailerWithTemplate { */ public MailerResult sendMailAsSeparateMails(List<Identity> recipientsTO, List<Identity> recipientsCC, List<Identity> recipientsBCC, MailTemplate template, Identity sender) { + return sendMailAsSeparateMails(null, recipientsTO, recipientsCC, recipientsBCC, template, sender); + } + //fxdiff VCRP-16: intern mail system + public MailerResult sendMailAsSeparateMails(MailContext mCtxt, List<Identity> recipientsTO, List<Identity> recipientsCC, List<Identity> recipientsBCC, + MailTemplate template, Identity sender) { + + String metaId = UUID.randomUUID().toString().replace("-", ""); MailerResult result = new MailerResult(); if (MailHelper.getMailhost() == null) { result.setReturnCode(MailerResult.MAILHOST_UNDEFINED); @@ -200,7 +210,7 @@ public class MailerWithTemplate { // populate velocity context with variables VelocityContext context = new VelocityContext(); template.putVariablesInMailContext(context, recipient); - sendWithContext(context, recipient, null, null, template, sender, result); + sendWithContext(context, mCtxt, metaId, recipient, null, null, template, sender, result); if (!result.getFailedIdentites().contains(recipient)) { isMailSendToRecipient = true; } @@ -213,10 +223,7 @@ public class MailerWithTemplate { // populate velocity context with variables VelocityContext context = new VelocityContext(); template.putVariablesInMailContext(context, recipient); - sendWithContext(context, null, cc, null, template, sender, result); - if (!result.getFailedIdentites().contains(recipient)) { - isMailSendToRecipient = true; - } + sendWithContext(context, mCtxt, metaId, recipient, null, null, template, sender, result); } } if (recipientsBCC != null) { @@ -224,14 +231,14 @@ public class MailerWithTemplate { // populate velocity context with variables VelocityContext context = new VelocityContext(); template.putVariablesInMailContext(context, recipient); - sendWithContext(context, recipient, null, null, template, sender, result); - if (!result.getFailedIdentites().contains(recipient)) { - isMailSendToRecipient = true; - } + sendWithContext(context, mCtxt, metaId, recipient, null, null, template, sender, result); } } if(!isMailSendToRecipient) { result.setReturnCode(MailerResult.RECIPIENT_ADDRESS_ERROR); + }//only one successful to is needed to return OK + else if(isMailSendToRecipient && result.getReturnCode() == MailerResult.RECIPIENT_ADDRESS_ERROR) { + result.setReturnCode(MailerResult.OK); } return result; } @@ -248,7 +255,8 @@ public class MailerWithTemplate { * @param result * @return */ - private MimeMessage createWithContext(VelocityContext context, Identity recipientTO, List<Identity> recipientsCC, List<Identity> recipientsBCC, + //fxdiff VCRP-16: intern mail system + private MessageContent createWithContext(VelocityContext context, Identity recipientTO, List<Identity> recipientsCC, List<Identity> recipientsBCC, MailTemplate template, Identity sender, MailerResult result){ // prepare cc addresses - will stay the same for each mail Address[] addressesCC = createAddressesFromIdentities(recipientsCC, result); @@ -269,39 +277,33 @@ public class MailerWithTemplate { recLocale = I18nManager.getInstance().getLocaleOrDefault(recipientTO.getUser().getPreferences().getLanguage()); }else if(recipientsCC!=null && recipientsCC.size()>0){ recLocale = I18nManager.getInstance().getLocaleOrDefault(recipientsCC.get(0).getUser().getPreferences().getLanguage()); + }else if(recipientsBCC!=null && recipientsBCC.size()>0){ + recLocale = I18nManager.getInstance().getLocaleOrDefault(recipientsBCC.get(0).getUser().getPreferences().getLanguage()); } String subject = subjectWriter.toString(); String body = bodyWriter.toString() + MailHelper.getMailFooter(recLocale, sender) + "\n"; + + // create mime message + return new MessageContent(subject, body); + + } - // add sender to mail - Address from, to; - try { - if (sender == null) { - from = new InternetAddress(WebappHelper.getMailConfig("mailFrom")); - } else { - from = new InternetAddress(sender.getUser().getProperty(UserConstants.EMAIL, null)); - } - } catch (AddressException e) { - result.setReturnCode(MailerResult.SENDER_ADDRESS_ERROR); - return null; + private class MessageContent { + private final String subject; + private final String body; + + public MessageContent(String subject, String body) { + this.subject = subject; + this.body = body; } - Address[] toArray = new Address[1]; - if(recipientTO != null){ - try { - to = new InternetAddress(recipientTO.getUser().getProperty(UserConstants.EMAIL, null)); - } catch (AddressException e) { - result.addFailedIdentites(recipientTO); - // skip this user, go to next one - return null; - } - toArray[0] = to; - }else{ - toArray = new Address[0]; + + public String getSubject() { + return subject; + } + + public String getBody() { + return body; } - - // create mime message - return MailHelper.createMessage(from, toArray, addressesCC, addressesBCC, body, subject, template.getAttachments(), result); - } /** @@ -314,7 +316,8 @@ public class MailerWithTemplate { * @param sender * @param result */ - private void sendWithContext(VelocityContext context, Identity recipientTO, List<Identity> recipientsCC, List<Identity> recipientsBCC, + //fxdiff VCRP-16: intern mail system + private void sendWithContext(VelocityContext context, MailContext mCtxt, String metaId, Identity recipientTO, List<Identity> recipientsCC, List<Identity> recipientsBCC, MailTemplate template, Identity sender, MailerResult result) { List<Identity> identityTO = new ArrayList<Identity>(); if(recipientTO != null) identityTO.add(recipientTO); @@ -343,12 +346,49 @@ public class MailerWithTemplate { failedIdentitiesBCC.removeAll(failedIdentitiesCC); recipientsBCC.removeAll(failedIdentitiesBCC); } - MimeMessage msg = createWithContext(context, recipientTO, recipientsCC, recipientsBCC, template, sender, result); + MessageContent msg = createWithContext(context, recipientTO, recipientsCC, recipientsBCC, template, sender, result); if(msg != null && result.getReturnCode() == MailerResult.OK){ // send mail - MailHelper.sendMessage(msg, result); + List<File> attachmentList = new ArrayList<File>(); + File[] attachments = template.getAttachments(); + if(attachments != null) { + for(File attachment:attachments) { + if(attachment == null || !attachment.exists()) { + result.setReturnCode(MailerResult.ATTACHMENT_INVALID); + } else { + attachmentList.add(attachment); + } + } + } + + List<ContactList> ccList = createContactList(recipientsCC); + List<ContactList> bccList = createContactList(recipientsBCC); + MailerResult mgrResult = MailManager.getInstance().sendMessage(mCtxt, sender, null, recipientTO, null, null, ccList, bccList, + metaId, msg.getSubject(), msg.getBody(), attachmentList); + + if(mgrResult.getReturnCode() != MailerResult.OK) { + result.setReturnCode(mgrResult.getReturnCode()); + } + if(mgrResult.getFailedIdentites() != null) { + for(Identity failedIdentity:mgrResult.getFailedIdentites()) { + result.addFailedIdentites(failedIdentity); + } + } + } } + //fxdiff VCRP-16: intern mail system + private List<ContactList> createContactList(List<Identity> recipients) { + if(recipients == null || recipients.isEmpty()) { + return null; + } + + ContactList contactList = new ContactList(""); + contactList.addAllIdentites(recipients); + List<ContactList> list = new ArrayList<ContactList>(1); + list.add(contactList); + return list; + } /** * Internal Helper: merges a velocity context with a template. diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_ar.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_ar.properties index 6dc8c3292394e38d9734e0aa8f8d9b54c3055bee..3d087698a9ca95ab2b42351d108c9cb05269a389 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_ar.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_ar.properties @@ -8,7 +8,7 @@ chelp.sendMail7=\u0648\u0635\u0641 \u0627\u0644\u0645\u062C\u0645\u0648\u0639\u0 chelp.sendMail8=\u0642\u0627\u0626\u0645\u0629 \u0628\u0627\u0644\u0645\u0642\u0631\u0631\u0627\u062A \u0627\u0644\u062F\u0631\u0627\u0633\u064A\u0629 \u0627\u0644\u062A\u0649 \u062A\u0633\u062A\u062E\u062F\u0645\u0647\u0627 \u0627\u0644\u0645\u062C\u0645\u0648\u0639\u0629. contact.cp.from=\u0646\u0633\u062E\u0629 \u0625\u0644\u0649 \u0627\u0644\u0645\u0631\u0633\u0644 footer.no.userdata=--- \r\n \u062A\u0645 \u0625\u0631\u0633\u0627\u0644 \u0647\u0630\u0647 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u062A\u0644\u0642\u0627\u0626\u064A\u0627\u064B \u0639\u0628\u0631 \u0623\u0648\u0644\u0627\u062A\r\n{0} -footer.with.userdata=--- \r\n{0} {1} ({2})\r\n{3}\r\n\r\n\u062A\u0645 \u0625\u0631\u0633\u0627\u0644 \u0647\u0630\u0647 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u062A\u0644\u0642\u0627\u0626\u064A\u0627\u064B \u0639\u0628\u0631 \u0623\u0648\u0644\u0627\u062A\r\n{4} +footer.with.userdata=--- \r\n{2} {3} ({0})\r\n{4}\r\n\r\n\u062A\u0645 \u0625\u0631\u0633\u0627\u0644 \u0647\u0630\u0647 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u062A\u0644\u0642\u0627\u0626\u064A\u0627\u064B \u0639\u0628\u0631 \u0623\u0648\u0644\u0627\u062A\r\n{1} help.hover.mail-templ=\u0645\u0633\u0627\u0639\u062F\u0629 \u0628\u0634\u0623\u0646 \u0627\u0633\u062A\u062E\u062F\u0627\u0645 \u0646\u0645\u0627\u0630\u062C \u0627\u0644\u0628\u0631\u064A\u062F mailhelper.error.attachment=\u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u0644\u0627 \u064A\u0645\u0643\u0646 \u0625\u0631\u0633\u0627\u0644\u0647\u0627\: \u0627\u0644\u0645\u0631\u0641\u0642\u0627\u062A \u063A\u064A\u0631 \u0635\u0627\u0644\u062D\u0629\u060C \u064A\u0631\u062C\u0649 \u0625\u062E\u0637\u0627\u0631 \u0627\u0644\u0645\u0633\u062A\u0644\u0645\u064A\u0646 \u064A\u062F\u0648\u064A\u0627\u064B. mailhelper.error.failedusers=\u0644\u0627 \u064A\u0645\u0643\u0646 \u0625\u0631\u0633\u0627\u0644 \u0627\u0644\u0628\u0631\u064A\u062F \u0627\u0644\u0627\u0644\u0643\u062A\u0631\u0648\u0646\u0649 \u0625\u0644\u0649 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645\u064A\u0646 \u0627\u0644\u062A\u0627\u0644\u064A\u064A\u0646 \u0648\u0644\u0630\u0627 \u064A\u0631\u062C\u0649 \u0625\u062E\u0637\u0627\u0631\u0647\u0645 \u064A\u062F\u0648\u064A\u0627\u064B\u060C \u0648\u062A\u0637\u0644\u0628 \u0645\u0646\u0647\u0645 \u0627\u0644\u062A\u062D\u0642\u0642 \u0645\u0646 \u0639\u0646\u0627\u0648\u064A\u0646 \u0627\u0644\u0628\u0631\u064A\u062F \u0627\u0644\u0627\u0644\u0643\u062A\u0631\u0648\u0646\u0649 \u0627\u0644\u062E\u0627\u0635\u0629 \u0628\u0647\u0645. diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_bg.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_bg.properties index 2ed4c21f9b39195c9f2f5673ad535e8fda80742e..ebfed8f2077f8fad90d93880a080b7af6cee087f 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_bg.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_bg.properties @@ -8,7 +8,7 @@ chelp.sendMail7=\u0421\u043F\u0438\u0441\u044A\u043A \u043D\u0430 \u043A\u0443\u chelp.sendMail8=\u0421\u043F\u0438\u0441\u044A\u043A \u043D\u0430 \u043A\u0443\u0440\u0441\u043E\u0432\u0435\u0442\u0435, \u0432 \u043A\u043E\u0438\u0442\u043E \u0435 \u0438\u0437\u043F\u043E\u043B\u0437\u0432\u0430\u043D\u0430 \u0442\u0430\u0437\u0438 \u0433\u0440\u0443\u043F\u0430. contact.cp.from=\u041A\u043E\u043F\u0438\u0435\u0442\u043E \u0435 \u0438\u0437\u043F\u0440\u0430\u0442\u0435\u043D\u043E \u043D\u0430 \u0430\u0434\u0440\u0435\u0441\u0430\u043D\u0442\u0430 footer.no.userdata=--- \r\n\u0422\u043E\u0432\u0430 \u0441\u044A\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0435 \u0438\u0437\u043F\u0440\u0430\u0442\u0435\u043D\u043E \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E \u0447\u0440\u0435\u0437 \u0441\u0438\u0441\u0442\u0435\u043C\u0430\u0442\u0430.\r\n{0} -footer.with.userdata=--- \r\n{0} {1} ({2})\r\n{3}\r\n\r\n\u0422\u043E\u0432\u0430 \u0441\u044A\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0435 \u0438\u0437\u043F\u0440\u0430\u0442\u0435\u043D\u043E \u0447\u0440\u0435\u0437 \u0441\u0438\u0441\u0442\u0435\u043C\u0430\u0442\u0430.\r\n{4} +footer.with.userdata=--- \r\n{2} {3} ({0})\r\n{4}\r\n\r\n\u0422\u043E\u0432\u0430 \u0441\u044A\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0435 \u0438\u0437\u043F\u0440\u0430\u0442\u0435\u043D\u043E \u0447\u0440\u0435\u0437 \u0441\u0438\u0441\u0442\u0435\u043C\u0430\u0442\u0430.\r\n{1} help.hover.mail-templ=\u041F\u043E\u043C\u043E\u0449 \u0437\u0430 \u0438\u0437\u043F\u043E\u043B\u0437\u0432\u0430\u043D\u0435 \u043D\u0430 \u0448\u0430\u0431\u043B\u043E\u043D\u0430 \u0437\u0430 \u043F\u043E\u0449\u0430 mailhelper.error.attachment=\u041F\u043E\u0449\u0430\u0442\u0430 \u043D\u0435 \u043C\u043E\u0436\u0435 \u0434\u0430 \u0431\u044A\u0434\u0435 \u0438\u0437\u043F\u0440\u0430\u0442\u0435\u043D\u0430\: \u043D\u0435\u0432\u0430\u043B\u0438\u0434\u043D\u0438 \u043F\u0440\u0438\u0442\u0443\u0440\u043A\u0438. \u041C\u043E\u043B\u044F, \u0443\u0432\u0435\u0434\u043E\u043C\u0435\u0442\u0435 \u0432\u0430\u0448\u0438\u0442\u0435 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u0438 \u0443\u0441\u0442\u043D\u043E. mailhelper.error.failedusers=\u041F\u043E\u0449\u0430\u0442\u0430 \u043D\u0435 \u043C\u043E\u0436\u0435 \u0434\u0430 \u0431\u044A\u0434\u0435 \u0438\u0437\u043F\u0440\u0430\u0442\u0435\u043D\u0430 \u043D\u0430 \u0441\u043B\u0435\u0434\u043D\u0438\u0442\u0435 \u0445\u043E\u0440\u0430. \u041C\u043E\u043B\u044F, \u0443\u0432\u0435\u0434\u043E\u043C\u0435\u0442\u0435 \u0433\u0438 \u0443\u0441\u0442\u043D\u043E \u0438 \u043F\u0440\u043E\u0432\u0435\u0440\u0435\u0442\u0435 \u0442\u0435\u0445\u043D\u0438\u0442\u0435 \u0438-\u043C\u0435\u0439\u043B \u0430\u0434\u0440\u0435\u0441\u0438. diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_cs.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_cs.properties index 7e3876edf3a9310d6058795ae41629560a46acf0..a66329f04429a63a819509083481d7d8e0baccc4 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_cs.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_cs.properties @@ -6,7 +6,7 @@ chelp.sendMail5=Jm\u00E9no skupiny chelp.sendMail6=Popis skupiny chelp.sendMail7=Seznam kurz\u016F, kter\u00E9 u\u017Eivatel pou\u017E\u00EDv\u00E1. footer.no.userdata=\n\n--- \nTato zpr\u00E1va byla posl\u00E1na z OLATu.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\nTato zpr\u00E1va byla posl\u00E1na z OLATu.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\nTato zpr\u00E1va byla posl\u00E1na z OLATu.\n{1} help.hover.mail-templ=N\u00E1pov\u011Bda pro pou\u017E\u00EDv\u00E1n\u00ED \u0161ablon mail\u016F mailhelper.error.attachment=E-mail nemohl b\u00FDt odesl\u00E1n\: \u0161patn\u00E1 p\u0159\u00EDloha. Informujte pros\u00EDm p\u0159\u00EDjemce ru\u010Dn\u011B. mailhelper.error.failedusers=E-mail nemohl b\u00FDt n\u00E1sleduj\u00EDc\u00EDm osob\u00E1m odesl\u00E1n\: Informujte pros\u00EDm p\u0159\u00EDjemce ru\u010Dn\u011B a zkontrolujte jejich e-mailov\u00E9 adresy. diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_da.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_da.properties index 3754fa01a5ee9866fc2e7fb6f766a9368a9f6b50..f70beb4daa744ee8cdeb1a52cf2dceace21b4062 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_da.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_da.properties @@ -1,6 +1,6 @@ #Mon Mar 02 09:54:08 CET 2009 footer.no.userdata=\n\n--- \nDenne besked er afsendt automatisk via OLAT.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\nDenne besked er afsendt via OLAT.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\nDenne besked er afsendt via OLAT.\n{1} help.hover.mail-templ=Hj\u00E6lp til brug af e-mail skabelonen mailhelper.error.attachment=E-mail kunne ikke sendes\: ugyldige vedh\u00E6ftede filer. Kontakt venligst modtagerne ad anden vej. mailhelper.error.failedusers=E-mail kunne ikke sendes til f\u00F8lgende modtagere. Kontakt venligst modtagerne ad anden vej og check deres e-mailadresser. diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_de.properties index aae572c4dbf06938f3ecce0659bd1685d3888828..d7ada9f495f2be5d8a4b734f1c9d4e1be5253d79 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_de.properties @@ -8,7 +8,7 @@ chelp.sendMail7=Beschreibung der Gruppe chelp.sendMail8=Liste der Kurse, in denen die Gruppe verwendet wird. contact.cp.from = Kopie an Absender footer.no.userdata=\n\n--- \nDiese Nachricht wurde automatisch von der Lernplattform OLAT versandt.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\nDiese Nachricht wurde \u00FCber die Lernplattform OLAT versandt.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4} {5}\n\nDiese Nachricht wurde \u00FCber die Lernplattform OLAT versandt.\n{1} help.hover.mail-templ=Hilfe zur Anwendung der Mailvorlage mailhelper.error.attachment=Die E-Mail konnte nicht verschickt werden\: ung\u00FCltiges Attachment. Bitte benachrichtigen Sie die Empf\u00E4nger manuell. mailhelper.error.failedusers=Den folgenden Benutzern kann Ihre Nachricht nicht zugestellt werden. Bitte benachrichtigen Sie diese Benutzer manuell und bitten Sie diese, ihre E-Mail-Adresse zu \u00FCberpr\u00FCfen\: @@ -29,3 +29,52 @@ mailtemplateform.subject=Betreffzeile chelp.mailtempsubject=Der Betreff der Nachricht ist vorgegeben, kann aber von Ihnen nach Belieben geändert werden. mailtemplateform.continue=Weiter chelp.mail-templ.title=E-Mail-Benachrichtigung +mail.admin.title=E-Mail Postfach und Versand +mail.admin.description=Konfiguration der OLAT E-Mail Versandoptionen und des Postfachs +chelp.mail-admin.title=$:mail.admin.title +chelp.mail.module=OLAT verfügt über ein internes E-Mail Postfach System, das alle in dem System gesendeten und empfangenen E-Mails im Homebereich jedes Benutzers im persönlichen Poftfach auflistet. Das E-Mail Postfach in OLAT ist eine optionale Komponente. +chelp.mail.module.intern=Ist das OLAT Postfach ausgeschaltet, so werden alle in OLAT erstellten E-Mails ausschliesslich und an die persönliche E-Mail Adresse versandt. Das OLAT Postfach ist im Home nicht sichtbar. +chelp.mail.module.extern=Ist das OLAT Postfach eingeschaltet, so werden alle empfangenen und gesendeten E-Mails im Homebereich jedes Benutzers im persönlichen Postfach aufgelistet. +chelp.mail.module.extern.config=Jeder Benutzer kann zudem in den Systemeinstellungen konfigurieren, ob empfangene E-Mails nur intern oder auch an die persönliche E-Mail Adresse zugestellt werden soll. Als Administrator können Sie das Standardverhalten festlegen: +mail.admin.intern.enabled=OLAT Postfach aktivieren +mail.admin.default.settings=Standardeinstellung für E-Mail Versand +mail.admin.intern.only=E-Mails an das interne OLAT Postfach zustellen +mail.admin.intern.real.mail=E-Mails an das interne OLAT Postfach und die persönliche E-Mail Adresse zustellen +mail.attachments=Anhang +mail.confirm.delete.title=E-Mails l\u00F6schen +mail.confirm.delete.multi.text=Bitte bestätigen Sie, dass Sie die selektierten {0} E-Mails inklusive aller Anhänge unwiederruflich l\u00F6schen wollen: +mail.confirm.delete.single.text=Bitte bestätigen Sie, dass Sie die selektierte E-Mail inklusive aller Anhänge unwiederruflich l\u00F6schen wollen: +mail.context=Kontext +mail.from=Von +mail.from.miscellaneous=Diverse +mail.inbox=Eingang +mail.inbox.alt=E-Mail Eingang +mail.inbox.title=E-Mail Eingang +mail.outbox=Gesendet +mail.outbox.alt=Gesendete E-Mails +mail.outbox.title=Gesendete E-Mails +mail.outbox.meta=diese E-Mails sind als Massen E-Mails versendet worden. +mail.empty.box=Diese Mailbox enth\u00E4lt keine E-Mails. +mail.marked.header=\u2691 +mail.marked=Markiert +mail.notification.type=E-Mails +mail.unmarked=Unmarkiert +mail.read.header=\u26AB +mail.read=Gelesen +mail.unread=Nicht gelesen +mail.subject=Betreff +mail.body=Nachricht +mail.sendDate=Gesendet +mail.receivedDate=Empfangen +mail.recipients=An +menu.mail=E-Mail +menu.mail.alt=E-Mail Systemkonfiguration +mail.action.open=Lesen +mail.action.send.real=Weiterleiten +mail.action.send.real.success=Die Nachricht mit dem Betreff "{0}" wurde an Ihre private E-Mail Adresse weitergeleitet. +mail.action.read=Gelesen +mail.action.unread=Nicht gelesen +mail.action.mark=Markieren +mail.action.unmark=Nicht markieren +mail.action.emtpy=Wählen Sie mindestens eine E-Mail aus um eine Aktion auszulösen. + diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_en.properties index 7a4e8d70df591af36fd9ab21bd28df32230bc733..1a20a4896e83bd4d6b99ac599b030a6f4acc37f1 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_en.properties @@ -1,5 +1,10 @@ -#Fri Jan 21 10:21:23 CET 2011 +#Thu May 26 09:42:27 CEST 2011 +chelp.mail-admin.title=$\:mail.admin.title chelp.mail-templ.title=E-mail notification +chelp.mail.module=OLAT has an internal e-mail inbox system that lists all sent and received e-mails of each user in his personal home area. The OLAT e-mail inbox system is an optional component. +chelp.mail.module.extern=If the OLAT inbox system is enabled, all received and sent emails will be listed in the users personal inbox. +chelp.mail.module.extern.config=In addition, each user can configure in his preferences wether he wants to receive mails from OLAT to his personal e-mail address or if he prefers to read the mail within OLAT. As administrator you can define the default behavior. +chelp.mail.module.intern=If the OLAT inbox system is disabled, all OLAT e-mails will be sent exclusively to the personal e-mail address. The OLAT inbox is not visible in the home area with this configuration. chelp.mailtemplateformbody=By default any message will contain a standardized text that can then be altered according to your needs. chelp.mailtempsubject=Subjects of messages are pre-set but can be altered according to your needs. chelp.sendMail1=Here you can determine if a user shall receive an e-mail after having been registered, delisted or moved. @@ -10,8 +15,49 @@ chelp.sendMail7=Description of group chelp.sendMail8=List of courses in which this group is used. contact.cp.from=Copy sent to addresser footer.no.userdata=--- \r\nThis message has been sent automatically via the learning platform OLAT.\r\n{0} -footer.with.userdata=--- \r\n{0} {1} ({2})\r\n{3}\r\n\r\nThis message has been sent via the learning platform OLAT.\r\n{4} +footer.with.userdata=--- \r\n{2} {3} ({0})\r\n{4} {5}\r\n\r\nThis message has been sent via the learning platform OLAT.\r\n{1} help.hover.mail-templ=Help on how to use the mail template +mail.action.emtpy=Select at least one e-mail to perform this action. +mail.action.mark=Mark +mail.action.open=Read +mail.action.read=Read +mail.action.send.real=Forward +mail.action.send.real.success=The message with the subject "{0}" has been forwarded to your personal e-mail account. +mail.action.unmark=Unmark +mail.action.unread=Unread +mail.admin.default.settings=Standard settings for e-mail sending +mail.admin.description=Configuration of the OLAT e-mails and the OLAT inbox +mail.admin.intern.enabled=Enable your OLAT e-mail inbox +mail.admin.intern.only=Send e-mails to the internal OLAT inbox +mail.admin.intern.real.mail=Send e-Mails to the internal OLAT inbox and the personal e-mail address +mail.admin.title=E-mail inbox and outbox +mail.attachments=Attachment +mail.body=Message +mail.confirm.delete.multi.text=Please confirm that you want to delete the selected {0} e-mails including their attachments. This can not be undone. +mail.confirm.delete.single.text=Please confirm that you want to delete the selected e-mail including all attachments. This can not be undone. +mail.confirm.delete.title=Delete e-mails +mail.context=Context +mail.empty.box=This inbox does not contain any e-mails. +mail.from=Sender +mail.from.miscellaneous=Miscellaneous +mail.inbox=Inbox +mail.inbox.alt=E-mail inbox +mail.inbox.title=E-mail inbox +mail.marked=Marked +mail.marked.header=\u2691 +mail.notification.type=E-mails +mail.outbox=Outbox +mail.outbox.alt=E-mail outbox +mail.outbox.meta=those e-mails have been sent as mass e-mails. +mail.outbox.title=E-mail outbox +mail.read=Read +mail.read.header=\u26AB +mail.receivedDate=Received +mail.recipients=Receiver +mail.sendDate=Sent +mail.subject=Subject +mail.unmarked=Unmarked +mail.unread=Unread mailhelper.error.attachment=Mail could not be sent\: invalid attachments. Please notify your recipients manually. mailhelper.error.failedusers=Your e-mail cannot be sent to the following users. Please notify them manually and ask them to check their e-mail address\: mailhelper.error.failedusers.title=Disabled recipients' addresses @@ -28,3 +74,5 @@ mailtemplateform.error.emptyfield=This field is mandatory. mailtemplateform.error.velocity=The \# character is not allowed here. mailtemplateform.sendMailSwitchElem=Send e-mail mailtemplateform.subject=Mail subject +menu.mail=E-mail +menu.mail.alt=E-mail system configuration diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_es.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_es.properties index 2d0695977fe411fce5d9d4633d14d893d817c3fa..f7719a8fc0d1c4e8035c513d17f1334c82394b04 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_es.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_es.properties @@ -8,7 +8,7 @@ chelp.sendMail7=Lista de cursos donde el grupo es usado. chelp.sendMail8=Lista de curso en los que este grupo es usado. contact.cp.from=Copia enviada al emisor footer.no.userdata=\n\n--- \nEste mensaje ha sido generado autom\u00E1ticamente mediante la plataforma de aprendizaje OLAT.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\nEste mensaje ha sido generado mediante la plataforma de aprendizaje OLAT.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\nEste mensaje ha sido generado mediante la plataforma de aprendizaje OLAT.\n{1} help.hover.mail-templ=Ayuda para el uso de la plantilla del correo mailhelper.error.attachment=El correo no pod\u00EDa ser enviado\: ap\u00E9ndice inv\u00E1lidos. Por favor notificar los recipientes. mailhelper.error.failedusers=El correo no se pod\u00EDa enviar a la gente siguiente. Por favor notificar los recipientes y comprobar los direcciones de correo. diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fa.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fa.properties index 7b26ab963a265fe2ef2d1f575d16abcfe07d0ed8..e8df4af6eb57bb7e6dea855081d17c84a95c0769 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fa.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fa.properties @@ -1,3 +1,3 @@ #Mon Mar 02 09:54:12 CET 2009 footer.no.userdata=\n\n--- \nThis message has been sent automatically via OLAT.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\nThis message has been sent via OLAT.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\nThis message has been sent via OLAT.\n{1} diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fr.properties index ad4f14c3c9b612c139b3ddf9a40549b1d716f7a0..e4ce496c2ede584b4d128f44e941182a381f330f 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_fr.properties @@ -10,7 +10,7 @@ chelp.sendMail7=Liste des cours qui utilisent le groupe. chelp.sendMail8=Liste des cours utilisant ce groupe. contact.cp.from=Copie \u00E0 l'exp\u00E9diteur footer.no.userdata=--- \r\nCe message a \u00E9t\u00E9 envoy\u00E9 automatiquement via la plateforme d'apprentissage OLAT.\r\n{0} -footer.with.userdata=--- \r\n{0} {1} ({2})\r\n{3}\r\n\r\nCe message a \u00E9t\u00E9 envoy\u00E9 via la plateforme d'apprentissage OLAT.\r\n{4} +footer.with.userdata=--- \r\n{2} {3} ({0})\r\n{4} {5}\r\n\r\nCe message a \u00E9t\u00E9 envoy\u00E9 via la plateforme d'apprentissage OLAT.\r\n{1} help.hover.mail-templ=Aide pour l'utilisation de l'e-mail mod\u00E8le mailhelper.error.attachment=L'e-mail n'a pas pu \u00EAtre envoy\u00E9\: fichiers attach\u00E9s non valables. Veuillez contacter le destinataire manuellement. mailhelper.error.failedusers=Les personnes suivantes n'ont pas re\u00E7u votre e-mail. Veuillez contacter ces personnes manuellement et v\u00E9rifiez leurs adresses e-mail\: diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_it.properties index d0105e5e08e493780c9219f078dec58f9356b199..208c8d859d908d7fbe5fa917aef832fd290cdac9 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_it.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_it.properties @@ -10,7 +10,7 @@ chelp.sendMail7=lista dei corsi in cui viene utlizzato il gruppo. chelp.sendMail8=Lista dei corsi in cui viene utilizzato il gruppo. contact.cp.from=Copia al mittente footer.no.userdata=\n\n--- \nQuesto messaggio \u00E8 stato inviato automaticamente dalla piattaforma didattica OLAT.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\nQuesto messaggio \u00E8 stato inviato attraverso la piattaforma didattica OLAT.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4} {5}\n\nQuesto messaggio \u00E8 stato inviato attraverso la piattaforma didattica OLAT.\n{1} help.hover.mail-templ=Aiuto per l'utilizzo del modello mail mailhelper.error.attachment=Il messaggio non \u00E8 stato inviato\: allegato non valido. Contatti i destinatari manualmente, p.f. mailhelper.error.failedusers=Non \u00E8 stato possibile inviare il messaggio alle persone seguenti. Contatti queste persone manualmente, p.f., e controlli i loro indirizzi e-mail\: diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_jp.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_jp.properties index 57eee0bbabd07bef696373fcb0e1eeb92dd4df07..e32c599f03a06d29caee0e466af26149a05456f7 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_jp.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_jp.properties @@ -10,7 +10,7 @@ chelp.sendMail7=\u3053\u306E\u30B0\u30EB\u30FC\u30D7\u304C\u4F7F\u7528\u3055\u30 chelp.sendMail8=\u3053\u306E\u30B0\u30EB\u30FC\u30D7\u304C\u4F7F\u7528\u3055\u308C\u308B\u30B3\u30FC\u30B9\u4E00\u89A7\u3067\u3059\u3002 contact.cp.from=\u767A\u4FE1\u8005\u306B\u30B3\u30D4\u30FC\u3092\u9001\u4FE1\u3059\u308B footer.no.userdata=\r\n--- \r\n\u3053\u308C\u306F\u3001OLAT\u7D4C\u7531\u3067\u81EA\u52D5\u7684\u306B\u9001\u4FE1\u3055\u308C\u305F\u30E1\u30C3\u30BB\u30FC\u30B8\u3067\u3059\u3002\r\n{0} -footer.with.userdata=\r\n--- \r\n{0} {1} ({2})\r\n{3}\r\n\r\n\u3053\u308C\u306F\u3001OLAT\u7D4C\u7531\u3067\u9001\u4FE1\u3055\u308C\u305F\u30E1\u30C3\u30BB\u30FC\u30B8\u3067\u3059\u3002\r\n{4} +footer.with.userdata=\r\n--- \r\n{2} {3} ({0})\r\n{4}\r\n\r\n\u3053\u308C\u306F\u3001OLAT\u7D4C\u7531\u3067\u9001\u4FE1\u3055\u308C\u305F\u30E1\u30C3\u30BB\u30FC\u30B8\u3067\u3059\u3002\r\n{1} help.hover.mail-templ=\u30E1\u30FC\u30EB\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u4F7F\u7528\u306B\u95A2\u3059\u308B\u30D8\u30EB\u30D7 mailhelper.error.attachment=\u30E1\u30FC\u30EB\u306F\u9001\u4FE1\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\: \u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB\u304C\u7121\u52B9\u3067\u3059\u3002\u3042\u306A\u305F\u306E\u53D7\u4FE1\u8005\u306B\u76F4\u63A5\u77E5\u3089\u305B\u3066\u304F\u3060\u3055\u3044\u3002 mailhelper.error.failedusers=\u4EE5\u4E0B\u306E\u30E6\u30FC\u30B6\u306B\u30E1\u30FC\u30EB\u3092\u9001\u4FE1\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u53D7\u4FE1\u8005\u306B\u76F4\u63A5\u77E5\u3089\u305B\u305F\u5F8C\u3001\u53D7\u4FE1\u8005\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002 diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_lt.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_lt.properties index 66fb9dbf2e5e4cd9933d99e6b5dbe5d2ec76ac43..30fea196f346ac724733009fdc79adc774681ef5 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_lt.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_lt.properties @@ -4,7 +4,7 @@ chelp.sendMail5=Grup\u0117s pavadinimas chelp.sendMail6=Grup\u0117s apib\u016Bdinimas chelp.sendMail7=Kurs\u0173 s\u0105ra\u0161as, kuriame \u0161i grup\u0117 yra panaudota. footer.no.userdata=\n\n--- \n\u0160is prane\u0161imas automati\u0161kai buvo i\u0161si\u0173stas per OLAT.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\n\u0160is prane\u0161imas buvo i\u0161si\u0173stas per OLAT.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4} {5}\n\n\u0160is prane\u0161imas buvo i\u0161si\u0173stas per OLAT.\n{1} help.hover.mail-templ=Pagalba d\u0117l pa\u0161to \u0161ablono vartojimo mailhelper.error.failedusers.user={0} {1} naudojamas el. pa\u0161to adresas {2} ir prisijungimas {3} mailnotification.title=El. pa\u0161to prane\u0161imas diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_nl_NL.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_nl_NL.properties index d4085b0dbad7180b5eed38fe54e74d4d1a55523f..5810405d64214bce827d9d1255ea33410928c30b 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_nl_NL.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_nl_NL.properties @@ -10,7 +10,7 @@ chelp.sendMail7=Groepsbeschrijving chelp.sendMail8=Lijst van cursussen waarbinnen deze groep wordt gebruikt. contact.cp.from=Kopie aan afzender verzonden footer.no.userdata=---\r\nDit bericht werd automatisch verstuurd via OLAT.\r\n{0} -footer.with.userdata=\r\n---\r\n{0} {1} ({2}\r\n{3}\r\nDit bericht werd via OLAT verstuurd.\r\n{4} +footer.with.userdata=\r\n---\r\n{2} {3} ({0}\r\n{4}\r\nDit bericht werd via OLAT verstuurd.\r\n{1} help.hover.mail-templ=Hulp voor het gebruik van het e-mailsjabloon mailhelper.error.attachment=Uw e-mail is niet verzonden\: ongeldige bijlagen. Breng uw ontvangers op een andere manier op de hoogte. mailhelper.error.failedusers=Uw e-mail is niet verzonden naar de volgende contactpersonen. Breng hen op een andere manier op de hoogte en kijk hun e-mailadressen na. diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pl.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pl.properties index afe4cfc2576fe30c2e9a7370f08c9fb46909ee9d..2de9ac4dba3d0ba82d27952518bc007a96fdf18f 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pl.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pl.properties @@ -10,7 +10,7 @@ chelp.sendMail7=Zestawienie kurs\u00F3w, w kt\u00F3rych wykorzystywana jest ta g chelp.sendMail8=Lista kurs\u00F3w, w kt\u00F3rych wykorzystywana jest ta grupa. contact.cp.from=Kopia wys\u0142ana do nadawcy footer.no.userdata=\n\n--- \n Wiadomo\u015B\u0107 zosta\u0142a automatycznie wys\u0142ana z systemu OLAT\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\n Wiadomo\u015B\u0107 zosta\u0142a wys\u0142ana z systemu OLAT\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\n Wiadomo\u015B\u0107 zosta\u0142a wys\u0142ana z systemu OLAT\n{1} help.hover.mail-templ=Pomoc dla szablonu u\u017Cycia poczty mailhelper.error.attachment=Wiadomo\u015B\u0107 nie mog\u0142a zosta\u0107 wys\u0142ana\: nieprawid\u0142owy za\u0142\u0105cznik. Powiadom adresat\u00F3w tej wiadomo\u015Bci w inny spos\u00F3b... mailhelper.error.failedusers=Wiadomo\u015B\u0107 nie mog\u0142a zosta\u0107 wys\u0142ana do nast\u0119puj\u0105cych os\u00F3b. Powiadom adresat\u00F3w tej wiadomo\u015Bci w inny spos\u00F3b... diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pt_BR.properties index 6b5a01133b76c5bda9d1d20199c3bd181541415b..dcca4f126f5bbc35812bf28249b3428f2f425a52 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pt_BR.properties @@ -10,7 +10,7 @@ chelp.sendMail7=Listas de cursos nos quais este grupo \u00E9 usado. chelp.sendMail8=Lista de cursos em que esse grupo \u00E9 utilizado contact.cp.from=C\u00F3pia enviada ao endere\u00E7o footer.no.userdata=\n\n--- \nEsta mensagem foi enviada automaticamente via OLAT.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\nEsta mensagem foi enviada via OLAT.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\nEsta mensagem foi enviada via OLAT.\n{1} help.hover.mail-templ=Ajuda para o uso do modelo de e-mail mailhelper.error.attachment=O e-mail n\u00E3o p\u00F4de ser enviado\:anexa\u00E7\u00E3o inv\u00E1lida. Favor notificar os receptores manualmente. mailhelper.error.failedusers=O e-mail n\u00E3o p\u00F4de ser enviado para as seguintes pessoas. Favor notificar aquelas pessoas manualmente e checar seus endere\u00E7os de e-mail. diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pt_PT.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pt_PT.properties index 0480b3dfcc3b0d712316bbf7b9f3eabb34a8d91f..a2d7402cc1dffc9f1be54d022d94e4e639700236 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pt_PT.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_pt_PT.properties @@ -6,7 +6,7 @@ chelp.sendMail5=Nome do grupo chelp.sendMail6=Descri\u00E7\u00E3o do grupo chelp.sendMail7=Listas de cursos nos quais este grupo \u00E9 usado. footer.no.userdata=\n\n--- \nEsta mensagem foi enviada automaticamente via OLAT.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\nEsta mensagem foi enviada via OLAT.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\nEsta mensagem foi enviada via OLAT.\n{1} help.hover.mail-templ=Ajuda para o uso do modelo de e-mail mailhelper.error.attachment=O e-mail n\u00E3o p\u00F4de ser enviado\:anexa\u00E7\u00E3o inv\u00E1lida. Favor notificar os receptores manualmente. mailhelper.error.failedusers=O e-mail n\u00E3o p\u00F4de ser enviado para as seguintes pessoas. Favor notificar aquelas pessoas manualmente e checar seus endere\u00E7os de e-mail. diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_ru.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_ru.properties index 31698b200b4d5d8ad2ed8a449436dedccd900084..0b21445d89780a5ff2fabe150057dbcacfc19ddf 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_ru.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_ru.properties @@ -2,7 +2,7 @@ chelp.mail-templ.title=$\:mailnotification.title contact.cp.from=\u041F\u043E\u0441\u043B\u0430\u0442\u044C \u043A\u043E\u043F\u0438\u044E \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u0435\u043B\u044E footer.no.userdata=\n\n--- \n\u042D\u0442\u043E \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0431\u044B\u043B\u043E \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u043E\u0442\u043E\u0441\u043B\u0430\u043D\u043E \u043E\u0431\u0443\u0447\u0430\u044E\u0449\u0435\u0439 \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u043E\u0439 OLAT.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\n\u042D\u0442\u043E \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0431\u044B\u043B\u043E \u043E\u0442\u043E\u0441\u043B\u0430\u043D\u043E \u043E\u0431\u0443\u0447\u0430\u044E\u0449\u0435\u0439 \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u043E\u0439 OLAT.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\n\u042D\u0442\u043E \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0431\u044B\u043B\u043E \u043E\u0442\u043E\u0441\u043B\u0430\u043D\u043E \u043E\u0431\u0443\u0447\u0430\u044E\u0449\u0435\u0439 \u043F\u043B\u0430\u0442\u0444\u043E\u0440\u043C\u043E\u0439 OLAT.\n{1} help.hover.mail-templ=\u041F\u043E\u043C\u043E\u0449\u044C \u043A \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u0438\u044E mail-\u0448\u0430\u0431\u043B\u043E\u043D\u0430 mailhelper.error.attachment=Email \u043D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0431\u044B\u043B\u043E \u043E\u0442\u043E\u0441\u043B\u0430\u0442\u044C\: \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \u043D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u043E. \u041F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430, \u043E\u043F\u043E\u0432\u0435\u0441\u0442\u0438\u0442\u0435 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044F \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0441\u0432\u044F\u0437\u0438. mailhelper.error.failedusers=\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u043C \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u044F\u043C \u043D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0431\u044B\u043B\u043E \u0434\u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435. \u041F\u043E\u0436\u0430\u0439\u043B\u0443\u0441\u0442\u0430, \u043E\u043F\u043E\u0432\u0435\u0441\u0442\u0438\u0442\u0435 \u0434\u0430\u043D\u043D\u044B\u0445 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u0435\u043B\u0435\u0439 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044F \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0441\u0432\u044F\u0437\u0438 \u0438 \u043F\u0435\u0440\u0435\u043F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u0438\u0445 email-\u0430\u0434\u0440\u0435\u0441\: diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_zh_CN.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_zh_CN.properties index 914b9e190d22049fb766812e3f1ce66ed6324a2f..419b2456268d71f3d6cbec11d718084359059047 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_zh_CN.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_zh_CN.properties @@ -10,7 +10,7 @@ chelp.sendMail7=\u672C\u7FA4\u7EC4\u6B63\u5728\u4F7F\u7528\u7684\u5B66\u7A0B\u52 chelp.sendMail8=\u672C\u7FA4\u7EC4\u6B63\u5728\u4F7F\u7528\u7684\u5B66\u7A0B\u5217\u8868\u3002 contact.cp.from=\u53D1\u9001\u7ED9\u53D1\u4EF6\u4EBA\u7684\u590D\u4EF6 footer.no.userdata=\n\n--- \n\u8BE5\u6D88\u606F\u5DF2\u7ECF\u901A\u8FC7OLAT\u81EA\u52A8\u53D1\u9001.\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\n\u8BE5\u6D88\u606F\u5DF2\u7ECF\u901A\u8FC7 OLAT\u53D1\u9001.\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\n\u8BE5\u6D88\u606F\u5DF2\u7ECF\u901A\u8FC7 OLAT\u53D1\u9001.\n{1} help.hover.mail-templ=\u6709\u5173\u90AE\u4EF6\u6A21\u7248\u7684\u4F7F\u7528\u5E2E\u52A9 mailhelper.error.attachment=\u90AE\u4EF6\u4E0D\u80FD\u88AB\u53D1\u9001\uFF1A\u65E0\u6548\u9644\u4EF6.\u8BF7\u4EBA\u5DE5\u901A\u77E5\u90AE\u4EF6\u63A5\u53D7\u8005. mailhelper.error.failedusers=\u4F60\u7684\u7535\u5B50\u90AE\u4EF6\u4E0D\u80FD\u88AB\u53D1\u9001\u7ED9\u4E0B\u9762\u7684\u7528\u6237\u3002\u8BF7\u4EBA\u5DE5\u901A\u77E5\u4ED6\u4EEC\u5E76\u8981\u6C42\u5176\u68C0\u67E5\u7535\u5B50\u90AE\u4EF6\u5730\u5740 diff --git a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_zh_TW.properties b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_zh_TW.properties index 0a9bd33aab0f1cfeb18e4286c0ddabd894c5b01e..da68139885759e1e117dab883ffd843e5c2ecc6a 100644 --- a/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_zh_TW.properties +++ b/src/main/java/org/olat/core/util/mail/_i18n/LocalStrings_zh_TW.properties @@ -8,7 +8,7 @@ chelp.sendMail7=\u4F7F\u7528\u9019\u500B\u7FA4\u7D44\u7684\u8AB2\u7A0B\u6E05\u55 chelp.sendMail8=\u9019\u500B\u7FA4\u7D44\u88AB\u4F7F\u7528\u5230\u7684\u8AB2\u7A0B\u6E05\u55AE contact.cp.from=\u8907\u88FD\u5BC4\u4EF6\u4EBA\u81F3\u901A\u8A0A\u9304 footer.no.userdata=\n\n--- \n\u672C\u4FE1\u4EF6\u7531 OLAT \u81EA\u52D5\u5BC4\u9001\u3002\n{0} -footer.with.userdata=\n\n--- \n{0} {1} ({2})\n{3}\n\n\u672C\u4FE1\u4EF6\u7531 OLAT \u5BC4\u9001\u3002\n{4} +footer.with.userdata=\n\n--- \n{2} {3} ({0})\n{4}\n\n\u672C\u4FE1\u4EF6\u7531 OLAT \u5BC4\u9001\u3002\n{1} help.hover.mail-templ=\u6709\u95DC\u90F5\u4EF6\u7BC4\u672C\u4F7F\u7528\u8AAA\u660E mailhelper.error.attachment=\u90F5\u4EF6\u7121\u6CD5\u767C\u9001\uFF1A \u7121\u6548\u7684\u9644\u4EF6\u3002\u8ACB\u624B\u52D5\u901A\u77E5\u60A8\u7684\u6536\u4EF6\u4EBA\u3002 mailhelper.error.failedusers=\u60A8\u7684\u96FB\u5B50\u90F5\u4EF6\u7121\u6CD5\u767C\u9001\u7D66\u4E0B\u5217\u7684\u4F7F\u7528\u8005\u3002\u8ACB\u624B\u52D5\u901A\u77E5\u4ED6\u5011\u4E26\u8981\u6C42\u4ED6\u5011\u6AA2\u67E5\u4ED6\u5011\u7684\u96FB\u5B50\u90F5\u4EF6\u5730\u5740\u3002 diff --git a/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml b/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml new file mode 100644 index 0000000000000000000000000000000000000000..6f5206bbcdaafe10587fd6f1f7d248bd92359275 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + + <context:property-placeholder location="classpath:serviceconfig/olat.properties, classpath:olat.local.properties" /> + + <!-- MAIL CONFIGURATION --> + <!-- ========================= --> + + <bean id="mailModule" class="org.olat.core.util.mail.MailModule" depends-on="org.olat.core.util.WebappHelper,coordinatorManager,org.olat.core.util.event.FrameworkStartupEventChannel"> + <property name="persistedProperties"> + <bean class="org.olat.core.configuration.PersistedProperties" scope="prototype" init-method="init" destroy-method="destroy" + depends-on="coordinatorManager,org.olat.core.util.WebappHelper"> + <constructor-arg index="0" ref="coordinatorManager"/> + <constructor-arg index="1" ref="mailModule" /> + </bean> + </property> + <property name="webappHelper" ref="org.olat.core.util.WebappHelper"/> + </bean> + + <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> + <property name="targetObject" ref="mailModule" /> + <property name="targetMethod" value="init" /> + <property name="arguments"> + <value> + internSystem=${mail.intern} + receiveRealMailUserDefaultSetting=${mail.receiveRealMailUserDefaultSetting} + </value> + </property> + </bean> + + <!-- Mail admin. panel --> + <bean class="org.olat.core.extensions.action.GenericActionExtension" id="sysadmin.menupoint.syscfg.mailcfg" init-method="initExtensionPoints"> + <property name="actionController"> + <bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype"> + <property name="className" value="org.olat.core.util.mail.ui.MailAdminController"/> + </bean> + </property> + <property name="navigationKey" value="mail" /> + <property name="i18nActionKey" value="menu.mail"/> + <property name="i18nDescriptionKey" value="menu.mail.alt"/> + <property name="translationPackage" value="org.olat.core.util.mail"/> + <property name="extensionPoints"> + <list> + <value>org.olat.admin.SystemAdminMainController</value> + </list> + </property> + <property name="parentTreeNodeIdentifier" value="sysconfigParent" /> + <property name="order" value="780" /> + </bean> + + <bean id="mailManager" class="org.olat.core.util.mail.manager.MailManager"> + <constructor-arg index="0" ref="mailModule" /> + <property name="dbInstance" ref="database"/> + <property name="notificationsManager" ref="org.olat.core.util.notifications.NotificationsManager"/> + </bean> + + <bean id="mailDBMappings" class="org.olat.core.commons.persistence.AdditionalDBMappings"> + <property name="xmlFiles"> + <list> + <value>org/olat/core/util/mail/model/DBMail.hbm.xml</value> + <value>org/olat/core/util/mail/model/DBMailAttachment.hbm.xml</value> + <value>org/olat/core/util/mail/model/DBMailRecipient.hbm.xml</value> + </list> + </property> + </bean> + + <bean id="org.olat.core.util.mail.manager.MailNotificationsHandler" class="org.olat.core.util.mail.manager.MailNotificationsHandler"> + <property name="mailModule" ref="mailModule"/> + </bean> + + + <!-- the email-parent-menu --> + <bean class="org.olat.core.util.mail.ui.MailActionExtension" name="mailAEparent" init-method="initExtensionPoints"> + <property name="order" value="108" /> + <property name="navigationKey" value="Mail" /> + <property name="securityCallbackClassName" value="org.olat.core.extensions.security.UserOnlyExtensionSecurityCallback" /> + <property name="nodeIdentifierIfParent" value="homeEmailParent" /> + <property name="translationPackage" value="org.olat.home" /> + <property name="i18nActionKey" value="menu.mail" /> + <property name="i18nDescriptionKey" value="menu.mail.alt" /> + <property name="extensionPoints"> + <list> + <value>org.olat.home.HomeMainController</value> + </list> + </property> + </bean> + + <!-- The name of this extension is used by the NotificationUIFactory, don't change it --> + <bean class="org.olat.core.extensions.action.GenericActionExtension" name="mailAEinbox" init-method="initExtensionPoints" > + <property name="order" value="401" /> + <property name="navigationKey" value="Inbox" /> + <property name="actionController"> + <bean class=" org.olat.core.gui.control.creator.FactoryControllerCreator" scope="prototype"> + <property name="factoryName" value="org.olat.core.util.mail.MailUIFactory"/> + <property name="factoryMethod" value="createInboxController"/> + </bean> + </property> + <property name="securityCallbackClassName" value="org.olat.core.extensions.security.UserOnlyExtensionSecurityCallback" /> + <property name="i18nActionKey" value="mail.inbox"/> + <property name="i18nDescriptionKey" value="mail.inbox.alt"/> + <property name="parentTreeNodeIdentifier" value="homeEmailParent" /> + <property name="extensionPoints"> + <list> + <value>org.olat.home.HomeMainController</value> + </list> + </property> + </bean> + + + <bean class="org.olat.core.extensions.action.GenericActionExtension" name="mailAEoutbox" init-method="initExtensionPoints" > + <property name="order" value="402" /> + <property name="navigationKey" value="Outbox" /> + <property name="actionController"> + <bean class=" org.olat.core.gui.control.creator.FactoryControllerCreator" scope="prototype"> + <property name="factoryName" value="org.olat.core.util.mail.MailUIFactory"/> + <property name="factoryMethod" value="createOutboxController"/> + </bean> + </property> + <property name="securityCallbackClassName" value="org.olat.core.extensions.security.UserOnlyExtensionSecurityCallback" /> + <property name="i18nActionKey" value="mail.outbox"/> + <property name="i18nDescriptionKey" value="mail.outbox.alt"/> + <property name="parentTreeNodeIdentifier" value="homeEmailParent" /> + <property name="extensionPoints"> + <list> + <value>org.olat.home.HomeMainController</value> + </list> + </property> + </bean> + + +</beans> diff --git a/src/main/java/org/olat/core/util/mail/manager/MailManager.java b/src/main/java/org/olat/core/util/mail/manager/MailManager.java new file mode 100644 index 0000000000000000000000000000000000000000..123700d74b4f1ba038d426c2715c85d9280654b7 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/manager/MailManager.java @@ -0,0 +1,1202 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail.manager; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Properties; + +import javax.activation.DataHandler; +import javax.activation.DataSource; +import javax.activation.FileDataSource; +import javax.mail.Address; +import javax.mail.Authenticator; +import javax.mail.BodyPart; +import javax.mail.Message.RecipientType; +import javax.mail.MessagingException; +import javax.mail.Multipart; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import javax.mail.util.ByteArrayDataSource; + +import org.olat.core.commons.persistence.DB; +import org.olat.core.commons.persistence.DBQuery; +import org.olat.core.commons.persistence.PersistentObject; +import org.olat.core.helpers.Settings; +import org.olat.core.id.Identity; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.UserConstants; +import org.olat.core.manager.BasicManager; +import org.olat.core.util.StringHelper; +import org.olat.core.util.WebappHelper; +import org.olat.core.util.mail.ContactList; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailModule; +import org.olat.core.util.mail.MailerResult; +import org.olat.core.util.mail.MailerSMTPAuthenticator; +import org.olat.core.util.mail.model.DBMail; +import org.olat.core.util.mail.model.DBMailAttachment; +import org.olat.core.util.mail.model.DBMailAttachmentData; +import org.olat.core.util.mail.model.DBMailImpl; +import org.olat.core.util.mail.model.DBMailRecipient; +import org.olat.core.util.notifications.NotificationsManager; +import org.olat.core.util.notifications.Publisher; +import org.olat.core.util.notifications.PublisherData; +import org.olat.core.util.notifications.Subscriber; +import org.olat.core.util.notifications.SubscriptionContext; + +/** + * + * Description:<br> + * Manager which send e-mails, make the triage between mails which are + * really send by POP, or only saved in the intern mail system (a.k.a on + * the database). + * + * <P> + * Initial Date: 24 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailManager extends BasicManager { + + private final MailModule mailModule; + private DB dbInstance; + private NotificationsManager notificationsManager; + + private static MailManager INSTANCE; + + public MailManager(MailModule mailModule) { + INSTANCE = this; + this.mailModule = mailModule; + } + + public static MailManager getInstance() { + return INSTANCE; + } + + /** + * [used by Spring] + * + * @param dbInstance + */ + public void setDbInstance(DB dbInstance) { + this.dbInstance = dbInstance; + } + + /** + * [used by Spring] + * @param notificationsManager + */ + public void setNotificationsManager(NotificationsManager notificationsManager) { + this.notificationsManager = notificationsManager; + } + + public SubscriptionContext getSubscriptionContext() { + return new SubscriptionContext("Inbox", 0l, ""); + } + + public PublisherData getPublisherData() { + String data = ""; + String businessPath = "[Inbox:0]"; + PublisherData publisherData = new PublisherData("Inbox", data, businessPath); + return publisherData; + } + + public Subscriber getSubscriber(Identity identity) { + SubscriptionContext context = getSubscriptionContext(); + if(context == null) return null; + Publisher publisher = notificationsManager.getPublisher(context); + if(publisher == null) { + return null; + } + return notificationsManager.getSubscriber(identity, publisher); + } + + public void subscribe(Identity identity) { + PublisherData data = getPublisherData(); + SubscriptionContext context = getSubscriptionContext(); + if(context != null) { + notificationsManager.subscribe(identity, context, data); + } + } + + public DBMail getMessageByKey(Long key) { + StringBuilder sb = new StringBuilder(); + sb.append("select mail from ").append(DBMailImpl.class.getName()).append(" mail") + .append(" left join fetch mail.recipients recipients") + .append(" where mail.key=:mailKey"); + + DBQuery query = dbInstance.createQuery(sb.toString()); + query.setLong("mailKey", key); + + List<DBMailImpl> mails = query.list(); + if(mails.isEmpty()) return null; + DBMailImpl mail = mails.get(0); + return mail; + } + + public List<DBMailAttachment> getAttachments(DBMail mail) { + StringBuilder sb = new StringBuilder(); + sb.append("select attachment from ").append(DBMailAttachment.class.getName()).append(" attachment") + .append(" inner join attachment.mail mail") + .append(" where mail.key=:mailKey"); + + DBQuery query = dbInstance.createQuery(sb.toString()); + query.setLong("mailKey", mail.getKey()); + + List<DBMailAttachment> attachments = query.list(); + return attachments; + } + + public DBMailAttachmentData getAttachmentWithData(Long key) { + StringBuilder sb = new StringBuilder(); + sb.append("select attachment from ").append(DBMailAttachmentData.class.getName()).append(" attachment") + .append(" where attachment.key=:attachmentKey"); + + DBQuery query = dbInstance.createQuery(sb.toString()); + query.setLong("attachmentKey", key); + + List<DBMailAttachmentData> mails = query.list(); + if(mails.isEmpty()) return null; + return mails.get(0); + } + + public boolean hasNewMail(Identity identity) { + StringBuilder sb = new StringBuilder(); + sb.append("select count(mail) from ").append(DBMailImpl.class.getName()).append(" mail") + .append(" inner join mail.recipients recipient") + .append(" inner join recipient.recipient recipientIdentity") + .append(" where recipientIdentity.key=:recipientKey and recipient.read=false and recipient.deleted=false"); + + DBQuery query = dbInstance.createQuery(sb.toString()); + query.setLong("recipientKey", identity.getKey()); + + List<Number> mails = query.list(); + if(mails.isEmpty()) return false; + return mails.get(0).intValue() > 0; + } + + /** + * + * @param mail + * @param read cannot be null + * @param identity + * @return true if the read flag has been changed + */ + public boolean setRead(DBMail mail, Boolean read, Identity identity) { + if(mail == null || read == null || identity == null) throw new NullPointerException(); + + boolean changed = false; + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient == null) continue; + if(recipient.getRecipient() != null && recipient.getRecipient().equalsByPersistableKey(identity)) { + if(!read.equals(recipient.getRead())) { + recipient.setRead(read); + dbInstance.updateObject(recipient); + changed |= true; + } + } + } + return changed; + } + + public DBMail toggleRead(DBMail mail, Identity identity) { + Boolean read = null; + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient == null) continue; + if(recipient.getRecipient() != null && recipient.getRecipient().equalsByPersistableKey(identity)) { + if(read == null) { + read = recipient.getRead() == null ? Boolean.FALSE : recipient.getRead(); + } + recipient.setRead(read.booleanValue() ? Boolean.FALSE : Boolean.TRUE); + dbInstance.updateObject(recipient); + } + } + return mail; + } + + /** + * @param mail + * @param marked cannot be null + * @param identity + * @return true if the marked flag has been changed + */ + public boolean setMarked(DBMail mail, Boolean marked, Identity identity) { + if(mail == null || marked == null || identity == null) throw new NullPointerException(); + + boolean changed = false; + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient == null) continue; + if(recipient != null && recipient.getRecipient() != null && recipient.getRecipient().equalsByPersistableKey(identity)) { + if(marked == null) { + marked = Boolean.FALSE; + } + if(!marked.equals(recipient.getMarked())) { + recipient.setMarked(marked.booleanValue()); + dbInstance.updateObject(recipient); + changed |= true; + } + } + } + return changed; + } + + public DBMail toggleMarked(DBMail mail, Identity identity) { + Boolean marked = null; + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient == null) continue; + if(recipient != null && recipient.getRecipient() != null && recipient.getRecipient().equalsByPersistableKey(identity)) { + if(marked == null) { + marked = recipient.getMarked() == null ? Boolean.FALSE : recipient.getMarked(); + } + recipient.setMarked(marked.booleanValue() ? Boolean.FALSE : Boolean.TRUE); + dbInstance.updateObject(recipient); + } + } + return mail; + } + + /** + * Set the mail as deleted for a user + * @param mail + * @param identity + */ + public void delete(DBMail mail, Identity identity, boolean deleteMetaMail) { + if(StringHelper.containsNonWhitespace(mail.getMetaId()) && deleteMetaMail) { + List<DBMail> mails = getEmailsByMetaId(mail.getMetaId()); + for(DBMail childMail:mails) { + deleteMail(childMail, identity, false); + } + } else { + deleteMail(mail, identity, false); + } + } + + private void deleteMail(DBMail mail, Identity identity, boolean forceRemoveRecipient) { + boolean delete = true; + List<DBMailRecipient> updates = new ArrayList<DBMailRecipient>(); + if(mail.getFrom() != null && mail.getFrom().getRecipient() != null) { + if(identity.equalsByPersistableKey(mail.getFrom().getRecipient())) { + DBMailRecipient from = mail.getFrom(); + from.setDeleted(Boolean.TRUE); + if(forceRemoveRecipient) { + from.setRecipient(null); + } + updates.add(from); + } + if(mail.getFrom().getDeleted() != null) { + delete &= mail.getFrom().getDeleted().booleanValue(); + } + } + + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient == null) continue; + if(recipient.getRecipient() != null && recipient.getRecipient().equalsByPersistableKey(identity)) { + recipient.setDeleted(Boolean.TRUE); + if(forceRemoveRecipient) { + recipient.setRecipient(null); + } + updates.add(recipient); + } + if(recipient.getDeleted() != null) { + delete &= recipient.getDeleted().booleanValue(); + } + } + + if(delete) { + //all marked as deleted -> delete the mail + List<DBMailAttachment> attachments = getAttachments(mail); + for(DBMailAttachment attachment: attachments) { + mail = attachment.getMail();//reload from the hibernate session + dbInstance.deleteObject(attachment); + } + dbInstance.deleteObject(mail); + } else { + for(DBMailRecipient update:updates) { + dbInstance.updateObject(update); + } + } + } + + /** + * Load all mails with the identity as from, mail which are not deleted + * for this user. Recipients are loaded. + * @param from + * @param firstResult + * @param maxResults + * @return + */ + public List<DBMail> getOutbox(Identity from, int firstResult, int maxResults) { + StringBuilder sb = new StringBuilder(); + sb.append("select mail from ").append(DBMailImpl.class.getName()).append(" mail") + .append(" inner join fetch mail.from fromRecipient") + .append(" inner join fromRecipient.recipient fromRecipientIdentity") + .append(" inner join fetch mail.recipients recipient") + .append(" inner join recipient.recipient recipientIdentity") + .append(" where fromRecipientIdentity.key=:fromKey and fromRecipient.deleted=false and recipientIdentity.key!=:fromKey") + .append(" order by mail.creationDate desc"); + + DBQuery query = dbInstance.createQuery(sb.toString()); + if(maxResults > 0) { + query.setMaxResults(maxResults); + } + if(firstResult >= 0) { + query.setFirstResult(firstResult); + } + query.setLong("fromKey", from.getKey()); + + List<DBMail> mails = query.list(); + return mails; + } + + public List<DBMail> getEmailsByMetaId(String metaId) { + if(!StringHelper.containsNonWhitespace(metaId)) return Collections.emptyList(); + + StringBuilder sb = new StringBuilder(); + sb.append("select mail from ").append(DBMailImpl.class.getName()).append(" mail") + .append(" inner join fetch mail.from fromRecipient") + .append(" inner join fromRecipient.recipient fromRecipientIdentity") + .append(" where mail.metaId=:metaId"); + + DBQuery query = dbInstance.createQuery(sb.toString()); + query.setString("metaId", metaId); + List<DBMail> mails = query.list(); + return mails; + } + + /** + * Load all mails with the identity as recipient, only mails which are not deleted + * for this user. Recipients are NOT loaded if not explicitly wanted! + * @param identity + * @param unreadOnly + * @param fetchRecipients + * @param from + * @param firstResult + * @param maxResults + * @return + */ + public List<DBMail> getInbox(Identity identity, Boolean unreadOnly, Boolean fetchRecipients, Date from, int firstResult, int maxResults) { + StringBuilder sb = new StringBuilder(); + String fetchOption = (fetchRecipients != null && fetchRecipients.booleanValue()) ? "fetch" : ""; + sb.append("select mail from ").append(DBMailImpl.class.getName()).append(" mail") + .append(" inner join ").append(fetchOption).append(" mail.recipients recipient") + .append(" inner join ").append(fetchOption).append(" recipient.recipient recipientIdentity") + .append(" where recipientIdentity.key=:recipientKey and recipient.deleted=false"); + if(unreadOnly != null && unreadOnly.booleanValue()) { + sb.append(" and recipient.read=false"); + } + if(from != null) { + sb.append(" and mail.creationDate>=:from"); + } + + sb.append(" order by mail.creationDate desc"); + + DBQuery query = dbInstance.createQuery(sb.toString()); + if(maxResults > 0) { + query.setMaxResults(maxResults); + } + if(firstResult >= 0) { + query.setFirstResult(firstResult); + } + query.setLong("recipientKey", identity.getKey()); + if(from != null) { + query.setDate("from", from); + } + + List<DBMail> mails = query.list(); + return mails; + } + + public MailerResult sendMessage(MailContext context, Identity fromId, String from, Identity toId, String to, + Identity cc, List<ContactList> ccLists, List<ContactList> bccLists, + String metaId, String subject, String body, List<File> attachments) { + + MailerResult result = new MailerResult(); + if(mailModule.isInternSystem()) { + saveDBMessage(context, fromId, from, toId, to, cc, ccLists, bccLists, metaId, subject, body, attachments, result); + } else { + sendExternMessage(fromId, from, toId, to, cc, ccLists, bccLists, subject, body, attachments, result); + } + return result; + } + + + public MailerResult forwardToRealInbox(Identity identity, DBMail mail, MailerResult result) { + + if(result == null) { + result = new MailerResult(); + } + + List<DBMailAttachment> attachments = getAttachments(mail); + + try { + Address from = createAddress(WebappHelper.getMailConfig("mailFrom")); + Address to = createAddress(identity, result, true); + MimeMessage message = createForwardMimeMessage(from, to, mail.getSubject(), mail.getBody(), attachments, result); + if(message != null) { + sendMessage(message, result); + } + } catch (AddressException e) { + logError("mailFrom is not configured", e); + } + return result; + } + + + /** + * Send the message via e-mail, always. + * @param from + * @param to + * @param cc + * @param contactLists + * @param listAsBcc + * @param subject + * @param body + * @param attachments + * @return + */ + public MailerResult sendExternMessage(Identity fromId, String from, Identity toId, String to, Identity cc, List<ContactList> ccLists, List<ContactList> bccLists, + String subject, String body, List<File> attachments, MailerResult result) { + + if(result == null) { + result = new MailerResult(); + } + MimeMessage mail = createMimeMessage(fromId, from, toId, to, cc, ccLists, bccLists, subject, body, attachments, result); + if(mail != null) { + sendMessage(mail, result); + } + return result; + } + + private boolean wantRealMailToo(Identity id) { + if(id == null) return false; + String want = id.getUser().getPreferences().getReceiveRealMail(); + if(want != null) { + return "true".equals(want); + } + return mailModule.isReceiveRealMailUserDefaultSetting(); + } + + protected DBMail saveDBMessage(MailContext context, Identity fromId, String from, Identity toId, String to, + Identity cc, List<ContactList> ccLists, List<ContactList> bccLists, + String metaId, String subject, String body, List<File> attachments, MailerResult result) { + + try { + DBMailImpl mail = new DBMailImpl(); + if(result == null) { + result = new MailerResult(); + } + + boolean makeRealMail = makeRealMail(toId, ccLists, bccLists); + Address fromAddress = null; + List<Address> toAddress = new ArrayList<Address>(); + List<Address> ccAddress = new ArrayList<Address>(); + List<Address> bccAddress = new ArrayList<Address>(); + + if(fromId != null) { + DBMailRecipient fromRecipient = new DBMailRecipient(); + fromRecipient.setRecipient(fromId); + if(StringHelper.containsNonWhitespace(from)) { + fromRecipient.setEmailAddress(from); + fromAddress = createFromAddress(from, result); + } else { + fromAddress = createFromAddress(fromId, result); + } + fromRecipient.setVisible(Boolean.TRUE); + fromRecipient.setMarked(Boolean.FALSE); + fromRecipient.setDeleted(Boolean.FALSE); + mail.setFrom(fromRecipient); + } else { + if(!StringHelper.containsNonWhitespace(from)) { + from = WebappHelper.getMailConfig("mailFrom"); + } + DBMailRecipient fromRecipient = new DBMailRecipient(); + fromRecipient.setEmailAddress(from); + fromRecipient.setVisible(Boolean.TRUE); + fromRecipient.setMarked(Boolean.FALSE); + fromRecipient.setDeleted(Boolean.TRUE);//marked as delted as nobody can read it + mail.setFrom(fromRecipient); + fromAddress = createFromAddress(from, result); + } + + if(result.getReturnCode() != MailerResult.OK) { + return null; + } + + mail.setMetaId(metaId); + if(subject != null && subject.length() > 500) { + logWarn("Cut a too long subkect in name. Size: " + subject.length(), null); + subject = subject.substring(0, 500); + } + mail.setSubject(subject); + if(body != null && body.length() > 16777210) { + logWarn("Cut a too long body in mail. Size: " + body.length(), null); + body = body.substring(0, 16000000); + } + mail.setBody(body); + mail.setLastModified(new Date()); + + if(context != null) { + OLATResourceable ores = context.getOLATResourceable(); + if(ores != null) { + String resName = ores.getResourceableTypeName(); + if(resName != null && resName.length() > 50) { + logWarn("Cut a too long resourceable type name in mail context: " + resName, null); + resName = resName.substring(0, 49); + } + mail.getContext().setResName(ores.getResourceableTypeName()); + mail.getContext().setResId(ores.getResourceableId()); + } + + String resSubPath = context.getResSubPath(); + if(resSubPath != null && resSubPath.length() > 2000) { + logWarn("Cut a too long resSubPath in mail context: " + resSubPath, null); + resSubPath = resSubPath.substring(0, 2000); + } + mail.getContext().setResSubPath(resSubPath); + + String businessPath = context.getBusinessPath(); + if(businessPath != null && businessPath.length() > 2000) { + logWarn("Cut a too long resSubPath in mail context: " + businessPath, null); + businessPath = businessPath.substring(0, 2000); + } + mail.getContext().setBusinessPath(businessPath); + } + + //add to + DBMailRecipient recipientTo = null; + if(toId != null) { + recipientTo = new DBMailRecipient(); + if(toId instanceof PersistentObject) { + recipientTo.setRecipient(toId); + } else { + to = toId.getUser().getProperty(UserConstants.EMAIL, null); + } + if(StringHelper.containsNonWhitespace(to)) { + recipientTo.setEmailAddress(to); + } + recipientTo.setVisible(Boolean.TRUE); + recipientTo.setDeleted(Boolean.FALSE); + recipientTo.setMarked(Boolean.FALSE); + recipientTo.setRead(Boolean.FALSE); + } else if (StringHelper.containsNonWhitespace(to)) { + recipientTo = new DBMailRecipient(); + recipientTo.setEmailAddress(to); + recipientTo.setVisible(Boolean.TRUE); + recipientTo.setDeleted(Boolean.TRUE); + recipientTo.setMarked(Boolean.FALSE); + recipientTo.setRead(Boolean.FALSE); + } + + if(recipientTo != null) { + mail.getRecipients().add(recipientTo); + createAddress(toAddress, recipientTo, true, result, true); + } + if(makeRealMail && StringHelper.containsNonWhitespace(to)) { + createAddress(toAddress, to, result); + } + + if(cc != null) { + DBMailRecipient recipient = new DBMailRecipient(); + if(cc instanceof PersistentObject) { + recipient.setRecipient(cc); + } else { + recipient.setEmailAddress(cc.getUser().getProperty(UserConstants.EMAIL, null)); + } + recipient.setVisible(Boolean.TRUE); + recipient.setDeleted(Boolean.FALSE); + recipient.setMarked(Boolean.FALSE); + recipient.setRead(Boolean.FALSE); + mail.getRecipients().add(recipient); + createAddress(ccAddress, recipient, false, result, true); + } + + //add cc recipients + appendRecipients(mail, ccLists, toAddress, ccAddress, true, makeRealMail, result); + + //add bcc recipients + appendRecipients(mail, bccLists, toAddress, bccAddress, false, makeRealMail, result); + + dbInstance.saveObject(mail); + + //save attachments + if(attachments != null && !attachments.isEmpty()) { + for(File attachment:attachments) { + DBMailAttachmentData data = new DBMailAttachmentData(); + data.setSize(attachment.length()); + data.setName(attachment.getName()); + data.setMimetype(WebappHelper.getMimeType(attachment.getName())); + data.setMail(mail); + + try { + byte[] datas = new byte[(int)attachment.length()]; + FileInputStream fis = new FileInputStream(attachment); + fis.read(datas); + data.setDatas(datas); + dbInstance.saveObject(data); + } catch (FileNotFoundException e) { + logError("File attachment not found: " + attachment, e); + } catch (IOException e) { + logError("Error with file attachment: " + attachment, e); + } + } + } + + if(makeRealMail) { + sendRealMessage(fromAddress, toAddress, ccAddress, bccAddress, subject, body, attachments, result); + } + + //update subscription + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient.getRecipient() != null) { + subscribe(recipient.getRecipient()); + } + } + + SubscriptionContext subContext = getSubscriptionContext(); + Publisher publisher = NotificationsManager.getInstance().getPublisher(subContext); + if(publisher != null && publisher.getKey() != null) { + publisher.setLatestNewsDate(new Date()); + notificationsManager.updatePublisher(publisher); + } + return mail; + } catch (AddressException e) { + logError("Cannot send e-mail: ", e); + result.setReturnCode(MailerResult.RECIPIENT_ADDRESS_ERROR); + return null; + } + } + + private void appendRecipients(DBMailImpl mail, List<ContactList> ccLists, List<Address> toAddress, List<Address> ccAddress, + boolean visible, boolean makeRealMail, MailerResult result) throws AddressException { + + //append cc/bcc recipients + if(ccLists != null && !ccLists.isEmpty()) { + for(ContactList contactList:ccLists) { + if(makeRealMail && StringHelper.containsNonWhitespace(contactList.getName())) { + Address[] groupAddress = InternetAddress.parse(contactList.getRFC2822Name() + ";"); + if(groupAddress != null && groupAddress.length > 0) { + for(Address groupAdd:groupAddress) { + toAddress.add(groupAdd); + } + } + } + + for(String email:contactList.getStringEmails().values()) { + DBMailRecipient recipient = new DBMailRecipient(); + recipient.setEmailAddress(email); + recipient.setGroup(contactList.getName()); + recipient.setVisible(visible); + recipient.setDeleted(Boolean.FALSE); + recipient.setMarked(Boolean.FALSE); + recipient.setRead(Boolean.FALSE); + mail.getRecipients().add(recipient); + + if(makeRealMail) { + createAddress(ccAddress, recipient, false, result, false); + } + } + + for(Identity identityEmail:contactList.getIdentiEmails().values()) { + DBMailRecipient recipient = new DBMailRecipient(); + if(identityEmail instanceof PersistentObject) { + recipient.setRecipient(identityEmail); + } else { + recipient.setEmailAddress(identityEmail.getUser().getProperty(UserConstants.EMAIL, null)); + } + recipient.setGroup(contactList.getName()); + recipient.setVisible(visible); + recipient.setDeleted(Boolean.FALSE); + recipient.setMarked(Boolean.FALSE); + recipient.setRead(Boolean.FALSE); + mail.getRecipients().add(recipient); + + if(makeRealMail) { + createAddress(ccAddress, recipient, false, result, false); + } + } + } + } + } + + private boolean makeRealMail(Identity toId, List<ContactList> ccLists, List<ContactList> bccLists) { + //need real mail to??? + boolean makeRealMail = false; + // can occur on self-registration + if (toId == null && ccLists == null && bccLists == null) return true; + + if(toId != null) { + makeRealMail |= wantRealMailToo(toId); + } + + //add bcc recipients + if(bccLists != null && !bccLists.isEmpty()) { + for(ContactList contactList:bccLists) { + for(Identity identityEmail:contactList.getIdentiEmails().values()) { + makeRealMail |= wantRealMailToo(identityEmail); + } + + if(!contactList.getStringEmails().isEmpty()) { + makeRealMail |= true; + } + } + } + + //add bcc recipients + if(ccLists != null && !ccLists.isEmpty()) { + for(ContactList contactList:ccLists) { + for(Identity identityEmail:contactList.getIdentiEmails().values()) { + makeRealMail |= wantRealMailToo(identityEmail); + } + + if(!contactList.getStringEmails().isEmpty()) { + makeRealMail |= true; + } + } + } + + return makeRealMail; + } + + private MimeMessage createMimeMessage(Identity fromId, String mailFrom, Identity toId, String to, Identity ccId, + List<ContactList> ccLists, List<ContactList> bccLists, + String subject, String body, List<File> attachments, MailerResult result) { + try { + Address from; + if(StringHelper.containsNonWhitespace(mailFrom)) { + from = createFromAddress(mailFrom, result); + } else if (fromId != null) { + from = createFromAddress(fromId, result); + } else { + // fxdiff: change from/replyto, see FXOLAT-74 . if no from is set, use default sysadmin-address (adminemail). + from = createAddress(WebappHelper.getMailConfig("mailReplyTo")); + } + + List<Address> toList = new ArrayList<Address>(); + if(StringHelper.containsNonWhitespace(to)) { + Address[] toAddresses = InternetAddress.parse(to); + for(Address toAddress:toAddresses) { + toList.add(toAddress); + } + } else if (toId != null) { + Address toAddress = createAddress(toId, result, true); + if(toAddress != null) { + toList.add(toAddress); + } + } + + List<Address> ccList = new ArrayList<Address>(); + if(ccId != null) { + Address ccAddress = createAddress(ccId, result, true); + ccList.add(ccAddress); + } + + //add cc contact list + if(ccLists != null) { + for (ContactList contactList : ccLists) { + if(StringHelper.containsNonWhitespace(contactList.getName())) { + Address[] groupNames = InternetAddress.parse(contactList.getRFC2822Name() + ";"); + for(Address groupName:groupNames) { + toList.add(groupName); + } + } + + Address[] members = contactList.getEmailsAsAddresses(); + for(Address member:members) { + ccList.add(member); + } + } + } + + //add bcc contact lists + List<Address> bccList = new ArrayList<Address>(); + if(bccLists != null) { + for (ContactList contactList : bccLists) { + if(StringHelper.containsNonWhitespace(contactList.getName())) { + Address[] groupNames = InternetAddress.parse(contactList.getRFC2822Name() + ";"); + for(Address groupName:groupNames) { + toList.add(groupName); + } + } + + Address[] members = contactList.getEmailsAsAddresses(); + for(Address member:members) { + bccList.add(member); + } + } + } + + Address[] tos = toList.toArray(new Address[toList.size()]); + Address[] ccs = ccList.toArray(new Address[ccList.size()]); + Address[] bccs = bccList.toArray(new Address[bccList.size()]); + return createMimeMessage(from, tos, ccs, bccs, subject, body, attachments, result); + } catch (MessagingException e) { + logError("", e); + return null; + } + } + + private Address createAddress(String address) throws AddressException { + return new InternetAddress(address); + } + + private Address createAddressWithName(String address, String name) throws UnsupportedEncodingException, AddressException { + InternetAddress add = new InternetAddress(address, name); + try { + add.validate(); + } catch (AddressException e) { + throw e; + } + return add; + } + + private Address createFromAddress(String address, MailerResult result) throws AddressException { + try { + Address add = new InternetAddress(address); + return add; + } catch (AddressException e) { + result.setReturnCode(MailerResult.SENDER_ADDRESS_ERROR); + throw e; + } + } + + private boolean createAddress(List<Address> addressList, String address, MailerResult result) throws AddressException { + Address add = createAddress(address); + if(add != null) { + addressList.add(add); + } + return true; + } + + private boolean createAddress(List<Address> addressList, DBMailRecipient recipient, boolean force, MailerResult result, boolean error) { + String emailAddress = recipient.getEmailAddress(); + if(recipient.getRecipient() == null) { + try { + Address address = createAddress(emailAddress); + if(address != null) { + addressList.add(address); + return true; + } else { + if(error) { + result.setReturnCode(MailerResult.RECIPIENT_ADDRESS_ERROR); + } + } + } catch (AddressException e) { + if(error) { + result.setReturnCode(MailerResult.RECIPIENT_ADDRESS_ERROR); + } + } + } else { + if(force || wantRealMailToo(recipient.getRecipient())) { + if(!StringHelper.containsNonWhitespace(emailAddress)) { + emailAddress = recipient.getRecipient().getUser().getProperty(UserConstants.EMAIL, null); + } + try { + Address address = createAddress(emailAddress); + if(address != null) { + addressList.add(address); + return true; + } else { + result.addFailedIdentites(recipient.getRecipient()); + if(error) { + result.setReturnCode(MailerResult.RECIPIENT_ADDRESS_ERROR); + } + } + } catch (AddressException e) { + result.addFailedIdentites(recipient.getRecipient()); + if(error) { + result.setReturnCode(MailerResult.RECIPIENT_ADDRESS_ERROR); + } + } + } + } + return false; + } + + private Address createAddress(Identity recipient, MailerResult result, boolean error) { + if(recipient != null) { + String emailAddress = recipient.getUser().getProperty(UserConstants.EMAIL, null); + Address address; + try { + address = createAddress(emailAddress); + if(address == null) { + result.addFailedIdentites(recipient); + if(error) { + result.setReturnCode(MailerResult.RECIPIENT_ADDRESS_ERROR); + } + } + return address; + } catch (AddressException e) { + result.addFailedIdentites(recipient); + if(error) { + result.setReturnCode(MailerResult.RECIPIENT_ADDRESS_ERROR); + } + } + } + return null; + } + + private Address createFromAddress(Identity recipient, MailerResult result) { + if(recipient != null) { + String emailAddress = recipient.getUser().getProperty(UserConstants.EMAIL, null); + String name = recipient.getUser().getProperty(UserConstants.FIRSTNAME, null) + " " + recipient.getUser().getProperty(UserConstants.LASTNAME, null); + Address address; + try { + address = createAddressWithName(emailAddress, name); + if(address == null) { + result.addFailedIdentites(recipient); + result.setReturnCode(MailerResult.SENDER_ADDRESS_ERROR); + } + return address; + } catch (AddressException e) { + result.addFailedIdentites(recipient); + result.setReturnCode(MailerResult.SENDER_ADDRESS_ERROR); + } catch (UnsupportedEncodingException e) { + result.addFailedIdentites(recipient); + result.setReturnCode(MailerResult.SENDER_ADDRESS_ERROR); + } + } + return null; + } + + private void sendRealMessage(Address from, List<Address> toList, List<Address> ccList, List<Address> bccList, String subject, String body, + List<File> attachments, MailerResult result) { + + Address[] tos = null; + if(toList != null && !toList.isEmpty()) { + tos = new Address[toList.size()]; + tos = toList.toArray(tos); + } + + Address[] ccs = null; + if(ccList != null && !ccList.isEmpty()) { + ccs = new Address[ccList.size()]; + ccs = ccList.toArray(ccs); + } + + Address[] bccs = null; + if(bccList != null && !bccList.isEmpty()) { + bccs = new Address[bccList.size()]; + bccs = bccList.toArray(bccs); + } + + MimeMessage msg = createMimeMessage(from, tos, ccs, bccs, subject, body, attachments, result); + sendMessage(msg, result); + } + + private MimeMessage createForwardMimeMessage(Address from, Address to, String subject, String body, + List<DBMailAttachment> attachments, MailerResult result) { + + try { + Address convertedFrom = getRawEmailFromAddress(from); + MimeMessage msg = createMessage(convertedFrom); + msg.setFrom(from); + msg.setSubject(subject, "utf-8"); + + if(to != null) { + msg.addRecipient(RecipientType.TO, to); + } + + if (attachments != null && !attachments.isEmpty()) { + // with attachment use multipart message + Multipart multipart = new MimeMultipart(); + // 1) add body part + BodyPart messageBodyPart = new MimeBodyPart(); + messageBodyPart.setText(body); + multipart.addBodyPart(messageBodyPart); + // 2) add attachments + for (DBMailAttachment attachment : attachments) { + // abort if attachment does not exist + if (attachment == null || attachment.getSize() <= 0) { + result.setReturnCode(MailerResult.ATTACHMENT_INVALID); + logError("Tried to send mail wit attachment that does not exist::" + + (attachment == null ? null : attachment.getName()), null); + return msg; + } + messageBodyPart = new MimeBodyPart(); + + DBMailAttachmentData data = getAttachmentWithData(attachment.getKey()); + DataSource source = new ByteArrayDataSource(data.getDatas(), attachment.getMimetype()); + messageBodyPart.setDataHandler(new DataHandler(source)); + messageBodyPart.setFileName(attachment.getName()); + multipart.addBodyPart(messageBodyPart); + } + // Put parts in message + msg.setContent(multipart); + } else { + // without attachment everything is easy, just set as text + msg.setText(body, "utf-8"); + } + msg.setSentDate(new Date()); + msg.saveChanges(); + return msg; + } catch (MessagingException e) { + logError("", e); + return null; + } + } + + /** + * + * @param bounceAdress must be a raw email, without anything else (no "bla bli <bla@bli.ch>" !) + * @return + */ + public MimeMessage createMessage(Address bounceAdress) { + String mailhost = WebappHelper.getMailConfig("mailhost"); + String mailhostTimeout = WebappHelper.getMailConfig("mailTimeout"); + boolean sslEnabled = Boolean.parseBoolean(WebappHelper.getMailConfig("sslEnabled")); + boolean sslCheckCertificate = Boolean.parseBoolean(WebappHelper.getMailConfig("sslCheckCertificate")); + + Authenticator smtpAuth; + if (WebappHelper.isMailHostAuthenticationEnabled()) { + String smtpUser = WebappHelper.getMailConfig("smtpUser"); + String smtpPwd = WebappHelper.getMailConfig("smtpPwd"); + smtpAuth = new MailerSMTPAuthenticator(smtpUser, smtpPwd); + } else { + smtpAuth = null; + } + + Properties p = new Properties(); + p.put("mail.smtp.from", bounceAdress.toString()); + p.put("mail.smtp.host", mailhost); + p.put("mail.smtp.timeout", mailhostTimeout); + p.put("mail.smtp.connectiontimeout", mailhostTimeout); + p.put("mail.smtp.ssl.enable", sslEnabled); + p.put("mail.smtp.ssl.checkserveridentity", sslCheckCertificate); + Session mailSession; + if (smtpAuth == null) { + mailSession = javax.mail.Session.getInstance(p); + } else { + // use smtp authentication from configuration + p.put("mail.smtp.auth", "true"); + mailSession = Session.getDefaultInstance(p, smtpAuth); + } + if (isLogDebugEnabled()) { + // enable mail session debugging on console + mailSession.setDebug(true); + } + return new MimeMessage(mailSession); + } + + // converts an address "bla bli <bla@bli.ch>" => "bla@bli.ch" + private InternetAddress getRawEmailFromAddress(Address address) throws AddressException{ + InternetAddress fromAddress = new InternetAddress(address.toString()); + String fromPlainAddress = fromAddress.getAddress(); + return new InternetAddress(fromPlainAddress); + } + + public MimeMessage createMimeMessage(Address from, Address[] tos, Address[] ccs, Address[] bccs, String subject, String body, + List<File> attachments, MailerResult result) { + + try { + // see FXOLAT-74: send all mails as <fromemail> (in config) to have a valid reverse lookup and therefore pass spam protection. + // following doesn't work correctly, therefore add bounce-address in message already + Address convertedFrom = getRawEmailFromAddress(from); + MimeMessage msg = createMessage(convertedFrom); + String uri = Settings.createServerURI(); + Address viewableFrom = createAddressWithName(WebappHelper.getMailConfig("mailFrom"), "OLAT @ " + uri); + msg.setFrom(viewableFrom); + msg.setSubject(subject, "utf-8"); + // reply to can only be an address without name (at least for postfix!), see FXOLAT-312 + msg.setReplyTo(new Address[] { convertedFrom }); + + if(tos != null && tos.length > 0) { + msg.addRecipients(RecipientType.TO, tos); + } + + if(ccs != null && ccs.length > 0) { + msg.addRecipients(RecipientType.CC, ccs); + } + + if(bccs != null && bccs.length > 0) { + msg.addRecipients(RecipientType.BCC, bccs); + } + + if (attachments != null && !attachments.isEmpty()) { + // with attachment use multipart message + Multipart multipart = new MimeMultipart(); + // 1) add body part + BodyPart messageBodyPart = new MimeBodyPart(); + messageBodyPart.setText(body); + multipart.addBodyPart(messageBodyPart); + // 2) add attachments + for (File attachmentFile : attachments) { + // abort if attachment does not exist + if (attachmentFile == null || !attachmentFile.exists()) { + result.setReturnCode(MailerResult.ATTACHMENT_INVALID); + logError("Tried to send mail wit attachment that does not exist::" + + (attachmentFile == null ? null : attachmentFile.getAbsolutePath()), null); + return msg; + } + messageBodyPart = new MimeBodyPart(); + DataSource source = new FileDataSource(attachmentFile); + messageBodyPart.setDataHandler(new DataHandler(source)); + messageBodyPart.setFileName(attachmentFile.getName()); + multipart.addBodyPart(messageBodyPart); + } + // Put parts in message + msg.setContent(multipart); + } else { + // without attachment everything is easy, just set as text + msg.setText(body, "utf-8"); + } + msg.setSentDate(new Date()); + msg.saveChanges(); + return msg; + } catch (MessagingException e) { + result.setReturnCode(MailerResult.SEND_GENERAL_ERROR); + logError("", e); + return null; + } catch (UnsupportedEncodingException e) { + result.setReturnCode(MailerResult.SENDER_ADDRESS_ERROR); + logError("", e); + return null; + } + } + + public void sendMessage(MimeMessage msg, MailerResult result){ + try{ + if(Settings.isJUnitTest()) { + //we want not send really e-mails + } else if (mailModule.isMailHostEnabled() && result.getReturnCode() == MailerResult.OK) { + // now send the mail + Transport.send(msg); + } else { + result.setReturnCode(MailerResult.MAILHOST_UNDEFINED); + } + } catch (MessagingException e) { + result.setReturnCode(MailerResult.SEND_GENERAL_ERROR); + logWarn("Could not send mail", e); + } + } + +} diff --git a/src/main/java/org/olat/core/util/mail/manager/MailNotificationsHandler.java b/src/main/java/org/olat/core/util/mail/manager/MailNotificationsHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..1d7437b9c1a4edf19272ce81d878f88fd3418184 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/manager/MailNotificationsHandler.java @@ -0,0 +1,126 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail.manager; + +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import org.olat.core.gui.translator.Translator; +import org.olat.core.logging.LogDelegator; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.core.util.mail.MailModule; +import org.olat.core.util.mail.model.DBMail; +import org.olat.core.util.notifications.NotificationHelper; +import org.olat.core.util.notifications.NotificationsHandler; +import org.olat.core.util.notifications.NotificationsManager; +import org.olat.core.util.notifications.Publisher; +import org.olat.core.util.notifications.Subscriber; +import org.olat.core.util.notifications.SubscriptionInfo; +import org.olat.core.util.notifications.items.SubscriptionListItem; +import org.olat.core.util.notifications.items.TitleItem; + +/** + * + * Description:<br> + * + * + * <P> + * Initial Date: 24 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailNotificationsHandler extends LogDelegator implements NotificationsHandler { + + private MailModule mailModule; + + public MailNotificationsHandler() { + // + } + + /** + * [user by Spring] + * @param mailModule + */ + public void setMailModule(MailModule mailModule) { + this.mailModule = mailModule; + } + + + + @Override + public SubscriptionInfo createSubscriptionInfo(Subscriber subscriber, Locale locale, Date compareDate) { + if(!mailModule.isInternSystem()) { + return NotificationsManager.getInstance().getNoSubscriptionInfo(); + } + + String realMail = subscriber.getIdentity().getUser().getPreferences().getReceiveRealMail(); + if("true".equals(realMail)) { + //receive real e-mails + return NotificationsManager.getInstance().getNoSubscriptionInfo(); + } else if (!StringHelper.containsNonWhitespace(realMail) && mailModule.isReceiveRealMailUserDefaultSetting()) { + //user has no settings, check the default setting + return NotificationsManager.getInstance().getNoSubscriptionInfo(); + } + + SubscriptionInfo si = null; + Publisher p = subscriber.getPublisher(); + Date latestNews = p.getLatestNewsDate(); + + // do not try to create a subscription info if state is deleted - results in + // exceptions, course + // can't be loaded when already deleted + if (NotificationsManager.getInstance().isPublisherValid(p) && compareDate.before(latestNews)) { + try { + List<DBMail> inbox = MailManager.getInstance().getInbox(subscriber.getIdentity(), Boolean.TRUE, Boolean.FALSE, compareDate, 0, 0); + if(!inbox.isEmpty()) { + Translator translator = Util.createPackageTranslator(MailModule.class, locale); + si = new SubscriptionInfo(subscriber.getKey(), p.getType(), new TitleItem(translator.translate("mail.notification.type"), "o_co_icon"), null); + for (DBMail mail : inbox) { + String subject = mail.getSubject(); + String businessPath = "[Inbox:" + mail.getKey() + "]"; + String urlToSend = NotificationHelper.getURLFromBusinessPathString(p, businessPath); + SubscriptionListItem subListItem = new SubscriptionListItem(subject, urlToSend, mail.getCreationDate(), "o_co_icon"); + si.addSubscriptionListItem(subListItem); + } + } + } catch(Exception ex) { + logError("", ex); + } + } + + if( si == null) { + si = NotificationsManager.getInstance().getNoSubscriptionInfo(); + } + return si; + } + + @Override + public String createTitleInfo(Subscriber subscriber, Locale locale) { + Translator translator = Util.createPackageTranslator(MailModule.class, locale); + return translator.translate("mail.notification.type"); + } + + @Override + public String getType() { + return "Inbox"; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/util/mail/model/DBMail.hbm.xml b/src/main/java/org/olat/core/util/mail/model/DBMail.hbm.xml new file mode 100644 index 0000000000000000000000000000000000000000..d97fdd2c354a2f55143edea791d38aaf11458318 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/model/DBMail.hbm.xml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> +<hibernate-mapping default-lazy="false"> + + <class name="org.olat.core.util.mail.model.DBMailImpl" mutable="false" table="o_mail"> + <id name="key" column="mail_id" type="long" unsaved-value="null"> + <generator class="hilo"/> + </id> + + <property name="creationDate" column="creationdate" type="timestamp" /> + <property name="lastModified" column="lastmodified" type="timestamp" /> + + <property name="subject" column="subject" type="string" length="512" not-null="false"/> + <property name="body" column="body" type="string" length="16777210" not-null="false"/> + <property name="metaId" column="meta_mail_id" type="string" length="64" not-null="false"/> + + <component name="context"> + <property name="resName" column="resname" type="string" length="50" not-null="false"/> + <property name="resId" column="resid" type="long" not-null="false"/> + <property name="resSubPath" column="ressubpath" type="string" length="2048" not-null="false"/> + <property name="businessPath" column="businesspath" type="string" length="2048" not-null="false"/> + </component> + + <many-to-one name="from" column="fk_from_id" class="org.olat.core.util.mail.model.DBMailRecipient" fetch="join" unique="false" cascade="all"/> + + <list name="recipients" table="o_mail_to_recipient" cascade="all,delete-orphan" lazy="true" inverse="false"> + <key column="fk_mail_id" not-null="true" /> + <list-index column="pos"/> + <many-to-many column="fk_recipient_id" class="org.olat.core.util.mail.model.DBMailRecipient"/> + </list> + </class> + +</hibernate-mapping> \ No newline at end of file diff --git a/src/main/java/org/olat/core/util/mail/model/DBMail.java b/src/main/java/org/olat/core/util/mail/model/DBMail.java new file mode 100644 index 0000000000000000000000000000000000000000..c045e906983b72799e2c3ac0e6296e2ee82d0b5a --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/model/DBMail.java @@ -0,0 +1,54 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail.model; + +import java.util.Date; +import java.util.List; + +import org.olat.core.id.CreateInfo; +import org.olat.core.id.ModifiedInfo; +import org.olat.core.id.Persistable; + +/** + * + * Description:<br> + * + * + * <P> + * Initial Date: 28 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public interface DBMail extends CreateInfo, ModifiedInfo, Persistable { + + public DBMailRecipient getFrom(); + + public String getSubject(); + + public String getBody(); + + public Date getLastModified(); + + public String getMetaId(); + + public List<DBMailRecipient> getRecipients(); + + public DBMailContext getContext(); +} diff --git a/src/main/java/org/olat/core/util/mail/model/DBMailAttachment.hbm.xml b/src/main/java/org/olat/core/util/mail/model/DBMailAttachment.hbm.xml new file mode 100644 index 0000000000000000000000000000000000000000..49a26127fcfea9e11b6a3eff2ef4618c8cb2a722 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/model/DBMailAttachment.hbm.xml @@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<!DOCTYPE hibernate-mapping PUBLIC + "-//Hibernate/Hibernate Mapping DTD//EN" + "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> +<hibernate-mapping default-lazy="false"> + + <class name="org.olat.core.util.mail.model.DBMailAttachment" table="o_mail_attachment"> + <id name="key" column="attachment_id" type="long" unsaved-value="null"> + <generator class="hilo"/> + </id> + <property name="creationDate" column="creationdate" type="timestamp" /> + <property name="size" column="datas_size" type="long"/> + <property name="mimetype" column="mimetype" type="string" not-null="false" length="255"/> + <property name="name" column="datas_name" type="string" not-null="false" length="255"/> + <many-to-one name="mail" column="fk_att_mail_id" class="org.olat.core.util.mail.model.DBMailImpl" fetch="join" unique="false" cascade="none"/> + </class> + + <class name="org.olat.core.util.mail.model.DBMailAttachmentData" table="o_mail_attachment"> + <id name="key" column="attachment_id" type="long" unsaved-value="null"> + <generator class="hilo"/> + </id> + <property name="creationDate" column="creationdate" type="timestamp" /> + <property name="datas" column="datas" type="binary" length="16777215"/> + <property name="size" column="datas_size" type="long"/> + <property name="mimetype" column="mimetype" type="string" not-null="false" length="255"/> + <property name="name" column="datas_name" type="string" not-null="false" length="255"/> + <many-to-one name="mail" column="fk_att_mail_id" class="org.olat.core.util.mail.model.DBMailImpl" fetch="join" unique="false" cascade="none"/> + </class> + +</hibernate-mapping> diff --git a/src/main/java/org/olat/core/util/mail/model/DBMailAttachment.java b/src/main/java/org/olat/core/util/mail/model/DBMailAttachment.java new file mode 100644 index 0000000000000000000000000000000000000000..6420eeacc5504097a0db869638cdc1434c86f2e6 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/model/DBMailAttachment.java @@ -0,0 +1,85 @@ +/** + * <p> + * Copyright (c) frentix GmbH<br> + * http://www.frentix.com<br> + */ +package org.olat.core.util.mail.model; + +import org.olat.core.commons.persistence.PersistentObject; +import org.olat.core.gui.util.CSSHelper; + +/** + * + * Description:<br> + * + * <P> + * Initial Date: 8 sept. 2010 <br> + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class DBMailAttachment extends PersistentObject { + + private static final long serialVersionUID = -1713863670528439651L; + + private Long size; + private String name; + private String mimetype; + private DBMailImpl mail; + + public DBMailAttachment() { + // + } + + public DBMailImpl getMail() { + return mail; + } + + public void setMail(DBMailImpl mail) { + this.mail = mail; + } + + public Long getSize() { + return size; + } + + public void setSize(Long size) { + this.size = size; + } + + public String getCssClass() { + return CSSHelper.createFiletypeIconCssClassFor(name); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMimetype() { + return mimetype; + } + + public void setMimetype(String mimetype) { + this.mimetype = mimetype; + } + + @Override + public int hashCode() { + return getKey() == null ? 2951 : getKey().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof DBMailAttachment) { + DBMailAttachment attachment = (DBMailAttachment)obj; + return getKey() != null && getKey().equals(attachment.getKey()); + } + return false; + } +} diff --git a/src/main/java/org/olat/core/util/mail/model/DBMailAttachmentData.java b/src/main/java/org/olat/core/util/mail/model/DBMailAttachmentData.java new file mode 100644 index 0000000000000000000000000000000000000000..2aa57362cc42bb29a91c6e34095b9195bb2e8043 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/model/DBMailAttachmentData.java @@ -0,0 +1,89 @@ +/** + * <p> + * Copyright (c) frentix GmbH<br> + * http://www.frentix.com<br> + */ +package org.olat.core.util.mail.model; + +import org.olat.core.commons.persistence.PersistentObject; + +/** + * + * Description:<br> + * + * <P> + * Initial Date: 8 sept. 2010 <br> + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class DBMailAttachmentData extends PersistentObject { + + private static final long serialVersionUID = -3741636430048220733L; + + private Long size; + private String name; + private String mimetype; + private byte[] datas; + private DBMailImpl mail; + + public DBMailAttachmentData() { + // + } + + public DBMailImpl getMail() { + return mail; + } + + public void setMail(DBMailImpl mail) { + this.mail = mail; + } + + public byte[] getDatas() { + return datas; + } + + public void setDatas(byte[] datas) { + this.datas = datas; + } + + public Long getSize() { + return size; + } + + public void setSize(Long size) { + this.size = size; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMimetype() { + return mimetype; + } + + public void setMimetype(String mimetype) { + this.mimetype = mimetype; + } + + @Override + public int hashCode() { + return getKey() == null ? 921536 : getKey().intValue(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof DBMailAttachmentData) { + DBMailAttachmentData data = (DBMailAttachmentData)obj; + return getKey() != null && getKey().equals(data.getKey()); + } + return false; + } +} diff --git a/src/main/java/org/olat/core/util/mail/model/DBMailContext.java b/src/main/java/org/olat/core/util/mail/model/DBMailContext.java new file mode 100644 index 0000000000000000000000000000000000000000..d583caf6747777c79057d53ef9ffcbf1ab8f27fb --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/model/DBMailContext.java @@ -0,0 +1,94 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + + +package org.olat.core.util.mail.model; + +import org.olat.core.id.OLATResourceable; +import org.olat.core.util.mail.MailContext; + +/** + * + * Description:<br> + * + * + * <P> + * Initial Date: 30 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class DBMailContext implements MailContext { + + private String resName; + private Long resId; + private String businessPath; + private String resSubPath; + + + public OLATResourceable getOLATResourceable() { + final Long id = resId; + final String name = resName; + + if(id == null || name == null) return null; + + return new OLATResourceable() { + @Override + public Long getResourceableId() { + return id; + } + + @Override + public String getResourceableTypeName() { + return name; + } + }; + } + + public String getResSubPath() { + return resSubPath; + } + + public void setResSubPath(String resSubPath) { + this.resSubPath = resSubPath; + } + + public String getBusinessPath() { + return businessPath; + } + + public void setBusinessPath(String businessPath) { + this.businessPath = businessPath; + } + + public String getResName() { + return resName; + } + + public void setResName(String resName) { + this.resName = resName; + } + + public Long getResId() { + return resId; + } + + public void setResId(Long resId) { + this.resId = resId; + } +} diff --git a/src/main/java/org/olat/core/util/mail/model/DBMailImpl.java b/src/main/java/org/olat/core/util/mail/model/DBMailImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..3d70935224df5942d1bd62ef0dda6565bf78bd15 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/model/DBMailImpl.java @@ -0,0 +1,138 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail.model; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.olat.core.commons.persistence.PersistentObject; + +/** + * + * Description:<br> + * + * + * <P> + * Initial Date: 28 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class DBMailImpl extends PersistentObject implements DBMail { + + private static final long serialVersionUID = 6407865711769961684L; + + private String subject; + private String body; + private Date lastModified; + private String metaId; + + private DBMailRecipient from; + private List<DBMailRecipient> recipients; + private DBMailContext context; + + + + @Override + public DBMailRecipient getFrom() { + return from; + } + + public void setFrom(DBMailRecipient from) { + this.from = from; + } + + @Override + public String getMetaId() { + return metaId; + } + + public void setMetaId(String metaId) { + this.metaId = metaId; + } + + @Override + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + @Override + public Date getLastModified() { + return lastModified; + } + + @Override + public void setLastModified(Date lastModified) { + this.lastModified = lastModified; + } + + public List<DBMailRecipient> getRecipients() { + if(recipients == null) { + recipients = new ArrayList<DBMailRecipient>(); + } + return recipients; + } + + public void setRecipients(List<DBMailRecipient> recipients) { + this.recipients = recipients; + } + + + + public DBMailContext getContext() { + if(context == null) { + context = new DBMailContext(); + } + return context; + } + + public void setContext(DBMailContext context) { + this.context = context; + } + + @Override + public int hashCode() { + return getKey() == null ? 2991 : getKey().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof DBMailImpl) { + DBMailImpl mail = (DBMailImpl)obj; + return getKey() != null && getKey().equals(mail.getKey()); + } + return false; + } +} diff --git a/src/main/java/org/olat/core/util/mail/model/DBMailRecipient.hbm.xml b/src/main/java/org/olat/core/util/mail/model/DBMailRecipient.hbm.xml new file mode 100644 index 0000000000000000000000000000000000000000..14a7d4379940204ff10ad9f951c06c8beda426db --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/model/DBMailRecipient.hbm.xml @@ -0,0 +1,23 @@ +<?xml version="1.0"?> +<!DOCTYPE hibernate-mapping PUBLIC + "-//Hibernate/Hibernate Mapping DTD//EN" + "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> +<hibernate-mapping default-lazy="false"> + + <class name="org.olat.core.util.mail.model.DBMailRecipient" table="o_mail_recipient"> + <!-- the default columns --> + <id name="key" column="recipient_id" type="long" unsaved-value="null"> + <generator class="hilo"/> + </id> + <property name="creationDate" column="creationdate" type="timestamp" /> + <property name="deleted" column="deleted" type="boolean" /> + <property name="visible" column="recipientvisible" type="boolean" /> + <property name="read" column="mailread" type="boolean" /> + <property name="marked" column="mailmarked" type="boolean" /> + <property name="group" column="recipientgroup" type="string" length="255"/> + <property name="emailAddress" column="email" type="string" length="255"/> + + <many-to-one name="recipient" column="fk_recipient_id" class="org.olat.basesecurity.IdentityImpl" fetch="join" unique="false" cascade="none"/> + </class> + +</hibernate-mapping> diff --git a/src/main/java/org/olat/core/util/mail/model/DBMailRecipient.java b/src/main/java/org/olat/core/util/mail/model/DBMailRecipient.java new file mode 100644 index 0000000000000000000000000000000000000000..feebbf28054e4172112b60ceceb092416d3f1d5d --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/model/DBMailRecipient.java @@ -0,0 +1,127 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail.model; + +import org.olat.core.commons.persistence.PersistentObject; +import org.olat.core.id.Identity; + +/** + * + * Description:<br> + * + * + * <P> + * Initial Date: 24 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class DBMailRecipient extends PersistentObject { + + private static final long serialVersionUID = -6793421633217512631L; + + private Identity recipient; + private String emailAddress; + private Boolean deleted; + private Boolean visible; + private Boolean read; + private Boolean marked; + private String group; + + public DBMailRecipient() { + //make Hibernate happy + } + + public DBMailRecipient(Identity recipient) { + this.recipient = recipient; + } + + public Identity getRecipient() { + return recipient; + } + + public void setRecipient(Identity recipient) { + this.recipient = recipient; + } + + public String getEmailAddress() { + return emailAddress; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } + + public Boolean getDeleted() { + return deleted; + } + + public void setDeleted(Boolean deleted) { + this.deleted = deleted; + } + + public Boolean getVisible() { + return visible; + } + + public void setVisible(Boolean visible) { + this.visible = visible; + } + + public Boolean getRead() { + return read; + } + + public void setRead(Boolean read) { + this.read = read; + } + + public Boolean getMarked() { + return marked; + } + + public void setMarked(Boolean marked) { + this.marked = marked; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + @Override + public int hashCode() { + return getKey() == null ? 2981 : getKey().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof DBMailRecipient) { + DBMailRecipient recipient = (DBMailRecipient)obj; + return getKey() != null && getKey().equals(recipient.getKey()); + } + return false; + } +} diff --git a/src/main/java/org/olat/core/util/mail/ui/BooleanCSSCellRenderer.java b/src/main/java/org/olat/core/util/mail/ui/BooleanCSSCellRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..39f4a2215199f6f901ead99c124374ff4ed80945 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/BooleanCSSCellRenderer.java @@ -0,0 +1,71 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ +package org.olat.core.util.mail.ui; + +import org.olat.core.gui.components.table.CustomCssCellRenderer; +import org.olat.core.gui.translator.Translator; + +/** + * + * Description:<br> + * + * <P> + * Initial Date: 25 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class BooleanCSSCellRenderer extends CustomCssCellRenderer { + + private String trueCss; + private String falseCss; + private String trueHoverText; + private String falseHoverText; + + private final Translator translator; + + public BooleanCSSCellRenderer(Translator translator, String trueCss, String falseCss, + String trueHoverText, String falseHoverText) { + this.trueCss = trueCss; + this.falseCss = falseCss; + this.trueHoverText = trueHoverText; + this.falseHoverText = falseHoverText; + this.translator = translator; + } + + @Override + protected String getCssClass(Object val) { + if(val instanceof Boolean) { + return ((Boolean)val).booleanValue() ? trueCss : falseCss; + } + return ""; + } + + @Override + protected String getCellValue(Object val) { + return ""; + } + + @Override + protected String getHoverText(Object val) { + if(val instanceof Boolean) { + return ((Boolean)val).booleanValue() ? translator.translate(trueHoverText) : translator.translate(falseHoverText); + } + return ""; + } +} diff --git a/src/main/java/org/olat/core/util/mail/ui/MailActionExtension.java b/src/main/java/org/olat/core/util/mail/ui/MailActionExtension.java new file mode 100644 index 0000000000000000000000000000000000000000..cc3cf468faf5b43e7ae75b2b0a81f84ca0913220 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailActionExtension.java @@ -0,0 +1,53 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 2008 frentix GmbH, Switzerland<br> + * <p> + */ +package org.olat.core.util.mail.ui; + +import org.olat.core.extensions.action.GenericActionExtension; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.tree.GenericTreeNode; + +/** + * + * Description:<br> + * MailActionExtension is used in MinimalHomeController (Home-menu). it returns + * a MailTreeNode which displays an iconDecorator if user has unread e-mails in + * his inbox + * + * <P> + * Initial Date: 13.09.2011 <br> + * + * @author Sergio Trentini, sergio.trentini@frentix.com, www.frentix.com + */ +public class MailActionExtension extends GenericActionExtension { + + @Override + public GenericTreeNode createMenuNode(UserRequest ureq) { + GenericTreeNode node = new MailTreeNode(ureq.getIdentity()); + node.setAltText(getDescription(ureq.getLocale())); + node.setTitle(getActionText(ureq.getLocale())); + node.setIconCssClass(getIconCssClass()); + node.setCssClass(getCssClass()); + + node.setUserObject(this); + + return node; + } + +} diff --git a/src/main/java/org/olat/core/util/mail/ui/MailAdminController.java b/src/main/java/org/olat/core/util/mail/ui/MailAdminController.java new file mode 100644 index 0000000000000000000000000000000000000000..fb943b6586cd9836207832fb88b64be3ff8a96d5 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailAdminController.java @@ -0,0 +1,143 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ +package org.olat.core.util.mail.ui; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.SingleSelection; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.Util; +import org.olat.core.util.mail.MailModule; +import org.olat.core.util.mail.MailUIFactory; + +/** + * + * Description:<br> + * Small administration to set on/off the intern mail system + * + * <P> + * Initial Date: 14 avr. 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailAdminController extends FormBasicController { + + private MultipleSelectionElement enabled; + private SingleSelection userDefaultSettingEl; + + private String[] values = {""}; + private String[] keys = {"on"}; + + + private String[] userSettingValues ; + private String[] userSettingKeys = {"intern.only","send.copy"}; + + public MailAdminController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, null, Util.createPackageTranslator(MailModule.class, ureq.getLocale())); + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + this.setFormTitle("mail.admin.title"); + this.setFormDescription("mail.admin.description"); + this.setFormContextHelp(MailUIFactory.class.getPackage().getName(), "mail-admin.html", "chelp.mail-admin.title"); + + boolean internEnabled = isEnabled(); + enabled = uifactory.addCheckboxesHorizontal("mail.admin.intern.enabled", formLayout, keys, values, null); + enabled.select(keys[0], internEnabled); + enabled.addActionListener(this, FormEvent.ONCHANGE); + + boolean realMailSetting = isUserDefaultSetting(); + userSettingValues = new String[] { + translate("mail.admin.intern.only"), + translate("mail.admin.intern.real.mail") + }; + userDefaultSettingEl = uifactory.addRadiosVertical("mail-system", "mail.admin.default.settings", formLayout, userSettingKeys, userSettingValues); + if(realMailSetting) { + userDefaultSettingEl.select(userSettingKeys[1], true); + } else { + userDefaultSettingEl.select(userSettingKeys[0], true); + } + userDefaultSettingEl.setEnabled(internEnabled); + + final FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonLayout", getTranslator()); + buttonGroupLayout.setRootForm(mainForm); + formLayout.add(buttonGroupLayout); + + uifactory.addFormSubmitButton("save", formLayout); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + boolean on = !enabled.getSelectedKeys().isEmpty(); + setEnabled(on); + + if(userDefaultSettingEl.isOneSelected()) { + boolean realMailSetting = userDefaultSettingEl.getSelected() == 1; + setUserDefaultSetting(realMailSetting); + } + userDefaultSettingEl.setEnabled(on); + + getWindowControl().setInfo("saved"); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source == enabled) { + boolean on = !enabled.getSelectedKeys().isEmpty(); + userDefaultSettingEl.setEnabled(on); + } + super.formInnerEvent(ureq, source, event); + } + + private boolean isEnabled() { + MailModule config = (MailModule) CoreSpringFactory.getBean("mailModule"); + return config.isInternSystem(); + } + + private void setEnabled(boolean enabled) { + MailModule config = (MailModule) CoreSpringFactory.getBean("mailModule"); + config.setInterSystem(enabled); + } + + + private boolean isUserDefaultSetting() { + MailModule config = (MailModule) CoreSpringFactory.getBean("mailModule"); + return config.isReceiveRealMailUserDefaultSetting(); + } + + private void setUserDefaultSetting(boolean enabled) { + MailModule config = (MailModule) CoreSpringFactory.getBean("mailModule"); + config.setReceiveRealMailUserDefaultSetting(enabled); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/util/mail/ui/MailAttachmentMapper.java b/src/main/java/org/olat/core/util/mail/ui/MailAttachmentMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..ba8fccfe3c69998f0f1e21f2157136513c32555a --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailAttachmentMapper.java @@ -0,0 +1,144 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail.ui; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.olat.core.dispatcher.mapper.Mapper; +import org.olat.core.gui.media.ForbiddenMediaResource; +import org.olat.core.gui.media.MediaResource; +import org.olat.core.gui.media.NotFoundMediaResource; +import org.olat.core.util.StringHelper; +import org.olat.core.util.WebappHelper; +import org.olat.core.util.mail.manager.MailManager; +import org.olat.core.util.mail.model.DBMail; +import org.olat.core.util.mail.model.DBMailAttachmentData; + +/** + * + * Description:<br> + * TODO: srosse Class Description for MailAttachmentMapper + * + * <P> + * Initial Date: 28 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailAttachmentMapper implements Mapper { + + public static final String ATTACHMENT_CONTEXT = "/attachments/"; + + private final DBMail mail; + private final MailManager mailManager; + + public MailAttachmentMapper(DBMail mail, MailManager mailManager) { + this.mail = mail; + this.mailManager = mailManager; + } + + @Override + public MediaResource handle(String relPath, HttpServletRequest request) { + if(relPath != null && relPath.indexOf(ATTACHMENT_CONTEXT) >= 0) { + int startIndex = relPath.indexOf(ATTACHMENT_CONTEXT); + int endIndex = relPath.indexOf("/", startIndex + ATTACHMENT_CONTEXT.length()); + if(startIndex >= 0 && endIndex > startIndex) { + String attachmentKey = relPath.substring(startIndex + ATTACHMENT_CONTEXT.length(), endIndex); + try { + Long key = new Long(attachmentKey); + + boolean rightMail = true; + /*for(DBMailAttachment attachment:mail.getAttachments()) { + if(key.equals(attachment.getKey())) { + rightMail = true; + break; + } + }*/ + + if(rightMail) { + DBMailAttachmentData datas = mailManager.getAttachmentWithData(key); + BytesMediaResource resource = new BytesMediaResource(datas); + return resource; + } else { + //only show the attachment of the selected e-mail + return new ForbiddenMediaResource(relPath); + } + } catch(NumberFormatException e) { + return new NotFoundMediaResource(relPath); + } + } + } + return new NotFoundMediaResource(relPath); + } + + public class BytesMediaResource implements MediaResource { + + private final DBMailAttachmentData datas; + + public BytesMediaResource(DBMailAttachmentData datas) { + this.datas = datas; + } + + @Override + public String getContentType() { + if(StringHelper.containsNonWhitespace(datas.getMimetype())) { + return datas.getMimetype(); + } + if(StringHelper.containsNonWhitespace(datas.getName())) { + String mimeType = WebappHelper.getMimeType(datas.getName()); + if(StringHelper.containsNonWhitespace(mimeType)) { + return mimeType; + } + } + return "application/octet-stream"; + } + + @Override + public Long getSize() { + if(datas.getDatas() == null) return 0l; + return new Long(datas.getDatas().length); + } + + @Override + public InputStream getInputStream() { + return new ByteArrayInputStream(datas.getDatas()); + } + + @Override + public Long getLastModified() { + return null; + } + + @Override + public void prepare(HttpServletResponse hres) { + String fileName = datas.getName(); + hres.setHeader("Content-Disposition","filename=\"" + StringHelper.urlEncodeISO88591(fileName) + "\""); + hres.setHeader("Content-Description",StringHelper.urlEncodeISO88591(fileName)); + } + + @Override + public void release() { + // + } + } +} diff --git a/src/main/java/org/olat/core/util/mail/ui/MailContextCellRenderer.java b/src/main/java/org/olat/core/util/mail/ui/MailContextCellRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..3f4645140a49a5503f390c3c04b537908bf82b8c --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailContextCellRenderer.java @@ -0,0 +1,76 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) frentix GmbH<br> + * http://www.frentix.com<br> + * <p> + */ +package org.olat.core.util.mail.ui; + +import java.util.Locale; +import java.util.UUID; + +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.table.CustomCellRenderer; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.render.RenderResult; +import org.olat.core.gui.render.Renderer; +import org.olat.core.gui.render.StringOutput; +import org.olat.core.gui.render.URLBuilder; +import org.olat.core.gui.translator.Translator; +import org.olat.core.util.mail.ui.MailDataModel.ContextPair; + +/** + * + * Description:<br> + * Render a list of resources / with link + * + * <P> + * Initial Date: 7 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailContextCellRenderer implements CustomCellRenderer { + + private final Translator translator; + private VelocityContainer container; + private final Controller listeningController; + + public MailContextCellRenderer(Controller listeningController, VelocityContainer container, Translator translator) { + this.listeningController = listeningController; + this.container = container; + this.translator = translator; + } + + @Override + public void render(StringOutput sb, Renderer renderer, Object val, Locale locale, int alignment, String action) { + if(val instanceof ContextPair) { + ContextPair context = (ContextPair)val; + if(renderer == null) { + sb.append(context.getName()); + } else { + Link link = LinkFactory.createLink("bp_" + UUID.randomUUID().toString(), container, listeningController); + link.setCustomDisplayText(context.getName()); + link.setUserObject(context.getBusinessPath()); + + URLBuilder ubu = renderer.getUrlBuilder().createCopyFor(link); + RenderResult renderResult = new RenderResult(); + link.getHTMLRendererSingleton().render(renderer, sb, link, ubu, translator, renderResult, null); + } + } + } +} diff --git a/src/main/java/org/olat/core/util/mail/ui/MailContextResolver.java b/src/main/java/org/olat/core/util/mail/ui/MailContextResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..1f9f26e05e5d537aaa85f9d8680f7964f1b30fa3 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailContextResolver.java @@ -0,0 +1,23 @@ +package org.olat.core.util.mail.ui; + +import java.util.Locale; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.WindowControl; + +/** + * + * Description:<br> + * TODO: srosse Class Description for MailContextResolver + * + * <P> + * Initial Date: 30 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public interface MailContextResolver { + + public String getName(String businessPath, Locale locale); + + public void open(UserRequest ureq, WindowControl wControl, String url); + +} diff --git a/src/main/java/org/olat/core/util/mail/ui/MailContextShortName.java b/src/main/java/org/olat/core/util/mail/ui/MailContextShortName.java new file mode 100644 index 0000000000000000000000000000000000000000..34ccc59e101ed825a90e085dd3eea1c6aac468a6 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailContextShortName.java @@ -0,0 +1,59 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + + +package org.olat.core.util.mail.ui; + +import org.olat.core.gui.ShortName; + +/** + * + * Description:<br> + * + * <P> + * Initial Date: 30 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailContextShortName implements ShortName { + private String businessPath; + private String contextName; + + public MailContextShortName(String contextName) { + this(contextName, null); + } + + public MailContextShortName(String contextName, String businessPath) { + this.contextName = contextName; + this.businessPath = businessPath; + } + + @Override + public String getShortName() { + return contextName; + } + + public String getBusinessPath() { + return businessPath; + } + + public String getContextName() { + return contextName; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/core/util/mail/ui/MailController.java b/src/main/java/org/olat/core/util/mail/ui/MailController.java new file mode 100644 index 0000000000000000000000000000000000000000..249e9ed456f0d4c4f5114da31225b1706a13fecd --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailController.java @@ -0,0 +1,188 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail.ui; + +import java.text.DateFormat; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.id.Identity; +import org.olat.core.id.User; +import org.olat.core.id.UserConstants; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.core.util.mail.MailModule; +import org.olat.core.util.mail.manager.MailManager; +import org.olat.core.util.mail.model.DBMail; +import org.olat.core.util.mail.model.DBMailAttachment; +import org.olat.core.util.mail.model.DBMailRecipient; + +/** + * + * Description:<br> + * + * <P> + * Initial Date: 24 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailController extends FormBasicController { + + private FormLink backLink; + + private String mapperBaseURI; + private final boolean back; + private final DBMail mail; + private final List<DBMailAttachment> attachments; + private final MailManager mailManager; + + public MailController(UserRequest ureq, WindowControl wControl, DBMail mail, boolean back) { + super(ureq, wControl, LAYOUT_VERTICAL); + setTranslator(Util.createPackageTranslator(MailModule.class, ureq.getLocale())); + this.mail = mail; + this.back = back; + mailManager = MailManager.getInstance(); + attachments = MailManager.getInstance().getAttachments(mail); + if(!attachments.isEmpty()) { + mapperBaseURI = registerMapper(new MailAttachmentMapper(mail, mailManager)); + } + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer mainLayout, Controller listener, UserRequest ureq) { + setTranslator(Util.createPackageTranslator(MailModule.class, ureq.getLocale())); + String page = Util.getPackageVelocityRoot(MailModule.class) + "/mail.html"; + FormLayoutContainer vcLayout = FormLayoutContainer.createCustomFormLayout("wrapper", getTranslator(), page); + vcLayout.setRootForm(mainForm); + mainLayout.add(vcLayout); + + if(back) { + backLink = uifactory.addFormLink("back", vcLayout, Link.LINK_BACK); + vcLayout.add("back", backLink); + } + + FormLayoutContainer formLayout = FormLayoutContainer.createDefaultFormLayout("mainCmp", getTranslator()); + formLayout.setRootForm(mainForm); + vcLayout.add("mainCmp", formLayout); + + uifactory.addStaticTextElement("subject", "mail.subject", mail.getSubject(), formLayout); + + String from = getFullName(mail.getFrom()); + uifactory.addStaticTextElement("from", "mail.from", from, formLayout); + + String recipients = getRecipients(); + uifactory.addStaticTextElement("recipients", "mail.recipients", recipients, formLayout); + + String date = DateFormat.getDateInstance(DateFormat.MEDIUM, getLocale()).format(mail.getCreationDate()); + uifactory.addStaticTextElement("date", "mail.sendDate", date, formLayout); + + uifactory.addSpacerElement("spacer2", formLayout, false); + uifactory.addStaticTextElement("body", "mail.body", formattedBody(), formLayout); + + if(!attachments.isEmpty()) { + uifactory.addSpacerElement("spacer3", formLayout, false); + String attachmentsPage = Util.getPackageVelocityRoot(MailModule.class) + "/attachments.html"; + FormLayoutContainer container = FormLayoutContainer.createCustomFormLayout("attachments", getTranslator(), attachmentsPage); + container.setLabel("mail.attachments", null); + container.setRootForm(mainForm); + container.contextPut("attachments", attachments); + container.contextPut("mapperBaseURI", mapperBaseURI); + formLayout.add(container); + } + } + + private String getRecipients() { + StringBuilder sb = new StringBuilder(); + Set<String> groups = new HashSet<String>(); + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient == null) continue; + String group = recipient.getGroup(); + if(StringHelper.containsNonWhitespace(group) && !groups.contains(group)) { + if(sb.length() > 0) sb.append(", "); + sb.append(group); + groups.add(group); + } + } + return sb.toString(); + } + + private String getFullName(DBMailRecipient recipient) { + if(recipient == null) return ""; + return getFullName(recipient.getRecipient()); + } + + private String getFullName(Identity identity) { + StringBuilder sb = new StringBuilder(); + if(identity != null) { + User user = identity.getUser(); + sb.append(user.getProperty(UserConstants.LASTNAME, null)) + .append(" ") + .append(user.getProperty(UserConstants.FIRSTNAME, null)); + } + return sb.toString(); + } + + private String formattedBody() { + String body = mail.getBody(); + if(!StringHelper.containsNonWhitespace(body)) return ""; + + if(body.indexOf("<") >= 0 && body.indexOf("/>") >= 0) { + //html + return body; + } + + body = body.replace("\n\r", "<br />");//if windows + body = body.replace("\n", "<br />"); + return body; + } + + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(source == backLink) { + fireEvent(ureq, Event.BACK_EVENT); + } else { + super.formInnerEvent(ureq, source, event); + } + } +} diff --git a/src/main/java/org/olat/core/util/mail/ui/MailDataModel.java b/src/main/java/org/olat/core/util/mail/ui/MailDataModel.java new file mode 100644 index 0000000000000000000000000000000000000000..e92a86f454b88a378733ceefe6c7612b86beac79 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailDataModel.java @@ -0,0 +1,243 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail.ui; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.olat.core.gui.components.table.TableDataModelWithMarkableRows; +import org.olat.core.gui.translator.Translator; +import org.olat.core.id.Identity; +import org.olat.core.util.Formatter; +import org.olat.core.util.StringHelper; +import org.olat.core.util.mail.model.DBMail; +import org.olat.core.util.mail.model.DBMailRecipient; + +/** + * + * Description:<br> + * + * + * <P> + * Initial Date: 28 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailDataModel implements TableDataModelWithMarkableRows { + + private boolean outbox; + private List<DBMail> mails; + private List<DBMail> filteredMails; + private final Identity identity; + private final Formatter formatter; + private final Translator translator; + private final Map<String,String> bpToContexts; + + public MailDataModel(List<DBMail> mails, Map<String,String> bpToContexts, Identity identity, + Translator translator, Formatter formatter, boolean outbox) { + this.mails = mails; + this.bpToContexts = bpToContexts; + this.identity = identity; + this.formatter = formatter; + this.translator = translator; + this.outbox = outbox; + } + + @Override + public int getColumnCount() { + return 2; + } + + @Override + public int getRowCount() { + return filteredMails == null ? mails.size() : filteredMails.size(); + } + + @Override + public Object getValueAt(int row, int col) { + DBMail mail = filteredMails == null ? mails.get(row) : filteredMails.get(row); + Columns[] cols = Columns.values(); + if(col < cols.length) { + switch(cols[col]) { + case read: { + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient != null && recipient.getRecipient() != null && recipient.getRecipient().equalsByPersistableKey(identity)) { + return recipient.getRead(); + } + } + return Boolean.FALSE; + } + case marked: { + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient != null && recipient.getRecipient() != null && recipient.getRecipient().equalsByPersistableKey(identity)) { + return recipient.getMarked(); + } + } + return Boolean.FALSE; + } + case context: { + String businessPath = mail.getContext().getBusinessPath(); + if(StringHelper.containsNonWhitespace(businessPath)) { + String contextName = bpToContexts.get(businessPath); + if(StringHelper.containsNonWhitespace(businessPath) && StringHelper.containsNonWhitespace(contextName)) { + return new ContextPair(contextName, businessPath); + } + } + return null; + } + case subject: return mail.getSubject(); + case receivedDate: + case sendDate: { + return mail.getCreationDate(); + } + case from: { + DBMailRecipient from = mail.getFrom(); + if(from != null ) { + if(from.getRecipient() != null) { + return from.getRecipient(); + } else if (StringHelper.containsNonWhitespace(from.getGroup())) { + return from.getGroup(); + } else if (StringHelper.containsNonWhitespace(from.getEmailAddress())) { + return from.getEmailAddress(); + } + } + return "-"; + } + case recipients: { + if(StringHelper.containsNonWhitespace(mail.getMetaId())) { + return translator.translate("mail.from.miscellaneous"); + } + + StringBuilder sb = new StringBuilder(); + Set<String> groupSet = new HashSet<String>(); + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient != null && recipient.getGroup() != null) { + String group = recipient.getGroup(); + if(!groupSet.contains(group)) { + if(sb.length() > 0) sb.append(", "); + sb.append(group); + groupSet.add(group); + } + } + } + return sb.toString(); + } + } + } + return mail; + } + + @Override + public DBMail getObject(int row) { + return filteredMails == null ? mails.get(row) : filteredMails.get(row); + } + + @Override + public void setObjects(List objects) { + mails = objects; + filteredMails = null; + } + + /** + * @see org.olat.core.gui.components.table.TableDataModelWithMarkableRows#getRowCssClass(int) + */ + @Override + public String getRowCssClass(int row) { + if(outbox) return null; + + DBMail mail = filteredMails == null ? mails.get(row) : filteredMails.get(row); + for(DBMailRecipient recipient:mail.getRecipients()) { + if(recipient != null && recipient.getRecipient() != null && recipient.getRecipient().equalsByPersistableKey(identity)) { + if (!recipient.getRead()) { + return "b_marked"; + } + } + } + return null; + } + + public void replace(DBMail mail) { + int index = mails.indexOf(mail); + if(index >= 0 && index < mails.size()) { + mails.set(index, mail); + } + } + + public void filter(MailContextShortName filter) { + if(filter == null || !StringHelper.containsNonWhitespace(filter.getBusinessPath())) { + filteredMails = null; + } else { + filteredMails = new ArrayList<DBMail>(); + for(DBMail mail:mails) { + if(filter.getBusinessPath().equals(mail.getContext().getBusinessPath())) { + filteredMails.add(mail); + } + } + } + } + + @Override + public Object createCopyWithEmptyList() { + return new MailDataModel(Collections.<DBMail>emptyList(), bpToContexts, identity, translator, formatter, outbox); + } + + public enum Columns { + read("mail.read.header"), + marked("mail.marked.header"), + context("mail.context"), + subject("mail.subject"), + sendDate("mail.sendDate"), + receivedDate("mail.receivedDate"), + from("mail.from"), + recipients("mail.recipients"); + + + private final String i18nKey; + + private Columns(String i18nKey) { + this.i18nKey = i18nKey; + } + + public String i18nKey() { + return i18nKey; + } + } + + public class ContextPair { + private final String name; + private final String businessPath; + + public ContextPair(String name, String businessPath) { + this.name = name; + this.businessPath = businessPath; + } + + public String getName() { + return name; + } + public String getBusinessPath() { + return businessPath; + } + } +} diff --git a/src/main/java/org/olat/core/util/mail/ui/MailFromCellRenderer.java b/src/main/java/org/olat/core/util/mail/ui/MailFromCellRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..e11ac751672112cc9f8b56d6fb6f88a0c4e0b71b --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailFromCellRenderer.java @@ -0,0 +1,82 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) frentix GmbH<br> + * http://www.frentix.com<br> + * <p> + */ +package org.olat.core.util.mail.ui; + +import java.util.Locale; +import java.util.UUID; + +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.table.CustomCellRenderer; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.render.RenderResult; +import org.olat.core.gui.render.Renderer; +import org.olat.core.gui.render.StringOutput; +import org.olat.core.gui.render.URLBuilder; +import org.olat.core.gui.translator.Translator; +import org.olat.core.id.Identity; +import org.olat.core.id.User; +import org.olat.core.id.UserConstants; + +/** + * + * Description:<br> + * Render the from with link to visit card or group name or email + * + * <P> + * Initial Date: 7 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailFromCellRenderer implements CustomCellRenderer { + + private final Translator translator; + private VelocityContainer container; + private final Controller listeningController; + + public MailFromCellRenderer(Controller listeningController, VelocityContainer container, Translator translator) { + this.listeningController = listeningController; + this.container = container; + this.translator = translator; + } + + @Override + public void render(StringOutput sb, Renderer renderer, Object val, Locale locale, int alignment, String action) { + if(val instanceof Identity) { + Identity identity = (Identity)val; + User user = identity.getUser(); + String fullName = user.getProperty(UserConstants.LASTNAME, null) + " " + user.getProperty(UserConstants.FIRSTNAME, null); + + if(renderer == null) { + sb.append(fullName); + } else { + Link link = LinkFactory.createLink("bp_" + UUID.randomUUID().toString(), container, listeningController); + link.setCustomDisplayText(fullName); + link.setUserObject("[Identity:" + identity.getKey() + "]"); + URLBuilder ubu = renderer.getUrlBuilder().createCopyFor(link); + RenderResult renderResult = new RenderResult(); + link.getHTMLRendererSingleton().render(renderer, sb, link, ubu, translator, renderResult, null); + } + } else if (val instanceof String) { + sb.append("<span>").append((String)val).append("</span>"); + } + } +} diff --git a/src/main/java/org/olat/core/util/mail/ui/MailListController.java b/src/main/java/org/olat/core/util/mail/ui/MailListController.java new file mode 100644 index 0000000000000000000000000000000000000000..7965d84bab57ba568623e87013c955bdeca88935 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailListController.java @@ -0,0 +1,447 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.core.util.mail.ui; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.olat.core.gui.ShortName; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; +import org.olat.core.gui.components.table.ColumnDescriptor; +import org.olat.core.gui.components.table.CustomCellRenderer; +import org.olat.core.gui.components.table.CustomRenderColumnDescriptor; +import org.olat.core.gui.components.table.DefaultColumnDescriptor; +import org.olat.core.gui.components.table.StaticColumnDescriptor; +import org.olat.core.gui.components.table.Table; +import org.olat.core.gui.components.table.TableController; +import org.olat.core.gui.components.table.TableEvent; +import org.olat.core.gui.components.table.TableGuiConfiguration; +import org.olat.core.gui.components.table.TableMultiSelectEvent; +import org.olat.core.gui.components.velocity.VelocityContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.gui.control.generic.dtabs.Activateable; +import org.olat.core.gui.control.generic.dtabs.Activateable2; +import org.olat.core.gui.control.generic.modal.DialogBoxController; +import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; +import org.olat.core.id.OLATResourceable; +import org.olat.core.id.context.ContextEntry; +import org.olat.core.id.context.StateEntry; +import org.olat.core.util.Formatter; +import org.olat.core.util.StringHelper; +import org.olat.core.util.mail.MailHelper; +import org.olat.core.util.mail.MailModule; +import org.olat.core.util.mail.MailerResult; +import org.olat.core.util.mail.manager.MailManager; +import org.olat.core.util.mail.model.DBMail; +import org.olat.core.util.mail.model.DBMailImpl; +import org.olat.core.util.mail.model.DBMailRecipient; +import org.olat.core.util.mail.ui.MailDataModel.Columns; +import org.olat.core.util.resource.OresHelper; + + +/** + * + * Description:<br> + * Represent a list of mails. + * + * <P> + * Initial Date: 24 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailListController extends BasicController implements Activateable, Activateable2 { + + private static final String CMD_READ_TOGGLE = "creadt"; + private static final String CMD_READ = "cread"; + private static final String CMD_DELETE = "cdelselected"; + private static final String CMD_MARK_TOGGLE = "cmark"; + private static final String CMD_PROFILE = "cprofile"; + private static final String CMD_SEND_REAL_MAIL = "cfwd"; + private static final String CMD_MARK_READ = "creadselected"; + private static final String CMD_MARK_UNREAD = "cunreadselected"; + private static final String CMD_MARK_MARKED = "cmarkselected"; + private static final String CMD_MARK_UNMARKED = "cunmarkselected"; + private static final String MAIN_CMP = "mainCmp"; + + private Link backLink; + private final VelocityContainer mainVC; + private MailController mailCtr; + private MailListController metaMailCtr; + private final TableController tableCtr; + private final VelocityContainer tableVC; + private DialogBoxController deleteConfirmationBox; + + + private final boolean outbox; + private final String metaId; + private final MailManager mailManager; + private final MailContextResolver contextResolver; + + public MailListController(UserRequest ureq, WindowControl wControl, boolean outbox, MailContextResolver resolver) { + this(ureq, wControl, null, outbox, resolver); + } + + private MailListController(UserRequest ureq, WindowControl wControl, String metaId, boolean outbox, MailContextResolver resolver) { + super(ureq, wControl); + setBasePackage(MailModule.class); + this.outbox = outbox; + this.metaId = metaId; + this.contextResolver = resolver; + + mailManager = MailManager.getInstance(); + + TableGuiConfiguration tableConfig = new TableGuiConfiguration(); + tableConfig.setDownloadOffered(true); + tableConfig.setPreferencesOffered(true, "MailBox"); + tableConfig.setTableEmptyMessage(translate("mail.empty.box")); + tableConfig.setMultiSelect(true); + + mainVC = createVelocityContainer("mails"); + tableVC = createVelocityContainer("mailsTable"); + + String context = translate("mail.context"); + tableCtr = new TableController(tableConfig, ureq, wControl, Collections.<ShortName>emptyList(), null, context , null, false, getTranslator()); + + //only for outbox + if(outbox) { + //context / recipients / subject / sendDate + tableCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Columns.context.i18nKey(), Columns.context.ordinal(), null, + getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, new MailContextCellRenderer(this, tableVC, getTranslator()))); + tableCtr.addColumnDescriptor(new DefaultColumnDescriptor(Columns.recipients.i18nKey(), Columns.recipients.ordinal(), null, getLocale())); + tableCtr.addColumnDescriptor(new DefaultColumnDescriptor(Columns.subject.i18nKey(), Columns.subject.ordinal(), CMD_READ, getLocale())); + tableCtr.addColumnDescriptor(new DefaultColumnDescriptor(Columns.sendDate.i18nKey(), Columns.sendDate.ordinal(), null, getLocale())); + } else { + //read / marked / context / from / subject / receivedDate + CustomCellRenderer readRenderer = new BooleanCSSCellRenderer(getTranslator(), "b_mail_read", "b_mail_unread", "mail.read", "mail.unread"); + tableCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Columns.read.i18nKey(), Columns.read.ordinal(), CMD_READ_TOGGLE, + getLocale(), ColumnDescriptor.ALIGNMENT_CENTER, readRenderer)); + CustomCellRenderer markRenderer = new BooleanCSSCellRenderer(getTranslator(), "b_mail_marked", "b_mail_unmarked", "mail.marked", "mail.unmarked"); + tableCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Columns.marked.i18nKey(), Columns.marked.ordinal(), CMD_MARK_TOGGLE, + getLocale(), ColumnDescriptor.ALIGNMENT_CENTER, markRenderer)); + tableCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Columns.context.i18nKey(), Columns.context.ordinal(), null, + getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, new MailContextCellRenderer(this, tableVC, getTranslator()))); + tableCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Columns.from.i18nKey(), Columns.from.ordinal(), null, + getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, new MailFromCellRenderer(this, tableVC, getTranslator()))); + tableCtr.addColumnDescriptor(new DefaultColumnDescriptor(Columns.subject.i18nKey(), Columns.subject.ordinal(), CMD_READ, getLocale())); + tableCtr.addColumnDescriptor(new DefaultColumnDescriptor(Columns.receivedDate.i18nKey(), Columns.receivedDate.ordinal(), null, getLocale())); + } + + tableCtr.addColumnDescriptor(new StaticColumnDescriptor(CMD_READ, "mail.action.open", translate("mail.action.open"))); + + // only for inbox + if (!outbox) { + tableCtr.addMultiSelectAction("mail.action.read", CMD_MARK_READ); + tableCtr.addMultiSelectAction("mail.action.unread", CMD_MARK_UNREAD); + tableCtr.addMultiSelectAction("mail.action.mark", CMD_MARK_MARKED); + tableCtr.addMultiSelectAction("mail.action.unmark", CMD_MARK_UNMARKED); + } + tableCtr.addMultiSelectAction("mail.action.send.real", CMD_SEND_REAL_MAIL); + tableCtr.addMultiSelectAction("delete", CMD_DELETE); + + reloadModel(); + + int dateSort = outbox ? 4 : 6; + tableCtr.setSortColumn(dateSort, false); + + listenTo(tableCtr); + + tableVC.put("tableCmp", tableCtr.getInitialComponent()); + if(outbox) { + if(StringHelper.containsNonWhitespace(metaId)) { + tableVC.contextPut("title", translate("mail.outbox.title")); + tableVC.contextPut("description", translate("mail.outbox.meta")); + + } else { + tableVC.contextPut("title", translate("mail.outbox.title")); + } + } else { + tableVC.contextPut("title", translate("mail.inbox.title")); + } + + mainVC.put(MAIN_CMP, tableVC); + if(StringHelper.containsNonWhitespace(metaId)) { + backLink = LinkFactory.createLinkBack(mainVC, this); + mainVC.put("back", backLink); + } + + putInitialPanel(mainVC); + } + + private void replaceInModel(DBMail mail) { + MailDataModel dataModel = (MailDataModel)tableCtr.getTableDataModel(); + dataModel.replace(mail); + tableCtr.modelChanged(); + } + + private void reloadModel() { + List<DBMail> mails; + if(outbox) { + if(StringHelper.containsNonWhitespace(metaId)) { + mails = MailManager.getInstance().getEmailsByMetaId(metaId); + } else { + mails = MailManager.getInstance().getOutbox(getIdentity(), 0, 0); + } + + //strip meta emails + Set<String> metaIds = new HashSet<String>(); + for(Iterator<DBMail> it=mails.iterator(); it.hasNext(); ) { + DBMail mail = it.next(); + if(StringHelper.containsNonWhitespace(mail.getMetaId())) { + if(metaIds.contains(mail.getMetaId())) { + it.remove(); + } else { + metaIds.add(mail.getMetaId()); + } + } + } + } else { + mails = MailManager.getInstance().getInbox(getIdentity(), null, Boolean.TRUE, null, 0, 0); + } + + //extract contexts + Map<String, String> bpToContexts = new HashMap<String, String>(); + for(DBMail mail:mails) { + String businessPath = mail.getContext().getBusinessPath(); + if(StringHelper.containsNonWhitespace(businessPath) && !bpToContexts.containsKey(businessPath)) { + String contextName = contextResolver.getName(businessPath, getLocale()); + if(StringHelper.containsNonWhitespace(contextName)) { + bpToContexts.put(businessPath, contextName); + } + } + } + + if(!bpToContexts.isEmpty()) { + List<ShortName> filters = new ArrayList<ShortName>(); + ShortName allContextFilter = new MailContextShortName("-"); + filters.add(allContextFilter); + for(Map.Entry<String, String> entry:bpToContexts.entrySet()) { + String businessPath = entry.getKey(); + String contextName = entry.getValue(); + filters.add(new MailContextShortName(contextName, businessPath)); + } + tableCtr.setFilters(filters, allContextFilter); + } + + Formatter formatter = Formatter.getInstance(getLocale()); + MailDataModel dataModel = new MailDataModel(mails, bpToContexts, getIdentity(), getTranslator(), formatter, outbox); + tableCtr.setTableDataModel(dataModel); + } + + @Override + protected void event(UserRequest ureq, Component source, Event event) { + if(source == backLink) { + if(mailCtr != null) { + backFromMail(); + } else { + fireEvent(ureq, event); + } + } else if (source instanceof Link && source.getComponentName().startsWith("bp_")) { + String businessPath = (String)((Link)source).getUserObject(); + if(StringHelper.containsNonWhitespace(businessPath)) { + contextResolver.open(ureq, getWindowControl(), businessPath); + } + } + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(source == tableCtr) { + if (event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) { + TableEvent te = (TableEvent) event; + String actionid = te.getActionId(); + int rowid = te.getRowId(); + DBMail mail = (DBMail)tableCtr.getTableDataModel().getObject(rowid); + if(CMD_READ.equals(actionid)) { + if(outbox && StringHelper.containsNonWhitespace(mail.getMetaId()) && !mail.getMetaId().equals(metaId)) { + selectMetaMail(ureq, mail.getMetaId()); + } else { + selectMail(ureq, mail.getKey()); + } + } else if (CMD_PROFILE.equals(actionid)) { + DBMailRecipient from = mail.getFrom(); + if(from != null&& from.getRecipient() != null) { + contextResolver.open(ureq, getWindowControl(), "[Identity:" + from.getRecipient().getKey() + "]"); + } + } else if (CMD_MARK_TOGGLE.equals(actionid)) { + mail = mailManager.toggleMarked(mail, getIdentity()); + replaceInModel(mail); + } else if (CMD_READ_TOGGLE.equals(actionid)) { + mail = mailManager.toggleRead(mail, getIdentity()); + replaceInModel(mail); + } + } else if (event.getCommand().equals(Table.COMMAND_MULTISELECT)) { + // Multiselect events + TableMultiSelectEvent tmse = (TableMultiSelectEvent) event; + BitSet selectedMails = tmse.getSelection(); + if(selectedMails.isEmpty()){ + tableVC.setDirty(true); + showWarning("mail.action.emtpy"); + return; + } + String actionid = tmse.getAction(); + if (CMD_DELETE.equals(actionid)) { + String title = translate("mail.confirm.delete.title"); + int selected = selectedMails.cardinality(); + String text; + if (selected == 1) { + text = translate("mail.confirm.delete.single.text"); + } else { + text = translate("mail.confirm.delete.multi.text", selected + ""); + } + deleteConfirmationBox = activateYesNoDialog(ureq, title, text, deleteConfirmationBox); + deleteConfirmationBox.setUserObject(selectedMails); + } else if (CMD_SEND_REAL_MAIL.equals(actionid)) { + for (int i=selectedMails.nextSetBit(0); i >= 0; i=selectedMails.nextSetBit(i+1)) { + DBMail mail = (DBMail) tableCtr.getTableDataModel().getObject(i); + MailerResult result = forwardToMyRealMail(mail); + if(result.getReturnCode() != MailerResult.OK) { + MailHelper.printErrorsAndWarnings(result, getWindowControl(), getLocale()); + } else { + this.showInfo("mail.action.send.real.success", mail.getSubject()); + } + } + reloadModel(); + } else if (CMD_MARK_MARKED.equals(actionid) || CMD_MARK_UNMARKED.equals(actionid)) { + for (int i=selectedMails.nextSetBit(0); i >= 0; i=selectedMails.nextSetBit(i+1)) { + DBMailImpl mail = (DBMailImpl) tableCtr.getTableDataModel().getObject(i); + mailManager.setMarked(mail, CMD_MARK_MARKED.equals(actionid), getIdentity()); + } + reloadModel(); + } else if (CMD_MARK_READ.equals(actionid) || CMD_MARK_UNREAD.equals(actionid)) { + for (int i=selectedMails.nextSetBit(0); i >= 0; i=selectedMails.nextSetBit(i+1)) { + DBMailImpl mail = (DBMailImpl) tableCtr.getTableDataModel().getObject(i); + mailManager.setRead(mail, CMD_MARK_READ.equals(actionid), getIdentity()); + } + reloadModel(); + } + + } else if (TableController.EVENT_FILTER_SELECTED == event) { + MailDataModel dataModel = (MailDataModel)tableCtr.getTableDataModel(); + MailContextShortName filter = (MailContextShortName)tableCtr.getActiveFilter(); + dataModel.filter(filter); + } else if (TableController.EVENT_NOFILTER_SELECTED == event) { + MailDataModel dataModel = (MailDataModel)tableCtr.getTableDataModel(); + dataModel.filter(null); + } + + } else if (source == mailCtr) { + backFromMail(); + + } else if (source == metaMailCtr) { + removeAsListenerAndDispose(metaMailCtr); + metaMailCtr = null; + mainVC.put(MAIN_CMP, tableVC); + + } else if (source == deleteConfirmationBox) { + if(DialogBoxUIFactory.isYesEvent(event)) { + BitSet deleteMails = (BitSet)deleteConfirmationBox.getUserObject(); + for (int i=deleteMails.nextSetBit(0); i >= 0; i=deleteMails.nextSetBit(i+1)) { + DBMailImpl mail = (DBMailImpl) tableCtr.getTableDataModel().getObject(i); + boolean deleteMetaMail = outbox && !StringHelper.containsNonWhitespace(metaId); + mailManager.delete(mail, getIdentity(), deleteMetaMail); + // Do not remove from model to prevent concurrent modification + // exception, instead just reload model afterwards + } + reloadModel(); + } + } else { + super.event(ureq, source, event); + } + } + + @Override + protected void doDispose() { + // + } + + @Override + public void activate(UserRequest ureq, String viewIdentifier) { + if(!StringHelper.containsNonWhitespace(viewIdentifier) || "0".equals(viewIdentifier)) return; + + try { + Long mailKey = Long.parseLong(viewIdentifier); + selectMail(ureq, mailKey); + } catch(NumberFormatException e) { + //not a key + logWarn("Cannot activate with this identifier: " + viewIdentifier, e); + } + } + + + + @Override + public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) { + if(entries == null || entries.isEmpty()) return; + + ContextEntry entry = entries.get(0); + String type = entry.getOLATResourceable().getResourceableTypeName(); + if(DBMail.class.getSimpleName().equals(type)) { + selectMail(ureq, entry.getOLATResourceable().getResourceableId()); + } + } + + private void backFromMail() { + removeAsListenerAndDispose(mailCtr); + mailCtr = null; + mainVC.put(MAIN_CMP, tableVC); + } + + private MailerResult forwardToMyRealMail(DBMail mail) { + return mailManager.forwardToRealInbox(getIdentity(), mail, null); + } + + private void selectMetaMail(UserRequest ureq, String metaID) { + metaMailCtr = new MailListController(ureq, getWindowControl(), metaID, outbox, contextResolver); + listenTo(metaMailCtr); + mainVC.put(MAIN_CMP, metaMailCtr.getInitialComponent()); + } + + private void selectMail(UserRequest ureq, Long mailKey) { + DBMail mail = mailManager.getMessageByKey(mailKey); + selectMail(ureq, mail); + } + + private void selectMail(UserRequest ureq, DBMail mail) { + removeAsListenerAndDispose(mailCtr); + boolean back = !StringHelper.containsNonWhitespace(mail.getMetaId()) || !outbox; + OLATResourceable ores = OresHelper.createOLATResourceableInstance(DBMail.class, mail.getKey()); + WindowControl bwControl = addToHistory(ureq, ores, null); + mailCtr = new MailController(ureq, bwControl, mail, back); + listenTo(mailCtr); + mainVC.put(MAIN_CMP, mailCtr.getInitialComponent()); + + if(mailManager.setRead(mail, Boolean.TRUE, getIdentity())) { + reloadModel(); + } + } +} diff --git a/src/main/java/org/olat/core/util/mail/ui/MailTreeNode.java b/src/main/java/org/olat/core/util/mail/ui/MailTreeNode.java new file mode 100644 index 0000000000000000000000000000000000000000..e86022c23d52057990258e03fcc95d5106d332a7 --- /dev/null +++ b/src/main/java/org/olat/core/util/mail/ui/MailTreeNode.java @@ -0,0 +1,57 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ +package org.olat.core.util.mail.ui; + +import org.olat.core.gui.components.tree.GenericTreeNode; +import org.olat.core.id.Identity; +import org.olat.core.util.mail.manager.MailManager; + +/** + * + * Description:<br> + * overwrites <code>getIconDecorator1CssClass()</code> to display a special icon + * if the user has unread mails in his inbox. + * + * <P> + * Initial Date: 24 mars 2011 <br> + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * @author strentini, sergio.trentini@frentix.com + * + */ +public class MailTreeNode extends GenericTreeNode { + + private static final long serialVersionUID = -2579792704194953641L; + + private final Identity identity; + + public MailTreeNode(Identity identity) { + this.identity = identity; + } + + + @Override + public String getIconDecorator1CssClass() { + if(MailManager.getInstance().hasNewMail(identity)) { + return "b_mail_new"; + } + return null; + } +} diff --git a/src/main/java/org/olat/core/util/notifications/ContextualSubscriptionController.java b/src/main/java/org/olat/core/util/notifications/ContextualSubscriptionController.java index 0d16e43596d071d10db68f4a2e2b4066fd4dc98c..30e3d076ec2dcc800e67fc6dcbc9d0bb3f2e3ac2 100644 --- a/src/main/java/org/olat/core/util/notifications/ContextualSubscriptionController.java +++ b/src/main/java/org/olat/core/util/notifications/ContextualSubscriptionController.java @@ -61,7 +61,7 @@ public class ContextualSubscriptionController extends BasicController { myContent = createVelocityContainer("consubs"); if (subscriptionContext == null) { - setInitialComponent(new Panel("empty:nosubscription")); + putInitialPanel(new Panel("empty:nosubscription")); return; } diff --git a/src/main/java/org/olat/core/util/notifications/NotificationsManager.java b/src/main/java/org/olat/core/util/notifications/NotificationsManager.java index 377a7b624aab911b66bb451b659683ce4937b57d..3cac0e943e41bcfa939217631864a967eebbd094 100644 --- a/src/main/java/org/olat/core/util/notifications/NotificationsManager.java +++ b/src/main/java/org/olat/core/util/notifications/NotificationsManager.java @@ -232,6 +232,16 @@ public abstract class NotificationsManager extends BasicManager { */ public abstract SubscriptionItem createSubscriptionItem(Subscriber subscriber, Locale locale, String mimeTypeTitle, String mimeTypeContent, Date lowerDateBoundary); + /** + * Create a subscription item from info without reloading all the subscription + * @param subsInfo + * @param subscriber + * @param locale + * @param mimeTypeTitle + * @param mimeTypeContent + * @return + */ + public abstract SubscriptionItem createSubscriptionItem(SubscriptionInfo subsInfo, Subscriber subscriber, Locale locale, String mimeTypeTitle, String mimeTypeContent); public abstract SubscriptionInfo getNoSubscriptionInfo(); diff --git a/src/main/java/org/olat/core/util/notifications/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/util/notifications/_i18n/LocalStrings_de.properties index 6fdf1b082980c51633a2fa48734012db0f7eccbb..1a1ee8c89155d9ef3fd00c736b82cf87974f5495 100644 --- a/src/main/java/org/olat/core/util/notifications/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/core/util/notifications/_i18n/LocalStrings_de.properties @@ -1,7 +1,7 @@ #Mon Mar 02 09:54:04 CET 2009 actions.title=\u00C4nderungen chelp.del=<i>$org.olat.notifications\:subs.deleted</i> -chelp.home=<i>$org.olat.home\:menu.root</i> +chelp.home=<i>$org.olat.home\:main.menu.title.title</i> chelp.home-notifications.title=Abonnements und Benachrichtigungen chelp.notif=<i>$org.olat.home\:menu.notifications</i> chelp.notif1=OLAT bietet Ihnen die M\u00F6glichkeit, \u00FCber \u00C4nderungen in abonnierbaren Objekten informiert zu werden. diff --git a/src/main/java/org/olat/core/util/notifications/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/util/notifications/_i18n/LocalStrings_en.properties index 07a434df2460b21ce72995ba3d2bfed8388392df..0395615b8003418101b7187982bdcebbdf7f661b 100644 --- a/src/main/java/org/olat/core/util/notifications/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/core/util/notifications/_i18n/LocalStrings_en.properties @@ -1,7 +1,7 @@ #Fri Jan 21 10:25:59 CET 2011 actions.title=Modifications chelp.del=<i>$org.olat.notifications\:subs.deleted</i> -chelp.home=<i>$org.olat.home\:menu.root</i> +chelp.home=<i>$org.olat.home\:main.menu.title.title</i> chelp.home-notifications.title=Subscriptions and notifications chelp.notif=<i>$org.olat.home\:menu.notifications</i> chelp.notif1=OLAT can assist you in getting information on modifications regarding subscribed objects. diff --git a/src/main/java/org/olat/core/util/notifications/items/SubscriptionListItem.java b/src/main/java/org/olat/core/util/notifications/items/SubscriptionListItem.java index 013c8afa106ccefcd23e5b9978246f95a332789f..e73df7e863395726b780c88c91dfefa93628128f 100644 --- a/src/main/java/org/olat/core/util/notifications/items/SubscriptionListItem.java +++ b/src/main/java/org/olat/core/util/notifications/items/SubscriptionListItem.java @@ -68,15 +68,15 @@ public class SubscriptionListItem { public String getDescription() { return description; } - - public String getIconCssClass() { - return iconCssClass; - } public String getDescriptionTooltip() { return descriptionTooltip; } + public String getIconCssClass() { + return iconCssClass; + } + /** * compose list item representation depending on mimeType * @param mimeType @@ -121,7 +121,9 @@ public class SubscriptionListItem { sb.append(link); sb.append("\">"); } - sb.append(description.trim()); + if (StringHelper.containsNonWhitespace(description)) { + sb.append(description.trim()); + } if (StringHelper.containsNonWhitespace(link)) sb.append("</a>"); sb.append(" ").append(datePart.trim()); sb.append("</li>"); diff --git a/src/main/java/org/olat/course/nodes/en/EnrollmentManager.java b/src/main/java/org/olat/course/nodes/en/EnrollmentManager.java index 245552a20a056d0a29b648dd60d419f866d9b0c0..2b9e4b5a4deb580debe7a8f7519b6809c143595a 100644 --- a/src/main/java/org/olat/course/nodes/en/EnrollmentManager.java +++ b/src/main/java/org/olat/course/nodes/en/EnrollmentManager.java @@ -36,6 +36,8 @@ import org.olat.core.logging.Tracing; import org.olat.core.manager.BasicManager; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.SyncerExecutor; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerResult; @@ -166,7 +168,9 @@ public class EnrollmentManager extends BasicManager { // 3. Send notification mail MailTemplate mailTemplate = BGMailHelper.createRemoveMyselfMailTemplate(enrolledGroup, identity); MailerWithTemplate mailer = MailerWithTemplate.getInstance(); - MailerResult mailerResult = mailer.sendMail(identity, null, null, mailTemplate, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(wControl.getBusinessControl().getAsString()); + MailerResult mailerResult = mailer.sendMail(context, identity, null, null, mailTemplate, null); MailHelper.printErrorsAndWarnings(mailerResult, wControl, trans.getLocale()); } @@ -189,7 +193,9 @@ public class EnrollmentManager extends BasicManager { // 3. Send notification mail MailTemplate mailTemplate = BGMailHelper.createRemoveWaitinglistMailTemplate(enrolledWaitingListGroup, identity); MailerWithTemplate mailer = MailerWithTemplate.getInstance(); - MailerResult mailerResult = mailer.sendMail(identity, null, null, mailTemplate, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(wControl.getBusinessControl().getAsString()); + MailerResult mailerResult = mailer.sendMail(context, identity, null, null, mailTemplate, null); MailHelper.printErrorsAndWarnings(mailerResult, wControl, trans.getLocale()); } @@ -332,7 +338,9 @@ public class EnrollmentManager extends BasicManager { // 4. Send notification mail MailTemplate mailTemplate = BGMailHelper.createAddMyselfMailTemplate(group, identity); MailerWithTemplate mailer = MailerWithTemplate.getInstance(); - MailerResult mailerResult = mailer.sendMail(identity, null, null, mailTemplate, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(wControl.getBusinessControl().getAsString()); + MailerResult mailerResult = mailer.sendMail(context, identity, null, null, mailTemplate, null); MailHelper.printErrorsAndWarnings(mailerResult, wControl, trans.getLocale()); @@ -368,7 +376,9 @@ public class EnrollmentManager extends BasicManager { // 4. Send notification mail MailTemplate mailTemplate = BGMailHelper.createAddWaitinglistMailTemplate(group, identity); MailerWithTemplate mailer = MailerWithTemplate.getInstance(); - MailerResult mailerResult = mailer.sendMail(identity, null, null, mailTemplate, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(wControl.getBusinessControl().getAsString()); + MailerResult mailerResult = mailer.sendMail(context, identity, null, null, mailTemplate, null); MailHelper.printErrorsAndWarnings(mailerResult, wControl, trans.getLocale()); return true; diff --git a/src/main/java/org/olat/course/nodes/info/SendMailFormatterForCourse.java b/src/main/java/org/olat/course/nodes/info/SendMailFormatterForCourse.java index 537dc8c7dc5951de476d3ce815e08fcf90622645..9937865906fc79b5ff8774ec67b0ef2e14f9fd55 100644 --- a/src/main/java/org/olat/course/nodes/info/SendMailFormatterForCourse.java +++ b/src/main/java/org/olat/course/nodes/info/SendMailFormatterForCourse.java @@ -54,6 +54,12 @@ public class SendMailFormatterForCourse implements MailFormatter { this.translator = translator; this.businessPath = businessPath; } + + @Override + //fxdiff VCRP-16: intern mail system + public String getBusinessPath() { + return businessPath; + } @Override public String getSubject(InfoMessage msg) { diff --git a/src/main/java/org/olat/course/nodes/info/_chelp/ced-info-config.html b/src/main/java/org/olat/course/nodes/info/_chelp/ced-info-config.html index a7ccf06a05a12bff4cd0e397e5a23b296e9df7dc..e591d81326cf92c3b4cf3b7fce2f42186b7c271e 100644 --- a/src/main/java/org/olat/course/nodes/info/_chelp/ced-info-config.html +++ b/src/main/java/org/olat/course/nodes/info/_chelp/ced-info-config.html @@ -1,4 +1,4 @@ -<br/>$r.translate("chelp.ced-info-config1") +<br/>$r.translate("chelp.ced-info-config1") $r.translate("chelp.ced-info-config2") <br/><br/> <b>$r.translate("chelp.ced-info-config2.label"):</b> $r.translate("chelp.ced-info-config2")<br/> <b>$r.translate("chelp.ced-info-config3.label"):</b> $r.translate("chelp.ced-info-config3") \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/iq/IQEditReplaceWizard.java b/src/main/java/org/olat/course/nodes/iq/IQEditReplaceWizard.java index 355359c66b32c75d5b2ea35b31c8d002c5706080..4d3b6bf4494307fadc9d820d874def90302f850f 100644 --- a/src/main/java/org/olat/course/nodes/iq/IQEditReplaceWizard.java +++ b/src/main/java/org/olat/course/nodes/iq/IQEditReplaceWizard.java @@ -32,6 +32,8 @@ import org.olat.core.gui.control.generic.wizard.WizardController; import org.olat.core.helpers.Settings; import org.olat.core.id.Identity; import org.olat.core.logging.OLATRuntimeException; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailNotificationEditController; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerWithTemplate; @@ -136,7 +138,9 @@ public class IQEditReplaceWizard extends WizardController { recipientsCC = new ArrayList<Identity>(); recipientsCC.add(ureq.getIdentity()); } - MailerWithTemplate.getInstance().sendMailAsSeparateMails(learners, recipientsCC, null, mailCtr.getMailTemplate(), ureq.getIdentity()); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString()); + MailerWithTemplate.getInstance().sendMailAsSeparateMails(context, learners, recipientsCC, null, mailCtr.getMailTemplate(), ureq.getIdentity()); } fireEvent(ureq, Event.DONE_EVENT); } else if (source == searchCtr && event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) { diff --git a/src/main/java/org/olat/course/nodes/projectbroker/ProjectGroupController.java b/src/main/java/org/olat/course/nodes/projectbroker/ProjectGroupController.java index ed3d8e662182945f57223a10325519812fb43e38..6035a1949bdb07cf97b67625d4fe94e4f165521d 100644 --- a/src/main/java/org/olat/course/nodes/projectbroker/ProjectGroupController.java +++ b/src/main/java/org/olat/course/nodes/projectbroker/ProjectGroupController.java @@ -38,6 +38,8 @@ import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.id.Identity; import org.olat.core.logging.activity.ActionType; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerResult; @@ -159,7 +161,9 @@ public class ProjectGroupController extends BasicController { } else { ccIdentities = null; } - MailerResult mailerResult = mailer.sendMailAsSeparateMails(identitiesMoveEvent.getMovedIdentities(), ccIdentities, null, mailTemplate, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString()); + MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, identitiesMoveEvent.getMovedIdentities(), ccIdentities, null, mailTemplate, null); MailHelper.printErrorsAndWarnings(mailerResult, getWindowControl(), urequest.getLocale()); } fireEvent(urequest, Event.CHANGED_EVENT ); diff --git a/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectBrokerMailerImpl.java b/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectBrokerMailerImpl.java index 5f4e0510c5da51ddf67ed7713af564dcac48b19a..dd45fb0c348934d034336a44dbea2697fd3341bf 100644 --- a/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectBrokerMailerImpl.java +++ b/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectBrokerMailerImpl.java @@ -35,6 +35,8 @@ import org.olat.core.id.UserConstants; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.Formatter; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerResult; import org.olat.core.util.mail.MailerWithTemplate; @@ -176,7 +178,9 @@ public class ProjectBrokerMailerImpl implements ProjectBrokerMailer { // als Workaround wurde die Methode sendMailAsSeparateMails verwendet List<Identity> enrolledIdentityList = new ArrayList<Identity>(); enrolledIdentityList.add(enrolledIdentity); - MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(enrolledIdentityList, null, null, enrolledMailTemplate, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(project.getProjectBroker(), null, null); + MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(context, enrolledIdentityList, null, null, enrolledMailTemplate, null); log.audit("ProjectBroker: sendEmail to identity.name=" + enrolledIdentity.getName() + " , mailerResult.returnCode=" + mailerResult.getReturnCode()); return mailerResult; } @@ -190,7 +194,9 @@ public class ProjectBrokerMailerImpl implements ProjectBrokerMailer { if (identityNames.length()>0) identityNames.append(","); identityNames.append(identity.getName()); } - MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(projectManagerList, null, null, enrolledMailTemplate, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(project.getProjectBroker(), null, null); + MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(context, projectManagerList, null, null, enrolledMailTemplate, null); log.audit("ProjectBroker: sendEmailToGroup: identities=" + identityNames.toString() + " , mailerResult.returnCode=" + mailerResult.getReturnCode()); return mailerResult; } @@ -204,7 +210,9 @@ public class ProjectBrokerMailerImpl implements ProjectBrokerMailer { if (identityNames.length()>0) identityNames.append(","); identityNames.append(identity.getName()); } - MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(projectManagerList, null, null, enrolledMailTemplate, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(project.getProjectBroker(), null, null); + MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(context, projectManagerList, null, null, enrolledMailTemplate, null); log.audit("ProjectBroker: sendEmailToGroup: identities=" + identityNames.toString() + " , mailerResult.returnCode=" + mailerResult.getReturnCode()); return mailerResult; } diff --git a/src/main/java/org/olat/course/nodes/ta/DropboxController.java b/src/main/java/org/olat/course/nodes/ta/DropboxController.java index 36deb9ab4909dab75757009740fd3bb246d5872e..bc358ed2d00dac916573a77c19cc907b956d353b 100644 --- a/src/main/java/org/olat/course/nodes/ta/DropboxController.java +++ b/src/main/java/org/olat/course/nodes/ta/DropboxController.java @@ -54,6 +54,8 @@ import org.olat.core.id.Identity; import org.olat.core.id.UserConstants; import org.olat.core.util.FileUtils; import org.olat.core.util.Formatter; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerResult; @@ -275,7 +277,9 @@ public class DropboxController extends BasicController { } }; - MailerResult result = MailerWithTemplate.getInstance().sendMail(ureq.getIdentity(), null, null, mailTempl, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString()); + MailerResult result = MailerWithTemplate.getInstance().sendMail(context, ureq.getIdentity(), null, null, mailTempl, null); if(result.getFailedIdentites().size() > 0) { List<Identity> disabledIdentities = new ArrayList<Identity>(); disabledIdentities = result.getFailedIdentites(); diff --git a/src/main/java/org/olat/course/nodes/ta/DropboxScoringViewController.java b/src/main/java/org/olat/course/nodes/ta/DropboxScoringViewController.java index 836eb90de27a03a0909d8916cafcb89dce0ac3ad..f2654e1e2465d4fcb6dc064244c41837811e8ccc 100644 --- a/src/main/java/org/olat/course/nodes/ta/DropboxScoringViewController.java +++ b/src/main/java/org/olat/course/nodes/ta/DropboxScoringViewController.java @@ -54,6 +54,8 @@ import org.olat.core.id.UserConstants; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.i18n.I18nManager; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerResult; import org.olat.core.util.mail.MailerWithTemplate; @@ -284,8 +286,9 @@ public class DropboxScoringViewController extends BasicController { // nothing to do } }; - - MailerResult result = MailerWithTemplate.getInstance().sendMail(student, null, null, mailTempl, null); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString()); + MailerResult result = MailerWithTemplate.getInstance().sendMail(context, student, null, null, mailTempl, null); if(result.getReturnCode() > 0) { am.appendToUserNodeLog(node, coach, student, "MAIL SEND FAILED TO:" + toMail + "; MailReturnCode: " + result.getReturnCode()); diff --git a/src/main/java/org/olat/course/nodes/ta/TACourseNodeEditController.java b/src/main/java/org/olat/course/nodes/ta/TACourseNodeEditController.java index 90aa425880e621a6e9bfa5577bb7c5630ca92395..12aa166a88f79eaa7b2847489d3fcd86f8a6372a 100644 --- a/src/main/java/org/olat/course/nodes/ta/TACourseNodeEditController.java +++ b/src/main/java/org/olat/course/nodes/ta/TACourseNodeEditController.java @@ -54,6 +54,8 @@ import org.olat.core.id.UserConstants; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.Util; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailNotificationEditController; import org.olat.core.util.mail.MailTemplate; @@ -533,7 +535,9 @@ public class TACourseNodeEditController extends ActivateableTabbableDefaultContr } else { ccIdentities = null; } - MailerResult mailerResult = mailer.sendMailAsSeparateMails(recipients, ccIdentities, null, mailTemplate, sender); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString()); + MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, recipients, ccIdentities, null, mailTemplate, sender); MailHelper.printErrorsAndWarnings(mailerResult, getWindowControl(), ureq.getLocale()); } } diff --git a/src/main/java/org/olat/group/BusinessGroupManagerImpl.java b/src/main/java/org/olat/group/BusinessGroupManagerImpl.java index fc1263092060f81b020f286a0badd0c649662ea3..49e8e8f40507cceaa82dd10321873ea88555f684 100644 --- a/src/main/java/org/olat/group/BusinessGroupManagerImpl.java +++ b/src/main/java/org/olat/group/BusinessGroupManagerImpl.java @@ -68,6 +68,8 @@ import org.olat.core.util.StringHelper; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.SyncerCallback; import org.olat.core.util.coordinate.SyncerExecutor; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerResult; @@ -630,9 +632,9 @@ public class BusinessGroupManagerImpl extends BasicManager implements BusinessGr MailTemplate mailTemplate = BGMailHelper.createDeleteGroupMailTemplate(businessGroupTodelete, ureq.getIdentity()); if (mailTemplate != null) { //fxdiff VCRP-16: intern mail system - //TODO SR MailContext context = new MailContextImpl(wControl.getBusinessControl().getAsString()); - //TODO SR MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, users, null, null, mailTemplate, null); - //TODO SR MailHelper.printErrorsAndWarnings(mailerResult, wControl, ureq.getLocale()); + MailContext context = new MailContextImpl(wControl.getBusinessControl().getAsString()); + MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, users, null, null, mailTemplate, null); + MailHelper.printErrorsAndWarnings(mailerResult, wControl, ureq.getLocale()); } } @@ -1643,8 +1645,8 @@ public class BusinessGroupManagerImpl extends BasicManager implements BusinessGr if (mailTemplate != null) { MailerWithTemplate mailer = MailerWithTemplate.getInstance(); //fxdiff VCRP-16: intern mail system - //TODO SR MailContext context = new MailContextImpl("[BusinessGroup:" + group.getKey() + "]"); - //TODO SR MailerResult mailerResult = mailer.sendMail(context, firstWaitingListIdentity, null, null, mailTemplate, null); + MailContext context = new MailContextImpl("[BusinessGroup:" + group.getKey() + "]"); + MailerResult mailerResult = mailer.sendMail(context, firstWaitingListIdentity, null, null, mailTemplate, null); // Does not report errors to current screen because this is the identity who triggered the transfer Tracing.logWarn("Could not send WaitinglistTransferMail for identity=" + firstWaitingListIdentity.getName() , BusinessGroupManagerImpl.class); } diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java index 6568683f765028ef6e5f0e8b3ebd0e43bce84009..edd4282d3c953668ebcf4ad3d886d8f37dc9c353 100644 --- a/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java +++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupEditController.java @@ -64,6 +64,8 @@ import org.olat.core.util.Util; import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.LockResult; import org.olat.core.util.event.GenericEventListener; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailTemplate; import org.olat.core.util.mail.MailerResult; @@ -363,9 +365,9 @@ public class BusinessGroupEditController extends BasicController implements Cont MailTemplate mailTemplate = identitiesMoveEvent.getMailTemplate(); if (mailTemplate != null) { //fxdiff VCRP-16: intern mail system - //TODO SR MailContext context = new MailContextImpl(currBusinessGroup, null, getWindowControl().getBusinessControl().getAsString()); - //TODO SR MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, identitiesMoveEvent.getMovedIdentities(), null, null, mailTemplate, null); - //TODO SR MailHelper.printErrorsAndWarnings(mailerResult, getWindowControl(), ureq.getLocale()); + MailContext context = new MailContextImpl(currBusinessGroup, null, getWindowControl().getBusinessControl().getAsString()); + MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, identitiesMoveEvent.getMovedIdentities(), null, null, mailTemplate, null); + MailHelper.printErrorsAndWarnings(mailerResult, getWindowControl(), ureq.getLocale()); } fireEvent(ureq, Event.CHANGED_EVENT ); } diff --git a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties index b23ad9d239613cbf5e9d727f812534691b56d509..c5cb3e907a4c023c88704f3bc3c7149da1fde73a 100644 --- a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties @@ -1,4 +1,4 @@ -#Sat Jan 22 16:31:11 CET 2011 +#Mon May 16 17:34:39 CEST 2011 areachoice.no.areas.admin=No learning areas found. Please create a learning area within your group management. areachoice.no.areas.owner=No learning areas found. New learning areas can only be created by users who have access to the entire group management. chelp.area1=Provided that learning groups have already been created in the course, these will appear in the tab. @@ -98,6 +98,7 @@ chelp.tools.right6=All members of a $org.olat.group.ui\:RightGroup have the righ chelp.tools.right8=You can put a calendar at the disposal of your $org.olat.group.ui\:RightGroup to record joint events. Furthermore you can determine the calendar's write access, that is, who will have the right to record data. chelp.tools.right9=You can put a Wiki at the disposal of your $org.olat.group.ui\:RightGroup chelp.tools.title=Configuration of collaborative tools +chkBox.open=Publish group in group area for booking chkBox.show.owners=Members can see owners chkBox.show.partips=Members can see participants chkBox.show.waitingList=Members can see waiting list @@ -108,8 +109,10 @@ fieldset.legend.details=Details fieldset.legend.displaymembers=Display members fieldset.legend.groupowners=Owners fieldset.legend.grouppartips=Participants +fieldset.legend.open=Visibility fieldset.legend.rights=Assigned rights fieldset.legend.waitinggroup=Waiting list +group.edit.tab.accesscontrol=Publishing and booking configuration group.edit.tab.areas=Learning areas group.edit.tab.collabtools=Tools group.edit.tab.details=Description diff --git a/src/main/java/org/olat/home/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/home/_i18n/LocalStrings_de.properties index 00e6be2d6f10b5997882822cdf6adb660c6a5496..a16ad6b34900a0cffccde30beb2fd50a08326c66 100644 --- a/src/main/java/org/olat/home/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/home/_i18n/LocalStrings_de.properties @@ -46,12 +46,16 @@ menu.guestinfo=Informationen menu.guestinfo.alt=Informationen \u00FCber die OLAT-Bedienung menu.guestwelcome=Willkommen menu.guestwelcome.alt=Willkommen bei OLAT +menu.mail=E-Mails +menu.mail.alt=Mailbereich menu.mysettings=Einstellungen menu.mysettings.alt=Meine OLAT-Einstellungen menu.note=Notizen menu.note.alt=Meine Notizen menu.notifications=Abonnements menu.notifications.alt=Meine Abonnements f\u00FCr Benachrichtigungen verwalten +menu.orders=Buchungen +menu.orders.alt=Meine Buchungen menu.otherusers=Andere Benutzer menu.otherusers.alt=Visitenkarte anderer Benutzer menu.portfolio=ePortfolio diff --git a/src/main/java/org/olat/home/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/home/_i18n/LocalStrings_en.properties index bb6c7300888bbd97e6c6183a1f9ecf3ca8105b6f..049e792ff6640f18c07fb0342474fab8f15674da 100644 --- a/src/main/java/org/olat/home/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/home/_i18n/LocalStrings_en.properties @@ -46,12 +46,16 @@ menu.guestinfo=Information menu.guestinfo.alt=Information on how to use OLAT menu.guestwelcome=Welcome menu.guestwelcome.alt=Welcome to OLAT +menu.mail=E-mails +menu.mail.alt=Mail area menu.mysettings=Settings menu.mysettings.alt=My personal OLAT settings menu.note=Notes menu.note.alt=My notes menu.notifications=Subscriptions menu.notifications.alt=Administer my notifications and subsriptions +menu.orders=Bookings +menu.orders.alt=My bookings menu.otherusers=Other users menu.otherusers.alt=Visiting card of other users menu.portfolio=ePortfolio diff --git a/src/main/java/org/olat/modules/co/ContactForm.java b/src/main/java/org/olat/modules/co/ContactForm.java index 24c7a1bafbe8ad8258e46e792f7666f2e7e4fa66..6c58ac5715033a2891a0b0aca1025c0574adac8a 100644 --- a/src/main/java/org/olat/modules/co/ContactForm.java +++ b/src/main/java/org/olat/modules/co/ContactForm.java @@ -196,9 +196,8 @@ class ContactForm extends FormBasicController { /** * @return */ - protected String getEmailFrom() { - String ccMail = emailFrom.getUser().getProperty(UserConstants.EMAIL, null); - return ccMail; + protected Identity getEmailFrom() { + return emailFrom; } /** diff --git a/src/main/java/org/olat/modules/co/ContactFormController.java b/src/main/java/org/olat/modules/co/ContactFormController.java index 7f3f57a7ee53a488166963d43753b645951f0af8..8ab7b4aa9673688a672148b8c92b8b9de6533ce1 100644 --- a/src/main/java/org/olat/modules/co/ContactFormController.java +++ b/src/main/java/org/olat/modules/co/ContactFormController.java @@ -52,6 +52,8 @@ import org.olat.core.util.WebappHelper; import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.ContactMessage; import org.olat.core.util.mail.Emailer; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailLoggingAction; @@ -207,10 +209,12 @@ public class ContactFormController extends BasicController { // boolean success = false; try { - List<File> attachments = cntctForm.getAttachments(); - success = emailer.sendEmail(cntctForm.getEmailToContactLists(), cntctForm.getSubject(), cntctForm.getBody(), attachments); + List<File> attachments = cntctForm.getAttachments(); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString()); + success = emailer.sendEmail(context, cntctForm.getEmailToContactLists(), cntctForm.getSubject(), cntctForm.getBody(), attachments); if(cntctForm.isTcpFrom()) { - success = emailer.sendEmailCC(cntctForm.getEmailFrom(), cntctForm.getSubject(), cntctForm.getBody(), attachments); + success = emailer.sendEmailCC(context, cntctForm.getEmailFrom(), cntctForm.getSubject(), cntctForm.getBody(), attachments); } } catch (AddressException e) { //error in recipient email address(es) diff --git a/src/main/java/org/olat/notifications/NotificationNewsController.java b/src/main/java/org/olat/notifications/NotificationNewsController.java index 2374f5a8ae76541ffbe04060af1cd39e779beb22..758d548d6f258256828a399eb2183f2079dc4675 100644 --- a/src/main/java/org/olat/notifications/NotificationNewsController.java +++ b/src/main/java/org/olat/notifications/NotificationNewsController.java @@ -25,7 +25,6 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; @@ -119,7 +118,7 @@ class NotificationNewsController extends BasicController implements Activateable newsVC.contextPut("subs", subs); subsInfoMap = NotificationHelper.getSubscriptionMap(getLocale(), true, compareDate, subs); - NotificationSubscriptionAndNewsFormatter subsFormatter = new NotificationSubscriptionAndNewsFormatter(compareDate, getTranslator(), subsInfoMap); + NotificationSubscriptionAndNewsFormatter subsFormatter = new NotificationSubscriptionAndNewsFormatter(getTranslator(), subsInfoMap); newsVC.contextPut("subsFormatter", subsFormatter); return subs; } diff --git a/src/main/java/org/olat/notifications/NotificationSubscriptionAndNewsFormatter.java b/src/main/java/org/olat/notifications/NotificationSubscriptionAndNewsFormatter.java index 4b9265f8465ebf889fca0561c2f25def8a932ef5..9dee854f08da52e714c1e220bde429cfe2934031 100644 --- a/src/main/java/org/olat/notifications/NotificationSubscriptionAndNewsFormatter.java +++ b/src/main/java/org/olat/notifications/NotificationSubscriptionAndNewsFormatter.java @@ -20,7 +20,6 @@ */ package org.olat.notifications; -import java.util.Date; import java.util.Map; import org.olat.ControllerFactory; @@ -41,12 +40,11 @@ import org.olat.core.util.notifications.SubscriptionItem; * @author gnaegi */ public class NotificationSubscriptionAndNewsFormatter { - private Date compareDate; + private Translator translator; private Map<Subscriber, SubscriptionInfo> subsInfoMap; - NotificationSubscriptionAndNewsFormatter(Date compareDate, Translator translator, Map<Subscriber, SubscriptionInfo> subsInfoMap) { - this.compareDate = compareDate; + NotificationSubscriptionAndNewsFormatter(Translator translator, Map<Subscriber, SubscriptionInfo> subsInfoMap) { this.translator = translator; this.subsInfoMap = subsInfoMap; } @@ -103,11 +101,9 @@ public class NotificationSubscriptionAndNewsFormatter { } public SubscriptionItem getSubscriptionItem(Subscriber sub) { + SubscriptionInfo subsInfo = subsInfoMap.get(sub); NotificationsManager notiMgr = NotificationsManager.getInstance(); - SubscriptionItem subscrItem = notiMgr.createSubscriptionItem(sub, translator.getLocale(), SubscriptionInfo.MIME_HTML, SubscriptionInfo.MIME_HTML, compareDate); + SubscriptionItem subscrItem = notiMgr.createSubscriptionItem(subsInfo, sub, translator.getLocale(), SubscriptionInfo.MIME_HTML, SubscriptionInfo.MIME_HTML); return subscrItem; } - - - -} +} \ No newline at end of file diff --git a/src/main/java/org/olat/notifications/NotificationsManagerImpl.java b/src/main/java/org/olat/notifications/NotificationsManagerImpl.java index 863e0831b37ddee065d50ef1466817fd91300861..7f85dad2f135cb55ca77726a9a5be4543567823e 100644 --- a/src/main/java/org/olat/notifications/NotificationsManagerImpl.java +++ b/src/main/java/org/olat/notifications/NotificationsManagerImpl.java @@ -484,13 +484,24 @@ public class NotificationsManagerImpl extends NotificationsManager implements Us // nothing to do } }; - - MailerResult result = MailerWithTemplate.getInstance().sendMail(to, null, null, mailTempl, null); - if (result.getReturnCode() > 0) { - log.warn("Could not send email to identity " + to.getName() + ". (returncode="+result.getReturnCode()+", to="+to+")"); + + MailerResult result = null; + try { + // fxdiff VCRP-16: intern mail system + result = MailerWithTemplate.getInstance().sendRealMail(to, mailTempl); + } catch (Exception e) { + // FXOLAT-294 :: sending the mail will throw nullpointer exception if To-Identity has no + // valid email-address!, catch it... + } + if (result == null || result.getReturnCode() > 0) { + if(result!=null) + log.warn("Could not send email to identity " + to.getName() + ". (returncode=" + result.getReturnCode() + ", to=" + to + ")"); + else + log.warn("Could not send email to identity " + to.getName() + ". (returncode = null) , to=" + to + ")"); return false; + } else { + return true; } - return true; } /** @@ -518,6 +529,12 @@ public class NotificationsManagerImpl extends NotificationsManager implements Us private Publisher findOrCreatePublisher(final SubscriptionContext scontext, final PublisherData pdata) { final OLATResourceable ores = OresHelper.createOLATResourceableInstance(scontext.getResName() + "_" + scontext.getSubidentifier(),scontext.getResId()); //o_clusterOK by:cg + //fxdiff VCRP-16:prevent nested doInSync + Publisher pub = getPublisher(scontext.getResName(), scontext.getResId(), scontext.getSubidentifier()); + if(pub != null) { + return pub; + } + Publisher publisher = CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(ores, new SyncerCallback<Publisher>(){ public Publisher execute() { Publisher p = getPublisher(scontext.getResName(), scontext.getResId(), scontext.getSubidentifier()); @@ -977,23 +994,13 @@ public class NotificationsManagerImpl extends NotificationsManager implements Us SubscriptionItem si = null; Publisher pub = subscriber.getPublisher(); NotificationsHandler notifHandler = getNotificationsHandler(pub); + if (isLogDebugEnabled()) logDebug("create subscription with handler: " + notifHandler.getClass().getName()); // do not create subscription item when deleted if (isPublisherValid(pub)) { if (isLogDebugEnabled()) logDebug("NotifHandler: " + notifHandler.getClass().getName() + " compareDate: " + latestEmailed.toString() + " now: " + new Date().toString(), null); SubscriptionInfo subsInfo = notifHandler.createSubscriptionInfo(subscriber, locale, latestEmailed); if (subsInfo.hasNews()) { - String title = getFormatedTitle(subsInfo, subscriber, locale, mimeTypeTitle); - - String itemLink = null; - if(subsInfo.getCustomUrl() != null) { - itemLink = subsInfo.getCustomUrl(); - } - if(itemLink == null && pub.getBusinessPath() != null) { - itemLink = NotificationHelper.getURLFromBusinessPathString(pub, pub.getBusinessPath()); - } - - String description = subsInfo.getSpecificInfo(mimeTypeContent, locale); - si = new SubscriptionItem(title, itemLink, description); + si = createSubscriptionItem(subsInfo, subscriber, locale, mimeTypeTitle, mimeTypeContent); } } return si; @@ -1003,6 +1010,23 @@ public class NotificationsManagerImpl extends NotificationsManager implements Us } } + @Override + public SubscriptionItem createSubscriptionItem(SubscriptionInfo subsInfo, Subscriber subscriber, Locale locale, String mimeTypeTitle, String mimeTypeContent) { + Publisher pub = subscriber.getPublisher(); + String title = getFormatedTitle(subsInfo, subscriber, locale, mimeTypeTitle); + + String itemLink = null; + if(subsInfo.getCustomUrl() != null) { + itemLink = subsInfo.getCustomUrl(); + } + if(itemLink == null && pub.getBusinessPath() != null) { + itemLink = NotificationHelper.getURLFromBusinessPathString(pub, pub.getBusinessPath()); + } + + String description = subsInfo.getSpecificInfo(mimeTypeContent, locale); + return new SubscriptionItem(title, itemLink, description); + } + /** * format the type-title and title-details * @param subscriber diff --git a/src/main/java/org/olat/notifications/NotificationsPortletRunController.java b/src/main/java/org/olat/notifications/NotificationsPortletRunController.java index 3640ff3a13a9bab9b25cba135266097087080e1f..31b76b6aeec61edbc25ac57681a01fa385fa9911 100644 --- a/src/main/java/org/olat/notifications/NotificationsPortletRunController.java +++ b/src/main/java/org/olat/notifications/NotificationsPortletRunController.java @@ -59,8 +59,6 @@ import org.olat.core.gui.translator.Translator; import org.olat.core.id.OLATResourceable; import org.olat.core.id.context.BusinessControl; import org.olat.core.id.context.BusinessControlFactory; -import org.olat.core.logging.OLog; -import org.olat.core.logging.Tracing; import org.olat.core.util.event.GenericEventListener; import org.olat.core.util.event.PersistsEvent; import org.olat.core.util.notifications.NotificationHelper; @@ -81,7 +79,6 @@ import org.olat.group.BusinessGroupManagerImpl; * @author gnaegi */ public class NotificationsPortletRunController extends AbstractPortletRunController implements GenericEventListener { - private OLog log = Tracing.createLoggerFor(NotificationsPortletRunController.class); private static final String CMD_LAUNCH = "cmd.launch"; @@ -178,32 +175,21 @@ public class NotificationsPortletRunController extends AbstractPortletRunControl */ protected void reloadModel(SortingCriteria sortingCriteria) { if (sortingCriteria.getSortingType() == SortingCriteria.AUTO_SORTING) { - notificationsList = man.getValidSubscribers(identity); - // calc subscriptioninfo for all subscriptions and, if only those with news are to be shown, remove the other ones - for (Iterator<Subscriber> it_subs = notificationsList.iterator(); it_subs.hasNext();) { - Subscriber subscriber = it_subs.next(); - Publisher pub = subscriber.getPublisher(); - try { - NotificationsHandler notifHandler = man.getNotificationsHandler(pub); - if(notifHandler == null) { - it_subs.remove(); - } else { - SubscriptionInfo subsInfo = notifHandler.createSubscriptionInfo(subscriber, locale, compareDate); - if (!subsInfo.hasNews()) { - it_subs.remove(); - } + Map<Subscriber,SubscriptionInfo> subscriptionMap = NotificationHelper.getSubscriptionMap(getIdentity(), getLocale(), true, compareDate); + + notificationsList = new ArrayList<Subscriber>(); + for (Iterator<Map.Entry<Subscriber, SubscriptionInfo>> it_subs = subscriptionMap.entrySet().iterator(); it_subs.hasNext();) { + Map.Entry<Subscriber, SubscriptionInfo> sInfo = it_subs.next(); + Subscriber subscrer = sInfo.getKey(); + SubscriptionInfo infos = sInfo.getValue(); + if(infos.hasNews()) { + notificationsList.add(subscrer); } - } catch(Exception e) { - log.error("Cannot load publisher:" + pub, e); } - } - - notificationsList = getSortedList(notificationsList, sortingCriteria ); - List<PortletEntry> entries = convertNotificationToPortletEntryList(notificationsList); - - Map subscriptionMap = NotificationHelper.getSubscriptionMap(getIdentity(), getLocale(), true, compareDate); - notificationListModel = new NotificationsPortletTableDataModel(entries, locale, subscriptionMap); - tableCtr.setTableDataModel(notificationListModel); + notificationsList = getSortedList(notificationsList, sortingCriteria ); + List<PortletEntry> entries = convertNotificationToPortletEntryList(notificationsList); + notificationListModel = new NotificationsPortletTableDataModel(entries, locale, subscriptionMap); + tableCtr.setTableDataModel(notificationListModel); } else { reloadModel(this.getPersistentManuallySortedItems()); } diff --git a/src/main/java/org/olat/portfolio/ui/structel/EPShareListController.java b/src/main/java/org/olat/portfolio/ui/structel/EPShareListController.java index 69324838cab129af3a5a73dd0876a8bfbf8723d1..3c477837bcd1ca79aefd517a2ca2535ec830dd82 100644 --- a/src/main/java/org/olat/portfolio/ui/structel/EPShareListController.java +++ b/src/main/java/org/olat/portfolio/ui/structel/EPShareListController.java @@ -66,6 +66,8 @@ import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.Emailer; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupManager; @@ -309,7 +311,9 @@ public class EPShareListController extends FormBasicController { String last = getIdentity().getUser().getProperty(UserConstants.LASTNAME, null); String sender = first + " " + last; String[] bodyArgs = new String[]{busLink, sender}; - success = mailer.sendEmail(clList, translate("map.share.invitation.mail.subject"), translate("map.share.invitation.mail.body", bodyArgs)); + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(map.getOlatResource(), null, getWindowControl().getBusinessControl().getAsString()); + success = mailer.sendEmail(context, clList, translate("map.share.invitation.mail.subject"), translate("map.share.invitation.mail.body", bodyArgs)); } catch (AddressException e) { logError("Error on sending invitation mail to contactlist, invalid address.", e); } catch (MessagingException e) { diff --git a/src/main/java/org/olat/registration/RegistrationController.java b/src/main/java/org/olat/registration/RegistrationController.java index 7c57b8b1ae87240a66f442a0b602c5fe3c1f22f0..0e8194e68a3ffba5bad29523b45f03d91f8d560c 100644 --- a/src/main/java/org/olat/registration/RegistrationController.java +++ b/src/main/java/org/olat/registration/RegistrationController.java @@ -50,7 +50,9 @@ import org.olat.core.logging.OLATRuntimeException; import org.olat.core.util.Util; import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nManager; -import org.olat.core.util.mail.Emailer; +import org.olat.core.util.i18n.I18nModule; +import org.olat.core.util.mail.MailerResult; +import org.olat.core.util.mail.manager.MailManager; import org.olat.dispatcher.LocaleNegotiator; import org.olat.user.UserManager; import org.olat.user.propertyhandlers.UserPropertyHandler; @@ -228,7 +230,7 @@ public class RegistrationController extends BasicController { String ip = ureq.getHttpReq().getRemoteAddr(); String body = null; String today = DateFormat.getDateInstance(DateFormat.LONG, ureq.getLocale()).format(new Date()); - Emailer mailer = new Emailer(ureq.getLocale()); + MailManager mailM = MailManager.getInstance(); //TODO eMail Vorlagen String serverpath = Settings.getServerContextPathURI(); boolean isMailSent = false; @@ -241,7 +243,8 @@ public class RegistrationController extends BasicController { + SEPARATOR + getTranslator().translate("reg.wherefrom", new String [] { serverpath, today, ip }); try { - if (mailer.sendEmail(email, translate("reg.subject"), body)) isMailSent = true; + MailerResult result = mailM.sendExternMessage(null, null, null, email, null, null, null, translate("reg.subject"), body, null, null); + if (MailerResult.OK == result.getReturnCode()) isMailSent = true; } catch (Exception e) { // nothing to do, emailSent flag is false, errors will be reported to user } @@ -252,7 +255,8 @@ public class RegistrationController extends BasicController { body = translate("login.body", identity.getName()) + SEPARATOR + getTranslator().translate("reg.wherefrom", new String[] { serverpath, today, ip }); try { - isMailSent = mailer.sendEmail(email, translate("login.subject"), body); + MailerResult result = mailM.sendExternMessage(null, null, null, email, null, null, null, translate("login.subject"), body, null, null); + if (MailerResult.OK == result.getReturnCode()) isMailSent = true; } catch (Exception e) { // nothing to do, emailSent flag is false, errors will be reported to user } diff --git a/src/main/java/org/olat/registration/RegistrationManager.java b/src/main/java/org/olat/registration/RegistrationManager.java index 8d95844d323df9a1deff50bab1208caa4941a242..fba0e313c3b44ab5f4155870da401d44481f5283 100644 --- a/src/main/java/org/olat/registration/RegistrationManager.java +++ b/src/main/java/org/olat/registration/RegistrationManager.java @@ -28,6 +28,7 @@ import java.util.Locale; import javax.mail.Address; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; import org.hibernate.Hibernate; import org.olat.basesecurity.AuthHelper; @@ -45,8 +46,8 @@ import org.olat.core.util.Encoder; import org.olat.core.util.Util; import org.olat.core.util.WebappHelper; import org.olat.core.util.i18n.I18nModule; -import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailerResult; +import org.olat.core.util.mail.manager.MailManager; import org.olat.properties.Property; import org.olat.properties.PropertyManager; @@ -58,7 +59,7 @@ import org.olat.properties.PropertyManager; public class RegistrationManager extends BasicManager { public final String PW_CHANGE = "PW_CHANGE"; - protected final String REGISTRATION = "REGISTRATION"; + public final String REGISTRATION = "REGISTRATION";//fxdiff FXOLAT-113: business path in DMZ public static final String EMAIL_CHANGE = "EMAIL_CHANGE"; protected static final int REG_WORKFLOW_STEPS = 5; protected static final int PWCHANGE_WORKFLOW_STEPS = 4; @@ -101,7 +102,8 @@ public class RegistrationManager extends BasicManager { Address from; Address[] to; try { - from = new InternetAddress(WebappHelper.getMailConfig("mailFrom")); + // fxdiff: change from/replyto, see FXOLAT-74 + from = new InternetAddress(WebappHelper.getMailConfig("mailReplyTo")); to = new Address[] { new InternetAddress(notificationMailAddress)}; } catch (AddressException e) { Tracing.logError("Could not send registration notification message, bad mail address", e, RegistrationManager.class); @@ -116,7 +118,9 @@ public class RegistrationManager extends BasicManager { String subject = trans.translate("reg.notiEmail.subject", userParams); String body = trans.translate("reg.notiEmail.body", userParams); - MailHelper.sendMessage(from, to , null, null, body, subject, null, result); + //fxdiff VCRP-16: intern mail system + MimeMessage msg = MailManager.getInstance().createMimeMessage(from, to, null, null, body, subject, null, result); + MailManager.getInstance().sendMessage(msg, result); if (result.getReturnCode() != MailerResult.OK ) { Tracing.logError("Could not send registration notification message, MailerResult was ::" + result.getReturnCode(), RegistrationManager.class); } diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties index 3d02a52c9c67c3a80e176981375b29d6fdc359b2..99d01574fb984905696031e7291cf28c23c401ae 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_de.properties @@ -377,6 +377,7 @@ tab.log=Logfiles tab.public=Allgemein tab.glossary.flexions=Morphologischer Dienst tab.glossary.register=Alphabetisches Register +tab.glossary.edit=Schreibberechtigung tab.sharedfolder=Ressourcenordner table.header.ac=AC table.header.access=Zugriff* diff --git a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties index 79710067b8b9a58a7a50e9d8d27b3a384d1fcdcd..502bfcd4986617bf87a53e6f7a94dcc01d60b49a 100644 --- a/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/repository/_i18n/LocalStrings_en.properties @@ -354,6 +354,7 @@ tab.calendar=Calendar tab.chat=Course chat tab.efficencystatement=Evidence of achievement tab.glossary=Glossary +tab.glossary.edit=Write permissions tab.glossary.flexions=Morphologic service tab.glossary.register=Alphabetical index tab.layout=Layout diff --git a/src/main/java/org/olat/repository/controllers/WizardCloseCourseController.java b/src/main/java/org/olat/repository/controllers/WizardCloseCourseController.java index d596a2157c7feb95e1fb947517f0f63d33c7819c..321c00aa5632f3b4c34ffd41c511080f5972c8b3 100644 --- a/src/main/java/org/olat/repository/controllers/WizardCloseCourseController.java +++ b/src/main/java/org/olat/repository/controllers/WizardCloseCourseController.java @@ -51,6 +51,8 @@ import org.olat.core.gui.translator.PackageTranslator; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; import org.olat.core.id.UserConstants; +import org.olat.core.util.mail.MailContext; +import org.olat.core.util.mail.MailContextImpl; import org.olat.core.util.mail.MailHelper; import org.olat.core.util.mail.MailNotificationEditController; import org.olat.core.util.mail.MailTemplate; @@ -190,7 +192,9 @@ public class WizardCloseCourseController extends WizardController implements Wiz } else { ccIdentities = null; } - MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(ownerList, ccIdentities, null, + //fxdiff VCRP-16: intern mail system + MailContext context = new MailContextImpl(wControl.getBusinessControl().getAsString()); + MailerResult mailerResult = MailerWithTemplate.getInstance().sendMailAsSeparateMails(context, ownerList, ccIdentities, null, mailNotificationCtr.getMailTemplate(), ureq.getIdentity()); StringBuilder errorMessage = new StringBuilder(); StringBuilder warningMessage = new StringBuilder(); diff --git a/src/main/java/org/olat/upgrade/OLATUpgrade_7_1_1.java b/src/main/java/org/olat/upgrade/OLATUpgrade_7_1_1.java index 82d54dc1be5e497257ed17ca4cc2566e7f903db4..988f82a9ca9c0e569ea08f21e922d11ac430db58 100644 --- a/src/main/java/org/olat/upgrade/OLATUpgrade_7_1_1.java +++ b/src/main/java/org/olat/upgrade/OLATUpgrade_7_1_1.java @@ -25,6 +25,10 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import org.olat.basesecurity.BaseSecurity; +import org.olat.basesecurity.BaseSecurityManager; +import org.olat.basesecurity.Constants; +import org.olat.basesecurity.SecurityGroup; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.commons.persistence.DBQuery; @@ -33,6 +37,10 @@ import org.olat.core.commons.services.commentAndRating.CommentAndRatingService; import org.olat.core.commons.services.commentAndRating.UserCommentsManager; import org.olat.core.commons.services.commentAndRating.model.UserComment; import org.olat.core.id.Identity; +import org.olat.group.BusinessGroup; +import org.olat.group.context.BGContext; +import org.olat.group.context.BGContextManager; +import org.olat.group.context.BGContextManagerImpl; import org.olat.portfolio.PortfolioModule; import org.olat.portfolio.manager.EPFrontendManager; import org.olat.portfolio.model.artefacts.AbstractArtefact; @@ -42,6 +50,7 @@ import org.olat.portfolio.model.structel.EPStructuredMap; import org.olat.portfolio.model.structel.EPStructuredMapTemplate; import org.olat.portfolio.model.structel.ElementType; import org.olat.portfolio.model.structel.PortfolioStructure; +import org.olat.repository.RepositoryEntry; /** * Description:<br> @@ -59,12 +68,15 @@ public class OLATUpgrade_7_1_1 extends OLATUpgrade { private static final String TASK_CLEANUP_TEMPLATES = "Cleanup template maps on db directly"; private static final String TASK_CHECK_AND_FIX_TEMPLATEMAPS = "Check templates and fix portfolio-task child elements"; + private static final String MIGRATE_SECURITY_GROUP = "Migrate repository entry security groups"; + private static final int REPO_ENTRIES_BATCH_SIZE = 20; private static final String VERSION = "OLAT_7.1.1"; private boolean portfolioCourseNodeEnabled; private EPFrontendManager ePFMgr; private CommentAndRatingService commentAndRatingService; private PortfolioModule epfModule; + public OLATUpgrade_7_1_1(PortfolioModule epfModule) { super(); this.epfModule = epfModule; @@ -97,6 +109,8 @@ public class OLATUpgrade_7_1_1 extends OLATUpgrade { // remove invalid references on db fixInvalidTemplateMaps(upgradeManager, uhd); + + migrateSecurityGroups(upgradeManager, uhd); // uhd.setInstallationComplete(true); upgradeManager.setUpgradesHistory(uhd, VERSION); @@ -378,6 +392,128 @@ public class OLATUpgrade_7_1_1 extends OLATUpgrade { } + //fxdiff VCRP-1: access control repository entry + private void migrateSecurityGroups(UpgradeManager upgradeManager, UpgradeHistoryData uhd) { + if (!uhd.getBooleanDataValue(MIGRATE_SECURITY_GROUP)) { + log.audit("+-----------------------------------------------------------------------------+"); + log.audit("+... Migrate the repository entry security groups from business groups ...+"); + log.audit("+-----------------------------------------------------------------------------+"); + + int counter = 0; + List<RepositoryEntry> entries; + do { + entries = queryEntries(counter); + for(RepositoryEntry entry:entries) { + createRepoEntrySecurityGroups(entry); + migrateRepoEntrySecurityGroups(entry); + } + counter += entries.size(); + log.audit("Processed entries: " + entries.size()); + } while(entries.size() == REPO_ENTRIES_BATCH_SIZE); + + log.audit("+... Migration processed " + counter + " repository entries ...+"); + + uhd.setBooleanDataValue(MIGRATE_SECURITY_GROUP, true); + upgradeManager.setUpgradesHistory(uhd, VERSION); + } + } + + private void createRepoEntrySecurityGroups(RepositoryEntry entry) { + BaseSecurity securityManager = BaseSecurityManager.getInstance(); + + boolean save = false; + if(entry.getTutorGroup() == null) { + // security group for tutors / coaches + SecurityGroup tutorGroup = securityManager.createAndPersistSecurityGroup(); + // member of this group may modify member's membership + securityManager.createAndPersistPolicy(tutorGroup, Constants.PERMISSION_ACCESS, entry.getOlatResource()); + // members of this group are always tutors also + securityManager.createAndPersistPolicy(tutorGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_TUTOR); + entry.setTutorGroup(tutorGroup); + + securityManager.createAndPersistPolicy(entry.getTutorGroup(), Constants.PERMISSION_COACH, entry.getOlatResource()); + + DBFactory.getInstance().commit(); + save = true; + } + + if(entry.getParticipantGroup() == null) { + // security group for participants + SecurityGroup participantGroup = securityManager.createAndPersistSecurityGroup(); + // member of this group may modify member's membership + securityManager.createAndPersistPolicy(participantGroup, Constants.PERMISSION_ACCESS, entry.getOlatResource()); + // members of this group are always participants also + securityManager.createAndPersistPolicy(participantGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_PARTICIPANT); + entry.setParticipantGroup(participantGroup); + + securityManager.createAndPersistPolicy(entry.getParticipantGroup(), Constants.PERMISSION_PARTI, entry.getOlatResource()); + + DBFactory.getInstance().commit(); + save = true; + } + + if(save) { + DBFactory.getInstance().updateObject(entry); + } + } + + private void migrateRepoEntrySecurityGroups(RepositoryEntry entry) { + BaseSecurity securityManager = BaseSecurityManager.getInstance(); + BGContextManager contextManager = BGContextManagerImpl.getInstance(); + + List<BGContext> contexts = contextManager.findBGContextsForResource(entry.getOlatResource(), true, true); + for(BGContext context:contexts) { + List<BusinessGroup> groups = contextManager.getGroupsOfBGContext(context); + for(BusinessGroup group:groups) { + //migrate tutors + if(group.getOwnerGroup() != null) { + int count = 0; + List<Identity> owners = securityManager.getIdentitiesOfSecurityGroup(group.getOwnerGroup()); + SecurityGroup tutorGroup = entry.getTutorGroup(); + for(Identity owner:owners) { + if(securityManager.isIdentityInSecurityGroup(owner, tutorGroup)) { + continue; + } + securityManager.addIdentityToSecurityGroup(owner, tutorGroup); + if(count++ % 20 == 0) { + DBFactory.getInstance().intermediateCommit(); + } + } + DBFactory.getInstance().intermediateCommit(); + } + + //migrate participants + if(group.getPartipiciantGroup() != null) { + int count = 0; + List<Identity> participants = securityManager.getIdentitiesOfSecurityGroup(group.getPartipiciantGroup()); + SecurityGroup participantGroup = entry.getParticipantGroup(); + for(Identity participant:participants) { + if(securityManager.isIdentityInSecurityGroup(participant, participantGroup)) { + continue; + } + securityManager.addIdentityToSecurityGroup(participant, participantGroup); + if(count++ % 20 == 0) { + DBFactory.getInstance().intermediateCommit(); + } + } + + DBFactory.getInstance().intermediateCommit(); + } + } + } + } + + public List<RepositoryEntry> queryEntries(int firstResult) { + StringBuilder sb = new StringBuilder(); + sb.append("select v from ").append(RepositoryEntry.class.getName()).append(" v inner join fetch v.olatResource as res order by v.key asc"); + DBQuery dbquery = DBFactory.getInstance().createQuery(sb.toString()); + dbquery.setFirstResult(firstResult); + dbquery.setMaxResults(REPO_ENTRIES_BATCH_SIZE); + return dbquery.list(); + } + + + @Override public String getVersion() { return VERSION; diff --git a/src/main/java/org/olat/user/ChangePasswordController.java b/src/main/java/org/olat/user/ChangePasswordController.java index c4a160849e0d910a32a67b39920da30b8b547c3d..38fffe60ca8c95d2855bfe0cd69ab84e8872712d 100644 --- a/src/main/java/org/olat/user/ChangePasswordController.java +++ b/src/main/java/org/olat/user/ChangePasswordController.java @@ -135,6 +135,8 @@ public class ChangePasswordController extends BasicController implements Support String newPwd = chPwdForm.getNewPasswordValue(); if(OLATAuthManager.changePassword(ureq.getIdentity(), provenIdent, newPwd)) { //TODO: verify that we are NOT in a transaction (changepwd should be commited immediately) + // fxdiff: we need this event for the afterlogin-controller + fireEvent(ureq, Event.DONE_EVENT); getLogger().audit("Changed password for identity."+provenIdent.getName()); showInfo("password.successful"); } else { diff --git a/src/main/java/org/olat/user/MailBoxExtension.java b/src/main/java/org/olat/user/MailBoxExtension.java new file mode 100644 index 0000000000000000000000000000000000000000..ea0134b68c73d266af8d8e04c1329e0a08ecbca5 --- /dev/null +++ b/src/main/java/org/olat/user/MailBoxExtension.java @@ -0,0 +1,159 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) frentix GmbH<br> + * http://www.frentix.com<br> + * <p> + */ +package org.olat.user; + +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +import org.olat.NewControllerFactory; +import org.olat.admin.user.delete.service.UserDeletionManager; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.id.Identity; +import org.olat.core.id.context.BusinessControl; +import org.olat.core.id.context.BusinessControlFactory; +import org.olat.core.id.context.ContextEntry; +import org.olat.core.id.context.ContextEntryControllerCreator; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; +import org.olat.core.manager.BasicManager; +import org.olat.core.util.StringHelper; +import org.olat.core.util.mail.manager.MailManager; +import org.olat.core.util.mail.model.DBMail; +import org.olat.core.util.mail.ui.MailContextResolver; +import org.olat.group.BusinessGroup; +import org.olat.group.BusinessGroupManagerImpl; +import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryManager; + +import org.olat.home.HomeSite; + +/** + * + * Description:<br> + * The MailBoxExtensio for + * + * <P> + * Initial Date: 25 mars 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MailBoxExtension extends BasicManager implements MailContextResolver, UserDataDeletable { + + private static final OLog log = Tracing.createLoggerFor(MailBoxExtension.class); + + private MailManager mailManager; + + public MailBoxExtension(UserDeletionManager userDeletionManager) { + userDeletionManager.registerDeletableUserData(this); + } + + public void init() { + NewControllerFactory.getInstance().addContextEntryControllerCreator("Inbox", new ContextEntryControllerCreator(){ + @Override + public Controller createController(ContextEntry ce, UserRequest ureq, WindowControl wControl) { + return null; + } + + @Override + public String getTabName(ContextEntry ce) { + // opens in home-tab + return null; + } + + @Override + public String getSiteClassName(ContextEntry ce) { + return HomeSite.class.getName(); + } + + @Override + public boolean validateContextEntryAndShowError(ContextEntry ce, UserRequest ureq, WindowControl wControl) { + return true; + } + }); + } + + /** + * [used by Spring] + * @param mailManager + */ + public void setMailManager(MailManager mailManager) { + this.mailManager = mailManager; + } + + + @Override + public void deleteUserData(Identity identity, String newDeletedUserName) { + //set as deleted all recpient + logInfo("Delete intern messages"); + + List<DBMail> inbox = mailManager.getInbox(identity, null, false, null, 0, 0); + for(DBMail inMail:inbox) { + mailManager.delete(inMail, identity, true); + } + + List<DBMail> outbox = mailManager.getOutbox(identity, 0, 0); + for(DBMail outMail:outbox) { + mailManager.delete(outMail, identity, true); + } + + logInfo("Delete " + inbox.size() + " messages in INBOX and " + outbox.size() + " in OUTBOX"); + } + + @Override + public String getName(String businessPath, Locale locale) { + if(!StringHelper.containsNonWhitespace(businessPath)) return null; + + try { + List<ContextEntry> entries = BusinessControlFactory.getInstance().createCEListFromString(businessPath); + Collections.reverse(entries); + + for(ContextEntry entry:entries) { + String resourceTypeName = entry.getOLATResourceable().getResourceableTypeName(); + Long resourceId = entry.getOLATResourceable().getResourceableId(); + if("BusinessGroup".equals(resourceTypeName)) { + BusinessGroup group = BusinessGroupManagerImpl.getInstance().loadBusinessGroup(resourceId, false); + if(group == null) { + return null; + } + return group.getName(); + } else if ("RepositoryEntry".equals(resourceTypeName)) { + RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntry(resourceId); + if(re == null) { + return null; + } + return re.getDisplayname(); + } + } + } catch (Exception e) { + log.error("", e); + } + return null; + } + + @Override + public void open(UserRequest ureq, WindowControl wControl, String businessPath) { + BusinessControl bc = BusinessControlFactory.getInstance().createFromString(businessPath); + WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(bc, wControl); + NewControllerFactory.getInstance().launch(ureq, bwControl); + } +} diff --git a/src/main/java/org/olat/user/PreferencesFormController.java b/src/main/java/org/olat/user/PreferencesFormController.java index 44791c5a59185ead10615fa0b6d86527feb647b9..e412ccc492cd80d920ee8f2eea5bc9e647ec34f6 100644 --- a/src/main/java/org/olat/user/PreferencesFormController.java +++ b/src/main/java/org/olat/user/PreferencesFormController.java @@ -27,6 +27,7 @@ import java.util.Map; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityManager; +import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; @@ -41,10 +42,12 @@ import org.olat.core.gui.control.WindowBackOffice; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Identity; import org.olat.core.id.Preferences; +import org.olat.core.id.UserConstants; import org.olat.core.util.ArrayHelper; import org.olat.core.util.StringHelper; import org.olat.core.util.i18n.I18nManager; import org.olat.core.util.i18n.I18nModule; +import org.olat.core.util.mail.MailModule; import org.olat.core.util.notifications.NotificationsManager; /** @@ -64,7 +67,8 @@ import org.olat.core.util.notifications.NotificationsManager; public class PreferencesFormController extends FormBasicController { private static final String[] cssFontsizeKeys = new String[] { "80", "90", "100", "110", "120", "140" }; private Identity tobeChangedIdentity; - private SingleSelection language, fontsize, charset, notificationInterval; + private SingleSelection language, fontsize, charset, notificationInterval, mailSystem; + private static final String[] mailIntern = new String[]{"intern.only","send.copy"}; /** * Constructor for the user preferences form @@ -104,6 +108,11 @@ public class PreferencesFormController extends FormBasicController { // set window dirty to force full page refresh wbo.getWindow().setDirty(true); } + //fxdiff VCRP-16: intern mail system + if(mailSystem != null && mailSystem.isOneSelected()) { + String val = mailSystem.isSelected(1) ? "true" : "false"; + prefs.setReceiveRealMail(val); + } if (um.updateUserFromIdentity(tobeChangedIdentity)) { // Language change needs logout / login @@ -180,6 +189,26 @@ public class PreferencesFormController extends FormBasicController { notificationInterval = uifactory.addDropdownSingleselect("form.notification", formLayout, intervalKeys, intervalValues, null); notificationInterval.select(prefs.getNotificationInterval(), true); } + //fxdiff VCRP-16: intern mail system + MailModule mailModule = (MailModule)CoreSpringFactory.getBean("mailModule"); + if(mailModule.isInternSystem()) { + String userEmail = tobeChangedIdentity.getUser().getProperty(UserConstants.EMAIL, getLocale()); + String[] mailInternLabels = new String[] { translate("mail." + mailIntern[0], userEmail), translate("mail." + mailIntern[1], userEmail) }; + mailSystem = uifactory.addRadiosVertical("mail-system", "mail.system", formLayout, mailIntern, mailInternLabels); + + String mailPrefs = prefs.getReceiveRealMail(); + if(StringHelper.containsNonWhitespace(mailPrefs)) { + if("true".equals(mailPrefs)) { + mailSystem.select(mailIntern[1], true); + } else { + mailSystem.select(mailIntern[0], true); + } + } else if(mailModule.isReceiveRealMailUserDefaultSetting()) { + mailSystem.select(mailIntern[1], true); + } else { + mailSystem.select(mailIntern[0], true); + } + } // Text encoding Map<String, Charset> charsets = Charset.availableCharsets(); diff --git a/src/main/java/org/olat/user/PreferencesImpl.java b/src/main/java/org/olat/user/PreferencesImpl.java index b82ae996c41c265fdcaa37293b32f507674f945e..1a4c1948654b141bc982f367ed2f605190e4996d 100644 --- a/src/main/java/org/olat/user/PreferencesImpl.java +++ b/src/main/java/org/olat/user/PreferencesImpl.java @@ -39,6 +39,7 @@ public class PreferencesImpl implements Preferences{ private String fontsize; private String notificationInterval; boolean informSessionTimeout; + private String receiveRealMail; private boolean presenceMessagesPublic; /** @@ -103,7 +104,7 @@ public class PreferencesImpl implements Preferences{ // Always return a valid notification interval NotificationsManager notiMgr = NotificationsManager.getInstance(); if (notificationInterval == null || notificationInterval.isEmpty() - || !notiMgr.getEnabledNotificationIntervals().contains(notificationInterval)) { + || notiMgr == null || !notiMgr.getEnabledNotificationIntervals().contains(notificationInterval)) { notificationInterval = notiMgr.getDefaultNotificationInterval(); } return notificationInterval; @@ -122,6 +123,23 @@ public class PreferencesImpl implements Preferences{ public void setInformSessionTimeout(boolean b) { informSessionTimeout = b; } + + /** + * @see org.olat.core.id.Preferences#isReceiveRealMail() + */ + //fxdiff VCRP-16: intern mail system + @Override + public String getReceiveRealMail() { + return receiveRealMail; + } + + /** + * @see org.olat.core.id.Preferences#setReceiveRealMail(boolean) + */ + @Override + public void setReceiveRealMail(String receiveRealMail) { + this.receiveRealMail = receiveRealMail; + } /** * @see org.olat.user.Preferences#getPresenceMessagesPublic() diff --git a/src/main/java/org/olat/user/UserImpl.hbm.xml b/src/main/java/org/olat/user/UserImpl.hbm.xml index e59b9ad0bf8125a83450145443de222b179ea13f..7ace2e77abecaf8877b08175e71df612b0f42d9f 100644 --- a/src/main/java/org/olat/user/UserImpl.hbm.xml +++ b/src/main/java/org/olat/user/UserImpl.hbm.xml @@ -25,8 +25,10 @@ <column name="presencemessagespublic" unique="false" not-null="false"/> </property> <property name="informSessionTimeout"> - <column name="informsessiontimeout" not-null="true"/> - </property> + <column name="informsessiontimeout" unique="false" not-null="false" length="16"/> + </property> + + <property name="receiveRealMail" column="receiverealmail" unique="false" not-null="false" length="16" type="string"/> </component> <map name="properties" table="o_userproperty" cascade="all,delete-orphan" fetch="join"> diff --git a/src/main/java/org/olat/user/UserManager.java b/src/main/java/org/olat/user/UserManager.java index 379fb0662297f4be939890904e87d40cb59559d1..d9d27a58475379660d8e71e7cd022ad0aeeea484 100644 --- a/src/main/java/org/olat/user/UserManager.java +++ b/src/main/java/org/olat/user/UserManager.java @@ -176,8 +176,7 @@ public abstract class UserManager extends BasicManager { return userNameAndPasswordSyntaxChecker.syntaxCheckOlatLogin(login); } - // only package scope, used by user impl - UserPropertiesConfig getUserPropertiesConfig() { + public UserPropertiesConfig getUserPropertiesConfig() { return userPropertiesConfig; } @@ -210,6 +209,9 @@ public abstract class UserManager extends BasicManager { public boolean isUserViewReadOnly(String usageIdentifyer, UserPropertyHandler propertyHandler) { return userPropertiesConfig.isUserViewReadOnly(usageIdentifyer, propertyHandler); } + + // fxdiff: check also for emails in change-workflow + public abstract boolean isEmailInUse(String email); /** * Spring setter diff --git a/src/main/java/org/olat/user/UserManagerImpl.java b/src/main/java/org/olat/user/UserManagerImpl.java index 36e08358260b9f3b3a13f634c56bf54a6e5e1d42..6383150d2977c4cbcaec5797addf17d153d44f4a 100644 --- a/src/main/java/org/olat/user/UserManagerImpl.java +++ b/src/main/java/org/olat/user/UserManagerImpl.java @@ -92,6 +92,28 @@ public class UserManagerImpl extends UserManager { DBFactory.getInstance().saveObject(user); return user; } + + // fxdiff: check also for emails in change-workflow + public boolean isEmailInUse(String email) { + DB db = DBFactory.getInstance(); + String[] emailProperties = {UserConstants.EMAIL, UserConstants.INSTITUTIONALEMAIL}; + for(String emailProperty:emailProperties) { + StringBuilder sb = new StringBuilder(); + sb.append("select count(user) from org.olat.core.id.User user where ") + .append("user.properties['") + .append(emailProperty) + .append("']=:email_value"); + + String query = sb.toString(); + DBQuery dbq = db.createQuery(query); + dbq.setString("email_value", email); + Number countEmail = (Number)dbq.uniqueResult(); + if(countEmail.intValue() > 0) { + return true; + } + } + return false; + } /** * @see org.olat.user.UserManager#findIdentityByEmail(java.lang.String) diff --git a/src/main/java/org/olat/user/_chelp/home-prefs.html b/src/main/java/org/olat/user/_chelp/home-prefs.html index 95ac281fd179fc495b2f05dcb07fb0c048a3ae0f..e0f0ad7e6be9dd3a69bb20d7e2fde502f992a2d9 100644 --- a/src/main/java/org/olat/user/_chelp/home-prefs.html +++ b/src/main/java/org/olat/user/_chelp/home-prefs.html @@ -5,5 +5,6 @@ $r.translate("chelp.prefs5") <br/><br/> <b>$r.translate("form.fontsize"):</b> $r.translate("chelp.prefs6") $r.translate("chelp.prefs7") <br/><br/> <b>$r.translate("form.notification"):</b> $r.translate("chelp.prefs15") $r.translate("chelp.prefs16") <br/><br/> + <b>$r.translate("mail.system"):</b> $r.translate("chelp.mail.system") <br/><br/> <b>$r.translate("form.charset"):</b> $r.translate("chelp.prefs8") $r.translate("chelp.prefs9") <br/><br/> $r.translate("chelp.prefs10") $r.translate("chelp.prefs11") diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties index 0461dfe54bda900653c90ca9b1cf0c1ffa6e38b8..3aef0d99ab7d13fe9a8ea831174c6a983d69e838 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties @@ -20,7 +20,7 @@ chelp.contact=<b>$org.olat.user\:menu.contact</b> chelp.fName=<i>$org.olat.user.propertyhandlers\:form.name.firstName</i> chelp.fNameF=<b>$org.olat.user.propertyhandlers\:form.name.firstName\:</b> chelp.folder=<b>$org.olat.user\:menu.folder</b> -chelp.home=<i>$org.olat.home\:menu.root</i> +chelp.home=<i>$org.olat.home\:main.menu.title</i> chelp.home-imsettings.title=Instant-Messaging: Konfiguration chelp.home-imsettings-roster.title=Instant-Messaging: Statusanzeige in der Kontaktliste chelp.home-prefs-ajax.title=AJAX-Einstellungen @@ -196,6 +196,10 @@ success.change.email = Die E-Mail-Adresse wurde erfolgreich von {0} auf {1} ge\u error.change.email.time = Dieser Aktivierungs-Link hat eine G\u00fcltigkeitsdauer von {0} Stunden und ist somit nicht mehr g\u00fcltig. email.change.form.info = Ihre neue E-Mail-Adresse <b>{0}</b> wurde noch nicht aktiviert. Bitte folgen Sie den Anweisungen in der Ihnen zugestellten E-Mail zur Aktivierung der neuen E-Mail-Adresse. email.change.reminder = Sie haben die \u00c4nderung Ihrer in OLAT hinterlegten E-Mail-Adresse beantragt, die neue Adresse jedoch noch nicht aktiviert. Weitere Informationen zu diesem Vorgang finden Sie in der kontextsensitiven Hilfe im Bereich "Home" \u2192 "Meine Einstellungen". +mail.system=E-Mail Versand +mail.intern.only=E-Mails an das interne OLAT Postfach zustellen +mail.send.copy=E-Mails an das interne OLAT Postfach und die Adresse {0} zustellen +chelp.mail.system= Hier k�nnen Sie einstellen, ob Ihre pers�nlichen E-Mails and Ihre konfigurierte E-Mail Adresse verschickt oder nur in dem Posteingang innerhalb des OLAT Systems angezeigt werden sollen. Bitte beachten Sie, dass die Benachrichtigungen �ber Neuigkeiten innerhalb des System in jedem Fall per E-Mail an Ihre konfigurierte Mailadresse versendet werden. In dieser Benachrichtigungsemail finden Sie denn auch einen Hinweis �ber allf�llige neue E-Mails innerhalb des OLAT Postfachs falls Sie die Option "$:mail.intern.only" gew�hlt haben.. runonce.profile.intro=Bitte pr\u00FCfen Sie, ob Ihr Profil auf dem aktuellsten Stand ist und dr\u00FCcken Sie danach "Speichern". runonce.changepw.intro=Bitte \u00E4ndern Sie Ihr Passwort. pwdav.title=WebDAV Zugang diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties index 5ab26377a2c3941158f2cbda2c7abdd137166c05..b3a8328a531a176bf0379b73baa0a4c820b110cc 100644 --- a/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/user/_i18n/LocalStrings_en.properties @@ -27,7 +27,7 @@ chelp.contact=<b>$org.olat.user\:menu.contact</b> chelp.fName=<i>$org.olat.user.propertyhandlers\:form.name.firstName</i> chelp.fNameF=<b>$org.olat.user.propertyhandlers\:form.name.firstName\:</b> chelp.folder=<b>$org.olat.user\:menu.folder</b> -chelp.home=<i>$org.olat.home\:menu.root</i> +chelp.home=<i>$org.olat.home\:main.menu.title</i> chelp.home-imsettings-roster.title=Instant Messaging\: status display in contact list chelp.home-imsettings.title=Instant Messaging\: configuration chelp.home-picture.hover=Help to upload an image to your user profile @@ -50,6 +50,7 @@ chelp.instMail=<i>$org.olat.user.propertyhandlers\:form.name.institutionalEmail< chelp.lName=<i>$org.olat.user.propertyhandlers\:form.name.lastName</i> chelp.lNameF=<b>$org.olat.user.propertyhandlers\:form.name.lastName\:</b> chelp.large=<i>«$org.olat.user\:form.fontsize.large»</i> +chelp.mail.system=Here you can configure if you e-mails sent within the OLAT system should be delivered to you personal e-mail address or to the OLAT e-mail inbox in your home area. Please note that notification e-mails will be sent to your e-mail address in any case. In this notification e-mail you will find information about new internal e-mails if you selected the option "$\:mail.intern.only". chelp.nname=<i>$org.olat.user.propertyhandlers\:form.name.lastName</i> chelp.normal=<i>«$org.olat.user\:form.fontsize.normal»</i> chelp.onl1=Here you can determine if your $\:chelp.uname, $\:chelp.vname, and $\:chelp.nname on the online user list should be visible to all other OLAT users. @@ -151,6 +152,9 @@ interval.monthly=Monthly interval.never=Never interval.two-hourly=Every two hours interval.weekly=Weekly +mail.intern.only=Send e-mails to the OLAT internal inbox +mail.send.copy=Send e-mails to the OLAT internal inbox and the address {0} +mail.system=E-mail delivery menu.calendar=Calendar menu.calendar.alt=Personal calendar of selected user menu.contact=Contact diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index 4b56b98c384e6d35cb62897dcba78bf1739fa908..7eff19e9595b070d1e5851cf2c6ab36159c6e0f0 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -98,15 +98,22 @@ smtp.host=localhost # if required by your local SMTP you may need to provide credentials smtp.user= smtp.pwd= -# enable SSL if you smtp server supports it +# enable SSL if your smtp server supports it smtp.sslEnabled=false smtp.sslCheckCertificate=false -# set this email to a mail address in your domain -adminemail=webmaster@myolat.com -# set this email to a mail address in your domain -supportemail=support@myolat.com +# system mails will be sent from this address (from local domain with valid reverse dns): +fromemail=no-reply@openolat.org +# set this email to a mail address in your domain (used as reply-to address) +adminemail=webmaster@openolat.org +# set this email to a mail address in your domain (for RS-reports) +supportemail=support@openolat.org + # maximum size for email attachements (in MB) mail.attachment.maxsize=5 +# if mail intern is enabled you must make sure, that your mysql-db accepts large packets to also save the attachments: +# set "max_allowed_packet = 134217728" in my.cnf/my.ini see FXOLAT-154 +mail.intern=false +mail.receiveRealMailUserDefaultSetting=true ######################################################################## # User registration, login and deletion settings diff --git a/src/test/java/org/olat/core/test/OlatcoreTestCaseWithMocking.java b/src/test/java/org/olat/core/test/OlatcoreTestCaseWithMocking.java index 30ea7586a45f4a4cd9aab47247aa2e813e64ddc2..6dcb8191b37f17e86f412da220c784065bf1fce7 100644 --- a/src/test/java/org/olat/core/test/OlatcoreTestCaseWithMocking.java +++ b/src/test/java/org/olat/core/test/OlatcoreTestCaseWithMocking.java @@ -38,6 +38,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; "classpath*:/org/olat/core/test/_spring/webapphelperMock.xml", "classpath*:/org/olat/core/util/i18n/_spring/i18nCorecontext.xml", "classpath*:/org/olat/core/test/_spring/coordinatorMock.xml", + //fxdiff VCRP-16: intern mail system + "classpath*:/org/olat/core/test/_spring/mailModuleMock.xml", "classpath*:/org/olat/core/util/i18n/devtools/_spring/devtoolsCorecontext.xml", "classpath*:/org/olat/core/util/_spring/utilCorecontext.xml"}) diff --git a/src/test/java/org/olat/core/test/_spring/coordinatorMock.xml b/src/test/java/org/olat/core/test/_spring/coordinatorMock.xml index 22cb8c1f303d8818f5fdbc6eea9ba97efe67834a..89fc4eca12a6802451a63826cd135bdfde3f93b3 100644 --- a/src/test/java/org/olat/core/test/_spring/coordinatorMock.xml +++ b/src/test/java/org/olat/core/test/_spring/coordinatorMock.xml @@ -13,4 +13,9 @@ <bean id="coordinatorManager" class="org.olat.test.CoordinatorManagerMock" /> +<bean class="org.olat.core.util.event.FrameworkStartupEventChannel"> + <constructor-arg type="String" value="${node.id}" /> + <property name="coordinatorManager" ref="coordinatorManager" /> +</bean> + </beans> \ No newline at end of file diff --git a/src/test/java/org/olat/core/test/_spring/mailModuleMock.xml b/src/test/java/org/olat/core/test/_spring/mailModuleMock.xml new file mode 100644 index 0000000000000000000000000000000000000000..fadedcadabb8ff31aaeeed26d528f64e1884b6f5 --- /dev/null +++ b/src/test/java/org/olat/core/test/_spring/mailModuleMock.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + +<context:property-placeholder location="classpath:serviceconfig/olat.properties, classpath:olat.local.properties" /> +<context:annotation-config /> + + <bean id="mailModule" class="org.olat.core.util.mail.MailModule" depends-on="org.olat.core.util.WebappHelper,coordinatorManager,org.olat.core.util.event.FrameworkStartupEventChannel"> + <property name="persistedProperties"> + <bean class="org.olat.core.configuration.PersistedProperties" scope="prototype" init-method="init" destroy-method="destroy" + depends-on="coordinatorManager,org.olat.core.util.WebappHelper"> + <constructor-arg index="0" ref="coordinatorManager"/> + <constructor-arg index="1" ref="mailModule" /> + </bean> + </property> + <property name="webappHelper" ref="org.olat.core.util.WebappHelper"/> + </bean> + + <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> + <property name="targetObject" ref="mailModule" /> + <property name="targetMethod" value="init" /> + <property name="arguments"> + <value> + internSystem=false + receiveRealMailUserDefaultSetting=true + </value> + </property> + </bean> + + <bean id="mailManager" class="org.olat.core.util.mail.manager.MailManager"> + <constructor-arg index="0" ref="mailModule" /> + </bean> + +</beans> \ No newline at end of file diff --git a/src/test/java/org/olat/core/util/mail/MailTest.java b/src/test/java/org/olat/core/util/mail/MailTest.java index eddbd88e3e862bd909c01fdd2244b90e2ea3ba27..ed640f47f42c5dc00f9d69a9fc3ac2cfb64692b7 100644 --- a/src/test/java/org/olat/core/util/mail/MailTest.java +++ b/src/test/java/org/olat/core/util/mail/MailTest.java @@ -466,6 +466,16 @@ class TestUser implements User { public void setLanguage(String l) {} public void setPresenceMessagesPublic(boolean b) {} + + @Override + public String getReceiveRealMail() { + return "false"; + } + + @Override + public void setReceiveRealMail(String receiveRealMail) { + // + } }); } diff --git a/src/test/java/org/olat/course/nodes/en/EnrollmentManagerTest.java b/src/test/java/org/olat/course/nodes/en/EnrollmentManagerTest.java index 67c95fb03c211558f368c70038b07e4a277bf660..4be6eecab1f5d7b0f779538b195f6c704ebb1536 100644 --- a/src/test/java/org/olat/course/nodes/en/EnrollmentManagerTest.java +++ b/src/test/java/org/olat/course/nodes/en/EnrollmentManagerTest.java @@ -33,6 +33,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.ArrayList; +import java.util.List; import java.util.Locale; import org.apache.log4j.Logger; @@ -54,6 +55,7 @@ import org.olat.core.id.IdentityEnvironment; import org.olat.core.id.OLATResourceable; import org.olat.core.id.User; import org.olat.core.id.context.BusinessControl; +import org.olat.core.id.context.ContextEntry; import org.olat.core.util.Encoder; import org.olat.core.util.Util; import org.olat.core.util.resource.OresHelper; @@ -252,7 +254,50 @@ public class EnrollmentManagerTest extends OlatTestCase implements WindowControl public DTabs getDTabs(){return null;}; public WindowControlInfo getWindowControlInfo(){return null;}; public void makeFlat(){}; - public BusinessControl getBusinessControl() {return null;} + public BusinessControl getBusinessControl() { + + BusinessControl control = new BusinessControl() { + + @Override + public String getAsString() { + return null; + } + + @Override + public List<ContextEntry> getEntries() { + return null; + } + + @Override + public ContextEntry popLauncherContextEntry() { + return null; + } + + @Override + public ContextEntry getCurrentContextEntry() { + return null; + } + + @Override + public void setCurrentContextEntry(ContextEntry cw) { + // + } + + @Override + public void dropLauncherEntries() { + // + } + + @Override + public boolean hasContextEntry() { + return false; + } + + }; + + return control; + + } public WindowBackOffice getWindowBackOffice() { // TODO Auto-generated method stub