/** * OLAT - Online Learning and Training
* http://www.olat.org *

* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. *

* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),
* University of Zurich, Switzerland. *

*/ package org.olat.modules.co; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.mail.Address; import javax.mail.AuthenticationFailedException; import javax.mail.MessagingException; import javax.mail.SendFailedException; import javax.mail.internet.AddressException; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.panel.Panel; 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.messages.MessageUIFactory; import org.olat.core.gui.control.generic.modal.DialogBoxController; import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; import org.olat.core.id.Identity; import org.olat.core.logging.OLATRuntimeException; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.logging.activity.ThreadLocalUserActivityLogger; 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.MailHelper; import org.olat.core.util.mail.MailLoggingAction; /** * Fires Event: *

*

* Consumes Events from: *

*

* Main Purpose: is to provide an easy interface for contact message * creation and sending from within different OLAT bulding blocks. *

* Responsabilites:
*

*

* TODO:pb:b refactor ContactFormController and ContactForm to extract a ContactMessageManager, * setSubject(..) setRecipients.. etc. should not be in the controller. Refactor to use ContactMessage! * @see org.olat.modules.co.ContactList * Initial Date: Jul 19, 2004 * @author patrick */ public class ContactFormController extends BasicController { OLog log = Tracing.createLoggerFor(this.getClass()); // private Identity emailFrom; private ContactForm cntctForm; private VelocityContainer vcCreateContactMsg; private DialogBoxController noUsersErrorCtr; private ArrayList myButtons; private Panel main; /** * * @param ureq * @param windowControl * @param useDefaultTitle * @param isCanceable * @param isReadonly * @param hasRecipientsEditable * @param cmsg */ public ContactFormController(UserRequest ureq, WindowControl windowControl, boolean useDefaultTitle, boolean isCanceable, boolean isReadonly, boolean hasRecipientsEditable, ContactMessage cmsg) { super(ureq, windowControl); //init email form this.emailFrom = cmsg.getFrom(); cntctForm = new ContactForm(ureq, windowControl, emailFrom, isReadonly,isCanceable,hasRecipientsEditable); listenTo(cntctForm); List recipList = cmsg.getEmailToContactLists(); boolean hasAtLeastOneAddress = hasAtLeastOneAddress(recipList); cntctForm.setBody(cmsg.getBodyText()); cntctForm.setSubject(cmsg.getSubject()); main = new Panel("contactFormMainPanel"); //init display component init(ureq, useDefaultTitle, hasAtLeastOneAddress, cmsg.getDisabledIdentities()); } private boolean hasAtLeastOneAddress(List recipList) { boolean hasAtLeastOneAddress = false; if (recipList != null && recipList.size() > 0 ) { for (Iterator iter = recipList.iterator(); iter.hasNext();) { ContactList cl = (ContactList) iter.next(); if (!hasAtLeastOneAddress && cl != null && cl.getEmailsAsStrings().size() > 0) { hasAtLeastOneAddress = true; } if (cl.getEmailsAsStrings().size() > 0) cntctForm.addEmailTo(cl); } } return hasAtLeastOneAddress; } /** * @param useDefaultTitle * @param hasAtLeastOneAddress */ private void init(UserRequest ureq, boolean useDefaultTitle, boolean hasAtLeastOneAddress, List disabledIdentities) { if (hasAtLeastOneAddress) { vcCreateContactMsg = createVelocityContainer("c_contactMsg"); vcCreateContactMsg.put("cntctForm", cntctForm.getInitialComponent()); main.setContent(vcCreateContactMsg); putInitialPanel(main); } else { Controller mCtr = MessageUIFactory.createInfoMessage(ureq, getWindowControl(), null, translate("error.msg.send.no.rcps")); listenTo(mCtr);// to be disposed as this controller gets disposed putInitialPanel(mCtr.getInitialComponent()); } if(!hasAtLeastOneAddress | disabledIdentities.size() > 0){ //show error that message can not be sent myButtons = new ArrayList(); myButtons.add(translate("back")); String title = ""; String message = ""; if(disabledIdentities.size() > 0) { title = MailHelper.getTitleForFailedUsersError(ureq.getLocale()); message = MailHelper.getMessageForFailedUsersError(ureq.getLocale(), disabledIdentities); } else { title = translate("error.title.nousers"); message = translate("error.msg.nousers"); } noUsersErrorCtr = activateGenericDialog(ureq, title, message, myButtons, noUsersErrorCtr); } } /** * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, * org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event) */ public void event(UserRequest ureq, Controller source, Event event) { if (source == noUsersErrorCtr) { if(event.equals(Event.CANCELLED_EVENT)) { // user has clicked the close button in the top-right corner fireEvent(ureq, Event.CANCELLED_EVENT); } else { // user has clicked the cancel button int pos = DialogBoxUIFactory.getButtonPos(event); if (pos == 0){ // cancel button has been pressed, fire event to parent fireEvent(ureq, Event.CANCELLED_EVENT); } } } else if (source == cntctForm) { if (event == Event.DONE_EVENT) { boolean useInstitutionalEmail = false; Emailer emailer = new Emailer(emailFrom, useInstitutionalEmail); // boolean success = false; try { List attachments = cntctForm.getAttachments(); success = emailer.sendEmail(cntctForm.getEmailToContactLists(), cntctForm.getSubject(), cntctForm.getBody(), attachments); if(cntctForm.isTcpFrom()) { success = emailer.sendEmailCC(cntctForm.getEmailFrom(), cntctForm.getSubject(), cntctForm.getBody(), attachments); } } catch (AddressException e) { //error in recipient email address(es) handleAddressException(success); //no return here, depending on boolean success there are //events to fire } catch (SendFailedException e) { // error in sending message // CAUSE: sender email address invalid if(handleSendFailedException(e) ) { // exception handling says that although the message could not be // send we should proceed and finish this workflow with a failed event fireEvent(ureq, Event.FAILED_EVENT); return; } else { fireEvent(ureq, Event.FAILED_EVENT); return; } } catch (MessagingException e) { // error in message-subject || .-body handleMessagingException(); //fireEvent(ureq, Event.FAILED_EVENT); return; } cntctForm.setDisplayOnly(true); if (success) { showInfo("msg.send.ok"); // do logging ThreadLocalUserActivityLogger.log(MailLoggingAction.MAIL_SENT, getClass()); fireEvent(ureq, Event.DONE_EVENT); } else { showInfo("error.msg.send.nok"); fireEvent(ureq, Event.FAILED_EVENT); } } else if (event == Event.CANCELLED_EVENT) { fireEvent(ureq, Event.CANCELLED_EVENT); } } } /** * handles events from Components
* i.e. ContactForm and c_contactMsg.html
* creates an InfoMessage in the WindowController on error.
* Fires: *

*

* * @param ureq * @param source * @param event */ public void event(UserRequest ureq, Component source, Event event) { // } /** */ private void handleMessagingException() { String infoMessage = translate("error.msg.send.nok"); infoMessage += "
"; infoMessage += translate("error.msg.content.nok"); this.getWindowControl().setError(infoMessage); } /** * @param success */ private void handleAddressException(boolean success) { StringBuilder errorMessage = new StringBuilder(); if (success) { errorMessage.append(translate("error.msg.send.partially.nok")); errorMessage.append("
"); errorMessage.append(translate("error.msg.send.invalid.rcps")); } else { errorMessage.append(translate("error.msg.send.nok")); errorMessage.append("
"); errorMessage.append(translate("error.msg.send.553")); } this.getWindowControl().setError(errorMessage.toString()); } /** * handles the sendFailedException

generates an infoMessage * * @param e * @throws OLATRuntimeException * return boolean true: handling was successful, exception can be ignored; * false: handling was not successful, refuse to proceed. */ private boolean handleSendFailedException(SendFailedException e) { //get wrapped excpetion MessagingException me = (MessagingException) e.getNextException(); if (me instanceof AuthenticationFailedException) { // catch this one separately, this kind of exception has no message // as the other below StringBuilder infoMessage = new StringBuilder(); infoMessage.append(translate("error.msg.send.nok")); infoMessage.append("
"); infoMessage.append(translate("error.msg.smtp.authentication.failed")); this.getWindowControl().setInfo(infoMessage.toString()); log.warn("Mail message could not be sent: ", e); // message could not be sent, however let user proceed with his action return true; } String message = me.getMessage(); if (message.startsWith("553")) { //javax.mail.MessagingException: 553 5.5.4 ... Domain name // required for sender address invalid@id.unizh.ch //javax.mail.MessagingException: 553 5.1.8 ... // Domain of sender address invalid@invalid does not exist //... StringBuilder infoMessage = new StringBuilder(); infoMessage.append(translate("error.msg.send.553")); showInfo(infoMessage.toString()); } else if (message.startsWith("Invalid Addresses")) { // javax.mail.SendFailedException: Sending failed; // nested exception is: // class javax.mail.SendFailedException: Invalid Addresses; // nested exception is: // class javax.mail.SendFailedException: 550 5.1.1 ... User // unknownhandleSendFailedException StringBuilder infoMessage = new StringBuilder(); infoMessage.append(translate("error.msg.send.nok")); infoMessage.append("
"); infoMessage.append(translate("error.msg.send.invalid.rcps")); infoMessage.append(addressesArr2HtmlOList(e.getInvalidAddresses())); this.getWindowControl().setInfo(infoMessage.toString()); } else if (message.startsWith("503 5.0.0")) { // message:503 5.0.0 Need RCPT (recipient) ,javax.mail.MessagingException StringBuilder infoMessage = new StringBuilder(); infoMessage.append(translate("error.msg.send.nok")); infoMessage.append("
"); infoMessage.append(translate("error.msg.send.no.rcps")); this.getWindowControl().setInfo(infoMessage.toString()); } else if (message.startsWith("Unknown SMTP host")) { StringBuilder infoMessage = new StringBuilder(); infoMessage.append(translate("error.msg.send.nok")); infoMessage.append("
"); infoMessage.append(translate("error.msg.unknown.smtp", WebappHelper.getMailConfig("mailFrom"))); this.getWindowControl().setInfo(infoMessage.toString()); log.warn("Mail message could not be sent: ", e); // message could not be sent, however let user proceed with his action return true; } else if (message.startsWith("Could not connect to SMTP host")){ //could not connect to smtp host, no connection or connection timeout StringBuilder infoMessage = new StringBuilder(); infoMessage.append(translate("error.msg.send.nok")); infoMessage.append("
"); infoMessage.append(translate("error.msg.notconnectto.smtp", WebappHelper.getMailConfig("mailhost"))); this.getWindowControl().setInfo(infoMessage.toString()); log.warn(null, e); // message could not be sent, however let user proceed with his action return true; } else { throw new OLATRuntimeException(ContactFormController.class, "" + cntctForm.getEmailTo(), e.getNextException()); } // message could not be sent, return false return false; } /** * converts an Address[] to an HTML ordered list * * @param invalidAdr Address[] with invalid addresses * @return StringBuilder */ private StringBuilder addressesArr2HtmlOList(Address[] invalidAdr) { StringBuilder iAddressesSB = new StringBuilder(); if (invalidAdr != null && invalidAdr.length > 0) { iAddressesSB.append("

    "); for (int i = 0; i < invalidAdr.length; i++) { iAddressesSB.append("
  1. "); iAddressesSB.append(invalidAdr[i].toString()); iAddressesSB.append("
  2. "); } iAddressesSB.append("
"); } return iAddressesSB; } /** * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) */ protected void doDispose() { // } }